Files
vexplor_dev/frontend/lib/api/shipping.ts
kjs f8ad041a8c Enhance Shipping Order and Plan Functionality
- Added new fields for delivery details in the shipping order controller, including delivery date, delivery destination ID, and delivery address.
- Implemented validation logic to ensure that only confirmed sales orders can be processed, preventing the registration of shipments for orders that are waiting, canceled, or completed.
- Updated the save functionality to handle new delivery-related fields and improved error handling for blocked orders.
- Enhanced the shipping plan controller to include status checks and automatic updates based on changes in order quantities.

(TASK: ERP-047)
2026-05-14 15:46:35 +09:00

186 lines
4.7 KiB
TypeScript

import { apiClient } from "./client";
export interface EnrichedOrder {
sourceId: string;
orderNo: string;
partCode: string;
partName: string;
partnerName: string;
dueDate: string;
orderQty: number;
shipQty: number;
balanceQty: number;
}
export interface ExistingPlan {
id: number;
sourceId: string;
planQty: number;
planDate: string;
shipmentPlanNo: string;
status: string;
}
export interface AggregateResponse {
[partCode: string]: {
totalBalance: number;
totalPlanQty: number;
currentStock: number;
availableStock: number;
inProductionQty: number;
existingPlans: ExistingPlan[];
orders: EnrichedOrder[];
};
}
export interface BatchSavePlan {
sourceId: string;
planQty: number;
planDate?: string;
}
// ID만 전달 → 백엔드에서 소스 테이블 자동 감지 + JOIN
export async function getShippingPlanAggregate(ids: string[]) {
const res = await apiClient.get("/shipping-plan/aggregate", {
params: { ids: ids.join(",") },
});
return res.data as {
success: boolean;
data: AggregateResponse;
source: "master" | "detail";
};
}
export async function batchSaveShippingPlans(plans: BatchSavePlan[], source?: string) {
const res = await apiClient.post("/shipping-plan/batch", { plans, source });
return res.data as { success: boolean; message?: string; data?: any };
}
// 출하계획 목록 조회 (관리 화면용)
export interface ShipmentPlanListItem {
id: number;
plan_date: string;
plan_qty: string;
status: string;
memo: string | null;
shipment_plan_no: string | null;
created_date: string;
created_by: string;
detail_id: string | null;
sales_order_id: number | null;
remain_qty: string | null;
order_no: string;
part_code: string;
part_name: string;
spec: string;
material: string;
customer_name: string;
partner_code: string;
due_date: string;
order_qty: string;
shipped_qty: string;
}
export interface ShipmentPlanListParams {
dateFrom?: string;
dateTo?: string;
status?: string;
customer?: string;
keyword?: string;
page?: number;
size?: number;
}
export async function getShipmentPlanList(params: ShipmentPlanListParams) {
const res = await apiClient.get("/shipping-plan/list", { params });
return res.data as {
success: boolean;
data: ShipmentPlanListItem[];
total?: number;
page?: number;
size?: number;
totalPages?: number;
};
}
// 출하계획 단건 수정
export async function updateShipmentPlan(id: number, data: { planQty?: number; planDate?: string; memo?: string }) {
const res = await apiClient.put(`/shipping-plan/${id}`, data);
return res.data as { success: boolean; data?: any; message?: string };
}
// ─── 출하지시 API ───
export async function getShippingOrderList(params?: {
dateFrom?: string;
dateTo?: string;
status?: string;
customer?: string;
keyword?: string;
page?: number;
size?: number;
}) {
const res = await apiClient.get("/shipping-order/list", { params });
return res.data as {
success: boolean;
data: any[];
total?: number;
page?: number;
size?: number;
totalPages?: number;
};
}
export async function saveShippingOrder(data: any) {
const res = await apiClient.post("/shipping-order/save", data);
return res.data as { success: boolean; data?: any; message?: string };
}
export async function previewShippingOrderNo() {
const res = await apiClient.get("/shipping-order/preview-no");
return res.data as { success: boolean; instructionNo: string };
}
export async function deleteShippingOrders(ids: number[]) {
const res = await apiClient.post("/shipping-order/delete", { ids });
return res.data as { success: boolean; deletedCount?: number; message?: string };
}
// 모달 데이터 소스 (페이징 지원)
export interface PaginatedSourceResponse {
success: boolean;
data: any[];
totalCount: number;
page: number;
pageSize: number;
}
export async function getShipmentPlanSource(params?: {
keyword?: string;
customer?: string;
dateFrom?: string;
dateTo?: string;
page?: number;
pageSize?: number;
}) {
const res = await apiClient.get("/shipping-order/source/shipment-plan", { params });
return res.data as PaginatedSourceResponse;
}
export async function getSalesOrderSource(params?: {
keyword?: string;
customer?: string;
dateFrom?: string;
dateTo?: string;
page?: number;
pageSize?: number;
}) {
const res = await apiClient.get("/shipping-order/source/sales-order", { params });
return res.data as PaginatedSourceResponse;
}
export async function getItemSource(params?: { keyword?: string; page?: number; pageSize?: number }) {
const res = await apiClient.get("/shipping-order/source/item", { params });
return res.data as PaginatedSourceResponse;
}