feat(WEB): 주문/작업지시 공정 연동 개선
- process_id 필드 추가 (공정 연동) - 공정별 다중 작업지시 생성 지원 (processIds) - ApiProductionOrderResponse 타입 수정 (work_orders 배열 지원) - process 정보 포함 응답 처리
This commit is contained in:
@@ -416,7 +416,7 @@ export function OrderRegistration({
|
||||
<span>{form.selectedQuotation.siteName}</span>
|
||||
<span className="text-muted-foreground mx-2">/</span>
|
||||
<span className="text-green-600 font-medium">
|
||||
{formatAmount(form.selectedQuotation.amount)}원
|
||||
{formatAmount(form.selectedQuotation.amount)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -491,6 +491,7 @@ export function OrderRegistration({
|
||||
setForm((prev) => ({ ...prev, siteName: e.target.value }));
|
||||
clearFieldError("siteName");
|
||||
}}
|
||||
disabled={!!form.selectedQuotation}
|
||||
className={cn(fieldErrors.siteName && "border-red-500")}
|
||||
/>
|
||||
{fieldErrors.siteName && (
|
||||
@@ -757,8 +758,6 @@ export function OrderRegistration({
|
||||
<TableHead className="w-[60px] text-center">순번</TableHead>
|
||||
<TableHead>품목코드</TableHead>
|
||||
<TableHead>품명</TableHead>
|
||||
<TableHead>층</TableHead>
|
||||
<TableHead>부호</TableHead>
|
||||
<TableHead>규격</TableHead>
|
||||
<TableHead className="w-[80px] text-center">수량</TableHead>
|
||||
<TableHead className="w-[60px] text-center">단위</TableHead>
|
||||
@@ -770,7 +769,7 @@ export function OrderRegistration({
|
||||
<TableBody>
|
||||
{form.items.length === 0 ? (
|
||||
<TableRow>
|
||||
<TableCell colSpan={11} className="text-center py-8 text-muted-foreground">
|
||||
<TableCell colSpan={9} className="text-center py-8 text-muted-foreground">
|
||||
품목이 없습니다. 견적을 선택하거나 품목을 추가해주세요.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
@@ -784,8 +783,6 @@ export function OrderRegistration({
|
||||
</code>
|
||||
</TableCell>
|
||||
<TableCell>{item.itemName}</TableCell>
|
||||
<TableCell>{item.type || "-"}</TableCell>
|
||||
<TableCell>{item.symbol || "-"}</TableCell>
|
||||
<TableCell>{item.spec}</TableCell>
|
||||
<TableCell className="text-center">
|
||||
<Input
|
||||
@@ -803,10 +800,10 @@ export function OrderRegistration({
|
||||
</TableCell>
|
||||
<TableCell className="text-center">{item.unit}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
{formatAmount(item.unitPrice)}원
|
||||
{formatAmount(item.unitPrice)}
|
||||
</TableCell>
|
||||
<TableCell className="text-right font-medium">
|
||||
{formatAmount(item.amount)}원
|
||||
{formatAmount(item.amount)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Button
|
||||
@@ -838,7 +835,7 @@ export function OrderRegistration({
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<span className="text-muted-foreground">소계:</span>
|
||||
<span className="w-32 text-right">
|
||||
{formatAmount(form.subtotal)}원
|
||||
{formatAmount(form.subtotal)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
@@ -860,7 +857,7 @@ export function OrderRegistration({
|
||||
<div className="flex items-center gap-4 text-lg font-semibold">
|
||||
<span>총금액:</span>
|
||||
<span className="w-32 text-right text-green-600">
|
||||
{formatAmount(form.totalAmount)}원
|
||||
{formatAmount(form.totalAmount)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -120,6 +120,7 @@ interface ApiWorkOrder {
|
||||
work_order_no: string;
|
||||
sales_order_id: number;
|
||||
project_name: string | null;
|
||||
process_id: number | null;
|
||||
process_type: string;
|
||||
status: string;
|
||||
assignee_id: number | null;
|
||||
@@ -131,10 +132,12 @@ interface ApiWorkOrder {
|
||||
updated_at: string;
|
||||
assignee?: { id: number; name: string } | null;
|
||||
team?: { id: number; name: string } | null;
|
||||
process?: { id: number; process_name: string } | null;
|
||||
}
|
||||
|
||||
interface ApiProductionOrderResponse {
|
||||
work_order: ApiWorkOrder;
|
||||
work_order?: ApiWorkOrder;
|
||||
work_orders?: ApiWorkOrder[];
|
||||
order: ApiOrder;
|
||||
}
|
||||
|
||||
@@ -292,7 +295,8 @@ export interface CreateFromQuoteData {
|
||||
|
||||
// 생산지시 생성용
|
||||
export interface CreateProductionOrderData {
|
||||
processType?: 'screen' | 'slat' | 'bending';
|
||||
processId?: number;
|
||||
processIds?: number[]; // 공정별 다중 작업지시 생성용
|
||||
priority?: 'urgent' | 'high' | 'normal' | 'low';
|
||||
assigneeId?: number;
|
||||
teamId?: number;
|
||||
@@ -306,6 +310,7 @@ export interface WorkOrder {
|
||||
workOrderNo: string;
|
||||
salesOrderId: number;
|
||||
projectName: string | null;
|
||||
processId?: number;
|
||||
processType: string;
|
||||
status: string;
|
||||
assigneeId?: number;
|
||||
@@ -317,11 +322,13 @@ export interface WorkOrder {
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
process?: { id: number; processName: string };
|
||||
}
|
||||
|
||||
// 생산지시 생성 결과
|
||||
export interface ProductionOrderResult {
|
||||
workOrder: WorkOrder;
|
||||
workOrder?: WorkOrder;
|
||||
workOrders?: WorkOrder[];
|
||||
order: Order;
|
||||
}
|
||||
|
||||
@@ -514,6 +521,11 @@ function transformWorkOrderApiToFrontend(apiData: ApiWorkOrder): WorkOrder {
|
||||
isActive: apiData.is_active,
|
||||
createdAt: apiData.created_at,
|
||||
updatedAt: apiData.updated_at,
|
||||
processId: apiData.process_id ?? undefined,
|
||||
process: apiData.process ? {
|
||||
id: apiData.process.id,
|
||||
processName: apiData.process.process_name,
|
||||
} : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -956,7 +968,12 @@ export async function createProductionOrder(
|
||||
}> {
|
||||
try {
|
||||
const apiData: Record<string, unknown> = {};
|
||||
if (data?.processType) apiData.process_type = data.processType;
|
||||
// 다중 공정 ID (우선) 또는 단일 공정 ID
|
||||
if (data?.processIds && data.processIds.length > 0) {
|
||||
apiData.process_ids = data.processIds;
|
||||
} else if (data?.processId) {
|
||||
apiData.process_id = data.processId;
|
||||
}
|
||||
if (data?.priority) apiData.priority = data.priority;
|
||||
if (data?.assigneeId) apiData.assignee_id = data.assigneeId;
|
||||
if (data?.teamId) apiData.team_id = data.teamId;
|
||||
@@ -982,12 +999,22 @@ export async function createProductionOrder(
|
||||
return { success: false, error: result.message || '생산지시 생성에 실패했습니다.' };
|
||||
}
|
||||
|
||||
// 다중 또는 단일 작업지시 응답 처리
|
||||
const responseData: ProductionOrderResult = {
|
||||
order: transformApiToFrontend(result.data.order),
|
||||
};
|
||||
|
||||
if (result.data.work_orders && result.data.work_orders.length > 0) {
|
||||
// 다중 작업지시 응답
|
||||
responseData.workOrders = result.data.work_orders.map(transformWorkOrderApiToFrontend);
|
||||
} else if (result.data.work_order) {
|
||||
// 단일 작업지시 응답 (하위 호환성)
|
||||
responseData.workOrder = transformWorkOrderApiToFrontend(result.data.work_order);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
workOrder: transformWorkOrderApiToFrontend(result.data.work_order),
|
||||
order: transformApiToFrontend(result.data.order),
|
||||
},
|
||||
data: responseData,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('[createProductionOrder] Error:', error);
|
||||
|
||||
Reference in New Issue
Block a user