From 6fa69d81f464aee673c12ab943eff72063695302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Thu, 22 Jan 2026 09:47:05 +0900 Subject: [PATCH] =?UTF-8?q?CEO=20=EB=8C=80=EC=8B=9C=EB=B3=B4=EB=93=9C=20AP?= =?UTF-8?q?I=20=EC=A0=84=ED=99=98=20=EB=B0=8F=20=EC=A3=BC=EB=AC=B8=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CEO 대시보드 mock 데이터 제거, 실제 API 연동 - 대시보드 transformers/types 추가 - 영업 주문 관리 페이지 수정 - 주문 actions 업데이트 --- src/app/.DS_Store | Bin 0 -> 6148 bytes .../order-management-sales/[id]/page.tsx | 54 ++-- .../sales/order-management-sales/page.tsx | 3 + src/components/.DS_Store | Bin 0 -> 10244 bytes .../business/CEODashboard/CEODashboard.tsx | 6 +- .../business/CEODashboard/mockData.ts | 305 +----------------- .../sections/TodayIssueSection.tsx | 8 +- src/components/orders/actions.ts | 24 +- src/lib/.DS_Store | Bin 0 -> 6148 bytes src/lib/api/dashboard/transformers.ts | 87 ++++- src/lib/api/dashboard/types.ts | 7 + 11 files changed, 149 insertions(+), 345 deletions(-) create mode 100644 src/app/.DS_Store create mode 100644 src/components/.DS_Store create mode 100644 src/lib/.DS_Store diff --git a/src/app/.DS_Store b/src/app/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e26ff0f25c76352d38a4299580eb7b5be32f5c8e GIT binary patch literal 6148 zcmeHKy-veG47S@0K`b2^?-lX}p$bos5g|cS#E%js3ld{yM&5;;1+nlDEDXE_pU+m> zkRmZ51h(Y+E@%6E`L2p6}jLi>#b@ z`@(NzKri6v<~UDBSMqBbEOd9jv235Ac^S@NaZS6)JhhJU(WB&ZaR!_LXW+jufSN6m?koD} z3^)VMz`%ff9|BY`H|!PTrvpQ50e}gXqhKz*gv12H+^|=K1;QE%)KIn-gEbuM!TfT= zUQxq|t@&Wf%+{fB%#Qs-bSKUgeRKw#fiVMfeOyTWKl-}=9|!r9GvEyTDF!$x%3_IE zvf4U%IjOY)dI}X0zg}?&!6cSq_(~~0fJVW3kO?q1>=m&B@jn8Q1|OV(A7$VJ`~6Pw literal 0 HcmV?d00001 diff --git a/src/app/[locale]/(protected)/sales/order-management-sales/[id]/page.tsx b/src/app/[locale]/(protected)/sales/order-management-sales/[id]/page.tsx index b680f045..4b9d6295 100644 --- a/src/app/[locale]/(protected)/sales/order-management-sales/[id]/page.tsx +++ b/src/app/[locale]/(protected)/sales/order-management-sales/[id]/page.tsx @@ -775,31 +775,35 @@ export default function OrderDetailPage() { /> {/* 문서 모달 */} - + {order && ( + + )} - {/* 취소 확인 다이얼로그 */} + {/* 다이얼로그들 */} + {order && ( + <> @@ -1097,6 +1101,8 @@ export default function OrderDetailPage() { + + )} ); } \ No newline at end of file diff --git a/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx b/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx index 519bfc5d..c8cfb6df 100644 --- a/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx +++ b/src/app/[locale]/(protected)/sales/order-management-sales/page.tsx @@ -71,9 +71,12 @@ function getOrderStatusBadge(status: OrderStatus) { order_confirmed: { label: "수주확정", variant: "default", className: "bg-gray-100 text-gray-700 border-gray-200" }, production_ordered: { label: "생산지시완료", variant: "default", className: "bg-blue-100 text-blue-700 border-blue-200" }, in_production: { label: "생산중", variant: "default", className: "bg-green-100 text-green-700 border-green-200" }, + produced: { label: "생산완료", variant: "default", className: "bg-blue-100 text-blue-700 border-blue-200" }, rework: { label: "재작업중", variant: "default", className: "bg-orange-100 text-orange-700 border-orange-200" }, work_completed: { label: "작업완료", variant: "default", className: "bg-blue-600 text-white border-blue-600" }, + shipping: { label: "출하중", variant: "default", className: "bg-purple-100 text-purple-700 border-purple-200" }, shipped: { label: "출하완료", variant: "default", className: "bg-gray-500 text-white border-gray-500" }, + completed: { label: "완료", variant: "default", className: "bg-gray-500 text-white border-gray-500" }, cancelled: { label: "취소", variant: "default", className: "bg-red-100 text-red-700 border-red-200" }, }; diff --git a/src/components/.DS_Store b/src/components/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..81805e1752124a8bb6990941ea899b6c0c119540 GIT binary patch literal 10244 zcmeHMziU%b6h8ME+Y}Y56`_jq5C?G(Gj(xDO9~Dhq#bk-+N7ZkP4dzvMcpzu2>uH? zDX5#H;NVyXXD0_8ii?9F;w1RpAH6x}y_e@yka92Fd(wBmbIsr|5oNGbM6QZo(?~6ZP90m6b-)>1D9tK~Nwl5EKXs1O;lLEk&@Yoc5Mjl{%VrQ$)4y`q=7}I7C%DF0+ zVkqm5{#e6dtIiIsweF;>J1G}gxeP^_=d()s)8 zJF>Tv)N1v1QpeMBe{1I3lkL6vG-CZ9h~6f@A-Dl|oB(UI3kI9=_Ta@Q-p6A zx08$_=k?3DZ*<%;)e*N(E$UJeR^DDjOONv~oX5}R?Z)TCXpk9;^C`j!UeT)NHAxL> zgH;o}1}Rpw{5y-_oO+Mu+tUNXDK!pfG#(}Rkl`}{K6-U@(01h;i ze*0$@4))6w6ieI zt=9x?V;&Q;w&hH!^MBI)oXguQo{JcRt1}KGd6@IQjJaxp#lY&4T2-pQ4K5iB=hMCA z`Q+e6>J;GwuV`B9Gv#)D&+I>a0!WqU?)7{W=k{*JbITczD^`pY{IHNvBFtV(uA<7d zgXf&X(ml_?`0%LdJ`pD}adfOuf&xK-pg>R{C=e7lnhNOuj!|NL|Gzl?_kRNlO;8{x za5NQArP@ku0q%b#`d2 zaRYL;o>=-D4JK^*nPbMv6SjzE&!4mzi70|3m)ov-F&s0 - {/* 버튼 */} + {/* TODO: 버튼 - API 구현 후 활성화
e.stopPropagation()}> - {item.needsApproval ? ( + {item.needsApproval && ( <>
+ */} )) )} diff --git a/src/components/orders/actions.ts b/src/components/orders/actions.ts index 14588f69..7a0f170d 100644 --- a/src/components/orders/actions.ts +++ b/src/components/orders/actions.ts @@ -197,10 +197,13 @@ export type OrderStatus = | 'order_registered' // DRAFT | 'order_confirmed' // CONFIRMED | 'production_ordered' // IN_PROGRESS - | 'in_production' // IN_PROGRESS (세부) - | 'rework' // IN_PROGRESS (세부) - | 'work_completed' // IN_PROGRESS (세부) - | 'shipped' // COMPLETED + | 'in_production' // IN_PRODUCTION + | 'produced' // PRODUCED + | 'shipping' // SHIPPING + | 'shipped' // SHIPPED + | 'completed' // COMPLETED + | 'rework' // (세부 - 레거시) + | 'work_completed' // (세부 - 레거시) | 'cancelled'; // CANCELLED export interface Order { @@ -401,7 +404,11 @@ const API_TO_FRONTEND_STATUS: Record = { 'DRAFT': 'order_registered', 'CONFIRMED': 'order_confirmed', 'IN_PROGRESS': 'production_ordered', - 'COMPLETED': 'shipped', + 'IN_PRODUCTION': 'in_production', + 'PRODUCED': 'produced', + 'SHIPPING': 'shipping', + 'SHIPPED': 'shipped', + 'COMPLETED': 'completed', 'CANCELLED': 'cancelled', }; @@ -409,10 +416,13 @@ const FRONTEND_TO_API_STATUS: Record = { 'order_registered': 'DRAFT', 'order_confirmed': 'CONFIRMED', 'production_ordered': 'IN_PROGRESS', - 'in_production': 'IN_PROGRESS', + 'in_production': 'IN_PRODUCTION', + 'produced': 'PRODUCED', + 'shipping': 'SHIPPING', + 'shipped': 'SHIPPED', + 'completed': 'COMPLETED', 'rework': 'IN_PROGRESS', 'work_completed': 'IN_PROGRESS', - 'shipped': 'COMPLETED', 'cancelled': 'CANCELLED', }; diff --git a/src/lib/.DS_Store b/src/lib/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f346b7985ee912ea073f6c18ff3f533ae506b9c0 GIT binary patch literal 6148 zcmeHKy-ve05I)l&Ra6xn7!XsKS?IzXs`3If`DCwj1q! z5gqp2RWp=P0KPGesOK@#`m-BzId86W&b)SzPFaiM9xrV&?;^!uj;TinKJ(hSA9cBR zp9U|lNBX=@y~|#lQOM7y?o&c1KL6xa^XE~QfA6A^)JB%y$(WwLIK$_^;`3K%g7YWX zK^Mq7N$L3WUaDL3Gu?fS&z9e)t@kx&U00*;v;F;YKN9<41<NKosy5D4E+D_y3*w|NnlG+=&9Bz`s&J1#P26YK0+m7`Gx8hX{ZHR?@0gNnW2H}Cphk%wrCQ;y56?g{}9HiU; literal 0 HcmV?d00001 diff --git a/src/lib/api/dashboard/transformers.ts b/src/lib/api/dashboard/transformers.ts index f8bc53db..360c2d68 100644 --- a/src/lib/api/dashboard/transformers.ts +++ b/src/lib/api/dashboard/transformers.ts @@ -75,6 +75,59 @@ function calculateChangeRate(current: number, previous: number): number { // 1. DailyReport 변환 // ============================================ +/** + * 운영자금 안정성에 따른 색상 반환 + * 참조: AI 리포트 색상 체계 가이드 - 섹션 2.3 + */ +function getStabilityColor(stability: string): 'red' | 'green' | 'blue' { + switch (stability) { + case 'stable': + return 'blue'; // 6개월 이상 - 안정적 + case 'caution': + return 'green'; // 3-6개월 - 주의 (주황 대신 green 사용, 기존 타입 호환) + case 'warning': + return 'red'; // 3개월 미만 - 경고 + default: + return 'blue'; + } +} + +/** + * 운영자금 안정성 메시지 생성 + * - 음수: 현금성 자산 적자 상태 + * - 0~3개월: 자금 부족 우려 + * - 3~6개월: 자금 관리 필요 + * - 6개월 이상: 안정적 + */ +function getStabilityMessage(months: number | null, stability: string, cashAsset: number): string { + if (months === null) { + return '월 운영비 데이터가 없어 안정성을 판단할 수 없습니다.'; + } + + // 현금성 자산이 음수인 경우 (적자 상태) + if (cashAsset < 0 || months < 0) { + return '현금성 자산이 부족한 상태입니다. 긴급 자금 확보가 필요합니다.'; + } + + // 운영 가능 기간이 거의 없는 경우 (1개월 미만) + if (months < 1) { + return '운영 자금이 거의 소진된 상태입니다. 즉시 자금 확보가 필요합니다.'; + } + + const monthsText = `${months}개월분`; + + switch (stability) { + case 'stable': + return `월 운영비용 대비 ${monthsText}이 확보되어 안정적입니다.`; + case 'caution': + return `월 운영비용 대비 ${monthsText}이 확보되어 있습니다. 자금 관리가 필요합니다.`; + case 'warning': + return `월 운영비용 대비 ${monthsText}만 확보되어 자금 부족 우려가 있습니다.`; + default: + return `월 운영비용 대비 ${monthsText}이 확보되어 있습니다.`; + } +} + /** * 일일 일보 CheckPoints 생성 * 참조: AI 리포트 색상 체계 가이드 - 섹션 2 @@ -109,15 +162,37 @@ function generateDailyReportCheckPoints(api: DailyReportApiResponse): CheckPoint }); } - // 현금성 자산 현황 + // 현금성 자산 + 운영자금 안정성 현황 const cashAsset = api.cash_asset_total; + const operatingMonths = api.operating_months; + const operatingStability = api.operating_stability; + const stabilityColor = getStabilityColor(operatingStability); + const stabilityMessage = getStabilityMessage(operatingMonths, operatingStability, cashAsset); + + // 하이라이트 생성 (음수/적자 상태일 때는 "X개월분" 대신 다른 메시지) + const isDeficit = cashAsset < 0 || (operatingMonths !== null && operatingMonths < 0); + const isAlmostEmpty = operatingMonths !== null && operatingMonths >= 0 && operatingMonths < 1; + + const highlights: Array<{ text: string; color: 'red' | 'green' | 'blue' }> = []; + + if (isDeficit) { + highlights.push({ text: '긴급 자금 확보 필요', color: 'red' }); + } else if (isAlmostEmpty) { + highlights.push({ text: '즉시 자금 확보 필요', color: 'red' }); + } else if (operatingMonths !== null && operatingMonths >= 1) { + highlights.push({ text: `${operatingMonths}개월분`, color: stabilityColor }); + if (operatingStability === 'stable') { + highlights.push({ text: '안정적', color: 'blue' }); + } else if (operatingStability === 'warning') { + highlights.push({ text: '자금 부족 우려', color: 'red' }); + } + } + checkPoints.push({ id: 'dr-cash-asset', - type: 'info' as CheckPointType, - message: `총 현금성 자산이 ${formatAmount(cashAsset)}입니다.`, - highlights: [ - { text: formatAmount(cashAsset), color: 'blue' as const }, - ], + type: isDeficit || isAlmostEmpty ? 'warning' as CheckPointType : 'info' as CheckPointType, + message: `총 현금성 자산이 ${formatAmount(cashAsset)}입니다. ${stabilityMessage}`, + highlights, }); return checkPoints; diff --git a/src/lib/api/dashboard/types.ts b/src/lib/api/dashboard/types.ts index 2cddb9c1..1f3d6555 100644 --- a/src/lib/api/dashboard/types.ts +++ b/src/lib/api/dashboard/types.ts @@ -16,6 +16,9 @@ export interface CurrencyTotals { balance: number; // 잔액 } +/** 운영자금 안정성 상태 */ +export type OperatingStability = 'stable' | 'caution' | 'warning' | 'unknown'; + /** GET /api/proxy/daily-report/summary 응답 */ export interface DailyReportApiResponse { date: string; // "2026-01-20" @@ -25,6 +28,10 @@ export interface DailyReportApiResponse { cash_asset_total: number; // 현금성 자산 합계 krw_totals: CurrencyTotals; // 원화 합계 usd_totals: CurrencyTotals; // 달러 합계 + // 운영자금 안정성 지표 + monthly_operating_expense: number; // 월 운영비 (직전 3개월 평균) + operating_months: number | null; // 운영 가능 개월 수 + operating_stability: OperatingStability; // 안정성 상태 } // ============================================