/** * ============================================================ * 랭킹 요청 DTO * ============================================================ * * 사용 페이지: 개체 목록 페이지 (/cow) * * 프론트에서 POST /cow/ranking 호출 시 사용 * * 지원하는 랭킹 기준: * 1. GENOME - 35개 유전체 형질 EBV 가중치 기반 * ============================================================ */ import { IsEnum, IsOptional, IsArray, IsString, IsNumber, Min, Max, ValidateNested, } from 'class-validator'; import { Type } from 'class-transformer'; import { FilterCondition, SortOption, PaginationOption, FilterEngineOptions, } from '../../shared/filter/interfaces/filter.interface'; import { RankingCriteriaType } from '../../common/const/RankingCriteriaType'; // Re-export for convenience export { RankingCriteriaType }; // ============================================================ // 랭킹 조건 DTO // ============================================================ /** * 유전체 형질 랭킹 조건 * - 35개 형질 중 사용자가 선택한 형질만 대상 * - weight: 1~10 가중치 (10이 100%) * * 예: { traitNm: '도체중', weight: 8 } */ export class TraitRankingConditionDto { @IsString() traitNm: string; // 형질명 (예: '도체중', '근내지방도') @IsOptional() @IsNumber() @Min(1) @Max(10) weight?: number; // 가중치 1~10 (기본값: 1) } /** * 랭킹 옵션 DTO */ export class RankingOptionsDto { @IsEnum(RankingCriteriaType) criteriaType: RankingCriteriaType; // 랭킹 기준 타입 @IsOptional() @IsArray() @ValidateNested({ each: true }) @Type(() => TraitRankingConditionDto) traitConditions?: TraitRankingConditionDto[]; // GENOME용: 형질별 가중치 @IsOptional() @IsNumber() @Min(1) limit?: number; @IsOptional() @IsNumber() @Min(0) offset?: number; } // ============================================================ // 필터 옵션 DTO (FilterEngine용) // ============================================================ /** * 필터 엔진 옵션 DTO * - 개체 목록 필터링에 사용 */ export class FilterEngineOptionsDto implements FilterEngineOptions { @IsOptional() @IsArray() filters?: FilterCondition[]; @IsOptional() @IsArray() sorts?: SortOption[]; @IsOptional() pagination?: PaginationOption; } // ============================================================ // 메인 요청 DTO // ============================================================ /** * 랭킹 요청 DTO * * 프론트에서 POST /cow/ranking 호출 시 Body로 전송 * * @example * { * filterOptions: { * filters: [{ field: 'cowSex', operator: 'eq', value: 'F' }], * pagination: { page: 1, limit: 20 } * }, * rankingOptions: { * criteriaType: 'GENOME', * traitConditions: [ * { traitNm: '도체중', weight: 8 }, * { traitNm: '근내지방도', weight: 10 } * ] * } * } */ export class RankingRequestDto { @IsOptional() @ValidateNested() @Type(() => FilterEngineOptionsDto) filterOptions?: FilterEngineOptionsDto; // 필터/정렬/페이지네이션 @ValidateNested() @Type(() => RankingOptionsDto) rankingOptions: RankingOptionsDto; // 랭킹 조건 }