fix: [material] 입고관리 코드 정리 + 단가목록 동기화버튼 주석처리

- 입고 상세/처리 다이얼로그 코드 간소화
- 단가 목록 품목마스터 동기화 버튼 주석처리 (미구현)
- 테넌트 모듈 분리 분석/계획 문서 추가
This commit is contained in:
유병철
2026-03-17 20:51:58 +09:00
parent 37f0e57b16
commit 1151fb0bf7
6 changed files with 2275 additions and 57 deletions

View File

@@ -0,0 +1,437 @@
# Tenant-Based Module Separation: Cross-Module Dependency Audit
**Date**: 2026-03-17
**Scope**: Full dependency analysis for tenant-based module separation
**Status**: COMPLETE
---
## Module Separation Plan
| Tenant Package | Modules | File Count |
|---|---|---|
| Common ERP | dashboard, accounting, sales, HR, approval, board, customer-center, settings, master-data, material, outbound | ~majority |
| Kyungdong (Shutter MES) | production (56 files), quality (35 files) | 91 files |
| Juil (Construction) | construction (161 files) | 161 files |
| Optional | vehicle-management (13 files), vehicle (10 files) | 23 files |
---
## CRITICAL RISK (Will break immediately on separation)
### C1. Approval Module -> Production Component Import
**Files affected**: 1 file, blocks entire approval workflow
```
src/components/approval/ApprovalBox/index.tsx:76
import { InspectionReportModal } from '@/components/production/WorkOrders/documents/InspectionReportModal';
```
**Impact**: The approval inbox (Common ERP) directly imports a production document modal. If production module is removed, the approval box crashes entirely.
**Fix**: Extract `InspectionReportModal` to a shared `@/components/document-system/` or a shared document viewer module. Alternatively, use dynamic import with fallback.
---
### C2. Sales Module -> Production Component Imports (3 page files)
**Files affected**: 3 files under `src/app/[locale]/(protected)/sales/`
```
sales/order-management-sales/production-orders/page.tsx
import { getProductionOrders, getProductionOrderStats } from "@/components/production/ProductionOrders/actions";
import { ProductionOrder, ProductionOrderStats } from "@/components/production/ProductionOrders/types";
sales/order-management-sales/production-orders/[id]/page.tsx
import { getProductionOrderDetail } from "@/components/production/ProductionOrders/actions";
import { ProductionOrderDetail, ProductionOrderStats } from "@/components/production/ProductionOrders/types";
sales/order-management-sales/[id]/production-order/page.tsx
import { AssigneeSelectModal } from "@/components/production/WorkOrders/AssigneeSelectModal";
import { getProcessList } from "@/components/process-management/actions";
import { createProductionOrder } from "@/components/orders/actions";
```
**Impact**: The sales module has a "production orders" sub-page that directly imports production actions, types, and UI components. This entire sub-section becomes non-functional without the production module.
**Fix strategy**:
1. The `production-orders` sub-pages under sales should be conditionally loaded (tenant feature flag)
2. `ProductionOrders/actions.ts` and `types.ts` should be extracted to a shared interface package
3. `AssigneeSelectModal` should be moved to a shared component or lazy-loaded with fallback
---
### C3. Sales -> Production Route Navigation
**File**: `sales/order-management-sales/production-orders/[id]/page.tsx:247`
```
router.push("/production/work-orders");
```
**Impact**: Hard navigation to production route from sales. Will 404 if production routes don't exist.
**Fix**: Conditional navigation wrapped in tenant feature check.
---
### C4. QMS Page (Quality) -> Production + Outbound + Orders Imports
**File**: `src/app/[locale]/(protected)/quality/qms/page.tsx`
```
import { InspectionReportModal } from '@/components/production/WorkOrders/documents';
import { WorkLogModal } from '@/components/production/WorkOrders/documents';
import { ProductInspectionViewModal } from '@/components/quality/InspectionManagement/ProductInspectionViewModal';
```
**File**: `src/app/[locale]/(protected)/quality/qms/mockData.ts`
```
import type { WorkOrder } from '@/components/production/ProductionDashboard/types';
import type { ShipmentDetail } from '@/components/outbound/ShipmentManagement/types';
```
**File**: `src/app/[locale]/(protected)/quality/qms/components/InspectionModal.tsx`
```
import { DeliveryConfirmation } from '@/components/outbound/ShipmentManagement/documents/DeliveryConfirmation';
import { ShippingSlip } from '@/components/outbound/ShipmentManagement/documents/ShippingSlip';
import { SalesOrderDocument } from '@/components/orders/documents/SalesOrderDocument';
import type { ShipmentDetail } from '@/components/outbound/ShipmentManagement/types';
```
**Impact**: QMS (assigned to Kyungdong tenant with quality) imports from production (same tenant -- OK), but also from outbound and orders (Common ERP). If QMS is extracted WITH quality, it will still need access to outbound/orders document components from Common ERP.
**Fix**: This is actually a reverse dependency -- quality module needs Common ERP's outbound/orders docs. This direction is acceptable (tenant module depends on common). However, the production type imports need a shared types interface.
---
### C5. CEO Dashboard -> Production + Construction Data Sections
**Files affected**: Multiple files in `src/components/business/CEODashboard/`
```
CEODashboard.tsx: 'production' and 'construction' section rendering
sections/DailyProductionSection.tsx: production data display
sections/ConstructionSection.tsx: construction data display
sections/CalendarSection.tsx: '/production/work-orders' and '/construction/project/contract' route references
types.ts: DailyProductionData, ConstructionData, production/construction settings flags
useSectionSummary.ts: production and construction summary logic
```
**File**: `src/lib/api/dashboard/transformers/production-logistics.ts`
```
import type { DailyProductionData, UnshippedData, ConstructionData } from '@/components/business/CEODashboard/types';
```
**File**: `src/hooks/useCEODashboard.ts`
```
useDashboardFetch('dashboard/production/summary', ...)
useDashboardFetch('dashboard/construction/summary', ...)
```
**Impact**: The CEO Dashboard (Common ERP) renders production and construction sections. If modules are removed, these sections will fail. The dashboard types contain production/construction data structures hardcoded.
**Fix**:
1. Dashboard sections must be conditionally rendered based on tenant configuration
2. Dashboard types need module-awareness (optional types, feature flags)
3. Dashboard API hooks should gracefully handle missing endpoints
4. Route references in CalendarSection need tenant-aware navigation
---
### C6. Dashboard Invalidation System
**File**: `src/lib/dashboard-invalidation.ts`
```typescript
type DomainKey = '...' | 'production' | 'shipment' | 'construction';
const DOMAIN_SECTION_MAP = {
production: ['statusBoard', 'dailyProduction'],
construction: ['statusBoard', 'construction'],
};
```
**Impact**: The dashboard invalidation system in `@/lib/` (Common ERP) has hardcoded production and construction domains. If production/construction modules call `invalidateDashboard('production')`, this works cross-module. If they are removed, stale keys remain.
**Fix**: Make domain-section mapping configurable/dynamic. Register domains at module initialization.
---
## HIGH RISK (Will cause issues during development/testing)
### H1. Construction -> HR Module Import
**File**: `src/components/business/construction/site-briefings/SiteBriefingForm.tsx:61-64`
```
import { getEmployees } from '@/components/hr/EmployeeManagement/actions';
import type { Employee } from '@/components/hr/EmployeeManagement/types';
```
**Impact**: Construction module (Juil tenant) depends on HR module (Common ERP). This direction (tenant -> common) is acceptable for single-binary, but if construction is extracted to a separate package, it needs access to HR's interface.
**Fix**: Extract employee lookup to a shared API interface. Or accept that tenant modules depend on Common ERP (allowed direction).
---
### H2. Production -> Process-Management Import
**File**: `src/components/production/WorkerScreen/index.tsx:47`
```
import { getProcessList } from '@/components/process-management/actions';
```
**Impact**: Process management is under `master-data` (Common ERP). Production depends on it.
**Fix**: This is allowed (tenant -> common), but if extracting to separate package, needs clear interface.
---
### H3. Shared Type: `@/types/process.ts`
**Files**: 8 production files import from this shared type file
```
src/components/production/WorkerScreen/index.tsx
src/components/production/WorkOrders/documents/BendingInspectionContent.tsx
src/components/production/WorkOrders/documents/BendingWipInspectionContent.tsx
src/components/production/WorkOrders/documents/InspectionReportModal.tsx
src/components/production/WorkOrders/documents/ScreenInspectionContent.tsx
src/components/production/WorkOrders/documents/SlatInspectionContent.tsx
src/components/production/WorkOrders/documents/SlatJointBarInspectionContent.tsx
src/components/production/WorkOrders/documents/inspection-shared.tsx
```
**Impact**: `@/types/process.ts` (296 lines) contains `InspectionSetting`, `InspectionScope`, `Process`, `ProcessStep` types. These are used heavily by production but defined at the project root level.
**Fix**: This file should remain in Common ERP (it's process master-data definition). Production depends on it -- that direction is acceptable.
---
### H4. Dev Generator -> Production Type Import
**File**: `src/components/dev/generators/workOrderData.ts:13`
```
import type { ProcessOption } from '@/components/production/WorkOrders/actions';
```
**Impact**: Dev tooling imports a type from production. Low runtime risk (dev only) but will cause TS errors if production module is absent.
**Fix**: Move `ProcessOption` type to a shared types location, or make dev generators tenant-aware.
---
### H5. Production -> Dashboard Invalidation (Bidirectional)
**Files**:
```
src/components/production/WorkOrders/WorkOrderCreate.tsx:10 -> import { invalidateDashboard } from '@/lib/dashboard-invalidation';
src/components/production/WorkOrders/WorkOrderDetail.tsx:10 -> same
src/components/production/WorkOrders/WorkOrderEdit.tsx:11 -> same
src/components/business/construction/management/ConstructionDetailClient.tsx:4 -> same
```
**Impact**: Production and construction call `invalidateDashboard()` from `@/lib/` (Common ERP). This is allowed direction (tenant -> common). But the function's domain keys include `'production'` and `'construction'` -- if those modules are absent, orphan event listeners remain.
**Fix**: Register domain keys dynamically. Modules register their dashboard sections at init.
---
### H6. CEO Dashboard CalendarSection Route References
**File**: `src/components/business/CEODashboard/sections/CalendarSection.tsx`
```
order: '/production/work-orders',
construction: '/construction/project/contract',
```
**Impact**: Clicking calendar items navigates to production/construction routes. Will 404 if those tenant routes don't exist.
**Fix**: Tenant-aware route resolution with fallback or hidden navigation for unavailable modules.
---
### H7. Menu Transform Production Icon Mapping
**File**: `src/lib/utils/menuTransform.ts:89`
```
production: Factory,
```
**Impact**: Menu icon mapping contains production key. Low risk (backend controls menu visibility), but vestigial code remains.
**Fix**: Menu rendering is already dynamic from backend. Icon map can safely retain unused entries.
---
## MEDIUM RISK (Requires attention but not immediately breaking)
### M1. Shared Component Dependencies (template/document-system)
All three target modules (production, quality, construction) heavily depend on these shared components:
- `@/components/templates/UniversalListPage` -- used by all list pages
- `@/components/templates/IntegratedDetailTemplate` -- used by all detail pages
- `@/components/document-system/` -- DocumentViewer, SectionHeader, ConstructionApprovalTable
- `@/components/common/ServerErrorPage`
- `@/components/common/ScheduleCalendar`
- `@/components/organisms/` -- PageLayout, PageHeader, MobileCard
**Impact**: These are all Common ERP components. The dependency direction (tenant -> common) is allowed. No breakage on separation.
**Risk**: If extracting to separate npm packages, these become peer dependencies.
---
### M2. Zustand Store Dependencies
Target modules use these stores (all Common ERP):
```
production/WorkerScreen -> menuStore (useSidebarCollapsed)
quality/EquipmentRepair -> menuStore (useMenuStore)
quality/EquipmentManagement -> menuStore (useMenuStore)
quality/EquipmentForm -> menuStore (useMenuStore)
construction/estimates -> authStore (useAuthStore)
```
**Impact**: All stores are in Common ERP. Direction is allowed. No breakage on separation.
**Risk**: If separate packages, stores become shared singletons requiring careful provider setup.
---
### M3. Shared Hook Dependencies
Target modules import from `@/hooks/`:
```
production: usePermission
quality: useStatsLoader
construction: useStatsLoader, useListHandlers, useDateRange, useDaumPostcode, useCurrentTime
```
**Impact**: All hooks are Common ERP. Allowed direction.
---
### M4. `@/lib/` Utility Dependencies
All modules depend on standard utilities:
```
@/lib/utils (cn)
@/lib/utils/amount (formatNumber, formatAmount)
@/lib/utils/date (formatDate)
@/lib/utils/excel-download
@/lib/utils/redirect-error (isNextRedirectError)
@/lib/utils/status-config (getPresetStyle, getPriorityStyle)
@/lib/api/* (executeServerAction, executePaginatedAction, buildApiUrl, apiClient, serverFetch)
@/lib/formatters
@/lib/constants/filter-presets
```
**Impact**: All in Common ERP. Direction allowed.
---
### M5. document-system `ConstructionApprovalTable` Name Confusion
**File**: `src/components/document-system/components/ConstructionApprovalTable.tsx`
**Impact**: Despite the name, this is a generic 4-column approval table component in the shared `document-system`. It is imported by both production and construction modules. The name is misleading but the component is tenant-agnostic.
**Fix**: Consider renaming to `FourColumnApprovalTable` or similar during separation to avoid confusion.
---
### M6. Production -> Bending Image API References
**File**: `src/components/production/WorkOrders/documents/bending/utils.ts`
```
return `${API_BASE}/images/bending/guiderail/...`
return `${API_BASE}/images/bending/bottombar/...`
return `${API_BASE}/images/bending/box/...`
```
**Impact**: Production references backend image API paths specific to the shutter MES domain. These endpoints exist on the backend and are module-specific.
**Fix**: These stay with the production module. No cross-dependency issue.
---
### M7. Two Vehicle Modules
There are TWO vehicle-related component directories:
- `src/components/vehicle/` (10 files) -- older, simpler
- `src/components/vehicle-management/` (13 files) -- newer, IntegratedDetailTemplate-based
Both have separate app routes:
- `src/app/[locale]/(protected)/vehicle/` (old)
- `src/app/[locale]/(protected)/vehicle-management/` (new)
**Impact**: No cross-references found between them or from other modules. Both are fully self-contained.
**Fix**: Clean separation. May want to consolidate before extracting.
---
## LOW RISK (Informational / No action needed)
### L1. Module-Internal Dynamic Imports
Quality and production use `next/dynamic` for their own internal components (modals, heavy components). All dynamic imports are within their own module boundaries. No cross-module dynamic imports found.
### L2. No Shared CSS/Style Modules
All modules use Tailwind utility classes. No module-specific CSS modules or shared stylesheets exist. No breakage risk.
### L3. No React Context Providers in Modules
No module-specific React Context providers were found in production/quality/construction. All context comes from the shared `(protected)/layout.tsx` (RootProvider, ApiErrorProvider, FCMProvider, DevFillProvider, PermissionGate).
### L4. No Module-Specific Layout Files
No nested `layout.tsx` files exist under production/quality/construction app routes. All pages use the shared `(protected)/layout.tsx`.
### L5. No Test Files
No test files (`*.test.*`, `*.spec.*`) exist in the codebase. No test dependency issues.
### L6. No Cross-Module API Endpoint Calls
Each module calls only its own backend API endpoints:
- Production: `/api/v1/work-orders/*`, `/api/v1/work-results/*`, `/api/v1/production-orders/*`
- Quality: `/api/v1/quality/*`, `/api/v1/equipment/*`
- Construction: `/construction/*` (via apiClient)
No module calls another module's backend API directly. Clean backend separation.
### L7. CustomEvent System
The `dashboard:invalidate` CustomEvent in `@/lib/dashboard-invalidation.ts` is the only cross-module event system. Production and construction dispatch events; the CEO Dashboard listens. This is a pub/sub pattern and tolerant of missing publishers.
### L8. Tenant-Aware Cache Already Exists
`src/lib/cache/TenantAwareCache.ts` already implements tenant-id-based cache key isolation. This utility supports the separation strategy.
### L9. Middleware Has No Module-Specific Logic
`src/middleware.ts` handles i18n and bot detection. No module-specific routing or tenant-based path filtering exists in middleware. Clean.
---
## Dependency Flow Diagram (ASCII)
```
+-----------------+
| Common ERP |
| (dashboard, |
| accounting, |
| sales, HR, |
| approval, |
| settings, |
| master-data, |
| outbound, |
| templates, |
| document-sys) |
+--------+--------+
|
+--------------+---------------+
| | |
+--------v------+ +----v-------+ +-----v----------+
| Kyungdong | | Juil | | Vehicle |
| (production | | (construc | | (vehicle-mgmt) |
| + quality) | | tion) | | |
+------+--------+ +-----+------+ +----------------+
| | |
v v |
depends on depends on |
Common ERP Common ERP v
self-contained
FORBIDDEN ARROWS (must be broken):
Common ERP --X--> Production (approval, sales, dashboard)
Common ERP --X--> Construction (dashboard)
```
---
## Action Items Summary
### Must Fix Before Separation (6 items)
| # | Severity | Issue | Effort |
|---|----------|-------|--------|
| C1 | CRITICAL | ApprovalBox imports InspectionReportModal from production | Medium |
| C2 | CRITICAL | Sales production-orders pages import from production | High |
| C3 | CRITICAL | Sales page hard-navigates to /production/work-orders | Low |
| C4 | CRITICAL | QMS page imports production document modals | Medium |
| C5 | CRITICAL | CEO Dashboard hardcodes production/construction sections | High |
| C6 | CRITICAL | Dashboard invalidation hardcodes production/construction domains | Medium |
### Recommended Actions (6 items)
| # | Severity | Issue | Effort |
|---|----------|-------|--------|
| H1 | HIGH | Construction SiteBriefing imports HR actions | Low |
| H2 | HIGH | Production WorkerScreen imports process-management | Low |
| H4 | HIGH | Dev generator imports production type | Low |
| H5 | HIGH | Bidirectional dashboard invalidation coupling | Medium |
| H6 | HIGH | CEO Calendar hardcoded module routes | Low |
| H7 | HIGH | Menu transform production icon mapping | Low |
### Total Estimated Effort
- **CRITICAL fixes**: ~3-5 days of focused refactoring
- **HIGH fixes**: ~1-2 days
- **MEDIUM/LOW**: informational, no code changes needed
---
## Recommended Separation Strategy
### Phase 1: Shared Interface Layer (1-2 days)
1. Create `@/interfaces/production.ts` with shared types (ProcessOption, WorkOrder summary types)
2. Create `@/interfaces/quality.ts` with shared types (InspectionReport view props)
3. Move InspectionReportModal and WorkLogModal to `@/components/document-system/modals/`
### Phase 2: Feature Flags (1-2 days)
1. Add tenant feature flags: `hasProduction`, `hasQuality`, `hasConstruction`, `hasVehicle`
2. Conditionally render CEO Dashboard sections based on flags
3. Conditionally render sales production-order sub-pages based on flags
4. Make dashboard invalidation domain registry dynamic
### Phase 3: Route Guards (0.5 day)
1. Replace hardcoded route strings with a tenant-aware route resolver
2. Add fallback/redirect for unavailable module routes
### Phase 4: Clean Separation (1 day)
1. Move production + quality components to a Kyungdong-specific directory or package
2. Move construction components to a Juil-specific directory or package
3. Verify all builds pass with each module removed independently

File diff suppressed because it is too large Load Diff

View File

@@ -91,16 +91,6 @@ const INITIAL_FORM_DATA: Partial<ReceivingDetailType> = {
inventoryAdjustments: [],
};
// 로트번호 생성 (YYMMDD-NN)
function generateLotNo(): string {
const now = new Date();
const yy = String(now.getFullYear()).slice(-2);
const mm = String(now.getMonth() + 1).padStart(2, '0');
const dd = String(now.getDate()).padStart(2, '0');
const seq = String(Math.floor(Math.random() * 100)).padStart(2, '0');
return `${yy}${mm}${dd}-${seq}`;
}
// localStorage에서 로그인 사용자 정보 가져오기
function getLoggedInUser(): { name: string; department: string } {
if (typeof window === 'undefined') return { name: '', department: '' };
@@ -169,7 +159,6 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
const data = generateReceivingData();
setFormData((prev) => ({
...prev,
lotNo: generateLotNo(),
itemCode: data.itemCode,
itemName: data.itemName,
specification: data.specification,
@@ -574,15 +563,12 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
/>
</div>
{/* 원자재로트 - 수정 가능 */}
{/* 원자재로트 - 자동채번 (readOnly) */}
<div>
<Label className="text-sm text-muted-foreground"></Label>
<Input
className="mt-1.5"
value={formData.lotNo || ''}
onChange={(e) => setFormData((prev) => ({ ...prev, lotNo: e.target.value }))}
placeholder="원자재로트를 입력하세요"
/>
<div className="mt-1.5 px-3 py-2 bg-gray-200 border border-gray-300 rounded-md text-sm text-gray-500 cursor-not-allowed select-none">
{formData.lotNo || (isNewMode ? '저장 시 자동 생성' : '-')}
</div>
</div>
{/* 품목코드 - 검색 모달 선택 */}

View File

@@ -23,16 +23,6 @@ import {
import { Alert, AlertDescription } from '@/components/ui/alert';
import type { ReceivingDetail, ReceivingProcessFormData } from './types';
// LOT 번호 생성 함수 (YYMMDD-NN 형식)
function generateLotNo(): string {
const now = new Date();
const yy = String(now.getFullYear()).slice(-2);
const mm = String(now.getMonth() + 1).padStart(2, '0');
const dd = String(now.getDate()).padStart(2, '0');
const random = String(Math.floor(Math.random() * 100)).padStart(2, '0');
return `${yy}${mm}${dd}-${random}`;
}
interface Props {
open: boolean;
onOpenChange: (open: boolean) => void;
@@ -42,7 +32,7 @@ interface Props {
export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete }: Props) {
// 폼 데이터
const [receivingLot, setReceivingLot] = useState(() => generateLotNo());
const [receivingLot, setReceivingLot] = useState('');
const [supplierLot, setSupplierLot] = useState('');
const [receivingQty, setReceivingQty] = useState<string>((detail.orderQty ?? 0).toString());
const [receivingLocation, setReceivingLocation] = useState('');
@@ -56,9 +46,7 @@ export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete
const validateForm = useCallback((): boolean => {
const errors: string[] = [];
if (!receivingLot.trim()) {
errors.push('입고LOT는 필수 입력 항목입니다.');
}
// 입고LOT는 API가 자동 채번하므로 필수 검증 제거
if (!receivingQty.trim() || isNaN(Number(receivingQty)) || Number(receivingQty) <= 0) {
errors.push('입고수량은 필수 입력 항목입니다. 유효한 숫자를 입력해주세요.');
@@ -68,7 +56,7 @@ export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete
setValidationErrors(errors);
return errors.length === 0;
}, [receivingLot, receivingQty]);
}, [receivingQty]);
// 입고 처리
const handleSubmit = useCallback(async () => {
@@ -161,16 +149,12 @@ export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete
{/* 입력 필드 */}
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label className="text-sm">
LOT <span className="text-red-500">*</span>
</Label>
<Label className="text-sm text-muted-foreground">LOT</Label>
<Input
value={receivingLot}
onChange={(e) => {
setReceivingLot(e.target.value);
setValidationErrors([]);
}}
placeholder="예: 251223-41"
readOnly
className="bg-gray-50"
placeholder="저장 시 자동 생성"
/>
</div>
<div className="space-y-2">

View File

@@ -497,7 +497,7 @@ function transformFrontendToApi(
if (data.remark !== undefined) result.remark = data.remark;
if (data.receivingQty !== undefined) result.receiving_qty = data.receivingQty;
if (data.receivingDate !== undefined) result.receiving_date = data.receivingDate;
if (data.lotNo !== undefined) result.lot_no = data.lotNo;
// lot_no는 API가 자동 채번하므로 프론트에서 전송하지 않음
if (data.supplierMaterialNo !== undefined) result.material_no = data.supplierMaterialNo;
if (data.manufacturer !== undefined) result.manufacturer = data.manufacturer;
if (data.certificateFileId !== undefined) result.certificate_file_id = data.certificateFileId;
@@ -511,7 +511,7 @@ function transformProcessDataToApi(
): Record<string, unknown> {
return {
receiving_qty: data.receivingQty,
lot_no: data.receivingLot,
// lot_no는 API가 자동 채번하므로 프론트에서 전송하지 않음
supplier_lot: data.supplierLot,
receiving_location: data.receivingLocation,
remark: data.remark,

View File

@@ -13,7 +13,6 @@ import {
Package,
AlertCircle,
CheckCircle2,
RefreshCw,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
@@ -326,18 +325,19 @@ export function PricingListClient({
};
// 헤더 액션 (함수로 정의)
const headerActions = () => (
<Button
variant="outline"
onClick={() => {
// TODO: API 연동 시 품목 마스터 동기화 로직 구현
}}
className="ml-auto gap-2"
>
<RefreshCw className="h-4 w-4" />
</Button>
);
// NOTE: 품목 마스터 동기화 버튼 - 실제 로직 미구현 상태로 주석처리
// const headerActions = () => (
// <Button
// variant="outline"
// onClick={() => {
// // TODO: API 연동 시 품목 마스터 동기화 로직 구현
// }}
// className="ml-auto gap-2"
// >
// <RefreshCw className="h-4 w-4" />
// 품목 마스터 동기화
// </Button>
// );
// UniversalListPage 설정
const pricingConfig: UniversalListConfig<PricingListItem> = {
@@ -356,7 +356,7 @@ export function PricingListClient({
},
columns: tableColumns,
headerActions,
// headerActions, // 품목 마스터 동기화 버튼 미구현으로 주석처리
stats,
tabs,