feat(WEB): 수주관리 Phase 2 타입 정의 확장 및 공정관리 개별 품목 표시 수정

- Order, OrderItem 인터페이스에 상세 페이지용 필드 추가
- OrderFormData, OrderItemFormData에 수정 페이지용 필드 추가
- 변환 함수에서 새 필드 매핑 처리
- 공정관리 개별 품목을 ID 대신 품목명으로 표시
This commit is contained in:
2026-01-08 20:57:49 +09:00
parent ba36c0ec19
commit fde8726e14
4 changed files with 87 additions and 29 deletions

View File

@@ -178,39 +178,36 @@ export function ProcessDetail({ process }: ProcessDetailProps) {
<CardTitle className="text-base flex items-center gap-2">
<Package className="h-4 w-4" />
{individualItems.length > 0 && individualItems[0].items && (
<Badge variant="secondary" className="ml-2">
{individualItems[0].items.length}
</Badge>
)}
</CardTitle>
</CardHeader>
<CardContent className="pt-6">
{individualItems.length === 0 ? (
{individualItems.length === 0 || !individualItems[0].items?.length ? (
<div className="text-center py-8 text-muted-foreground">
<Package className="h-10 w-10 mx-auto mb-3 opacity-30" />
<p className="text-sm"> </p>
</div>
) : (
<div className="space-y-3">
{individualItems.map((rule) => (
<div
key={rule.id}
className="flex items-center justify-between p-4 border rounded-lg"
>
<div className="flex items-center gap-4">
<Badge variant={rule.isActive ? 'default' : 'secondary'}>
{rule.isActive ? '활성' : '비활성'}
</Badge>
<div>
<div className="font-medium">
{rule.conditionValue}
</div>
{rule.description && (
<div className="text-sm text-muted-foreground">
{rule.description}
</div>
)}
<div className="max-h-80 overflow-y-auto">
<div className="space-y-2">
{individualItems[0].items.map((item) => (
<div
key={item.id}
className="flex items-center justify-between p-3 border rounded-lg bg-muted/30 hover:bg-muted/50 transition-colors"
>
<div className="flex items-center gap-3">
<Badge variant="outline" className="font-mono text-xs">
{item.code}
</Badge>
<span className="font-medium">{item.name}</span>
</div>
</div>
<Badge variant="outline">: {rule.priority}</Badge>
</div>
))}
))}
</div>
</div>
)}
</CardContent>

View File

@@ -3,7 +3,7 @@
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { serverFetch } from '@/lib/api/fetch-wrapper';
import type { Process, ProcessFormData, ClassificationRule } from '@/types/process';
import type { Process, ProcessFormData, ClassificationRule, IndividualItem } from '@/types/process';
// ============================================================================
// API 타입 정의
@@ -107,13 +107,22 @@ function transformApiToFrontend(apiData: ApiProcess): Process {
function transformProcessItemsToRules(processItems: ApiProcessItem[]): ClassificationRule[] {
if (processItems.length === 0) return [];
const activeItems = processItems.filter(pi => pi.is_active);
if (activeItems.length === 0) return [];
// 모든 품목 ID를 쉼표로 구분하여 하나의 규칙으로 통합
const itemIds = processItems
.filter(pi => pi.is_active)
const itemIds = activeItems
.map(pi => String(pi.item_id))
.join(',');
if (!itemIds) return [];
// 품목 상세 정보 추출 (code, name 포함)
const items: IndividualItem[] = activeItems
.filter(pi => pi.item) // item 정보가 있는 것만
.map(pi => ({
id: String(pi.item!.id),
code: pi.item!.code,
name: pi.item!.name,
}));
return [{
id: `individual-${Date.now()}`,
@@ -122,9 +131,10 @@ function transformProcessItemsToRules(processItems: ApiProcessItem[]): Classific
matchingType: 'equals',
conditionValue: itemIds,
priority: 0,
description: `개별 품목 ${processItems.length}`,
description: `개별 품목 ${activeItems.length}`,
isActive: true,
createdAt: new Date().toISOString(),
items, // 품목 상세 정보 추가
}];
}