feat: Add cutting plan management for COMPANY_30
- Cutting optimization (Guillotine FFDH) with mixed/homogeneous modes - Remnant management with persistence (cutting_plan_sheet.remnants JSONB) - Work instruction creation linked via batch_no/cutting_plan_id Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
97
backend-node/src/controllers/cuttingPlanController.ts
Normal file
97
backend-node/src/controllers/cuttingPlanController.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 절단계획 컨트롤러
|
||||
*/
|
||||
|
||||
import { Response } from "express";
|
||||
import { AuthenticatedRequest } from "../types/auth";
|
||||
import * as svc from "../services/cuttingPlanService";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
function wrap(res: Response, fn: () => Promise<any>, errMsg: string) {
|
||||
return fn().then(
|
||||
(data) => res.json({ success: true, data }),
|
||||
(e: any) => {
|
||||
logger.error(errMsg, { error: e?.message });
|
||||
return res.status(500).json({ success: false, message: e?.message || errMsg });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function getMaterials(req: AuthenticatedRequest, res: Response) {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const cutType = (req.query.cutType as string) || "area";
|
||||
return wrap(res, () => svc.getMaterials(companyCode, cutType), "원자재 조회 실패");
|
||||
}
|
||||
|
||||
export function searchItems(req: AuthenticatedRequest, res: Response) {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const keyword = req.query.keyword as string | undefined;
|
||||
return wrap(res, () => svc.searchItems(companyCode, keyword), "품목 검색 실패");
|
||||
}
|
||||
|
||||
export function getOrders(req: AuthenticatedRequest, res: Response) {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const from = req.query.from as string | undefined;
|
||||
const to = req.query.to as string | undefined;
|
||||
const keyword = req.query.keyword as string | undefined;
|
||||
const page = req.query.page ? parseInt(req.query.page as string, 10) : undefined;
|
||||
const limit = req.query.limit ? parseInt(req.query.limit as string, 10) : undefined;
|
||||
const excludeInPlan = req.query.excludeInPlan === "true";
|
||||
return wrap(
|
||||
res,
|
||||
() => svc.getOrders(companyCode, { from, to, keyword, page, limit, excludeInPlan }),
|
||||
"수주 조회 실패"
|
||||
);
|
||||
}
|
||||
|
||||
export function getPlans(req: AuthenticatedRequest, res: Response) {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const { from, to, planNo, status } = req.query;
|
||||
return wrap(res, () => svc.getPlans(companyCode, {
|
||||
from: from as string, to: to as string,
|
||||
planNo: planNo as string, status: status as string,
|
||||
}), "계획 목록 조회 실패");
|
||||
}
|
||||
|
||||
export async function getPlanDetail(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const id = parseInt(req.params.id, 10);
|
||||
const data = await svc.getPlanDetail(companyCode, id);
|
||||
if (!data) return res.status(404).json({ success: false, message: "계획을 찾을 수 없습니다" });
|
||||
return res.json({ success: true, data });
|
||||
} catch (e: any) {
|
||||
logger.error("계획 상세 조회 실패", { error: e?.message });
|
||||
return res.status(500).json({ success: false, message: e?.message });
|
||||
}
|
||||
}
|
||||
|
||||
export function nextPlanNo(req: AuthenticatedRequest, res: Response) {
|
||||
const companyCode = req.user!.companyCode;
|
||||
return wrap(res, () => svc.nextPlanNo(companyCode), "계획번호 생성 실패");
|
||||
}
|
||||
|
||||
export async function savePlan(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const userId = req.user!.userId || "system";
|
||||
const data = await svc.savePlan(companyCode, userId, req.body);
|
||||
return res.json({ success: true, data });
|
||||
} catch (e: any) {
|
||||
logger.error("계획 저장 실패", { error: e?.message });
|
||||
return res.status(500).json({ success: false, message: e?.message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function deletePlan(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const id = parseInt(req.params.id, 10);
|
||||
const ok = await svc.deletePlan(companyCode, id);
|
||||
if (!ok) return res.status(404).json({ success: false, message: "삭제 대상을 찾을 수 없습니다" });
|
||||
return res.json({ success: true });
|
||||
} catch (e: any) {
|
||||
logger.error("계획 삭제 실패", { error: e?.message });
|
||||
return res.status(500).json({ success: false, message: e?.message });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user