feat: 회계/결재/생산/출하/대시보드 다수 개선 및 QA 수정

- BadDebtCollection, BillManagement, CardTransaction, TaxInvoice 회계 개선
- VendorManagement/VendorDetailClient 소폭 추가
- DocumentCreate/DraftBox 결재 기능 개선
- WorkOrder Create/Detail/Edit, ShipmentEdit 생산/출하 개선
- CEO 대시보드: PurchaseStatusSection, receivable/status-issue transformer 정비
- dashboard types/invalidation 확장
- LoginPage, Sidebar, HeaderFavoritesBar 레이아웃 수정
- QMS 페이지, StockStatusDetail, OrderRegistration 소폭 수정
- AttendanceManagement, VacationManagement HR 수정
- ConstructionDetailClient 건설 상세 개선
- claudedocs: 주간 구현내역, 대시보드 QA/수정계획, 결재/품질/생산/출하 문서 추가
This commit is contained in:
유병철
2026-03-09 21:06:01 +09:00
parent 7d369d1404
commit 68331be0ef
39 changed files with 1363 additions and 139 deletions

View File

@@ -1,6 +1,7 @@
'use client';
import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
import { invalidateDashboard } from '@/lib/dashboard-invalidation';
import { useRouter } from 'next/navigation';
import {
Clock,
@@ -310,6 +311,7 @@ export function AttendanceManagement() {
if (attendanceDialogMode === 'create') {
const result = await createAttendance(data);
if (result.success && result.data) {
invalidateDashboard('attendance');
setAttendanceRecords(prev => [result.data!, ...prev]);
} else {
console.error('Create failed:', result.error);
@@ -317,6 +319,7 @@ export function AttendanceManagement() {
} else if (selectedAttendance) {
const result = await updateAttendance(selectedAttendance.id, data);
if (result.success && result.data) {
invalidateDashboard('attendance');
setAttendanceRecords(prev =>
prev.map(r => r.id === selectedAttendance.id ? result.data! : r)
);

View File

@@ -1,6 +1,7 @@
'use client';
import { useState, useMemo, useCallback, useEffect, useRef } from 'react';
import { invalidateDashboard } from '@/lib/dashboard-invalidation';
import { format } from 'date-fns';
import { useDateRange } from '@/hooks';
import {
@@ -312,6 +313,7 @@ export function VacationManagement() {
const ids = Array.from(selectedItems).map((id) => parseInt(id, 10));
const result = await approveLeavesMany(ids);
if (result.success) {
invalidateDashboard('leave');
await fetchLeaveRequests();
await fetchUsageData(); // 휴가 사용현황도 갱신
} else {
@@ -340,6 +342,7 @@ export function VacationManagement() {
const ids = Array.from(selectedItems).map((id) => parseInt(id, 10));
const result = await rejectLeavesMany(ids, '관리자에 의해 반려됨');
if (result.success) {
invalidateDashboard('leave');
await fetchLeaveRequests();
} else {
console.error('[VacationManagement] 반려 실패:', result.error);
@@ -750,6 +753,7 @@ export function VacationManagement() {
reason: data.reason,
});
if (result.success) {
invalidateDashboard('leave');
await fetchGrantData();
await fetchUsageData();
} else {
@@ -780,6 +784,7 @@ export function VacationManagement() {
days: data.vacationDays,
});
if (result.success) {
invalidateDashboard('leave');
await fetchLeaveRequests();
await fetchUsageData();
} else {