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 += '- ' + sn + '
';
});
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 += '- ' + sn + '
';
});
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){