Implement production plan listing feature with API and frontend integration
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* 생산계획 API 클라이언트
|
||||
*/
|
||||
|
||||
import apiClient from "./client";
|
||||
import { apiClient } from "./client";
|
||||
|
||||
// ─── 타입 정의 ───
|
||||
|
||||
@@ -94,10 +94,51 @@ export interface GenerateScheduleResponse {
|
||||
deleted_count: number;
|
||||
};
|
||||
schedules: ProductionPlan[];
|
||||
deletedSchedules?: ProductionPlan[];
|
||||
keptSchedules?: ProductionPlan[];
|
||||
}
|
||||
|
||||
// ─── API 함수 ───
|
||||
|
||||
/** 생산계획 목록 조회 */
|
||||
export async function getPlans(params?: {
|
||||
productType?: string;
|
||||
status?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
itemCode?: string;
|
||||
}) {
|
||||
const queryParams = new URLSearchParams();
|
||||
if (params?.productType) queryParams.set("productType", params.productType);
|
||||
if (params?.status) queryParams.set("status", params.status);
|
||||
if (params?.startDate) queryParams.set("startDate", params.startDate);
|
||||
if (params?.endDate) queryParams.set("endDate", params.endDate);
|
||||
if (params?.itemCode) queryParams.set("itemCode", params.itemCode);
|
||||
|
||||
const qs = queryParams.toString();
|
||||
const url = `/production/plans${qs ? `?${qs}` : ""}`;
|
||||
const response = await apiClient.get(url);
|
||||
return response.data as { success: boolean; data: ProductionPlan[] };
|
||||
}
|
||||
|
||||
/** 자동 스케줄 미리보기 (DB 변경 없이 예상 결과) */
|
||||
export async function previewSchedule(request: GenerateScheduleRequest) {
|
||||
const response = await apiClient.post("/production/generate-schedule/preview", request);
|
||||
return response.data as { success: boolean; data: GenerateScheduleResponse };
|
||||
}
|
||||
|
||||
/** 반제품 계획 미리보기 */
|
||||
export async function previewSemiSchedule(
|
||||
planIds: number[],
|
||||
options?: { considerStock?: boolean; excludeUsed?: boolean }
|
||||
) {
|
||||
const response = await apiClient.post("/production/generate-semi-schedule/preview", {
|
||||
plan_ids: planIds,
|
||||
options: options || {},
|
||||
});
|
||||
return response.data as { success: boolean; data: { count: number; schedules: ProductionPlan[] } };
|
||||
}
|
||||
|
||||
/** 수주 데이터 조회 (품목별 그룹핑) */
|
||||
export async function getOrderSummary(params?: {
|
||||
excludePlanned?: boolean;
|
||||
@@ -110,44 +151,44 @@ export async function getOrderSummary(params?: {
|
||||
if (params?.itemName) queryParams.set("itemName", params.itemName);
|
||||
|
||||
const qs = queryParams.toString();
|
||||
const url = `/api/production/order-summary${qs ? `?${qs}` : ""}`;
|
||||
const url = `/production/order-summary${qs ? `?${qs}` : ""}`;
|
||||
const response = await apiClient.get(url);
|
||||
return response.data as { success: boolean; data: OrderSummaryItem[] };
|
||||
}
|
||||
|
||||
/** 안전재고 부족분 조회 */
|
||||
export async function getStockShortage() {
|
||||
const response = await apiClient.get("/api/production/stock-shortage");
|
||||
const response = await apiClient.get("/production/stock-shortage");
|
||||
return response.data as { success: boolean; data: StockShortageItem[] };
|
||||
}
|
||||
|
||||
/** 생산계획 상세 조회 */
|
||||
export async function getPlanById(planId: number) {
|
||||
const response = await apiClient.get(`/api/production/plan/${planId}`);
|
||||
const response = await apiClient.get(`/production/plan/${planId}`);
|
||||
return response.data as { success: boolean; data: ProductionPlan };
|
||||
}
|
||||
|
||||
/** 생산계획 수정 */
|
||||
export async function updatePlan(planId: number, data: Partial<ProductionPlan>) {
|
||||
const response = await apiClient.put(`/api/production/plan/${planId}`, data);
|
||||
const response = await apiClient.put(`/production/plan/${planId}`, data);
|
||||
return response.data as { success: boolean; data: ProductionPlan };
|
||||
}
|
||||
|
||||
/** 생산계획 삭제 */
|
||||
export async function deletePlan(planId: number) {
|
||||
const response = await apiClient.delete(`/api/production/plan/${planId}`);
|
||||
const response = await apiClient.delete(`/production/plan/${planId}`);
|
||||
return response.data as { success: boolean; message: string };
|
||||
}
|
||||
|
||||
/** 자동 스케줄 생성 */
|
||||
export async function generateSchedule(request: GenerateScheduleRequest) {
|
||||
const response = await apiClient.post("/api/production/generate-schedule", request);
|
||||
const response = await apiClient.post("/production/generate-schedule", request);
|
||||
return response.data as { success: boolean; data: GenerateScheduleResponse };
|
||||
}
|
||||
|
||||
/** 스케줄 병합 */
|
||||
export async function mergeSchedules(scheduleIds: number[], productType?: string) {
|
||||
const response = await apiClient.post("/api/production/merge-schedules", {
|
||||
const response = await apiClient.post("/production/merge-schedules", {
|
||||
schedule_ids: scheduleIds,
|
||||
product_type: productType || "완제품",
|
||||
});
|
||||
@@ -159,7 +200,7 @@ export async function generateSemiSchedule(
|
||||
planIds: number[],
|
||||
options?: { considerStock?: boolean; excludeUsed?: boolean }
|
||||
) {
|
||||
const response = await apiClient.post("/api/production/generate-semi-schedule", {
|
||||
const response = await apiClient.post("/production/generate-semi-schedule", {
|
||||
plan_ids: planIds,
|
||||
options: options || {},
|
||||
});
|
||||
@@ -168,7 +209,7 @@ export async function generateSemiSchedule(
|
||||
|
||||
/** 스케줄 분할 */
|
||||
export async function splitSchedule(planId: number, splitQty: number) {
|
||||
const response = await apiClient.post(`/api/production/plan/${planId}/split`, {
|
||||
const response = await apiClient.post(`/production/plan/${planId}/split`, {
|
||||
split_qty: splitQty,
|
||||
});
|
||||
return response.data as {
|
||||
|
||||
Reference in New Issue
Block a user