구매관리 발주서 _outsourcing/_english 양식 + 양식 선택 모달

- 양식 선택 모달 신설 (운영판 wace 1:1: 일반/외주가공/영문/취소)
- 외주가공 발주서 다이얼로그 — 타이틀 변경, 좌 4필드, 그리드 WORK_ORDER_NO/업체명/제품명/부품명
- 영문 발주서 다이얼로그 — 영문 헤더, 2열 5행 필드(Shipment/Attn.to/Packing/Validity/Remarks),
  CURRENCY 컬럼, TOTAL, 서명영역(stamp_seal)
- proposal 발주서생성 → 양식 선택 모달, order 행클릭 → row.form_type 자동 분기
- listVendorOptions: client_mng.status 컬럼 부재로 빈배열 반환 → use_yn 사용 (RPS 함정)
- listUserOptions: name/position/phone/email alias 추가 (담당자 select 자동 채움)
- init API: USER_INFO 에서 안동윤/서동민 user_id lookup → sales_mng_user_id 자동 채움
This commit is contained in:
hjjeong
2026-05-19 14:12:33 +09:00
parent 806153174c
commit 8258c2f0cf
7 changed files with 1336 additions and 20 deletions
@@ -87,6 +87,25 @@ export async function getPurchaseOrderFormInit(proposalObjid: string): Promise<O
logger.warn("발주번호 채번 실패", { error: e.message });
}
// USER_INFO 에서 기본 담당자 user_id lookup (select 자동 매칭용)
// 운영판 wace 는 매니저 select 옵션에 user_id 가 바인딩됨
let mgr1Id = "";
let mgr2Id = "";
try {
const r = await pool.query(
`SELECT USER_ID, USER_NAME
FROM USER_INFO
WHERE USER_NAME IN ('안동윤', '서동민')
OR EMAIL IN ('ady1225@rps-korea.com', 'sdm0927@rps-korea.com')`,
);
for (const u of r.rows) {
if (u.user_name === "안동윤" && !mgr1Id) mgr1Id = String(u.user_id);
if (u.user_name === "서동민" && !mgr2Id) mgr2Id = String(u.user_id);
}
} catch (e: any) {
logger.warn("기본 담당자 user_id lookup 실패", { error: e.message });
}
const todayIso = new Date().toISOString().slice(0, 10);
const master: Record<string, any> = {
objid: "", // 신규 — 클라이언트가 채워 보내거나 save 시 채번
@@ -100,10 +119,12 @@ export async function getPurchaseOrderFormInit(proposalObjid: string): Promise<O
contract_mgmt_objid: proposal?.project_no ?? "",
title: proposal?.title ?? "",
// wace controller _general 기본 담당자 (RPS 운영 고정값)
sales_mng_user_id: mgr1Id,
manager_name: "안동윤",
manager_position: "팀장",
manager_phone: "010-2313-2702",
manager_email: "ady1225@rps-korea.com",
sales_mng_user_id2: mgr2Id,
manager_name2: "서동민",
manager_position2: "주임",
manager_phone2: "010-9538-9513",
@@ -114,6 +135,7 @@ export async function getPurchaseOrderFormInit(proposalObjid: string): Promise<O
const parts: Record<string, any>[] = [];
if (proposalObjid) {
try {
logger.info("발주서 init parts 조회", { proposalObjid });
const r = await pool.query(
`SELECT
ROW_NUMBER() OVER(ORDER BY SRP.REGDATE) AS rnum,
@@ -155,6 +177,7 @@ export async function getPurchaseOrderFormInit(proposalObjid: string): Promise<O
ORDER BY SRP.REGDATE`,
[proposalObjid],
);
logger.info("발주서 init parts 결과", { proposalObjid, rowCount: r.rows.length });
for (const row of r.rows) {
const qty = toNum(row.qty);
+17 -7
View File
@@ -1062,19 +1062,21 @@ export async function listPurchaseOrderList(filter: PurchaseListFilter): Promise
// ─── 옵션 — 공급업체 / 작성자 (구매메뉴 공용) ──────────────────
// 견적요청서 / 발주서 vendor — wace 매퍼는 client_mng 와 매칭 (supply_mng 아님)
// RPS client_mng 는 status 컬럼 없음 → use_yn 사용 ('Y'/'N')
export async function listVendorOptions(): Promise<{ code: string; label: string }[]> {
const pool = getPool();
try {
const r = await pool.query(
`SELECT OBJID AS code, CLIENT_NM AS label
FROM CLIENT_MNG
WHERE COALESCE(STATUS, 'Y') IN ('Y', 'active', 'ACTIVE', '활성')
WHERE COALESCE(USE_YN, 'Y') IN ('Y', 'y', '1')
AND CLIENT_NM IS NOT NULL AND CLIENT_NM <> ''
ORDER BY CLIENT_NM
LIMIT 2000`,
);
return r.rows;
} catch {
} catch (e: any) {
logger.error("listVendorOptions 실패", { error: e.message });
return [];
}
}
@@ -1090,24 +1092,32 @@ export async function listSupplierOptions(): Promise<{ code: string; label: stri
ORDER BY SUPPLY_NAME`,
);
return r.rows;
} catch {
} catch (e: any) {
logger.error("listSupplierOptions 실패", { error: e.message });
return [];
}
}
export async function listUserOptions(): Promise<{ code: string; label: string }[]> {
export async function listUserOptions(): Promise<
{ code: string; label: string; name?: string; position?: string; phone?: string; email?: string }[]
> {
const pool = getPool();
try {
const r = await pool.query(
`SELECT USER_ID AS code,
USER_NAME || COALESCE(' (' || DEPT_NAME || ')', '') AS label
`SELECT USER_ID AS code,
USER_NAME || COALESCE(' (' || DEPT_NAME || ')', '') AS label,
USER_NAME AS name,
POSITION_NAME AS position,
CELL_PHONE AS phone,
EMAIL AS email
FROM USER_INFO
WHERE COALESCE(STATUS, 'active') IN ('active', '활성', 'ACTIVE')
AND USER_NAME IS NOT NULL AND USER_NAME <> ''
ORDER BY USER_NAME`,
);
return r.rows;
} catch {
} catch (e: any) {
logger.error("listUserOptions 실패", { error: e.message });
return [];
}
}