diff --git a/WebContent/WEB-INF/view/salesMng/purchaseRegProposalMngList.jsp b/WebContent/WEB-INF/view/salesMng/purchaseRegProposalMngList.jsp new file mode 100644 index 0000000..d351bd7 --- /dev/null +++ b/WebContent/WEB-INF/view/salesMng/purchaseRegProposalMngList.jsp @@ -0,0 +1,227 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ page import="com.pms.common.utils.*"%> +<%@ page import="java.util.*" %> +<%@include file= "/init.jsp" %> + + +<% +// DB에서 메뉴명 조회 (공통 유틸 사용) +String menuObjId = request.getParameter("menuObjId"); +String menuName = CommonUtils.getMenuName(menuObjId, "구매요청_품의서관리"); +%> + + + + +<%=Constants.SYSTEM_NAME%> + + + + +
+ +
+
+
+
+

+ <%=menuName%> +

+
+ + +
+
+ +
+ + + + + + + + + + + + + +
+ + + + + + + ~ + +
+
+ + <%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %> +
+
+
+
+ + + diff --git a/WebContent/WEB-INF/view/salesMng/purchaseRequestRegList.jsp b/WebContent/WEB-INF/view/salesMng/purchaseRequestRegList.jsp index 10fdff3..73bcfd5 100644 --- a/WebContent/WEB-INF/view/salesMng/purchaseRequestRegList.jsp +++ b/WebContent/WEB-INF/view/salesMng/purchaseRequestRegList.jsp @@ -203,28 +203,8 @@ var columns = [ fn_openSalesRequestFormPopUp(data.OBJID); } } - ,{headerHozAlign : 'center', hozAlign : 'center', title : "요청인", field :"REQUEST_USER_NAME" , widthGrow:1.1, - // 요청인: 구매요청서 작성 시에만 표시 - formatter: function(cell, formatterParams, onRendered){ - var data = cell.getData(); - var hasPurchaseRequest = fnc_checkNull(data.HAS_PURCHASE_REQUEST); - if(hasPurchaseRequest == 'Y') { - return fnc_checkNull(data.REQUEST_USER_NAME); - } - return '-'; - } - } - ,{headerHozAlign : 'center', hozAlign : 'center', title : "입고요청일", field :"DELIVERY_REQUEST_DATE" , widthGrow:1.1, - // 입고요청일: 구매요청서 작성 시에만 표시 - formatter: function(cell, formatterParams, onRendered){ - var data = cell.getData(); - var hasPurchaseRequest = fnc_checkNull(data.HAS_PURCHASE_REQUEST); - if(hasPurchaseRequest == 'Y') { - return fnc_checkNull(data.DELIVERY_REQUEST_DATE); - } - return '-'; - } - } + ,{headerHozAlign : 'center', hozAlign : 'center', title : "요청인", field :"REQUEST_USER_NAME" , widthGrow:1.1 } + ,{headerHozAlign : 'center', hozAlign : 'center', title : "입고요청일", field :"DELIVERY_REQUEST_DATE" , widthGrow:1.1 } ,{headerHozAlign : 'center', hozAlign : 'center', title : "작성일", field :"REGDATE_TITLE" , widthGrow:1.1 } ,{headerHozAlign : 'center', hozAlign : 'center', title : "상태", field :"STATUS_TITLE" , widthGrow:1.1 } ]; @@ -480,10 +460,9 @@ function fn_formPopUp(objId,sales_request_objid){ } /** - * 품의서 생성 함수 - * - 선택된 구매요청서에서 단가가 입력된 품목만 필터링 + * 품의서 생성 함수 (구매요청서 전용) + * - 선택된 구매요청서에서 단가+공급업체 입력된 품목만 필터링 * - 이미 품의서가 생성된 품목은 제외 - * - 하나의 품의서로 생성 */ function fn_createProposal() { // 1. 선택된 행 확인 @@ -510,9 +489,9 @@ function fn_createProposal() { var selectedRow = selectedRows[0]; var salesRequestObjid = fnc_checkNull(selectedRow.OBJID); - // 2. 구매요청서의 품목 중 단가가 입력되고 품의서 미생성된 품목 조회 + // 2. 구매요청서 품의서 대상 품목 조회 (전용 API) $.ajax({ - url: "/salesMng/getProposalTargetParts.do", + url: "/salesMng/getProposalTargetPartsFromPurchaseReg.do", type: "POST", data: { SALES_REQUEST_MASTER_OBJID: salesRequestObjid @@ -521,13 +500,13 @@ function fn_createProposal() { success: function(response) { if(response.resultFlag === "S") { var targetParts = response.data; - var excludedParts = response.excludedParts || []; // 공급업체 미입력 품목 + var excludedParts = response.excludedParts || []; // 3. 대상 품목 확인 if(!targetParts || targetParts.length == 0) { Swal.fire({ title: '알림', - text: '품의서를 생성할 품목이 없습니다.\n(단가와 공급업체가 모두 입력되고 품의서가 생성되지 않은 품목만 대상)', + text: '품의서를 생성할 품목이 없습니다.\n(단가+공급업체 입력, 품의서 미생성 품목만 대상)', icon: 'info' }); return; @@ -536,14 +515,14 @@ function fn_createProposal() { // 4. 품의서 생성 확인 var partCount = targetParts.length; var partListHtml = targetParts.map(function(part) { - return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME); + return '- ' + fnc_checkNull(part.PART_NO || part.part_no) + ' / ' + fnc_checkNull(part.PART_NAME || part.part_name); }).join('
'); // 공급업체 미입력으로 제외된 품목이 있는 경우 알림 추가 var excludedHtml = ''; if(excludedParts && excludedParts.length > 0) { var excludedListHtml = excludedParts.map(function(part) { - return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME); + return '- ' + fnc_checkNull(part.PART_NO || part.part_no) + ' / ' + fnc_checkNull(part.PART_NAME || part.part_name); }).join('
'); excludedHtml = '
' + @@ -569,7 +548,7 @@ function fn_createProposal() { cancelButtonText: '취소' }).then((result) => { if (result.isConfirmed) { - fn_executeCreateProposal(salesRequestObjid, targetParts); + fn_executeCreateProposal(salesRequestObjid); } }); } else { @@ -579,7 +558,7 @@ function fn_createProposal() { if(excludedParts && excludedParts.length > 0) { var excludedListHtml = excludedParts.map(function(part) { - return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME); + return '- ' + fnc_checkNull(part.PART_NO || part.part_no) + ' / ' + fnc_checkNull(part.PART_NAME || part.part_name); }).join('
'); excludedHtml = '

' + @@ -600,7 +579,7 @@ function fn_createProposal() { error: function(xhr, status, error) { Swal.fire({ title: '오류', - text: '서버 통신 중 오류가 발생했습니다.22', + text: '서버 통신 중 오류가 발생했습니다.', icon: 'error' }); } @@ -608,22 +587,21 @@ function fn_createProposal() { } /** - * 품의서 생성 실행 + * 품의서 생성 실행 (구매요청서 전용) */ -function fn_executeCreateProposal(salesRequestObjid, targetParts) { +function fn_executeCreateProposal(salesRequestObjid) { $.ajax({ - url: "/salesMng/createProposalFromPurchaseList.do", + url: "/salesMng/createProposalFromPurchaseReg.do", type: "POST", data: { - SALES_REQUEST_MASTER_OBJID: salesRequestObjid, - TARGET_PARTS: JSON.stringify(targetParts) + SALES_REQUEST_MASTER_OBJID: salesRequestObjid }, dataType: "json", success: function(response) { if(response.resultFlag === "S") { Swal.fire({ title: '생성 완료', - text: '품의서가 생성되었습니다.\n품의서 관리에서 확인하세요.', + html: response.message || '품의서가 생성되었습니다.', icon: 'success' }).then(() => { fn_search(); // 목록 새로고침 diff --git a/src/com/pms/mapper/purchaseOrder.xml b/src/com/pms/mapper/purchaseOrder.xml index b509da5..c580968 100644 --- a/src/com/pms/mapper/purchaseOrder.xml +++ b/src/com/pms/mapper/purchaseOrder.xml @@ -879,10 +879,15 @@ SELECT SRP.OBJID, SRP.PART_OBJID, - SRP.QTY, - COALESCE(SRP.PO_QTY, SRP.QTY::NUMERIC, 0) AS ORDER_QTY, -- 발주수량 (PO_QTY 우선, 없으면 QTY) - SRP.UNIT_PRICE AS PARTNER_PRICE, - SRP.TOTAL_PRICE, + COALESCE(NULLIF(SRP.QTY::VARCHAR, ''), '0') AS QTY, + -- 발주수량: PO_QTY가 있고 0보다 크면 사용, 아니면 QTY 사용 + CASE + WHEN SRP.PO_QTY IS NOT NULL AND SRP.PO_QTY::NUMERIC > 0 THEN SRP.PO_QTY::VARCHAR + WHEN SRP.QTY IS NOT NULL THEN SRP.QTY::VARCHAR + ELSE '0' + END AS ORDER_QTY, + COALESCE(SRP.UNIT_PRICE, 0) AS PARTNER_PRICE, + COALESCE(SRP.TOTAL_PRICE, 0) AS TOTAL_PRICE, SRP.VENDOR_PM AS PARTNER_OBJID, PM.PART_NO, PM.PART_NAME, @@ -3317,7 +3322,7 @@ SELECT POM.OBJID ON POM.CONTRACT_MGMT_OBJID = CM.OBJID left outer join SALES_REQUEST_MASTER as SRM on POM.SALES_REQUEST_OBJID = SRM.OBJID - and SRM.DOC_TYPE = 'PROPOSAL' + and SRM.DOC_TYPE IN ('PROPOSAL', 'PURCHASE_REG_PROPOSAL') + AND ( + SRM.DOC_TYPE = 'PROPOSAL' + OR (SRM.DOC_TYPE = 'PURCHASE_REG_PROPOSAL' AND A.ROUTE_STATUS = 'complete') + ) AND SRM.REQUEST_MNG_NO LIKE '%${SEARCH_PROPOSAL_NO}%' @@ -4138,6 +4143,130 @@ ORDER BY V.PATH2 ORDER BY SRM.REGDATE DESC + + + + SELECT + SRP.OBJID, + SRP.PART_OBJID, + PM.PART_NO, + PM.PART_NAME, + SRP.QTY, + COALESCE(SRP.UNIT_PRICE, NULLIF(SRP.PARTNER_PRICE, '')::NUMERIC, 0) AS UNIT_PRICE, + SRP.TOTAL_PRICE, + COALESCE(SRP.VENDOR_PM, SRP.PARTNER_OBJID) AS VENDOR_PM, + CASE + WHEN COALESCE(SRP.VENDOR_PM, SRP.PARTNER_OBJID) LIKE 'C_%' THEN (SELECT CLIENT_NM FROM CLIENT_MNG WHERE 'C_' || OBJID::VARCHAR = COALESCE(SRP.VENDOR_PM, SRP.PARTNER_OBJID)) + ELSE (SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE OBJID::VARCHAR = COALESCE(SRP.VENDOR_PM, SRP.PARTNER_OBJID)) + END AS VENDOR_NAME, + SRP.NET_QTY, + SRP.PO_QTY + FROM + SALES_REQUEST_PART SRP + LEFT JOIN PART_MNG PM ON SRP.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR + WHERE + SRP.SALES_REQUEST_MASTER_OBJID = #{SALES_REQUEST_MASTER_OBJID} + -- 단가가 입력되어 있고 (UNIT_PRICE 또는 PARTNER_PRICE) + AND ( + (SRP.UNIT_PRICE IS NOT NULL AND SRP.UNIT_PRICE > 0) + OR (SRP.PARTNER_PRICE IS NOT NULL AND SRP.PARTNER_PRICE != '' AND SRP.PARTNER_PRICE::NUMERIC > 0) + ) + -- 공급업체가 입력되어 있고 (VENDOR_PM 또는 PARTNER_OBJID) + AND ( + (SRP.VENDOR_PM IS NOT NULL AND SRP.VENDOR_PM != '') + OR (SRP.PARTNER_OBJID IS NOT NULL AND SRP.PARTNER_OBJID != '') + ) + -- 품의서가 생성되지 않은 품목만 + AND SRP.PROPOSAL_DATE IS NULL + ORDER BY SRP.REGDATE + + + + + + + + INSERT INTO SALES_REQUEST_MASTER ( + OBJID, + REQUEST_MNG_NO, + PROJECT_NO, + PURCHASE_TYPE, + ORDER_TYPE, + PRODUCT_NAME, + AREA_CD, + CUSTOMER_OBJID, + PAID_TYPE, + REQUEST_USER_ID, + DELIVERY_REQUEST_DATE, + STATUS, + WRITER, + REGDATE, + DOC_TYPE + ) VALUES ( + #{OBJID}, + #{REQUEST_MNG_NO}, + #{PROJECT_NO}, + #{PURCHASE_TYPE}, + #{ORDER_TYPE}, + #{PRODUCT_NAME}, + #{AREA_CD}, + #{CUSTOMER_OBJID}, + #{PAID_TYPE}, + #{REQUEST_USER_ID}, + #{DELIVERY_REQUEST_DATE}, + 'create', + #{WRITER}, + NOW(), + 'PURCHASE_REG_PROPOSAL' + ) + + + + + INSERT INTO SALES_REQUEST_PART ( + OBJID, + SALES_REQUEST_MASTER_OBJID, + PART_OBJID, + QTY, + UNIT_PRICE, + TOTAL_PRICE, + VENDOR_PM, + NET_QTY, + PO_QTY, + USE_YN, + PROPOSAL_DATE, + WRITER, + REGDATE + ) + SELECT + #{NEW_OBJID}, + #{PROPOSAL_MASTER_OBJID}, + PART_OBJID, + QTY, + CASE + WHEN UNIT_PRICE IS NOT NULL AND UNIT_PRICE > 0 THEN UNIT_PRICE + WHEN PARTNER_PRICE IS NOT NULL AND PARTNER_PRICE != '' THEN PARTNER_PRICE::NUMERIC + ELSE 0 + END AS UNIT_PRICE, + CASE + WHEN TOTAL_PRICE IS NOT NULL AND TOTAL_PRICE > 0 THEN TOTAL_PRICE + ELSE COALESCE(QTY::NUMERIC, 0) * + CASE + WHEN UNIT_PRICE IS NOT NULL AND UNIT_PRICE > 0 THEN UNIT_PRICE + WHEN PARTNER_PRICE IS NOT NULL AND PARTNER_PRICE != '' THEN PARTNER_PRICE::NUMERIC + ELSE 0 + END + END AS TOTAL_PRICE, + COALESCE(NULLIF(VENDOR_PM, ''), PARTNER_OBJID) AS VENDOR_PM, + NET_QTY, + COALESCE(QTY::NUMERIC, 0) AS PO_QTY, -- 발주수량에 QTY 값 저장 + USE_YN, + NOW() AS PROPOSAL_DATE, + #{WRITER}, + NOW() + FROM SALES_REQUEST_PART + WHERE OBJID = #{SOURCE_OBJID} + + + + + UPDATE SALES_REQUEST_PART + SET PROPOSAL_DATE = NOW() + WHERE OBJID IN + + #{objid} + + + \ No newline at end of file diff --git a/src/com/pms/salesmgmt/controller/SalesMngController.java b/src/com/pms/salesmgmt/controller/SalesMngController.java index 59fee7e..52110b0 100644 --- a/src/com/pms/salesmgmt/controller/SalesMngController.java +++ b/src/com/pms/salesmgmt/controller/SalesMngController.java @@ -1337,6 +1337,24 @@ public class SalesMngController { return paramMap; } + /** + * 구매요청_품의서 관리 - 목록 화면 + */ + @RequestMapping("/salesMng/purchaseRegProposalMngList.do") + public String purchaseRegProposalMngList(HttpServletRequest request, @RequestParam Map paramMap){ + return "/salesMng/purchaseRegProposalMngList"; + } + + /** + * 구매요청_품의서 관리 - 목록 조회 (페이징) + */ + @ResponseBody + @RequestMapping("/salesMng/purchaseRegProposalMngGridList.do") + public Map getPurchaseRegProposalMngGridList(HttpServletRequest request, @RequestParam Map paramMap){ + commonService.selectListPagingNew("salesMng.getPurchaseRegProposalMngGridList", request, paramMap); + return paramMap; + } + /** * 품의서 상세 팝업 * @param request @@ -1783,4 +1801,22 @@ public class SalesMngController { public Map sendQuotationRequestMail(HttpServletRequest request, @RequestParam Map paramMap){ return salesMngService.sendQuotationRequestMail(request, paramMap); } + + /** + * 구매요청서 품의서 대상 품목 조회 + */ + @ResponseBody + @RequestMapping("/salesMng/getProposalTargetPartsFromPurchaseReg.do") + public Map getProposalTargetPartsFromPurchaseReg(HttpServletRequest request, @RequestParam Map paramMap){ + return salesMngService.getProposalTargetPartsFromPurchaseReg(request, paramMap); + } + + /** + * 구매요청서 품의서 생성 + */ + @ResponseBody + @RequestMapping("/salesMng/createProposalFromPurchaseReg.do") + public Map createProposalFromPurchaseReg(HttpServletRequest request, @RequestParam Map paramMap){ + return salesMngService.createProposalFromPurchaseReg(request, paramMap); + } } diff --git a/src/com/pms/salesmgmt/service/SalesMngService.java b/src/com/pms/salesmgmt/service/SalesMngService.java index 8b26ec2..fe9ca0f 100644 --- a/src/com/pms/salesmgmt/service/SalesMngService.java +++ b/src/com/pms/salesmgmt/service/SalesMngService.java @@ -13,6 +13,7 @@ import java.io.FileInputStream; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -1974,6 +1975,10 @@ public class SalesMngService { List materialExcludedParts = null; // 소재 제외 (공급업체 미입력) List processingExcludedParts = null; // 가공 제외 (가공업체 미입력) + // DOC_TYPE 확인 (PURCHASE_REG는 가공 컬럼이 없음) + String docType = CommonUtils.checkNull(purchaseRequestInfo.get("DOC_TYPE")); + boolean isPurchaseReg = "PURCHASE_REG".equals(docType); + if(!mbomHeaderObjid.isEmpty()) { // M-BOM 기반 -> MBOM_DETAIL에서 조회 Map mbomParam = new HashMap(); @@ -1992,9 +1997,14 @@ public class SalesMngService { materialTargetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromManual", paramMap); materialExcludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromManual", paramMap); - // 가공 품의서 대상 - processingTargetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromManualProcessing", paramMap); - processingExcludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromManualProcessing", paramMap); + // 가공 품의서 대상 (PURCHASE_REG는 가공 컬럼이 없으므로 제외) + if(!isPurchaseReg) { + processingTargetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromManualProcessing", paramMap); + processingExcludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromManualProcessing", paramMap); + } else { + processingTargetParts = new ArrayList(); + processingExcludedParts = new ArrayList(); + } } materialTargetParts = CommonUtils.keyChangeUpperList(materialTargetParts); @@ -2138,6 +2148,11 @@ public class SalesMngService { proposalMaster.put("WRITER", userId); proposalMaster.put("PROPOSAL_TYPE", proposalType); // 소재/가공 구분 + // 원본 DOC_TYPE에 따라 품의서 DOC_TYPE 결정 + String sourceDocType = CommonUtils.checkNull(purchaseRequestInfo.get("DOC_TYPE")); + String proposalDocType = "PURCHASE_REG".equals(sourceDocType) ? "PURCHASE_REG_PROPOSAL" : "PROPOSAL"; + proposalMaster.put("DOC_TYPE", proposalDocType); + sqlSession.insert("salesMng.insertProposal", proposalMaster); // 3. 품의서용 SALES_REQUEST_PART 생성 (대상 품목 복사) @@ -2701,4 +2716,176 @@ public class SalesMngService { return resultMap; } + + /** + * 구매요청서 품의서 대상 품목 조회 + */ + public Map getProposalTargetPartsFromPurchaseReg(HttpServletRequest request, Map paramMap) { + SqlSession sqlSession = null; + Map resultMap = new HashMap(); + + try { + sqlSession = SqlMapConfig.getInstance().getSqlSession(); + + String salesRequestMasterObjid = CommonUtils.checkNull(paramMap.get("SALES_REQUEST_MASTER_OBJID")); + + Map param = new HashMap(); + param.put("SALES_REQUEST_MASTER_OBJID", salesRequestMasterObjid); + + // 대상 품목 조회 + List targetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromPurchaseReg", param); + // 제외 품목 조회 (공급업체 미입력) + List excludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromPurchaseReg", param); + + if(targetParts != null && !targetParts.isEmpty()) { + resultMap.put("resultFlag", "S"); + resultMap.put("data", targetParts); + resultMap.put("excludedParts", excludedParts); + } else { + resultMap.put("resultFlag", "F"); + resultMap.put("message", "품의서 생성 대상 품목이 없습니다.\n(단가+공급업체 입력, 품의서 미생성 품목만 대상)"); + resultMap.put("excludedParts", excludedParts); + } + } catch(Exception e) { + e.printStackTrace(); + resultMap.put("resultFlag", "F"); + resultMap.put("message", "조회 중 오류가 발생했습니다: " + e.getMessage()); + } finally { + if(sqlSession != null) sqlSession.close(); + } + + return resultMap; + } + + /** + * 구매요청서 품의서 생성 (PURCHASE_REG 전용) - 업체별로 분리 생성 + */ + public Map createProposalFromPurchaseReg(HttpServletRequest request, Map paramMap) { + SqlSession sqlSession = null; + Map resultMap = new HashMap(); + + try { + sqlSession = SqlMapConfig.getInstance().getSqlSession(false); + + HttpSession session = request.getSession(); + PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN); + String userId = CommonUtils.checkNull(person.getUserId()); + + String salesRequestMasterObjid = CommonUtils.checkNull(paramMap.get("SALES_REQUEST_MASTER_OBJID")); + + if(salesRequestMasterObjid.isEmpty()) { + resultMap.put("resultFlag", "F"); + resultMap.put("message", "구매요청서 정보가 없습니다."); + return resultMap; + } + + // 1. 구매요청서 마스터 정보 조회 + Map masterParam = new HashMap(); + masterParam.put("SALES_REQUEST_MASTER_OBJID", salesRequestMasterObjid); + Map purchaseRequestInfo = (Map)sqlSession.selectOne("salesMng.getSalesRequestMasterInfo", masterParam); + purchaseRequestInfo = CommonUtils.toUpperCaseMapKey(purchaseRequestInfo); + + // 2. 대상 품목 조회 + List targetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromPurchaseReg", masterParam); + + if(targetParts == null || targetParts.isEmpty()) { + resultMap.put("resultFlag", "F"); + resultMap.put("message", "품의서 생성 대상 품목이 없습니다."); + return resultMap; + } + + // 3. 업체별로 품목 그룹화 + Map> partsByVendor = new LinkedHashMap>(); + for(Map part : targetParts) { + String vendorPm = CommonUtils.checkNull(part.get("VENDOR_PM")); + if(vendorPm.isEmpty()) { + vendorPm = CommonUtils.checkNull(part.get("vendor_pm")); + } + + if(!partsByVendor.containsKey(vendorPm)) { + partsByVendor.put(vendorPm, new ArrayList()); + } + partsByVendor.get(vendorPm).add(part); + } + + // 4. 업체별로 품의서 생성 + List createdProposalNos = new ArrayList(); + List allSourceObjids = new ArrayList(); + + for(String vendorPm : partsByVendor.keySet()) { + List vendorParts = partsByVendor.get(vendorPm); + + // 품의서 번호 생성 + String proposalNo = (String)sqlSession.selectOne("salesMng.getNextProposalNo"); + createdProposalNos.add(proposalNo); + + // 품의서 마스터 생성 + Map proposalMaster = new HashMap(); + String proposalMasterObjid = CommonUtils.createObjId(); + proposalMaster.put("OBJID", proposalMasterObjid); + proposalMaster.put("REQUEST_MNG_NO", proposalNo); + proposalMaster.put("PROJECT_NO", purchaseRequestInfo.get("PROJECT_NO")); + proposalMaster.put("PURCHASE_TYPE", purchaseRequestInfo.get("PURCHASE_TYPE")); + proposalMaster.put("ORDER_TYPE", purchaseRequestInfo.get("ORDER_TYPE")); + proposalMaster.put("PRODUCT_NAME", purchaseRequestInfo.get("PRODUCT_NAME")); + proposalMaster.put("AREA_CD", purchaseRequestInfo.get("AREA_CD")); + proposalMaster.put("CUSTOMER_OBJID", purchaseRequestInfo.get("CUSTOMER_OBJID")); + proposalMaster.put("PAID_TYPE", purchaseRequestInfo.get("PAID_TYPE")); + proposalMaster.put("DELIVERY_REQUEST_DATE", purchaseRequestInfo.get("DELIVERY_REQUEST_DATE")); + proposalMaster.put("REQUEST_USER_ID", userId); + proposalMaster.put("WRITER", userId); + + sqlSession.insert("salesMng.insertProposalFromPurchaseReg", proposalMaster); + + // 해당 업체의 품목 생성 + for(Map part : vendorParts) { + String sourceObjid = CommonUtils.checkNull(part.get("OBJID")); + if(sourceObjid.isEmpty()) { + sourceObjid = CommonUtils.checkNull(part.get("objid")); + } + allSourceObjids.add(sourceObjid); + + Map partParam = new HashMap(); + partParam.put("NEW_OBJID", CommonUtils.createObjId()); + partParam.put("PROPOSAL_MASTER_OBJID", proposalMasterObjid); + partParam.put("SOURCE_OBJID", sourceObjid); + partParam.put("WRITER", userId); + + sqlSession.insert("salesMng.insertProposalPartFromPurchaseReg", partParam); + } + } + + // 5. 원본 품목 PROPOSAL_DATE 업데이트 + if(!allSourceObjids.isEmpty()) { + Map updateParam = new HashMap(); + updateParam.put("PART_OBJIDS", allSourceObjids); + sqlSession.update("salesMng.updateProposalDateForPurchaseRegParts", updateParam); + } + + sqlSession.commit(); + + // 결과 메시지 생성 + String message = "품의서가 " + createdProposalNos.size() + "건 생성되었습니다.\n"; + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < createdProposalNos.size(); i++) { + if(i > 0) sb.append(", "); + sb.append(createdProposalNos.get(i)); + } + message += sb.toString(); + + resultMap.put("resultFlag", "S"); + resultMap.put("message", message); + resultMap.put("proposalNos", createdProposalNos); + + } catch(Exception e) { + if(sqlSession != null) sqlSession.rollback(); + e.printStackTrace(); + resultMap.put("resultFlag", "F"); + resultMap.put("message", "품의서 생성 중 오류가 발생했습니다: " + e.getMessage()); + } finally { + if(sqlSession != null) sqlSession.close(); + } + + return resultMap; + } } diff --git a/src/com/pms/service/PurchaseOrderService.java b/src/com/pms/service/PurchaseOrderService.java index 9b79488..056b096 100644 --- a/src/com/pms/service/PurchaseOrderService.java +++ b/src/com/pms/service/PurchaseOrderService.java @@ -1839,8 +1839,9 @@ public class PurchaseOrderService { String docType = CommonUtils.checkNull((String) salesRequestInfo.get("doc_type")); System.out.println("docType: " + docType); - // 품의서(PROPOSAL)인 경우 VENDOR_PM 사용, 구매요청서는 PARTNER_OBJID 사용 - String queryId = "PROPOSAL".equals(docType) + // 품의서(PROPOSAL, PURCHASE_REG_PROPOSAL)인 경우 VENDOR_PM 사용, 구매요청서는 PARTNER_OBJID 사용 + boolean isProposal = "PROPOSAL".equals(docType) || "PURCHASE_REG_PROPOSAL".equals(docType); + String queryId = isProposal ? "purchaseOrder.getVendorListByProposalObjid" : "purchaseOrder.grtPartnerObjidBySalesRequestObjid"; System.out.println("queryId: " + queryId); @@ -1881,7 +1882,7 @@ public class PurchaseOrderService { sqlSession.update("purchaseOrder.mergePurchaseOrderMasterBySalesRequest", masterParam); // 해당 공급업체의 품목 조회 - String partQueryId = "PROPOSAL".equals(docType) + String partQueryId = isProposal ? "purchaseOrder.getProposalPartsByVendor" : "purchaseOrder.getSalesRequestPartsByVendor"; @@ -1898,16 +1899,28 @@ public class PurchaseOrderService { partParam.put("PURCHASE_ORDER_MASTER_OBJID", purchaseOrderMasterObjid); partParam.put("PART_OBJID", CommonUtils.checkNull((String) partMap.get("part_objid"))); - // 수량 처리 - String qtyStr = CommonUtils.checkNull(partMap.get("qty"), "0"); - String orderQtyStr = CommonUtils.checkNull(partMap.get("order_qty"), "0"); + // 수량 처리 (Object 타입 대응) + Object qtyObj = partMap.get("qty"); + Object orderQtyObj = partMap.get("order_qty"); + String qtyStr = (qtyObj != null) ? String.valueOf(qtyObj).trim() : "0"; + if("".equals(qtyStr)) qtyStr = "0"; + + String orderQtyStr = (orderQtyObj != null) ? String.valueOf(orderQtyObj).trim() : ""; + // ORDER_QTY가 없거나 빈값/0이면 QTY 사용 + if("".equals(orderQtyStr) || "0".equals(orderQtyStr)) { + orderQtyStr = qtyStr; + } partParam.put("QTY", qtyStr); partParam.put("ORDER_QTY", orderQtyStr); - // 단가 정보 - String partnerPrice = CommonUtils.checkNull(partMap.get("partner_price"), "0"); - String totalPrice = CommonUtils.checkNull(partMap.get("total_price"), "0"); + // 단가 정보 (Object 타입 대응) + Object partnerPriceObj = partMap.get("partner_price"); + Object totalPriceObj = partMap.get("total_price"); + String partnerPrice = (partnerPriceObj != null) ? String.valueOf(partnerPriceObj).trim() : "0"; + if("".equals(partnerPrice)) partnerPrice = "0"; + String totalPrice = (totalPriceObj != null) ? String.valueOf(totalPriceObj).trim() : "0"; + if("".equals(totalPrice)) totalPrice = "0"; partParam.put("PARTNER_PRICE", partnerPrice);