feat: 품번/품명 Select2 AJAX 검색 기능 추가
- common.js에 initPartSelect2Ajax 함수 추가 (기존 select2 영향 없음) - estimateList_new.jsp: 품번/품명 AJAX 검색 적용 - orderMgmtList.jsp: 품번/품명 AJAX 검색 적용 - 디버깅 로그 추가로 문제 해결 용이
This commit is contained in:
@@ -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: '발송',
|
||||
@@ -381,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);
|
||||
}
|
||||
|
||||
@@ -495,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){
|
||||
@@ -508,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>';
|
||||
@@ -515,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>';
|
||||
});
|
||||
|
||||
@@ -855,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>
|
||||
|
||||
@@ -224,6 +224,7 @@ var g_contractObjId = "<%=objId%>";
|
||||
var g_templateObjId = "<%=templateObjId%>";
|
||||
var g_exchangeRate = 1; // 환율 (기본값 1)
|
||||
var g_currencyName = "KRW"; // 통화명 (기본값 원화)
|
||||
var g_apprStatus = ""; // 결재상태
|
||||
|
||||
$(function(){
|
||||
|
||||
@@ -293,6 +294,33 @@ $(function(){
|
||||
}
|
||||
});
|
||||
|
||||
// 결재상태에 따라 버튼 표시 제어
|
||||
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";
|
||||
@@ -376,12 +404,17 @@ function fn_loadData() {
|
||||
g_exchangeRate = parseFloat(data.estimate.EXCHANGE_RATE || "1");
|
||||
g_currencyName = data.estimate.CONTRACT_CURRENCY_NAME || "KRW";
|
||||
|
||||
// 데이터 바인딩
|
||||
$("#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_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) {
|
||||
@@ -423,18 +456,24 @@ function fn_loadData() {
|
||||
itemsHtml += '</td>';
|
||||
itemsHtml += '</tr>';
|
||||
|
||||
$("#itemsTableBody").html(itemsHtml);
|
||||
|
||||
// 합계 계산
|
||||
fn_calculateTotal();
|
||||
}
|
||||
$("#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("데이터를 불러오는데 실패했습니다.");
|
||||
@@ -461,33 +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_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){
|
||||
@@ -530,26 +581,32 @@ function fn_loadTemplateData(templateObjId){
|
||||
$("#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);
|
||||
|
||||
// 합계 계산
|
||||
fn_calculateTotal();
|
||||
}
|
||||
} else {
|
||||
console.error("데이터 로드 실패:", data);
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
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("데이터를 불러오는데 실패했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 저장
|
||||
@@ -596,6 +653,9 @@ function fn_save() {
|
||||
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(),
|
||||
@@ -665,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>
|
||||
|
||||
@@ -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();
|
||||
@@ -599,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>
|
||||
|
||||
@@ -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 '테이블 내 비고 (품목 하단)';
|
||||
|
||||
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 '계약-품목별 프로젝트 조회 성능 향상';
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
|
||||
@@ -753,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 != ''">
|
||||
@@ -779,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
|
||||
@@ -3095,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} -->
|
||||
)
|
||||
@@ -3465,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.*
|
||||
@@ -3809,25 +3829,40 @@ 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 테이블) -->
|
||||
@@ -3848,24 +3883,42 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
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
|
||||
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 ET
|
||||
LEFT JOIN CONTRACT_MGMT CM ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE
|
||||
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
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND ET.TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
ORDER BY ET.REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (OBJID 기준) -->
|
||||
@@ -3886,14 +3939,32 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
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
|
||||
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 ET
|
||||
LEFT JOIN CONTRACT_MGMT CM ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
@@ -3963,39 +4034,45 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
TOTAL_AMOUNT,
|
||||
TOTAL_AMOUNT_KRW,
|
||||
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},
|
||||
#{total_amount},
|
||||
#{total_amount_krw},
|
||||
#{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>
|
||||
|
||||
<!-- 견적서 템플릿 수정 -->
|
||||
@@ -4010,16 +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},
|
||||
TOTAL_AMOUNT = #{total_amount},
|
||||
TOTAL_AMOUNT_KRW = #{total_amount_krw},
|
||||
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>
|
||||
|
||||
<!-- 견적서 템플릿 품목 삭제 -->
|
||||
@@ -4095,8 +4175,11 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
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",
|
||||
@@ -4104,11 +4187,11 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
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}
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE ET
|
||||
LEFT JOIN CONTRACT_MGMT CM ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE
|
||||
ET.CONTRACT_OBJID = #{objId}
|
||||
ORDER BY
|
||||
ET.TEMPLATE_TYPE,
|
||||
ET.REGDATE DESC
|
||||
|
||||
@@ -1621,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>");
|
||||
@@ -1656,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()){
|
||||
@@ -1704,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"));
|
||||
|
||||
@@ -1729,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>");
|
||||
}
|
||||
|
||||
@@ -1744,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
|
||||
@@ -1907,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")))){
|
||||
|
||||
Reference in New Issue
Block a user