Files
wace_plm/WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp
hjjeong e017520b60 영업관리 금액 소수점 2자리 표시 및 계산 정확성 개선
- 견적/주문서/판매관리 전 페이지 금액 필드 소수점 2자리 + 천단위 콤마 표시
- parseInt → parseFloat, Math.round 제거로 소수점 계산 정확성 확보
- estimateTemplate1 fn_save() 소수점 제거 버그 수정 (/[^0-9]/g → /[^0-9.]/g)
- contractMgmt.xml, salesNcollectMgmt.xml VARCHAR→NUMERIC CAST 시 REPLACE 안전 처리
- EST_TOTAL_AMOUNT_KRW 환율 변경 시 동적 재계산 (SQL 쿼리 수정)

Made-with: Cursor
2026-03-13 17:36:06 +09:00

1096 lines
40 KiB
Plaintext

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.pms.common.utils.*"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page import="java.util.*" %>
<%@include file= "/init.jsp" %>
<%
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
String connector = person.getUserId();
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><%=Constants.SYSTEM_NAME%></title>
<c:set var="now" value="<%=new java.util.Date() %>"/>
<c:set var="sysYear"><fmt:formatDate value="${now}" pattern="yyyy" /></c:set>
<c:set var="connector" value="<%=connector %>" />
<script>
$(document).ready(function(){
//날짜
_fnc_datepick();
$('.select2').select2();
// 품번/품명 Select2 AJAX 초기화 (common.js의 새 함수 사용)
initPartSelect2Ajax("#search_partNo", "#search_partName", "#search_partObjId", {
debug: false // 디버깅 모드 비활성화
});
$("#btnSearch").click(function(){
$("#page").val("1");
fn_search();
});
//SR자료등록 팝업
$(".File").click(function(){
var popup_width = 800;
var popup_height = 335;
var objId = $(this).attr("data-OBJID");
var docType =$(this).attr("data-docType");
var docTypeName = $(this).attr("data-docTypeName");
var params = "?targetObjId="+objId+"&docType="+docType+"&docTypeName="+docTypeName;
var url = "/projectConcept/FileRegistPopup.do"+params;
fn_centerPopup(popup_width, popup_height, url);
});
//수주 등록 팝업
$(".btnRegist").click(function(){
var selectedData = _tabulGrid.getSelectedData();
if(selectedData.length < 1){
// 선택이 없으면 견적요청+수주 통합 등록 팝업 오픈
var popup_width = 1600;
var popup_height = 800;
var params = "?actionType=regist";
var url = "/contractMgmt/estimateAndOrderRegistFormPopup.do"+params;
fn_centerPopup(popup_width, popup_height, url);
} else if(selectedData.length > 1){
Swal.fire("한번에 한개의 수주만 등록 가능합니다.");
return false;
} else {
var contractObjId = fnc_checkNull(selectedData[0].OBJID);
var isDirectOrder = fnc_checkNull(selectedData[0].IS_DIRECT_ORDER);
// 통합 등록 건이면 통합 팝업 오픈 (수정 모드)
if(isDirectOrder === 'Y') {
var popup_width = 1600;
var popup_height = 800;
var params = "?actionType=update&objId="+contractObjId;
var url = "/contractMgmt/estimateAndOrderRegistFormPopup.do"+params;
fn_centerPopup(popup_width, popup_height, url);
} else {
// 일반 견적요청 건이면 기존 수주등록 팝업 오픈
var popup_width = 1400;
var popup_height = 450;
var params = "?actionType=regist&contractObjId="+contractObjId;
var url = "/contractMgmt/orderRegistFormPopup.do"+params;
fn_centerPopup(popup_width, popup_height, url);
}
}
});
//결재상신 (Amaranth)
$("#btnApproval").click(function(){
var selectedData = _tabulGrid.getSelectedData();
if(selectedData.length < 1){
Swal.fire("결재상신할 행을 선택해주십시오.");
return false;
} else if(selectedData.length > 1){
Swal.fire("한번에 한개의 결재만 가능합니다.");
return false;
} else {
var amaranthStatus = fnc_checkNull(selectedData[0].ORDER_AMARANTH_STATUS);
var objId = fnc_checkNull(selectedData[0].OBJID);
var contractNo = fnc_checkNull(selectedData[0].CONTRACT_NO);
var hasOrderData = parseInt(selectedData[0].HAS_ORDER_DATA) || 0;
if(hasOrderData == 0){
Swal.fire("수주 품목을 먼저 등록해주세요.");
return false;
}
if(amaranthStatus == "inProcess"){
Swal.fire("결재 진행중인 건은 상신할 수 없습니다.");
return false;
} else if(amaranthStatus == "complete"){
Swal.fire("결재 완료된 건은 상신할 수 없습니다.");
return false;
}
Swal.fire({
title: '결재상신',
html: '결재상신 하시겠습니까?',
icon: 'question',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: '결재상신',
cancelButtonText: '취소'
}).then((result) => {
if(result.isConfirmed) {
fn_openAmaranthApproval(objId, contractNo);
}
});
}
});
//엔터 조회
$("input").keyup(function(e){
if(e.keyCode == 13){
$("#page").val("1");
fn_search();
}
});
//삭제
$("#btnDelete").click(function(){
fn_delete();
});
$("#btnExcel").click(function(){
document.form1.actionType.value = "excel";
document.form1.action = "/contractMgmt/contractList.do";
document.form1.submit();
});
// 수주취소
$("#btnOrderCancel").click(function(){
var selectedData = _tabulGrid.getSelectedData();
if(selectedData.length < 1){
Swal.fire("수주취소할 행을 선택해주십시오.");
return false;
} else if(selectedData.length > 1){
Swal.fire("한번에 한개의 수주만 취소 가능합니다.");
return false;
}
var contractObjId = fnc_checkNull(selectedData[0].OBJID);
var orderQty = parseInt(selectedData[0].ORDER_QUANTITY) || 0;
if(orderQty === 0){
Swal.fire("수주 수량이 없는 건은 취소할 수 없습니다.");
return false;
}
fn_openOrderCancelPopup(contractObjId);
});
fn_search();
});
var columns = [
// 컬럼 순서: 영업번호, 주문유형, 발주일, 발주번호, 요청납기, 고객사, 품명, 수주수량, 유무상, 수주상태, 공급가액, 부가세, 총액, 원화총액, 주문서첨부, 고객사요청사항, 결재상태, 환종, 환율, S/N, 품번
// 1. 영업번호
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 75, widthGrow: 1, title : '영업번호', field : 'CONTRACT_NO', frozen:true,
formatter:fnc_createGridAnchorTag,
cellClick:function(e, cell){
var objid = fnc_checkNull(cell.getData().OBJID);
fn_projectConceptDetail(objid);
}
},
// 2. 주문유형
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 77, widthGrow: 0.8, title : '주문유형', field : 'CATEGORY_NAME' },
// 3. 발주일
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 70, widthGrow: 0.7, title : '발주일', field : 'ORDER_DATE' },
// 4. 발주번호
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 70, widthGrow: 0.8, title : '발주번호', field : 'PO_NO' },
// 5. 요청납기
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 70, widthGrow: 0.7, title : '요청납기', field : 'EARLIEST_DUE_DATE',
formatter: function(cell, formatterParams, onRendered){
var dueDate = fnc_checkNull(cell.getValue());
var otherCount = fnc_checkNull(cell.getData().OTHER_DUE_DATE_COUNT);
if(dueDate === '') return '';
if(otherCount && parseInt(otherCount) > 0){
return dueDate + ' 외 ' + otherCount + '건';
}
return dueDate;
}
},
// 6. 고객사
{headerHozAlign : 'center', hozAlign : 'left', minWidth : 80, widthGrow: 1, title : '고객사', field : 'CUSTOMER_NAME' },
// 7. 품명
{headerHozAlign : 'center', hozAlign : 'left', minWidth : 100, widthGrow: 1.2, title : '품명', field : 'ITEM_SUMMARY',
formatter: function(cell) {
var value = cell.getValue();
if(!value || value === '') return '';
return value;
}
},
// 8. 수주수량
{headerHozAlign : 'center', hozAlign : 'right', minWidth : 60, widthGrow: 0.7, title : '수주수량', field : 'ORDER_QUANTITY',
formatter: function(cell) {
var value = cell.getValue();
if(!value || value === '' || value === '0') return '';
return Number(value).toLocaleString();
}
},
// 8-1. 수주취소
{headerHozAlign : 'center', hozAlign : 'right', minWidth : 60, widthGrow: 0.7, title : '수주취소', field : 'CANCEL_QTY_SUM',
formatter: function(cell) {
var value = cell.getValue();
if(!value || value === '' || value === 0 || value === '0') return '';
return "<span style='color:#e74c3c; font-weight:bold;'>" + Number(value).toLocaleString() + "</span>";
}
},
// 9. 유/무상
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 45, widthGrow: 0.5, title : '유/무상', field : 'PAID_TYPE' },
// 10. 수주상태
{headerHozAlign : 'center', hozAlign : 'left', minWidth : 60, widthGrow: 0.7, title : '수주상태', field : 'CONTRACT_RESULT_NAME' },
// 11. 공급가액
{headerHozAlign : 'center', hozAlign : 'right', minWidth : 75, widthGrow: 0.8, title : '공급가액', field : 'ORDER_SUPPLY_PRICE_SUM',
formatter: function(cell) {
var value = cell.getValue();
if(!value || value === '' || value === '0') return '';
var rowData = cell.getRow().getData();
var currencyName = rowData.CONTRACT_CURRENCY_NAME || '';
var currencySymbol = '';
if(currencyName.includes('원') || currencyName === 'KRW') currencySymbol = '₩';
else if(currencyName.includes('달러') || currencyName === 'USD') currencySymbol = '$';
else if(currencyName.includes('유로') || currencyName === 'EUR') currencySymbol = '€';
else if(currencyName.includes('엔') || currencyName === 'JPY') currencySymbol = '¥';
else if(currencyName.includes('위안') || currencyName === 'CNY') currencySymbol = '¥';
return currencySymbol + Number(value).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
},
// 12. 부가세
{headerHozAlign : 'center', hozAlign : 'right', minWidth : 65, widthGrow: 0.7, title : '부가세', field : 'ORDER_VAT_SUM',
formatter: function(cell) {
var value = cell.getValue();
if(!value || value === '' || value === '0') return '';
var rowData = cell.getRow().getData();
var currencyName = rowData.CONTRACT_CURRENCY_NAME || '';
var currencySymbol = '';
if(currencyName.includes('원') || currencyName === 'KRW') currencySymbol = '₩';
else if(currencyName.includes('달러') || currencyName === 'USD') currencySymbol = '$';
else if(currencyName.includes('유로') || currencyName === 'EUR') currencySymbol = '€';
else if(currencyName.includes('엔') || currencyName === 'JPY') currencySymbol = '¥';
else if(currencyName.includes('위안') || currencyName === 'CNY') currencySymbol = '¥';
return currencySymbol + Number(value).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
},
// 13. 총액
{headerHozAlign : 'center', hozAlign : 'right', minWidth : 70, widthGrow: 0.8, title : '총액', field : 'ORDER_TOTAL_AMOUNT_SUM',
formatter: function(cell) {
var value = cell.getValue();
if(!value || value === '' || value === '0') return '';
var rowData = cell.getRow().getData();
var currencyName = rowData.CONTRACT_CURRENCY_NAME || '';
var currencySymbol = '';
if(currencyName.includes('원') || currencyName === 'KRW') currencySymbol = '₩';
else if(currencyName.includes('달러') || currencyName === 'USD') currencySymbol = '$';
else if(currencyName.includes('유로') || currencyName === 'EUR') currencySymbol = '€';
else if(currencyName.includes('엔') || currencyName === 'JPY') currencySymbol = '¥';
else if(currencyName.includes('위안') || currencyName === 'CNY') currencySymbol = '¥';
return currencySymbol + Number(value).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
},
// 14. 원화총액
{headerHozAlign : 'center', hozAlign : 'right', minWidth : 80, widthGrow: 0.9, title : '원화총액', field : 'ORDER_TOTAL_AMOUNT_KRW',
formatter: function(cell) {
var value = cell.getValue();
if(!value || value === '' || value === '0') return '';
return '₩' + Number(value).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
},
// 15. 주문서첨부
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 50, widthGrow: 0.5, title : '주문서첨부', field : 'CU01_CNT' ,
formatter:fnc_subInfoValueFormatter,
cellClick:function(e, cell){
var objid = fnc_checkNull(cell.getData().OBJID);
fn_FileRegist(objid,"ORDER_DOC","ORDER_DOC","CU01_CNT");
}
},
// 16. 주문서 (자동생성 뷰)
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 50, widthGrow: 0.5, title : '주문서', field : 'HAS_ORDER_DATA',
formatter: function(cell){
var value = parseInt(cell.getValue()) || 0;
if(value > 0){
return '<img src="/images/icon/doc_view.png" style="width:16px;height:16px;cursor:pointer;" onerror="this.outerHTML=\'<span style=color:#3085d6;cursor:pointer;font-weight:bold;>보기</span>\'">';
}
return '';
},
cellClick: function(e, cell){
var hasData = parseInt(cell.getValue()) || 0;
if(hasData > 0){
var objid = fnc_checkNull(cell.getData().OBJID);
fn_openOrderFormView(objid);
}
}
},
// 17. 고객사요청사항
{headerHozAlign : 'center', hozAlign : 'left', minWidth : 100, widthGrow: 1, title : '고객사요청사항', field : 'CUSTOMER_REQUEST' },
// 17. 결재상태 (Amaranth) - 주문서 전용
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 60, widthGrow: 0.7, title : '결재상태', field : 'ORDER_APPR_STATUS',
formatter: function(cell){
var val = fnc_checkNull(cell.getValue());
if(val == '결재중') return "<span style='color:#e67e22; font-weight:bold;'>" + val + "</span>";
if(val == '결재완료') return "<span style='color:#27ae60; font-weight:bold;'>" + val + "</span>";
if(val == '반려') return "<span style='color:#e74c3c; font-weight:bold;'>" + val + "</span>";
if(val == '작성중') return "<span style='color:#3498db;'>" + val + "</span>";
return val;
}
},
// 18. 환종
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 50, widthGrow: 0.5, title : '환종', field : 'CONTRACT_CURRENCY_NAME' },
// 19. 환율
{headerHozAlign : 'center', hozAlign : 'right', minWidth : 55, widthGrow: 0.6, title : '환율', field : 'EXCHANGE_RATE',
formatter: function(cell) {
var value = cell.getValue();
if(!value || value === '' || value === '0') return '';
return Number(value).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
},
// 20. S/N
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 80, widthGrow: 0.8, title : 'S/N', field : 'SERIAL_NO',
formatter: function(cell, formatterParams, onRendered){
var value = fnc_checkNull(cell.getValue());
if(value === '') return '';
var serialNumbers = value.split(',').map(function(s){ return s.trim(); }).filter(function(s){ return s !== ''; });
var count = serialNumbers.length;
if(count === 0) return '';
if(count === 1) return '<a href="javascript:void(0);">' + serialNumbers[0] + '</a>';
var displayText = serialNumbers[0] + ' 외 ' + (count - 1) + '개';
return '<a href="javascript:void(0);">' + displayText + '</a>';
},
cellClick:function(e, cell){
var serialNo = fnc_checkNull(cell.getData().SERIAL_NO);
var contractObjId = fnc_checkNull(cell.getData().OBJID);
fn_showSerialNoPopup(serialNo, contractObjId);
}
},
// 21. 품번
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 70, widthGrow: 0.8, title : '품번', field : 'PART_NO' },
/* 주석처리된 컬럼 - 필요시 활성화 */
/*
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 55, widthGrow: 0.6, title : '제품구분', field : 'PRODUCT_NAME' },
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 55, widthGrow: 0.6, title : '국내/해외', field : 'AREA_NAME' },
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 70, widthGrow: 0.7, title : '접수일', field : 'RECEIPT_DATE' },
*/
];
//var grid;
function fn_search(){
// fnc_tabul_search로 페이징 처리
_tabulGrid = fnc_tabul_search(
_tabul_layout_fitDataStretch,
_tabulGrid,
"/contractMgmt/contractGridList.do",
columns,
true
);
// 데이터 렌더링 완료 후 합계 계산 (한 번만 실행)
if(_tabulGrid) {
// 기존 이벤트 제거 후 재등록
_tabulGrid.off("renderComplete");
_tabulGrid.on("renderComplete", function(){
fn_calculateTotalFromGrid();
// 그리드 렌더링 완료 후 높이 계산
fnc_calculateContentHeight("gridDiv", 30);
});
}
// 윈도우 리사이즈 이벤트 (한 번만 등록)
$(window).off("resize.gridHeight").on("resize.gridHeight", function() {
fnc_calculateContentHeight("gridDiv", 30);
});
}
// 그리드에 표시된 데이터의 원화총액 합계 계산
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(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}));
}
function _fnc_datepick(){
var $dateinput = $("input.date_icon");
for(var i=0; i<$dateinput.length; i++){
$dateinput.eq(i).attr("size","10");
$dateinput.eq(i).datepicker({
changeMonth:true,
changeYear:true
});
}
}
function fn_delete(){
var checkedObj = _tabulGrid.getSelectedData();
if(0 < checkedObj.length){
var objId = fnc_checkNull(checkedObj[0].OBJID);
//if(confirm("선택한 정보를 삭제하시겠습니까?")){
Swal.fire({
title: '선택한 고객정보를 삭제하시겠습니까?',
text: '',
icon: 'warning',
showCancelButton: true, // cancel버튼 보이기. 기본은 원래 없음
confirmButtonColor: '#3085d6', // confrim 버튼 색깔 지정
cancelButtonColor: '#d33', // cancel 버튼 색깔 지정
confirmButtonText: '확인', // confirm 버튼 텍스트 지정
cancelButtonText: '취소', // cancel 버튼 텍스트 지정
reverseButtons: false, // 버튼 순서 거꾸로
}).then(result => {
// 만약 Promise리턴을 받으면,
if (result.isConfirmed) { // 만약 모달창에서 confirm 버튼을 눌렀다면
//var param = $("#form1").serialize();
$.ajax({
type : "POST",
url : "/contractMgmt/deleteContractMngInfo.do",
data: {
"objId":objId
},
dataType:"json",
success:function(data){
if(data.result == 'true'){
Swal.fire("삭제되었습니다.");
fn_search();
};
}
,error: function(jqxhr, status, error){
}
});
}
});
}else{
Swal.fire("선택한 항목이 없습니다.");
}
}
// Amaranth10 전자결재 SSO 팝업 열기
function fn_openAmaranthApproval(objId, contractNo) {
var title = "주문서 결재" + (contractNo ? " - " + contractNo : "");
$.ajax({
url: "/approval/getAmaranthSsoUrl.do",
type: "POST",
data: {
"targetType": "CONTRACT_ORDER",
"targetObjId": objId,
"approvalTitle": title,
"outProcessCode": "${AMARANTH_OUT_PROCESS_CODE}",
"formId": "",
"compSeq": "1000",
"deptSeq": ""
},
dataType: "json",
success: function(data) {
if(data.resultCode == 0 && data.resultData && data.resultData.fullUrl) {
var fullUrl = data.resultData.fullUrl;
window.open(fullUrl, "amaranthApproval", "width=1200,height=900,scrollbars=yes,resizable=yes");
} else {
Swal.fire("결재 연동 오류: " + (data.resultMsg || "알 수 없는 오류"));
}
},
error: function(xhr, status, error) {
console.error("Amaranth SSO URL 요청 오류:", error);
Swal.fire("결재 시스템 연동 중 오류가 발생했습니다.");
}
});
}
function fn_openOrderFormView(objId){
var popup_width = 950;
var popup_height = 800;
var url = "/contractMgmt/orderFormView.do?objId=" + objId;
window.open(url, "orderFormView_" + objId, "width=" + popup_width + ",height=" + popup_height + ",menubar=no,scrollbars=yes,resizable=yes");
}
function fn_FileRegist(objId, docType, docTypeName, columnField){
var popup_width = 800;
var popup_height = 650;
var objId = objId;
var docType = docType;
var docTypeName = docTypeName;
var columnField = columnField || '';
var params = "?targetObjId="+objId+"&docType="+docType+"&docTypeName="+docTypeName+"&columnField="+columnField;
var url = "/contractMgmt/FileRegistPopup.do"+params;
fn_centerPopup(popup_width, popup_height, url);
}
//영업활동등록 상세 (뷰 전용 팝업)
function fn_projectConceptDetail(objId){
var popup_width = 900;
var popup_height = 700;
var url = "/contractMgmt/estimateViewPopup.do?objId="+objId;
fn_centerPopup(popup_width, popup_height, url);
}
//검토내용 상세
function fn_projectConceptReviewDetail(objId){
var popup_width = 800;
var popup_height = 250;
var url = "/contractMgmt/contracMgmtReviewFormPopup.do?objId="+objId;
fn_centerPopup(popup_width, popup_height, url);
}
// 견적서 목록 팝업
function fn_showEstimateList(contractObjId){
$.ajax({
url: "/contractMgmt/getEstimateTemplateList.do",
type: "POST",
data: { objId: contractObjId },
dataType: "json",
success: function(data){
//console.log("견적서 목록 응답:", data); // 디버깅용
if(data.result === "success" && data.list && data.list.length > 0){
var html = '<div style="max-height: 400px; overflow-y: auto;">';
html += '<table style="width: 100%; border-collapse: collapse;">';
html += '<thead><tr style="background-color: #f0f0f0;">';
html += '<th style="border: 1px solid #ddd; padding: 8px;">차수</th>';
html += '<th style="border: 1px solid #ddd; padding: 8px;">견적서 유형</th>';
html += '<th style="border: 1px solid #ddd; padding: 8px;">견적번호</th>';
html += '<th style="border: 1px solid #ddd; padding: 8px;">작성일</th>';
html += '<th style="border: 1px solid #ddd; padding: 8px;">작성자</th>';
html += '</tr></thead><tbody>';
data.list.forEach(function(item){
//console.log("견적서 항목:", item); // 디버깅용
// 대문자/소문자 모두 지원하도록 안전하게 처리
var objid = item.OBJID || item.objid || '';
var templateType = item.TEMPLATE_TYPE || item.template_type || item.templateType || '';
var revision = item.REVISION || item.revision || '';
var templateTypeName = item.TEMPLATE_TYPE_NAME || item.template_type_name || item.templateTypeName || '';
var estimateNo = item.ESTIMATE_NO || item.estimate_no || item.estimateNo || '-';
var regdate = item.REGDATE || item.regdate || '';
var writer = item.WRITER || item.writer || '';
html += '<tr style="cursor: pointer;" onclick="fn_openEstimateByObjId(\'' + objid + '\', \'' + templateType + '\')">';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + revision + '차</td>';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + templateTypeName + '</td>';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + estimateNo + '</td>';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + regdate + '</td>';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + writer + '</td>';
html += '</tr>';
});
html += '</tbody></table></div>';
Swal.fire({
title: '견적서 목록',
html: html,
width: '700px',
showConfirmButton: false,
showCancelButton: true,
cancelButtonText: '닫기'
});
} else {
Swal.fire({
title: '견적서가 없습니다',
text: '작성된 견적서가 없습니다.',
icon: 'info'
});
}
},
error: function(xhr, status, error){
console.error("견적서 목록 조회 오류:", xhr, status, error); // 디버깅용
Swal.fire({
title: '오류',
text: '견적서 목록 조회 중 오류가 발생했습니다.',
icon: 'error'
});
}
});
}
// OBJID로 견적서 열기
function fn_openEstimateByObjId(templateObjId, templateType){
Swal.close();
var popup_width = 900;
var popup_height = 800;
var url = "";
if(templateType === "1"){
// 일반 견적서
url = "/contractMgmt/estimateTemplate1.do?templateObjId="+templateObjId;
} else if(templateType === "2"){
// 장비 견적서
url = "/contractMgmt/estimateTemplate2.do?templateObjId="+templateObjId;
}
window.open(url, "estimateTemplate_"+templateObjId, "width="+popup_width+",height="+popup_height+",menubar=no,scrollbars=yes,resizable=yes");
}
//견적서 양식 열기 (CONTRACT_OBJID로)
function fn_openEstimateTemplate(objId, templateType){
var popup_width = 900;
var popup_height = 800;
var url = "";
if(templateType === "1"){
// 일반 견적서
url = "/contractMgmt/estimateTemplate1.do?objId="+objId;
} else if(templateType === "2"){
// 장비 견적서
url = "/contractMgmt/estimateTemplate2.do?objId="+objId;
}
window.open(url, "estimateTemplate", "width="+popup_width+",height="+popup_height+",menubar=no,scrollbars=yes,resizable=yes");
}
// S/N 목록 팝업 표시
function fn_showSerialNoPopup(serialNoString, contractObjId){
if(!serialNoString || serialNoString === ''){
Swal.fire("S/N 정보가 없습니다.");
return;
}
// "외 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 = '<div style="text-align: left; max-height: 400px; overflow-y: auto;">';
listHtml += '<ol style="padding-left: 20px; margin: 10px 0;">';
serialNumbers.forEach(function(sn){
listHtml += '<li style="padding: 5px 0; font-size: 14px;">' + sn + '</li>';
});
listHtml += '</ol>';
listHtml += '</div>';
Swal.fire({
title: 'S/N 목록',
html: listHtml,
width: 500,
confirmButtonText: '확인',
confirmButtonColor: '#3085d6'
});
}
// 수주취소 팝업 - 품목별 취소 수량 입력
function fn_openOrderCancelPopup(contractObjId){
$.ajax({
url: "/contractMgmt/getContractItems.do",
type: "POST",
data: { contractObjId: contractObjId },
dataType: "json",
success: function(data){
if(data.result !== "success" || !data.items || data.items.length === 0){
Swal.fire("수주 품목 정보가 없습니다.");
return;
}
var items = data.items;
var html = '<div style="max-height: 400px; overflow-y: auto;">';
html += '<table style="width: 100%; border-collapse: collapse;">';
html += '<thead><tr style="background-color: #f0f0f0;">';
html += '<th style="border: 1px solid #ddd; padding: 8px;">품번</th>';
html += '<th style="border: 1px solid #ddd; padding: 8px;">품명</th>';
html += '<th style="border: 1px solid #ddd; padding: 8px;">수주수량</th>';
html += '<th style="border: 1px solid #ddd; padding: 8px;">취소수량</th>';
html += '</tr></thead><tbody>';
items.forEach(function(item, idx){
var objid = item.OBJID || item.objid || '';
var partNo = item.PART_NO || item.part_no || '';
var partName = item.PART_NAME || item.part_name || '';
var orderQty = item.ORDER_QUANTITY || item.order_quantity || '0';
var cancelQty = item.CANCEL_QTY || item.cancel_qty || '';
var orderQtyNum = parseInt(orderQty) || 0;
var maxCancel = orderQtyNum > 0 ? orderQtyNum - 1 : 0;
html += '<tr>';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + partNo + '</td>';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: left;">' + partName + '</td>';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: right;">' + (orderQtyNum > 0 ? Number(orderQtyNum).toLocaleString() : '-') + '</td>';
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">';
if(orderQtyNum > 0){
html += '<input type="number" class="cancel-qty-input" data-objid="' + objid + '" data-order-qty="' + orderQtyNum + '" ';
html += 'value="' + (cancelQty || '') + '" min="0" max="' + maxCancel + '" ';
html += 'style="width: 80px; text-align: right; padding: 4px;" placeholder="0">';
} else {
html += '-';
}
html += '</td>';
html += '</tr>';
});
html += '</tbody></table>';
html += '<p style="margin-top: 10px; color: #888; font-size: 12px;">※ 전체 수량 취소는 불가하며, 부분 수량만 취소 가능합니다.</p>';
html += '</div>';
Swal.fire({
title: '수주취소 수량 입력',
html: html,
width: '700px',
showCancelButton: true,
confirmButtonText: '저장',
cancelButtonText: '닫기',
confirmButtonColor: '#e74c3c',
preConfirm: function(){
var inputs = document.querySelectorAll('.cancel-qty-input');
var itemObjIds = [];
var cancelQtys = [];
var orderQtys = [];
var hasError = false;
inputs.forEach(function(input){
var val = input.value.trim();
var orderQty = parseInt(input.getAttribute('data-order-qty'));
var cancelVal = val === '' ? 0 : parseInt(val);
if(cancelVal < 0){
Swal.showValidationMessage('취소 수량은 0 이상이어야 합니다.');
hasError = true;
return;
}
if(cancelVal >= orderQty){
Swal.showValidationMessage('취소 수량(' + cancelVal + ')은 수주수량(' + orderQty + ')보다 적어야 합니다.');
hasError = true;
return;
}
itemObjIds.push(input.getAttribute('data-objid'));
cancelQtys.push(cancelVal);
orderQtys.push(orderQty);
});
if(hasError) return false;
return { itemObjIds: itemObjIds, cancelQtys: cancelQtys, orderQtys: orderQtys };
}
}).then(function(result){
if(result.isConfirmed && result.value){
var val = result.value;
$.ajax({
url: "/contractMgmt/saveOrderCancelQty.do",
type: "POST",
data: {
itemObjIds: val.itemObjIds.join(","),
cancelQtys: val.cancelQtys.join(","),
orderQtys: val.orderQtys.join(",")
},
dataType: "json",
success: function(res){
if(res.result === "true"){
Swal.fire({ title: '저장 완료', text: res.msg, icon: 'success' });
fn_search();
} else {
Swal.fire({ title: '저장 실패', text: res.msg, icon: 'error' });
}
},
error: function(){
Swal.fire("수주취소 저장 중 오류가 발생했습니다.");
}
});
}
});
},
error: function(){
Swal.fire("품목 정보 조회 중 오류가 발생했습니다.");
}
});
}
//코드값을 받아와서 동적으로 selectbox 생성
function optionJobGroup(code){
var val=code;
var params = "";
var option="";
var combobox = $("#writer");
combobox.empty();
if(val!=""){
params += "codeId="+val;
$.ajax({
type : "POST",
url : "/projectConcept/makewrite.do",
data : params,
dataType:"json",
async: false,
success: function(data){
if(data.RESULT !=""){
option += "<option value=''>전체</option>";
option += data.RESULT;
combobox.append(option);
}
}
});
// alert(Number(lev-1));
//$("#code"+Number(lev-1)).val(code).prop("selected", true);
}else{
option += "<option value=''>전체</option>";
combobox.append(option);
}
}
//코드값을 받아와서 동적으로 selectbox 생성
function makeSelect(code){
var val=code;
var params = "";
var option="";
var combobox = $("#outc_cd6_td");
combobox.empty();
/* <select name="outc_cd6" id="outc_cd6" type="select">
<option value="">선택</option>
</select> */
if(val!="" && val!="PLA03000"){
params += "codeId="+val;
$.ajax({
type : "POST",
url : "/ordermgmt/makeCodeselect.do",
data : params,
dataType:"json",
async: false,
success: function(data){
if(data.RESULT !=""){
option += "<select name='outc_cd6' id='outc_cd6' type='select'>"
option += "<option value=''>선택</option>";
option += data.RESULT;
option += "</select>";
combobox.append(option);
$("#outc_cd6").val("${param.outc_cd6}");
//$("#outc_cd6").select2();
}
}
});
}else{
if(val=="PLA03000"){
option += "<input type='text' name='outc_cd6' id='outc_cd6' value='${param.outc_cd6}'>"
combobox.append(option);
}else{
option += "<select name='outc_cd6' id='outc_cd6' type='select'>"
option += "<option value=''>선택</option>";
option += "</select>";
combobox.append(option);
//$("#outc_cd6").select2();
}
}
}
function saveexcelpop() {
var partLength = $("input[name=partCheckBox]:checked").length;
if(partLength == 0){
Swal.fire('선택된 영업정보가 없습니다.');
return;
}
if(partLength > 1){
Swal.fire('단건씩 선택해 주세요');
return;
}
var orderobjId ="";
$("input[name=partCheckBox]:checked").each(function(){
orderobjId = fnc_checkNull($(this).attr("data-objId").replace(" ",""));
});
var url = "/ordermgmt/openOrderExcelImportPopUp.do?orderobjId="+orderobjId;
var target = "openOrderExcelImportPopUp";
window.open(url, target,"width=1245, height=700, menubars=no, scrollbars=yes, resizable=yes");
}
//프로젝트의 form,detail 팝업을 보여준다.
function openProjectFormPopUp(objId){
window.open("","projectFormPopUp","width=1150, height=676");
var params = "?actionType=regist"
var url = "/project/projectFormPopUp.do"+params;
if("" != objId){
url = "/project/projectDetailPopUp.do";
}
var form = document.form1;
form.objId.value = objId;
form.action = url;
form.target = "projectFormPopUp";
form.submit();
}
</script>
</head>
<body class="bodyNoScroll">
<form name="form1" id="form1" action="" method="post">
<input type="hidden" name="actionType" value="" />
<!-- 대시보드용 -->
<input type="hidden" name="contract_month" id="contract_month" value="${param.contract_month}">
<div class="min_part_enroll">
<div class="content-box">
<div class="content-box-s">
<div class="plm_menu_name_gdnsi">
<h2>
<span>영업관리_주문서관리</span>
</h2>
<div class="btnArea">
<input type="button" value="조회" class="plm_btns" id="btnSearch" name="btnSearch">
<input type="button" value="수주등록" class="plm_btns btnRegist">
<input type="button" value="수주취소" class="plm_btns" id="btnOrderCancel" style="background-color:#e74c3c; color:#fff;">
<input type="button" value="결재상신" class="plm_btns" id="btnApproval">
</div>
</div>
<div id="plmSearchZon">
<!-- 검색필터: 주문유형, 발주번호, 고객사, 품번, 품명, S/N, 수주상태, 발주일(기간), 요청납기(기간) -->
<div style="display: flex; flex-wrap: wrap; gap: 10px 15px; align-items: center;">
<!-- 주문유형 -->
<div style="display: flex; align-items: center; gap: 5px;">
<label for="category_cd">주문유형</label>
<select name="category_cd" id="category_cd" style="width:120px" class="select2" autocomplete="off">
<option value="">선택</option>
${code_map.category_cd}
</select>
</div>
<!-- 발주번호 -->
<div style="display: flex; align-items: center; gap: 5px;">
<label for="search_poNo">발주번호</label>
<input type="text" name="search_poNo" id="search_poNo" value="${param.search_poNo}" style="width:100px;"/>
</div>
<!-- 고객사 -->
<div style="display: flex; align-items: center; gap: 5px;">
<label for="customer_objid">고객사</label>
<select name="customer_objid" id="customer_objid" style="width:150px" class="select2" autocomplete="off">
<option value="">선택</option>
${code_map.customer_cd}
</select>
</div>
<!-- 품번 -->
<div style="display: flex; align-items: center; gap: 5px;">
<label for="search_partNo">품번</label>
<select name="search_partNo" id="search_partNo" class="select2-part" style="width: 120px;">
<option value="">품번 선택</option>
</select>
<input type="hidden" name="search_partObjId" id="search_partObjId" value=""/>
</div>
<!-- 품명 -->
<div style="display: flex; align-items: center; gap: 5px;">
<label for="search_partName">품명</label>
<select name="search_partName" id="search_partName" class="select2-part" style="width: 120px;">
<option value="">품명 선택</option>
</select>
</div>
<!-- S/N -->
<div style="display: flex; align-items: center; gap: 5px;">
<label for="search_serialNo">S/N</label>
<input type="text" name="search_serialNo" id="search_serialNo" value="${param.search_serialNo}" style="width:100px;"/>
</div>
<!-- 수주상태 -->
<div style="display: flex; align-items: center; gap: 5px;">
<label for="contract_result">수주상태</label>
<select name="contract_result" id="contract_result" style="width:120px" class="select2" autocomplete="off">
<option value="">선택</option>
${code_map.result_cd}
</select>
</div>
<!-- 발주일 (기간) -->
<div style="display: flex; align-items: center; gap: 5px;">
<label>발주일</label>
<input type="text" name="order_start_date" id="order_start_date" autocomplete="off" value="${param.order_start_date}" class="date_icon" style="width:90px;"> ~
<input type="text" name="order_end_date" id="order_end_date" autocomplete="off" value="${param.order_end_date}" class="date_icon" style="width:90px;">
</div>
<!-- 요청납기 (기간) -->
<div style="display: flex; align-items: center; gap: 5px;">
<label>요청납기</label>
<input type="text" name="due_start_date" id="due_start_date" autocomplete="off" value="${param.due_start_date}" class="date_icon" style="width:90px;"> ~
<input type="text" name="due_end_date" id="due_end_date" autocomplete="off" value="${param.due_end_date}" class="date_icon" style="width:90px;">
</div>
</div>
</div>
<!-- 주석처리된 검색필터 - 필요시 활성화
<div style="display: flex; align-items: center; gap: 5px;">
<label for="product">제품구분</label>
<select name="product" id="product" style="width:120px" class="select2" autocomplete="off">
<option value="">선택</option>
${code_map.product_cd}
</select>
</div>
<div style="display: flex; align-items: center; gap: 5px;">
<label for="area_cd">국내/해외</label>
<select name="area_cd" id="area_cd" style="width:100px" class="select2" autocomplete="off">
<option value="">선택</option>
<option value="0001220">국내</option>
<option value="0001221">해외</option>
</select>
</div>
<div style="display: flex; align-items: center; gap: 5px;">
<label for="paid_type">유/무상</label>
<select name="paid_type" id="paid_type" style="width:90px" class="select2" autocomplete="off">
<option value="">선택</option>
<option value="paid">유상</option>
<option value="free">무상</option>
</select>
</div>
<div style="display: flex; align-items: center; gap: 5px;">
<label for="contract_currency">견적환종</label>
<select name="contract_currency" id="contract_currency" style="width:100px" class="select2" autocomplete="off">
<option value="">선택</option>
${code_map.contract_currency}
</select>
</div>
-->
<!-- Total 합계 표시 영역 (그리드 위) -->
<div style="padding:5px 10px; background: #f5f5f5;">
<span style="font-weight: bold; font-size: 13px;">
수주 금액 : <span id="totalAmount" style="color: #4CAF50;">0</span> 원
</span>
</div>
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
</div>
</div>
</form>
</body>
</html>