diff --git a/WebContent/WEB-INF/classes/com/pms/mapper/common.xml b/WebContent/WEB-INF/classes/com/pms/mapper/common.xml index fb01425..d718536 100644 --- a/WebContent/WEB-INF/classes/com/pms/mapper/common.xml +++ b/WebContent/WEB-INF/classes/com/pms/mapper/common.xml @@ -3205,4 +3205,32 @@ SELECT option_objid::VARCHAR AS CODE WHERE USER_ID = #{userId} AND MASTER_OBJID::varchar = #{masterObjid} + + + \ No newline at end of file diff --git a/WebContent/WEB-INF/classes/com/pms/salesmgmt/mapper/contractMgmt.xml b/WebContent/WEB-INF/classes/com/pms/salesmgmt/mapper/contractMgmt.xml index d512aad..d9544f4 100644 --- a/WebContent/WEB-INF/classes/com/pms/salesmgmt/mapper/contractMgmt.xml +++ b/WebContent/WEB-INF/classes/com/pms/salesmgmt/mapper/contractMgmt.xml @@ -790,6 +790,102 @@ ORDER BY REGDATE DESC + + + @@ -3935,6 +4038,12 @@ ORDER BY ASM.SUPPLY_NAME ET.TOTAL_AMOUNT_KRW, ET.MANAGER_NAME, ET.MANAGER_CONTACT, + ET.PART_NAME, + ET.PART_OBJID, + ET.NOTES_CONTENT, + ET.VALIDITY_PERIOD, + ET.CATEGORIES_JSON, + ET.GROUP1_SUBTOTAL, ET.WRITER, ET.REGDATE, ET.CHG_USER_ID, @@ -3960,12 +4069,19 @@ ORDER BY ASM.SUPPLY_NAME ESTIMATE_TEMPLATE ET LEFT JOIN CONTRACT_MGMT CM ON ET.CONTRACT_OBJID = CM.OBJID WHERE - ET.CONTRACT_OBJID = #{objId} - - AND ET.TEMPLATE_TYPE = #{template_type} - - ORDER BY ET.REGDATE DESC - LIMIT 1 + + + ET.OBJID = #{templateObjId} + + + ET.CONTRACT_OBJID = #{objId} + + AND ET.TEMPLATE_TYPE = #{template_type} + + ORDER BY ET.REGDATE DESC + LIMIT 1 + + @@ -3991,6 +4107,13 @@ ORDER BY ASM.SUPPLY_NAME ET.TOTAL_AMOUNT_KRW, ET.MANAGER_NAME, ET.MANAGER_CONTACT, + ET.SHOW_TOTAL_ROW, + ET.PART_NAME, + ET.PART_OBJID, + ET.NOTES_CONTENT, + ET.VALIDITY_PERIOD, + ET.CATEGORIES_JSON, + ET.GROUP1_SUBTOTAL, ET.WRITER, TO_CHAR(ET.REGDATE, 'YYYY-MM-DD HH24:MI') AS REGDATE, ET.CHG_USER_ID, @@ -4069,6 +4192,30 @@ ORDER BY ASM.SUPPLY_NAME ORDER BY SEQ + + + INSERT INTO ESTIMATE_TEMPLATE ( @@ -4092,6 +4239,7 @@ ORDER BY ASM.SUPPLY_NAME TOTAL_AMOUNT_KRW, MANAGER_NAME, MANAGER_CONTACT, + SHOW_TOTAL_ROW, WRITER, REGDATE, CHG_USER_ID, @@ -4117,6 +4265,7 @@ ORDER BY ASM.SUPPLY_NAME #{total_amount_krw}, #{manager_name}, #{manager_contact}, + #{show_total_row}, #{writer}, NOW(), #{chg_user_id}, @@ -4145,6 +4294,7 @@ ORDER BY ASM.SUPPLY_NAME TOTAL_AMOUNT_KRW = #{total_amount_krw}, MANAGER_NAME = #{manager_name}, MANAGER_CONTACT = #{manager_contact}, + SHOW_TOTAL_ROW = #{show_total_row}, CHG_USER_ID = #{chg_user_id}, CHGDATE = NOW() WHERE @@ -4202,6 +4352,67 @@ WHERE OBJID = #{template_objid} + + + INSERT INTO ESTIMATE_TEMPLATE ( + OBJID, + CONTRACT_OBJID, + TEMPLATE_TYPE, + EXECUTOR_DATE, + RECIPIENT, + PART_NAME, + PART_OBJID, + NOTES_CONTENT, + VALIDITY_PERIOD, + CATEGORIES_JSON, + GROUP1_SUBTOTAL, + TOTAL_AMOUNT, + TOTAL_AMOUNT_KRW, + WRITER, + REGDATE, + CHG_USER_ID, + CHGDATE + ) VALUES ( + #{template_objid}, + #{contract_objid}, + '2', + #{executor_date}, + #{recipient}, + #{part_name}, + #{part_objid}, + #{notes_content}, + #{validity_period}, + #{categories_json}, + #{group1_subtotal}, + #{total_amount}, + #{total_amount_krw}, + #{writer}, + NOW(), + #{chg_user_id}, + NOW() + ) + + + + + UPDATE ESTIMATE_TEMPLATE + SET + EXECUTOR_DATE = #{executor_date}, + RECIPIENT = #{recipient}, + PART_NAME = #{part_name}, + PART_OBJID = #{part_objid}, + NOTES_CONTENT = #{notes_content}, + VALIDITY_PERIOD = #{validity_period}, + CATEGORIES_JSON = #{categories_json}, + GROUP1_SUBTOTAL = #{group1_subtotal}, + TOTAL_AMOUNT = #{total_amount}, + TOTAL_AMOUNT_KRW = #{total_amount_krw}, + CHG_USER_ID = #{chg_user_id}, + CHGDATE = NOW() + WHERE + OBJID = #{template_objid} + + + + + + /* salesNcollectMgmt.getTotalSalesQuantity - project_no로 시작하는 모든 레코드의 판매 수량 합계 */ + SELECT COALESCE(SUM(sales_quantity), 0) as total + FROM sales_registration + WHERE project_no LIKE #{orderNo} || '%' + + + + + + + + /* salesNcollectMgmt.deleteSaleRegistration - sales_registration 삭제 */ + DELETE FROM sales_registration + WHERE project_no = #{orderNo} + + + + + /* salesNcollectMgmt.updateSaleRegistration - sales_registration 업데이트 */ + UPDATE sales_registration + SET + shipping_order_status = + + #{shippingOrderStatus}, + + + '', + + + serial_no = #{serialNo}, + sales_quantity = #{salesQuantity}::integer, + 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, + shipping_date = + + TO_DATE(#{shippingDate}, 'YYYY-MM-DD'), + + + NULL, + + + shipping_method = #{shippingMethod}, + manager_user_id = #{manager}, + incoterms = #{incoterms}, + upd_date = NOW(), + upd_user_id = #{cretEmpNo} + WHERE project_no = #{orderNo} + + + + + + + + + + /* salesNcollectMgmt.insertShipmentLog - 분할 출하 기록 저장 */ + INSERT INTO shipment_log ( + target_objid, log_type, log_message, split_quantity, original_quantity, + remaining_quantity, shipping_status, shipping_date, shipping_method, + sales_unit_price, sales_supply_price, sales_vat, sales_total_amount, + sales_currency, sales_exchange_rate, manager_user_id, incoterms, + serial_no, parent_sale_no, reg_user_id + ) VALUES ( + #{targetObjid}, 'SPLIT_SHIPMENT', '분할 출하', + #{salesQuantity}::integer, #{originalQuantity}::integer, #{remainingQuantity}::integer, + #{shippingOrderStatus}, + + + TO_DATE(#{shippingDate}, 'YYYY-MM-DD'), + + NULL, + + #{shippingMethod}, #{salesUnitPrice}::numeric, #{salesSupplyPrice}::numeric, + #{salesVat}::numeric, #{salesTotalAmount}::numeric, #{salesCurrency}, + #{salesExchangeRate}::numeric, #{manager}, #{incoterms}, #{serialNo}, + #{parentSaleNo}::integer, #{cretEmpNo} + ) + + + + + + + + diff --git a/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp b/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp index 611b9ce..a92d4cf 100644 --- a/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp +++ b/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp @@ -24,6 +24,11 @@ $(document).ready(function(){ //날짜 _fnc_datepick(); + // 그리드 높이 동적 계산 (Total 합계 영역 + 여유 공간 80px) + fnc_calculateContentHeight("gridDiv", 80); + $(window).resize(function() { + fnc_calculateContentHeight("gridDiv", 80); + }); $('.select2').select2(); @@ -96,14 +101,14 @@ $(document).ready(function(){ }); var columns = [ - {formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:40, frozen:true}, - {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '영업번호', field : 'CONTRACT_NO', frozen:true, - formatter:fnc_createGridAnchorTag, - cellClick:function(e, cell){ - var objid = fnc_checkNull(cell.getData().OBJID); - fn_projectConceptDetail(objid); - } - }, + // rowSelection 제거 - fnc_tabul_search의 showCheck 파라미터로 자동 추가됨 + {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '영업번호', field : 'CONTRACT_NO', frozen:true, + formatter:fnc_createGridAnchorTag, + cellClick:function(e, cell){ + var objid = fnc_checkNull(cell.getData().OBJID); + fn_projectConceptDetail(objid); + } + }, {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '주문유형', field : 'CATEGORY_NAME' }, {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주일', field : 'ORDER_DATE' }, {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주번호', field : 'PO_NO' }, @@ -182,64 +187,49 @@ var columns = [ //var grid; function fn_search(){ - // 그리드 조회 및 Total 합계 업데이트를 위한 커스텀 AJAX - $.ajax({ - url: "/contractMgmt/contractGridList.do", - type: "POST", - data: $("#form1").serializeObject(), - dataType: "json", - beforeSend: function(){ - _startLoading("Loading..."); - }, - complete: function(){ - _endLoading(); - }, - success: function(response) { - // 그리드 데이터 설정 - if(_tabulGrid){ - _tabulGrid.setData(response.RESULTLIST || []); - } else { - // 그리드 초기화 - _tabulGrid = new Tabulator("#mainGrid", { - layout: _tabul_layout_fitColumns, - columns: columns, - data: response.RESULTLIST || [], - selectable: true - }); - } - - // 조회된 전체 데이터의 합계 계산 - var totalSupplyPrice = 0; - var totalVat = 0; - var totalAmount = 0; - - if(response.RESULTLIST && response.RESULTLIST.length > 0) { - response.RESULTLIST.forEach(function(row) { - var supplyPrice = parseFloat(row.ORDER_SUPPLY_PRICE_SUM || 0); - var vat = parseFloat(row.ORDER_VAT_SUM || 0); - var amount = parseFloat(row.ORDER_TOTAL_AMOUNT_SUM || 0); - - totalSupplyPrice += supplyPrice; - totalVat += vat; - totalAmount += amount; - }); - } - - // 합계 표시 - $("#totalSupplyPrice").text(Number(totalSupplyPrice).toLocaleString()); - $("#totalVat").text(Number(totalVat).toLocaleString()); - $("#totalAmount").text(Number(totalAmount).toLocaleString()); - - // 페이징 HTML 업데이트 - if(response.PAGE_HTML){ - $(".table_paging_wrap").html(response.PAGE_HTML); - } - }, - error: function(jqxhr, status, error){ - alert("데이터 조회 중 오류가 발생했습니다."); - console.error(error); - } - }); + // fnc_tabul_search로 페이징 처리 + _tabulGrid = fnc_tabul_search( + _tabul_layout_fitColumns, + _tabulGrid, + "/contractMgmt/contractGridList.do", + columns, + true + ); + + // 데이터 렌더링 완료 후 합계 계산 (한 번만 실행) + if(_tabulGrid) { + // 기존 이벤트 제거 후 재등록 + _tabulGrid.off("renderComplete"); + _tabulGrid.on("renderComplete", function(){ + fn_calculateTotalFromGrid(); + }); + } +} + +// 그리드에 표시된 데이터의 원화총액 합계 계산 +function fn_calculateTotalFromGrid(){ + if(!_tabulGrid) { + console.log("⚠️ [주문서관리] 그리드가 초기화되지 않음"); + $("#totalAmount").text("0"); + return; + } + + // 현재 그리드에 표시된 데이터만 가져오기 + var data = _tabulGrid.getData(); + var totalAmountKRW = 0; + + console.log("🔍 [주문서관리] 표시된 데이터 개수:", data.length); + + if(data.length > 0) { + // ORDER_TOTAL_AMOUNT_KRW 합산 + data.forEach(function(row) { + var amountKRW = parseFloat(row.ORDER_TOTAL_AMOUNT_KRW || 0); + totalAmountKRW += amountKRW; + }); + } + + console.log("✅ [주문서관리] 표시된 데이터 합계:", totalAmountKRW); + $("#totalAmount").text(Number(totalAmountKRW).toLocaleString()); } function _fnc_datepick(){ @@ -716,23 +706,17 @@ function openProjectFormPopUp(objId){ - - - - -
- - Total 공급가액: 0 원 - - - Total 부가세: 0 원 - - - Total 총액: 0 원 - -
- - <%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %> + + + + +
+ + 수주 금액 : 0 원 + +
+ + <%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %> diff --git a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesMgmtList.jsp b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesMgmtList.jsp index f32ef17..3def3ef 100644 --- a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesMgmtList.jsp +++ b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesMgmtList.jsp @@ -53,6 +53,11 @@ $("#btnBulkRegister").click(function(){ fn_bulkRegister(); }); + + // 거래명세서 출력 버튼 + $("#btnTransactionStatement").click(function(){ + fn_printTransactionStatement(); + }); }); // 날짜 선택기 초기화 함수 @@ -125,6 +130,39 @@ fn_centerPopup(popup_width, popup_height, url); } + // 그리드 데이터를 전달하는 판매등록 팝업 + function fn_openSaleRegPopupWithData(rowData){ + console.log("=== fn_openSaleRegPopupWithData 호출 ==="); + console.log("rowData:", rowData); + console.log("SALES_QUANTITY:", rowData.SALES_QUANTITY); + console.log("SALES_UNIT_PRICE:", rowData.SALES_UNIT_PRICE); + console.log("SALES_SUPPLY_PRICE:", rowData.SALES_SUPPLY_PRICE); + console.log("SALES_VAT:", rowData.SALES_VAT); + console.log("SALES_TOTAL_AMOUNT:", rowData.SALES_TOTAL_AMOUNT); + console.log("SALES_CURRENCY:", rowData.SALES_CURRENCY); + console.log("SALES_EXCHANGE_RATE:", rowData.SALES_EXCHANGE_RATE); + + var popup_width = 850; + var popup_height = 550; + + // 기본 파라미터 + var params = "orderNo=" + encodeURIComponent(rowData.PROJECT_NO); + params += "&saleNo=" + (rowData.SALE_NO ? encodeURIComponent(rowData.SALE_NO) : ""); + + // 그리드에서 표시되고 있는 금액 정보 전달 + if(rowData.SALES_QUANTITY !== undefined && rowData.SALES_QUANTITY !== null) params += "&salesQuantity=" + encodeURIComponent(rowData.SALES_QUANTITY); + if(rowData.SALES_UNIT_PRICE !== undefined && rowData.SALES_UNIT_PRICE !== null) params += "&salesUnitPrice=" + encodeURIComponent(rowData.SALES_UNIT_PRICE); + if(rowData.SALES_SUPPLY_PRICE !== undefined && rowData.SALES_SUPPLY_PRICE !== null) params += "&salesSupplyPrice=" + encodeURIComponent(rowData.SALES_SUPPLY_PRICE); + if(rowData.SALES_VAT !== undefined && rowData.SALES_VAT !== null) params += "&salesVat=" + encodeURIComponent(rowData.SALES_VAT); + if(rowData.SALES_TOTAL_AMOUNT !== undefined && rowData.SALES_TOTAL_AMOUNT !== null) params += "&salesTotalAmount=" + encodeURIComponent(rowData.SALES_TOTAL_AMOUNT); + if(rowData.SALES_CURRENCY) params += "&salesCurrency=" + encodeURIComponent(rowData.SALES_CURRENCY); + if(rowData.SALES_EXCHANGE_RATE !== undefined && rowData.SALES_EXCHANGE_RATE !== null) params += "&salesExchangeRate=" + encodeURIComponent(rowData.SALES_EXCHANGE_RATE); + + var url = "/salesMgmt/salesRegForm.do?" + params; + console.log("최종 URL:", url); + fn_centerPopup(popup_width, popup_height, url); + } + function fn_FileRegist(objId, docType, docTypeName){ var popup_width = 800; var popup_height = 680; @@ -163,11 +201,39 @@ var columns = [ {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주일', field : 'ORDER_DATE'}, {headerHozAlign : 'center', hozAlign : 'center', width : '120', title : '발주번호', field : 'PO_NO'}, {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '요청납기', field : 'REQUEST_DATE'}, - {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '출하일', field : 'SHIPPING_DATE'}, + {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '출하일', field : 'SHIPPING_DATE', + cellClick: function(e, cell) { + var projectNo = cell.getRow().getData().PROJECT_NO; + if(projectNo) { + fn_openShippingDetail(projectNo); + } + } + }, {headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER'}, {headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'PRODUCT_NAME'}, + {headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '견적수량', field : 'ESTIMATE_QUANTITY', + formatter: function(cell) { + var value = cell.getValue(); + if(!value || value === '' || value === '0') return ''; + // "X 외 Y건" 형식인지 확인 + if(typeof value === 'string' && value.includes('외')) { + return value; + } + // 숫자인 경우 포맷팅 + return Number(value).toLocaleString(); + } + }, {headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '수주수량', field : 'ORDER_QUANTITY', - formatter: "money", formatterParams: {thousand: ",", symbolAfter: "", precision: false} + formatter: function(cell) { + var value = cell.getValue(); + if(!value || value === '' || value === '0') return ''; + // "X 외 Y건" 형식인지 확인 + if(typeof value === 'string' && value.includes('외')) { + return value; + } + // 숫자인 경우 포맷팅 + return Number(value).toLocaleString(); + } }, {headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '판매수량', field : 'SALES_QUANTITY', formatter: "money", formatterParams: {thousand: ",", symbolAfter: "", precision: false} @@ -294,6 +360,23 @@ function fn_search(){ }); } +// 출하일 상세 내역 팝업 +function fn_openShippingDetail(projectNo) { + console.log("=== fn_openShippingDetail 호출 ==="); + console.log("전달받은 projectNo:", projectNo); + console.log("projectNo 타입:", typeof projectNo); + + if(!projectNo) { + alert("프로젝트 번호가 없습니다."); + return; + } + + var url = "/salesMgmt/shippingDetailPopup.do?projectNo=" + encodeURIComponent(projectNo); + console.log("팝업 URL:", url); + + window.open(url, "shippingDetailPopup", "width=800,height=600,scrollbars=yes,resizable=yes"); +} + // 출하지시/판매등록 함수 (1건만 선택 가능) function fn_bulkRegister(){ if(!_tabulGrid){ @@ -318,8 +401,8 @@ function fn_bulkRegister(){ // 선택한 1건의 항목 가져오기 var selectedRow = selectedRows[0]; - // 판매등록 팝업 열기 - fn_openSaleRegPopup(selectedRow.PROJECT_NO, selectedRow.SALE_NO); + // 판매등록 팝업 열기 (그리드 데이터 전달) + fn_openSaleRegPopupWithData(selectedRow); } diff --git a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesRegForm.jsp b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesRegForm.jsp index 8b2c4db..ee2cd8c 100644 --- a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesRegForm.jsp +++ b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesRegForm.jsp @@ -19,6 +19,15 @@ var snCounter = 1; $(function() { + console.log("=== salesRegForm.jsp 로드 ==="); + console.log("SALES_QUANTITY: ${saleInfo.SALES_QUANTITY}"); + console.log("SALES_UNIT_PRICE: ${saleInfo.SALES_UNIT_PRICE}"); + console.log("SALES_SUPPLY_PRICE: ${saleInfo.SALES_SUPPLY_PRICE}"); + console.log("SALES_VAT: ${saleInfo.SALES_VAT}"); + console.log("SALES_TOTAL_AMOUNT: ${saleInfo.SALES_TOTAL_AMOUNT}"); + console.log("SALES_CURRENCY: ${saleInfo.SALES_CURRENCY}"); + console.log("SALES_EXCHANGE_RATE: ${saleInfo.SALES_EXCHANGE_RATE}"); + $('.select2').select2(); // 날짜 선택기 초기화 @@ -33,18 +42,6 @@ // 판매환종 초기값 설정 (견적환종과 동기화) initializeSalesCurrency(); - // 페이지 로드 시 금액 자동 계산 (수주 데이터가 있을 때) - setTimeout(function() { - var quantity = parseFloat($("#salesQuantity").val()) || 0; - var unitPrice = parseFloat($("#salesUnitPrice").val()) || 0; - - // 수주 데이터가 있으면 자동 계산 - if(quantity > 0 || unitPrice > 0) { - fn_calculateSupplyPrice(); - console.log("페이지 로드 시 금액 자동 계산 완료"); - } - }, 500); - // S/N 필드 클릭 이벤트 $("#serialNo").click(function() { fn_openSnManagePopup(); @@ -511,23 +508,65 @@ } console.log("=== S/N 처리 완료 ==="); - if (confirm("저장하시겠습니까?")) { + if (confirm("저장하시겠습니까?")) { + $.ajax({ + url : "/salesMgmt/saveSales.do", + type : "POST", + data : $("#form1").serialize(), + dataType : "json", + success : function(data) { + alert(data.msg); + + // 저장 후 잔량 확인을 위해 서버에 다시 조회 $.ajax({ - url : "/salesMgmt/saveSales.do", - type : "POST", - data : $("#form1").serialize(), - dataType : "json", - success : function(data) { - alert(data.msg); + url: "/salesMgmt/salesRegForm.do", + type: "GET", + data: { orderNo: "${param.orderNo}" }, + dataType: "html", + success: function(response) { + // 응답에서 SALES_QUANTITY 추출 (잔량) + var match = response.match(/SALES_QUANTITY:\s*(\d+)/); + var remainingQuantity = match ? parseInt(match[1]) : 0; + + console.log("서버에서 계산한 잔량:", remainingQuantity); + + if(remainingQuantity > 0) { + if(confirm("잔량 " + remainingQuantity + "개가 남았습니다. 계속 등록하시겠습니까?")) { + // 팝업 새로고침 (잔량으로 수량 자동 설정) + location.reload(); + } else { + // 목록 새로고침 후 팝업 닫기 + if(opener && opener.fn_search) { + opener.fn_search(); + } + self.close(); + } + } else { + // 목록 새로고침 후 팝업 닫기 + if(opener && opener.fn_search) { + opener.fn_search(); + } + self.close(); + } + }, + error: function() { + // 에러 시 그냥 팝업 닫기 if(opener && opener.fn_search) { opener.fn_search(); } self.close(); - }, - error : function(jqxhr, status, error) { - alert("저장 중 오류가 발생했습니다."); } }); + }, + error : function(jqxhr, status, error) { + console.log("=== AJAX 에러 ==="); + console.log("status:", status); + console.log("error:", error); + console.log("responseText:", jqxhr.responseText); + console.log("status code:", jqxhr.status); + alert("저장 중 오류가 발생했습니다.\n상태: " + status + "\n에러: " + error); + } + }); } } @@ -693,7 +732,7 @@ - + diff --git a/WebContent/WEB-INF/view/salesmgmt/salesMgmt/shippingDetailPopup.jsp b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/shippingDetailPopup.jsp new file mode 100644 index 0000000..594190d --- /dev/null +++ b/WebContent/WEB-INF/view/salesmgmt/salesMgmt/shippingDetailPopup.jsp @@ -0,0 +1,97 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + +출하일 상세 내역 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
출하일출하수량출하지시상태S/N
출하 내역이 없습니다.
${item.shipping_date}${item.shipping_quantity}${item.shipping_order_status}${item.serial_no}
+ +
+ +
+ + diff --git a/src/com/pms/salesmgmt/controller/ContractMgmtController.java b/src/com/pms/salesmgmt/controller/ContractMgmtController.java index 4172e01..6b688c9 100644 --- a/src/com/pms/salesmgmt/controller/ContractMgmtController.java +++ b/src/com/pms/salesmgmt/controller/ContractMgmtController.java @@ -269,7 +269,24 @@ public class ContractMgmtController { @ResponseBody @RequestMapping("/contractMgmt/contractGridList.do") public Map getProductKindSpecListPaging(HttpServletRequest request, @RequestParam Map paramMap){ - commonService.selectListPagingNew("contractMgmt.contractGridList", request, paramMap); + try { + // 페이징 데이터 조회 + commonService.selectListPagingNew("contractMgmt.contractGridList", request, paramMap); + + // 조회된 데이터의 전체 합계 조회 + Map totalAmount = (Map) commonService.selectOne("contractMgmt.getContractGridTotalAmount", request, paramMap); + + // 합계 데이터 추가 + if(totalAmount != null) { + paramMap.put("TOTAL_AMOUNT_KRW", totalAmount.get("totalAmountKRW")); + } else { + paramMap.put("TOTAL_AMOUNT_KRW", 0); + } + } catch(Exception e) { + e.printStackTrace(); + paramMap.put("TOTAL_AMOUNT_KRW", 0); + } + return paramMap; } @@ -2359,6 +2376,41 @@ public class ContractMgmtController { return paramMap; } + /** + * 주문서관리 - Total 합계 조회 + * @param request + * @param paramMap + * @return + */ + @ResponseBody + @RequestMapping("/contractMgmt/getOrderTotalAmount.do") + public Map getOrderTotalAmount(HttpServletRequest request, @RequestParam Map paramMap){ + Map resultMap = new HashMap(); + + try { + // Total 합계 조회 + Map totalData = contractMgmtService.getOrderTotalAmount(request, paramMap); + + if(totalData != null) { + resultMap.put("result", "success"); + resultMap.put("totalSupplyPrice", totalData.get("TOTAL_SUPPLY_PRICE")); + resultMap.put("totalVat", totalData.get("TOTAL_VAT")); + resultMap.put("totalAmount", totalData.get("TOTAL_AMOUNT")); + } else { + resultMap.put("result", "success"); + resultMap.put("totalSupplyPrice", 0); + resultMap.put("totalVat", 0); + resultMap.put("totalAmount", 0); + } + } catch (Exception e) { + e.printStackTrace(); + resultMap.put("result", "error"); + resultMap.put("message", e.getMessage()); + } + + return resultMap; + } + /** * 수주등록 팝업 페이지 * @param session diff --git a/src/com/pms/salesmgmt/controller/SalesNcollectMgmtController.java b/src/com/pms/salesmgmt/controller/SalesNcollectMgmtController.java index d982029..734ce9c 100644 --- a/src/com/pms/salesmgmt/controller/SalesNcollectMgmtController.java +++ b/src/com/pms/salesmgmt/controller/SalesNcollectMgmtController.java @@ -282,11 +282,47 @@ public class SalesNcollectMgmtController { } // orderNo가 있으면 기존 판매 정보 조회 else if(paramMap.get("orderNo") != null && !paramMap.get("orderNo").equals("")) { + System.out.println("=== salesRegForm.do 파라미터 확인 ==="); + System.out.println("orderNo: " + paramMap.get("orderNo")); + System.out.println("salesQuantity: " + paramMap.get("salesQuantity")); + System.out.println("salesUnitPrice: " + paramMap.get("salesUnitPrice")); + System.out.println("salesSupplyPrice: " + paramMap.get("salesSupplyPrice")); + System.out.println("salesVat: " + paramMap.get("salesVat")); + System.out.println("salesTotalAmount: " + paramMap.get("salesTotalAmount")); + System.out.println("salesCurrency: " + paramMap.get("salesCurrency")); + System.out.println("salesExchangeRate: " + paramMap.get("salesExchangeRate")); + saleInfo = salesNcollectMgmtService.getSaleInfo(paramMap); salesCurrency = CommonUtils.nullToEmpty((String)saleInfo.get("SALES_CURRENCY")); + System.out.println("=== DB에서 조회한 saleInfo ==="); + System.out.println("SALES_QUANTITY: " + saleInfo.get("SALES_QUANTITY")); + System.out.println("SALES_UNIT_PRICE: " + saleInfo.get("SALES_UNIT_PRICE")); + System.out.println("SALES_SUPPLY_PRICE: " + saleInfo.get("SALES_SUPPLY_PRICE")); + + // URL 파라미터로 그리드 데이터가 전달된 경우 우선 사용 + if(paramMap.get("salesQuantity") != null && !paramMap.get("salesQuantity").equals("")) { + System.out.println("=== URL 파라미터로 그리드 데이터 설정 ==="); + if(saleInfo == null) saleInfo = new HashMap(); + + saleInfo.put("SALES_UNIT_PRICE", paramMap.get("salesUnitPrice")); + saleInfo.put("SALES_SUPPLY_PRICE", paramMap.get("salesSupplyPrice")); + saleInfo.put("SALES_VAT", paramMap.get("salesVat")); + saleInfo.put("SALES_TOTAL_AMOUNT", paramMap.get("salesTotalAmount")); + if(paramMap.get("salesCurrency") != null) { + saleInfo.put("SALES_CURRENCY", paramMap.get("salesCurrency")); + salesCurrency = CommonUtils.nullToEmpty((String)paramMap.get("salesCurrency")); + } + if(paramMap.get("salesExchangeRate") != null) { + saleInfo.put("SALES_EXCHANGE_RATE", paramMap.get("salesExchangeRate")); + } + System.out.println("설정 후 SALES_UNIT_PRICE: " + saleInfo.get("SALES_UNIT_PRICE")); + System.out.println("설정 후 SALES_SUPPLY_PRICE: " + saleInfo.get("SALES_SUPPLY_PRICE")); + System.out.println("설정 후 SALES_VAT: " + saleInfo.get("SALES_VAT")); + System.out.println("설정 후 SALES_TOTAL_AMOUNT: " + saleInfo.get("SALES_TOTAL_AMOUNT")); + } // 판매 정보가 비어있거나 금액이 0이면 수주 데이터로 채우기 - if(saleInfo == null || + else if(saleInfo == null || (saleInfo.get("SALES_SUPPLY_PRICE") == null || "0".equals(String.valueOf(saleInfo.get("SALES_SUPPLY_PRICE"))) || Integer.parseInt(String.valueOf(saleInfo.get("SALES_SUPPLY_PRICE"))) == 0)) { @@ -310,13 +346,40 @@ public class SalesNcollectMgmtController { saleInfo.put("SHIPPING_DATE", orderData.get("SHIPPING_DATE")); } salesCurrency = CommonUtils.nullToEmpty((String)orderData.get("SALES_CURRENCY")); + } + } + + // 잔량 계산: ORDER_QUANTITY - 모든 분할 출하의 합계 + if(saleInfo != null && saleInfo.get("ORDER_QUANTITY") != null) { + int orderQuantity = Integer.parseInt(String.valueOf(saleInfo.get("ORDER_QUANTITY")).split("\\.")[0]); + + // 모든 분할 출하의 합계 조회 + int totalSoldQuantity = 0; + try { + Map totalResult = salesNcollectMgmtService.getTotalSalesQuantity(paramMap); + if(totalResult != null && totalResult.get("total") != null) { + totalSoldQuantity = Integer.parseInt(String.valueOf(totalResult.get("total")).split("\\.")[0]); } + } catch(Exception e) { + e.printStackTrace(); } - request.setAttribute("saleInfo", saleInfo); + int remainingQuantity = orderQuantity - totalSoldQuantity; - // orderInfo로 견적 정보 전달 (saleInfo가 이미 모든 필요한 정보를 포함) - request.setAttribute("orderInfo", saleInfo); + System.out.println("=== 잔량 계산 ==="); + System.out.println("주문수량 (ORDER_QUANTITY): " + orderQuantity); + System.out.println("총 판매 수량 (모든 분할 출하 합계): " + totalSoldQuantity); + System.out.println("잔량 (remainingQuantity): " + remainingQuantity); + + // 잔량을 판매수량으로 설정 (정수) + saleInfo.put("SALES_QUANTITY", remainingQuantity > 0 ? remainingQuantity : orderQuantity); + System.out.println("설정 후 SALES_QUANTITY: " + saleInfo.get("SALES_QUANTITY")); + } + + request.setAttribute("saleInfo", saleInfo); + + // orderInfo로 견적 정보 전달 (saleInfo가 이미 모든 필요한 정보를 포함) + request.setAttribute("orderInfo", saleInfo); } // 환종(통화) - 공통코드 0001533 @@ -418,6 +481,27 @@ public class SalesNcollectMgmtController { return resultMap; } + /** + *
+	 * 출하일 상세 내역 팝업
+	 * 
+ * @param request + * @param paramMap - projectNo + * @return String + */ + @RequestMapping(value = "/salesMgmt/shippingDetailPopup.do", method = RequestMethod.GET) + public String showShippingDetailPopup(HttpServletRequest request, @RequestParam Map paramMap) { + try { + String projectNo = (String) paramMap.get("projectNo"); + List> shippingList = salesNcollectMgmtService.getShippingDetailList(projectNo); + request.setAttribute("shippingList", shippingList); + request.setAttribute("projectNo", projectNo); + } catch (Exception e) { + e.printStackTrace(); + } + return "/salesmgmt/salesMgmt/shippingDetailPopup"; + } + /** *
 	 * 계약관리 목록 조회
diff --git a/src/com/pms/salesmgmt/mapper/contractMgmt.xml b/src/com/pms/salesmgmt/mapper/contractMgmt.xml
index 0e5b92a..d9544f4 100644
--- a/src/com/pms/salesmgmt/mapper/contractMgmt.xml
+++ b/src/com/pms/salesmgmt/mapper/contractMgmt.xml
@@ -790,6 +790,102 @@
 	ORDER BY REGDATE DESC				
 
 
+
+
+
 
+
+	
+	
 	
 	
 	
+		/* salesNcollectMgmt.getTotalSalesQuantity - project_no로 시작하는 모든 레코드의 판매 수량 합계 */
+		SELECT COALESCE(SUM(sales_quantity), 0) as total
+		FROM sales_registration
+		WHERE project_no LIKE #{orderNo} || '%'
+	
+	
+	
+	
+	
+	
+	
+		/* salesNcollectMgmt.deleteSaleRegistration - sales_registration 삭제 */
+		DELETE FROM sales_registration
+		WHERE project_no = #{orderNo}
+	
+	
+	
+	
+		/* salesNcollectMgmt.updateSaleRegistration - sales_registration 업데이트 */
+		UPDATE sales_registration
+		SET
+			shipping_order_status = 
+				
+					#{shippingOrderStatus},
+				
+				
+					'',
+				
+			
+			serial_no = #{serialNo},
+			sales_quantity = #{salesQuantity}::integer,
+			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,
+			shipping_date = 
+				
+					TO_DATE(#{shippingDate}, 'YYYY-MM-DD'),
+				
+				
+					NULL,
+				
+			
+			shipping_method = #{shippingMethod},
+			manager_user_id = #{manager},
+			incoterms = #{incoterms},
+			upd_date = NOW(),
+			upd_user_id = #{cretEmpNo}
+		WHERE project_no = #{orderNo}
+	
+	
+	
+	
+	
+	
+	
+	
+	
+		/* salesNcollectMgmt.insertShipmentLog - 분할 출하 기록 저장 */
+		INSERT INTO shipment_log (
+			target_objid, log_type, log_message, split_quantity, original_quantity, 
+			remaining_quantity, shipping_status, shipping_date, shipping_method,
+			sales_unit_price, sales_supply_price, sales_vat, sales_total_amount,
+			sales_currency, sales_exchange_rate, manager_user_id, incoterms,
+			serial_no, parent_sale_no, reg_user_id
+		) VALUES (
+			#{targetObjid}, 'SPLIT_SHIPMENT', '분할 출하',
+			#{salesQuantity}::integer, #{originalQuantity}::integer, #{remainingQuantity}::integer,
+			#{shippingOrderStatus},
+			
+				
+					TO_DATE(#{shippingDate}, 'YYYY-MM-DD'),
+				
+				NULL,
+			
+			#{shippingMethod}, #{salesUnitPrice}::numeric, #{salesSupplyPrice}::numeric,
+			#{salesVat}::numeric, #{salesTotalAmount}::numeric, #{salesCurrency},
+			#{salesExchangeRate}::numeric, #{manager}, #{incoterms}, #{serialNo},
+			#{parentSaleNo}::integer, #{cretEmpNo}
+		)
+	
+	
+	
+	
+	
+	
+	
+	
 
 
diff --git a/src/com/pms/salesmgmt/service/ContractMgmtService.java b/src/com/pms/salesmgmt/service/ContractMgmtService.java
index bcd2ef8..9af52aa 100644
--- a/src/com/pms/salesmgmt/service/ContractMgmtService.java
+++ b/src/com/pms/salesmgmt/service/ContractMgmtService.java
@@ -2423,6 +2423,41 @@ private String encodeImageToBase64(String imagePath) {
 		return items;
 	}
 	
+	/**
+	 * 주문서관리 Total 합계 조회
+	 * @param request
+	 * @param paramMap - 검색 조건
+	 * @return Map - TOTAL_SUPPLY_PRICE, TOTAL_VAT, TOTAL_AMOUNT
+	 */
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public Map getOrderTotalAmount(HttpServletRequest request, Map paramMap){
+		SqlSession sqlSession = null;
+		Map resultMap = new HashMap();
+		
+		try{
+			sqlSession = SqlMapConfig.getInstance().getSqlSession();
+			resultMap = sqlSession.selectOne("contractMgmt.getOrderTotalAmount", paramMap);
+			
+			// 대문자 변환
+			if(resultMap != null) {
+				resultMap = CommonUtils.keyChangeUpperMap(resultMap);
+			} else {
+				// 데이터가 없을 경우 기본값 설정
+				resultMap = new HashMap();
+				resultMap.put("TOTAL_SUPPLY_PRICE", 0);
+				resultMap.put("TOTAL_VAT", 0);
+				resultMap.put("TOTAL_AMOUNT", 0);
+			}
+			
+		}catch(Exception e){
+			e.printStackTrace();
+		}finally{
+			if(sqlSession != null) sqlSession.close();
+		}
+		
+		return resultMap;
+	}
+	
 	/**
 	 * 견적서 템플릿 품목 조회 (수주등록용)
 	 * 최종 견적서의 품목 정보를 수주등록 형식으로 변환하여 반환
diff --git a/src/com/pms/salesmgmt/service/SalesNcollectMgmtService.java b/src/com/pms/salesmgmt/service/SalesNcollectMgmtService.java
index 909596f..f973bbc 100644
--- a/src/com/pms/salesmgmt/service/SalesNcollectMgmtService.java
+++ b/src/com/pms/salesmgmt/service/SalesNcollectMgmtService.java
@@ -321,12 +321,38 @@ public class SalesNcollectMgmtService {
 			PersonBean person = (PersonBean) request.getSession().getAttribute(Constants.PERSON_BEAN);
 			paramMap.put("cretEmpNo", person.getUserId());
 			
-			// sales_registration 테이블에 판매 데이터 저장 (ON CONFLICT로 자동 UPDATE)
-			sqlSession.insert("salesNcollectMgmt.insertSaleRegistration", paramMap);
+		// 기존 데이터 확인
+		Map existingData = sqlSession.selectOne("salesNcollectMgmt.getSaleInfo", paramMap);
+		
+		if(existingData != null && existingData.get("sale_no") != null) {
+			// 이미 있으면 순번을 붙여서 새로운 project_no로 INSERT
+			String originalProjectNo = String.valueOf(paramMap.get("orderNo"));
+			
+			// 기존 레코드 개수 조회
+			Map countResult = sqlSession.selectOne("salesNcollectMgmt.getSaleRegistrationCount", paramMap);
+			int count = countResult != null && countResult.get("count") != null ? 
+				Integer.parseInt(String.valueOf(countResult.get("count"))) : 0;
+			
+			// 새로운 project_no 생성 (순번 추가)
+			String newProjectNo = originalProjectNo + "_" + (count + 1);
+			paramMap.put("orderNo", newProjectNo);
+			
+			System.out.println("=== 분할 출하 저장 ===");
+			System.out.println("원본 PROJECT_NO: " + originalProjectNo);
+			System.out.println("새 PROJECT_NO: " + newProjectNo);
+			System.out.println("수량: " + paramMap.get("salesQuantity"));
+		} else {
+			System.out.println("=== 판매 정보 신규 저장 ===");
+			System.out.println("PROJECT_NO: " + paramMap.get("orderNo"));
+			System.out.println("수량: " + paramMap.get("salesQuantity"));
+		}
+		
+		// INSERT
+		sqlSession.insert("salesNcollectMgmt.insertSaleRegistration", paramMap);
+		resultMap.put("msg", "저장되었습니다.");
 			
 			sqlSession.commit();
 			resultMap.put("result", true);
-			resultMap.put("msg", "저장되었습니다.");
 		} catch(Exception e) {
 			if(sqlSession != null) {
 				sqlSession.rollback();
@@ -918,4 +944,61 @@ public class SalesNcollectMgmtService {
 		}
 		return resultMap;
 	}
+	
+	/**
+	 * 출하일 상세 내역 조회
+	 * @param projectNo
+	 * @return List
+	 */
+	public List> getShippingDetailList(String projectNo) {
+		SqlSession sqlSession = null;
+		List> resultList = new ArrayList>();
+		try {
+			sqlSession = SqlMapConfig.getInstance().getSqlSession();
+			Map paramMap = new HashMap();
+			paramMap.put("projectNo", projectNo);
+			resultList = sqlSession.selectList("salesNcollectMgmt.getShippingDetailList", paramMap);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			if (sqlSession != null) {
+				sqlSession.close();
+			}
+		}
+		return resultList;
+	}
+	
+	public Map getTotalSalesQuantity(Map paramMap) {
+		SqlSession sqlSession = null;
+		Map result = null;
+		
+		try {
+			sqlSession = SqlMapConfig.getInstance().getSqlSession();
+			result = sqlSession.selectOne("salesNcollectMgmt.getTotalSalesQuantity", paramMap);
+		} catch(Exception e) {
+			e.printStackTrace();
+		} finally {
+			if(sqlSession != null) {
+				sqlSession.close();
+			}
+		}
+		
+		return result;
+	}
+	
+	public Map getShipmentLogTotal(Map paramMap) {
+		SqlSession sqlSession = null;
+		Map result = new HashMap();
+		try {
+			sqlSession = SqlMapConfig.getInstance().getSqlSession();
+			result = sqlSession.selectOne("salesNcollectMgmt.getShipmentLogTotal", paramMap);
+		} catch (Exception e) {
+			e.printStackTrace();
+		} finally {
+			if (sqlSession != null) {
+				sqlSession.close();
+			}
+		}
+		return result;
+	}
 }