diff --git a/WebContent/WEB-INF/classes/com/pms/salesmgmt/mapper/salesNcollectMgmt.xml b/WebContent/WEB-INF/classes/com/pms/salesmgmt/mapper/salesNcollectMgmt.xml index 5c83660..9a65e1d 100644 --- a/WebContent/WEB-INF/classes/com/pms/salesmgmt/mapper/salesNcollectMgmt.xml +++ b/WebContent/WEB-INF/classes/com/pms/salesmgmt/mapper/salesNcollectMgmt.xml @@ -844,19 +844,22 @@ FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID) AS PAYMENT_TYPE, T.PART_NO AS PRODUCT_NO, T.PART_NAME AS PRODUCT_NAME, - -- S/N: 해당 품목의 시리얼 번호 (여러 개일 경우 "S/N 외 N건" 형식) - (SELECT - CASE - WHEN COUNT(*) = 0 THEN '' - WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO) - ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건' - END - FROM CONTRACT_ITEM CI - LEFT JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID AND UPPER(CIS.STATUS) = 'ACTIVE' - WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID - AND CI.PART_OBJID = T.PART_OBJID - AND CI.STATUS = 'ACTIVE' - AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO, + -- S/N: CONTRACT_ITEM_SERIAL(마스터) 우선, 없으면 판매등록 텍스트 fallback (그리드 요약용) + COALESCE( + (SELECT + CASE + WHEN COUNT(*) = 0 THEN NULL + WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO) + ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건' + END + FROM CONTRACT_ITEM CI + LEFT JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID AND UPPER(CIS.STATUS) = 'ACTIVE' + WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID + AND CI.PART_OBJID = T.PART_OBJID + AND CI.STATUS = 'ACTIVE' + AND CIS.SERIAL_NO IS NOT NULL), + SR.serial_no + ) AS SERIAL_NO, COALESCE(T.QUANTITY::numeric, 0) AS ORDER_QUANTITY, -- 요청납기: CONTRACT_ITEM 우선, 없으면 PROJECT_MGMT, 없으면 CONTRACT_MGMT COALESCE( @@ -893,20 +896,10 @@ COALESCE(SR.sales_vat, 0) AS SALES_VAT, COALESCE(SR.sales_total_amount, 0) AS SALES_TOTAL_AMOUNT, COALESCE(SR.sales_total_amount, 0) AS SALES_TOTAL_AMOUNT_KRW, - -- 잔량 계산: 수주수량 - shipment_log의 split_quantity 합계 - COALESCE(T.QUANTITY::numeric, 0) - COALESCE( - (SELECT SUM(COALESCE(split_quantity, 0)) - FROM shipment_log - WHERE target_objid = T.PROJECT_NO), - 0 - ) AS REMAINING_QUANTITY, - -- 잔량원화총액 계산: (수주수량 - shipment_log 합계) * 판매단가 - (COALESCE(T.QUANTITY::numeric, 0) - COALESCE( - (SELECT SUM(COALESCE(split_quantity, 0)) - FROM shipment_log - WHERE target_objid = T.PROJECT_NO), - 0 - )) * COALESCE(SR.sales_unit_price, 0) AS REMAINING_AMOUNT_KRW, + -- 잔량 계산: 수주수량 - sales_registration.sales_quantity + COALESCE(T.QUANTITY::numeric, 0) - COALESCE(SR.sales_quantity, 0) AS REMAINING_QUANTITY, + -- 잔량원화총액 계산: 잔량 * 판매단가 + (COALESCE(T.QUANTITY::numeric, 0) - COALESCE(SR.sales_quantity, 0)) * COALESCE(SR.sales_unit_price, 0) AS REMAINING_AMOUNT_KRW, COALESCE(SR.sales_currency, T.CONTRACT_CURRENCY) AS SALES_CURRENCY, CODE_NAME(COALESCE(SR.sales_currency, T.CONTRACT_CURRENCY)) AS SALES_CURRENCY_NAME, COALESCE(SR.sales_exchange_rate, T.CONTRACT_PRICE_CURRENCY::numeric, 0) AS SALES_EXCHANGE_RATE, @@ -942,13 +935,14 @@ THEN '분할판매' ELSE '' END AS SALES_STATUS, + SR.sale_no AS SALES_REG_NO, T.OBJID::VARCHAR AS SALE_NO, 'ORIGINAL' AS RECORD_TYPE, '' AS SPLIT_LOG_ID, - -- 거래명세서 존재 여부 + -- 거래명세서 존재 여부 (LinkedProjectObjids에 해당 프로젝트 OBJID 포함 여부) CASE WHEN EXISTS( - SELECT 1 FROM NSWOS100_TBL - WHERE OdOrderNo = T.PROJECT_NO + SELECT 1 FROM NSWOS100_TBL + WHERE T.OBJID::VARCHAR = ANY(STRING_TO_ARRAY(LinkedProjectObjids, ',')) ) THEN 'Y' ELSE 'N' END AS HAS_TRANSACTION_STATEMENT FROM PROJECT_MGMT AS T LEFT JOIN sales_registration SR ON T.PROJECT_NO = SR.project_no @@ -1346,7 +1340,18 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC AND T.CUSTOMER_OBJID = #{customer_objid} - AND SR.serial_no LIKE '%' || #{serialNo} || '%' + AND ( + EXISTS ( + SELECT 1 FROM CONTRACT_ITEM CI + JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID + WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID + AND CI.PART_OBJID = T.PART_OBJID + AND CI.STATUS = 'ACTIVE' + AND UPPER(CIS.STATUS) = 'ACTIVE' + AND UPPER(CIS.SERIAL_NO) LIKE UPPER('%' || #{serialNo} || '%') + ) + OR SR.serial_no LIKE '%' || #{serialNo} || '%' + ) AND EXISTS (SELECT 1 FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID AND CM.PO_NO LIKE '%' || #{poNo} || '%') @@ -1550,19 +1555,17 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID) AS PAYMENT_TYPE, T.PART_NO AS PRODUCT_NO, T.PART_NAME AS PRODUCT_NAME, - -- S/N: 해당 품목의 시리얼 번호 (여러 개일 경우 "S/N 외 N건" 형식) - (SELECT - CASE - WHEN COUNT(*) = 0 THEN '' - WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO) - ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건' - END - FROM CONTRACT_ITEM CI - LEFT JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID AND UPPER(CIS.STATUS) = 'ACTIVE' - WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID - AND CI.PART_OBJID = T.PART_OBJID - AND CI.STATUS = 'ACTIVE' - AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO, + -- S/N: CONTRACT_ITEM_SERIAL(마스터) 우선, 전체 콤마 리스트 (판매등록 폼 파싱용) + COALESCE( + (SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO) + FROM CONTRACT_ITEM CI + LEFT JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID AND UPPER(CIS.STATUS) = 'ACTIVE' + WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID + AND CI.PART_OBJID = T.PART_OBJID + AND CI.STATUS = 'ACTIVE' + AND CIS.SERIAL_NO IS NOT NULL), + SR.serial_no + ) AS SERIAL_NO, COALESCE(T.QUANTITY::numeric, 0) AS ORDER_QUANTITY, -- 요청납기: CONTRACT_ITEM 우선, 없으면 PROJECT_MGMT, 없으면 CONTRACT_MGMT COALESCE( @@ -1648,8 +1651,8 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC CODE_NAME(CM.CONTRACT_CURRENCY) AS SALES_CURRENCY_NAME, COALESCE(CM.EXCHANGE_RATE::NUMERIC, 0) AS SALES_EXCHANGE_RATE, - -- 수주 날짜 - VARCHAR 타입이므로 그대로 사용 - CM.ORDER_DATE AS SHIPPING_DATE, + -- 출하일 기본값: 오늘 날짜 + TO_CHAR(CURRENT_DATE, 'YYYY-MM-DD') AS SHIPPING_DATE, -- 담당자 CM.PM_USER_ID AS MANAGER @@ -1662,7 +1665,6 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC CM.OBJID, CM.CONTRACT_CURRENCY, CM.EXCHANGE_RATE, - CM.ORDER_DATE, CM.PM_USER_ID @@ -1696,24 +1698,35 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC CODE_NAME(CM.CONTRACT_CURRENCY) AS SALES_CURRENCY_NAME, COALESCE(NULLIF(CM.EXCHANGE_RATE, '')::NUMERIC, 0) AS SALES_EXCHANGE_RATE, - -- 수주 날짜 - VARCHAR 타입이므로 그대로 사용 - CM.ORDER_DATE AS SHIPPING_DATE, - + -- 출하일 기본값: 오늘 날짜 + TO_CHAR(CURRENT_DATE, 'YYYY-MM-DD') AS SHIPPING_DATE, + -- 담당자 - CM.PM_USER_ID AS MANAGER - + CM.PM_USER_ID AS MANAGER, + + -- 기존 S/N (CONTRACT_ITEM_SERIAL 마스터에서 조회) + COALESCE(( + SELECT STRING_AGG(CIS2.SERIAL_NO, ',' ORDER BY CIS2.SEQ) + FROM CONTRACT_ITEM CI2 + JOIN CONTRACT_ITEM_SERIAL CIS2 ON CI2.OBJID = CIS2.ITEM_OBJID AND CIS2.STATUS = 'ACTIVE' + WHERE CI2.CONTRACT_OBJID = PM.CONTRACT_OBJID + AND CI2.PART_OBJID = PM.PART_OBJID + AND CI2.STATUS = 'ACTIVE' + ), '') AS SERIAL_NO + FROM PROJECT_MGMT PM INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID LEFT JOIN CONTRACT_ITEM CI ON CM.OBJID::VARCHAR = CI.CONTRACT_OBJID AND UPPER(CI.STATUS) = 'ACTIVE' WHERE PM.PROJECT_NO = #{orderNo} - GROUP BY + GROUP BY CM.CONTRACT_NO, CM.OBJID, CM.CONTRACT_CURRENCY, CM.EXCHANGE_RATE, - CM.ORDER_DATE, CM.PM_USER_ID, - PM.QUANTITY + PM.QUANTITY, + PM.CONTRACT_OBJID, + PM.PART_OBJID @@ -1932,19 +1969,98 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC - + + + + + + + /* salesNcollectMgmt.updateShipmentLog - shipment_log 수정 */ + UPDATE shipment_log SET + split_quantity = #{salesQuantity}::integer, + shipping_status = #{shippingOrderStatus} + + , shipping_date = TO_DATE(#{shippingDate}, 'YYYY-MM-DD') + + + , shipping_method = #{shippingMethod} + + + , serial_no = #{serialNo} + + + , sales_unit_price = #{salesUnitPrice}::numeric + + + , sales_supply_price = #{salesSupplyPrice}::numeric + + + , sales_vat = #{salesVat}::numeric + + + , sales_total_amount = #{salesTotalAmount}::numeric + + + , sales_currency = #{salesCurrency} + + + , sales_exchange_rate = #{salesExchangeRate}::numeric + + + , manager_user_id = #{managerUserId} + + + , incoterms = #{incoterms} + + WHERE log_id = #{logId}::integer + + - + /* salesNcollectMgmt.saveTransactionStatement - 거래명세서 저장 */ INSERT INTO NSWOS100_TBL ( @@ -1995,6 +2111,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC ,IsQty /* 납품수량 */ ,IsPrice /* 납품단가 */ ,IsAmount /* 납품금액 */ + ,LinkedProjectObjids /* 연결된 프로젝트 OBJID 목록 */ ) VALUES ( #{suVndCd} /* 업체코드 */ ,#{issueDt} /* 작성일자 */ @@ -2011,6 +2128,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC ,COALESCE(#{isQty}, 0)::integer /* 납품수량 */ ,COALESCE(#{isPrice}, 0)::numeric /* 납품단가 */ ,COALESCE(#{isAmount}, 0)::numeric /* 납품금액 */ + ,#{linkedProjectObjids} /* 연결된 프로젝트 OBJID 목록 */ ) ON CONFLICT (SuVndCd, IssueDt, IssueNo, IsNo) DO UPDATE SET ProdCd = COALESCE(#{prodCd}, '') @@ -2024,6 +2142,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC ,IsQty = COALESCE(#{isQty}, 0)::integer ,IsPrice = COALESCE(#{isPrice}, 0)::numeric ,IsAmount = COALESCE(#{isAmount}, 0)::numeric + ,LinkedProjectObjids = #{linkedProjectObjids} @@ -2051,7 +2170,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC @@ -2142,6 +2262,102 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC LOADING_DATE = #{loadingDate} WHERE OBJID::VARCHAR = #{OBJID} - + + + + + + + + + + + + /* salesNcollectMgmt.updateSlipInfo - 전표 연동 정보 저장 */ + UPDATE PROJECT_MGMT + SET + SALES_STATUS = '완료', + SALES_DEADLINE_DATE = #{deadlineDate}, + SALES_SLIP_DATE = #{slipDate}, + SALES_SLIP_MENU_SQ = #{slipMenuSq} + WHERE OBJID::VARCHAR = #{OBJID} + + diff --git a/WebContent/WEB-INF/view/contractMgmt/estimateList_new.jsp b/WebContent/WEB-INF/view/contractMgmt/estimateList_new.jsp index c9dba45..1dba40b 100644 --- a/WebContent/WEB-INF/view/contractMgmt/estimateList_new.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/estimateList_new.jsp @@ -467,7 +467,8 @@ var columns = [ }, cellClick:function(e, cell){ var serialNo = fnc_checkNull(cell.getData().SERIAL_NO); - fn_showSerialNoPopup(serialNo); + var contractObjId = fnc_checkNull(cell.getData().OBJID); + fn_showSerialNoPopup(serialNo, contractObjId); } }, // 17. 품번 @@ -784,29 +785,49 @@ function fn_openEstimateTemplate(objId, templateType){ } // S/N 목록 팝업 표시 -function fn_showSerialNoPopup(serialNoString){ +function fn_showSerialNoPopup(serialNoString, contractObjId){ if(!serialNoString || serialNoString === ''){ Swal.fire("S/N 정보가 없습니다."); return; } - // 쉼표로 구분된 S/N을 배열로 변환 - var serialNumbers = serialNoString.split(',').map(function(sn){ return sn.trim(); }); - - // HTML 리스트 생성 + // "외 N건" 형식이면 서버에서 전체 S/N 조회 + if(serialNoString.indexOf('외') > -1 && serialNoString.indexOf('건') > -1 && contractObjId){ + $.ajax({ + url: '/contractMgmt/getAllSerialNumbers.do', + type: 'POST', + data: { contractObjId: contractObjId }, + dataType: 'json', + success: function(response){ + if(response.result === 'success' && response.serialNumbers && response.serialNumbers.length > 0){ + fn_displaySerialNoList(response.serialNumbers); + } else { + fn_displaySerialNoList([serialNoString]); + } + }, + error: function(){ + fn_displaySerialNoList([serialNoString]); + } + }); + } else { + var serialNumbers = serialNoString.split(',').map(function(sn){ return sn.trim(); }).filter(function(sn){ return sn !== ''; }); + fn_displaySerialNoList(serialNumbers); + } +} + +// S/N 리스트 팝업 표시 (공통) +function fn_displaySerialNoList(serialNumbers){ var listHtml = '
'; listHtml += '
    '; - serialNumbers.forEach(function(sn, index){ + serialNumbers.forEach(function(sn){ listHtml += '
  1. ' + sn + '
  2. '; }); listHtml += '
'; listHtml += '
'; - // SweetAlert2로 팝업 표시 Swal.fire({ title: 'S/N 목록', html: listHtml, - icon: 'info', width: 500, confirmButtonText: '확인', confirmButtonColor: '#3085d6' diff --git a/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp b/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp index f908135..571cc21 100644 --- a/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/estimateRegistFormPopup.jsp @@ -288,6 +288,13 @@ } } + // 결재여부 체크박스 토글 (단일 선택) + function fn_toggleApprovalRequired(clicked) { + $("input[name='approval_required_chk']").prop("checked", false); + $(clicked).prop("checked", true); + $("#approval_required").val($(clicked).val()); + } + function fn_save() { if (fnc_valitate("form1")) { // 품목 유효성 검사 @@ -1990,6 +1997,25 @@ + + + + + + + + + + diff --git a/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp b/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp index 64366ec..cac118e 100644 --- a/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp @@ -355,7 +355,8 @@ var columns = [ }, cellClick:function(e, cell){ var serialNo = fnc_checkNull(cell.getData().SERIAL_NO); - fn_showSerialNoPopup(serialNo); + var contractObjId = fnc_checkNull(cell.getData().OBJID); + fn_showSerialNoPopup(serialNo, contractObjId); } }, // 21. 품번 @@ -657,29 +658,49 @@ function fn_openEstimateTemplate(objId, templateType){ } // S/N 목록 팝업 표시 -function fn_showSerialNoPopup(serialNoString){ +function fn_showSerialNoPopup(serialNoString, contractObjId){ if(!serialNoString || serialNoString === ''){ Swal.fire("S/N 정보가 없습니다."); return; } - // 쉼표로 구분된 S/N을 배열로 변환 - var serialNumbers = serialNoString.split(',').map(function(sn){ return sn.trim(); }); - - // HTML 리스트 생성 + // "외 N건" 형식이면 서버에서 전체 S/N 조회 + if(serialNoString.indexOf('외') > -1 && serialNoString.indexOf('건') > -1 && contractObjId){ + $.ajax({ + url: '/contractMgmt/getAllSerialNumbers.do', + type: 'POST', + data: { contractObjId: contractObjId }, + dataType: 'json', + success: function(response){ + if(response.result === 'success' && response.serialNumbers && response.serialNumbers.length > 0){ + fn_displaySerialNoList(response.serialNumbers); + } else { + fn_displaySerialNoList([serialNoString]); + } + }, + error: function(){ + fn_displaySerialNoList([serialNoString]); + } + }); + } else { + var serialNumbers = serialNoString.split(',').map(function(sn){ return sn.trim(); }).filter(function(sn){ return sn !== ''; }); + fn_displaySerialNoList(serialNumbers); + } +} + +// S/N 리스트 팝업 표시 (공통) +function fn_displaySerialNoList(serialNumbers){ var listHtml = '
'; listHtml += '
    '; - serialNumbers.forEach(function(sn, index){ + serialNumbers.forEach(function(sn){ listHtml += '
  1. ' + sn + '
  2. '; }); listHtml += '
'; listHtml += '
'; - // SweetAlert2로 팝업 표시 Swal.fire({ title: 'S/N 목록', html: listHtml, - icon: 'info', width: 500, confirmButtonText: '확인', confirmButtonColor: '#3085d6' diff --git a/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp b/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp index 224b40c..67184fe 100644 --- a/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp +++ b/WebContent/WEB-INF/view/productionplanning/mBomPopupLeft.jsp @@ -957,6 +957,9 @@ function fn_initGrid() { function fn_preprocessBomData(dataList) { if(!dataList || dataList.length === 0) return dataList; + // 레벨별 항목수량 추적 (제작수량 누적 곱 계산용) + var parentItemQtyByLevel = {}; + dataList.forEach(function(row) { // 필드명 정규화 (소문자 → 대문자 복사, 기존 대문자 유지) if(row.part_unit_qty !== undefined && row.PART_UNIT_QTY === undefined) { @@ -985,13 +988,27 @@ function fn_initGrid() { console.log("전처리 - PART_NO:", row.PART_NO, "소재품번:", row.RAW_MATERIAL_NO, "소재소요량(DB):", savedRequiredQty, "소재소요량(최종):", row.REQUIRED_QTY); - // 제작수량: 저장된 값이 있으면 유지, 없으면 항목수량 × 총생산수량으로 자동계산 + // 제작수량: 상위 항목수량을 누적 곱하여 계산 + var level = parseInt(row.LEVEL) || 1; + var itemQty = parseFloat(row.ITEM_QTY || row.item_qty) || 0; + + // 현재 레벨의 항목수량 저장 (하위 레벨 계산에 사용) + parentItemQtyByLevel[level] = itemQty; + // 현재 레벨보다 깊은 레벨 데이터 제거 (형제 노드 전환 시 오염 방지) + for(var l = level + 1; l <= _maxLevel; l++) { + delete parentItemQtyByLevel[l]; + } + var savedProdQty = parseFloat(row.PRODUCTION_QTY) || 0; if(savedProdQty > 0) { row.PRODUCTION_QTY = savedProdQty; } else { - var itemQty = parseFloat(row.ITEM_QTY || row.item_qty) || 0; - row.PRODUCTION_QTY = itemQty * totalProductionQty; + // 최상위(1)부터 현재 레벨까지 항목수량 누적 곱 × 총생산수량 + var cumulativeItemQty = 1; + for(var l = 1; l <= level; l++) { + cumulativeItemQty *= (parentItemQtyByLevel[l] || 1); + } + row.PRODUCTION_QTY = cumulativeItemQty * totalProductionQty; } // 소재발주수량: 저장된 값이 있으면 유지, 없으면 계산 diff --git a/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp b/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp index 129c0d1..302a40e 100644 --- a/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp +++ b/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp @@ -144,26 +144,15 @@ $(document).ready(function(){ fn_search(); }); -// 프로젝트별 파트 목록 캐시 -var _PART_LIST_CACHE = {}; - -// 프로젝트번호로 MBOM 파트 목록 조회 +// 프로젝트번호로 MBOM 파트 목록 조회 (미선택 시 전체 조회) function fn_getPartListByProject(projectNo) { - if (!projectNo) return [{"CODE": "", "NAME": "선택"}]; + var param = {"sqlId": "common.getMbomPartListByProjectNo"}; + if (projectNo) param.PROJECT_NO = projectNo; - // 캐시에 있으면 캐시에서 반환 - if (_PART_LIST_CACHE[projectNo]) { - return _PART_LIST_CACHE[projectNo]; - } - - // 서버에서 조회 var partList = [{"CODE": "", "NAME": "선택"}].concat( - fnc_getJsonAllDataListBySqlId({"sqlId": "common.getMbomPartListByProjectNo", "PROJECT_NO": projectNo}) + fnc_getJsonAllDataListBySqlId(param) ); - // 캐시에 저장 - _PART_LIST_CACHE[projectNo] = partList; - return partList; } @@ -207,30 +196,32 @@ function fn_select2Editor(cell, onRendered, success, cancel, editorParams) { $(select).select2("open"); }); - var isCleared = false; + var isCompleted = false; $(select).on("select2:select", function(e) { + if(isCompleted) return; + isCompleted = true; var selectedVal = $(select).val() || ""; - if(typeof editorParams.onSelect === "function") { - editorParams.onSelect(cell, selectedVal); - } + try { $(select).select2("destroy"); } catch(e) {} success(selectedVal); }); $(select).on("select2:clear", function(e) { - isCleared = true; - if(typeof editorParams.onSelect === "function") { - editorParams.onSelect(cell, ""); - } + if(isCompleted) return; + isCompleted = true; + var $sel = $(select); setTimeout(function() { - $(select).select2("close"); + try { $sel.select2("destroy"); } catch(e) {} success(""); - }, 0); + }, 50); }); $(select).on("select2:close", function() { - if(isCleared) return; - success($(select).val() || ""); + if(isCompleted) return; + isCompleted = true; + var val = $(select).val() || ""; + try { $(select).select2("destroy"); } catch(e) {} + success(val); }); return container; @@ -270,21 +261,7 @@ function fn_search(){ editor: fn_select2Editor, editorParams: { valueId: "CODE", labelId: "NAME", values: _PROJECT_LIST, - placeholder: "프로젝트 검색...", - onSelect: function(cell, selectedValue) { - var productName = ""; - for(var i = 0; i < _PROJECT_LIST.length; i++) { - if(_PROJECT_LIST[i].CODE == selectedValue) { - productName = _PROJECT_LIST[i].PRODUCT_NAME || ""; - break; - } - } - if(selectedValue) fn_getPartListByProject(selectedValue); - cell.getRow().update({ - "PART_OBJID": "", "PART_NO": "", "PART_NAME": "", - "PRODUCT_NAME": productName - }); - } + placeholder: "프로젝트 검색..." }, formatter: function(cell) { return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_PROJECT_LIST}); @@ -412,11 +389,28 @@ function fn_search(){ var row = cell.getRow(); var field = cell.getField(); + // 프로젝트 변경 시 제품구분 설정 + 파트 초기화 + if (field === 'PROJECT_OBJID') { + var projectObjid = cell.getValue() || ""; + var productName = ""; + for(var i = 0; i < _PROJECT_LIST.length; i++) { + if(_PROJECT_LIST[i].CODE == projectObjid) { + productName = _PROJECT_LIST[i].PRODUCT_NAME || ""; + break; + } + } + fn_getPartListByProject(projectObjid); + row.update({ + "PART_OBJID": "", "PART_NO": "", "PART_NAME": "", + "PRODUCT_NAME": productName + }); + } + // 파트 선택 시 품번/품명 자동 설정 if (field === 'PART_OBJID') { var partObjid = cell.getValue(); var projectObjid = row.getData().PROJECT_OBJID; - if (partObjid && projectObjid) { + if (partObjid) { var partList = fn_getPartListByProject(projectObjid); for (var i = 0; i < partList.length; i++) { if (partList[i].CODE == partObjid) { diff --git a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/projectDetailView.jsp b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/projectDetailView.jsp index ff1d88c..465295e 100644 --- a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/projectDetailView.jsp +++ b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/projectDetailView.jsp @@ -39,7 +39,7 @@ background: #f9f9f9; font-weight: bold; text-align: center; - width: 120px; + width: 70px; } .item-table { width: 100%; diff --git a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/revenueMgmtList.jsp b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/revenueMgmtList.jsp index 037f207..a291ed1 100644 --- a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/revenueMgmtList.jsp +++ b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/revenueMgmtList.jsp @@ -78,10 +78,10 @@ return false; } - // 선택된 OBJID 목록 - var objIdList = []; + // 선택된 LOG_ID 목록 + var logIdList = []; for(var i = 0; i < targetObj.length; i++){ - objIdList.push(fnc_checkNull(targetObj[i].OBJID)); + logIdList.push(fnc_checkNull(targetObj[i].LOG_ID)); } // 단건 선택 시 기존 마감정보 불러오기 @@ -164,7 +164,7 @@ url: "/revenueMgmt/saveDeadlineInfo.do", type: "POST", data: { - "objIdList": objIdList.join(','), + "logIdList": logIdList.join(','), "taxType": formData.taxType, "taxInvoiceDate": formData.taxInvoiceDate, "exportDeclNo": formData.exportDeclNo, @@ -286,17 +286,17 @@ }).then(function(result) { if (result.isConfirmed) { var deadlineDate = result.value; - var objIdList = []; + var logIdList = []; for(var i = 0; i < targetObj.length; i++){ - objIdList.push(fnc_checkNull(targetObj[i].OBJID)); + logIdList.push(fnc_checkNull(targetObj[i].LOG_ID)); } $.ajax({ url: "/salesNcollectMgmt/salesDeadlineConfirm.do", type: "POST", data: { - "objIdList": objIdList.join(','), + "logIdList": logIdList.join(','), "deadlineDate": deadlineDate }, dataType: "json", @@ -332,7 +332,13 @@ var columns = [ // 컬럼 순서: 프로젝트번호, 주문유형, 매출마감, 발주일, 발주번호, 고객사, 제품구분, 품명, 수량, 단가, 공급가액, 부가세, 총액, 원화총액, 출하일, 국내/해외, 환종, 환율, S/N, 품번 {formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:40, frozen:true}, // 1. 프로젝트번호 - {headerHozAlign : 'center', hozAlign : 'center', width : '130', title : '프로젝트번호', field : 'PROJECT_NO', frozen : true}, + {headerHozAlign : 'center', hozAlign : 'center', width : '130', title : '프로젝트번호', field : 'PROJECT_NO', frozen : true, + formatter: fnc_createGridAnchorTag, + cellClick: function(e, cell){ + var orderNo = cell.getData().PROJECT_NO; + fn_openSaleRegPopup(orderNo, "detail"); + } + }, // 2. 주문유형 {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '주문유형', field : 'ORDER_TYPE'}, // 3. 매출마감 @@ -605,6 +611,13 @@ function fn_excel() { return false; } +function fn_openSaleRegPopup(orderNo, saleNo){ + var popup_width = 850; + var popup_height = 520; + var url = "/salesMgmt/salesRegForm.do?orderNo=" + encodeURIComponent(orderNo) + "&saleNo=" + (saleNo ? encodeURIComponent(saleNo) : ""); + fn_centerPopup(popup_width, popup_height, url); +} + function fn_FileRegist(objId, docType, docTypeName){ var popup_width = 800; var popup_height = 680; @@ -624,7 +637,7 @@ function fn_FileRegist(objId, docType, docTypeName){
- + - +

- 판매 등록 (주문번호: ${param.orderNo}) + + + 출하 수정 (주문번호: ${param.orderNo}) + 판매 등록 (주문번호: ${param.orderNo}) + +

diff --git a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/shippingDetailPopup.jsp b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/shippingDetailPopup.jsp index 594190d..3dafa70 100644 --- a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/shippingDetailPopup.jsp +++ b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/shippingDetailPopup.jsp @@ -13,6 +13,7 @@ body { margin: 0; padding: 20px; font-family: 'Malgun Gothic', sans-serif; + width: auto !important; } .popup-header { font-size: 18px; @@ -38,6 +39,15 @@ body { border: 1px solid #ddd; text-align: center; } +.shipping-date-link { + color: #2196F3; + text-decoration: underline; + cursor: pointer; +} +.shipping-date-link:hover { + color: #1565C0; + font-weight: bold; +} .btn-close { padding: 8px 20px; background-color: #666; @@ -54,6 +64,24 @@ body { margin-top: 20px; } +