diff --git a/WebContent/WEB-INF/classes/com/pms/mapper/salesMng.xml b/WebContent/WEB-INF/classes/com/pms/mapper/salesMng.xml index 1287ea3..c752153 100644 --- a/WebContent/WEB-INF/classes/com/pms/mapper/salesMng.xml +++ b/WebContent/WEB-INF/classes/com/pms/mapper/salesMng.xml @@ -663,15 +663,20 @@ VALUES SRM.PROJECT_NO, PM.PROJECT_NO AS PROJECT_NUMBER, PM.PROJECT_NAME, - COALESCE( - PM.OBJID, - (SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1) - ) AS PROJECT_MGMT_OBJID, - -- M-BOM 조회용 BOM_REPORT_OBJID 추가 - COALESCE( - PM.BOM_REPORT_OBJID, - (SELECT BOM_REPORT_OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1) - ) AS BOM_REPORT_OBJID, + COALESCE( + PM.OBJID, + (SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1) + ) AS PROJECT_MGMT_OBJID, + -- M-BOM 조회용: MBOM_HEADER에서 직접 OBJID 가져오기 + (SELECT MH.OBJID FROM MBOM_HEADER MH + WHERE MH.PROJECT_OBJID = COALESCE(PM.OBJID, (SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1)) + AND MH.STATUS = 'Y' + ORDER BY MH.REGDATE DESC LIMIT 1 + ) AS MBOM_HEADER_OBJID, + COALESCE( + PM.BOM_REPORT_OBJID, + (SELECT BOM_REPORT_OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1) + ) AS BOM_REPORT_OBJID, PM.SETUP, SM.SUPPLY_NAME AS CUSTOMER_NAME, SM.OBJID::VARCHAR AS CUSTOMER_OBJID, -- 고객사 OBJID (드롭다운 선택용) @@ -2927,26 +2932,26 @@ UPDATE SET - SELECT SRP.OBJID, SRP.SALES_REQUEST_MASTER_OBJID, SRP.PART_OBJID, - COALESCE(PMG.PART_NO, '') AS PART_NO, - COALESCE(PMG.PART_NAME, '') AS PART_NAME, + COALESCE(PM.PART_NO, '') AS PART_NO, + COALESCE(PM.PART_NAME, '') AS PART_NAME, SRP.QTY, 0 AS ITEM_QTY, - -- 파일 개수 (PART_MNG.OBJID 기준으로 조회) - COALESCE((SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = PMG.OBJID AND DOC_TYPE IN ('3D_CAD') AND UPPER(STATUS) = 'ACTIVE'), 0) AS CU01_CNT, - COALESCE((SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = PMG.OBJID AND DOC_TYPE IN ('2D_DRAWING_CAD') AND UPPER(STATUS) = 'ACTIVE'), 0) AS CU02_CNT, - COALESCE((SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = PMG.OBJID AND DOC_TYPE IN ('2D_PDF_CAD') AND UPPER(STATUS) = 'ACTIVE'), 0) AS CU03_CNT, - COALESCE(PMG.MATERIAL, '') AS MATERIAL, - COALESCE(PMG.HEAT_TREATMENT_HARDNESS, '') AS HEAT_TREATMENT_HARDNESS, - COALESCE(PMG.HEAT_TREATMENT_METHOD, '') AS HEAT_TREATMENT_METHOD, - COALESCE(PMG.SURFACE_TREATMENT, '') AS SURFACE_TREATMENT, - COALESCE(PMG.MAKER, '') AS VENDOR, - COALESCE(PMG.PART_TYPE, '') AS PART_TYPE_TITLE, + -- 파일 개수 + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE PM.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('3D_CAD')) AS CU01_CNT, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE PM.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('2D_DRAWING_CAD')) AS CU02_CNT, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE PM.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('2D_PDF_CAD')) AS CU03_CNT, + COALESCE(PM.MATERIAL, '') AS MATERIAL, + COALESCE(PM.HEAT_TREATMENT_HARDNESS, '') AS HEAT_TREATMENT_HARDNESS, + COALESCE(PM.HEAT_TREATMENT_METHOD, '') AS HEAT_TREATMENT_METHOD, + COALESCE(PM.SURFACE_TREATMENT, '') AS SURFACE_TREATMENT, + COALESCE(PM.MAKER, '') AS VENDOR, + (SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = PM.PART_TYPE) AS PART_TYPE_TITLE, '' AS SUPPLY_TYPE, '' AS RAW_MATERIAL, '' AS SIZE, @@ -2958,86 +2963,314 @@ UPDATE SET '' AS PROCESSING_VENDOR, NULL AS PROCESSING_DEADLINE, NULL AS GRINDING_DEADLINE, - 'Y' AS USE_YN, - 0 AS NET_QTY, - 0 AS PO_QTY, - SRP.PARTNER_OBJID AS VENDOR_PM, - COALESCE(NULLIF(SRP.PARTNER_PRICE, '')::numeric, 0) AS UNIT_PRICE, - COALESCE( - COALESCE(NULLIF(SRP.PARTNER_PRICE, '')::numeric, 0) * COALESCE(SRP.QTY::numeric, 0), - 0 - ) AS TOTAL_PRICE, - NULL AS PROPOSAL_DATE + -- 구매 관련 컬럼 (SALES_REQUEST_PART에서 조회) + COALESCE(SRP.USE_YN, 'Y') AS USE_YN, + COALESCE(SRP.NET_QTY, 0) AS NET_QTY, + COALESCE(SRP.PO_QTY, 0) AS PO_QTY, + COALESCE(SRP.VENDOR_PM, SRP.PARTNER_OBJID) AS VENDOR_PM, + COALESCE(SRP.UNIT_PRICE, NULLIF(SRP.PARTNER_PRICE, '')::numeric, 0) AS UNIT_PRICE, + COALESCE(SRP.TOTAL_PRICE, 0) AS TOTAL_PRICE, + SRP.PROPOSAL_DATE, + 'SRP' AS DATA_SOURCE -- 데이터 소스 구분용 FROM SALES_REQUEST_PART SRP - LEFT JOIN PART_MNG PMG ON SRP.PART_OBJID = PMG.OBJID::VARCHAR AND PMG.IS_LAST = '1' + LEFT JOIN PART_MNG PM ON SRP.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR WHERE SRP.SALES_REQUEST_MASTER_OBJID = #{SALES_REQUEST_MASTER_OBJID} ORDER BY SRP.REGDATE - - +WITH RECURSIVE VIEW_BOM( + MBOM_HEADER_OBJID, + OBJID, + PARENT_OBJID, + CHILD_OBJID, + PART_OBJID, + PART_NO, + PART_NAME, + QTY, + ITEM_QTY, + QTY_TEMP, + REGDATE, + SEQ, + STATUS, + LEV, + PATH, + PATH2, + CYCLE, + UNIT, + SUPPLY_TYPE, + MAKE_OR_BUY, + RAW_MATERIAL_PART_NO, + RAW_MATERIAL_SPEC, + RAW_MATERIAL, + RAW_MATERIAL_SIZE, + PROCESSING_VENDOR, + PROCESSING_DEADLINE, + GRINDING_DEADLINE, + REQUIRED_QTY, + ORDER_QTY, + PRODUCTION_QTY, + STOCK_QTY, + SHORTAGE_QTY, + VENDOR, + UNIT_PRICE, + TOTAL_PRICE, + CURRENCY, + LEAD_TIME, + MIN_ORDER_QTY, + WRITER, + EDITER, + EDIT_DATE, + REMARK, + USE_YN, + NET_QTY, + PO_QTY, + PROPOSAL_DATE +) AS ( + SELECT + A.MBOM_HEADER_OBJID, + A.OBJID, + A.PARENT_OBJID, + A.CHILD_OBJID, + A.PART_OBJID, + A.PART_NO, + A.PART_NAME, + A.QTY, + A.QTY, + A.QTY, + A.REGDATE, + A.SEQ, + A.STATUS, + 1, + ARRAY [A.CHILD_OBJID::TEXT], + ARRAY [A.SEQ::TEXT], + FALSE, + A.UNIT, + A.SUPPLY_TYPE, + A.MAKE_OR_BUY, + A.RAW_MATERIAL_PART_NO, + A.RAW_MATERIAL_SPEC, + A.RAW_MATERIAL, + A.RAW_MATERIAL_SIZE, + A.PROCESSING_VENDOR, + A.PROCESSING_DEADLINE, + A.GRINDING_DEADLINE, + A.REQUIRED_QTY, + A.ORDER_QTY, + A.PRODUCTION_QTY, + A.STOCK_QTY, + A.SHORTAGE_QTY, + A.VENDOR, + A.UNIT_PRICE, + A.TOTAL_PRICE, + A.CURRENCY, + A.LEAD_TIME, + A.MIN_ORDER_QTY, + A.WRITER, + A.EDITER, + A.EDIT_DATE, + A.REMARK, + COALESCE(A.USE_YN, 'Y'), + COALESCE(A.NET_QTY, 0), + COALESCE(A.PO_QTY, 0), + A.PROPOSAL_DATE + FROM + MBOM_DETAIL A + INNER JOIN MBOM_HEADER MH ON MH.OBJID = A.MBOM_HEADER_OBJID + WHERE 1=1 + AND (A.PARENT_OBJID IS NULL OR A.PARENT_OBJID = '') + AND ( + MH.PROJECT_OBJID::VARCHAR = #{PROJECT_MGMT_OBJID} + OR MH.OBJID::VARCHAR = #{PROJECT_MGMT_OBJID} + ) + + + UNION ALL + + SELECT + B.MBOM_HEADER_OBJID, + B.OBJID, + B.PARENT_OBJID, + B.CHILD_OBJID, + B.PART_OBJID, + B.PART_NO, + B.PART_NAME, + B.QTY, + B.QTY, + B.QTY, + B.REGDATE, + B.SEQ, + B.STATUS, + LEV + 1, + PATH||B.CHILD_OBJID::TEXT, + PATH2||B.SEQ::TEXT, + B.PARENT_OBJID = ANY(PATH), + B.UNIT, + B.SUPPLY_TYPE, + B.MAKE_OR_BUY, + B.RAW_MATERIAL_PART_NO, + B.RAW_MATERIAL_SPEC, + B.RAW_MATERIAL, + B.RAW_MATERIAL_SIZE, + B.PROCESSING_VENDOR, + B.PROCESSING_DEADLINE, + B.GRINDING_DEADLINE, + B.REQUIRED_QTY, + B.ORDER_QTY, + B.PRODUCTION_QTY, + B.STOCK_QTY, + B.SHORTAGE_QTY, + B.VENDOR, + B.UNIT_PRICE, + B.TOTAL_PRICE, + B.CURRENCY, + B.LEAD_TIME, + B.MIN_ORDER_QTY, + B.WRITER, + B.EDITER, + B.EDIT_DATE, + B.REMARK, + COALESCE(B.USE_YN, 'Y'), + COALESCE(B.NET_QTY, 0), + COALESCE(B.PO_QTY, 0), + B.PROPOSAL_DATE + FROM + MBOM_DETAIL B + JOIN + VIEW_BOM + ON B.PARENT_OBJID = VIEW_BOM.CHILD_OBJID + AND VIEW_BOM.MBOM_HEADER_OBJID = B.MBOM_HEADER_OBJID + +) +SELECT + V.MBOM_HEADER_OBJID AS BOM_REPORT_OBJID, + V.OBJID, + V.PARENT_OBJID, + V.CHILD_OBJID, + V.PART_OBJID, + V.PART_OBJID AS LAST_PART_OBJID, + V.PART_OBJID AS BOM_LAST_PART_OBJID, + V.PART_NO, + V.PART_NAME, + V.QTY, + V.ITEM_QTY, + V.QTY_TEMP, + V.LEV AS LEVEL, + (SELECT COUNT(*) FROM MBOM_DETAIL WHERE PARENT_OBJID = V.CHILD_OBJID) AS SUB_PART_CNT, + V.SEQ, + V.STATUS, + -- M-BOM 전용 필드 + V.UNIT, + V.SUPPLY_TYPE, + V.MAKE_OR_BUY, + V.RAW_MATERIAL_PART_NO AS RAW_MATERIAL_NO, + V.RAW_MATERIAL_SPEC, + V.RAW_MATERIAL, + V.RAW_MATERIAL_SIZE AS SIZE, + V.PROCESSING_VENDOR, + V.PROCESSING_DEADLINE, + V.GRINDING_DEADLINE, + V.REQUIRED_QTY, + V.ORDER_QTY, + V.PRODUCTION_QTY, + V.STOCK_QTY, + V.SHORTAGE_QTY, + V.VENDOR AS VENDOR_PM, + V.UNIT_PRICE, + V.TOTAL_PRICE, + V.CURRENCY, + V.LEAD_TIME, + V.MIN_ORDER_QTY, + V.WRITER, + TO_CHAR(V.REGDATE, 'YYYY-MM-DD HH24:MI:SS') AS REGDATE, + V.EDITER, + CASE WHEN V.EDIT_DATE IS NOT NULL THEN TO_CHAR(V.EDIT_DATE, 'YYYY-MM-DD HH24:MI:SS') ELSE NULL END AS EDIT_DATE, + V.REMARK, + -- E-BOM 호환 필드 + NULL AS PARENT_PART_NO, + NULL AS CONTRACT_OBJID, + CASE WHEN V.LEV = 1 THEN V.OBJID ELSE NULL END AS ROOT_OBJID, + CASE WHEN V.LEV = 1 THEN V.OBJID ELSE NULL END AS SUB_ROOT_OBJID, + 1 AS LEAF, + -- PART_MNG 테이블에서 추가 정보 (LEFT JOIN으로 PART_MNG에 없는 품번도 표시) + P.SPEC, + COALESCE(P.MATERIAL, V.RAW_MATERIAL) AS MATERIAL, + P.WEIGHT, + P.PART_TYPE, + P.REVISION, + COALESCE(P.MAKER, V.VENDOR) AS VENDOR, + P.THICKNESS, + P.WIDTH, + P.HEIGHT, + P.OUT_DIAMETER, + P.IN_DIAMETER, + P.LENGTH, + P.SOURCING_CODE, + COALESCE(P.HEAT_TREATMENT_HARDNESS, '') AS HEAT_TREATMENT_HARDNESS, + COALESCE(P.HEAT_TREATMENT_METHOD, '') AS HEAT_TREATMENT_METHOD, + COALESCE(P.SURFACE_TREATMENT, '') AS SURFACE_TREATMENT, + (SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = P.UNIT) AS UNIT_TITLE, + (SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = P.PART_TYPE) AS PART_TYPE_TITLE, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE P.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('3D_CAD')) AS CU01_CNT, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE P.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('2D_DRAWING_CAD')) AS CU02_CNT, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE P.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('2D_PDF_CAD')) AS CU03_CNT, + V.LEV, + -- 구매 컬럼들 (VIEW_BOM에서 가져온 MBOM_DETAIL 값) + V.USE_YN, + V.NET_QTY, + V.PO_QTY, + V.PROPOSAL_DATE, + 'MBOM' AS DATA_SOURCE -- 데이터 소스 구분용 +FROM VIEW_BOM V +LEFT JOIN PART_MNG P ON P.OBJID::VARCHAR = V.PART_OBJID::VARCHAR +WHERE 1=1 +ORDER BY V.PATH2 + + + + + + + UPDATE MBOM_DETAIL SET + USE_YN = #{USE_YN}, + NET_QTY = COALESCE(NULLIF(TRIM(#{NET_QTY}::TEXT), '')::NUMERIC, 0), + PO_QTY = COALESCE(NULLIF(TRIM(#{PO_QTY}::TEXT), '')::NUMERIC, 0), + VENDOR = #{VENDOR_PM}, + UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0), + TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0), + PROPOSAL_DATE = CASE WHEN NULLIF(TRIM(#{PROPOSAL_DATE}::TEXT), '') IS NOT NULL THEN #{PROPOSAL_DATE}::DATE ELSE NULL END, + EDITER = #{EDITER}, + EDIT_DATE = NOW() + WHERE OBJID::VARCHAR = #{OBJID} + + + + + UPDATE SALES_REQUEST_PART SET + USE_YN = #{USE_YN}, + NET_QTY = COALESCE(NULLIF(TRIM(#{NET_QTY}::TEXT), '')::NUMERIC, 0), + PO_QTY = COALESCE(NULLIF(TRIM(#{PO_QTY}::TEXT), '')::NUMERIC, 0), + VENDOR_PM = #{VENDOR_PM}, + UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0), + TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0), + PROPOSAL_DATE = CASE WHEN NULLIF(TRIM(#{PROPOSAL_DATE}::TEXT), '') IS NOT NULL THEN #{PROPOSAL_DATE}::DATE ELSE NULL END, + WRITER = #{EDITER} + WHERE OBJID::VARCHAR = #{OBJID} + \ No newline at end of file diff --git a/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp b/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp index 1bb0e75..37ff63f 100644 --- a/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp +++ b/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp @@ -12,6 +12,11 @@ value="${not empty param.BOM_REPORT_OBJID and param.BOM_REPORT_OBJID ne 'null' ? param.BOM_REPORT_OBJID : (not empty resultMap.BOM_REPORT_OBJID ? resultMap.BOM_REPORT_OBJID : '')}" /> +<%-- MBOM_HEADER.OBJID를 직접 사용 (M-BOM 관리 화면에서 사용하는 것과 동일) --%> + @@ -83,14 +88,18 @@ var _tabulGrid; var salesRequestMasterObjid = "${param.SALES_REQUEST_MASTER_OBJID}"; var projectMgmtObjid = "${resolvedProjectId}"; var bomReportObjid = "${resolvedBomReportObjid}"; +var mbomHeaderObjid = "${resolvedMbomHeaderObjid}"; // MBOM_HEADER.OBJID (M-BOM 관리 화면에서 사용하는 ID) +var vendorList = []; // 공급업체 목록 // 디버그: resultMap 내용 확인 console.log("=== JSP resultMap 디버그 ==="); console.log("resultMap.PROJECT_MGMT_OBJID:", "${resultMap.PROJECT_MGMT_OBJID}"); console.log("resultMap.BOM_REPORT_OBJID:", "${resultMap.BOM_REPORT_OBJID}"); +console.log("resultMap.MBOM_HEADER_OBJID:", "${resultMap.MBOM_HEADER_OBJID}"); console.log("resultMap.PROJECT_NO:", "${resultMap.PROJECT_NO}"); console.log("resolvedProjectId:", projectMgmtObjid); console.log("resolvedBomReportObjid:", bomReportObjid); +console.log("resolvedMbomHeaderObjid:", mbomHeaderObjid); function logDebug(){ if(window.console && typeof window.console.log === "function"){ console.log.apply(console, arguments); @@ -103,24 +112,66 @@ function logError(){ } $(document).ready(function(){ - fn_initGrid(); - logDebug("purchaseListFormPopUp :: grid initialized"); - fn_loadInitialData(); + // 공급업체 목록 먼저 로드 + fn_loadVendorList(function(){ + fn_initGrid(); + logDebug("purchaseListFormPopUp :: grid initialized"); + fn_loadInitialData(); + }); }); +// 공급업체 목록 로드 (기준정보_협력업체관리 - ADMIN_SUPPLY_MNG) +function fn_loadVendorList(callback) { + $.ajax({ + url: "/admin/supplyMngPagingGridList.do", + method: 'post', + data: { + searchStatus: 'Y', + countPerPage: 1000 // 충분히 많이 가져오기 + }, + dataType: 'json', + success: function(data) { + console.log("공급업체 목록 응답:", data); + if(data && data.RESULTLIST) { + vendorList = {}; // 객체 형태로 변경 + vendorList[''] = '선택'; // 빈 값 + data.RESULTLIST.forEach(function(item) { + var name = item.SUPPLY_NAME || ''; + var objid = item.OBJID || ''; + if(objid && name) { + vendorList[objid] = name; + } + }); + console.log("vendorList 생성 완료:", Object.keys(vendorList).length + "개"); + } + if(callback) callback(); + }, + error: function(xhr, status, error) { + logError("공급업체 목록 로드 실패:", error); + vendorList = {'': '선택'}; // 기본값 + if(callback) callback(); + } + }); +} + function fn_loadInitialData(){ logDebug("purchaseListFormPopUp :: fn_loadInitialData start", "projectMgmtObjid=", projectMgmtObjid, + "mbomHeaderObjid=", mbomHeaderObjid, "salesRequestMasterObjid=", salesRequestMasterObjid); var hasProject = projectMgmtObjid && projectMgmtObjid !== "" && projectMgmtObjid !== "null"; + var hasMbomHeader = mbomHeaderObjid && mbomHeaderObjid !== "" && mbomHeaderObjid !== "null"; var hasMaster = salesRequestMasterObjid && salesRequestMasterObjid !== "" && salesRequestMasterObjid !== "null"; - if(hasProject){ + // M-BOM이 있는지 확인 (MBOM_HEADER_OBJID가 있으면 M-BOM 존재) + if(hasProject || hasMbomHeader){ logDebug("purchaseListFormPopUp :: loading MBOM first"); - fn_loadFromMBom(function(){ + fn_loadFromMBom(function(mbomList){ if(hasMaster){ - logDebug("purchaseListFormPopUp :: merging saved purchase data after MBOM"); - fn_loadPurchaseList(true); + // M-BOM 데이터가 있으면 merge, 없으면 SALES_REQUEST_PART만 로드 + var hasMbomData = mbomList && mbomList.length > 0; + logDebug("purchaseListFormPopUp :: MBOM data count:", mbomList ? mbomList.length : 0); + fn_loadPurchaseList(hasMbomData); // M-BOM 있으면 merge, 없으면 단독 로드 } }); } else if(hasMaster){ @@ -155,6 +206,23 @@ function fn_initGrid() { field: 'ROW_NUM', formatter: "rownum" }, + // 2-1. 구분 (M-BOM / 수동) + { + headerHozAlign: 'center', + hozAlign: 'center', + width: 70, + title: '구분', + field: 'DATA_SOURCE', + formatter: function(cell) { + var value = cell.getValue(); + if(value === 'MBOM') { + return 'M-BOM'; + } else if(value === 'SRP') { + return '수동'; + } + return value || ''; + } + }, // 3. 품번 { headerHozAlign: 'center', @@ -383,7 +451,7 @@ function fn_initGrid() { values: ['Y', 'N'] } }, - // 28. 정미수량 (편집 가능) + // 28. 정미수량 (편집 가능) - 소재소요량 × 제작수량, 소수점 올림 { headerHozAlign: 'center', hozAlign: 'right', @@ -391,6 +459,15 @@ function fn_initGrid() { title: '정미수량', field: 'NET_QTY', editor: 'number', + mutator: function(value, data) { + // 값이 이미 설정되어 있으면 그대로 사용 + if(value && value > 0) return value; + // 소재소요량 × 제작수량, 소수점 올림 + var requiredQty = parseFloat(data.REQUIRED_QTY) || 0; + var productionQty = parseFloat(data.PRODUCTION_QTY) || 0; + var calculated = requiredQty * productionQty; + return calculated > 0 ? Math.ceil(calculated) : 0; + }, formatter: function(cell) { var value = cell.getValue(); return value ? Number(value).toLocaleString() : '0'; @@ -409,15 +486,29 @@ function fn_initGrid() { return value ? Number(value).toLocaleString() : '0'; } }, - // 30. 공급업체2 + // 30. 공급업체2 (기준정보에서 선택) { headerHozAlign: 'center', hozAlign: 'left', width: 150, - title: '공급업체2', + title: '공급업체', field: 'VENDOR_PM', - editor: 'input', - editable: true + editor: 'list', + editorParams: function(cell) { + return { + values: vendorList, + autocomplete: true, + listOnEmpty: true, + freetext: true, + allowEmpty: true + }; + }, + formatter: function(cell) { + var value = cell.getValue(); + if(!value) return ''; + // vendorList에서 해당 값의 이름 찾기 + return vendorList[value] || value; + } }, // 31. 단가 { @@ -520,11 +611,17 @@ function fn_loadFromMBom(callback) { console.log("=== fn_loadFromMBom 호출 ==="); console.log("PROJECT_MGMT_OBJID:", projectMgmtObjid); console.log("BOM_REPORT_OBJID:", bomReportObjid); + console.log("MBOM_HEADER_OBJID:", mbomHeaderObjid); + + // MBOM_HEADER_OBJID가 있으면 우선 사용 (M-BOM 관리 화면과 동일한 방식) + var mbomObjIdToUse = mbomHeaderObjid || projectMgmtObjid; + console.log("사용할 MBOM OBJID:", mbomObjIdToUse); + $.ajax({ url: "/salesMng/getMBomForPurchaseList.do", method: 'post', data: { - PROJECT_MGMT_OBJID: projectMgmtObjid, + PROJECT_MGMT_OBJID: mbomObjIdToUse, bomReportObjId: bomReportObjid }, dataType: 'json', diff --git a/db/add_sales_request_part_purchase_columns.sql b/db/add_sales_request_part_purchase_columns.sql new file mode 100644 index 0000000..6d97c9d --- /dev/null +++ b/db/add_sales_request_part_purchase_columns.sql @@ -0,0 +1,39 @@ +-- SALES_REQUEST_PART 테이블에 구매관리 관련 컬럼 추가 +-- 실행 전 백업 권장 + +-- 사용여부 +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS USE_YN VARCHAR(1) DEFAULT 'Y'; +COMMENT ON COLUMN SALES_REQUEST_PART.USE_YN IS '사용여부 (Y/N)'; + +-- 정미수량 +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS NET_QTY NUMERIC DEFAULT 0; +COMMENT ON COLUMN SALES_REQUEST_PART.NET_QTY IS '정미수량'; + +-- 발주수량 +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS PO_QTY NUMERIC DEFAULT 0; +COMMENT ON COLUMN SALES_REQUEST_PART.PO_QTY IS '발주수량'; + +-- 공급업체2 (기준정보에서 선택) +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS VENDOR_PM VARCHAR(255); +COMMENT ON COLUMN SALES_REQUEST_PART.VENDOR_PM IS '공급업체2 (기준정보_협력업체관리)'; + +-- 단가 +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS UNIT_PRICE NUMERIC DEFAULT 0; +COMMENT ON COLUMN SALES_REQUEST_PART.UNIT_PRICE IS '단가'; + +-- 총단가 +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS TOTAL_PRICE NUMERIC DEFAULT 0; +COMMENT ON COLUMN SALES_REQUEST_PART.TOTAL_PRICE IS '총단가 (발주수량 * 단가)'; + +-- 품의서작성일 +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS PROPOSAL_DATE DATE; +COMMENT ON COLUMN SALES_REQUEST_PART.PROPOSAL_DATE IS '품의서작성일'; + +-- 수정자 +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS EDITER VARCHAR(50); +COMMENT ON COLUMN SALES_REQUEST_PART.EDITER IS '수정자'; + +-- 수정일 +ALTER TABLE SALES_REQUEST_PART ADD COLUMN IF NOT EXISTS EDIT_DATE TIMESTAMP; +COMMENT ON COLUMN SALES_REQUEST_PART.EDIT_DATE IS '수정일'; + diff --git a/src/com/pms/mapper/salesMng.xml b/src/com/pms/mapper/salesMng.xml index 1287ea3..c752153 100644 --- a/src/com/pms/mapper/salesMng.xml +++ b/src/com/pms/mapper/salesMng.xml @@ -663,15 +663,20 @@ VALUES SRM.PROJECT_NO, PM.PROJECT_NO AS PROJECT_NUMBER, PM.PROJECT_NAME, - COALESCE( - PM.OBJID, - (SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1) - ) AS PROJECT_MGMT_OBJID, - -- M-BOM 조회용 BOM_REPORT_OBJID 추가 - COALESCE( - PM.BOM_REPORT_OBJID, - (SELECT BOM_REPORT_OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1) - ) AS BOM_REPORT_OBJID, + COALESCE( + PM.OBJID, + (SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1) + ) AS PROJECT_MGMT_OBJID, + -- M-BOM 조회용: MBOM_HEADER에서 직접 OBJID 가져오기 + (SELECT MH.OBJID FROM MBOM_HEADER MH + WHERE MH.PROJECT_OBJID = COALESCE(PM.OBJID, (SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1)) + AND MH.STATUS = 'Y' + ORDER BY MH.REGDATE DESC LIMIT 1 + ) AS MBOM_HEADER_OBJID, + COALESCE( + PM.BOM_REPORT_OBJID, + (SELECT BOM_REPORT_OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1) + ) AS BOM_REPORT_OBJID, PM.SETUP, SM.SUPPLY_NAME AS CUSTOMER_NAME, SM.OBJID::VARCHAR AS CUSTOMER_OBJID, -- 고객사 OBJID (드롭다운 선택용) @@ -2927,26 +2932,26 @@ UPDATE SET - SELECT SRP.OBJID, SRP.SALES_REQUEST_MASTER_OBJID, SRP.PART_OBJID, - COALESCE(PMG.PART_NO, '') AS PART_NO, - COALESCE(PMG.PART_NAME, '') AS PART_NAME, + COALESCE(PM.PART_NO, '') AS PART_NO, + COALESCE(PM.PART_NAME, '') AS PART_NAME, SRP.QTY, 0 AS ITEM_QTY, - -- 파일 개수 (PART_MNG.OBJID 기준으로 조회) - COALESCE((SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = PMG.OBJID AND DOC_TYPE IN ('3D_CAD') AND UPPER(STATUS) = 'ACTIVE'), 0) AS CU01_CNT, - COALESCE((SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = PMG.OBJID AND DOC_TYPE IN ('2D_DRAWING_CAD') AND UPPER(STATUS) = 'ACTIVE'), 0) AS CU02_CNT, - COALESCE((SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = PMG.OBJID AND DOC_TYPE IN ('2D_PDF_CAD') AND UPPER(STATUS) = 'ACTIVE'), 0) AS CU03_CNT, - COALESCE(PMG.MATERIAL, '') AS MATERIAL, - COALESCE(PMG.HEAT_TREATMENT_HARDNESS, '') AS HEAT_TREATMENT_HARDNESS, - COALESCE(PMG.HEAT_TREATMENT_METHOD, '') AS HEAT_TREATMENT_METHOD, - COALESCE(PMG.SURFACE_TREATMENT, '') AS SURFACE_TREATMENT, - COALESCE(PMG.MAKER, '') AS VENDOR, - COALESCE(PMG.PART_TYPE, '') AS PART_TYPE_TITLE, + -- 파일 개수 + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE PM.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('3D_CAD')) AS CU01_CNT, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE PM.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('2D_DRAWING_CAD')) AS CU02_CNT, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE PM.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('2D_PDF_CAD')) AS CU03_CNT, + COALESCE(PM.MATERIAL, '') AS MATERIAL, + COALESCE(PM.HEAT_TREATMENT_HARDNESS, '') AS HEAT_TREATMENT_HARDNESS, + COALESCE(PM.HEAT_TREATMENT_METHOD, '') AS HEAT_TREATMENT_METHOD, + COALESCE(PM.SURFACE_TREATMENT, '') AS SURFACE_TREATMENT, + COALESCE(PM.MAKER, '') AS VENDOR, + (SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = PM.PART_TYPE) AS PART_TYPE_TITLE, '' AS SUPPLY_TYPE, '' AS RAW_MATERIAL, '' AS SIZE, @@ -2958,86 +2963,314 @@ UPDATE SET '' AS PROCESSING_VENDOR, NULL AS PROCESSING_DEADLINE, NULL AS GRINDING_DEADLINE, - 'Y' AS USE_YN, - 0 AS NET_QTY, - 0 AS PO_QTY, - SRP.PARTNER_OBJID AS VENDOR_PM, - COALESCE(NULLIF(SRP.PARTNER_PRICE, '')::numeric, 0) AS UNIT_PRICE, - COALESCE( - COALESCE(NULLIF(SRP.PARTNER_PRICE, '')::numeric, 0) * COALESCE(SRP.QTY::numeric, 0), - 0 - ) AS TOTAL_PRICE, - NULL AS PROPOSAL_DATE + -- 구매 관련 컬럼 (SALES_REQUEST_PART에서 조회) + COALESCE(SRP.USE_YN, 'Y') AS USE_YN, + COALESCE(SRP.NET_QTY, 0) AS NET_QTY, + COALESCE(SRP.PO_QTY, 0) AS PO_QTY, + COALESCE(SRP.VENDOR_PM, SRP.PARTNER_OBJID) AS VENDOR_PM, + COALESCE(SRP.UNIT_PRICE, NULLIF(SRP.PARTNER_PRICE, '')::numeric, 0) AS UNIT_PRICE, + COALESCE(SRP.TOTAL_PRICE, 0) AS TOTAL_PRICE, + SRP.PROPOSAL_DATE, + 'SRP' AS DATA_SOURCE -- 데이터 소스 구분용 FROM SALES_REQUEST_PART SRP - LEFT JOIN PART_MNG PMG ON SRP.PART_OBJID = PMG.OBJID::VARCHAR AND PMG.IS_LAST = '1' + LEFT JOIN PART_MNG PM ON SRP.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR WHERE SRP.SALES_REQUEST_MASTER_OBJID = #{SALES_REQUEST_MASTER_OBJID} ORDER BY SRP.REGDATE - - +WITH RECURSIVE VIEW_BOM( + MBOM_HEADER_OBJID, + OBJID, + PARENT_OBJID, + CHILD_OBJID, + PART_OBJID, + PART_NO, + PART_NAME, + QTY, + ITEM_QTY, + QTY_TEMP, + REGDATE, + SEQ, + STATUS, + LEV, + PATH, + PATH2, + CYCLE, + UNIT, + SUPPLY_TYPE, + MAKE_OR_BUY, + RAW_MATERIAL_PART_NO, + RAW_MATERIAL_SPEC, + RAW_MATERIAL, + RAW_MATERIAL_SIZE, + PROCESSING_VENDOR, + PROCESSING_DEADLINE, + GRINDING_DEADLINE, + REQUIRED_QTY, + ORDER_QTY, + PRODUCTION_QTY, + STOCK_QTY, + SHORTAGE_QTY, + VENDOR, + UNIT_PRICE, + TOTAL_PRICE, + CURRENCY, + LEAD_TIME, + MIN_ORDER_QTY, + WRITER, + EDITER, + EDIT_DATE, + REMARK, + USE_YN, + NET_QTY, + PO_QTY, + PROPOSAL_DATE +) AS ( + SELECT + A.MBOM_HEADER_OBJID, + A.OBJID, + A.PARENT_OBJID, + A.CHILD_OBJID, + A.PART_OBJID, + A.PART_NO, + A.PART_NAME, + A.QTY, + A.QTY, + A.QTY, + A.REGDATE, + A.SEQ, + A.STATUS, + 1, + ARRAY [A.CHILD_OBJID::TEXT], + ARRAY [A.SEQ::TEXT], + FALSE, + A.UNIT, + A.SUPPLY_TYPE, + A.MAKE_OR_BUY, + A.RAW_MATERIAL_PART_NO, + A.RAW_MATERIAL_SPEC, + A.RAW_MATERIAL, + A.RAW_MATERIAL_SIZE, + A.PROCESSING_VENDOR, + A.PROCESSING_DEADLINE, + A.GRINDING_DEADLINE, + A.REQUIRED_QTY, + A.ORDER_QTY, + A.PRODUCTION_QTY, + A.STOCK_QTY, + A.SHORTAGE_QTY, + A.VENDOR, + A.UNIT_PRICE, + A.TOTAL_PRICE, + A.CURRENCY, + A.LEAD_TIME, + A.MIN_ORDER_QTY, + A.WRITER, + A.EDITER, + A.EDIT_DATE, + A.REMARK, + COALESCE(A.USE_YN, 'Y'), + COALESCE(A.NET_QTY, 0), + COALESCE(A.PO_QTY, 0), + A.PROPOSAL_DATE + FROM + MBOM_DETAIL A + INNER JOIN MBOM_HEADER MH ON MH.OBJID = A.MBOM_HEADER_OBJID + WHERE 1=1 + AND (A.PARENT_OBJID IS NULL OR A.PARENT_OBJID = '') + AND ( + MH.PROJECT_OBJID::VARCHAR = #{PROJECT_MGMT_OBJID} + OR MH.OBJID::VARCHAR = #{PROJECT_MGMT_OBJID} + ) + + + UNION ALL + + SELECT + B.MBOM_HEADER_OBJID, + B.OBJID, + B.PARENT_OBJID, + B.CHILD_OBJID, + B.PART_OBJID, + B.PART_NO, + B.PART_NAME, + B.QTY, + B.QTY, + B.QTY, + B.REGDATE, + B.SEQ, + B.STATUS, + LEV + 1, + PATH||B.CHILD_OBJID::TEXT, + PATH2||B.SEQ::TEXT, + B.PARENT_OBJID = ANY(PATH), + B.UNIT, + B.SUPPLY_TYPE, + B.MAKE_OR_BUY, + B.RAW_MATERIAL_PART_NO, + B.RAW_MATERIAL_SPEC, + B.RAW_MATERIAL, + B.RAW_MATERIAL_SIZE, + B.PROCESSING_VENDOR, + B.PROCESSING_DEADLINE, + B.GRINDING_DEADLINE, + B.REQUIRED_QTY, + B.ORDER_QTY, + B.PRODUCTION_QTY, + B.STOCK_QTY, + B.SHORTAGE_QTY, + B.VENDOR, + B.UNIT_PRICE, + B.TOTAL_PRICE, + B.CURRENCY, + B.LEAD_TIME, + B.MIN_ORDER_QTY, + B.WRITER, + B.EDITER, + B.EDIT_DATE, + B.REMARK, + COALESCE(B.USE_YN, 'Y'), + COALESCE(B.NET_QTY, 0), + COALESCE(B.PO_QTY, 0), + B.PROPOSAL_DATE + FROM + MBOM_DETAIL B + JOIN + VIEW_BOM + ON B.PARENT_OBJID = VIEW_BOM.CHILD_OBJID + AND VIEW_BOM.MBOM_HEADER_OBJID = B.MBOM_HEADER_OBJID + +) +SELECT + V.MBOM_HEADER_OBJID AS BOM_REPORT_OBJID, + V.OBJID, + V.PARENT_OBJID, + V.CHILD_OBJID, + V.PART_OBJID, + V.PART_OBJID AS LAST_PART_OBJID, + V.PART_OBJID AS BOM_LAST_PART_OBJID, + V.PART_NO, + V.PART_NAME, + V.QTY, + V.ITEM_QTY, + V.QTY_TEMP, + V.LEV AS LEVEL, + (SELECT COUNT(*) FROM MBOM_DETAIL WHERE PARENT_OBJID = V.CHILD_OBJID) AS SUB_PART_CNT, + V.SEQ, + V.STATUS, + -- M-BOM 전용 필드 + V.UNIT, + V.SUPPLY_TYPE, + V.MAKE_OR_BUY, + V.RAW_MATERIAL_PART_NO AS RAW_MATERIAL_NO, + V.RAW_MATERIAL_SPEC, + V.RAW_MATERIAL, + V.RAW_MATERIAL_SIZE AS SIZE, + V.PROCESSING_VENDOR, + V.PROCESSING_DEADLINE, + V.GRINDING_DEADLINE, + V.REQUIRED_QTY, + V.ORDER_QTY, + V.PRODUCTION_QTY, + V.STOCK_QTY, + V.SHORTAGE_QTY, + V.VENDOR AS VENDOR_PM, + V.UNIT_PRICE, + V.TOTAL_PRICE, + V.CURRENCY, + V.LEAD_TIME, + V.MIN_ORDER_QTY, + V.WRITER, + TO_CHAR(V.REGDATE, 'YYYY-MM-DD HH24:MI:SS') AS REGDATE, + V.EDITER, + CASE WHEN V.EDIT_DATE IS NOT NULL THEN TO_CHAR(V.EDIT_DATE, 'YYYY-MM-DD HH24:MI:SS') ELSE NULL END AS EDIT_DATE, + V.REMARK, + -- E-BOM 호환 필드 + NULL AS PARENT_PART_NO, + NULL AS CONTRACT_OBJID, + CASE WHEN V.LEV = 1 THEN V.OBJID ELSE NULL END AS ROOT_OBJID, + CASE WHEN V.LEV = 1 THEN V.OBJID ELSE NULL END AS SUB_ROOT_OBJID, + 1 AS LEAF, + -- PART_MNG 테이블에서 추가 정보 (LEFT JOIN으로 PART_MNG에 없는 품번도 표시) + P.SPEC, + COALESCE(P.MATERIAL, V.RAW_MATERIAL) AS MATERIAL, + P.WEIGHT, + P.PART_TYPE, + P.REVISION, + COALESCE(P.MAKER, V.VENDOR) AS VENDOR, + P.THICKNESS, + P.WIDTH, + P.HEIGHT, + P.OUT_DIAMETER, + P.IN_DIAMETER, + P.LENGTH, + P.SOURCING_CODE, + COALESCE(P.HEAT_TREATMENT_HARDNESS, '') AS HEAT_TREATMENT_HARDNESS, + COALESCE(P.HEAT_TREATMENT_METHOD, '') AS HEAT_TREATMENT_METHOD, + COALESCE(P.SURFACE_TREATMENT, '') AS SURFACE_TREATMENT, + (SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = P.UNIT) AS UNIT_TITLE, + (SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = P.PART_TYPE) AS PART_TYPE_TITLE, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE P.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('3D_CAD')) AS CU01_CNT, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE P.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('2D_DRAWING_CAD')) AS CU02_CNT, + (SELECT COUNT(1) FROM ATTACH_FILE_INFO F WHERE P.OBJID = F.TARGET_OBJID AND F.STATUS = 'Active' AND F.DOC_TYPE IN ('2D_PDF_CAD')) AS CU03_CNT, + V.LEV, + -- 구매 컬럼들 (VIEW_BOM에서 가져온 MBOM_DETAIL 값) + V.USE_YN, + V.NET_QTY, + V.PO_QTY, + V.PROPOSAL_DATE, + 'MBOM' AS DATA_SOURCE -- 데이터 소스 구분용 +FROM VIEW_BOM V +LEFT JOIN PART_MNG P ON P.OBJID::VARCHAR = V.PART_OBJID::VARCHAR +WHERE 1=1 +ORDER BY V.PATH2 + + + + + + + UPDATE MBOM_DETAIL SET + USE_YN = #{USE_YN}, + NET_QTY = COALESCE(NULLIF(TRIM(#{NET_QTY}::TEXT), '')::NUMERIC, 0), + PO_QTY = COALESCE(NULLIF(TRIM(#{PO_QTY}::TEXT), '')::NUMERIC, 0), + VENDOR = #{VENDOR_PM}, + UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0), + TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0), + PROPOSAL_DATE = CASE WHEN NULLIF(TRIM(#{PROPOSAL_DATE}::TEXT), '') IS NOT NULL THEN #{PROPOSAL_DATE}::DATE ELSE NULL END, + EDITER = #{EDITER}, + EDIT_DATE = NOW() + WHERE OBJID::VARCHAR = #{OBJID} + + + + + UPDATE SALES_REQUEST_PART SET + USE_YN = #{USE_YN}, + NET_QTY = COALESCE(NULLIF(TRIM(#{NET_QTY}::TEXT), '')::NUMERIC, 0), + PO_QTY = COALESCE(NULLIF(TRIM(#{PO_QTY}::TEXT), '')::NUMERIC, 0), + VENDOR_PM = #{VENDOR_PM}, + UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0), + TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0), + PROPOSAL_DATE = CASE WHEN NULLIF(TRIM(#{PROPOSAL_DATE}::TEXT), '') IS NOT NULL THEN #{PROPOSAL_DATE}::DATE ELSE NULL END, + WRITER = #{EDITER} + WHERE OBJID::VARCHAR = #{OBJID} + \ No newline at end of file diff --git a/src/com/pms/salesmgmt/service/SalesMngService.java b/src/com/pms/salesmgmt/service/SalesMngService.java index 1d58c9d..2372db4 100644 --- a/src/com/pms/salesmgmt/service/SalesMngService.java +++ b/src/com/pms/salesmgmt/service/SalesMngService.java @@ -1736,15 +1736,23 @@ public class SalesMngService { try { sqlSession = SqlMapConfig.getInstance().getSqlSession(false); String salesRequestMasterObjid = CommonUtils.checkNull(paramMap.get("SALES_REQUEST_MASTER_OBJID")); - String partListJson = CommonUtils.checkNull(paramMap.get("partList")); + String purchaseListJson = CommonUtils.checkNull(paramMap.get("purchaseListData")); - // JSON 파싱 - 기존 코드 참고하여 간단하게 처리 - // partListJson이 이미 파싱된 상태일 수 있으므로 직접 처리 - List partList = new ArrayList(); - // TODO: JSON 파싱 로직 추가 필요 + System.out.println("========== savePurchaseList =========="); + System.out.println("salesRequestMasterObjid: " + salesRequestMasterObjid); + System.out.println("purchaseListJson length: " + purchaseListJson.length()); - if(partList == null || partList.isEmpty()) { - resultMap.put("result", "error"); + // JSON 파싱 + List purchaseList = new ArrayList(); + if(purchaseListJson != null && !purchaseListJson.isEmpty()) { + org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper(); + purchaseList = mapper.readValue(purchaseListJson, List.class); + } + + System.out.println("purchaseList size: " + purchaseList.size()); + + if(purchaseList == null || purchaseList.isEmpty()) { + resultMap.put("resultFlag", "F"); resultMap.put("message", "저장할 데이터가 없습니다."); return resultMap; } @@ -1754,29 +1762,36 @@ public class SalesMngService { PersonBean personBean = (PersonBean) session.getAttribute(Constants.PERSON_BEAN); String userId = personBean.getUserId(); - // 각 품목별로 구매리스트 정보 저장 - for(Map partData : partList) { - String objid = CommonUtils.checkNull(partData.get("OBJID")); + // 각 품목별로 데이터 소스에 따라 다른 테이블 업데이트 + for(Map itemData : purchaseList) { + String objid = CommonUtils.checkNull(itemData.get("OBJID")); + String dataSource = CommonUtils.checkNull(itemData.get("DATA_SOURCE")); if(objid.isEmpty()) { - objid = CommonUtils.createObjId(); + System.out.println("OBJID가 없는 항목 스킵"); + continue; } - partData.put("OBJID", objid); - partData.put("SALES_REQUEST_MASTER_OBJID", salesRequestMasterObjid); - partData.put("WRITER", userId); + itemData.put("EDITER", userId); - // SALES_REQUEST_PART 테이블에 저장 - sqlSession.insert("salesMng.mergePurchaseListInfo", partData); + if("SRP".equals(dataSource)) { + // SALES_REQUEST_PART 테이블 업데이트 (구매요청서에서 수동 추가한 품목) + System.out.println("SALES_REQUEST_PART 업데이트: " + objid); + sqlSession.update("salesMng.updateSalesRequestPartForPurchase", itemData); + } else { + // MBOM_DETAIL 테이블 업데이트 (M-BOM에서 가져온 품목) + System.out.println("MBOM_DETAIL 업데이트: " + objid); + sqlSession.update("salesMng.updateMbomDetailForPurchase", itemData); + } } - resultMap.put("result", "success"); + resultMap.put("resultFlag", "S"); resultMap.put("message", "저장되었습니다."); sqlSession.commit(); } catch(Exception e) { if(sqlSession != null) sqlSession.rollback(); - resultMap.put("result", "error"); + resultMap.put("resultFlag", "F"); resultMap.put("message", "저장 중 오류가 발생했습니다: " + e.getMessage()); e.printStackTrace(); } finally {