From 3d022a1305dbaa4906d64b2f3118447088c8b58c Mon Sep 17 00:00:00 2001 From: chu eun ju Date: Mon, 15 Dec 2025 18:47:26 +0900 Subject: [PATCH] =?UTF-8?q?=ED=95=84=ED=84=B0=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/common/config/CowPurposeConfig.ts | 61 ------------------- backend/src/genome/genome.service.ts | 8 +-- frontend/src/app/cow/[cowNo]/page.tsx | 16 +++-- frontend/src/app/cow/page.tsx | 2 +- .../common/global-filter-dialog.tsx | 8 +-- frontend/src/types/filter.types.ts | 20 +++--- 6 files changed, 28 insertions(+), 87 deletions(-) delete mode 100644 backend/src/common/config/CowPurposeConfig.ts diff --git a/backend/src/common/config/CowPurposeConfig.ts b/backend/src/common/config/CowPurposeConfig.ts deleted file mode 100644 index 1b6406b..0000000 --- a/backend/src/common/config/CowPurposeConfig.ts +++ /dev/null @@ -1,61 +0,0 @@ -/** - * 소 용도 분류 설정 - * - * @description - * 소의 용도를 결정하는 비즈니스 로직 임계값 정의 - * - 도태 (Culling): 낮은 수태율, 번식 능력 부족 - * - 인공수정 (Artificial Insemination): 높은 수태율 + 우수 등급 - * - 공란우 (Donor): 중간 수태율 + 우수 등급 - * - 수란우 (Recipient): 높은 수태율 + 낮은 등급 - */ -export const COW_PURPOSE_CONFIG = { - /** - * 수태율 기반 임계값 (%) - */ - CONCEPTION_RATE_THRESHOLDS: { - /** - * 도태 대상 최대 수태율 (30% 미만) - * 수태율이 이 값보다 낮으면 번식 능력이 부족하여 도태 대상 - */ - CULLING_MAX: 30, - - /** - * 공란우 최대 수태율 (50% 미만) - * 수태율이 낮지만 우수한 유전자 보유 시 수정란 공급 - */ - DONOR_MAX: 50, - - /** - * 수란우 최소 수태율 (65% 이상) - * 높은 수태율을 가진 소에게 우수 수정란 이식 - */ - RECIPIENT_MIN: 65, - - /** - * 인공수정 최소 수태율 (65% 이상) - * 높은 수태율 + 우수 등급 → 일반 인공수정 대상 - */ - INSEMINATION_MIN: 65, - }, - - /** - * 나이 기반 임계값 (년) - */ - AGE_THRESHOLDS: { - /** - * 노령우 기준 (10년 이상) - * 이 나이 이상이면 도태 고려 대상 - */ - OLD_AGE_YEARS: 10, - - /** - * 번식 적정 최소 나이 (2년) - */ - BREEDING_MIN_AGE: 2, - - /** - * 번식 적정 최대 나이 (8년) - */ - BREEDING_MAX_AGE: 8, - }, -} as const; diff --git a/backend/src/genome/genome.service.ts b/backend/src/genome/genome.service.ts index d7bacb8..f6777f8 100644 --- a/backend/src/genome/genome.service.ts +++ b/backend/src/genome/genome.service.ts @@ -602,8 +602,8 @@ export class GenomeService { rank = lowerCount + 1; } else { // 나보다 높은 점수를 가진 농장 수 + 1 = 내 순위 (높을수록 좋음) - const higherCount = rankings.filter(r => r.avgEbv > farmData.avgEbv).length; - rank = higherCount + 1; + const higherCount = rankings.filter(r => r.avgEbv > farmData.avgEbv).length; + rank = higherCount + 1; } } @@ -1810,8 +1810,8 @@ export class GenomeService { ]; // inputTraitConditions가 있으면 사용, 없으면 35개 형질 기본값 사용 const traitConditions = inputTraitConditions && inputTraitConditions.length > 0 - ? inputTraitConditions - : ALL_TRAITS.map(traitNm => ({ traitNm, weight: 1 })); + ? inputTraitConditions // 프론트에서 보낸 형질사용 + : ALL_TRAITS.map(traitNm => ({ traitNm, weight: 1 })); // 기본값 사용 console.log('[getFarmRegionRanking] traitConditions:', traitConditions.length, 'traits'); diff --git a/frontend/src/app/cow/[cowNo]/page.tsx b/frontend/src/app/cow/[cowNo]/page.tsx index b895d26..e77d80d 100644 --- a/frontend/src/app/cow/[cowNo]/page.tsx +++ b/frontend/src/app/cow/[cowNo]/page.tsx @@ -10,7 +10,7 @@ import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog" import { Badge } from "@/components/ui/badge" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { useToast } from "@/hooks/use-toast" -import { ComparisonAveragesDto, TraitComparisonAveragesDto, cowApi, genomeApi, geneApi, GeneDetail, GenomeRequestDto } from "@/lib/api" +import { ComparisonAveragesDto, TraitComparisonAveragesDto, cowApi, genomeApi, geneApi, GeneDetail, GenomeRequestDto, mptApi, MptDto } from "@/lib/api" import { CowDetail } from "@/types/cow.types" import { GenomeTrait } from "@/types/genome.types" import { useGlobalFilter } from "@/contexts/GlobalFilterContext" @@ -35,6 +35,7 @@ import { TraitComparison } from "./genome/_components/genome-integrated-comparis import { CowNumberDisplay } from "@/components/common/cow-number-display" import { isValidGenomeAnalysis, getInvalidReason, getInvalidMessage } from "@/lib/utils/genome-analysis-config" import { AuthGuard } from "@/components/auth/auth-guard" +import { MptTable } from "./reproduction/_components/mpt-table" // 형질명 → 카테고리 매핑 (한우 35개 형질) const TRAIT_CATEGORY_MAP: Record = { @@ -628,7 +629,7 @@ export default function CowOverviewPage() { {/* 친자확인 섹션 */} -

친자확인 결과

+

혈통정보

@@ -997,7 +998,7 @@ export default function CowOverviewPage() { {/* 친자확인 섹션 */} -

친자확인 결과

+

혈통정보

@@ -1258,7 +1259,7 @@ export default function CowOverviewPage() { {/* 친자확인 결과 섹션 (유전체 탭과 동일) */} -

친자확인 결과

+

혈통정보

@@ -1674,11 +1675,15 @@ export default function CowOverviewPage() { )} + {/* 번식능력 탭 */} + {/* 혈액화학검사(MPT) 테이블 */} + + + {/* TODO: 번식능력 분석 결과 (추후 사용) {hasReproductionData ? (
- {/* TODO: 번식능력 분석 결과 표시 */}

번식능력 분석 결과

) : ( @@ -1692,6 +1697,7 @@ export default function CowOverviewPage() {
)} + */} diff --git a/frontend/src/app/cow/page.tsx b/frontend/src/app/cow/page.tsx index dbb4bf9..0ac1210 100644 --- a/frontend/src/app/cow/page.tsx +++ b/frontend/src/app/cow/page.tsx @@ -716,7 +716,7 @@ function MyCowContent() { > - 불가 {cows.filter(c => c.genomeScore === undefined || c.genomeScore === null).length} + 미검사 {cows.filter(c => c.genomeScore === undefined || c.genomeScore === null).length} diff --git a/frontend/src/components/common/global-filter-dialog.tsx b/frontend/src/components/common/global-filter-dialog.tsx index 838ee2d..d44ea08 100644 --- a/frontend/src/components/common/global-filter-dialog.tsx +++ b/frontend/src/components/common/global-filter-dialog.tsx @@ -504,13 +504,7 @@ export function GlobalFilterDialog({ externalOpen, onExternalOpenChange, geneCou className="h-8 md:h-9 text-xs md:text-base font-semibold px-2 md:px-3 relative" > - 필터 - 0 || traitCount > 0) ? "default" : "outline"} - className={`ml-1.5 text-[9px] md:text-xs px-1.5 py-0 ${(geneCount > 0 || traitCount > 0) ? "bg-white text-primary" : "text-muted-foreground"}`} - > - {(geneCount > 0 || traitCount > 0) ? "활성" : "비활성"} - + 필터 ({traitCount}) diff --git a/frontend/src/types/filter.types.ts b/frontend/src/types/filter.types.ts index 72bf2e8..a57f10e 100644 --- a/frontend/src/types/filter.types.ts +++ b/frontend/src/types/filter.types.ts @@ -112,9 +112,10 @@ export interface GlobalFilterSettings { } /** + * ==================================================================================================== * 기본 필터 초기값 설정 * 사용자가 해당 형질 선택하지 않았을때 필터의 초기 값 0 세팅 - * + * ==================================================================================================== * const [filterSettings, setFilterSettings] = useState(DEFAULT_FILTER_SETTINGS); * function resetFilter() { setFilterSettings(DEFAULT_FILTER_SETTINGS); // 초기화 @@ -134,22 +135,22 @@ export const DEFAULT_FILTER_SETTINGS: GlobalFilterSettings = { "12개월령체중": 0, // 경제형질 (점수: 0 ~ 10) - 도체중: 0, - 등심단면적: 0, - 등지방두께: 0, - 근내지방도: 0, + 도체중: 1, + 등심단면적: 1, + 등지방두께: 1, + 근내지방도: 1, // 체형형질 (점수: 0 ~ 10) - DB 형질명과 일치 - 체고: 0, + 체고: 1, 십자: 0, - 체장: 0, + 체장: 1, 흉심: 0, 흉폭: 0, 고장: 0, 요각폭: 0, 좌골폭: 0, 곤폭: 0, - 흉위: 0, + 흉위: 1, // 부위별무게 (점수: 0 ~ 10) - DB 형질명과 일치 안심weight: 0, @@ -176,7 +177,8 @@ export const DEFAULT_FILTER_SETTINGS: GlobalFilterSettings = { 갈비rate: 0, }, inbreedingThreshold: 0, // 근친도 기본값 0 - isActive: true, // 기본 7개 형질이 선택되어 있으므로 활성화 + isActive: true, // 기본 7개 형질이 선택되어 있으므로 활성화 + // 기본 각각 1점으로 세팅 updtDt: new Date(), };