refactor(order): 백엔드 데이터 구조 개선, 미사용 UI 제거

백엔드:
- order_mng_master + order_mng_sub LEFT JOIN 조회
- json_agg로 품목 배열화 (items: OrderItem[])
- 타입 정의 추가 (order.ts)

프론트엔드:
- 미사용 그룹화 UI 컴포넌트 삭제
- 평면 테이블 형태 유지 (기존 UI 그대로)

Modified:
- backend-node/src/controllers/orderController.ts
This commit is contained in:
SeongHyun Kim 2025-11-21 12:17:29 +09:00
parent 1a171d450c
commit 147f910c88
2 changed files with 126 additions and 8 deletions

View File

@ -164,7 +164,7 @@ export async function createOrder(req: Request, res: Response) {
}
/**
* API
* API ( + JOIN)
* GET /api/orders
*/
export async function getOrders(req: Request, res: Response) {
@ -183,14 +183,14 @@ export async function getOrders(req: Request, res: Response) {
// 멀티테넌시 (writer 필드에 company_code 포함)
if (companyCode !== "*") {
whereConditions.push(`writer LIKE $${paramIndex}`);
whereConditions.push(`m.writer LIKE $${paramIndex}`);
params.push(`%${companyCode}%`);
paramIndex++;
}
// 검색
if (searchText) {
whereConditions.push(`objid LIKE $${paramIndex}`);
whereConditions.push(`m.objid LIKE $${paramIndex}`);
params.push(`%${searchText}%`);
paramIndex++;
}
@ -200,16 +200,47 @@ export async function getOrders(req: Request, res: Response) {
? `WHERE ${whereConditions.join(" AND ")}`
: "";
// 카운트 쿼리
const countQuery = `SELECT COUNT(*) as count FROM order_mng_master ${whereClause}`;
// 카운트 쿼리 (고유한 수주 개수)
const countQuery = `
SELECT COUNT(DISTINCT m.objid) as count
FROM order_mng_master m
${whereClause}
`;
const countResult = await pool.query(countQuery, params);
const total = parseInt(countResult.rows[0]?.count || "0");
// 데이터 쿼리
// 데이터 쿼리 (마스터 + 품목 JOIN)
const dataQuery = `
SELECT * FROM order_mng_master
SELECT
m.objid as order_no,
m.partner_objid,
m.final_delivery_date,
m.reason,
m.status,
m.reg_date,
m.writer,
COALESCE(
json_agg(
CASE WHEN s.objid IS NOT NULL THEN
json_build_object(
'sub_objid', s.objid,
'part_objid', s.part_objid,
'partner_price', s.partner_price,
'partner_qty', s.partner_qty,
'delivery_date', s.delivery_date,
'status', s.status,
'regdate', s.regdate
)
END
ORDER BY s.regdate
) FILTER (WHERE s.objid IS NOT NULL),
'[]'::json
) as items
FROM order_mng_master m
LEFT JOIN order_mng_sub s ON m.objid = s.order_mng_master_objid
${whereClause}
ORDER BY reg_date DESC
GROUP BY m.objid, m.partner_objid, m.final_delivery_date, m.reason, m.status, m.reg_date, m.writer
ORDER BY m.reg_date DESC
LIMIT $${paramIndex} OFFSET $${paramIndex + 1}
`;
@ -218,6 +249,13 @@ export async function getOrders(req: Request, res: Response) {
const dataResult = await pool.query(dataQuery, params);
logger.info("수주 목록 조회 성공", {
companyCode,
total,
page: parseInt(page as string),
itemCount: dataResult.rows.length,
});
res.json({
success: true,
data: dataResult.rows,

View File

@ -0,0 +1,80 @@
/**
*
*/
/**
* (order_mng_sub)
*/
export interface OrderItem {
sub_objid: string; // 품목 고유 ID (예: ORD-20251121-051_1)
part_objid: string; // 품목 코드
partner_price: number; // 단가
partner_qty: number; // 수량
delivery_date: string | null; // 납기일
status: string; // 상태
regdate: string; // 등록일
}
/**
* (order_mng_master)
*/
export interface OrderMaster {
order_no: string; // 수주 번호 (예: ORD-20251121-051)
partner_objid: string; // 거래처 코드
final_delivery_date: string | null; // 최종 납품일
reason: string | null; // 메모/사유
status: string; // 상태
reg_date: string; // 등록일
writer: string; // 작성자 (userId|companyCode)
}
/**
* + (API )
*/
export interface OrderWithItems extends OrderMaster {
items: OrderItem[]; // 품목 목록
}
/**
*
*/
export interface CreateOrderRequest {
inputMode: string; // 입력 방식
salesType?: string; // 판매 유형 (국내/해외)
priceType?: string; // 단가 방식
customerCode: string; // 거래처 코드
contactPerson?: string; // 담당자
deliveryDestination?: string; // 납품처
deliveryAddress?: string; // 납품장소
deliveryDate?: string; // 납품일
items: Array<{
item_code?: string; // 품목 코드
id?: string; // 품목 ID (item_code 대체)
quantity?: number; // 수량
unit_price?: number; // 단가
selling_price?: number; // 판매가
amount?: number; // 금액
delivery_date?: string; // 품목별 납기일
}>;
memo?: string; // 메모
tradeInfo?: {
// 해외 판매 시
incoterms?: string;
paymentTerms?: string;
currency?: string;
portOfLoading?: string;
portOfDischarge?: string;
hsCode?: string;
};
}
/**
*
*/
export interface CreateOrderResponse {
orderNo: string; // 생성된 수주 번호
masterObjid: string; // 마스터 ID
itemCount: number; // 품목 개수
totalAmount: number; // 전체 금액
}