From f5cb14ae4847c9a4bd0e09b3e5f01607d113ce6a Mon Sep 17 00:00:00 2001 From: hjjeong Date: Thu, 5 Mar 2026 12:01:27 +0900 Subject: [PATCH 1/6] =?UTF-8?q?wbs=20=ED=85=9C=ED=94=8C=EB=A6=BF=20?= =?UTF-8?q?=EC=A4=91=EA=B0=84=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/project/WBSExcelImportPopUp.jsp | 692 +++++++++++------- .../view/project/wbsTemplateMngList.jsp | 30 +- src/com/pms/controller/ProjectController.java | 19 +- src/com/pms/mapper/project.xml | 27 +- src/com/pms/service/ProjectService.java | 61 +- 5 files changed, 490 insertions(+), 339 deletions(-) diff --git a/WebContent/WEB-INF/view/project/WBSExcelImportPopUp.jsp b/WebContent/WEB-INF/view/project/WBSExcelImportPopUp.jsp index 707837a..273a2d7 100644 --- a/WebContent/WEB-INF/view/project/WBSExcelImportPopUp.jsp +++ b/WebContent/WEB-INF/view/project/WBSExcelImportPopUp.jsp @@ -7,283 +7,408 @@ <%=Constants.SYSTEM_NAME%> +
- - - + +

- WBS Excel Upload + ${empty templateObjId ? 'WBS 템플릿 등록' : 'WBS 템플릿 수정'}

@@ -291,28 +416,20 @@ $(document).ready(function(){ - + - + - + - - - - - - - - @@ -320,7 +437,9 @@ $(document).ready(function(){
- + + +
@@ -335,31 +454,42 @@ $(document).ready(function(){
- -
- - - - - - - - - - - -
UNIT NameUNIT No
-
- -
- - - - - - -
-
+ +
+ + + + + + + + + + + + + + + + + + + + +
선택수준Unit Name / 공정
123
+
+
+ + + + + + + + + +
+
diff --git a/WebContent/WEB-INF/view/project/wbsTemplateMngList.jsp b/WebContent/WEB-INF/view/project/wbsTemplateMngList.jsp index aa92765..d481235 100644 --- a/WebContent/WEB-INF/view/project/wbsTemplateMngList.jsp +++ b/WebContent/WEB-INF/view/project/wbsTemplateMngList.jsp @@ -92,14 +92,14 @@ $(document).ready(function(){ var columns = [ {headerHozAlign : 'center', hozAlign : 'left', width : '250', title : '제품구분', field : 'PRODUCT_NAME' }, - {headerHozAlign : 'center', hozAlign : 'left', width : '250', title : '기계형식', field : 'TITLE' }, - {headerHozAlign : 'center', hozAlign : 'left', /* width : '250', */ title : '고객사_장비목적', field : 'CUSTOMER_PRODUCT', - formatter:fnc_createGridAnchorTag, - cellClick:function(e, cell){ - var objid = fnc_checkNull(cell.getData().OBJID); - fn_openTemplateMasterPopUp(objid); - } - }, + {headerHozAlign : 'center', hozAlign : 'left', /* width : '250', */ title : '제목', field : 'TITLE' }, + // {headerHozAlign : 'center', hozAlign : 'left', /* width : '250', */ title : '고객사_장비목적', field : 'CUSTOMER_PRODUCT', + // formatter:fnc_createGridAnchorTag, + // cellClick:function(e, cell){ + // var objid = fnc_checkNull(cell.getData().OBJID); + // fn_openTemplateMasterPopUp(objid); + // } + // }, {headerHozAlign : 'center', hozAlign : 'center', width : '250', title : 'UNIT', field : 'WBS_TASK_CNT0', formatter:fnc_getFolderIcon, cellClick:function(e, cell){ @@ -130,18 +130,12 @@ function fn_openTemplateMasterPopUp(objId){ } function fn_openWBSTaskListPopUp(objId){ - var hiddenForm = document.hiddenForm; - var popup_width = 800; - var popup_height = 700; - var url = "/project/wbsTemplateTaskListDetailPopUp.do"; + var popup_width = 1340; + var popup_height = 700; + var url = "/project/WBSExcelImportPopUp.do?templateObjId=" + objId; var target = "openWBSTaskListPopUp"; - + fn_centerPopup(popup_width, popup_height, url, target); - - hiddenForm.action = url; - hiddenForm.OBJID.value = objId; - hiddenForm.target = target; - hiddenForm.submit(); } function _fnc_datepick(){ diff --git a/src/com/pms/controller/ProjectController.java b/src/com/pms/controller/ProjectController.java index 8aedd0e..b237a43 100644 --- a/src/com/pms/controller/ProjectController.java +++ b/src/com/pms/controller/ProjectController.java @@ -2282,14 +2282,27 @@ public class ProjectController { @RequestMapping("/project/WBSExcelImportPopUp.do") public String partMngExcelImportPopUp(HttpServletRequest request, @RequestParam Map paramMap){ String objid = CommonUtils.createObjId(); + String templateObjId = CommonUtils.nullToEmpty((String)paramMap.get("templateObjId")); Map code_map = new HashMap(); try{ - code_map.put("product_cd", commonService.bizMakeOptionList("0000001", CommonUtils.nullToEmpty((String)paramMap.get("product")),"common.getCodeselect")); //공장 - + code_map.put("product_cd", commonService.bizMakeOptionList("0000001", CommonUtils.nullToEmpty((String)paramMap.get("product")),"common.getCodeselect")); + + if(!"".equals(templateObjId)){ + Map templateParam = new HashMap(); + templateParam.put("OBJID", templateObjId); + Map masterInfo = service.getWBSTemplateMasterInfo(request, templateParam); + List taskList = service.getWBSTemplateTaskList(request, templateParam); + request.setAttribute("masterInfo", masterInfo); + request.setAttribute("taskList", taskList); + request.setAttribute("templateObjId", templateObjId); + + String productObjId = CommonUtils.nullToEmpty((String)masterInfo.get("PRODUCT_OBJID")); + code_map.put("product_cd", commonService.bizMakeOptionList("0000001", productObjId, "common.getCodeselect")); + } }catch(Exception e){ e.printStackTrace(); } - + request.setAttribute("OBJID",objid); request.setAttribute("code_map",code_map); return "/project/WBSExcelImportPopUp"; diff --git a/src/com/pms/mapper/project.xml b/src/com/pms/mapper/project.xml index fce4c42..535257b 100644 --- a/src/com/pms/mapper/project.xml +++ b/src/com/pms/mapper/project.xml @@ -5611,29 +5611,38 @@ ,PARENT_OBJID ,TASK_NAME ,TASK_SEQ + ,TASK_LEVEL ,USER_ID ,WRITER ,REG_DATE ,UNIT_NO + ,UPPER_TASK_OBJID ) VALUES ( #{objid} ,#{parent_objid} ,#{task_name} ,#{task_seq} + ,#{task_level} ,#{user_id} ,#{writer} - ,now() + ,now() ,#{unit_no} + ,#{upper_task_objid} ) ON CONFLICT (OBJID) DO UPDATE SET - TASK_NAME = #{task_name} - ,TASK_SEQ = #{task_seq} - ,USER_ID = #{user_id} - ,UNIT_NO = #{unit_no} + TASK_NAME = #{task_name} + ,TASK_SEQ = #{task_seq} + ,TASK_LEVEL = #{task_level} + ,USER_ID = #{user_id} + ,UNIT_NO = #{unit_no} + ,UPPER_TASK_OBJID = #{upper_task_objid} - - + + + DELETE FROM PMS_WBS_TASK_STANDARD WHERE PARENT_OBJID = #{parent_objid} + + diff --git a/src/com/pms/service/ProjectService.java b/src/com/pms/service/ProjectService.java index f8801a8..a5170ac 100644 --- a/src/com/pms/service/ProjectService.java +++ b/src/com/pms/service/ProjectService.java @@ -2940,51 +2940,54 @@ public class ProjectService { try{ PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN); String writer = CommonUtils.checkNull(person.getUserId()); - + String product = CommonUtils.checkNull(request.getParameter("product")); String title = CommonUtils.checkNull(request.getParameter("title")); String customer_product = CommonUtils.checkNull(request.getParameter("customer_product")); - - Map templateMapsterSqlParamMap = new HashMap(); - - String wbsMasterObjId = CommonUtils.createObjId(); - - templateMapsterSqlParamMap.put("objid" , wbsMasterObjId); - templateMapsterSqlParamMap.put("product" , product); - templateMapsterSqlParamMap.put("title" , title); - templateMapsterSqlParamMap.put("writer" , writer); - templateMapsterSqlParamMap.put("customer_product" , customer_product); - - //템플릿 마스터를 저장한다. - sqlSession.insert("project.saveWBSTaskTemp",templateMapsterSqlParamMap); - + String templateObjId = CommonUtils.checkNull(request.getParameter("templateObjId")); + + String wbsMasterObjId; + + if(!"".equals(templateObjId)){ + wbsMasterObjId = templateObjId; + Map deleteParam = new HashMap(); + deleteParam.put("parent_objid", wbsMasterObjId); + sqlSession.delete("project.deleteWBSTemplateTaskByMaster", deleteParam); + } else { + wbsMasterObjId = CommonUtils.createObjId(); + Map templateMasterSqlParamMap = new HashMap(); + templateMasterSqlParamMap.put("objid", wbsMasterObjId); + templateMasterSqlParamMap.put("product", product); + templateMasterSqlParamMap.put("title", title); + templateMasterSqlParamMap.put("writer", writer); + templateMasterSqlParamMap.put("customer_product", customer_product); + sqlSession.insert("project.saveWBSTaskTemp", templateMasterSqlParamMap); + } + String[] wbsObjIdList = request.getParameterValues("WBS_TASK_OBJID"); - - if(null != wbsObjIdList || 0 < wbsObjIdList.length){ - + + if(null != wbsObjIdList && 0 < wbsObjIdList.length){ + for(int i = 0;i Date: Thu, 5 Mar 2026 15:50:36 +0900 Subject: [PATCH 2/6] =?UTF-8?q?=EA=B5=AC=EB=A7=A4=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EA=B0=80=EA=B3=B5=EC=97=85=EC=B2=B4,=20=EA=B3=B5?= =?UTF-8?q?=EA=B8=89=EC=97=85=EC=B2=B4=20=EB=B3=B5=EC=82=AC,=20=EB=B6=99?= =?UTF-8?q?=EC=97=AC=EB=84=A3=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../view/salesMng/purchaseListFormPopUp.jsp | 178 +++++++++++++++++- src/com/pms/mapper/salesMng.xml | 10 +- 2 files changed, 180 insertions(+), 8 deletions(-) diff --git a/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp b/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp index 8dbd86a..333ca26 100644 --- a/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp +++ b/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp @@ -68,6 +68,36 @@ body, html { padding: 20px; overflow: auto; } +.vendor-context-menu { + position: fixed; + background: #fff; + border: 1px solid #ccc; + box-shadow: 2px 2px 8px rgba(0,0,0,0.2); + z-index: 10000; + border-radius: 4px; + padding: 4px 0; + min-width: 180px; +} +.vendor-context-menu .ctx-item { + padding: 8px 16px; + cursor: pointer; + font-size: 13px; + white-space: nowrap; +} +.vendor-context-menu .ctx-item:hover { + background: #e3f2fd; +} +.vendor-context-menu .ctx-item.disabled { + color: #aaa; + cursor: default; +} +.vendor-context-menu .ctx-item.disabled:hover { + background: transparent; +} +.vendor-context-menu .ctx-divider { + border-top: 1px solid #eee; + margin: 4px 0; +} @@ -137,6 +167,7 @@ var bomReportObjid = "${resolvedBomReportObjid}"; var mbomHeaderObjid = "${resolvedMbomHeaderObjid}"; // MBOM_HEADER.OBJID (M-BOM 관리 화면에서 사용하는 ID) var vendorList = []; // 공급업체 목록 var processingVendorList = []; // 가공업체 목록 (Select2용 배열) +var copiedVendorData = { field: null, value: null, displayName: '' }; // 복사된 업체 정보 // 디버그: resultMap 내용 확인 (주석처리) // console.log("=== JSP resultMap 디버그 ==="); @@ -875,6 +906,149 @@ function fn_initGrid() { row.reformat(); } }); + + // 공급업체/가공업체 셀 우클릭 → 복사/붙여넣기 컨텍스트 메뉴 + _tabulGrid.on("cellContext", function(e, cell) { + var field = cell.getField(); + if(field !== 'VENDOR_PM' && field !== 'PROCESSING_VENDOR') return; + e.preventDefault(); + fn_showVendorContextMenu(e, cell); + }); + + // 다른 곳 클릭 시 컨텍스트 메뉴 닫기 + $(document).on('click', function() { + $('.vendor-context-menu').remove(); + }); +} + +// 업체 복사/붙여넣기 컨텍스트 메뉴 표시 +function fn_showVendorContextMenu(e, cell) { + $('.vendor-context-menu').remove(); + + var field = cell.getField(); + var cellValue = cell.getValue(); + var fieldLabel = (field === 'VENDOR_PM') ? '공급업체' : '가공업체'; + var displayName = fn_getVendorDisplayName(cellValue); + + var menu = $('
'); + + // 복사 + var copyLabel = cellValue ? '복사 : ' + displayName : '복사 (값 없음)'; + var $copyItem = $('
' + copyLabel + '
'); + if(cellValue) { + $copyItem.on('click', function() { + copiedVendorData = { field: field, value: cellValue, displayName: displayName }; + menu.remove(); + Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: fieldLabel + ' 복사: ' + displayName, showConfirmButton: false, timer: 1200 }); + }); + } else { + $copyItem.addClass('disabled'); + } + menu.append($copyItem); + + menu.append('
'); + + // 선택행에 붙여넣기 + var hasCopied = copiedVendorData.value && copiedVendorData.field === field; + var pasteLabel = hasCopied + ? '선택행에 붙여넣기 : ' + copiedVendorData.displayName + : '선택행에 붙여넣기 (복사된 ' + fieldLabel + ' 없음)'; + var $pasteItem = $('
' + pasteLabel + '
'); + if(hasCopied) { + $pasteItem.on('click', function() { + menu.remove(); + fn_pasteVendorToCheckedRows(copiedVendorData.field, copiedVendorData.value); + }); + } else { + $pasteItem.addClass('disabled'); + } + menu.append($pasteItem); + + menu.append('
'); + + // 전체행에 붙여넣기 + var pasteAllLabel = hasCopied + ? '전체행에 붙여넣기 : ' + copiedVendorData.displayName + : '전체행에 붙여넣기 (복사된 ' + fieldLabel + ' 없음)'; + var $pasteAllItem = $('
' + pasteAllLabel + '
'); + if(hasCopied) { + $pasteAllItem.on('click', function() { + menu.remove(); + fn_pasteVendorToAllRows(copiedVendorData.field, copiedVendorData.value); + }); + } else { + $pasteAllItem.addClass('disabled'); + } + menu.append($pasteAllItem); + + // 화면 밖으로 나가지 않도록 위치 보정 + var menuX = e.pageX; + var menuY = e.pageY; + $('body').append(menu); + var menuWidth = menu.outerWidth(); + var menuHeight = menu.outerHeight(); + if(menuX + menuWidth > $(window).width()) menuX = $(window).width() - menuWidth - 5; + if(menuY + menuHeight > $(window).height()) menuY = $(window).height() - menuHeight - 5; + menu.css({ left: menuX + 'px', top: menuY + 'px' }); +} + +// 업체 OBJID → 업체명 변환 +function fn_getVendorDisplayName(value) { + if(!value) return ''; + for(var i = 0; i < processingVendorList.length; i++) { + if(processingVendorList[i].id == value) return processingVendorList[i].text; + } + return value; +} + +// 체크된 행에 업체값 붙여넣기 +function fn_pasteVendorToCheckedRows(field, value) { + var count = 0; + $('.rowCheck:checked').each(function() { + var row = $(this).closest('.tabulator-row'); + if(row.length > 0 && _tabulGrid) { + var rowComponent = _tabulGrid.getRow(row[0]); + if(rowComponent) { + var updateData = {}; + updateData[field] = value; + rowComponent.update(updateData); + count++; + } + } + }); + var fieldLabel = (field === 'VENDOR_PM') ? '공급업체' : '가공업체'; + if(count > 0) { + Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: fieldLabel + ' ' + count + '건 적용 완료', showConfirmButton: false, timer: 1500 }); + } else { + Swal.fire({ title: '알림', text: '체크된 행이 없습니다.\n먼저 적용할 행을 체크해주세요.', icon: 'info' }); + } +} + +// 전체 행에 업체값 붙여넣기 +function fn_pasteVendorToAllRows(field, value) { + var fieldLabel = (field === 'VENDOR_PM') ? '공급업체' : '가공업체'; + var displayName = fn_getVendorDisplayName(value); + + Swal.fire({ + title: '전체 적용', + text: '모든 행의 ' + fieldLabel + '을(를) "' + displayName + '"(으)로 변경하시겠습니까?', + icon: 'question', + showCancelButton: true, + confirmButtonText: '적용', + cancelButtonText: '취소' + }).then(function(result) { + if(result.isConfirmed) { + var rows = _tabulGrid.getRows(); + var count = 0; + rows.forEach(function(row) { + var updateData = {}; + updateData[field] = value; + row.update(updateData); + count++; + }); + Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: fieldLabel + ' 전체 ' + count + '건 적용 완료', showConfirmButton: false, timer: 1500 }); + } + }); } // 기존 구매리스트 조회 @@ -944,11 +1118,7 @@ function fn_loadFromMBom(callback) { var list = (data && data.list) ? data.list : []; if(list.length > 0) { - // console.log("M-BOM 데이터 " + list.length + "건 로드됨"); _tabulGrid.setData(list); - } else { - // console.log("M-BOM 데이터 없음!"); - // 알림 제거 - 머지 모드에서는 알림 안 띄움 } if(typeof callback === "function"){ callback(list); diff --git a/src/com/pms/mapper/salesMng.xml b/src/com/pms/mapper/salesMng.xml index 9980caf..45bf26c 100644 --- a/src/com/pms/mapper/salesMng.xml +++ b/src/com/pms/mapper/salesMng.xml @@ -3305,7 +3305,7 @@ WITH RECURSIVE VIEW_BOM( A.PART_NO, A.PART_NAME, A.QTY, - A.QTY, + A.ITEM_QTY, A.QTY, A.REGDATE, A.SEQ, @@ -3368,7 +3368,7 @@ WITH RECURSIVE VIEW_BOM( B.PART_NO, B.PART_NAME, B.QTY, - B.QTY, + B.ITEM_QTY, B.QTY, B.REGDATE, B.SEQ, @@ -3445,6 +3445,7 @@ GROUPED_BOM AS ( MIN(V.CHILD_OBJID) AS CHILD_OBJID, MIN(V.PART_NAME) AS PART_NAME, SUM(COALESCE(NULLIF(V.QTY::TEXT, '')::NUMERIC, 0)) AS QTY, + SUM(COALESCE(NULLIF(V.ITEM_QTY::TEXT, '')::NUMERIC, 0)) AS ITEM_QTY, MIN(V.SEQ) AS SEQ, MIN(V.STATUS) AS STATUS, MIN(V.LEV) AS LEV, @@ -3476,6 +3477,7 @@ GROUPED_BOM AS ( COUNT(*) AS GROUPED_COUNT FROM VIEW_BOM V WHERE COALESCE(V.PRODUCTION_QTY, 0) > 0 + AND V.LEV > 1 GROUP BY V.PART_NO, V.PART_OBJID, COALESCE(V.SUPPLY_TYPE, ''), COALESCE(V.RAW_MATERIAL, ''), @@ -3494,7 +3496,7 @@ SELECT G.PART_NO, G.PART_NAME, G.QTY, - G.QTY AS ITEM_QTY, + G.ITEM_QTY, G.QTY AS QTY_TEMP, G.LEV AS LEVEL, 0 AS SUB_PART_CNT, @@ -3507,7 +3509,7 @@ SELECT G.RAW_MATERIAL_SPEC, G.RAW_MATERIAL, G.RAW_MATERIAL_SIZE AS SIZE, - CASE WHEN G.PROCESSING_VENDOR IS NULL THEN '0000008377' ELSE G.PROCESSING_VENDOR END AS PROCESSING_VENDOR, + G.PROCESSING_VENDOR, G.PROCESSING_DEADLINE, G.GRINDING_DEADLINE, G.REQUIRED_QTY, -- 2.49.1 From 82e43a2def0f7e8e97fdaf2af50a2954705bbbb9 Mon Sep 17 00:00:00 2001 From: hjjeong Date: Thu, 5 Mar 2026 16:34:40 +0900 Subject: [PATCH 3/6] =?UTF-8?q?=EC=84=A4=EB=B9=84model=20=ED=92=88?= =?UTF-8?q?=EB=AA=85=EC=9D=B4=EB=9E=91=20=EB=8F=99=EC=9D=BC=ED=95=98?= =?UTF-8?q?=EA=B2=8C=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp b/WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp index fbd1970..0532eeb 100644 --- a/WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/estimateTemplate2.jsp @@ -768,6 +768,7 @@ function fn_loadData() { $("#recipient").val(data.estimate.RECIPIENT || "").trigger('change'); $("#part_name").val(data.estimate.PART_NAME || ""); $("#part_objid").val(data.estimate.PART_OBJID || ""); + $("#model_code").val(data.estimate.PART_NAME || ""); // 환종 표시 if(data.estimate.CONTRACT_CURRENCY_NAME) { @@ -1239,7 +1240,7 @@ function fn_generateAndUploadPdf(callback) {
설비 Model : - +
-- 2.49.1 From 2081495a62f6362d7b51784f129be072b434ca95 Mon Sep 17 00:00:00 2001 From: hjjeong Date: Thu, 5 Mar 2026 16:44:53 +0900 Subject: [PATCH 4/6] =?UTF-8?q?=EC=8B=A4=EC=A0=81=EB=93=B1=EB=A1=9D=20?= =?UTF-8?q?=EC=B4=9D=20=EC=88=98=EB=9F=89=20=EC=B4=9D=EC=83=9D=EC=82=B0?= =?UTF-8?q?=EC=88=98=EB=9F=89=20=EB=84=98=EC=A7=80=20=EB=AA=BB=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prodResultFormPopup.jsp | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/WebContent/WEB-INF/view/productionplanning/prodResultFormPopup.jsp b/WebContent/WEB-INF/view/productionplanning/prodResultFormPopup.jsp index 1a65cf1..2549c40 100644 --- a/WebContent/WEB-INF/view/productionplanning/prodResultFormPopup.jsp +++ b/WebContent/WEB-INF/view/productionplanning/prodResultFormPopup.jsp @@ -226,9 +226,9 @@ function fn_addRow(resultDate, assemblyQty, inspectionQty, shipWaitQty) { var html = ''; html += ''; - html += ''; - html += ''; - html += ''; + html += ''; + html += ''; + html += ''; html += ''; html += ''; @@ -242,6 +242,47 @@ function fn_deleteRow(rowIndex) { fn_updateTotals(); } +// 총생산수량 반환 +function fn_getTotalProdQty() { + return parseInt($("#TOTAL_PROD_QTY").text().replace(/,/g, "")) || 0; +} + +// 특정 컬럼의 총합 계산 (excludeEl: 제외할 input) +function fn_getColumnTotal(className, excludeEl) { + var total = 0; + $("." + className).each(function() { + if(excludeEl && this === excludeEl) return; + total += parseInt($(this).val()) || 0; + }); + return total; +} + +// 입력값 검증 후 총수량 업데이트 +function fn_validateAndUpdate(inputEl, className, labelName) { + var totalProdQty = fn_getTotalProdQty(); + var othersTotal = fn_getColumnTotal(className, inputEl); + var currentVal = parseInt($(inputEl).val()) || 0; + var maxAllowed = totalProdQty - othersTotal; + + if(maxAllowed < 0) maxAllowed = 0; + + if(currentVal < 0) { + $(inputEl).val(0); + currentVal = 0; + } + + if(currentVal > maxAllowed) { + Swal.fire({ + icon: 'warning', + title: labelName + ' 수량 초과', + text: labelName + ' 총합이 총생산수량(' + totalProdQty + ')을 초과할 수 없습니다. (입력 가능: ' + maxAllowed + ')' + }); + $(inputEl).val(maxAllowed); + } + + fn_updateTotals(); +} + // 총수량 업데이트 function fn_updateTotals() { var totalAssembly = 0; @@ -298,6 +339,25 @@ function fn_save() { } } + // 총생산수량 초과 검사 + var totalProdQty = fn_getTotalProdQty(); + var totalAssembly = fn_getColumnTotal('assembly-qty'); + var totalInspection = fn_getColumnTotal('inspection-qty'); + var totalShipWait = fn_getColumnTotal('ship-wait-qty'); + + if(totalAssembly > totalProdQty) { + Swal.fire('완조립 총합(' + totalAssembly + ')이 총생산수량(' + totalProdQty + ')을 초과합니다.'); + return; + } + if(totalInspection > totalProdQty) { + Swal.fire('검사 총합(' + totalInspection + ')이 총생산수량(' + totalProdQty + ')을 초과합니다.'); + return; + } + if(totalShipWait > totalProdQty) { + Swal.fire('포장 총합(' + totalShipWait + ')이 총생산수량(' + totalProdQty + ')을 초과합니다.'); + return; + } + if(!confirm('저장하시겠습니까?')) return; $.ajax({ -- 2.49.1 From acd76ee2d21653918db57d76f8b28aa590ce6c00 Mon Sep 17 00:00:00 2001 From: hjjeong Date: Thu, 5 Mar 2026 16:57:19 +0900 Subject: [PATCH 5/6] =?UTF-8?q?=EA=B7=B8=EB=A6=AC=EB=93=9C=20=EC=85=80=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=20=EC=98=A4=EB=A5=98=20=EB=93=B1=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quality/processInspectionFormPopUp.jsp | 43 ++++++++++++------- .../semiProductInspectionFormPopUp.jsp | 26 ++++++++--- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp b/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp index ef0866e..129c0d1 100644 --- a/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp +++ b/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp @@ -181,6 +181,8 @@ function fn_select2Editor(cell, onRendered, success, cancel, editorParams) { var select = document.createElement("select"); select.style.width = "100%"; + select.style.opacity = "0"; + select.style.position = "absolute"; // 옵션 생성 if(values && values.length > 0) { @@ -203,21 +205,32 @@ function fn_select2Editor(cell, onRendered, success, cancel, editorParams) { width: "100%" }); $(select).select2("open"); - - $(select).on("select2:select select2:clear", function(e) { - var selectedVal = $(select).val() || ""; - - // 콜백 호출 (프로젝트 변경 시 연동 처리 등) - if(typeof editorParams.onSelect === "function") { - editorParams.onSelect(cell, selectedVal); - } - - success(selectedVal); - }); - - $(select).on("select2:close", function() { - setTimeout(function() { success($(select).val() || ""); }, 100); - }); + }); + + var isCleared = false; + + $(select).on("select2:select", function(e) { + var selectedVal = $(select).val() || ""; + if(typeof editorParams.onSelect === "function") { + editorParams.onSelect(cell, selectedVal); + } + success(selectedVal); + }); + + $(select).on("select2:clear", function(e) { + isCleared = true; + if(typeof editorParams.onSelect === "function") { + editorParams.onSelect(cell, ""); + } + setTimeout(function() { + $(select).select2("close"); + success(""); + }, 0); + }); + + $(select).on("select2:close", function() { + if(isCleared) return; + success($(select).val() || ""); }); return container; diff --git a/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp b/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp index e881b7d..1ac39de 100644 --- a/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp +++ b/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp @@ -386,6 +386,8 @@ function createSelect2Editor(options, allowClear) { var container = document.createElement("span"); var select = document.createElement("select"); select.style.width = "100%"; + select.style.opacity = "0"; + select.style.position = "absolute"; var emptyOption = document.createElement("option"); emptyOption.value = ""; @@ -410,14 +412,28 @@ function createSelect2Editor(options, allowClear) { allowClear: allowClear !== false, dropdownParent: $('body') }); - - $(select).on('select2:select select2:clear', function(e) { - success($(select).val() || ''); - }); - $(select).select2('open'); }); + var isCleared = false; + + $(select).on('select2:select', function(e) { + success($(select).val() || ''); + }); + + $(select).on('select2:clear', function(e) { + isCleared = true; + setTimeout(function() { + $(select).select2('close'); + success(''); + }, 0); + }); + + $(select).on('select2:close', function() { + if(isCleared) return; + success($(select).val() || ''); + }); + return container; }; } -- 2.49.1 From 2cc8350f6c96ff90e9ca388e31f5f3d3f652af28 Mon Sep 17 00:00:00 2001 From: hjjeong Date: Thu, 5 Mar 2026 17:56:26 +0900 Subject: [PATCH 6/6] =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../incomingInspectionProgressPopUp.jsp | 3 +- .../semiProductInspectionFormPopUp.jsp | 152 ++++++++++++------ 2 files changed, 106 insertions(+), 49 deletions(-) diff --git a/WebContent/WEB-INF/view/quality/incomingInspectionProgressPopUp.jsp b/WebContent/WEB-INF/view/quality/incomingInspectionProgressPopUp.jsp index 50c2f81..8b73699 100644 --- a/WebContent/WEB-INF/view/quality/incomingInspectionProgressPopUp.jsp +++ b/WebContent/WEB-INF/view/quality/incomingInspectionProgressPopUp.jsp @@ -119,7 +119,8 @@ var _ACTION_RESULT_LIST = [ {"CODE": "", "NAME": "선택"}, {"CODE": "수정", "NAME": "수정완료"}, {"CODE": "폐기", "NAME": "폐기"}, - {"CODE": "특채", "NAME": "특채완료"} + {"CODE": "특채", "NAME": "특채완료"}, + {"CODE": "검사완료", "NAME": "검사완료"} ]; // 검사자 목록 var _INSPECTOR_LIST = []; diff --git a/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp b/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp index 1ac39de..969df00 100644 --- a/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp +++ b/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp @@ -26,9 +26,10 @@ String loginUserId = CommonUtils.checkNull(person.getUserId()); <%=Constants.SYSTEM_NAME%> - + - + +