diff --git a/src/app/[locale]/(protected)/sales/client-management-sales-admin/page.tsx b/src/app/[locale]/(protected)/sales/client-management-sales-admin/page.tsx index e969c882..c605c683 100644 --- a/src/app/[locale]/(protected)/sales/client-management-sales-admin/page.tsx +++ b/src/app/[locale]/(protected)/sales/client-management-sales-admin/page.tsx @@ -94,22 +94,17 @@ export default function CustomerAccountManagementPage() { // 전체 통계 로드 (최초 1회만) const loadTotalStats = useCallback(async () => { try { - // 전체 데이터 조회 (검색 조건 없이) - const response = await fetch("/api/proxy/clients?size=1000"); + const response = await fetch("/api/proxy/clients/stats"); if (response.ok) { const result = await response.json(); if (result.success && result.data) { - const allClients = result.data.data || []; + const data = result.data; setTotalStats({ - total: result.data.total || allClients.length, - purchase: allClients.filter((c: { client_type?: string }) => - c.client_type === "매입" || c.client_type === "매입매출" - ).length, - sales: allClients.filter((c: { client_type?: string }) => - c.client_type === "매출" || c.client_type === "매입매출" - ).length, - active: allClients.filter((c: { is_active?: boolean }) => c.is_active === true).length, - inactive: allClients.filter((c: { is_active?: boolean }) => c.is_active === false).length, + total: data.total ?? 0, + purchase: (data.purchase ?? 0) + (data.both ?? 0), + sales: (data.sales ?? 0) + (data.both ?? 0), + active: data.active ?? 0, + inactive: data.inactive ?? 0, }); } } diff --git a/src/components/production/ProductionDashboard/actions.ts b/src/components/production/ProductionDashboard/actions.ts index dac5d310..abf3c0f0 100644 --- a/src/components/production/ProductionDashboard/actions.ts +++ b/src/components/production/ProductionDashboard/actions.ts @@ -113,6 +113,18 @@ export async function getProcessOptions(): Promise<{ }; } +// ===== 작업지시 통계 조회 (백엔드 stats API) ===== +interface WorkOrderStatsApi { + total: number; + unassigned: number; + pending: number; + waiting: number; + in_progress: number; + completed: number; + shipped: number; + by_process: Record; +} + // ===== 대시보드 데이터 조회 ===== export async function getDashboardData(processCode?: string): Promise<{ success: boolean; @@ -128,30 +140,49 @@ export async function getDashboardData(processCode?: string): Promise<{ stats: { total: 0, waiting: 0, inProgress: 0, completed: 0, urgent: 0, delayed: 0 }, }; - const result = await executeServerAction<{ data: WorkOrderApiItem[] }>({ - url: buildApiUrl('/api/v1/work-orders', { - per_page: 100, - process_code: processCode && processCode !== 'all' ? processCode : undefined, + // 통계와 목록을 병렬 조회 + const [statsResult, listResult] = await Promise.all([ + executeServerAction({ + url: buildApiUrl('/api/v1/work-orders/stats'), + errorMessage: '통계 조회에 실패했습니다.', }), - errorMessage: '데이터 조회에 실패했습니다.', - }); + executeServerAction<{ data: WorkOrderApiItem[] }>({ + url: buildApiUrl('/api/v1/work-orders', { + per_page: 100, + process_code: processCode && processCode !== 'all' ? processCode : undefined, + }), + errorMessage: '데이터 조회에 실패했습니다.', + }), + ]); - if (!result.success || !result.data) { - return { ...emptyResult, error: result.error }; + if (!listResult.success || !listResult.data) { + return { ...emptyResult, error: listResult.error }; } - const apiData = result.data.data || []; + const apiData = listResult.data.data || []; const workOrders = apiData.map(transformToProductionFormat); - // 통계 계산 - const stats: DashboardStats = { - total: workOrders.length, - waiting: workOrders.filter(o => o.status === 'waiting').length, - inProgress: workOrders.filter(o => o.status === 'inProgress').length, - completed: workOrders.filter(o => o.status === 'completed').length, - urgent: workOrders.filter(o => o.isUrgent).length, - delayed: workOrders.filter(o => o.isDelayed).length, - }; + // 통계: 백엔드 stats API 기반 (정확한 전체 카운트) + // urgent/delayed는 목록 데이터에서 계산 (stats API에 미포함) + const apiStats = statsResult.success && statsResult.data ? statsResult.data : null; + const stats: DashboardStats = apiStats + ? { + total: apiStats.total, + waiting: (apiStats.unassigned ?? 0) + (apiStats.pending ?? 0) + (apiStats.waiting ?? 0), + inProgress: apiStats.in_progress ?? 0, + completed: (apiStats.completed ?? 0) + (apiStats.shipped ?? 0), + urgent: workOrders.filter(o => o.isUrgent).length, + delayed: workOrders.filter(o => o.isDelayed).length, + } + : { + // stats API 실패 시 목록 데이터 기반 폴백 + total: workOrders.length, + waiting: workOrders.filter(o => o.status === 'waiting').length, + inProgress: workOrders.filter(o => o.status === 'inProgress').length, + completed: workOrders.filter(o => o.status === 'completed').length, + urgent: workOrders.filter(o => o.isUrgent).length, + delayed: workOrders.filter(o => o.isDelayed).length, + }; // 작업자별 현황 집계 const workerMap = new Map();