From 4c1967cd63cecb7a0ddad0db44d02015d959cea1 Mon Sep 17 00:00:00 2001 From: hjjeong Date: Tue, 2 Dec 2025 15:10:41 +0900 Subject: [PATCH] =?UTF-8?q?=ED=92=88=EC=9D=98=EC=84=9C=20=EC=96=91?= =?UTF-8?q?=EC=8B=9D=20=EA=B0=9C=EB=B0=9C,=20=EC=9E=85=EA=B3=A0=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EB=93=B1...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/productionplanning/mBomPopupLeft.jsp | 13 + .../deliveryMngAcceptanceList.jsp | 41 +- .../purchaseOrderFormPopup_new.jsp | 4 +- .../view/salesMng/proposalFormPopUp.jsp | 893 ++++++++++++++++++ .../WEB-INF/view/salesMng/proposalMngList.jsp | 2 +- src/com/pms/mapper/productionplanning.xml | 40 +- src/com/pms/mapper/purchaseOrder.xml | 7 +- src/com/pms/mapper/salesMng.xml | 60 +- .../controller/SalesMngController.java | 59 ++ .../service/ProductionPlanningService.java | 87 +- 10 files changed, 1133 insertions(+), 73 deletions(-) create mode 100644 WebContent/WEB-INF/view/salesMng/proposalFormPopUp.jsp diff --git a/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp b/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp index 48ee36d..8c3fea0 100644 --- a/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp +++ b/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp @@ -39,6 +39,11 @@ body { .tabulator-row.level-8 { background-color: #dce6f1 !important; } .tabulator-row.level-9 { background-color: #FFFFEB !important; } .tabulator-row.level-10 { background-color: #ffffff !important; } + +/* 편집 가능한 컬럼 헤더 스타일 */ +.editable-header { + background-color: #fff9c4 !important; +} + + + + + + + + + 등록된 품목이 없습니다. + + + + + + + +   +   +   +   +   +   +   +   +   + + + + + + + + +
+ + + + + +
참 조 문 서선택된 문서가 없습니다.
+
+ + + +
+ + + +
+ + + + + diff --git a/WebContent/WEB-INF/view/salesMng/proposalMngList.jsp b/WebContent/WEB-INF/view/salesMng/proposalMngList.jsp index aabba3c..2676618 100644 --- a/WebContent/WEB-INF/view/salesMng/proposalMngList.jsp +++ b/WebContent/WEB-INF/view/salesMng/proposalMngList.jsp @@ -200,7 +200,7 @@ function fn_search(){ // 품의서 상세 팝업 function fn_openProposalFormPopUp(objId){ var url = "/salesMng/proposalFormPopUp.do?PROPOSAL_OBJID=" + fnc_checkNull(objId); - window.open(url, "proposalFormPopUp", "width=1200,height=700,scrollbars=yes,resizable=yes"); + window.open(url, "proposalFormPopUp", "width=1200,height=900,scrollbars=yes,resizable=yes"); } function _fnc_datepick(){ diff --git a/src/com/pms/mapper/productionplanning.xml b/src/com/pms/mapper/productionplanning.xml index b826bcf..faea338 100644 --- a/src/com/pms/mapper/productionplanning.xml +++ b/src/com/pms/mapper/productionplanning.xml @@ -3833,12 +3833,50 @@ WHERE OBJID = #{mbomHeaderObjid} - + DELETE FROM MBOM_DETAIL WHERE MBOM_HEADER_OBJID = #{mbomHeaderObjid} + + + DELETE FROM MBOM_DETAIL + WHERE OBJID = #{objid} + + + + + UPDATE MBOM_DETAIL + SET + PARENT_OBJID = NULLIF(#{parentObjid}, ''), + SEQ = NULLIF(#{seq}::TEXT, '')::INTEGER, + LEVEL = NULLIF(#{level}::TEXT, '')::INTEGER, + PART_OBJID = NULLIF(#{partObjid}, ''), + PART_NO = NULLIF(#{partNo}, ''), + PART_NAME = NULLIF(#{partName}, ''), + QTY = NULLIF(#{qty}::TEXT, '')::NUMERIC, + UNIT = NULLIF(#{unit}, ''), + SUPPLY_TYPE = NULLIF(#{supplyType}, ''), + MAKE_OR_BUY = NULLIF(#{makeOrBuy}, ''), + RAW_MATERIAL_PART_NO = NULLIF(#{rawMaterialPartNo}, ''), + RAW_MATERIAL_SPEC = NULLIF(#{rawMaterialSpec}, ''), + RAW_MATERIAL = NULLIF(#{rawMaterial}, ''), + RAW_MATERIAL_SIZE = NULLIF(#{rawMaterialSize}, ''), + PROCESSING_VENDOR = NULLIF(#{processingVendor}, ''), + PROCESSING_DEADLINE = NULLIF(#{processingDeadline}, ''), + GRINDING_DEADLINE = NULLIF(#{grindingDeadline}, ''), + REQUIRED_QTY = NULLIF(#{requiredQty}::TEXT, '')::NUMERIC, + ORDER_QTY = NULLIF(#{orderQty}::TEXT, '')::NUMERIC, + PRODUCTION_QTY = NULLIF(#{productionQty}::TEXT, '')::NUMERIC, + STOCK_QTY = NULLIF(#{stockQty}::TEXT, '')::NUMERIC, + SHORTAGE_QTY = NULLIF(#{shortageQty}::TEXT, '')::NUMERIC, + EDITER = #{sessionUserId}, + EDIT_DATE = NOW(), + REMARK = NULLIF(#{remark}, '') + WHERE OBJID = #{objid} + + INSERT INTO MBOM_HISTORY ( diff --git a/src/com/pms/mapper/purchaseOrder.xml b/src/com/pms/mapper/purchaseOrder.xml index 0e9a7fa..3534bc1 100644 --- a/src/com/pms/mapper/purchaseOrder.xml +++ b/src/com/pms/mapper/purchaseOrder.xml @@ -4191,8 +4191,8 @@ SELECT POM.OBJID ,POM.MULTI_YN ,CASE WHEN POM.MULTI_MASTER_YN = 'Y' THEN '' ELSE POM.MULTI_YN END MULTI_YN_MAKED - - ,(SELECT SUM(REAL_ORDER_QTY::NUMERIC) FROM PURCHASE_ORDER_PART AS O WHERE POM.OBJID::VARCHAR = O.PURCHASE_ORDER_MASTER_OBJID) AS TOTAL_PO_QTY + ,(SELECT SUM(ORDER_QTY::NUMERIC) FROM PURCHASE_ORDER_PART AS O WHERE POM.OBJID::VARCHAR = O.PURCHASE_ORDER_MASTER_OBJID) AS TOTAL_PO_QTY + ,S1.CUR_DELIVERY_DATE ,S1.TOTAL_DELIVERY_QTY @@ -4261,7 +4261,8 @@ SELECT POM.OBJID ON POM.CONTRACT_MGMT_OBJID = CM.OBJID - WHERE POM.STATUS = 'approvalComplete' /*결재완료*/ + WHERE 1=1 + /*결재완료*/ AND (MULTI_MASTER_YN = 'Y' OR NVL(MULTI_MASTER_YN, '') != 'Y' AND NVL(MULTI_YN, '') != 'Y') diff --git a/src/com/pms/mapper/salesMng.xml b/src/com/pms/mapper/salesMng.xml index 7449abc..b2bbf9c 100644 --- a/src/com/pms/mapper/salesMng.xml +++ b/src/com/pms/mapper/salesMng.xml @@ -3828,14 +3828,72 @@ ORDER BY V.PATH2 END AS STATUS_TITLE, SRM.WRITER, (SELECT DEPT_NAME||' '||USER_NAME FROM USER_INFO WHERE USER_ID = SRM.WRITER) AS WRITER_NAME, + (SELECT DEPT_NAME FROM USER_INFO WHERE USER_ID = SRM.WRITER) AS WRITER_DEPT, SRM.REGDATE, TO_CHAR(SRM.REGDATE,'YYYY-MM-DD') AS REGDATE_TITLE, + TO_CHAR(SRM.REGDATE,'YYYY-MM-DD HH24:MI') AS REGDATE_TIME, SRM.REMARK, - SRM.DOC_TYPE + SRM.DOC_TYPE, + -- 품의서 추가 컬럼 + SRM.RECIPIENT_REF, + SRM.EXECUTOR, + SRM.EXECUTION_DATE, + TO_CHAR(SRM.EXECUTION_DATE, 'YYYY-MM-DD') AS EXECUTION_DATE_TITLE, + SRM.TITLE FROM SALES_REQUEST_MASTER SRM WHERE SRM.OBJID = #{PROPOSAL_OBJID} + + + + + + UPDATE SALES_REQUEST_MASTER SET + RECIPIENT_REF = #{RECIPIENT_REF}, + EXECUTOR = #{EXECUTOR}, + EXECUTION_DATE = CASE WHEN #{EXECUTION_DATE} IS NOT NULL AND #{EXECUTION_DATE} != '' THEN #{EXECUTION_DATE}::DATE ELSE NULL END, + TITLE = #{TITLE} + WHERE OBJID = #{PROPOSAL_OBJID} + + + + + UPDATE SALES_REQUEST_PART SET + DELIVERY_REQUEST_DATE = CASE WHEN #{DELIVERY_REQUEST_DATE} IS NOT NULL AND #{DELIVERY_REQUEST_DATE} != '' THEN #{DELIVERY_REQUEST_DATE} ELSE NULL END, + UNIT = #{UNIT}, + REMARK = #{REMARK} + WHERE OBJID = #{PART_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 9573582..4663cb3 100644 --- a/src/com/pms/salesmgmt/controller/SalesMngController.java +++ b/src/com/pms/salesmgmt/controller/SalesMngController.java @@ -1276,12 +1276,24 @@ public class SalesMngController { public String proposalFormPopUp(HttpServletRequest request, @RequestParam Map paramMap){ Map resultMap = new HashMap(); Map code_map = new HashMap(); + ArrayList approvalList = new ArrayList(); + List partList = new ArrayList(); try { String proposalObjId = CommonUtils.checkNull(paramMap.get("PROPOSAL_OBJID")); if(!"".equals(proposalObjId)){ resultMap = commonService.selectOne("salesMng.getProposalInfo", request, paramMap); + + // 결재 정보 조회 + Map approvalParam = new HashMap(); + approvalParam.put("OBJID", proposalObjId); + approvalList = approvalService.getApprovalLine(request, approvalParam); + + // 품의서 품목 리스트 조회 + Map partParam = new HashMap(); + partParam.put("PROPOSAL_OBJID", proposalObjId); + partList = commonService.selectList("salesMng.getProposalPartList", request, partParam); } else { resultMap.put("OBJID", CommonUtils.createObjId()); resultMap.put("STATUS", "create"); @@ -1293,6 +1305,8 @@ public class SalesMngController { code_map.put("order_type", commonService.bizMakeOptionList("0001822", (String)resultMap.get("ORDER_TYPE"), "common.getCodeselect")); // 제품구분 code_map.put("product_name", commonService.bizMakeOptionList("0000016", (String)resultMap.get("PRODUCT_NAME"), "common.getCodeselect")); + // 단위 코드 목록 (UNIT_CD: 단위) + code_map.put("unit_list", commonService.bizMakeOptionList("0001399", "", "common.getCodeselect")); } catch (Exception e) { e.printStackTrace(); @@ -1300,6 +1314,8 @@ public class SalesMngController { request.setAttribute("resultMap", resultMap); request.setAttribute("code_map", code_map); + request.setAttribute("approvalList", approvalList); + request.setAttribute("partList", partList); return "/salesMng/proposalFormPopUp"; } @@ -1388,4 +1404,47 @@ public class SalesMngController { public Map createProposalFromPurchaseList(HttpServletRequest request, @RequestParam Map paramMap){ return createProposal(request, paramMap); } + + /** + * 품의서 저장 (마스터 + 품목) + * @param request + * @param paramMap + * @return + */ + @ResponseBody + @RequestMapping("/salesMng/saveProposal.do") + public Map saveProposal(HttpServletRequest request, @RequestParam Map paramMap){ + Map resultMap = new HashMap(); + SqlSession sqlSession = null; + + try { + sqlSession = SqlMapConfig.getInstance().getSqlSession(false); + + // 1. 마스터 정보 저장 + sqlSession.update("salesMng.updateProposalMaster", paramMap); + + // 2. 품목 정보 저장 (JSON 배열로 전달받음) + String partListJson = CommonUtils.checkNull(paramMap.get("PART_LIST")); + if(!"".equals(partListJson)) { + List> partList = JsonUtil.JsonToList(partListJson); + for(Map part : partList) { + sqlSession.update("salesMng.updateProposalPart", part); + } + } + + sqlSession.commit(); + resultMap.put("resultFlag", "S"); + resultMap.put("message", "저장되었습니다."); + + } 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/ProductionPlanningService.java b/src/com/pms/service/ProductionPlanningService.java index 80e679d..5b19f62 100644 --- a/src/com/pms/service/ProductionPlanningService.java +++ b/src/com/pms/service/ProductionPlanningService.java @@ -1361,107 +1361,100 @@ public class ProductionPlanningService { } } - // M-BOM 업데이트 + // M-BOM 헤더 업데이트 paramMap.put("mbomHeaderObjid", existingMbom.get("OBJID")); sqlSession.update("productionplanning.updateMbomHeader", paramMap); - // 삭제 전에 기존 데이터 백업 (PROPOSAL_DATE, VENDOR, NET_QTY, PO_QTY 등 보존) + // 기존 데이터 조회 Map queryParam = new HashMap<>(); - queryParam.put("mbomHeaderObjid", existingMbom.get("OBJID")); // camelCase로 수정 + queryParam.put("mbomHeaderObjid", existingMbom.get("OBJID")); List oldMbomDetails = sqlSession.selectList("productionplanning.getMbomDetailList", queryParam); - // OBJID를 키로 하는 맵 생성 (빠른 조회) + // 기존 OBJID Set 생성 + java.util.Set existingObjids = new java.util.HashSet<>(); Map existingDataMap = new HashMap<>(); if(oldMbomDetails != null) { for(Map detail : oldMbomDetails) { detail = CommonUtils.toUpperCaseMapKey(detail); String objid = CommonUtils.checkNull(detail.get("OBJID")); if(!objid.isEmpty()) { + existingObjids.add(objid); existingDataMap.put(objid, detail); } } } - sqlSession.delete("productionplanning.deleteMbomDetail", paramMap); + // JSP에서 넘어온 OBJID Set 생성 + java.util.Set newObjids = new java.util.HashSet<>(); - - // 새 상세 데이터 삽입 + // UPSERT 처리 if(mbomData != null && !mbomData.isEmpty()) { for(Map item : mbomData) { item.put("mbomHeaderObjid", existingMbom.get("OBJID")); item.put("sessionUserId", userId); - // SEQ가 없으면 기존 SEQ 유지 (JSP에서 전송된 seq 사용) - // 없는 경우에만 새로 부여 + // SEQ 기본값 if(item.get("seq") == null || "".equals(item.get("seq"))) { - item.put("seq", 999); // 임시값 (나중에 정렬 필요) + item.put("seq", 999); } - // 기존 항목인 경우 objid와 childObjid 유지 - // 새 항목인 경우에만 생성 String objid = CommonUtils.checkNull(item.get("objid")); String childObjid = CommonUtils.checkNull(item.get("childObjid")); + // 신규 항목: objid가 비어있을 때만 if("".equals(objid)) { objid = CommonUtils.createObjId(); item.put("objid", objid); } if("".equals(childObjid)) { - childObjid = objid; // 새 항목은 objid와 동일 + childObjid = objid; item.put("childObjid", childObjid); } - // 기존 데이터에서 보존해야 할 값들 복원 + newObjids.add(objid); + + // 기존 데이터에서 보존할 값 복원 Map existingData = existingDataMap.get(objid); if(existingData != null) { - // PROPOSAL_DATE가 JSP에서 안 넘어왔으면 기존 값 사용 if(item.get("proposalDate") == null || "".equals(item.get("proposalDate"))) { - Object proposalDate = existingData.get("PROPOSAL_DATE"); - if(proposalDate != null) { - item.put("proposalDate", proposalDate); - System.out.println("PROPOSAL_DATE 복원: " + objid + " -> " + proposalDate); - } + Object val = existingData.get("PROPOSAL_DATE"); + if(val != null) item.put("proposalDate", val); } - - // VENDOR가 JSP에서 안 넘어왔으면 기존 값 사용 if(item.get("vendor") == null || "".equals(item.get("vendor"))) { - Object vendor = existingData.get("VENDOR"); - if(vendor != null) { - item.put("vendor", vendor); - System.out.println("VENDOR 복원: " + objid + " -> " + vendor); - } + Object val = existingData.get("VENDOR"); + if(val != null) item.put("vendor", val); } - - // NET_QTY가 JSP에서 안 넘어왔으면 기존 값 사용 if(item.get("netQty") == null || "".equals(item.get("netQty"))) { - Object netQty = existingData.get("NET_QTY"); - if(netQty != null) { - item.put("netQty", netQty); - } + Object val = existingData.get("NET_QTY"); + if(val != null) item.put("netQty", val); } - - // PO_QTY가 JSP에서 안 넘어왔으면 기존 값 사용 if(item.get("poQty") == null || "".equals(item.get("poQty"))) { - Object poQty = existingData.get("PO_QTY"); - if(poQty != null) { - item.put("poQty", poQty); - } + Object val = existingData.get("PO_QTY"); + if(val != null) item.put("poQty", val); } } - // LEVEL이 없으면 기본값 1 설정 + // LEVEL 기본값 if(item.get("level") == null || "".equals(item.get("level"))) { item.put("level", 1); } - System.out.println("UPDATE M-BOM DETAIL: seq=" + item.get("seq") + - ", level=" + item.get("level") + - ", partNo=" + item.get("partNo") + - ", parentObjid=" + item.get("parentObjid") + - ", childObjid=" + childObjid); - - sqlSession.insert("productionplanning.insertMbomDetail", item); + // UPSERT: 기존 항목이면 UPDATE, 신규면 INSERT + if(existingObjids.contains(objid)) { + sqlSession.update("productionplanning.updateMbomDetail", item); + } else { + sqlSession.insert("productionplanning.insertMbomDetail", item); + } + } + } + + // DELETE: DB에 있는데 JSP에 없는 항목 삭제 + for(String existingObjid : existingObjids) { + if(!newObjids.contains(existingObjid)) { + Map deleteParam = new HashMap<>(); + deleteParam.put("objid", existingObjid); + sqlSession.delete("productionplanning.deleteMbomDetailByObjid", deleteParam); } }