diff --git a/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp b/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp index 516f77f..a44404d 100644 --- a/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp +++ b/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp @@ -553,6 +553,26 @@ function fn_initGrid() { return cell.getValue() || '-'; } }, + // 숨김 컬럼: 공급업체 코드 (저장 시 필요) + { + field: 'VENDOR', + visible: false + }, + // 숨김 컬럼: 품의서 작성일 (저장 시 기존 값 유지) + { + field: 'PROPOSAL_DATE', + visible: false + }, + // 숨김 컬럼: 순수량 (저장 시 기존 값 유지) + { + field: 'NET_QTY', + visible: false + }, + // 숨김 컬럼: 발주수량 (저장 시 기존 값 유지) + { + field: 'PO_QTY', + visible: false + }, { headerHozAlign: 'center', hozAlign: 'right', @@ -870,7 +890,7 @@ function getMbomTreeData() { partNo: row.PART_NO, partName: row.PART_NAME, - // 수량 정보 (숫자로 변환) + // 수량 정보 (원본 값 유지 - null/undefined만 변환) qty: toNumber(row.QTY_TEMP || row.QTY || row.ITEM_QTY), unit: row.UNIT, @@ -884,19 +904,22 @@ function getMbomTreeData() { processingVendor: row.PROCESSING_VENDOR, processingDeadline: row.PROCESSING_DEADLINE, grindingDeadline: row.GRINDING_DEADLINE, - requiredQty: toNumber(row.REQUIRED_QTY), - orderQty: toNumber(row.ORDER_QTY), - productionQty: toNumber(row.PRODUCTION_QTY), - stockQty: toNumber(row.STOCK_QTY), - shortageQty: toNumber(row.SHORTAGE_QTY), + requiredQty: row.REQUIRED_QTY, // 원본 값 그대로 + orderQty: row.ORDER_QTY, // 원본 값 그대로 + productionQty: row.PRODUCTION_QTY, // 원본 값 그대로 + stockQty: row.STOCK_QTY, // 원본 값 그대로 + shortageQty: row.SHORTAGE_QTY, // 원본 값 그대로 // 구매 정보 - vendor: row.VENDOR_NAME, - unitPrice: toNumber(row.UNIT_PRICE), - totalPrice: toNumber(row.TOTAL_PRICE), + vendor: row.VENDOR || row.VENDOR_PM, // 공급업체 코드/OBJID (기존 값 유지) + unitPrice: row.UNIT_PRICE, // 원본 값 그대로 + totalPrice: row.TOTAL_PRICE, // 원본 값 그대로 currency: row.CURRENCY, - leadTime: toNumber(row.LEAD_TIME), - minOrderQty: toNumber(row.MIN_ORDER_QTY), + leadTime: row.LEAD_TIME, // 원본 값 그대로 + minOrderQty: row.MIN_ORDER_QTY, // 원본 값 그대로 + netQty: row.NET_QTY, // 순수량 추가 + poQty: row.PO_QTY, // 발주수량 추가 + proposalDate: row.PROPOSAL_DATE, // 품의서 작성일 (기존 값 유지) // 기타 status: row.STATUS, diff --git a/WebContent/WEB-INF/view/salesMng/salesRequestMngRegList.jsp b/WebContent/WEB-INF/view/salesMng/salesRequestMngRegList.jsp index c63307f..b3f6dd0 100644 --- a/WebContent/WEB-INF/view/salesMng/salesRequestMngRegList.jsp +++ b/WebContent/WEB-INF/view/salesMng/salesRequestMngRegList.jsp @@ -180,18 +180,24 @@ var columns = [ ,{headerHozAlign : 'center', hozAlign : 'center', title : "유/무상", field :"PAID_TYPE_NAME" , widthGrow:0.9 } ,{headerHozAlign : 'center', hozAlign : 'left', title : "품번", field :"PART_NO" , widthGrow:1.4} ,{headerHozAlign : 'center', hozAlign : 'left' , title : "품명", field :"PART_NAME" , widthGrow:1.8 } - ,{headerHozAlign : 'center', hozAlign : 'center', title : "구매요청서", field :"REQUEST_MNG_NO" , widthGrow:1.1, - formatter: function(cell, formatterParams, onRendered){ - // 구매요청서 작성 여부: PART_NO가 있으면 품목이 저장된 것 (구매요청서 작성됨) - var data = cell.getData(); - var partNo = fnc_checkNull(data.PART_NO); - var iconClass = (partNo != '' && partNo != null) ? 'file_icon' : 'file_empty_icon'; - return ''; - }, - cellClick : function(e, cell) { - fn_openSalesRequestFormPopUp(cell.getData().OBJID); - } - } + ,{headerHozAlign : 'center', hozAlign : 'center', title : "구매요청서", field :"REQUEST_MNG_NO" , widthGrow:1.1, + formatter: function(cell, formatterParams, onRendered){ + // 구매요청서 작성 여부: PART_NO가 있으면 품목이 저장된 것 (구매요청서 작성됨) + var data = cell.getData(); + var partNo = fnc_checkNull(data.PART_NO); + var iconClass = (partNo != '' && partNo != null) ? 'file_icon' : 'file_empty_icon'; + return ''; + }, + cellClick : function(e, cell) { + var data = cell.getData(); + var partNo = fnc_checkNull(data.PART_NO); + + // 구매요청서가 작성된 경우(파란색 아이콘)만 팝업 열기 + if(partNo != '' && partNo != null) { + fn_openSalesRequestFormPopUp(data.OBJID); + } + } + } ,{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 } diff --git a/src/com/pms/mapper/productionplanning.xml b/src/com/pms/mapper/productionplanning.xml index 5178f19..1de19ca 100644 --- a/src/com/pms/mapper/productionplanning.xml +++ b/src/com/pms/mapper/productionplanning.xml @@ -3766,7 +3766,11 @@ 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, + NET_QTY, PO_QTY, VENDOR, UNIT_PRICE, TOTAL_PRICE, CURRENCY, LEAD_TIME, MIN_ORDER_QTY, + + PROPOSAL_DATE, + STATUS, WRITER, REGDATE, REMARK ) VALUES ( #{objid}, #{mbomHeaderObjid}, #{parentObjid}, #{childObjid}, #{seq}, #{level}, @@ -3775,7 +3779,11 @@ #{rawMaterialPartNo}, #{rawMaterialSpec}, #{rawMaterial}, #{rawMaterialSize}, #{processingVendor}, #{processingDeadline}, #{grindingDeadline}, #{requiredQty}, #{orderQty}, #{productionQty}, #{stockQty}, #{shortageQty}, + #{netQty}, #{poQty}, #{vendor}, #{unitPrice}, #{totalPrice}, #{currency}, #{leadTime}, #{minOrderQty}, + + #{proposalDate}, + 'ACTIVE', #{sessionUserId}, NOW(), #{remark} ) @@ -3870,12 +3878,15 @@ PRODUCTION_QTY, STOCK_QTY, SHORTAGE_QTY, + NET_QTY, + PO_QTY, VENDOR, UNIT_PRICE, TOTAL_PRICE, CURRENCY, LEAD_TIME, MIN_ORDER_QTY, + PROPOSAL_DATE, STATUS, REMARK FROM diff --git a/src/com/pms/service/ProductionPlanningService.java b/src/com/pms/service/ProductionPlanningService.java index e2c44ab..80e679d 100644 --- a/src/com/pms/service/ProductionPlanningService.java +++ b/src/com/pms/service/ProductionPlanningService.java @@ -1361,52 +1361,109 @@ public class ProductionPlanningService { } } - // M-BOM 업데이트 - paramMap.put("mbomHeaderObjid", existingMbom.get("OBJID")); - sqlSession.update("productionplanning.updateMbomHeader", paramMap); - sqlSession.delete("productionplanning.deleteMbomDetail", paramMap); - - // 새 상세 데이터 삽입 - if(mbomData != null && !mbomData.isEmpty()) { - for(Map item : mbomData) { - item.put("mbomHeaderObjid", existingMbom.get("OBJID")); - item.put("sessionUserId", userId); - - // SEQ가 없으면 기존 SEQ 유지 (JSP에서 전송된 seq 사용) - // 없는 경우에만 새로 부여 - if(item.get("seq") == null || "".equals(item.get("seq"))) { - item.put("seq", 999); // 임시값 (나중에 정렬 필요) - } - - // 기존 항목인 경우 objid와 childObjid 유지 - // 새 항목인 경우에만 생성 - String objid = CommonUtils.checkNull(item.get("objid")); - String childObjid = CommonUtils.checkNull(item.get("childObjid")); - - if("".equals(objid)) { - objid = CommonUtils.createObjId(); - item.put("objid", objid); - } - - if("".equals(childObjid)) { - childObjid = objid; // 새 항목은 objid와 동일 - item.put("childObjid", childObjid); - } - - // LEVEL이 없으면 기본값 1 설정 - 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); + // 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로 수정 + List oldMbomDetails = sqlSession.selectList("productionplanning.getMbomDetailList", queryParam); + + // OBJID를 키로 하는 맵 생성 (빠른 조회) + 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()) { + existingDataMap.put(objid, detail); } } + } + + sqlSession.delete("productionplanning.deleteMbomDetail", paramMap); + + + // 새 상세 데이터 삽입 + if(mbomData != null && !mbomData.isEmpty()) { + for(Map item : mbomData) { + item.put("mbomHeaderObjid", existingMbom.get("OBJID")); + item.put("sessionUserId", userId); + + // SEQ가 없으면 기존 SEQ 유지 (JSP에서 전송된 seq 사용) + // 없는 경우에만 새로 부여 + if(item.get("seq") == null || "".equals(item.get("seq"))) { + item.put("seq", 999); // 임시값 (나중에 정렬 필요) + } + + // 기존 항목인 경우 objid와 childObjid 유지 + // 새 항목인 경우에만 생성 + String objid = CommonUtils.checkNull(item.get("objid")); + String childObjid = CommonUtils.checkNull(item.get("childObjid")); + + if("".equals(objid)) { + objid = CommonUtils.createObjId(); + item.put("objid", objid); + } + + if("".equals(childObjid)) { + childObjid = objid; // 새 항목은 objid와 동일 + item.put("childObjid", childObjid); + } + + // 기존 데이터에서 보존해야 할 값들 복원 + 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); + } + } + + // 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); + } + } + + // 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); + } + } + + // 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); + } + } + } + + // LEVEL이 없으면 기본값 1 설정 + 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); + } + } // 변경 사항이 있을 때만 이력 저장 if(!changedItems.isEmpty()) {