구매관리 견적요청서 빈 그리드 채움 (quotation_request_master/detail 신설)
- DDL: quotation_request_master(14 cols) + quotation_request_detail(15 cols) 운영 → RPS 타입 차이: numeric objid → varchar(64), detail.part_objid bigint(part_mng FK) - 데이터: 운영 sample master 4건 / detail 4건 (sales_request_part 미존재 → NULL fallback) - 백엔드 listQuotationRequest — wace salesMng.xml:5248-5349 매퍼 1:1 (vendor → client_mng JOIN, attach_file_info QUOTATION_RECEIVED 카운트) - listVendorOptions(client_mng) 신규 — 발주서 vendor 옵션이 supply_mng 와 분리됨 - listPurchaseRequest.has_quotation_request 분기 활성화 - quote-request page.tsx UI 문자열 내부 참조 제거, vendor 옵션 client_mng 로 교체
This commit is contained in:
@@ -47,6 +47,16 @@ export async function getSuppliers(_req: AuthenticatedRequest, res: Response) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function getVendors(_req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const data = await svc.listVendorOptions();
|
||||
return res.json({ success: true, data });
|
||||
} catch (e: any) {
|
||||
logger.error("공급업체(client_mng) 옵션 실패", { error: e.message });
|
||||
return res.status(500).json({ success: false, message: e.message });
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUsers(_req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const data = await svc.listUserOptions();
|
||||
|
||||
@@ -21,6 +21,7 @@ router.get("/project-status", ctrl.getProjectStatus); // 프로젝트별
|
||||
|
||||
// 공통 옵션
|
||||
router.get("/options/suppliers", ctrl.getSuppliers);
|
||||
router.get("/options/vendors", ctrl.getVendors); // wace client_mng 기반
|
||||
router.get("/options/users", ctrl.getUsers);
|
||||
router.get("/options/projects", ctrl.getProjects);
|
||||
|
||||
|
||||
@@ -144,8 +144,11 @@ export async function listPurchaseRequest(filter: PurchaseListFilter): Promise<L
|
||||
FROM MBOM_DETAIL MD
|
||||
JOIN PART_MNG PP ON MD.PART_OBJID::VARCHAR = PP.OBJID::VARCHAR
|
||||
WHERE MD.MBOM_HEADER_OBJID = SRM.MBOM_HEADER_OBJID) AS part_extra_count,
|
||||
-- 견적요청서 존재여부 (quotation_request_master 누락 → 일괄 'N')
|
||||
'N' AS has_quotation_request,
|
||||
-- 견적요청서 존재여부 (quotation_request_master 와 sales_request_master_objid 매칭)
|
||||
CASE WHEN EXISTS (
|
||||
SELECT 1 FROM QUOTATION_REQUEST_MASTER QRM
|
||||
WHERE QRM.SALES_REQUEST_MASTER_OBJID = SRM.OBJID
|
||||
) THEN 'Y' ELSE 'N' END AS has_quotation_request,
|
||||
SRM.REQUEST_USER_ID AS request_user,
|
||||
COALESCE(user_name(SRM.REQUEST_USER_ID), SRM.REQUEST_USER_ID, '') AS request_user_name,
|
||||
SRM.DELIVERY_REQUEST_DATE AS delivery_request_date,
|
||||
@@ -177,12 +180,115 @@ export async function listPurchaseRequest(filter: PurchaseListFilter): Promise<L
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 2) 견적요청서관리 (wace salesMng.xml quotationRequestList) ──
|
||||
// quotation_request_master 누락 → 빈 그리드.
|
||||
// ─── 2) 견적요청서관리 (wace salesMng.xml getQuotationRequestList 매퍼 1:1) ──
|
||||
//
|
||||
// quotation_request_master + quotation_request_detail + sales_request_master +
|
||||
// project_mgmt + contract_mgmt + client_mng (vendor) + comm_code + user_info +
|
||||
// attach_file_info (DOC_TYPE='QUOTATION_RECEIVED').
|
||||
//
|
||||
// 매퍼 본문: wace_plm/src/com/pms/mapper/salesMng.xml:5248-5349
|
||||
// 검색: year / project_no / quotation_request_no / vendor / mail_send_yn / writer / product_cd
|
||||
|
||||
export async function listQuotationRequest(filter: PurchaseListFilter): Promise<ListResult<any>> {
|
||||
const { page, pageSize } = clampPaging(filter);
|
||||
logger.warn("listQuotationRequest: quotation_request_master 테이블 미존재 — 빈 응답");
|
||||
return { rows: [], totalCount: 0, page, pageSize };
|
||||
const pool = getPool();
|
||||
const { limit, offset, page, pageSize } = clampPaging(filter);
|
||||
|
||||
const where: string[] = [];
|
||||
const params: any[] = [];
|
||||
const addParam = (val: any) => { params.push(val); return `$${params.length}`; };
|
||||
|
||||
if (filter.year) where.push(`EXTRACT(YEAR FROM QRM.REG_DATE) = ${addParam(Number(filter.year))}`);
|
||||
if (filter.project_no) where.push(`PM.PROJECT_NO ILIKE ${addParam(`%${filter.project_no}%`)}`);
|
||||
if (filter.proposal_no) where.push(`QRM.QUOTATION_REQUEST_NO ILIKE ${addParam(`%${filter.proposal_no}%`)}`);
|
||||
if (filter.partner_objid) where.push(`QRM.VENDOR_OBJID = ${addParam(filter.partner_objid)}`);
|
||||
if (filter.mail_send_yn) where.push(`COALESCE(QRM.MAIL_SEND_YN, 'N') = ${addParam(filter.mail_send_yn)}`);
|
||||
if (filter.writer) where.push(`QRM.WRITER = ${addParam(filter.writer)}`);
|
||||
if (filter.product_cd) where.push(`COALESCE(CTM.PRODUCT, SRM.PRODUCT_NAME) = ${addParam(filter.product_cd)}`);
|
||||
|
||||
const whereSql = where.length ? `WHERE ${where.join(" AND ")}` : "";
|
||||
|
||||
const dataSql = `
|
||||
SELECT
|
||||
QRM.OBJID AS objid,
|
||||
QRM.QUOTATION_REQUEST_NO AS quotation_request_no,
|
||||
QRM.SALES_REQUEST_MASTER_OBJID AS sales_request_master_objid,
|
||||
QRM.PROJECT_MGMT_OBJID AS project_mgmt_objid,
|
||||
QRM.VENDOR_OBJID AS vendor_objid,
|
||||
QRM.VENDOR_TYPE AS vendor_type,
|
||||
QRM.STATUS AS status,
|
||||
CASE QRM.STATUS
|
||||
WHEN 'create' THEN '작성중'
|
||||
WHEN 'sent' THEN '발송완료'
|
||||
WHEN 'received' THEN '견적수신'
|
||||
WHEN 'completed' THEN '완료'
|
||||
ELSE COALESCE(QRM.STATUS, '')
|
||||
END AS status_name,
|
||||
QRM.MAIL_SEND_DATE AS mail_send_date,
|
||||
TO_CHAR(QRM.MAIL_SEND_DATE, 'YYYY-MM-DD') AS mail_send_date_title,
|
||||
COALESCE(QRM.MAIL_SEND_YN, 'N') AS mail_send_yn,
|
||||
QRM.DUE_DATE AS due_date,
|
||||
TO_CHAR(QRM.DUE_DATE, 'YYYY-MM-DD') AS due_date_title,
|
||||
QRM.REMARK AS remark,
|
||||
QRM.WRITER AS writer,
|
||||
COALESCE((SELECT USER_NAME FROM USER_INFO WHERE USER_ID = QRM.WRITER LIMIT 1), QRM.WRITER, '') AS writer_name,
|
||||
QRM.REG_DATE AS reg_date,
|
||||
TO_CHAR(QRM.REG_DATE, 'YYYY-MM-DD') AS reg_date_title,
|
||||
SRM.REQUEST_MNG_NO AS request_mng_no,
|
||||
SRM.PURCHASE_TYPE AS purchase_type,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = SRM.PURCHASE_TYPE LIMIT 1), ''
|
||||
) AS purchase_type_name,
|
||||
COALESCE(PM.CATEGORY_CD, SRM.ORDER_TYPE) AS order_type,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = COALESCE(PM.CATEGORY_CD, SRM.ORDER_TYPE) LIMIT 1), ''
|
||||
) AS order_type_name,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CTM.PRODUCT LIMIT 1),
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = SRM.PRODUCT_NAME LIMIT 1),
|
||||
''
|
||||
) AS product_name_title,
|
||||
PM.PROJECT_NO AS project_number,
|
||||
CM.CLIENT_NM AS vendor_name,
|
||||
(SELECT QRD.PART_NO FROM QUOTATION_REQUEST_DETAIL QRD
|
||||
WHERE QRD.QUOTATION_REQUEST_MASTER_OBJID = QRM.OBJID
|
||||
ORDER BY QRD.OBJID LIMIT 1) AS part_no,
|
||||
(SELECT QRD.PART_NAME FROM QUOTATION_REQUEST_DETAIL QRD
|
||||
WHERE QRD.QUOTATION_REQUEST_MASTER_OBJID = QRM.OBJID
|
||||
ORDER BY QRD.OBJID LIMIT 1) AS part_name,
|
||||
(SELECT COUNT(*)::int FROM QUOTATION_REQUEST_DETAIL QRD
|
||||
WHERE QRD.QUOTATION_REQUEST_MASTER_OBJID = QRM.OBJID) AS detail_count,
|
||||
(SELECT COUNT(*)::int FROM ATTACH_FILE_INFO
|
||||
WHERE TARGET_OBJID = QRM.OBJID
|
||||
AND DOC_TYPE = 'QUOTATION_RECEIVED'
|
||||
AND COALESCE(STATUS, 'Active') = 'Active') AS attach_file_cnt
|
||||
FROM QUOTATION_REQUEST_MASTER QRM
|
||||
LEFT JOIN SALES_REQUEST_MASTER SRM ON QRM.SALES_REQUEST_MASTER_OBJID = SRM.OBJID
|
||||
LEFT JOIN PROJECT_MGMT PM ON PM.OBJID = SRM.PROJECT_NO
|
||||
LEFT JOIN CONTRACT_MGMT CTM ON CTM.OBJID = PM.CONTRACT_OBJID
|
||||
LEFT JOIN CLIENT_MNG CM ON QRM.VENDOR_OBJID = CM.OBJID
|
||||
${whereSql}
|
||||
ORDER BY QRM.REG_DATE DESC
|
||||
LIMIT ${addParam(limit)} OFFSET ${addParam(offset)}
|
||||
`;
|
||||
const countSql = `
|
||||
SELECT COUNT(*)::int AS cnt
|
||||
FROM QUOTATION_REQUEST_MASTER QRM
|
||||
LEFT JOIN SALES_REQUEST_MASTER SRM ON QRM.SALES_REQUEST_MASTER_OBJID = SRM.OBJID
|
||||
LEFT JOIN PROJECT_MGMT PM ON PM.OBJID = SRM.PROJECT_NO
|
||||
LEFT JOIN CONTRACT_MGMT CTM ON CTM.OBJID = PM.CONTRACT_OBJID
|
||||
LEFT JOIN CLIENT_MNG CM ON QRM.VENDOR_OBJID = CM.OBJID
|
||||
${whereSql}
|
||||
`;
|
||||
try {
|
||||
const [d, c] = await Promise.all([
|
||||
pool.query(dataSql, params),
|
||||
pool.query(countSql, params.slice(0, params.length - 2)),
|
||||
]);
|
||||
return { rows: d.rows, totalCount: c.rows[0]?.cnt ?? 0, page, pageSize };
|
||||
} catch (e: any) {
|
||||
logger.error("listQuotationRequest 실패", { error: e.message });
|
||||
return { rows: [], totalCount: 0, page, pageSize };
|
||||
}
|
||||
}
|
||||
|
||||
// ─── 3) 품의서관리 (wace salesMng.xml proposalMngList) ──
|
||||
@@ -388,6 +494,24 @@ export async function listProjectStatus(filter: PurchaseListFilter): Promise<Lis
|
||||
|
||||
// ─── 옵션 — 공급업체 / 작성자 (구매메뉴 공용) ──────────────────
|
||||
|
||||
// 견적요청서 / 발주서 vendor — wace 매퍼는 client_mng 와 매칭 (supply_mng 아님)
|
||||
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', '활성')
|
||||
AND CLIENT_NM IS NOT NULL AND CLIENT_NM <> ''
|
||||
ORDER BY CLIENT_NM
|
||||
LIMIT 2000`,
|
||||
);
|
||||
return r.rows;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function listSupplierOptions(): Promise<{ code: string; label: string }[]> {
|
||||
const pool = getPool();
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
-- ============================================================
|
||||
-- 견적요청서 운영 sample 데이터 → RPS 이관
|
||||
-- 운영: 211.115.91.141:11133/waceplm
|
||||
-- quotation_request_master 4건 / quotation_request_detail 4건
|
||||
-- 대상: 211.115.91.141:11134/vexplor_rps
|
||||
--
|
||||
-- 함정:
|
||||
-- 1) objid / sales_request_master_objid / project_mgmt_objid : numeric → varchar
|
||||
-- 2) detail.part_objid : numeric → bigint (RPS part_mng.objid bigint 호환)
|
||||
-- 3) FK 미매칭 sales_request_part_objid 는 NULL 처리
|
||||
--
|
||||
-- 멱등성: ON CONFLICT DO NOTHING.
|
||||
-- ============================================================
|
||||
|
||||
-- ── master ────────────────────────────────────────────────────
|
||||
INSERT INTO quotation_request_master
|
||||
(objid, quotation_request_no, sales_request_master_objid, project_mgmt_objid,
|
||||
vendor_objid, vendor_type, status, mail_send_date, mail_send_yn, due_date,
|
||||
remark, writer, reg_date, edit_date)
|
||||
VALUES
|
||||
('-1554146727','Q20260401-115','-722096187','-1752090174','0000000007','SUPPLY','received','2026-04-03 04:36:11.666917','Y','2026-04-06',NULL,'ady1225','2026-04-01 07:11:30.812611','2026-04-01 07:16:21.513931'),
|
||||
('-1629785580','Q20260401-116','-722096187','-1752090174','0000000012','PROCESSING','create',NULL,'N','2026-04-06',NULL,'ady1225','2026-04-01 07:11:30.814099',NULL),
|
||||
('185180465','Q20260401-118','-722096187','-1752090174','0000008379','PROCESSING','create',NULL,'N','2026-04-06',NULL,'ady1225','2026-04-01 07:11:30.836506',NULL),
|
||||
('211976545','Q20260401-119','-722096187','-1752090174','0000012062','PROCESSING','create',NULL,'N','2026-04-06',NULL,'ady1225','2026-04-01 07:11:30.841764',NULL)
|
||||
ON CONFLICT (objid) DO NOTHING;
|
||||
|
||||
-- ── detail ────────────────────────────────────────────────────
|
||||
INSERT INTO quotation_request_detail
|
||||
(objid, quotation_request_master_objid, sales_request_part_objid, part_objid,
|
||||
part_no, part_name, raw_material, size, qty, unit_price, total_price,
|
||||
remark, delivery_request_date, reg_date, edit_date)
|
||||
VALUES
|
||||
('-1266428262','-1554146727','-1279349416',1868255637,'C3P50L22','Ti(GR5)','Ti(GR5)','Ø50*22',0,10000,0,NULL,'2026-04-03','2026-04-01 07:11:30.812611','2026-04-01 07:16:21.513931'),
|
||||
('-2130546975','-1629785580','1187291883',1868255516,'10024-0066','SHEET',NULL,NULL,4,0,0,NULL,NULL,'2026-04-01 07:11:30.814099',NULL),
|
||||
('-392083183','185180465','-1279349416',1868255637,'10026-0031','HOLDER',NULL,NULL,4,0,0,NULL,NULL,'2026-04-01 07:11:30.836506',NULL),
|
||||
('-563828077','211976545','-1291084031',1868257572,'30004-0098','NUT',NULL,NULL,4,0,0,NULL,NULL,'2026-04-01 07:11:30.841764',NULL)
|
||||
ON CONFLICT (objid) DO NOTHING;
|
||||
|
||||
-- FK 미매칭 sales_request_part_objid 는 NULL 처리 (현재 RPS sales_request_part 0건)
|
||||
UPDATE quotation_request_detail
|
||||
SET sales_request_part_objid = NULL
|
||||
WHERE sales_request_part_objid IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM sales_request_part WHERE objid = quotation_request_detail.sales_request_part_objid
|
||||
);
|
||||
|
||||
-- FK 미매칭 part_objid 는 NULL 처리 (RPS part_mng 와 매칭 안 되면)
|
||||
UPDATE quotation_request_detail
|
||||
SET part_objid = NULL
|
||||
WHERE part_objid IS NOT NULL
|
||||
AND NOT EXISTS (SELECT 1 FROM part_mng WHERE objid = quotation_request_detail.part_objid);
|
||||
@@ -0,0 +1,73 @@
|
||||
-- ============================================================
|
||||
-- 견적요청서 (Quotation Request) — 구매관리 단독
|
||||
-- 원본: 운영DB 211.115.91.141:11133/waceplm (quotation_request_master 4건, quotation_request_detail 4건)
|
||||
-- 추출일: 2026-05-15
|
||||
-- 적용대상: vexplor_rps (11134)
|
||||
--
|
||||
-- 운영 ↔ RPS 타입 차이 (feedback_createobjid_pattern.md):
|
||||
-- 운영: quotation_request_master.objid numeric → RPS varchar(64)
|
||||
-- 운영: sales_request_master_objid / project_mgmt_objid numeric → RPS varchar(64) (FK 호환)
|
||||
-- 운영: detail.part_objid numeric → RPS bigint (part_mng.objid bigint 호환)
|
||||
-- 운영: detail.sales_request_part_objid numeric → RPS varchar(64)
|
||||
--
|
||||
-- 비즈니스 흐름:
|
||||
-- 구매리스트(sales_request_master) → 견적요청서(quotation_request_master + detail)
|
||||
-- → 품의서 → 발주서(purchase_order_master + part) → 입고(arrival_plan + inventory_*)
|
||||
--
|
||||
-- 매퍼 본문(getQuotationRequestList): wace_plm/src/com/pms/mapper/salesMng.xml:5248-5349
|
||||
-- ============================================================
|
||||
|
||||
-- ── 1. quotation_request_master ──────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS quotation_request_master (
|
||||
objid varchar(64) NOT NULL,
|
||||
quotation_request_no varchar(50),
|
||||
sales_request_master_objid varchar(64),
|
||||
project_mgmt_objid varchar(64),
|
||||
vendor_objid varchar(64),
|
||||
vendor_type varchar(20),
|
||||
status varchar(50) DEFAULT 'create',
|
||||
mail_send_date timestamp,
|
||||
mail_send_yn varchar(1) DEFAULT 'N',
|
||||
due_date date,
|
||||
remark text,
|
||||
writer varchar(50),
|
||||
reg_date timestamp DEFAULT now(),
|
||||
edit_date timestamp,
|
||||
CONSTRAINT quotation_request_master_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_qrm_sales_request ON quotation_request_master (sales_request_master_objid);
|
||||
CREATE INDEX IF NOT EXISTS idx_qrm_project ON quotation_request_master (project_mgmt_objid);
|
||||
CREATE INDEX IF NOT EXISTS idx_qrm_vendor ON quotation_request_master (vendor_objid);
|
||||
CREATE INDEX IF NOT EXISTS idx_qrm_status ON quotation_request_master (status);
|
||||
|
||||
-- ── 2. quotation_request_detail ──────────────────────────────
|
||||
CREATE TABLE IF NOT EXISTS quotation_request_detail (
|
||||
objid varchar(64) NOT NULL,
|
||||
quotation_request_master_objid varchar(64),
|
||||
sales_request_part_objid varchar(64),
|
||||
part_objid bigint,
|
||||
part_no varchar(100),
|
||||
part_name varchar(200),
|
||||
raw_material varchar(100),
|
||||
size varchar(100),
|
||||
qty numeric DEFAULT 0,
|
||||
unit_price numeric DEFAULT 0,
|
||||
total_price numeric DEFAULT 0,
|
||||
remark text,
|
||||
delivery_request_date varchar(10),
|
||||
reg_date timestamp DEFAULT now(),
|
||||
edit_date timestamp,
|
||||
CONSTRAINT quotation_request_detail_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_qrd_master ON quotation_request_detail (quotation_request_master_objid);
|
||||
CREATE INDEX IF NOT EXISTS idx_qrd_part ON quotation_request_detail (sales_request_part_objid);
|
||||
|
||||
ALTER TABLE quotation_request_detail
|
||||
DROP CONSTRAINT IF EXISTS fk_qrd_master;
|
||||
ALTER TABLE quotation_request_detail
|
||||
ADD CONSTRAINT fk_qrd_master
|
||||
FOREIGN KEY (quotation_request_master_objid)
|
||||
REFERENCES quotation_request_master (objid)
|
||||
ON DELETE CASCADE;
|
||||
@@ -4,7 +4,6 @@
|
||||
// 검색: 년도 / 프로젝트번호 / 견적요청서No / 공급업체 / 메일발송 / 작성자 / 제품구분
|
||||
// 그리드: 13컬럼 (견적번호 / 요청번호 / 구매유형 / 프로젝트번호 / 주문유형 / 제품구분 / 품번 / 품명 / 공급업체 / 견적요청서(파일) / 메일발송 / 수신견적서 / 작성자)
|
||||
// 액션: 메일발송 / 삭제 / 조회
|
||||
// ⚠️ 백엔드 quotation_request_master 미존재 → 빈 그리드 (UI 만 제공)
|
||||
|
||||
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
@@ -66,7 +65,7 @@ export default function QuoteRequestPage() {
|
||||
try {
|
||||
const [p, s, u] = await Promise.all([
|
||||
apiClient.get(`/sales/codes/${PARENT_PRODUCT}`),
|
||||
purchaseApi.listSuppliers(),
|
||||
purchaseApi.listVendors(),
|
||||
purchaseApi.listUsers(),
|
||||
]);
|
||||
if (dead) return;
|
||||
@@ -113,12 +112,12 @@ export default function QuoteRequestPage() {
|
||||
actions={<>
|
||||
<Button size="sm" variant="outline" className="h-8 gap-1 px-2 text-xs"
|
||||
disabled={checkedIds.length === 0}
|
||||
onClick={() => toast.info("메일발송 — 운영DB quotation_request_master 신설 후 활성")}>
|
||||
onClick={() => toast.info("메일발송 기능 준비 중입니다.")}>
|
||||
<Mail className="h-3.5 w-3.5" /> 메일발송
|
||||
</Button>
|
||||
<Button size="sm" variant="destructive" className="h-8 gap-1 px-2 text-xs"
|
||||
disabled={checkedIds.length === 0}
|
||||
onClick={() => toast.info("삭제 — 운영DB quotation_request_master 신설 후 활성")}>
|
||||
onClick={() => toast.info("삭제 기능 준비 중입니다.")}>
|
||||
<Trash2 className="h-3.5 w-3.5" /> 삭제
|
||||
</Button>
|
||||
</>}
|
||||
|
||||
@@ -71,6 +71,11 @@ export const purchaseApi = {
|
||||
const r = await apiClient.get("/purchase/options/suppliers");
|
||||
return (r.data?.data ?? []) as OptionItem[];
|
||||
},
|
||||
// 견적요청서 / 발주서 vendor (wace client_mng 매칭)
|
||||
async listVendors(): Promise<OptionItem[]> {
|
||||
const r = await apiClient.get("/purchase/options/vendors");
|
||||
return (r.data?.data ?? []) as OptionItem[];
|
||||
},
|
||||
async listUsers(): Promise<OptionItem[]> {
|
||||
const r = await apiClient.get("/purchase/options/users");
|
||||
return (r.data?.data ?? []) as OptionItem[];
|
||||
|
||||
Reference in New Issue
Block a user