Compare commits
2 Commits
038f64cc9f
...
ca25e0de56
| Author | SHA1 | Date | |
|---|---|---|---|
| ca25e0de56 | |||
| 889231ae27 |
@@ -24,8 +24,23 @@ $(document).ready(function(){
|
||||
//날짜
|
||||
_fnc_datepick();
|
||||
|
||||
// jQuery 및 select2 로드 확인
|
||||
console.log('jQuery loaded:', typeof $ !== 'undefined');
|
||||
console.log('jQuery.fn exists:', typeof $.fn !== 'undefined');
|
||||
console.log('select2 loaded:', typeof $.fn !== 'undefined' && typeof $.fn.select2 !== 'undefined');
|
||||
|
||||
$('.select2').select2();
|
||||
// select2가 로드되었을 때만 초기화
|
||||
if(typeof $.fn !== 'undefined' && typeof $.fn.select2 === 'function') {
|
||||
$('.select2').select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화 (common.js의 새 함수 사용)
|
||||
initPartSelect2Ajax("#search_partNo", "#search_partName", "#search_partObjId", {
|
||||
debug: true // 디버깅 모드 활성화
|
||||
});
|
||||
} else {
|
||||
console.error('select2 라이브러리가 로드되지 않았습니다.');
|
||||
console.error('$.fn:', $.fn);
|
||||
}
|
||||
|
||||
$("#btnSearch").click(function(){
|
||||
$("#page").val("1");
|
||||
@@ -178,7 +193,7 @@ $(document).ready(function(){
|
||||
// 메일 발송 확인
|
||||
Swal.fire({
|
||||
title: '견적서 메일 발송',
|
||||
text: "최종 차수의 견적서를 PDF로 발송하시겠습니까?",
|
||||
text: "최종 차수의 견적서를 발송하시겠습니까?",
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '발송',
|
||||
@@ -194,6 +209,13 @@ $(document).ready(function(){
|
||||
fn_search();
|
||||
});
|
||||
|
||||
// 콤마 추가 함수
|
||||
function addComma(num) {
|
||||
if(!num) return '';
|
||||
var regexp = /\B(?=(\d{3})+(?!\d))/g;
|
||||
return num.toString().replace(regexp, ',');
|
||||
}
|
||||
|
||||
var columns = [
|
||||
{title:'EST_OBJID' ,field:'EST_OBJID' ,visible:false},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '영업번호', field : 'CONTRACT_NO', frozen:true,
|
||||
@@ -288,11 +310,19 @@ var columns = [
|
||||
}
|
||||
},
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '견적단가', field : 'EST_PRICE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '130', title : '견적공급가액', field : 'EST_SUPPLY_PRICE',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false,},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '130', title : '견적공급가액', field : 'EST_TOTAL_AMOUNT',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === '' || value === '0') return '';
|
||||
return addComma(value);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '150', title : '견적원화환산공급가액', field : 'EXC_EST_SUPPLY_PRICE',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false,},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '150', title : '견적원화환산공급가액', field : 'EST_TOTAL_AMOUNT_KRW',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === '' || value === '0') return '';
|
||||
return addComma(value);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '견적환종', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '견적환율', field : 'EXCHANGE_RATE' },
|
||||
@@ -366,6 +396,20 @@ var columns = [
|
||||
|
||||
//var grid;
|
||||
function fn_search(){
|
||||
// Select2 값을 실제 input/select에 명시적으로 설정
|
||||
var partObjId = $("#search_partObjId").val();
|
||||
|
||||
// 디버깅: 검색 조건 확인
|
||||
console.log("품번:", $("#search_partNo").val());
|
||||
console.log("품명:", $("#search_partName").val());
|
||||
console.log("품목 OBJID:", partObjId);
|
||||
|
||||
// 품목 OBJID가 있으면 hidden 필드에 확실히 설정
|
||||
if(partObjId && partObjId !== '') {
|
||||
// 폼 데이터에 명시적으로 추가
|
||||
console.log("품목 검색 조건 설정됨:", partObjId);
|
||||
}
|
||||
|
||||
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/contractMgmt/contractGridList.do", columns, true);
|
||||
}
|
||||
|
||||
@@ -480,6 +524,7 @@ function fn_showEstimateList(contractObjId){
|
||||
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){
|
||||
@@ -493,6 +538,19 @@ function fn_showEstimateList(contractObjId){
|
||||
var estimateNo = item.ESTIMATE_NO || item.estimate_no || item.estimateNo || '-';
|
||||
var regdate = item.REGDATE || item.regdate || '';
|
||||
var writer = item.WRITER || item.writer || '';
|
||||
var apprStatus = item.APPR_STATUS || item.appr_status || item.apprStatus || '-';
|
||||
|
||||
// 결재상태별 색상 지정
|
||||
var statusColor = '#333';
|
||||
if(apprStatus === '결재완료') {
|
||||
statusColor = 'green';
|
||||
} else if(apprStatus === '결재중') {
|
||||
statusColor = 'blue';
|
||||
} else if(apprStatus === '반려') {
|
||||
statusColor = 'red';
|
||||
} else if(apprStatus === '작성중') {
|
||||
statusColor = '#999';
|
||||
}
|
||||
|
||||
html += '<tr style="cursor: pointer;" onclick="fn_openEstimateByObjId(\'' + objid + '\', \'' + templateType + '\')">';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + revision + '차</td>';
|
||||
@@ -500,6 +558,7 @@ function fn_showEstimateList(contractObjId){
|
||||
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 += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center; color: ' + statusColor + '; font-weight: bold;">' + apprStatus + '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
@@ -840,18 +899,23 @@ function openProjectFormPopUp(objId){
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="search_partNo" id="search_partNo" value="${param.search_partNo}"/>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="search_partName" id="search_partName" value="${param.search_partName}"/>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name="search_partNo" id="search_partNo" class="select2-part" style="width: 100%;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_partObjId" id="search_partObjId" value=""/>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
<select name="search_partName" id="search_partName" class="select2-part" style="width: 100%;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -380,6 +380,7 @@
|
||||
}
|
||||
|
||||
var item = {
|
||||
objId: $row.find(".item-objid").val(), // 기존 품목 OBJID (수정 시 유지)
|
||||
partObjId: $row.find(".item-part-objid").val(),
|
||||
partNo: $row.find(".item-part-no").val() ? $row.find(".item-part-no").val().trim() : "",
|
||||
partName: $row.find(".item-part-name").val() ? $row.find(".item-part-name").val().trim() : "",
|
||||
@@ -439,6 +440,7 @@
|
||||
(function() {
|
||||
var itemId = 'item_' + itemCounter++;
|
||||
// 대소문자 모두 시도
|
||||
var savedItemObjId = "<%= item.get("OBJID") != null ? item.get("OBJID") : (item.get("objid") != null ? item.get("objid") : "") %>";
|
||||
var savedPartObjId = "<%= item.get("PART_OBJID") != null ? item.get("PART_OBJID") : (item.get("part_objid") != null ? item.get("part_objid") : "") %>";
|
||||
var savedPartNo = "<%= item.get("PART_NO") != null ? item.get("PART_NO") : (item.get("part_no") != null ? item.get("part_no") : "") %>";
|
||||
var savedPartName = "<%= item.get("PART_NAME") != null ? item.get("PART_NAME") : (item.get("part_name") != null ? item.get("part_name") : "") %>";
|
||||
@@ -455,6 +457,7 @@
|
||||
html += '<select name="item_part_no_select[]" id="PART_NO_' + itemId + '" class="item-part-no-select" style="width:100%;" required>';
|
||||
html += '<option value="">선택</option>';
|
||||
html += '</select>';
|
||||
html += '<input type="hidden" name="item_objid[]" class="item-objid" value="' + savedItemObjId + '" />';
|
||||
html += '<input type="hidden" name="item_part_objid[]" class="item-part-objid" value="' + savedPartObjId + '" />';
|
||||
html += '<input type="hidden" name="item_part_no[]" class="item-part-no" value="' + savedPartNo + '" />';
|
||||
html += '</td>';
|
||||
@@ -1147,6 +1150,7 @@
|
||||
html += '<select name="item_part_no_select[]" id="PART_NO_' + itemId + '" class="item-part-no-select" style="width:100%;" required>';
|
||||
html += '<option value="">선택</option>';
|
||||
html += '</select>';
|
||||
html += '<input type="hidden" name="item_objid[]" class="item-objid" value="" />';
|
||||
html += '<input type="hidden" name="item_part_objid[]" class="item-part-objid" />';
|
||||
html += '<input type="hidden" name="item_part_no[]" class="item-part-no" />';
|
||||
html += '</td>';
|
||||
|
||||
@@ -222,6 +222,9 @@ textarea {
|
||||
// 전역 변수로 저장 (데이터 로드 시 설정됨)
|
||||
var g_contractObjId = "<%=objId%>";
|
||||
var g_templateObjId = "<%=templateObjId%>";
|
||||
var g_exchangeRate = 1; // 환율 (기본값 1)
|
||||
var g_currencyName = "KRW"; // 통화명 (기본값 원화)
|
||||
var g_apprStatus = ""; // 결재상태
|
||||
|
||||
$(function(){
|
||||
|
||||
@@ -256,6 +259,7 @@ $(function(){
|
||||
// 금액 자동 계산
|
||||
$(document).on("change keyup", ".item-qty, .item-price", function(){
|
||||
fn_calculateAmount($(this).closest("tr"));
|
||||
fn_calculateTotal(); // 합계 재계산
|
||||
});
|
||||
|
||||
// 콤마 자동 추가 (동적 요소 포함)
|
||||
@@ -284,9 +288,39 @@ $(function(){
|
||||
// 데이터 로드
|
||||
if("<%=objId%>" !== "" && "<%=objId%>" !== "-1") {
|
||||
fn_loadData();
|
||||
} else {
|
||||
// 초기 로드 시 합계 계산
|
||||
fn_calculateTotal();
|
||||
}
|
||||
});
|
||||
|
||||
// 결재상태에 따라 버튼 표시 제어
|
||||
function fn_controlButtons() {
|
||||
if(g_apprStatus === "결재완료") {
|
||||
// 결재완료된 경우 행추가, 저장 버튼 숨김
|
||||
$("#btnAddItem").hide();
|
||||
$("#btnSave").hide();
|
||||
|
||||
// 모든 입력 필드를 읽기 전용으로 변경
|
||||
$("input, textarea").attr("readonly", true);
|
||||
$("input, textarea").css("background-color", "#f5f5f5");
|
||||
|
||||
// 삭제 버튼 숨김
|
||||
$(".btn-delete-row").hide();
|
||||
} else {
|
||||
// 결재완료가 아닌 경우 버튼 표시
|
||||
$("#btnAddItem").show();
|
||||
$("#btnSave").show();
|
||||
|
||||
// 입력 필드 활성화
|
||||
$("input, textarea").attr("readonly", false);
|
||||
$("input, textarea").css("background-color", "");
|
||||
|
||||
// 삭제 버튼 표시
|
||||
$(".btn-delete-row").show();
|
||||
}
|
||||
}
|
||||
|
||||
// 금액 계산
|
||||
function fn_calculateAmount(row) {
|
||||
var qty = row.find(".item-qty").val().replace(/,/g, "") || "0";
|
||||
@@ -298,6 +332,32 @@ function fn_calculateAmount(row) {
|
||||
}
|
||||
}
|
||||
|
||||
// 합계 계산 (금액 컬럼의 총합)
|
||||
function fn_calculateTotal() {
|
||||
var total = 0;
|
||||
|
||||
// 품목 행만 순회 (계 행, 원화환산 행, 비고 행 제외)
|
||||
$("#itemsTableBody tr").not(".total-row, .total-krw-row, .remarks-row").each(function(){
|
||||
var amount = $(this).find(".item-amount").val() || "0";
|
||||
// 콤마와 ₩ 기호 제거 후 숫자로 변환
|
||||
amount = amount.replace(/,/g, "").replace(/₩/g, "");
|
||||
var numAmount = parseInt(amount) || 0;
|
||||
total += numAmount;
|
||||
});
|
||||
|
||||
// 합계 행에 표시
|
||||
$("#totalAmount").text(addComma(total));
|
||||
|
||||
// 원화환산 금액 계산 및 표시
|
||||
fn_calculateTotalKRW(total);
|
||||
}
|
||||
|
||||
// 원화환산 공급가액 계산
|
||||
function fn_calculateTotalKRW(total) {
|
||||
var totalKRW = total * g_exchangeRate;
|
||||
$("#totalAmountKRW").text(addComma(Math.round(totalKRW)));
|
||||
}
|
||||
|
||||
// 콤마 추가
|
||||
function addComma(num) {
|
||||
var regexp = /\B(?=(\d{3})+(?!\d))/g;
|
||||
@@ -306,10 +366,9 @@ function addComma(num) {
|
||||
|
||||
// 행 추가 함수
|
||||
function fn_addItemRow() {
|
||||
// 비고 행 제외하고 마지막 품목 행 찾기
|
||||
var $lastRow = $("#itemsTableBody tr").not(":last");
|
||||
var lastRowIndex = $lastRow.length;
|
||||
var nextNo = lastRowIndex + 1;
|
||||
// 계 행, 원화환산 행, 비고 행 제외하고 품목 행 개수 계산
|
||||
var itemRows = $("#itemsTableBody tr").not(".total-row, .total-krw-row, .remarks-row");
|
||||
var nextNo = itemRows.length + 1;
|
||||
|
||||
// 새 행 생성
|
||||
var newRow = '<tr>' +
|
||||
@@ -323,8 +382,11 @@ function fn_addItemRow() {
|
||||
'<td class="editable"><input type="text" class="item-note" value=""></td>' +
|
||||
'</tr>';
|
||||
|
||||
// 비고 행 바로 위에 추가 (이벤트는 이미 document에 바인딩되어 있으므로 별도 바인딩 불필요)
|
||||
$("#itemsTableBody tr:last").before(newRow);
|
||||
// 계 행 바로 위에 추가
|
||||
$(".total-row").before(newRow);
|
||||
|
||||
// 합계 재계산
|
||||
fn_calculateTotal();
|
||||
}
|
||||
|
||||
// 데이터 로드
|
||||
@@ -338,12 +400,21 @@ function fn_loadData() {
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data && data.estimate) {
|
||||
// 데이터 바인딩
|
||||
$("#executor").val(data.estimate.EXECUTOR || "");
|
||||
$("#recipient").val(data.estimate.RECIPIENT || "");
|
||||
$("#estimate_no").val(data.estimate.ESTIMATE_NO || "");
|
||||
$("#contact_person").val(data.estimate.CONTACT_PERSON || "");
|
||||
$("#greeting_text").val(data.estimate.GREETING_TEXT || "견적을 요청해 주셔서 대단히 감사합니다.\n하기와 같이 견적서를 제출합니다.");
|
||||
// 환율 정보 저장
|
||||
g_exchangeRate = parseFloat(data.estimate.EXCHANGE_RATE || "1");
|
||||
g_currencyName = data.estimate.CONTRACT_CURRENCY_NAME || "KRW";
|
||||
|
||||
// 결재상태 저장
|
||||
g_apprStatus = data.estimate.APPR_STATUS || "작성중";
|
||||
|
||||
// 데이터 바인딩
|
||||
$("#executor").val(data.estimate.EXECUTOR || "");
|
||||
$("#recipient").val(data.estimate.RECIPIENT || "");
|
||||
$("#estimate_no").val(data.estimate.ESTIMATE_NO || "");
|
||||
$("#contact_person").val(data.estimate.CONTACT_PERSON || "");
|
||||
$("#greeting_text").val(data.estimate.GREETING_TEXT || "견적을 요청해 주셔서 대단히 감사합니다.\n하기와 같이 견적서를 제출합니다.");
|
||||
$("#manager_name").val(data.estimate.MANAGER_NAME || "영업부");
|
||||
$("#manager_contact").val(data.estimate.MANAGER_CONTACT || "");
|
||||
|
||||
// 품목 데이터 로드
|
||||
if(data.items && data.items.length > 0) {
|
||||
@@ -362,15 +433,47 @@ function fn_loadData() {
|
||||
itemsHtml += '<td class="editable"><input type="text" class="item-note" value="' + (item.NOTE || '') + '"></td>';
|
||||
itemsHtml += '</tr>';
|
||||
}
|
||||
$("#itemsTableBody").html(itemsHtml);
|
||||
}
|
||||
|
||||
// 계 행 추가
|
||||
itemsHtml += '<tr class="total-row">';
|
||||
itemsHtml += '<td colspan="6" style="text-align: center; font-weight: bold; background-color: #f0f0f0;">계</td>';
|
||||
itemsHtml += '<td class="text-right" style="font-weight: bold; background-color: #f0f0f0;"><span id="totalAmount">0</span></td>';
|
||||
itemsHtml += '<td style="background-color: #f0f0f0;"></td>';
|
||||
itemsHtml += '</tr>';
|
||||
|
||||
// 원화환산 공급가액 행 추가
|
||||
itemsHtml += '<tr class="total-krw-row">';
|
||||
itemsHtml += '<td colspan="6" style="text-align: center; font-weight: bold; background-color: #e8f4f8;">원화환산 공급가액 (KRW)</td>';
|
||||
itemsHtml += '<td class="text-right" style="font-weight: bold; background-color: #e8f4f8;"><span id="totalAmountKRW">0</span></td>';
|
||||
itemsHtml += '<td style="background-color: #e8f4f8;"></td>';
|
||||
itemsHtml += '</tr>';
|
||||
|
||||
// 비고 행 추가
|
||||
itemsHtml += '<tr class="remarks-row">';
|
||||
itemsHtml += '<td colspan="8" style="height: 100px; vertical-align: top; padding: 10px; text-align: left;">';
|
||||
itemsHtml += '<div style="font-weight: bold; margin-bottom: 10px; text-align: left;"><비고></div>';
|
||||
itemsHtml += '<textarea id="note_remarks" style="width: 100%; height: 70px; border: none; resize: none; font-family: inherit; font-size: 10pt; text-align: left;"></textarea>';
|
||||
itemsHtml += '</td>';
|
||||
itemsHtml += '</tr>';
|
||||
|
||||
$("#itemsTableBody").html(itemsHtml);
|
||||
|
||||
// 비고 로드
|
||||
$("#note1").val(data.estimate.NOTE1 || "1. 견적유효기간: 일");
|
||||
$("#note2").val(data.estimate.NOTE2 || "2. 납품기간: 발주 후 1주 이내");
|
||||
$("#note3").val(data.estimate.NOTE3 || "3. VAT 별도");
|
||||
$("#note4").val(data.estimate.NOTE4 || "4. 결제 조건 : 기존 결제조건에 따름.");
|
||||
// 비고 로드 (테이블 생성 직후)
|
||||
$("#note_remarks").val(data.estimate.NOTE_REMARKS || "");
|
||||
|
||||
// 합계 계산
|
||||
fn_calculateTotal();
|
||||
}
|
||||
|
||||
// 하단 비고 로드
|
||||
$("#note1").val(data.estimate.NOTE1 || "1. 견적유효기간: 일");
|
||||
$("#note2").val(data.estimate.NOTE2 || "2. 납품기간: 발주 후 1주 이내");
|
||||
$("#note3").val(data.estimate.NOTE3 || "3. VAT 별도");
|
||||
$("#note4").val(data.estimate.NOTE4 || "4. 결제 조건 : 기존 결제조건에 따름.");
|
||||
|
||||
// 결재상태에 따라 버튼 제어
|
||||
fn_controlButtons();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
@@ -397,29 +500,45 @@ function fn_loadTemplateData(templateObjId){
|
||||
g_contractObjId = contractObjId;
|
||||
}
|
||||
|
||||
// 대문자/소문자 모두 지원
|
||||
// 환율 정보 저장
|
||||
g_exchangeRate = parseFloat(template.EXCHANGE_RATE || template.exchange_rate || template.exchangeRate || "1");
|
||||
g_currencyName = template.CONTRACT_CURRENCY_NAME || template.contract_currency_name || template.contractCurrencyName || "KRW";
|
||||
|
||||
// 결재상태 저장
|
||||
g_apprStatus = template.APPR_STATUS || template.appr_status || template.apprStatus || "작성중";
|
||||
|
||||
// 대문자/소문자 모두 지원
|
||||
var executor = template.EXECUTOR || template.executor || "";
|
||||
var recipient = template.RECIPIENT || template.recipient || "";
|
||||
var estimateNo = template.ESTIMATE_NO || template.estimate_no || template.estimateNo || "";
|
||||
var contactPerson = template.CONTACT_PERSON || template.contact_person || template.contactPerson || "";
|
||||
var greetingText = template.GREETING_TEXT || template.greeting_text || template.greetingText || "";
|
||||
var note1 = template.NOTE1 || template.note1 || "";
|
||||
var note2 = template.NOTE2 || template.note2 || "";
|
||||
var note3 = template.NOTE3 || template.note3 || "";
|
||||
var note4 = template.NOTE4 || template.note4 || "";
|
||||
|
||||
// 기본 정보 채우기
|
||||
$("#executor").val(executor);
|
||||
$("#recipient").val(recipient);
|
||||
$("#estimate_no").val(estimateNo);
|
||||
$("#contact_person").val(contactPerson);
|
||||
$("#greeting_text").val(greetingText);
|
||||
$("#note1").val(note1);
|
||||
$("#note2").val(note2);
|
||||
$("#note3").val(note3);
|
||||
$("#note4").val(note4);
|
||||
|
||||
// 품목 데이터 채우기
|
||||
var note1 = template.NOTE1 || template.note1 || "";
|
||||
var note2 = template.NOTE2 || template.note2 || "";
|
||||
var note3 = template.NOTE3 || template.note3 || "";
|
||||
var note4 = template.NOTE4 || template.note4 || "";
|
||||
var managerName = template.MANAGER_NAME || template.manager_name || template.managerName || "영업부";
|
||||
var managerContact = template.MANAGER_CONTACT || template.manager_contact || template.managerContact || "";
|
||||
|
||||
// 기본 정보 채우기
|
||||
$("#executor").val(executor);
|
||||
$("#recipient").val(recipient);
|
||||
$("#estimate_no").val(estimateNo);
|
||||
$("#contact_person").val(contactPerson);
|
||||
$("#greeting_text").val(greetingText);
|
||||
$("#manager_name").val(managerName);
|
||||
$("#manager_contact").val(managerContact);
|
||||
|
||||
// 하단 비고 로드
|
||||
$("#note1").val(note1);
|
||||
$("#note2").val(note2);
|
||||
$("#note3").val(note3);
|
||||
$("#note4").val(note4);
|
||||
|
||||
// 테이블 내 비고는 나중에 설정 (textarea 생성 후)
|
||||
var noteRemarks = template.NOTE_REMARKS || template.note_remarks || template.noteRemarks || "";
|
||||
|
||||
// 품목 데이터 채우기
|
||||
if(data.items && data.items.length > 0){
|
||||
$("#itemsTableBody").empty();
|
||||
data.items.forEach(function(item, idx){
|
||||
@@ -446,23 +565,55 @@ function fn_loadTemplateData(templateObjId){
|
||||
row.append('<td class="editable"><input type="text" class="item-note" value="' + note + '"></td>');
|
||||
$("#itemsTableBody").append(row);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.error("데이터 로드 실패:", data);
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
|
||||
// 계 행 추가
|
||||
var totalRow = $("<tr class='total-row'>");
|
||||
totalRow.append('<td colspan="6" style="text-align: center; font-weight: bold; background-color: #f0f0f0;">계</td>');
|
||||
totalRow.append('<td class="text-right" style="font-weight: bold; background-color: #f0f0f0;"><span id="totalAmount">0</span></td>');
|
||||
totalRow.append('<td style="background-color: #f0f0f0;"></td>');
|
||||
$("#itemsTableBody").append(totalRow);
|
||||
|
||||
// 원화환산 공급가액 행 추가
|
||||
var totalKRWRow = $("<tr class='total-krw-row'>");
|
||||
totalKRWRow.append('<td colspan="6" style="text-align: center; font-weight: bold; background-color: #e8f4f8;">원화환산 공급가액 (KRW)</td>');
|
||||
totalKRWRow.append('<td class="text-right" style="font-weight: bold; background-color: #e8f4f8;"><span id="totalAmountKRW">0</span></td>');
|
||||
totalKRWRow.append('<td style="background-color: #e8f4f8;"></td>');
|
||||
$("#itemsTableBody").append(totalKRWRow);
|
||||
|
||||
// 비고 행 추가
|
||||
var remarksRow = $("<tr class='remarks-row'>");
|
||||
remarksRow.append('<td colspan="8" style="height: 100px; vertical-align: top; padding: 10px; text-align: left;">' +
|
||||
'<div style="font-weight: bold; margin-bottom: 10px; text-align: left;"><비고></div>' +
|
||||
'<textarea id="note_remarks" style="width: 100%; height: 70px; border: none; resize: none; font-family: inherit; font-size: 10pt; text-align: left;"></textarea>' +
|
||||
'</td>');
|
||||
$("#itemsTableBody").append(remarksRow);
|
||||
|
||||
// 테이블 내 비고 값 설정 (textarea 생성 직후)
|
||||
$("#note_remarks").val(noteRemarks);
|
||||
|
||||
// 합계 계산
|
||||
fn_calculateTotal();
|
||||
|
||||
// 결재상태에 따라 버튼 제어
|
||||
fn_controlButtons();
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.error("AJAX 오류:", xhr, status, error);
|
||||
} else {
|
||||
console.error("데이터 로드 실패:", data);
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.error("AJAX 오류:", xhr, status, error);
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 저장
|
||||
function fn_save() {
|
||||
var items = [];
|
||||
$("#itemsTableBody tr").each(function(idx) {
|
||||
// 계 행, 원화환산 행, 비고 행 제외하고 품목 행만 저장
|
||||
$("#itemsTableBody tr").not(".total-row, .total-krw-row, .remarks-row").each(function(idx) {
|
||||
var row = $(this);
|
||||
var unitPrice = row.find(".item-price").val() || "";
|
||||
var amount = row.find(".item-amount").val() || "";
|
||||
@@ -488,6 +639,10 @@ function fn_save() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 합계 계산 (콤마 제거한 순수 숫자)
|
||||
var totalAmount = $("#totalAmount").text().replace(/,/g, "");
|
||||
var totalAmountKRW = $("#totalAmountKRW").text().replace(/,/g, "");
|
||||
|
||||
var formData = {
|
||||
objId: contractObjId,
|
||||
template_type: "1",
|
||||
@@ -496,6 +651,11 @@ function fn_save() {
|
||||
estimate_no: $("#estimate_no").val(),
|
||||
contact_person: $("#contact_person").val(),
|
||||
greeting_text: $("#greeting_text").val(),
|
||||
total_amount: totalAmount, // 합계
|
||||
total_amount_krw: totalAmountKRW, // 원화환산 공급가액
|
||||
manager_name: $("#manager_name").val(), // 담당자
|
||||
manager_contact: $("#manager_contact").val(), // 연락처
|
||||
note_remarks: $("#note_remarks").val(), // 테이블 내 비고
|
||||
note1: $("#note1").val(),
|
||||
note2: $("#note2").val(),
|
||||
note3: $("#note3").val(),
|
||||
@@ -565,10 +725,10 @@ function fn_save() {
|
||||
<div class="company-stamp-text">㈊알피에스<br>RPS CO., LTD<br>대표이사이동준</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: left; font-size: 9pt; line-height: 1.8; padding: 0 5px;">
|
||||
담당자 : 영업부<br>
|
||||
연락처 :
|
||||
</div>
|
||||
<div style="text-align: left; font-size: 9pt; line-height: 1.8; padding: 0 5px;">
|
||||
담당자 : <input type="text" id="manager_name" value="영업부" style="width: 80px; border: none; border-bottom: 1px solid #ddd; font-size: 9pt; padding: 2px;"><br>
|
||||
연락처 : <input type="text" id="manager_contact" value="" style="width: 120px; border: none; border-bottom: 1px solid #ddd; font-size: 9pt; padding: 2px;">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -637,7 +797,20 @@ function fn_save() {
|
||||
<td class="text-right editable"><input type="text" class="item-amount" value="" readonly></td>
|
||||
<td class="editable"><input type="text" class="item-note" value=""></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- 계 행 -->
|
||||
<tr class="total-row">
|
||||
<td colspan="6" style="text-align: center; font-weight: bold; background-color: #f0f0f0;">계</td>
|
||||
<td class="text-right" style="font-weight: bold; background-color: #f0f0f0;"><span id="totalAmount">0</span></td>
|
||||
<td style="background-color: #f0f0f0;"></td>
|
||||
</tr>
|
||||
<!-- 원화환산 공급가액 행 -->
|
||||
<tr class="total-krw-row">
|
||||
<td colspan="6" style="text-align: center; font-weight: bold; background-color: #e8f4f8;">원화환산 공급가액 (KRW)</td>
|
||||
<td class="text-right" style="font-weight: bold; background-color: #e8f4f8;"><span id="totalAmountKRW">0</span></td>
|
||||
<td style="background-color: #e8f4f8;"></td>
|
||||
</tr>
|
||||
<!-- 비고 행 -->
|
||||
<tr class="remarks-row">
|
||||
<td colspan="8" style="height: 100px; vertical-align: top; padding: 10px; text-align: left;">
|
||||
<div style="font-weight: bold; margin-bottom: 10px; text-align: left;"><비고></div>
|
||||
<textarea id="note_remarks" style="width: 100%; height: 70px; border: none; resize: none; font-family: inherit; font-size: 10pt; text-align: left;"></textarea>
|
||||
|
||||
@@ -27,6 +27,11 @@ $(document).ready(function(){
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화 (common.js의 새 함수 사용)
|
||||
initPartSelect2Ajax("#search_partNo", "#search_partName", "#search_partObjId", {
|
||||
debug: false // 디버깅 모드 비활성화
|
||||
});
|
||||
|
||||
$("#btnSearch").click(function(){
|
||||
$("#page").val("1");
|
||||
fn_search();
|
||||
@@ -57,7 +62,7 @@ $(document).ready(function(){
|
||||
return false;
|
||||
} else {
|
||||
var contractObjId = fnc_checkNull(selectedData[0].OBJID);
|
||||
var popup_width = 1000;
|
||||
var popup_width = 1400;
|
||||
var popup_height = 450;
|
||||
var params = "?actionType=regist&contractObjId="+contractObjId;
|
||||
var url = "/contractMgmt/orderRegistFormPopup.do"+params;
|
||||
@@ -100,36 +105,55 @@ var columns = [
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '주문유형', field : 'CATEGORY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제품구분', field : 'PRODUCT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '국내/해외', field : 'AREA_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '85', title : '국내/해외', field : 'AREA_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '접수일', field : 'RECEIPT_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '유/무상', field : 'PAID_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품번', field : 'PART_NO' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품명', field : 'PART_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '150', title : 'S/N', field : 'SERIAL_NO',
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'ITEM_SUMMARY' },
|
||||
//품번, 품명 추가 시 사용
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품번', field : 'PART_NO' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품명', field : 'PART_NAME' },
|
||||
|
||||
//S/N 추가 시 사용
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '150', title : 'S/N', field : 'SERIAL_NO',
|
||||
// formatter: function(cell, formatterParams, onRendered){
|
||||
// var value = fnc_checkNull(cell.getValue());
|
||||
// if(value === '') return '';
|
||||
//
|
||||
// // 쉼표로 구분된 S/N 개수 계산
|
||||
// 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>';
|
||||
//
|
||||
// // 2개 이상이면 "첫번째 외 N개" 형식
|
||||
// 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);
|
||||
// fn_showSerialNoPopup(serialNo);
|
||||
// }
|
||||
// },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '120', title : '요청납기', field : 'EARLIEST_DUE_DATE',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === '') return '';
|
||||
var dueDate = fnc_checkNull(cell.getValue());
|
||||
var otherCount = fnc_checkNull(cell.getData().OTHER_DUE_DATE_COUNT);
|
||||
|
||||
// 쉼표로 구분된 S/N 개수 계산
|
||||
var serialNumbers = value.split(',').map(function(s){ return s.trim(); }).filter(function(s){ return s !== ''; });
|
||||
var count = serialNumbers.length;
|
||||
if(dueDate === '') return '';
|
||||
|
||||
if(count === 0) return '';
|
||||
if(count === 1) return '<a href="javascript:void(0);">' + serialNumbers[0] + '</a>';
|
||||
// 다른 납기가 있으면 "날짜 외 N건" 형식으로 표시
|
||||
if(otherCount && parseInt(otherCount) > 0){
|
||||
return dueDate + ' 외 ' + otherCount + '건';
|
||||
}
|
||||
|
||||
// 2개 이상이면 "첫번째 외 N개" 형식
|
||||
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);
|
||||
fn_showSerialNoPopup(serialNo);
|
||||
return dueDate;
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '수량', field : 'QUANTITY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '요청납기', field : 'DUE_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객요청사항', field : 'CUSTOMER_REQUEST' },
|
||||
},
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '수량', field : 'QUANTITY' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '요청납기', field : 'DUE_DATE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객요청사항', field : 'CUSTOMER_REQUEST' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '수주상태', field : 'CONTRACT_RESULT_NAME' },
|
||||
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주번호', field : 'PO_NO' },
|
||||
@@ -142,21 +166,23 @@ var columns = [
|
||||
}
|
||||
},
|
||||
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '단가', field : 'ORDER_UNIT_PRICE',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '공급가액', field : 'ORDER_SUPPLY_PRICE',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '부가세', field : 'ORDER_VAT',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '총액', field : 'ORDER_TOTAL_AMOUNT',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
},
|
||||
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '환종', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '환율', field : 'EXCHANGE_RATE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '단가', field : 'ORDER_UNIT_PRICE',
|
||||
// formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
// },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '120', title : '수주공급가액', field : 'ORDER_SUPPLY_PRICE_SUM',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '수주부가세', field : 'ORDER_VAT_SUM',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '수주총액', field : 'ORDER_TOTAL_AMOUNT_SUM',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '120', title : '수주원화총액', field : 'ORDER_TOTAL_AMOUNT_KRW',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '견적환종', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '견적환율', field : 'EXCHANGE_RATE' },
|
||||
];
|
||||
|
||||
//var grid;
|
||||
@@ -241,7 +267,7 @@ function fn_FileRegist(objId, docType, docTypeName){
|
||||
|
||||
//영업활동등록 상세
|
||||
function fn_projectConceptDetail(objId){
|
||||
var popup_width = 1000;
|
||||
var popup_width = 1400;
|
||||
var popup_height = 560;
|
||||
var url = "/contractMgmt/estimateRegistFormPopup.do?objId="+objId;
|
||||
|
||||
@@ -578,18 +604,23 @@ function openProjectFormPopUp(objId){
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="search_partNo" id="search_partNo" value="${param.search_partNo}"/>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="search_partName" id="search_partName" value="${param.search_partName}"/>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name="search_partNo" id="search_partNo" class="select2-part" style="width: 100%;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_partObjId" id="search_partObjId" value=""/>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
<select name="search_partName" id="search_partName" class="select2-part" style="width: 100%;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -17,12 +17,48 @@
|
||||
.fileListscrollTbody td {
|
||||
font-size: 11px !important;
|
||||
}
|
||||
|
||||
/* 품목 테이블 스타일 */
|
||||
#itemListTable {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
#itemListTable th,
|
||||
#itemListTable td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#itemListTable th {
|
||||
background-color: #f5f5f5;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#itemListTable input[type="text"],
|
||||
#itemListTable input[type="number"] {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
// 품목 관리 변수
|
||||
var itemCounter = 1;
|
||||
var itemList = [];
|
||||
|
||||
$(function() {
|
||||
// 숫자 입력 필드에 콤마 자동 추가
|
||||
$("input:text[numberOnly]").on("keyup", function() {
|
||||
// 숫자 입력 필드에 콤마 자동 추가 및 금액 계산
|
||||
$(document).on("keyup", "input:text[numberOnly]", function() {
|
||||
$(this).val(addComma($(this).val().replace(/[^0-9]/g, "")));
|
||||
|
||||
// 수주수량 또는 수주단가가 변경되면 자동 계산
|
||||
if($(this).hasClass("item-quantity") || $(this).hasClass("item-unit-price")) {
|
||||
var itemId = $(this).closest("tr").attr("id");
|
||||
if(itemId) {
|
||||
fn_calculateItemAmount(itemId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 페이지 로드 시 기존 값에 콤마 표시
|
||||
@@ -48,93 +84,223 @@
|
||||
self.close();
|
||||
});
|
||||
|
||||
// 단가/수량 변경 시 금액 자동 계산
|
||||
$("#unit_price, #quantity").on("change keyup", function() {
|
||||
fn_calculateAmount();
|
||||
});
|
||||
|
||||
// 공급가액 변경 시 부가세/총액 자동 계산
|
||||
$("#supply_price").on("change keyup", function() {
|
||||
fn_calculateTax();
|
||||
});
|
||||
|
||||
// 환종 변경 시 환율 자동 로드
|
||||
$("#currency").change(function() {
|
||||
var selectedCurrency = $(this).val();
|
||||
if(selectedCurrency && selectedCurrency !== '') {
|
||||
fn_loadExchangeRate(selectedCurrency);
|
||||
} else {
|
||||
$("#exchange_rate").val('');
|
||||
}
|
||||
});
|
||||
// 기존 품목 데이터 로드 (CONTRACT_ITEM에서)
|
||||
fn_loadContractItems();
|
||||
});
|
||||
|
||||
// 콤마 추가 함수
|
||||
function addComma(data) {
|
||||
if(!data) return '';
|
||||
return data.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
// 콤마 제거 함수
|
||||
function removeComma(data) {
|
||||
if(!data) return '';
|
||||
return data.toString().replace(/,/g, "");
|
||||
}
|
||||
|
||||
// 금액 자동 계산 (단가 × 수량 = 공급가액)
|
||||
function fn_calculateAmount() {
|
||||
var unitPrice = removeComma($("#unit_price").val()) || 0;
|
||||
var quantity = removeComma($("#quantity").val()) || 0;
|
||||
|
||||
var supplyPrice = parseInt(unitPrice) * parseInt(quantity);
|
||||
|
||||
$("#supply_price").val(addComma(supplyPrice));
|
||||
|
||||
// 공급가액 변경 시 부가세/총액도 재계산
|
||||
fn_calculateTax();
|
||||
// 품목 행 추가 (사용 안함 - CONTRACT_ITEM에서만 로드)
|
||||
function fn_addItemRow() {
|
||||
alert("품목은 견적요청에서 등록된 항목만 표시됩니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 부가세/총액 자동 계산 (공급가액 × 10% = 부가세, 공급가액 + 부가세 = 총액)
|
||||
function fn_calculateTax() {
|
||||
var supplyPrice = parseInt(removeComma($("#supply_price").val())) || 0;
|
||||
// 품목 행 삭제
|
||||
function fn_removeItemRow(itemId) {
|
||||
if(confirm("이 품목을 삭제하시겠습니까?")) {
|
||||
$("#" + itemId).remove();
|
||||
|
||||
// itemList에서 제거
|
||||
for(var i = 0; i < itemList.length; i++) {
|
||||
if(itemList[i].id == itemId) {
|
||||
itemList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 번호 재정렬
|
||||
fn_reorderItems();
|
||||
|
||||
// 품목이 없으면 메시지 표시
|
||||
if($("#itemListBody tr.item-row").length == 0) {
|
||||
$("#itemListBody").html('<tr id="noItemRow"><td colspan="9" style="text-align:center; padding:30px; color:#999;">품목 추가 버튼을 클릭하여 품목을 등록하세요.</td></tr>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 품목 번호 재정렬
|
||||
function fn_reorderItems() {
|
||||
$("#itemListBody tr.item-row").each(function(index) {
|
||||
$(this).find("td:first").text(index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
// 품목별 금액 계산 (수량 × 단가 = 공급가액, 공급가액 × 10% = 부가세, 공급가액 + 부가세 = 총액)
|
||||
function fn_calculateItemAmount(itemId) {
|
||||
var quantity = parseInt(removeComma($("#" + itemId + " .item-quantity").val())) || 0;
|
||||
var unitPrice = parseInt(removeComma($("#" + itemId + " .item-unit-price").val())) || 0;
|
||||
|
||||
var vat = Math.round(supplyPrice * 0.1); // 부가세 10%
|
||||
var supplyPrice = quantity * unitPrice;
|
||||
var vat = Math.round(supplyPrice * 0.1);
|
||||
var totalAmount = supplyPrice + vat;
|
||||
|
||||
$("#vat").val(addComma(vat));
|
||||
$("#total_amount").val(addComma(totalAmount));
|
||||
$("#" + itemId + " .item-supply-price").val(addComma(supplyPrice));
|
||||
$("#" + itemId + " .item-vat").val(addComma(vat));
|
||||
$("#" + itemId + " .item-total-amount").val(addComma(totalAmount));
|
||||
}
|
||||
|
||||
// 기존 품목 데이터 로드 (CONTRACT_ITEM 테이블에서)
|
||||
function fn_loadContractItems() {
|
||||
var contractObjId = $("#contractObjId").val();
|
||||
if(!contractObjId || contractObjId === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "/contractMgmt/getContractItems.do",
|
||||
type: "POST",
|
||||
data: { contractObjId: contractObjId },
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data && data.items && data.items.length > 0) {
|
||||
$("#noItemRow").remove();
|
||||
|
||||
for(var i = 0; i < data.items.length; i++) {
|
||||
var item = data.items[i];
|
||||
var itemId = "item_" + itemCounter++;
|
||||
|
||||
// S/N 처리 (쉼표로 구분된 값)
|
||||
var serialNo = item.SERIAL_NO || '';
|
||||
var serialNoDisplay = serialNo;
|
||||
if(serialNo) {
|
||||
var snArray = serialNo.split(',').map(function(s){ return s.trim(); }).filter(function(s){ return s !== ''; });
|
||||
if(snArray.length > 1) {
|
||||
serialNoDisplay = snArray[0] + ' 외 ' + (snArray.length - 1) + '개';
|
||||
}
|
||||
}
|
||||
|
||||
var html = '<tr id="' + itemId + '" class="item-row">';
|
||||
html += '<td>' + (i + 1) + '</td>';
|
||||
html += '<td><input type="text" class="item-part-no" value="' + (item.PART_NO || '') + '" readonly style="background:#f5f5f5;" /></td>';
|
||||
html += '<td><input type="text" class="item-part-name" value="' + (item.PART_NAME || '') + '" readonly style="background:#f5f5f5;" /></td>';
|
||||
html += '<td><input type="text" class="item-serial-no" value="' + serialNoDisplay + '" readonly style="background:#f5f5f5;" title="' + serialNo + '" /></td>';
|
||||
html += '<td><input type="text" class="item-quantity" value="' + (item.ORDER_QUANTITY || item.QUANTITY || '') + '" numberOnly required /></td>';
|
||||
html += '<td><input type="text" class="item-unit-price" value="' + (item.ORDER_UNIT_PRICE || '') + '" numberOnly required /></td>';
|
||||
html += '<td><input type="text" class="item-supply-price" value="' + (item.ORDER_SUPPLY_PRICE || '') + '" numberOnly readonly style="background:#f5f5f5;" /></td>';
|
||||
html += '<td><input type="text" class="item-vat" value="' + (item.ORDER_VAT || '') + '" numberOnly readonly style="background:#f5f5f5;" /></td>';
|
||||
html += '<td><input type="text" class="item-total-amount" value="' + (item.ORDER_TOTAL_AMOUNT || '') + '" numberOnly readonly style="background:#f5f5f5;" /></td>';
|
||||
html += '<td style="text-align:center;">-</td>'; // 삭제 불가
|
||||
html += '<input type="hidden" class="item-objid" value="' + (item.OBJID || '') + '" />';
|
||||
html += '<input type="hidden" class="item-contract-item-objid" value="' + (item.OBJID || '') + '" />'; // CONTRACT_ITEM의 OBJID
|
||||
html += '<input type="hidden" class="item-part-objid" value="' + (item.PART_OBJID || '') + '" />';
|
||||
html += '<input type="hidden" class="item-serial-no-full" value="' + serialNo + '" />'; // 전체 S/N
|
||||
html += '</tr>';
|
||||
|
||||
$("#itemListBody").append(html);
|
||||
|
||||
// 콤마 추가
|
||||
$("#" + itemId + " .item-quantity").val(addComma($("#" + itemId + " .item-quantity").val()));
|
||||
$("#" + itemId + " .item-unit-price").val(addComma($("#" + itemId + " .item-unit-price").val()));
|
||||
$("#" + itemId + " .item-supply-price").val(addComma($("#" + itemId + " .item-supply-price").val()));
|
||||
$("#" + itemId + " .item-vat").val(addComma($("#" + itemId + " .item-vat").val()));
|
||||
$("#" + itemId + " .item-total-amount").val(addComma($("#" + itemId + " .item-total-amount").val()));
|
||||
|
||||
// 이벤트 바인딩 (클로저 문제 해결)
|
||||
(function(id) {
|
||||
$("#" + id + " .item-quantity, #" + id + " .item-unit-price").on("change keyup", function() {
|
||||
fn_calculateItemAmount(id);
|
||||
});
|
||||
})(itemId);
|
||||
|
||||
// S/N 클릭 시 전체 S/N 보기
|
||||
$("#" + itemId + " .item-serial-no").on("click", function() {
|
||||
var fullSn = $(this).attr("title");
|
||||
if(fullSn && fullSn !== '') {
|
||||
var snArray = fullSn.split(',').map(function(s){ return s.trim(); });
|
||||
var snList = '<ol style="text-align:left; padding-left:20px;">';
|
||||
for(var j = 0; j < snArray.length; j++) {
|
||||
snList += '<li>' + snArray[j] + '</li>';
|
||||
}
|
||||
snList += '</ol>';
|
||||
Swal.fire({
|
||||
title: 'S/N 목록',
|
||||
html: snList,
|
||||
width: 500,
|
||||
confirmButtonText: '확인'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 품목 정보 저장
|
||||
itemList.push({
|
||||
id: itemId
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
console.log("품목 데이터 로드 실패");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 저장 함수
|
||||
function fn_save() {
|
||||
if (fnc_valitate("form1")) {
|
||||
var message = "수정";
|
||||
if ("${actionType}" == 'regist') {
|
||||
message = "등록";
|
||||
}
|
||||
if (confirm(message + "하시겠습니까?")) {
|
||||
// 콤마 제거
|
||||
$("#unit_price").val(removeComma($("#unit_price").val()));
|
||||
$("#supply_price").val(removeComma($("#supply_price").val()));
|
||||
$("#vat").val(removeComma($("#vat").val()));
|
||||
$("#total_amount").val(removeComma($("#total_amount").val()));
|
||||
$("#quantity").val(removeComma($("#quantity").val()));
|
||||
|
||||
$.ajax({
|
||||
url : "/contractMgmt/saveOrderInfo.do",
|
||||
type : "POST",
|
||||
data : $("#form1").serialize(),
|
||||
dataType : "json",
|
||||
success : function(data) {
|
||||
alert(data.msg);
|
||||
if(opener && opener.fn_search) {
|
||||
opener.fn_search();
|
||||
}
|
||||
self.close();
|
||||
},
|
||||
error : function(jqxhr, status, error) {
|
||||
alert("저장 중 오류가 발생했습니다.");
|
||||
// 품목 검증
|
||||
if($("#itemListBody tr.item-row").length == 0) {
|
||||
alert("품목을 하나 이상 추가해주세요.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 기본정보 검증
|
||||
if (!fnc_valitate("form1")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 품목 데이터 수집
|
||||
var items = [];
|
||||
$("#itemListBody tr.item-row").each(function() {
|
||||
var $row = $(this);
|
||||
items.push({
|
||||
contractItemObjId: $row.find(".item-contract-item-objid").val(), // CONTRACT_ITEM의 OBJID
|
||||
partObjId: $row.find(".item-part-objid").val(),
|
||||
partNo: $row.find(".item-part-no").val(),
|
||||
partName: $row.find(".item-part-name").val(),
|
||||
serialNo: $row.find(".item-serial-no-full").val(),
|
||||
orderQuantity: removeComma($row.find(".item-quantity").val()),
|
||||
orderUnitPrice: removeComma($row.find(".item-unit-price").val()),
|
||||
orderSupplyPrice: removeComma($row.find(".item-supply-price").val()),
|
||||
orderVat: removeComma($row.find(".item-vat").val()),
|
||||
orderTotalAmount: removeComma($row.find(".item-total-amount").val())
|
||||
});
|
||||
});
|
||||
|
||||
var message = "수정";
|
||||
if ("${actionType}" == 'regist') {
|
||||
message = "등록";
|
||||
}
|
||||
|
||||
if (confirm(message + "하시겠습니까?")) {
|
||||
// 품목 데이터를 JSON으로 변환
|
||||
$("#items_json").val(JSON.stringify(items));
|
||||
|
||||
$.ajax({
|
||||
url : "/contractMgmt/saveOrderInfo.do",
|
||||
type : "POST",
|
||||
data : $("#form1").serialize(),
|
||||
dataType : "json",
|
||||
success : function(data) {
|
||||
alert(data.msg);
|
||||
if(opener && opener.fn_search) {
|
||||
opener.fn_search();
|
||||
}
|
||||
});
|
||||
}
|
||||
self.close();
|
||||
},
|
||||
error : function(jqxhr, status, error) {
|
||||
alert("저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,24 +316,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 환율 자동 로드
|
||||
function fn_loadExchangeRate(currencyCode) {
|
||||
$.ajax({
|
||||
url: "/common/getExchangeRate.do",
|
||||
type: "POST",
|
||||
data: { currencyCode: currencyCode },
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data && data.rate) {
|
||||
$("#exchange_rate").val(data.rate);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
console.log("환율 조회 실패");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -175,6 +323,7 @@
|
||||
<input type="hidden" name="contractObjId" id="contractObjId" value="${contractObjId}">
|
||||
<input type="hidden" name="objId" id="objId" value="${objId}">
|
||||
<input type="hidden" name="actionType" id="actionType" value="${actionType}">
|
||||
<input type="hidden" name="items_json" id="items_json" value="">
|
||||
|
||||
<section class="business_popup_min_width">
|
||||
<div class="plm_menu_name">
|
||||
@@ -184,8 +333,9 @@
|
||||
</div>
|
||||
|
||||
<div id="EntirePopupFormWrap">
|
||||
<!-- 기본정보 영역 -->
|
||||
<div class="form_popup_title">
|
||||
<span>수주 정보입력</span>
|
||||
<span>수주 기본정보</span>
|
||||
</div>
|
||||
<table class="">
|
||||
<colgroup>
|
||||
@@ -216,53 +366,25 @@
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 두번째 행: 발주일, 수량 -->
|
||||
<!-- 두번째 행: 발주일, 견적환종 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="">발주일 <span style="color:red;">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" class="date_icon" name="order_date" id="order_date" required reqTitle="발주일" value="${info.ORDER_DATE}">
|
||||
</td>
|
||||
<td class="input_title"><label for="">수량 <span style="color:red;">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="quantity" id="quantity" required reqTitle="수량" value="${info.QUANTITY}" numberOnly />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 세번째 행: 단가, 공급가액 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="">단가 <span style="color:red;">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="unit_price" id="unit_price" required reqTitle="단가" value="${info.ORDER_UNIT_PRICE}" numberOnly />
|
||||
</td>
|
||||
<td class="input_title"><label for="">공급가액 <span style="color:red;">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="supply_price" id="supply_price" required reqTitle="공급가액" value="${info.ORDER_SUPPLY_PRICE}" numberOnly />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 네번째 행: 부가세, 총액 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="">부가세 <span style="color:red;">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="vat" id="vat" required reqTitle="부가세" value="${info.ORDER_VAT}" numberOnly />
|
||||
</td>
|
||||
<td class="input_title"><label for="">총액 <span style="color:red;">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="total_amount" id="total_amount" required reqTitle="총액" value="${info.ORDER_TOTAL_AMOUNT}" numberOnly />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- 다섯번째 행: 환종, 환율 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="">환종</label></td>
|
||||
<td class="input_title"><label for="">견적환종</label></td>
|
||||
<td>
|
||||
<select name="contract_currency" id="contract_currency" reqTitle="환종" type="select" class="select2">
|
||||
<option value="">선택</option>
|
||||
${code_map.contract_currency}
|
||||
</select>
|
||||
</td>
|
||||
<td class="input_title"><label for="">환율</label></td>
|
||||
<td>
|
||||
</tr>
|
||||
|
||||
<!-- 세번째 행: 견적환율 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="">견적환율</label></td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="exchange_rate" id="exchange_rate" reqTitle="환율" value="${info.EXCHANGE_RATE}" numberOnly />
|
||||
</td>
|
||||
</tr>
|
||||
@@ -271,6 +393,58 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- 품목정보 영역 -->
|
||||
<div class="form_popup_title" style="margin-top:15px;">
|
||||
<span>품목정보 (견적요청에서 자동 로드)</span>
|
||||
</div>
|
||||
<table class="">
|
||||
<colgroup>
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="max-height:300px; overflow-y:auto;">
|
||||
<table class="pmsPopuptable" id="itemListTable">
|
||||
<colgroup>
|
||||
<col width="4%" /> <!-- 번호 -->
|
||||
<col width="10%" /> <!-- 품번 -->
|
||||
<col width="13%" /> <!-- 품명 -->
|
||||
<col width="12%" /> <!-- S/N -->
|
||||
<col width="8%" /> <!-- 수주수량 -->
|
||||
<col width="11%" /> <!-- 수주단가 -->
|
||||
<col width="12%" /> <!-- 수주공급가액 -->
|
||||
<col width="11%" /> <!-- 수주부가세 -->
|
||||
<col width="12%" /> <!-- 수주총액 -->
|
||||
<col width="7%" /> <!-- 삭제 -->
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr style="background:#f5f5f5;">
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">No</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">품번</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">품명</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">S/N</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주수량 <span style="color:red;">*</span></th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주단가 <span style="color:red;">*</span></th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주공급가액</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주부가세</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주총액</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">-</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="itemListBody">
|
||||
<!-- 품목 행이 동적으로 추가됩니다 -->
|
||||
<tr id="noItemRow">
|
||||
<td colspan="10" style="text-align:center; padding:30px; color:#999;">
|
||||
견적요청에 등록된 품목이 자동으로 표시됩니다.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -3255,4 +3255,182 @@ function fnc_tabulCallbackFnc(objid, docType, columnField, fileCnt){
|
||||
});
|
||||
}
|
||||
|
||||
//tabulator용 Function 종료
|
||||
//tabulator용 Function 종료
|
||||
|
||||
/**
|
||||
* 품번/품명 Select2 AJAX 검색 함수 (견적 목록 전용)
|
||||
* @param {string} partNoSelectId - 품번 셀렉트 박스 ID (예: "#search_partNo")
|
||||
* @param {string} partNameSelectId - 품명 셀렉트 박스 ID (예: "#search_partName")
|
||||
* @param {string} partObjIdInputId - 품목 OBJID hidden 필드 ID (예: "#search_partObjId")
|
||||
* @param {object} options - 추가 옵션 (placeholder, minimumInputLength 등)
|
||||
*/
|
||||
function initPartSelect2Ajax(partNoSelectId, partNameSelectId, partObjIdInputId, options) {
|
||||
options = options || {};
|
||||
var partNoPlaceholder = options.partNoPlaceholder || "품번 입력하여 검색...";
|
||||
var partNamePlaceholder = options.partNamePlaceholder || "품명 입력하여 검색...";
|
||||
var minimumInputLength = options.minimumInputLength || 1;
|
||||
var searchUrl = options.searchUrl || '/contractMgmt/searchPartList.do';
|
||||
var debug = options.debug || false;
|
||||
|
||||
// 품번 Select2 AJAX 설정
|
||||
$(partNoSelectId).select2({
|
||||
placeholder: partNoPlaceholder,
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
minimumInputLength: minimumInputLength,
|
||||
language: {
|
||||
inputTooShort: function() {
|
||||
return "최소 " + minimumInputLength + "글자 이상 입력하세요";
|
||||
},
|
||||
searching: function() {
|
||||
return "검색 중...";
|
||||
},
|
||||
noResults: function() {
|
||||
return "검색 결과가 없습니다";
|
||||
}
|
||||
},
|
||||
ajax: {
|
||||
url: searchUrl,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
delay: 250,
|
||||
data: function(params) {
|
||||
return {
|
||||
searchTerm: params.term
|
||||
};
|
||||
},
|
||||
processResults: function(data) {
|
||||
var results = $.map(data, function(item) {
|
||||
var objId = item.OBJID || item.objid || item.objId;
|
||||
var partNo = item.PART_NO || item.part_no || item.partNo;
|
||||
var partName = item.PART_NAME || item.part_name || item.partName;
|
||||
|
||||
return {
|
||||
id: partNo,
|
||||
text: partNo,
|
||||
objId: objId,
|
||||
partName: partName,
|
||||
partNo: partNo
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
results: results
|
||||
};
|
||||
},
|
||||
cache: true
|
||||
}
|
||||
});
|
||||
|
||||
// 품명 Select2 AJAX 설정
|
||||
$(partNameSelectId).select2({
|
||||
placeholder: partNamePlaceholder,
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
minimumInputLength: minimumInputLength,
|
||||
language: {
|
||||
inputTooShort: function() {
|
||||
return "최소 " + minimumInputLength + "글자 이상 입력하세요";
|
||||
},
|
||||
searching: function() {
|
||||
return "검색 중...";
|
||||
},
|
||||
noResults: function() {
|
||||
return "검색 결과가 없습니다";
|
||||
}
|
||||
},
|
||||
ajax: {
|
||||
url: searchUrl,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
delay: 250,
|
||||
data: function(params) {
|
||||
return {
|
||||
searchTerm: params.term
|
||||
};
|
||||
},
|
||||
processResults: function(data) {
|
||||
var results = $.map(data, function(item) {
|
||||
var objId = item.OBJID || item.objid || item.objId;
|
||||
var partNo = item.PART_NO || item.part_no || item.partNo;
|
||||
var partName = item.PART_NAME || item.part_name || item.partName;
|
||||
|
||||
return {
|
||||
id: partName,
|
||||
text: partName,
|
||||
objId: objId,
|
||||
partName: partName,
|
||||
partNo: partNo
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
results: results
|
||||
};
|
||||
},
|
||||
cache: true
|
||||
}
|
||||
});
|
||||
|
||||
// 품번 변경 이벤트 핸들러
|
||||
var partNoChangeHandler = function() {
|
||||
var selectedData = $(this).select2('data')[0];
|
||||
if(debug) console.log("품번 변경됨:", selectedData);
|
||||
|
||||
if(selectedData && selectedData.objId) {
|
||||
if(debug) console.log("품목 OBJID 설정:", selectedData.objId);
|
||||
$(partObjIdInputId).val(selectedData.objId);
|
||||
|
||||
// 품명 셀렉트박스도 동기화
|
||||
var $partNameSelect = $(partNameSelectId);
|
||||
$partNameSelect.off('change');
|
||||
if($partNameSelect.find("option[value='" + selectedData.partName + "']").length === 0) {
|
||||
var newOption = new Option(selectedData.partName, selectedData.partName, true, true);
|
||||
$partNameSelect.append(newOption);
|
||||
} else {
|
||||
$partNameSelect.val(selectedData.partName);
|
||||
}
|
||||
$partNameSelect.trigger('change.select2');
|
||||
|
||||
setTimeout(function() {
|
||||
$partNameSelect.on('change', partNameChangeHandler);
|
||||
}, 100);
|
||||
} else {
|
||||
$(partObjIdInputId).val("");
|
||||
}
|
||||
};
|
||||
|
||||
// 품명 변경 이벤트 핸들러
|
||||
var partNameChangeHandler = function() {
|
||||
var selectedData = $(this).select2('data')[0];
|
||||
if(debug) console.log("품명 변경됨:", selectedData);
|
||||
|
||||
if(selectedData && selectedData.objId) {
|
||||
if(debug) console.log("품목 OBJID 설정:", selectedData.objId);
|
||||
$(partObjIdInputId).val(selectedData.objId);
|
||||
|
||||
// 품번 셀렉트박스도 동기화
|
||||
var $partNoSelect = $(partNoSelectId);
|
||||
$partNoSelect.off('change');
|
||||
if($partNoSelect.find("option[value='" + selectedData.partNo + "']").length === 0) {
|
||||
var newOption = new Option(selectedData.partNo, selectedData.partNo, true, true);
|
||||
$partNoSelect.append(newOption);
|
||||
} else {
|
||||
$partNoSelect.val(selectedData.partNo);
|
||||
}
|
||||
$partNoSelect.trigger('change.select2');
|
||||
|
||||
setTimeout(function() {
|
||||
$partNoSelect.on('change', partNoChangeHandler);
|
||||
}, 100);
|
||||
} else {
|
||||
$(partObjIdInputId).val("");
|
||||
}
|
||||
};
|
||||
|
||||
// 이벤트 연결
|
||||
$(partNoSelectId).on('change', partNoChangeHandler);
|
||||
$(partNameSelectId).on('change', partNameChangeHandler);
|
||||
}
|
||||
16
database/add_manager_info_to_estimate_template.sql
Normal file
16
database/add_manager_info_to_estimate_template.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- ESTIMATE_TEMPLATE 테이블에 담당자 정보 및 테이블 내 비고 컬럼 추가
|
||||
|
||||
ALTER TABLE ESTIMATE_TEMPLATE
|
||||
ADD COLUMN IF NOT EXISTS MANAGER_NAME VARCHAR(100);
|
||||
|
||||
ALTER TABLE ESTIMATE_TEMPLATE
|
||||
ADD COLUMN IF NOT EXISTS MANAGER_CONTACT VARCHAR(100);
|
||||
|
||||
ALTER TABLE ESTIMATE_TEMPLATE
|
||||
ADD COLUMN IF NOT EXISTS NOTE_REMARKS TEXT;
|
||||
|
||||
-- 컬럼 설명 추가
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE.MANAGER_NAME IS '담당자 이름';
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE.MANAGER_CONTACT IS '담당자 연락처';
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE.NOTE_REMARKS IS '테이블 내 비고 (품목 하단)';
|
||||
|
||||
29
database/add_order_columns_to_contract_item.sql
Normal file
29
database/add_order_columns_to_contract_item.sql
Normal file
@@ -0,0 +1,29 @@
|
||||
-- CONTRACT_ITEM 테이블에 수주 관련 컬럼 추가
|
||||
|
||||
-- 수주 수량
|
||||
ALTER TABLE CONTRACT_ITEM
|
||||
ADD COLUMN IF NOT EXISTS ORDER_QUANTITY VARCHAR(50);
|
||||
|
||||
-- 수주 단가
|
||||
ALTER TABLE CONTRACT_ITEM
|
||||
ADD COLUMN IF NOT EXISTS ORDER_UNIT_PRICE VARCHAR(50);
|
||||
|
||||
-- 수주 공급가액
|
||||
ALTER TABLE CONTRACT_ITEM
|
||||
ADD COLUMN IF NOT EXISTS ORDER_SUPPLY_PRICE VARCHAR(50);
|
||||
|
||||
-- 수주 부가세
|
||||
ALTER TABLE CONTRACT_ITEM
|
||||
ADD COLUMN IF NOT EXISTS ORDER_VAT VARCHAR(50);
|
||||
|
||||
-- 수주 총액
|
||||
ALTER TABLE CONTRACT_ITEM
|
||||
ADD COLUMN IF NOT EXISTS ORDER_TOTAL_AMOUNT VARCHAR(50);
|
||||
|
||||
-- 컬럼 코멘트 추가
|
||||
COMMENT ON COLUMN CONTRACT_ITEM.ORDER_QUANTITY IS '수주 수량';
|
||||
COMMENT ON COLUMN CONTRACT_ITEM.ORDER_UNIT_PRICE IS '수주 단가';
|
||||
COMMENT ON COLUMN CONTRACT_ITEM.ORDER_SUPPLY_PRICE IS '수주 공급가액';
|
||||
COMMENT ON COLUMN CONTRACT_ITEM.ORDER_VAT IS '수주 부가세 (10%)';
|
||||
COMMENT ON COLUMN CONTRACT_ITEM.ORDER_TOTAL_AMOUNT IS '수주 총액 (공급가액 + 부가세)';
|
||||
|
||||
27
database/add_part_objid_to_project_mgmt.sql
Normal file
27
database/add_part_objid_to_project_mgmt.sql
Normal file
@@ -0,0 +1,27 @@
|
||||
-- PROJECT_MGMT 테이블에 품목 관련 컬럼 추가
|
||||
-- 품목별 프로젝트 생성을 위한 컬럼들
|
||||
|
||||
ALTER TABLE PROJECT_MGMT
|
||||
ADD COLUMN IF NOT EXISTS PART_OBJID VARCHAR(50);
|
||||
|
||||
ALTER TABLE PROJECT_MGMT
|
||||
ADD COLUMN IF NOT EXISTS PART_NO VARCHAR(100);
|
||||
|
||||
ALTER TABLE PROJECT_MGMT
|
||||
ADD COLUMN IF NOT EXISTS PART_NAME VARCHAR(200);
|
||||
|
||||
ALTER TABLE PROJECT_MGMT
|
||||
ADD COLUMN IF NOT EXISTS QUANTITY VARCHAR(50);
|
||||
|
||||
-- 컬럼 설명 추가
|
||||
COMMENT ON COLUMN PROJECT_MGMT.PART_OBJID IS '품목 OBJID (품목별 프로젝트 생성 시 사용)';
|
||||
COMMENT ON COLUMN PROJECT_MGMT.PART_NO IS '품번';
|
||||
COMMENT ON COLUMN PROJECT_MGMT.PART_NAME IS '품명';
|
||||
COMMENT ON COLUMN PROJECT_MGMT.QUANTITY IS '수주수량';
|
||||
|
||||
-- 기존 인덱스 확인 후 추가 (성능 향상)
|
||||
CREATE INDEX IF NOT EXISTS idx_project_mgmt_contract_part
|
||||
ON PROJECT_MGMT(CONTRACT_OBJID, PART_OBJID);
|
||||
|
||||
COMMENT ON INDEX idx_project_mgmt_contract_part IS '계약-품목별 프로젝트 조회 성능 향상';
|
||||
|
||||
14
database/add_total_amount_column.sql
Normal file
14
database/add_total_amount_column.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- 견적서 템플릿 테이블에 합계 관련 컬럼 추가
|
||||
|
||||
-- ESTIMATE_TEMPLATE 테이블에 TOTAL_AMOUNT 컬럼 추가
|
||||
ALTER TABLE ESTIMATE_TEMPLATE
|
||||
ADD COLUMN IF NOT EXISTS TOTAL_AMOUNT VARCHAR(50);
|
||||
|
||||
-- ESTIMATE_TEMPLATE 테이블에 TOTAL_AMOUNT_KRW 컬럼 추가 (원화환산공급가액)
|
||||
ALTER TABLE ESTIMATE_TEMPLATE
|
||||
ADD COLUMN IF NOT EXISTS TOTAL_AMOUNT_KRW VARCHAR(50);
|
||||
|
||||
-- 컬럼 코멘트 추가
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE.TOTAL_AMOUNT IS '견적서 총 합계 금액 (품목 금액의 합, 콤마 포맷팅 포함)';
|
||||
COMMENT ON COLUMN ESTIMATE_TEMPLATE.TOTAL_AMOUNT_KRW IS '원화환산 공급가액 (합계 × 환율, 콤마 포맷팅 포함)';
|
||||
|
||||
@@ -691,6 +691,7 @@ public class MailUtil {
|
||||
|
||||
//◆◆◆ 3. db log & send mail ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
|
||||
SqlSession sqlSession = null;
|
||||
boolean mailSendSuccess = false; // 메일 발송 성공 여부
|
||||
|
||||
Map paramMap = new HashMap();
|
||||
try{
|
||||
@@ -715,6 +716,7 @@ public class MailUtil {
|
||||
|
||||
//◆◆◆ send mail ◆◆◆
|
||||
Transport.send(message);
|
||||
mailSendSuccess = true; // 메일 발송 성공
|
||||
|
||||
if(Constants.Mail.dbLogWrite){
|
||||
System.out.println("메일 발송후 paramMap >> "+paramMap);
|
||||
@@ -722,6 +724,7 @@ public class MailUtil {
|
||||
}
|
||||
|
||||
}catch(Exception sqle){
|
||||
mailSendSuccess = false; // 메일 발송 실패
|
||||
if(Constants.Mail.dbLogWrite){
|
||||
paramMap.put("errorLog", sqle.getMessage());
|
||||
System.out.println("메일 발송 오류 paramMap >> "+paramMap);
|
||||
@@ -735,7 +738,7 @@ public class MailUtil {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return mailSendSuccess; // 실제 발송 성공 여부 반환
|
||||
}catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
|
||||
@@ -7362,16 +7362,20 @@ SELECT
|
||||
,EST_USER_ID
|
||||
,EST_COMP_DATE
|
||||
,EST_RESULT_CD
|
||||
,AREA_CD
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,IS_TEMP
|
||||
)
|
||||
,AREA_CD
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,IS_TEMP
|
||||
,PART_OBJID
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,QUANTITY
|
||||
)
|
||||
|
||||
(
|
||||
SELECT
|
||||
#{OBJID}
|
||||
,#{objId}
|
||||
,#{objId}
|
||||
,CATEGORY_CD
|
||||
,CUSTOMER_OBJID
|
||||
,PRODUCT
|
||||
@@ -7390,29 +7394,71 @@ SELECT
|
||||
,CHG_USER_ID
|
||||
,PLAN_DATE
|
||||
,COMPLETE_DATE
|
||||
,RESULT_CD
|
||||
<choose>
|
||||
<when test="overhaul_project_no != null and overhaul_project_no !='' ">
|
||||
,#{overhaul_project_no}<!-- || '_' || #{overhaul_order} -->
|
||||
</when>
|
||||
<otherwise>
|
||||
,MECHANICAL_TYPE || '-' ||
|
||||
<!--
|
||||
(SELECT (SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1))::integer+1 FROM PROJECT_MGMT WHERE PROJECT_NO NOT LIKE '%\_%' ESCAPE '\' ORDER BY SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1) DESC LIMIT 1)
|
||||
-->
|
||||
(SELECT CASE
|
||||
WHEN PROJECT_NO ~ '[-\s][0-9]+$'
|
||||
THEN REGEXP_REPLACE(PROJECT_NO, '.*[-\s]([0-9]+)$', '\1')::integer+1
|
||||
ELSE NULL
|
||||
END AS extracted_number
|
||||
FROM PROJECT_MGMT
|
||||
WHERE PROJECT_NO NOT LIKE '%\_%' ESCAPE '\'
|
||||
ORDER BY extracted_number DESC NULLS LAST
|
||||
LIMIT 1)
|
||||
</otherwise>
|
||||
</choose>
|
||||
<!-- ,#{project_no} -->
|
||||
<!-- ,(SELECT TITLE FROM PMS_WBS_TEMPLATE PWT WHERE PWT.OBJID = #{mechanical_type}) || '-' || (SELECT (SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1))::integer+1 FROM PROJECT_MGMT ORDER BY SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1) DESC LIMIT 1) -->
|
||||
,RESULT_CD
|
||||
<!-- 기존 PROJECT_NO 자동생성 로직 (주석처리)
|
||||
<choose>
|
||||
<when test="overhaul_project_no != null and overhaul_project_no !='' ">
|
||||
,#{overhaul_project_no}
|
||||
</when>
|
||||
<otherwise>
|
||||
,MECHANICAL_TYPE || '-' ||
|
||||
(SELECT CASE
|
||||
WHEN PROJECT_NO ~ '[-\s][0-9]+$'
|
||||
THEN REGEXP_REPLACE(PROJECT_NO, '.*[-\s]([0-9]+)$', '\1')::integer+1
|
||||
ELSE NULL
|
||||
END AS extracted_number
|
||||
FROM PROJECT_MGMT
|
||||
WHERE PROJECT_NO NOT LIKE '%\_%' ESCAPE '\'
|
||||
ORDER BY extracted_number DESC NULLS LAST
|
||||
LIMIT 1)
|
||||
</otherwise>
|
||||
</choose>
|
||||
-->
|
||||
|
||||
<!-- 신규 PROJECT_NO 생성 로직: 주문유형-제품구분-날짜-순번 형식 (예: R-AS-250302-001) -->
|
||||
,(
|
||||
SELECT
|
||||
-- 주문유형 코드 (CATEGORY_CD를 영문 약어로 매핑)
|
||||
CASE CODE_NAME(CATEGORY_CD)
|
||||
WHEN '오버홀' THEN 'O'
|
||||
WHEN '개조' THEN 'M'
|
||||
WHEN '개발' THEN 'D'
|
||||
WHEN '견적' THEN 'Q'
|
||||
WHEN '수리' THEN 'R'
|
||||
WHEN '판매' THEN 'S'
|
||||
ELSE 'T'
|
||||
END || '-' ||
|
||||
-- 제품구분 코드 (PRODUCT의 CODE_NAME에서 슬래시 제거)
|
||||
REPLACE(CODE_NAME(PRODUCT), '/', '') || '-' ||
|
||||
-- 날짜 (YYMMDD)
|
||||
TO_CHAR(CURRENT_DATE, 'YYMMDD') || '-' ||
|
||||
-- 순번 (001, 002, ...)
|
||||
LPAD(
|
||||
COALESCE(
|
||||
(
|
||||
SELECT MAX(SUBSTRING(PROJECT_NO FROM '\d{3}$')::INTEGER) + 1
|
||||
FROM PROJECT_MGMT
|
||||
WHERE PROJECT_NO LIKE
|
||||
CASE CODE_NAME(CATEGORY_CD)
|
||||
WHEN '오버홀' THEN 'O'
|
||||
WHEN '개조' THEN 'M'
|
||||
WHEN '개발' THEN 'D'
|
||||
WHEN '견적' THEN 'Q'
|
||||
WHEN '수리' THEN 'R'
|
||||
WHEN '판매' THEN 'S'
|
||||
ELSE 'T'
|
||||
END || '-' ||
|
||||
REPLACE(CODE_NAME(PRODUCT), '/', '') || '-' ||
|
||||
TO_CHAR(CURRENT_DATE, 'YYMMDD') || '-%'
|
||||
),
|
||||
1
|
||||
)::TEXT,
|
||||
3,
|
||||
'0'
|
||||
)
|
||||
FROM CONTRACT_MGMT
|
||||
WHERE OBJID = #{objId}
|
||||
)
|
||||
,PM_USER_ID
|
||||
,#{contract_price}
|
||||
,#{contract_price_currency}
|
||||
@@ -7437,12 +7483,16 @@ SELECT
|
||||
,EST_USER_ID
|
||||
,EST_COMP_DATE
|
||||
,EST_RESULT_CD
|
||||
,AREA_CD
|
||||
,MECHANICAL_TYPE
|
||||
,#{overhaul_order}
|
||||
,#{is_temp}
|
||||
FROM CONTRACT_MGMT
|
||||
WHERE OBJID=#{objId}
|
||||
,AREA_CD
|
||||
,MECHANICAL_TYPE
|
||||
,#{overhaul_order}
|
||||
,#{is_temp}
|
||||
,#{part_objid}
|
||||
,#{part_no}
|
||||
,#{part_name}
|
||||
,#{quantity}
|
||||
FROM CONTRACT_MGMT
|
||||
WHERE OBJID=#{objId}
|
||||
)
|
||||
</insert>
|
||||
|
||||
@@ -7549,7 +7599,12 @@ SELECT
|
||||
,REQ_DEL_DATE = #{req_del_date}
|
||||
,CONTRACT_COMPANY = #{contract_company}
|
||||
,MANUFACTURE_PLANT = #{manufacture_plant}
|
||||
,PART_OBJID = #{part_objid}
|
||||
,PART_NO = #{part_no}
|
||||
,PART_NAME = #{part_name}
|
||||
,QUANTITY = #{quantity}
|
||||
WHERE CONTRACT_OBJID = #{objId}
|
||||
AND PART_OBJID = #{part_objid}
|
||||
</update>
|
||||
|
||||
<delete id="deleteProjectMngInfo" parameterType="map">
|
||||
|
||||
@@ -2000,6 +2000,9 @@ public class ContractMgmtController {
|
||||
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
paramMap.put("userId", person.getUserId());
|
||||
|
||||
// 합계 정보 로그 (디버깅용)
|
||||
System.out.println("견적서 저장 - 합계: " + paramMap.get("total_amount") + ", 원화환산: " + paramMap.get("total_amount_krw"));
|
||||
|
||||
contractMgmtService.saveEstimateTemplate(request, paramMap);
|
||||
|
||||
resultMap.put("result", "success");
|
||||
@@ -2168,4 +2171,29 @@ public class ContractMgmtController {
|
||||
}
|
||||
return "/ajax/ajaxResult";
|
||||
}
|
||||
|
||||
/**
|
||||
* 계약 품목 조회 (AJAX)
|
||||
* @param request
|
||||
* @param paramMap - contractObjId
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/contractMgmt/getContractItems.do", method=RequestMethod.POST)
|
||||
public Map getContractItems(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
List<Map> items = contractMgmtService.getContractItems(paramMap);
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("items", items);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,8 +463,9 @@
|
||||
,TO_CHAR(REGDATE,'YYYY-MM-DD') AS REG_DATE
|
||||
,WRITER
|
||||
,(SELECT USER_NAME FROM USER_INFO AS O WHERE O.USER_ID = T.WRITER ) AS WRITER_NAME
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = T.OBJID AND DOC_TYPE='contractMgmt01' AND UPPER(STATUS) = 'ACTIVE') AS CU01_CNT
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = T.OBJID AND DOC_TYPE='contractMgmt02' AND UPPER(STATUS) = 'ACTIVE') AS CU02_CNT
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = T.OBJID AND DOC_TYPE='ORDER_DOC' AND UPPER(STATUS) = 'ACTIVE') AS CU01_CNT
|
||||
<!-- ,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = T.OBJID AND DOC_TYPE='contractMgmt01' AND UPPER(STATUS) = 'ACTIVE') AS CU01_CNT
|
||||
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO WHERE TARGET_OBJID = T.OBJID AND DOC_TYPE='contractMgmt02' AND UPPER(STATUS) = 'ACTIVE') AS CU02_CNT -->
|
||||
,(CASE WHEN (RESULT_CD is null or RESULT_CD ='') and (SPEC_RESULT_CD is null or RESULT_CD ='') and (EST_RESULT_CD is null or RESULT_CD ='') then '0'
|
||||
ELSE 1
|
||||
END
|
||||
@@ -477,6 +478,7 @@
|
||||
,CODE_NAME(CONTRACT_COMPANY) AS CONTRACT_COMPANY_NAME
|
||||
,CONTRACT_DATE
|
||||
,PO_NO
|
||||
,ORDER_DATE
|
||||
,MANUFACTURE_PLANT
|
||||
,CODE_NAME(MANUFACTURE_PLANT) AS MANUFACTURE_PLANT_NAME
|
||||
,CONTRACT_RESULT
|
||||
@@ -521,6 +523,19 @@
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
,(SELECT objid FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID order by regdate desc limit 1) AS EST_OBJID
|
||||
-- 최근 차수 견적서 합계 정보
|
||||
,(SELECT TOTAL_AMOUNT FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT
|
||||
,(SELECT TOTAL_AMOUNT_KRW FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID ORDER BY REGDATE DESC LIMIT 1) AS EST_TOTAL_AMOUNT_KRW
|
||||
-- 수주 합계 정보 (CONTRACT_MGMT 테이블에 저장된 값 사용)
|
||||
,T.ORDER_SUPPLY_PRICE AS ORDER_SUPPLY_PRICE_SUM
|
||||
,T.ORDER_VAT AS ORDER_VAT_SUM
|
||||
,T.ORDER_TOTAL_AMOUNT AS ORDER_TOTAL_AMOUNT_SUM
|
||||
,CASE
|
||||
WHEN T.ORDER_TOTAL_AMOUNT IS NOT NULL AND T.ORDER_TOTAL_AMOUNT != ''
|
||||
AND T.EXCHANGE_RATE IS NOT NULL AND T.EXCHANGE_RATE != ''
|
||||
THEN CAST(T.ORDER_TOTAL_AMOUNT AS NUMERIC) * CAST(T.EXCHANGE_RATE AS NUMERIC)
|
||||
ELSE 0
|
||||
END AS ORDER_TOTAL_AMOUNT_KRW
|
||||
-- 품목 정보 요약
|
||||
,(
|
||||
WITH item_info AS (
|
||||
@@ -740,12 +755,15 @@
|
||||
AND PAID_TYPE = #{paid_type}
|
||||
</if>
|
||||
|
||||
<if test="search_partNo != null and search_partNo != ''">
|
||||
AND UPPER(PART_NO) LIKE UPPER('%${search_partNo}%')
|
||||
</if>
|
||||
|
||||
<if test="search_partName != null and search_partName != ''">
|
||||
AND UPPER(PART_NAME) LIKE UPPER('%${search_partName}%')
|
||||
<!-- 품번/품명 검색: PART_OBJID로 정확하게 검색 -->
|
||||
<if test="search_partObjId != null and search_partObjId != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM CONTRACT_ITEM CI
|
||||
WHERE CI.CONTRACT_OBJID = T.OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
AND CI.PART_OBJID = #{search_partObjId}
|
||||
)
|
||||
</if>
|
||||
|
||||
<if test="search_serialNo != null and search_serialNo != ''">
|
||||
@@ -766,9 +784,9 @@
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{due_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
<select id="contractList_bak" parameterType="map" resultType="map">
|
||||
</select>
|
||||
|
||||
<select id="contractList_bak" parameterType="map" resultType="map">
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT CONTRACT_MGMT.*,ROW_NUMBER() OVER (ORDER BY CONTRACT_NO DESC) AS RNUM
|
||||
@@ -3082,7 +3100,8 @@ SELECT
|
||||
,#{writer}
|
||||
FROM PMS_WBS_TASK_STANDARD AS T LEFT JOIN PMS_WBS_TEMPLATE AS T1
|
||||
ON T.PARENT_OBJID = T1.OBJID
|
||||
WHERE T1.TITLE=#{mechanical_type}
|
||||
WHERE T1.OBJID = '1662715267'
|
||||
<!-- WHERE T1.TITLE=#{mechanical_type} -->
|
||||
<!-- WHERE T1.OBJID=#{mechanical_type} -->
|
||||
<!-- WHERE T1.PRODUCT_OBJID=#{product} -->
|
||||
)
|
||||
@@ -3452,6 +3471,20 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<!-- 품목별 프로젝트 조회 (PART_OBJID 기준) -->
|
||||
<select id="getProjectListByContractAndPartObjid" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
PROJECT_NAME,
|
||||
PART_OBJID,
|
||||
PART_NO,
|
||||
PART_NAME
|
||||
FROM
|
||||
PROJECT_MGMT
|
||||
WHERE CONTRACT_OBJID = #{contractObjId}
|
||||
AND PART_OBJID = #{part_objid}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<select id="overlapOrder" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
T.*
|
||||
@@ -3796,86 +3829,147 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
<!-- 견적서 템플릿 목록 조회 (CONTRACT_OBJID 기준) -->
|
||||
<select id="getEstimateTemplateList" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID AS "OBJID",
|
||||
CONTRACT_OBJID AS "CONTRACT_OBJID",
|
||||
TEMPLATE_TYPE AS "TEMPLATE_TYPE",
|
||||
ET.OBJID AS "OBJID",
|
||||
ET.CONTRACT_OBJID AS "CONTRACT_OBJID",
|
||||
ET.TEMPLATE_TYPE AS "TEMPLATE_TYPE",
|
||||
CASE
|
||||
WHEN TEMPLATE_TYPE = '1' THEN '일반 견적서'
|
||||
WHEN TEMPLATE_TYPE = '2' THEN '장비 견적서'
|
||||
ELSE TEMPLATE_TYPE
|
||||
WHEN ET.TEMPLATE_TYPE = '1' THEN '일반 견적서'
|
||||
WHEN ET.TEMPLATE_TYPE = '2' THEN '장비 견적서'
|
||||
ELSE ET.TEMPLATE_TYPE
|
||||
END AS "TEMPLATE_TYPE_NAME",
|
||||
ESTIMATE_NO AS "ESTIMATE_NO",
|
||||
WRITER AS "WRITER",
|
||||
TO_CHAR(REGDATE, 'YYYY-MM-DD HH24:MI') AS "REGDATE",
|
||||
CHG_USER_ID AS "CHG_USER_ID",
|
||||
TO_CHAR(CHGDATE, 'YYYY-MM-DD HH24:MI') AS "CHGDATE",
|
||||
ROW_NUMBER() OVER (PARTITION BY TEMPLATE_TYPE ORDER BY REGDATE) AS "REVISION"
|
||||
ET.ESTIMATE_NO AS "ESTIMATE_NO",
|
||||
ET.WRITER AS "WRITER",
|
||||
TO_CHAR(ET.REGDATE, 'YYYY-MM-DD HH24:MI') AS "REGDATE",
|
||||
ET.CHG_USER_ID AS "CHG_USER_ID",
|
||||
TO_CHAR(ET.CHGDATE, 'YYYY-MM-DD HH24:MI') AS "CHGDATE",
|
||||
ROW_NUMBER() OVER (PARTITION BY ET.TEMPLATE_TYPE ORDER BY ET.REGDATE) AS "REVISION",
|
||||
COALESCE(
|
||||
(SELECT CASE
|
||||
WHEN A.STATUS = 'complete' THEN '결재완료'
|
||||
WHEN A.STATUS = 'cancel' THEN '취소'
|
||||
WHEN A.STATUS = 'reject' THEN '반려'
|
||||
WHEN A.STATUS = 'inProcess' THEN '결재중'
|
||||
ELSE '작성중'
|
||||
END
|
||||
FROM APPROVAL A
|
||||
WHERE A.TARGET_OBJID::VARCHAR = ET.OBJID
|
||||
AND A.TARGET_TYPE = 'CONTRACT_ESTIMATE'
|
||||
ORDER BY A.REGDATE DESC
|
||||
LIMIT 1),
|
||||
'작성중'
|
||||
) AS "APPR_STATUS"
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
ESTIMATE_TEMPLATE ET
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}
|
||||
ORDER BY TEMPLATE_TYPE, REGDATE DESC
|
||||
ET.CONTRACT_OBJID = #{objId}
|
||||
ORDER BY ET.TEMPLATE_TYPE, ET.REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (ESTIMATE_TEMPLATE 테이블) -->
|
||||
<select id="getEstimateTemplateData" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
RECIPIENT,
|
||||
ESTIMATE_NO,
|
||||
CONTACT_PERSON,
|
||||
GREETING_TEXT,
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
ET.OBJID,
|
||||
ET.CONTRACT_OBJID,
|
||||
ET.TEMPLATE_TYPE,
|
||||
ET.EXECUTOR,
|
||||
ET.RECIPIENT,
|
||||
ET.ESTIMATE_NO,
|
||||
ET.CONTACT_PERSON,
|
||||
ET.GREETING_TEXT,
|
||||
ET.MODEL_NAME,
|
||||
ET.MODEL_CODE,
|
||||
ET.EXECUTOR_DATE,
|
||||
ET.NOTE1,
|
||||
ET.NOTE2,
|
||||
ET.NOTE3,
|
||||
ET.NOTE4,
|
||||
ET.NOTE_REMARKS,
|
||||
ET.TOTAL_AMOUNT,
|
||||
ET.TOTAL_AMOUNT_KRW,
|
||||
ET.MANAGER_NAME,
|
||||
ET.MANAGER_CONTACT,
|
||||
ET.WRITER,
|
||||
ET.REGDATE,
|
||||
ET.CHG_USER_ID,
|
||||
ET.CHGDATE,
|
||||
CM.EXCHANGE_RATE,
|
||||
CODE_NAME(CM.CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME,
|
||||
COALESCE(
|
||||
(SELECT CASE
|
||||
WHEN A.STATUS = 'complete' THEN '결재완료'
|
||||
WHEN A.STATUS = 'cancel' THEN '취소'
|
||||
WHEN A.STATUS = 'reject' THEN '반려'
|
||||
WHEN A.STATUS = 'inProcess' THEN '결재중'
|
||||
ELSE '작성중'
|
||||
END
|
||||
FROM APPROVAL A
|
||||
WHERE A.TARGET_OBJID::VARCHAR = ET.OBJID
|
||||
AND A.TARGET_TYPE = 'CONTRACT_ESTIMATE'
|
||||
ORDER BY A.REGDATE DESC
|
||||
LIMIT 1),
|
||||
'작성중'
|
||||
) AS APPR_STATUS
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
ESTIMATE_TEMPLATE ET
|
||||
LEFT JOIN CONTRACT_MGMT CM ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
ORDER BY REGDATE DESC
|
||||
LIMIT 1
|
||||
ET.CONTRACT_OBJID = #{objId}
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND ET.TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
ORDER BY ET.REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (OBJID 기준) -->
|
||||
<select id="getEstimateTemplateByObjId" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
RECIPIENT,
|
||||
ESTIMATE_NO,
|
||||
CONTACT_PERSON,
|
||||
GREETING_TEXT,
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
TO_CHAR(REGDATE, 'YYYY-MM-DD HH24:MI') AS REGDATE,
|
||||
CHG_USER_ID,
|
||||
TO_CHAR(CHGDATE, 'YYYY-MM-DD HH24:MI') AS CHGDATE
|
||||
ET.OBJID,
|
||||
ET.CONTRACT_OBJID,
|
||||
ET.TEMPLATE_TYPE,
|
||||
ET.EXECUTOR,
|
||||
ET.RECIPIENT,
|
||||
ET.ESTIMATE_NO,
|
||||
ET.CONTACT_PERSON,
|
||||
ET.GREETING_TEXT,
|
||||
ET.MODEL_NAME,
|
||||
ET.MODEL_CODE,
|
||||
ET.EXECUTOR_DATE,
|
||||
ET.NOTE1,
|
||||
ET.NOTE2,
|
||||
ET.NOTE3,
|
||||
ET.NOTE4,
|
||||
ET.NOTE_REMARKS,
|
||||
ET.TOTAL_AMOUNT,
|
||||
ET.TOTAL_AMOUNT_KRW,
|
||||
ET.MANAGER_NAME,
|
||||
ET.MANAGER_CONTACT,
|
||||
ET.WRITER,
|
||||
TO_CHAR(ET.REGDATE, 'YYYY-MM-DD HH24:MI') AS REGDATE,
|
||||
ET.CHG_USER_ID,
|
||||
TO_CHAR(ET.CHGDATE, 'YYYY-MM-DD HH24:MI') AS CHGDATE,
|
||||
CM.EXCHANGE_RATE,
|
||||
CODE_NAME(CM.CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME,
|
||||
COALESCE(
|
||||
(SELECT CASE
|
||||
WHEN A.STATUS = 'complete' THEN '결재완료'
|
||||
WHEN A.STATUS = 'cancel' THEN '취소'
|
||||
WHEN A.STATUS = 'reject' THEN '반려'
|
||||
WHEN A.STATUS = 'inProcess' THEN '결재중'
|
||||
ELSE '작성중'
|
||||
END
|
||||
FROM APPROVAL A
|
||||
WHERE A.TARGET_OBJID::VARCHAR = ET.OBJID
|
||||
AND A.TARGET_TYPE = 'CONTRACT_ESTIMATE'
|
||||
ORDER BY A.REGDATE DESC
|
||||
LIMIT 1),
|
||||
'작성중'
|
||||
) AS APPR_STATUS
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
ESTIMATE_TEMPLATE ET
|
||||
LEFT JOIN CONTRACT_MGMT CM ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE
|
||||
OBJID = #{templateObjId}
|
||||
ET.OBJID = #{templateObjId}
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 품목 조회 (TEMPLATE_OBJID 기준) -->
|
||||
@@ -3940,35 +4034,45 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
) VALUES (
|
||||
#{template_objid},
|
||||
#{objId},
|
||||
#{template_type},
|
||||
#{executor},
|
||||
#{recipient},
|
||||
#{estimate_no},
|
||||
#{contact_person},
|
||||
#{greeting_text},
|
||||
#{model_name},
|
||||
#{model_code},
|
||||
#{executor_date},
|
||||
#{note1},
|
||||
#{note2},
|
||||
#{note3},
|
||||
#{note4},
|
||||
#{writer},
|
||||
NOW(),
|
||||
#{chg_user_id},
|
||||
NOW()
|
||||
)
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
NOTE_REMARKS,
|
||||
TOTAL_AMOUNT,
|
||||
TOTAL_AMOUNT_KRW,
|
||||
MANAGER_NAME,
|
||||
MANAGER_CONTACT,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
) VALUES (
|
||||
#{template_objid},
|
||||
#{objId},
|
||||
#{template_type},
|
||||
#{executor},
|
||||
#{recipient},
|
||||
#{estimate_no},
|
||||
#{contact_person},
|
||||
#{greeting_text},
|
||||
#{model_name},
|
||||
#{model_code},
|
||||
#{executor_date},
|
||||
#{note1},
|
||||
#{note2},
|
||||
#{note3},
|
||||
#{note4},
|
||||
#{note_remarks},
|
||||
#{total_amount},
|
||||
#{total_amount_krw},
|
||||
#{manager_name},
|
||||
#{manager_contact},
|
||||
#{writer},
|
||||
NOW(),
|
||||
#{chg_user_id},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 견적서 템플릿 수정 -->
|
||||
@@ -3983,14 +4087,19 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
MODEL_NAME = #{model_name},
|
||||
MODEL_CODE = #{model_code},
|
||||
EXECUTOR_DATE = #{executor_date},
|
||||
NOTE1 = #{note1},
|
||||
NOTE2 = #{note2},
|
||||
NOTE3 = #{note3},
|
||||
NOTE4 = #{note4},
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
OBJID = #{template_objid}
|
||||
NOTE1 = #{note1},
|
||||
NOTE2 = #{note2},
|
||||
NOTE3 = #{note3},
|
||||
NOTE4 = #{note4},
|
||||
NOTE_REMARKS = #{note_remarks},
|
||||
TOTAL_AMOUNT = #{total_amount},
|
||||
TOTAL_AMOUNT_KRW = #{total_amount_krw},
|
||||
MANAGER_NAME = #{manager_name},
|
||||
MANAGER_CONTACT = #{manager_contact},
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
OBJID = #{template_objid}
|
||||
</update>
|
||||
|
||||
<!-- 견적서 템플릿 품목 삭제 -->
|
||||
@@ -4051,33 +4160,41 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
<!-- 최종 차수 견적서 조회 (메일 발송용) -->
|
||||
<select id="getLatestEstimateTemplate" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID AS "OBJID",
|
||||
CONTRACT_OBJID AS "CONTRACT_OBJID",
|
||||
TEMPLATE_TYPE AS "TEMPLATE_TYPE",
|
||||
EXECUTOR AS "EXECUTOR",
|
||||
RECIPIENT AS "RECIPIENT",
|
||||
ESTIMATE_NO AS "ESTIMATE_NO",
|
||||
CONTACT_PERSON AS "CONTACT_PERSON",
|
||||
GREETING_TEXT AS "GREETING_TEXT",
|
||||
MODEL_NAME AS "MODEL_NAME",
|
||||
MODEL_CODE AS "MODEL_CODE",
|
||||
EXECUTOR_DATE AS "EXECUTOR_DATE",
|
||||
NOTE1 AS "NOTE1",
|
||||
NOTE2 AS "NOTE2",
|
||||
NOTE3 AS "NOTE3",
|
||||
NOTE4 AS "NOTE4",
|
||||
WRITER AS "WRITER",
|
||||
TO_CHAR(REGDATE, 'YYYY-MM-DD HH24:MI') AS "REGDATE",
|
||||
CHG_USER_ID AS "CHG_USER_ID",
|
||||
TO_CHAR(CHGDATE, 'YYYY-MM-DD HH24:MI') AS "CHGDATE",
|
||||
CATEGORIES_JSON AS "CATEGORIES_JSON"
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}
|
||||
ET.OBJID AS "OBJID",
|
||||
ET.CONTRACT_OBJID AS "CONTRACT_OBJID",
|
||||
ET.TEMPLATE_TYPE AS "TEMPLATE_TYPE",
|
||||
ET.EXECUTOR AS "EXECUTOR",
|
||||
ET.RECIPIENT AS "RECIPIENT",
|
||||
ET.ESTIMATE_NO AS "ESTIMATE_NO",
|
||||
ET.CONTACT_PERSON AS "CONTACT_PERSON",
|
||||
ET.GREETING_TEXT AS "GREETING_TEXT",
|
||||
ET.MODEL_NAME AS "MODEL_NAME",
|
||||
ET.MODEL_CODE AS "MODEL_CODE",
|
||||
ET.EXECUTOR_DATE AS "EXECUTOR_DATE",
|
||||
ET.NOTE1 AS "NOTE1",
|
||||
ET.NOTE2 AS "NOTE2",
|
||||
ET.NOTE3 AS "NOTE3",
|
||||
ET.NOTE4 AS "NOTE4",
|
||||
ET.NOTE_REMARKS AS "NOTE_REMARKS",
|
||||
ET.TOTAL_AMOUNT AS "TOTAL_AMOUNT",
|
||||
ET.TOTAL_AMOUNT_KRW AS "TOTAL_AMOUNT_KRW",
|
||||
ET.MANAGER_NAME AS "MANAGER_NAME",
|
||||
ET.MANAGER_CONTACT AS "MANAGER_CONTACT",
|
||||
ET.WRITER AS "WRITER",
|
||||
TO_CHAR(ET.REGDATE, 'YYYY-MM-DD HH24:MI') AS "REGDATE",
|
||||
ET.CHG_USER_ID AS "CHG_USER_ID",
|
||||
TO_CHAR(ET.CHGDATE, 'YYYY-MM-DD HH24:MI') AS "CHGDATE",
|
||||
ET.CATEGORIES_JSON AS "CATEGORIES_JSON",
|
||||
CM.EXCHANGE_RATE AS "EXCHANGE_RATE",
|
||||
CODE_NAME(CM.CONTRACT_CURRENCY) AS "CONTRACT_CURRENCY_NAME"
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE ET
|
||||
LEFT JOIN CONTRACT_MGMT CM ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE
|
||||
ET.CONTRACT_OBJID = #{objId}
|
||||
ORDER BY
|
||||
TEMPLATE_TYPE,
|
||||
REGDATE DESC
|
||||
ET.TEMPLATE_TYPE,
|
||||
ET.REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
@@ -4240,14 +4357,70 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CONTRACT_RESULT = #{contract_result},
|
||||
PO_NO = #{po_no},
|
||||
ORDER_DATE = #{order_date},
|
||||
QUANTITY = #{quantity},
|
||||
ORDER_UNIT_PRICE = #{unit_price},
|
||||
ORDER_SUPPLY_PRICE = #{supply_price},
|
||||
ORDER_VAT = #{vat},
|
||||
ORDER_TOTAL_AMOUNT = #{total_amount},
|
||||
CONTRACT_CURRENCY = #{contract_currency},
|
||||
EXCHANGE_RATE = #{exchange_rate}
|
||||
WHERE OBJID = #{contractObjId}
|
||||
EXCHANGE_RATE = #{exchange_rate},
|
||||
ORDER_SUPPLY_PRICE = #{order_supply_price},
|
||||
ORDER_VAT = #{order_vat},
|
||||
ORDER_TOTAL_AMOUNT = #{order_total_amount}
|
||||
WHERE OBJID = #{objId}
|
||||
</update>
|
||||
|
||||
<!-- 계약 품목 조회 -->
|
||||
<select id="getContractItems" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
CI.OBJID,
|
||||
CI.CONTRACT_OBJID,
|
||||
CI.PART_OBJID,
|
||||
COALESCE(PM.PART_NO, CI.PART_NO) AS PART_NO,
|
||||
COALESCE(PM.PART_NAME, CI.PART_NAME) AS PART_NAME,
|
||||
STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SEQ) AS SERIAL_NO,
|
||||
CI.QUANTITY,
|
||||
CI.DUE_DATE,
|
||||
CI.CUSTOMER_REQUEST,
|
||||
CI.RETURN_REASON,
|
||||
CI.ORDER_QUANTITY,
|
||||
CI.ORDER_UNIT_PRICE,
|
||||
CI.ORDER_SUPPLY_PRICE,
|
||||
CI.ORDER_VAT,
|
||||
CI.ORDER_TOTAL_AMOUNT
|
||||
FROM
|
||||
CONTRACT_ITEM CI
|
||||
LEFT JOIN PART_MNG PM ON CI.PART_OBJID = PM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID AND CIS.STATUS = 'ACTIVE'
|
||||
WHERE
|
||||
CI.CONTRACT_OBJID = #{contractObjId}
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
GROUP BY
|
||||
CI.OBJID,
|
||||
CI.CONTRACT_OBJID,
|
||||
CI.PART_OBJID,
|
||||
CI.SEQ,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
CI.PART_NO,
|
||||
CI.PART_NAME,
|
||||
CI.QUANTITY,
|
||||
CI.DUE_DATE,
|
||||
CI.CUSTOMER_REQUEST,
|
||||
CI.RETURN_REASON,
|
||||
CI.ORDER_QUANTITY,
|
||||
CI.ORDER_UNIT_PRICE,
|
||||
CI.ORDER_SUPPLY_PRICE,
|
||||
CI.ORDER_VAT,
|
||||
CI.ORDER_TOTAL_AMOUNT
|
||||
ORDER BY CI.SEQ
|
||||
</select>
|
||||
|
||||
<!-- 계약 품목별 수주 정보 업데이트 (단일 품목) -->
|
||||
<update id="updateContractItemOrderInfo" parameterType="map">
|
||||
UPDATE CONTRACT_ITEM
|
||||
SET
|
||||
ORDER_QUANTITY = #{orderQuantity},
|
||||
ORDER_UNIT_PRICE = #{orderUnitPrice},
|
||||
ORDER_SUPPLY_PRICE = #{orderSupplyPrice},
|
||||
ORDER_VAT = #{orderVat},
|
||||
ORDER_TOTAL_AMOUNT = #{orderTotalAmount}
|
||||
WHERE OBJID = #{contractItemObjId}
|
||||
</update>
|
||||
|
||||
<!-- ====================================
|
||||
@@ -4409,7 +4582,94 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
SEQ
|
||||
</select>
|
||||
|
||||
<!-- 견적의 품목 전체 삭제 (상태 변경) -->
|
||||
<!-- 품목 UPSERT (INSERT or UPDATE) -->
|
||||
<insert id="upsertContractItem" parameterType="map">
|
||||
INSERT INTO CONTRACT_ITEM (
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
SEQ,
|
||||
PART_OBJID,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
QUANTITY,
|
||||
DUE_DATE,
|
||||
CUSTOMER_REQUEST,
|
||||
RETURN_REASON,
|
||||
REGDATE,
|
||||
WRITER,
|
||||
STATUS
|
||||
) VALUES (
|
||||
#{objId},
|
||||
#{contractObjId},
|
||||
#{seq},
|
||||
#{partObjId},
|
||||
#{partNo},
|
||||
#{partName},
|
||||
#{quantity},
|
||||
#{dueDate},
|
||||
#{customerRequest},
|
||||
#{returnReason},
|
||||
NOW(),
|
||||
#{writer},
|
||||
'ACTIVE'
|
||||
)
|
||||
ON CONFLICT (OBJID) DO UPDATE
|
||||
SET
|
||||
SEQ = #{seq},
|
||||
PART_OBJID = #{partObjId},
|
||||
PART_NO = #{partNo},
|
||||
PART_NAME = #{partName},
|
||||
QUANTITY = #{quantity},
|
||||
DUE_DATE = #{dueDate},
|
||||
CUSTOMER_REQUEST = #{customerRequest},
|
||||
RETURN_REASON = #{returnReason},
|
||||
CHGDATE = NOW(),
|
||||
CHG_USER_ID = #{writer},
|
||||
STATUS = 'ACTIVE'
|
||||
</insert>
|
||||
|
||||
<!-- S/N UPSERT (INSERT or UPDATE) -->
|
||||
<insert id="upsertContractItemSerial" parameterType="map">
|
||||
INSERT INTO CONTRACT_ITEM_SERIAL (
|
||||
OBJID,
|
||||
ITEM_OBJID,
|
||||
SEQ,
|
||||
SERIAL_NO,
|
||||
REGDATE,
|
||||
WRITER,
|
||||
STATUS
|
||||
) VALUES (
|
||||
#{objId},
|
||||
#{itemObjId},
|
||||
#{seq},
|
||||
#{serialNo},
|
||||
NOW(),
|
||||
#{writer},
|
||||
'ACTIVE'
|
||||
)
|
||||
ON CONFLICT (ITEM_OBJID, SERIAL_NO) DO UPDATE
|
||||
SET
|
||||
SEQ = #{seq},
|
||||
STATUS = 'ACTIVE'
|
||||
</insert>
|
||||
|
||||
<!-- 프론트에서 전달되지 않은 품목들 INACTIVE 처리 -->
|
||||
<update id="inactivateRemovedItems" parameterType="map">
|
||||
UPDATE CONTRACT_ITEM
|
||||
SET STATUS = 'INACTIVE',
|
||||
CHGDATE = NOW(),
|
||||
CHG_USER_ID = #{userId}
|
||||
WHERE CONTRACT_OBJID = #{contractObjId}
|
||||
AND STATUS = 'ACTIVE'
|
||||
<if test="currentItemObjIds != null and currentItemObjIds.size() > 0">
|
||||
AND OBJID NOT IN
|
||||
<foreach collection="currentItemObjIds" item="objId" open="(" separator="," close=")">
|
||||
#{objId}
|
||||
</foreach>
|
||||
</if>
|
||||
</update>
|
||||
|
||||
<!-- 견적의 품목 전체 삭제 (상태 변경) - 기존 방식, 호환성 유지 -->
|
||||
<update id="deleteContractItems" parameterType="map">
|
||||
UPDATE CONTRACT_ITEM
|
||||
SET STATUS = 'INACTIVE',
|
||||
|
||||
@@ -12,14 +12,19 @@ package com.pms.salesmgmt.service;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -1387,14 +1392,20 @@ public class ContractMgmtService {
|
||||
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = person.getUserId();
|
||||
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId")); // CONTRACT_OBJID
|
||||
String templateObjId = CommonUtils.checkNull(paramMap.get("templateObjId")); // 기존 템플릿 수정 시
|
||||
String templateType = CommonUtils.checkNull(paramMap.get("template_type"));
|
||||
String itemsJson = CommonUtils.checkNull(paramMap.get("items"));
|
||||
String categoriesJson = CommonUtils.checkNull(paramMap.get("categories"));
|
||||
|
||||
paramMap.put("writer", userId);
|
||||
paramMap.put("chg_user_id", userId);
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId")); // CONTRACT_OBJID
|
||||
String templateObjId = CommonUtils.checkNull(paramMap.get("templateObjId")); // 기존 템플릿 수정 시
|
||||
String templateType = CommonUtils.checkNull(paramMap.get("template_type"));
|
||||
String itemsJson = CommonUtils.checkNull(paramMap.get("items"));
|
||||
String categoriesJson = CommonUtils.checkNull(paramMap.get("categories"));
|
||||
|
||||
// 합계 정보 (일반 견적서용)
|
||||
String totalAmount = CommonUtils.checkNull(paramMap.get("total_amount"));
|
||||
String totalAmountKrw = CommonUtils.checkNull(paramMap.get("total_amount_krw"));
|
||||
|
||||
paramMap.put("writer", userId);
|
||||
paramMap.put("chg_user_id", userId);
|
||||
paramMap.put("total_amount", totalAmount);
|
||||
paramMap.put("total_amount_krw", totalAmountKrw);
|
||||
|
||||
// 기존 템플릿 수정인지 신규 작성인지 확인
|
||||
// 중요: templateObjId가 명시적으로 있을 때만 수정, 없으면 항상 신규 작성
|
||||
@@ -1610,18 +1621,24 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
contents.append("<head>");
|
||||
contents.append("<meta charset='UTF-8'>");
|
||||
contents.append("<style>");
|
||||
contents.append("body { font-family: 'Malgun Gothic', '맑은 고딕', Arial, sans-serif; margin: 20px; background-color: #f5f5f5; }");
|
||||
contents.append(".estimate-container { max-width: 800px; background: white; margin: 0 auto; padding: 40px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }");
|
||||
contents.append("body { font-family: 'Malgun Gothic', '맑은 고딕', Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }");
|
||||
contents.append(".estimate-container { max-width: 1200px; background: white; margin: 0 auto; padding: 40px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }");
|
||||
contents.append(".title { text-align: center; font-size: 24pt; font-weight: bold; letter-spacing: 10px; margin-bottom: 40px; border-bottom: 3px solid #333; padding-bottom: 20px; }");
|
||||
contents.append(".info-table { width: 100%; border-collapse: collapse; margin-bottom: 30px; }");
|
||||
contents.append(".info-table td { padding: 8px; border: 1px solid #000; font-size: 10pt; }");
|
||||
contents.append(".info-table .label { background-color: #f0f0f0; font-weight: bold; width: 100px; text-align: center; }");
|
||||
contents.append(".items-table { width: 100%; border-collapse: collapse; margin: 20px 0; }");
|
||||
contents.append(".header-section { width: 100%; margin-bottom: 30px; overflow: hidden; }");
|
||||
contents.append(".header-left { float: left; width: 48%; }");
|
||||
contents.append(".header-right { float: right; width: 48%; }");
|
||||
contents.append(".info-table { width: 100%; border-collapse: collapse; }");
|
||||
contents.append(".info-table td { padding: 10px; border: 1px solid #000; font-size: 10pt; vertical-align: middle; }");
|
||||
contents.append(".info-table .label { background-color: #f0f0f0; font-weight: bold; width: 120px; text-align: center; }");
|
||||
contents.append(".company-info { border: 2px solid #000; padding: 20px; text-align: center; min-height: 200px; box-sizing: border-box; }");
|
||||
contents.append(".company-stamp-img { max-width: 100%; height: auto; margin: 0 auto 15px; display: block; }");
|
||||
contents.append(".manager-info { margin-top: 15px; padding-top: 15px; border-top: 1px solid #ddd; text-align: left; font-size: 9pt; line-height: 1.8; }");
|
||||
contents.append(".items-table { width: 100%; border-collapse: collapse; margin: 20px 0; clear: both; }");
|
||||
contents.append(".items-table th, .items-table td { border: 1px solid #000; padding: 8px; font-size: 9pt; }");
|
||||
contents.append(".items-table th { background-color: #e0e0e0; font-weight: bold; text-align: center; }");
|
||||
contents.append(".text-right { text-align: right; }");
|
||||
contents.append(".text-center { text-align: center; }");
|
||||
contents.append(".note-section { margin-top: 30px; padding: 20px; background-color: #f9f9f9; border: 1px solid #ddd; }");
|
||||
contents.append(".note-section { margin-top: 30px; padding: 20px; background-color: #f9f9f9; border: 1px solid #ddd; clear: both; }");
|
||||
contents.append(".note-section h4 { margin-top: 0; font-size: 11pt; }");
|
||||
contents.append(".note-section div { margin: 10px 0; font-size: 9pt; line-height: 1.6; }");
|
||||
contents.append("</style>");
|
||||
@@ -1645,14 +1662,77 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
String executorDate = CommonUtils.checkNull(estimateTemplate.get("executor_date"));
|
||||
if("".equals(executorDate)) executorDate = CommonUtils.checkNull(estimateTemplate.get("EXECUTOR_DATE"));
|
||||
|
||||
// 기본 정보 테이블
|
||||
// 담당자 정보
|
||||
String managerName = CommonUtils.checkNull(estimateTemplate.get("manager_name"));
|
||||
if("".equals(managerName)) managerName = CommonUtils.checkNull(estimateTemplate.get("MANAGER_NAME"));
|
||||
if("".equals(managerName)) managerName = "영업부";
|
||||
|
||||
String managerContact = CommonUtils.checkNull(estimateTemplate.get("manager_contact"));
|
||||
if("".equals(managerContact)) managerContact = CommonUtils.checkNull(estimateTemplate.get("MANAGER_CONTACT"));
|
||||
|
||||
// 헤더 섹션 (왼쪽: 기본정보, 오른쪽: 회사정보)
|
||||
contents.append("<div class='header-section'>");
|
||||
|
||||
// 왼쪽: 기본 정보 테이블
|
||||
contents.append("<div class='header-left'>");
|
||||
contents.append("<table class='info-table'>");
|
||||
contents.append("<tr><td class='label'>수신처</td><td>" + recipient + "</td></tr>");
|
||||
contents.append("<tr><td class='label'>수신인</td><td>" + contactPerson + "</td></tr>");
|
||||
contents.append("<tr><td class='label'>견적번호</td><td>" + estimateNo + "</td></tr>");
|
||||
contents.append("<tr><td class='label'>영업번호</td><td>" + CommonUtils.checkNull(contractInfo.get("contract_no")) + "</td></tr>");
|
||||
contents.append("<tr><td class='label'>발행일</td><td>" + executorDate + "</td></tr>");
|
||||
contents.append("</table>");
|
||||
contents.append("</div>");
|
||||
|
||||
// 오른쪽: 회사 정보
|
||||
contents.append("<div class='header-right'>");
|
||||
contents.append("<div class='company-info'>");
|
||||
|
||||
// 회사 도장 이미지 경로
|
||||
String projectRoot = System.getProperty("user.dir");
|
||||
String companyStampPath = projectRoot + "/WebContent/images/company_stamp.png";
|
||||
|
||||
// Docker 환경인 경우 다른 경로 시도
|
||||
File stampFile = new File(companyStampPath);
|
||||
if(!stampFile.exists()) {
|
||||
companyStampPath = "/usr/local/tomcat/webapps/ROOT/images/company_stamp.png";
|
||||
stampFile = new File(companyStampPath);
|
||||
if(!stampFile.exists()) {
|
||||
companyStampPath = "";
|
||||
}
|
||||
}
|
||||
|
||||
String stampBase64 = !"".equals(companyStampPath) ? encodeImageToBase64(companyStampPath) : "";
|
||||
|
||||
if(!"".equals(stampBase64)) {
|
||||
// 이미지가 있으면 Base64로 인코딩된 이미지만 표시
|
||||
contents.append("<img src='" + stampBase64 + "' alt='회사 도장' class='company-stamp-img'>");
|
||||
} else {
|
||||
// 이미지가 없으면 텍스트로 표시
|
||||
contents.append("<div style='width:120px; height:120px; margin:0 auto 15px; border:2px solid #cc0000; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; background:linear-gradient(135deg, #fff 0%, #f5f5f5 100%);'>");
|
||||
contents.append("<div style='text-align:center; font-size:11pt; font-weight:bold; color:#cc0000; line-height:1.3;'>");
|
||||
contents.append("(주)알피에스<br>대표이사<br>이 종 현");
|
||||
contents.append("</div>");
|
||||
contents.append("</div>");
|
||||
contents.append("<div style='font-size:10pt; margin-bottom:5px;'>RPS CO., LTD</div>");
|
||||
contents.append("<div style='font-size:9pt; color:#666; margin-bottom:10px;'>대 표 이 사 이 종 현</div>");
|
||||
contents.append("<div style='font-size:9pt; line-height:1.8;'>");
|
||||
contents.append("<div>대전광역시 유성구 국제과학10로 8</div>");
|
||||
contents.append("<div>TEL:(042)602-3300 FAX:(042)672-3399</div>");
|
||||
contents.append("</div>");
|
||||
}
|
||||
|
||||
// 담당자 정보는 항상 표시
|
||||
contents.append("<div class='manager-info'>");
|
||||
contents.append("<div><strong>담당자 :</strong> " + managerName + "</div>");
|
||||
if(!"".equals(managerContact)) {
|
||||
contents.append("<div><strong>연락처 :</strong> " + managerContact + "</div>");
|
||||
}
|
||||
contents.append("</div>");
|
||||
|
||||
contents.append("</div>"); // company-info 닫기
|
||||
contents.append("</div>"); // header-right 닫기
|
||||
|
||||
contents.append("</div>"); // header-section 닫기
|
||||
|
||||
// 견적 품목
|
||||
if(estimateItems != null && !estimateItems.isEmpty()){
|
||||
@@ -1693,17 +1773,51 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
contents.append("</tr>");
|
||||
}
|
||||
|
||||
// 합계
|
||||
// 계 (총 합계)
|
||||
String totalAmountStr = CommonUtils.checkNull(estimateTemplate.get("total_amount"));
|
||||
if("".equals(totalAmountStr)) totalAmountStr = CommonUtils.checkNull(estimateTemplate.get("TOTAL_AMOUNT"));
|
||||
|
||||
// DB에 저장된 합계가 없으면 계산한 값 사용
|
||||
if("".equals(totalAmountStr)){
|
||||
totalAmountStr = String.format("%,d", totalAmount);
|
||||
}
|
||||
|
||||
contents.append("<tr style='background-color:#f0f0f0; font-weight:bold;'>");
|
||||
contents.append("<td colspan='6' class='text-right'>합계</td>");
|
||||
contents.append("<td class='text-right'>₩" + String.format("%,d", totalAmount) + "</td>");
|
||||
contents.append("<td colspan='6' class='text-center'>계</td>");
|
||||
contents.append("<td class='text-right'>" + totalAmountStr + "</td>");
|
||||
contents.append("<td></td>");
|
||||
contents.append("</tr>");
|
||||
|
||||
// 원화환산 공급가액
|
||||
String totalAmountKrw = CommonUtils.checkNull(estimateTemplate.get("total_amount_krw"));
|
||||
if("".equals(totalAmountKrw)) totalAmountKrw = CommonUtils.checkNull(estimateTemplate.get("TOTAL_AMOUNT_KRW"));
|
||||
|
||||
if(!"".equals(totalAmountKrw)){
|
||||
contents.append("<tr style='background-color:#e8f4f8; font-weight:bold;'>");
|
||||
contents.append("<td colspan='6' class='text-center'>원화환산 공급가액 (KRW)</td>");
|
||||
contents.append("<td class='text-right'>" + totalAmountKrw + "</td>");
|
||||
contents.append("<td></td>");
|
||||
contents.append("</tr>");
|
||||
}
|
||||
|
||||
// 테이블 내 비고
|
||||
String noteRemarks = CommonUtils.checkNull(estimateTemplate.get("note_remarks"));
|
||||
if("".equals(noteRemarks)) noteRemarks = CommonUtils.checkNull(estimateTemplate.get("NOTE_REMARKS"));
|
||||
|
||||
if(!"".equals(noteRemarks)){
|
||||
contents.append("<tr>");
|
||||
contents.append("<td colspan='8' style='height:100px; vertical-align:top; padding:10px; text-align:left;'>");
|
||||
contents.append("<div style='font-weight:bold; margin-bottom:10px;'><비고></div>");
|
||||
contents.append("<div style='white-space:pre-wrap;'>" + noteRemarks + "</div>");
|
||||
contents.append("</td>");
|
||||
contents.append("</tr>");
|
||||
}
|
||||
|
||||
contents.append("</tbody>");
|
||||
contents.append("</table>");
|
||||
}
|
||||
|
||||
// 비고 (대소문자 모두 체크)
|
||||
// 참조사항 (NOTE1~4)
|
||||
String note1 = CommonUtils.checkNull(estimateTemplate.get("note1"));
|
||||
if("".equals(note1)) note1 = CommonUtils.checkNull(estimateTemplate.get("NOTE1"));
|
||||
|
||||
@@ -1718,11 +1832,23 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
|
||||
if(!"".equals(note1) || !"".equals(note2) || !"".equals(note3) || !"".equals(note4)){
|
||||
contents.append("<div class='note-section'>");
|
||||
contents.append("<h4>※ 비고</h4>");
|
||||
if(!"".equals(note1)) contents.append("<div>1. " + note1 + "</div>");
|
||||
if(!"".equals(note2)) contents.append("<div>2. " + note2 + "</div>");
|
||||
if(!"".equals(note3)) contents.append("<div>3. " + note3 + "</div>");
|
||||
if(!"".equals(note4)) contents.append("<div>4. " + note4 + "</div>");
|
||||
contents.append("<h4>※ 참조사항</h4>");
|
||||
int noteNum = 1;
|
||||
if(!"".equals(note1)) {
|
||||
contents.append("<div>" + noteNum + ". " + note1 + "</div>");
|
||||
noteNum++;
|
||||
}
|
||||
if(!"".equals(note2)) {
|
||||
contents.append("<div>" + noteNum + ". " + note2 + "</div>");
|
||||
noteNum++;
|
||||
}
|
||||
if(!"".equals(note3)) {
|
||||
contents.append("<div>" + noteNum + ". " + note3 + "</div>");
|
||||
noteNum++;
|
||||
}
|
||||
if(!"".equals(note4)) {
|
||||
contents.append("<div>" + noteNum + ". " + note4 + "</div>");
|
||||
}
|
||||
contents.append("</div>");
|
||||
}
|
||||
|
||||
@@ -1733,6 +1859,42 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
return contents.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 이미지 파일을 Base64로 인코딩
|
||||
* @param imagePath 이미지 파일 경로
|
||||
* @return Base64 인코딩된 문자열 (data:image/png;base64,...)
|
||||
*/
|
||||
private String encodeImageToBase64(String imagePath) {
|
||||
try {
|
||||
File imageFile = new File(imagePath);
|
||||
if(!imageFile.exists()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
java.io.FileInputStream fis = new java.io.FileInputStream(imageFile);
|
||||
byte[] imageBytes = new byte[(int) imageFile.length()];
|
||||
fis.read(imageBytes);
|
||||
fis.close();
|
||||
|
||||
// Apache Commons Codec 사용 (Java 7 호환)
|
||||
String base64 = org.apache.commons.codec.binary.Base64.encodeBase64String(imageBytes);
|
||||
|
||||
// 파일 확장자로 MIME 타입 결정
|
||||
String mimeType = "image/png";
|
||||
if(imagePath.toLowerCase().endsWith(".jpg") || imagePath.toLowerCase().endsWith(".jpeg")) {
|
||||
mimeType = "image/jpeg";
|
||||
} else if(imagePath.toLowerCase().endsWith(".gif")) {
|
||||
mimeType = "image/gif";
|
||||
}
|
||||
|
||||
return "data:" + mimeType + ";base64," + base64;
|
||||
} catch(Exception e) {
|
||||
System.out.println("이미지 Base64 인코딩 실패: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 영업정보 조회 (수주등록용)
|
||||
* @param contractObjId
|
||||
@@ -1790,6 +1952,32 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
return resultMap != null ? resultMap : new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 계약 품목 조회
|
||||
* @param paramMap - contractObjId
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public List<Map> getContractItems(Map paramMap){
|
||||
SqlSession sqlSession = null;
|
||||
List<Map> items = new ArrayList<Map>();
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
items = sqlSession.selectList("contractMgmt.getContractItems", paramMap);
|
||||
|
||||
// 대문자 변환
|
||||
items = CommonUtils.keyChangeUpperList(items);
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Map saveOrderInfo(HttpServletRequest request, Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
@@ -1800,9 +1988,61 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
paramMap.put("writer", person.getUserId());
|
||||
|
||||
String contract_objid= CommonUtils.checkNull(paramMap.get("objId"));
|
||||
paramMap.put("objId", contract_objid);
|
||||
int cnt = sqlSession.update("contractMgmt.updateOrderInfo", paramMap);
|
||||
String contract_objid= CommonUtils.checkNull(paramMap.get("contractObjId"));
|
||||
paramMap.put("objId", contract_objid);
|
||||
|
||||
// 품목별 수주 정보 업데이트 및 합계 계산
|
||||
String itemsJson = CommonUtils.checkNull(paramMap.get("items_json"));
|
||||
long totalSupplyPrice = 0;
|
||||
long totalVat = 0;
|
||||
long totalAmount = 0;
|
||||
|
||||
if(!"".equals(itemsJson)){
|
||||
try {
|
||||
// JSON 파싱
|
||||
JSONParser parser = new JSONParser();
|
||||
JSONArray jsonArray = (JSONArray) parser.parse(itemsJson);
|
||||
|
||||
// 각 품목별로 업데이트 및 합계 계산
|
||||
for(int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject item = (JSONObject) jsonArray.get(i);
|
||||
Map<String, Object> itemMap = new HashMap<String, Object>();
|
||||
|
||||
String orderSupplyPrice = item.get("orderSupplyPrice") != null ? item.get("orderSupplyPrice").toString().replace(",", "") : "0";
|
||||
String orderVat = item.get("orderVat") != null ? item.get("orderVat").toString().replace(",", "") : "0";
|
||||
String orderTotalAmount = item.get("orderTotalAmount") != null ? item.get("orderTotalAmount").toString().replace(",", "") : "0";
|
||||
|
||||
itemMap.put("contractItemObjId", item.get("contractItemObjId") != null ? item.get("contractItemObjId").toString() : "");
|
||||
itemMap.put("orderQuantity", item.get("orderQuantity") != null ? item.get("orderQuantity").toString() : "");
|
||||
itemMap.put("orderUnitPrice", item.get("orderUnitPrice") != null ? item.get("orderUnitPrice").toString() : "");
|
||||
itemMap.put("orderSupplyPrice", orderSupplyPrice);
|
||||
itemMap.put("orderVat", orderVat);
|
||||
itemMap.put("orderTotalAmount", orderTotalAmount);
|
||||
|
||||
sqlSession.update("contractMgmt.updateContractItemOrderInfo", itemMap);
|
||||
|
||||
// 합계 계산
|
||||
try {
|
||||
totalSupplyPrice += Long.parseLong(orderSupplyPrice);
|
||||
totalVat += Long.parseLong(orderVat);
|
||||
totalAmount += Long.parseLong(orderTotalAmount);
|
||||
} catch (NumberFormatException e) {
|
||||
// 숫자 변환 실패 시 무시
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new Exception("품목 정보 저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
}
|
||||
|
||||
// 합계를 paramMap에 추가
|
||||
paramMap.put("order_supply_price", String.valueOf(totalSupplyPrice));
|
||||
paramMap.put("order_vat", String.valueOf(totalVat));
|
||||
paramMap.put("order_total_amount", String.valueOf(totalAmount));
|
||||
|
||||
// 기본 수주 정보 및 합계 업데이트
|
||||
int cnt = sqlSession.update("contractMgmt.updateOrderInfo", paramMap);
|
||||
|
||||
//영업 수주 완료시 자동 프로젝트 등록 로직
|
||||
String result_cd= CommonUtils.checkNull(paramMap.get("contract_result"));
|
||||
@@ -1818,51 +2058,96 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
//paramMap.put("contract_price_currency", contract_price_currency/project_cnt + "");
|
||||
//paramMap.put("contract_price", contract_price/project_cnt + "");
|
||||
|
||||
if("0000964".equals(result_cd) || "0000968".equals(result_cd)){
|
||||
resultList = sqlSession.selectOne("contractMgmt.getProjectListBycontractObjid", paramMap);
|
||||
System.out.println("resultList:::"+resultList);
|
||||
//resultList = sqlSession.selectOne("contractMgmt.getProjectCnt", paramMap);
|
||||
if(null==resultList){
|
||||
|
||||
// for (int i=0; i<project_cnt; i++){
|
||||
if("0000964".equals(result_cd) || "0000968".equals(result_cd)){
|
||||
// 품목별로 프로젝트 생성
|
||||
List<Map> contractItems = getContractItems(paramMap);
|
||||
|
||||
if(contractItems != null && !contractItems.isEmpty()) {
|
||||
System.out.println("품목 개수: " + contractItems.size() + "개 - 품목별 프로젝트 생성 시작");
|
||||
|
||||
for(Map item : contractItems) {
|
||||
// 품목별 프로젝트 존재 여부 확인
|
||||
Map<String, Object> projectCheckParam = new HashMap<String, Object>();
|
||||
projectCheckParam.put("contractObjId", contract_objid);
|
||||
projectCheckParam.put("part_objid", item.get("PART_OBJID"));
|
||||
|
||||
resultList = sqlSession.selectOne("contractMgmt.getProjectListByContractAndPartObjid", projectCheckParam);
|
||||
|
||||
if(null == resultList) {
|
||||
// 새 프로젝트 생성
|
||||
Map<String, Object> projectParam = new HashMap<String, Object>();
|
||||
projectParam.putAll(paramMap); // 기본 정보 복사
|
||||
|
||||
// 품목별 정보 설정
|
||||
projectParam.put("OBJID", CommonUtils.createObjId());
|
||||
projectParam.put("is_temp", '1');
|
||||
projectParam.put("part_objid", item.get("PART_OBJID"));
|
||||
projectParam.put("part_no", item.get("PART_NO"));
|
||||
projectParam.put("part_name", item.get("PART_NAME"));
|
||||
projectParam.put("quantity", item.get("ORDER_QUANTITY") != null ? item.get("ORDER_QUANTITY") : item.get("QUANTITY"));
|
||||
projectParam.put("due_date", item.get("DUE_DATE"));
|
||||
|
||||
paramMap.put("OBJID", CommonUtils.createObjId());
|
||||
paramMap.put("is_temp", '1');
|
||||
//paramMap.put("facility_qty", '1');
|
||||
if("0000170".equals(category_cd) || "0000171".equals(category_cd)){
|
||||
paramMap.put("overhaul_project_no", target_project_no);
|
||||
//paramMap.put("overhaul_order", overhaul_order+i);
|
||||
}else{
|
||||
projectParam.put("overhaul_project_no", target_project_no);
|
||||
}
|
||||
//프로젝트 등록
|
||||
cnt = sqlSession.update("project.createProject", paramMap);
|
||||
//프로젝트 TASK 등록
|
||||
cnt = sqlSession.insert("contractMgmt.insertProjectTask", paramMap);
|
||||
//프로젝트 SETUP_TASK 등록
|
||||
cnt = sqlSession.insert("contractMgmt.insertProjectSetupTask", paramMap);
|
||||
|
||||
//project_no - unit 폴더 생성
|
||||
//paramMap.put("OBJID", paramMap.get("OBJID"));
|
||||
Map<String,Object> projectInfo = (Map)sqlSession.selectOne("project.getProjectMngInfo", paramMap);
|
||||
|
||||
paramMap.put("contract_objid", paramMap.get("contractObjId"));
|
||||
paramMap.put("customer_product", paramMap.get("mechanical_type"));
|
||||
List<Map<String,Object>> taskUnitList = (ArrayList)sqlSession.selectList("project.getWbsTaskListByProject", paramMap);
|
||||
if(CommonUtils.isNotEmpty(taskUnitList) && !taskUnitList.isEmpty()){
|
||||
String projectNo = (String)projectInfo.get("project_no");
|
||||
String filepath = Constants.FILE_STORAGE+"\\PART_DATA\\";
|
||||
for (Map<String, Object> map : taskUnitList) {
|
||||
File file = new File(filepath+File.separator+projectNo+File.separator+CommonUtils.checkNull((String)map.get("unit_no"))+"-"+CommonUtils.checkNull((String)map.get("task_name")));
|
||||
if(!file.exists()){
|
||||
file.mkdirs();
|
||||
System.out.println("프로젝트 생성 - PART_OBJID: " + item.get("PART_OBJID") + ", 품번: " + item.get("PART_NO") + ", 품명: " + item.get("PART_NAME"));
|
||||
|
||||
// 프로젝트 등록
|
||||
cnt = sqlSession.update("project.createProject", projectParam);
|
||||
// 프로젝트 TASK 등록
|
||||
cnt = sqlSession.insert("contractMgmt.insertProjectTask", projectParam);
|
||||
// 프로젝트 SETUP_TASK 등록
|
||||
cnt = sqlSession.insert("contractMgmt.insertProjectSetupTask", projectParam);
|
||||
|
||||
// project_no - unit 폴더 생성
|
||||
Map<String,Object> projectInfo = (Map)sqlSession.selectOne("project.getProjectMngInfo", projectParam);
|
||||
|
||||
projectParam.put("contract_objid", contract_objid);
|
||||
projectParam.put("customer_product", projectParam.get("mechanical_type"));
|
||||
List<Map<String,Object>> taskUnitList = (ArrayList)sqlSession.selectList("project.getWbsTaskListByProject", projectParam);
|
||||
if(CommonUtils.isNotEmpty(taskUnitList) && !taskUnitList.isEmpty()){
|
||||
String projectNo = (String)projectInfo.get("project_no");
|
||||
String filepath = Constants.FILE_STORAGE+"\\PART_DATA\\";
|
||||
for (Map<String, Object> map : taskUnitList) {
|
||||
File file = new File(filepath+File.separator+projectNo+File.separator+CommonUtils.checkNull((String)map.get("unit_no"))+"-"+CommonUtils.checkNull((String)map.get("task_name")));
|
||||
if(!file.exists()){
|
||||
file.mkdirs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
} else {
|
||||
// 기존 프로젝트 업데이트
|
||||
Map<String, Object> updateParam = new HashMap<String, Object>();
|
||||
updateParam.putAll(paramMap);
|
||||
updateParam.put("part_objid", item.get("PART_OBJID"));
|
||||
updateParam.put("part_no", item.get("PART_NO"));
|
||||
updateParam.put("part_name", item.get("PART_NAME"));
|
||||
updateParam.put("quantity", item.get("ORDER_QUANTITY") != null ? item.get("ORDER_QUANTITY") : item.get("QUANTITY"));
|
||||
updateParam.put("due_date", item.get("DUE_DATE"));
|
||||
|
||||
System.out.println("프로젝트 업데이트 - PART_OBJID: " + item.get("PART_OBJID") + ", 품번: " + item.get("PART_NO"));
|
||||
sqlSession.update("project.ModifyProjectByContract", updateParam);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("품목이 없습니다 - 기존 방식으로 프로젝트 생성");
|
||||
// 품목이 없는 경우 기존 방식대로 처리
|
||||
resultList = sqlSession.selectOne("contractMgmt.getProjectListBycontractObjid", paramMap);
|
||||
if(null==resultList){
|
||||
paramMap.put("OBJID", CommonUtils.createObjId());
|
||||
paramMap.put("is_temp", '1');
|
||||
if("0000170".equals(category_cd) || "0000171".equals(category_cd)){
|
||||
paramMap.put("overhaul_project_no", target_project_no);
|
||||
}
|
||||
cnt = sqlSession.update("project.createProject", paramMap);
|
||||
cnt = sqlSession.insert("contractMgmt.insertProjectTask", paramMap);
|
||||
cnt = sqlSession.insert("contractMgmt.insertProjectSetupTask", paramMap);
|
||||
}else{
|
||||
sqlSession.update("project.ModifyProjectByContract", paramMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if(cnt > 0){
|
||||
//계약완료 일시 메일
|
||||
// if("0000964".equals(CommonUtils.checkNull(paramMap.get("contract_result")))){
|
||||
@@ -1890,7 +2175,7 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
}
|
||||
|
||||
/**
|
||||
* 품목 저장 (여러 건)
|
||||
* 품목 저장 (여러 건) - UPSERT 방식
|
||||
* @param contractObjId 견적 OBJID
|
||||
* @param itemList 품목 목록
|
||||
* @param userId 사용자 ID
|
||||
@@ -1901,94 +2186,109 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
System.out.println("=== saveContractItems 시작 ===");
|
||||
System.out.println("=== saveContractItems 시작 (UPSERT 방식) ===");
|
||||
System.out.println("contractObjId: " + contractObjId);
|
||||
System.out.println("itemList size: " + (itemList != null ? itemList.size() : 0));
|
||||
System.out.println("userId: " + userId);
|
||||
|
||||
// 기존 품목 삭제 (상태 변경)
|
||||
Map<String, Object> deleteParam = new HashMap<String, Object>();
|
||||
deleteParam.put("contractObjId", contractObjId);
|
||||
deleteParam.put("userId", userId);
|
||||
// 프론트에서 전달된 품목 OBJID 목록 수집
|
||||
Set<String> currentItemObjIds = new HashSet<String>();
|
||||
|
||||
sqlSession.update("contractMgmt.deleteContractItemSerials", deleteParam);
|
||||
sqlSession.update("contractMgmt.deleteContractItems", deleteParam);
|
||||
System.out.println("기존 품목 삭제 완료");
|
||||
|
||||
// 새 품목 저장
|
||||
// 품목 UPSERT
|
||||
if (itemList != null && !itemList.isEmpty()) {
|
||||
for (int i = 0; i < itemList.size(); i++) {
|
||||
Map<String, Object> item = itemList.get(i);
|
||||
|
||||
System.out.println("품목 " + (i+1) + " 처리 중: " + item);
|
||||
|
||||
// 품목 OBJID 생성 (CommonUtils 사용)
|
||||
String itemObjId = CommonUtils.createObjId();
|
||||
|
||||
// 품목 저장
|
||||
Map<String, Object> itemParam = new HashMap<String, Object>();
|
||||
itemParam.put("objId", itemObjId);
|
||||
itemParam.put("contractObjId", contractObjId);
|
||||
itemParam.put("seq", i + 1);
|
||||
itemParam.put("partObjId", item.get("partObjId"));
|
||||
itemParam.put("partNo", item.get("partNo"));
|
||||
itemParam.put("partName", item.get("partName"));
|
||||
|
||||
// quantity를 Integer로 변환
|
||||
Object quantityObj = item.get("quantity");
|
||||
Integer quantity = null;
|
||||
if(quantityObj != null) {
|
||||
if(quantityObj instanceof Integer) {
|
||||
quantity = (Integer) quantityObj;
|
||||
} else if(quantityObj instanceof Double) {
|
||||
quantity = ((Double) quantityObj).intValue();
|
||||
// 기존 품목 OBJID가 있으면 사용, 없으면 새로 생성
|
||||
String itemObjId = CommonUtils.checkNull(item.get("objId"));
|
||||
if (itemObjId.isEmpty()) {
|
||||
itemObjId = CommonUtils.createObjId();
|
||||
System.out.println("새 품목 OBJID 생성: " + itemObjId);
|
||||
} else {
|
||||
// String인 경우 콤마 제거 후 변환
|
||||
String quantityStr = quantityObj.toString().replace(",", "").trim();
|
||||
if(!quantityStr.isEmpty()) {
|
||||
quantity = Integer.parseInt(quantityStr);
|
||||
System.out.println("기존 품목 OBJID 사용: " + itemObjId);
|
||||
}
|
||||
currentItemObjIds.add(itemObjId);
|
||||
|
||||
// 품목 저장
|
||||
Map<String, Object> itemParam = new HashMap<String, Object>();
|
||||
itemParam.put("objId", itemObjId);
|
||||
itemParam.put("contractObjId", contractObjId);
|
||||
itemParam.put("seq", i + 1);
|
||||
itemParam.put("partObjId", item.get("partObjId"));
|
||||
itemParam.put("partNo", item.get("partNo"));
|
||||
itemParam.put("partName", item.get("partName"));
|
||||
|
||||
// quantity를 Integer로 변환
|
||||
Object quantityObj = item.get("quantity");
|
||||
Integer quantity = null;
|
||||
if(quantityObj != null) {
|
||||
if(quantityObj instanceof Integer) {
|
||||
quantity = (Integer) quantityObj;
|
||||
} else if(quantityObj instanceof Double) {
|
||||
quantity = ((Double) quantityObj).intValue();
|
||||
} else {
|
||||
// String인 경우 콤마 제거 후 변환
|
||||
String quantityStr = quantityObj.toString().replace(",", "").trim();
|
||||
if(!quantityStr.isEmpty()) {
|
||||
quantity = Integer.parseInt(quantityStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
itemParam.put("quantity", quantity);
|
||||
|
||||
itemParam.put("dueDate", item.get("dueDate"));
|
||||
itemParam.put("customerRequest", item.get("customerRequest"));
|
||||
itemParam.put("returnReason", item.get("returnReason"));
|
||||
itemParam.put("writer", userId);
|
||||
|
||||
System.out.println("품목 UPSERT 시도 - OBJID: " + itemObjId);
|
||||
int result = sqlSession.insert("contractMgmt.upsertContractItem", itemParam);
|
||||
System.out.println("품목 UPSERT 결과: " + result);
|
||||
|
||||
// 기존 S/N 전체 비활성화 (새로 저장할 것이므로)
|
||||
Map<String, Object> deleteSnParam = new HashMap<String, Object>();
|
||||
deleteSnParam.put("itemObjId", itemObjId);
|
||||
sqlSession.update("contractMgmt.deleteItemSerials", deleteSnParam);
|
||||
|
||||
// S/N 저장
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> snList = (List<Map<String, Object>>) item.get("snList");
|
||||
if (snList != null && !snList.isEmpty()) {
|
||||
for (int j = 0; j < snList.size(); j++) {
|
||||
Map<String, Object> sn = snList.get(j);
|
||||
String serialNo = (String) sn.get("value");
|
||||
|
||||
// S/N 값이 비어있으면 건너뛰기
|
||||
if (serialNo == null || serialNo.trim().isEmpty()) {
|
||||
System.out.println("S/N 값이 비어있어서 건너뜀");
|
||||
continue;
|
||||
}
|
||||
|
||||
// S/N OBJID는 항상 새로 생성 (기존 것을 비활성화했으므로)
|
||||
String snObjId = CommonUtils.createObjId();
|
||||
|
||||
Map<String, Object> snParam = new HashMap<String, Object>();
|
||||
snParam.put("objId", snObjId);
|
||||
snParam.put("itemObjId", itemObjId);
|
||||
snParam.put("seq", j + 1);
|
||||
snParam.put("serialNo", serialNo);
|
||||
snParam.put("writer", userId);
|
||||
|
||||
sqlSession.insert("contractMgmt.upsertContractItemSerial", snParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
itemParam.put("quantity", quantity);
|
||||
|
||||
itemParam.put("dueDate", item.get("dueDate"));
|
||||
itemParam.put("customerRequest", item.get("customerRequest"));
|
||||
itemParam.put("returnReason", item.get("returnReason"));
|
||||
itemParam.put("writer", userId);
|
||||
|
||||
System.out.println("품목 INSERT 시도 - OBJID: " + itemObjId);
|
||||
int result = sqlSession.insert("contractMgmt.insertContractItem", itemParam);
|
||||
System.out.println("품목 INSERT 결과: " + result);
|
||||
|
||||
// S/N 저장
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> snList = (List<Map<String, Object>>) item.get("snList");
|
||||
if (snList != null && !snList.isEmpty()) {
|
||||
for (int j = 0; j < snList.size(); j++) {
|
||||
Map<String, Object> sn = snList.get(j);
|
||||
String serialNo = (String) sn.get("value");
|
||||
|
||||
// S/N 값이 비어있으면 건너뛰기
|
||||
if (serialNo == null || serialNo.trim().isEmpty()) {
|
||||
System.out.println("S/N 값이 비어있어서 건너뜀");
|
||||
continue;
|
||||
}
|
||||
|
||||
// S/N OBJID 생성 (CommonUtils 사용)
|
||||
String snObjId = CommonUtils.createObjId();
|
||||
|
||||
Map<String, Object> snParam = new HashMap<String, Object>();
|
||||
snParam.put("objId", snObjId);
|
||||
snParam.put("itemObjId", itemObjId);
|
||||
snParam.put("seq", j + 1);
|
||||
snParam.put("serialNo", serialNo);
|
||||
snParam.put("writer", userId);
|
||||
|
||||
sqlSession.insert("contractMgmt.insertContractItemSerial", snParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 프론트에서 전달되지 않은 기존 품목들은 INACTIVE 처리
|
||||
if (!currentItemObjIds.isEmpty()) {
|
||||
Map<String, Object> inactiveParam = new HashMap<String, Object>();
|
||||
inactiveParam.put("contractObjId", contractObjId);
|
||||
inactiveParam.put("currentItemObjIds", new ArrayList<String>(currentItemObjIds));
|
||||
inactiveParam.put("userId", userId);
|
||||
sqlSession.update("contractMgmt.inactivateRemovedItems", inactiveParam);
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
|
||||
Reference in New Issue
Block a user