From 6f07267e1817cc8db356c88a1bb856fdea81f36b Mon Sep 17 00:00:00 2001 From: hjjeong Date: Fri, 27 Feb 2026 12:19:40 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A3=BC=EB=AC=B8=EC=84=9C=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=20=EC=88=98=EC=A3=BC=EC=B7=A8=EC=86=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80(=EB=B6=80=EB=B6=84=20=EC=B7=A8=EC=86=8C?= =?UTF-8?q?=EB=A7=8C=20=EA=B0=80=EB=8A=A5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/contractMgmt/orderMgmtList.jsp | 166 +++++++++++++++++- .../controller/ContractMgmtController.java | 19 ++ src/com/pms/salesmgmt/mapper/contractMgmt.xml | 26 ++- .../service/ContractMgmtService.java | 85 +++++++++ 4 files changed, 289 insertions(+), 7 deletions(-) diff --git a/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp b/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp index 1be8465..64366ec 100644 --- a/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp @@ -151,6 +151,28 @@ $(document).ready(function(){ document.form1.submit(); }); + // 수주취소 + $("#btnOrderCancel").click(function(){ + var selectedData = _tabulGrid.getSelectedData(); + if(selectedData.length < 1){ + Swal.fire("수주취소할 행을 선택해주십시오."); + return false; + } else if(selectedData.length > 1){ + Swal.fire("한번에 한개의 수주만 취소 가능합니다."); + return false; + } + + var contractObjId = fnc_checkNull(selectedData[0].OBJID); + var orderQty = parseInt(selectedData[0].ORDER_QUANTITY) || 0; + + if(orderQty === 0){ + Swal.fire("수주 수량이 없는 건은 취소할 수 없습니다."); + return false; + } + + fn_openOrderCancelPopup(contractObjId); + }); + fn_search(); }); @@ -203,6 +225,14 @@ var columns = [ return Number(value).toLocaleString(); } }, + // 8-1. 수주취소 + {headerHozAlign : 'center', hozAlign : 'right', minWidth : 60, widthGrow: 0.7, title : '수주취소', field : 'CANCEL_QTY_SUM', + formatter: function(cell) { + var value = cell.getValue(); + if(!value || value === '' || value === 0 || value === '0') return ''; + return "" + Number(value).toLocaleString() + ""; + } + }, // 9. 유/무상 {headerHozAlign : 'center', hozAlign : 'center', minWidth : 45, widthGrow: 0.5, title : '유/무상', field : 'PAID_TYPE' }, // 10. 수주상태 @@ -656,6 +686,131 @@ function fn_showSerialNoPopup(serialNoString){ }); } +// 수주취소 팝업 - 품목별 취소 수량 입력 +function fn_openOrderCancelPopup(contractObjId){ + $.ajax({ + url: "/contractMgmt/getContractItems.do", + type: "POST", + data: { contractObjId: contractObjId }, + dataType: "json", + success: function(data){ + if(data.result !== "success" || !data.items || data.items.length === 0){ + Swal.fire("수주 품목 정보가 없습니다."); + return; + } + + var items = data.items; + var html = '
'; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + + items.forEach(function(item, idx){ + var objid = item.OBJID || item.objid || ''; + var partNo = item.PART_NO || item.part_no || ''; + var partName = item.PART_NAME || item.part_name || ''; + var orderQty = item.ORDER_QUANTITY || item.order_quantity || '0'; + var cancelQty = item.CANCEL_QTY || item.cancel_qty || ''; + var orderQtyNum = parseInt(orderQty) || 0; + var maxCancel = orderQtyNum > 0 ? orderQtyNum - 1 : 0; + + html += ''; + html += ''; + html += ''; + html += ''; + html += '
품번품명수주수량취소수량
' + partNo + '' + partName + '' + (orderQtyNum > 0 ? Number(orderQtyNum).toLocaleString() : '-') + ''; + if(orderQtyNum > 0){ + html += '= orderQty){ + Swal.showValidationMessage('취소 수량(' + cancelVal + ')은 수주수량(' + orderQty + ')보다 적어야 합니다.'); + hasError = true; + return; + } + + itemObjIds.push(input.getAttribute('data-objid')); + cancelQtys.push(cancelVal); + orderQtys.push(orderQty); + }); + + if(hasError) return false; + + return { itemObjIds: itemObjIds, cancelQtys: cancelQtys, orderQtys: orderQtys }; + } + }).then(function(result){ + if(result.isConfirmed && result.value){ + var val = result.value; + $.ajax({ + url: "/contractMgmt/saveOrderCancelQty.do", + type: "POST", + data: { + itemObjIds: val.itemObjIds.join(","), + cancelQtys: val.cancelQtys.join(","), + orderQtys: val.orderQtys.join(",") + }, + dataType: "json", + success: function(res){ + if(res.result === "true"){ + Swal.fire({ title: '저장 완료', text: res.msg, icon: 'success' }); + fn_search(); + } else { + Swal.fire({ title: '저장 실패', text: res.msg, icon: 'error' }); + } + }, + error: function(){ + Swal.fire("수주취소 저장 중 오류가 발생했습니다."); + } + }); + } + }); + }, + error: function(){ + Swal.fire("품목 정보 조회 중 오류가 발생했습니다."); + } + }); +} + //코드값을 받아와서 동적으로 selectbox 생성 function optionJobGroup(code){ var val=code; @@ -790,11 +945,12 @@ function openProjectFormPopUp(objId){

영업관리_주문서관리

-
- - - -
+
+ + + + +
diff --git a/src/com/pms/salesmgmt/controller/ContractMgmtController.java b/src/com/pms/salesmgmt/controller/ContractMgmtController.java index 5de59ff..c3435b2 100644 --- a/src/com/pms/salesmgmt/controller/ContractMgmtController.java +++ b/src/com/pms/salesmgmt/controller/ContractMgmtController.java @@ -2853,6 +2853,25 @@ public class ContractMgmtController { return resultMap; } + /** + * 수주취소 수량 저장 + */ + @ResponseBody + @RequestMapping(value="/contractMgmt/saveOrderCancelQty.do", method=RequestMethod.POST) + public Map saveOrderCancelQty(HttpServletRequest request, @RequestParam Map paramMap){ + Map resultMap = new HashMap(); + + try { + resultMap = contractMgmtService.saveOrderCancelQty(request, paramMap); + } catch (Exception e) { + e.printStackTrace(); + resultMap.put("result", "false"); + resultMap.put("msg", "수주취소 저장 중 오류가 발생했습니다."); + } + + return resultMap; + } + @RequestMapping("/contractMgmt/FileRegistPopup.do") public String FileRegistPopup(HttpServletRequest request, @RequestParam Map paramMap){ request.setAttribute("docType", CommonUtils.checkNull(paramMap.get("docType"))); diff --git a/src/com/pms/salesmgmt/mapper/contractMgmt.xml b/src/com/pms/salesmgmt/mapper/contractMgmt.xml index 166227c..9386ede 100644 --- a/src/com/pms/salesmgmt/mapper/contractMgmt.xml +++ b/src/com/pms/salesmgmt/mapper/contractMgmt.xml @@ -717,6 +717,16 @@ AND ORDER_QUANTITY != '' AND ORDER_QUANTITY != '0' ) AS HAS_ORDER_DATA + -- 수주취소 수량 합계 + ,( + SELECT COALESCE(SUM(CAST(NULLIF(CANCEL_QTY, '') AS NUMERIC)), 0) + FROM CONTRACT_ITEM + WHERE CONTRACT_OBJID = T.OBJID + AND STATUS = 'ACTIVE' + AND CANCEL_QTY IS NOT NULL + AND CANCEL_QTY != '' + AND CANCEL_QTY != '0' + ) AS CANCEL_QTY_SUM FROM CONTRACT_MGMT AS T LEFT OUTER JOIN @@ -5092,7 +5102,8 @@ WHERE CI.ORDER_UNIT_PRICE, CI.ORDER_SUPPLY_PRICE, CI.ORDER_VAT, - CI.ORDER_TOTAL_AMOUNT + CI.ORDER_TOTAL_AMOUNT, + CI.CANCEL_QTY FROM CONTRACT_ITEM CI LEFT JOIN PART_MNG PM ON CI.PART_OBJID = PM.OBJID @@ -5117,7 +5128,8 @@ WHERE CI.ORDER_UNIT_PRICE, CI.ORDER_SUPPLY_PRICE, CI.ORDER_VAT, - CI.ORDER_TOTAL_AMOUNT + CI.ORDER_TOTAL_AMOUNT, + CI.CANCEL_QTY ORDER BY CI.SEQ @@ -5133,6 +5145,16 @@ WHERE WHERE OBJID = #{contractItemObjId} + + + UPDATE CONTRACT_ITEM + SET + CANCEL_QTY = #{cancelQty}, + CHGDATE = NOW(), + CHG_USER_ID = #{userId} + WHERE OBJID = #{itemObjId} + + diff --git a/src/com/pms/salesmgmt/service/ContractMgmtService.java b/src/com/pms/salesmgmt/service/ContractMgmtService.java index 0629287..2398004 100644 --- a/src/com/pms/salesmgmt/service/ContractMgmtService.java +++ b/src/com/pms/salesmgmt/service/ContractMgmtService.java @@ -3865,4 +3865,89 @@ private String encodeImageToBase64(String imagePath) { e.printStackTrace(); } } + + /** + * 수주취소 수량 저장 + * 품목별로 부분 취소 수량을 업데이트한다. (전체 취소 불가, 부분만 가능) + */ + public Map saveOrderCancelQty(HttpServletRequest request, Map paramMap) { + Map resultMap = new HashMap(); + SqlSession sqlSession = null; + + try { + sqlSession = SqlMapConfig.getInstance().getSqlSession(); + + HttpSession session = request.getSession(); + PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN); + String userId = person.getUserId(); + + String itemObjIdsStr = CommonUtils.checkNull(paramMap.get("itemObjIds")); + String cancelQtysStr = CommonUtils.checkNull(paramMap.get("cancelQtys")); + String orderQtysStr = CommonUtils.checkNull(paramMap.get("orderQtys")); + + if ("".equals(itemObjIdsStr) || "".equals(cancelQtysStr)) { + resultMap.put("result", "false"); + resultMap.put("msg", "취소 수량 정보가 없습니다."); + return resultMap; + } + + String[] itemObjIds = itemObjIdsStr.split(","); + String[] cancelQtys = cancelQtysStr.split(","); + String[] orderQtys = orderQtysStr.split(","); + + for (int i = 0; i < itemObjIds.length; i++) { + String cancelQty = cancelQtys[i].trim(); + String orderQty = orderQtys[i].trim(); + + // 빈 값이면 스킵 + if ("".equals(cancelQty) || "0".equals(cancelQty)) { + // 취소수량 0이면 초기화 + Map updateParam = new HashMap(); + updateParam.put("itemObjId", itemObjIds[i].trim()); + updateParam.put("cancelQty", ""); + updateParam.put("userId", userId); + sqlSession.update("contractMgmt.updateContractItemCancelQty", updateParam); + continue; + } + + int cancelQtyInt = Integer.parseInt(cancelQty); + int orderQtyInt = Integer.parseInt(orderQty); + + // 전체 수량 취소 불가 (부분만 가능) + if (cancelQtyInt >= orderQtyInt) { + resultMap.put("result", "false"); + resultMap.put("msg", "수주취소 수량은 수주수량(" + orderQtyInt + ")보다 적어야 합니다."); + sqlSession.rollback(); + return resultMap; + } + + if (cancelQtyInt < 0) { + resultMap.put("result", "false"); + resultMap.put("msg", "수주취소 수량은 0 이상이어야 합니다."); + sqlSession.rollback(); + return resultMap; + } + + Map updateParam = new HashMap(); + updateParam.put("itemObjId", itemObjIds[i].trim()); + updateParam.put("cancelQty", cancelQty); + updateParam.put("userId", userId); + sqlSession.update("contractMgmt.updateContractItemCancelQty", updateParam); + } + + sqlSession.commit(); + resultMap.put("result", "true"); + resultMap.put("msg", "수주취소 수량이 저장되었습니다."); + + } catch (Exception e) { + e.printStackTrace(); + if (sqlSession != null) sqlSession.rollback(); + resultMap.put("result", "false"); + resultMap.put("msg", "수주취소 저장 중 오류가 발생했습니다."); + } finally { + if (sqlSession != null) sqlSession.close(); + } + + return resultMap; + } }