fix: [misc] 거래처 카운트 수정 + 생산현황판 통계 API 교체

- 거래처 목록 카운트를 stats API 호출로 교체
- 생산현황판 대시보드 통계를 work-orders/stats API 활용
This commit is contained in:
2026-03-17 13:52:13 +09:00
parent 0931591dd3
commit 505aed2e8e
2 changed files with 56 additions and 30 deletions

View File

@@ -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,
});
}
}

View File

@@ -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<string, number>;
}
// ===== 대시보드 데이터 조회 =====
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<WorkOrderStatsApi>({
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<string, WorkerStatus>();