견적관리, 주문서관리 수정

This commit is contained in:
2025-10-22 16:18:07 +09:00
parent 4ba30255ba
commit 2fafff5ee5
7 changed files with 817 additions and 282 deletions

View File

@@ -596,7 +596,7 @@ function fn_openEstimateByObjId(templateObjId, templateType){
Swal.close();
var popup_width = 900;
var popup_height = 800;
var popup_height = 1200;
var url = "";
if(templateType === "1"){
@@ -613,7 +613,7 @@ function fn_openEstimateByObjId(templateObjId, templateType){
//견적서 양식 열기 (CONTRACT_OBJID로)
function fn_openEstimateTemplate(objId, templateType){
var popup_width = 900;
var popup_height = 800;
var popup_height = 1200;
var url = "";
if(templateType === "1"){
@@ -686,6 +686,9 @@ function fn_sendEstimateMail(contractObjId){
text: '견적서가 성공적으로 발송되었습니다.',
icon: 'success',
confirmButtonText: '확인'
}).then(() => {
// 메일 발송 상태 업데이트를 위해 목록 새로고침
fn_search();
});
} else {
Swal.fire({

View File

@@ -42,9 +42,15 @@
var itemCounter = 1;
var itemList = [];
// 반납사유 공통코드 옵션 (숨겨진 div에서 읽어옴)
var returnReasonOptions = '';
// 품번 데이터는 AJAX로 검색하므로 초기 데이터 없음
$(function() {
// 반납사유 옵션을 템플릿에서 읽어옴
returnReasonOptions = $('#return_reason_template').html();
//alert("${info.CATEGORY_CD}")
if("${info.CATEGORY_CD}" == '0000170' || "${info.CATEGORY_CD}" == '0000171'){//오버홀, 개조
$(".DIRECT").show();
@@ -480,7 +486,8 @@
var serialNos = "<%= item.get("SERIAL_NOS") != null ? item.get("SERIAL_NOS") : (item.get("serial_nos") != null ? item.get("serial_nos") : "") %>";
var quantity = "<%= item.get("QUANTITY") != null ? item.get("QUANTITY") : (item.get("quantity") != null ? item.get("quantity") : "") %>";
var dueDate = "<%= item.get("DUE_DATE") != null ? item.get("DUE_DATE") : (item.get("due_date") != null ? item.get("due_date") : "") %>";
var customerRequest = "<%= item.get("CUSTOMER_REQUEST") != null ? item.get("CUSTOMER_REQUEST") : (item.get("customer_request") != null ? item.get("customer_request") : "") %>";
// 고객요청사항 - 특수문자 이스케이프 처리
var customerRequest = <%= new com.google.gson.Gson().toJson(item.get("CUSTOMER_REQUEST") != null ? item.get("CUSTOMER_REQUEST") : (item.get("customer_request") != null ? item.get("customer_request") : "")) %>;
var returnReason = "<%= item.get("RETURN_REASON") != null ? item.get("RETURN_REASON") : (item.get("return_reason") != null ? item.get("return_reason") : "") %>";
html += '<td style="padding:5px; border:1px solid #ddd;">';
@@ -493,43 +500,71 @@
html += '<td style="padding:5px; border:1px solid #ddd;">';
html += '<input type="text" name="item_due_date[]" class="item-due-date date_icon" style="width:90%; padding:5px;" value="' + dueDate + '" />';
html += '</td>';
html += '<td style="padding:5px; border:1px solid #ddd;">';
html += '<input type="text" name="item_customer_request[]" class="item-customer-request" style="width:95%; padding:5px;" value="' + customerRequest + '" />';
html += '</td>';
html += '<td style="padding:5px; border:1px solid #ddd;">';
html += '<input type="text" name="item_return_reason[]" class="item-return-reason" style="width:95%; padding:5px;" value="' + returnReason + '" />';
html += '</td>';
html += '<td style="text-align:center; padding:5px; border:1px solid #ddd;">';
html += '<button type="button" onclick="fn_deleteItemRow(\'' + itemId + '\')" class="plm_btns" style="padding:5px 10px; font-size:12px;">삭제</button>';
html += '</td>';
html += '</tr>';
html += '<td style="padding:5px; border:1px solid #ddd;">';
html += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:95%; padding:5px; min-height:34px; resize:vertical; font-family:inherit; font-size:inherit;" rows="1"></textarea>';
html += '</td>';
html += '<td style="padding:5px; border:1px solid #ddd;">';
html += '<select name="item_return_reason[]" class="item-return-reason select2" style="width:95%;"></select>';
html += '</td>';
html += '<td style="text-align:center; padding:5px; border:1px solid #ddd;">';
html += '<button type="button" onclick="fn_deleteItemRow(\'' + itemId + '\')" class="plm_btns" style="padding:5px 10px; font-size:12px;">삭제</button>';
html += '</td>';
html += '</tr>';
$("#itemListBody").append(html);
// 고객요청사항 값 설정 (안전하게 text로 설정)
if(customerRequest) {
$("#" + itemId + " .item-customer-request").val(customerRequest);
}
$("#itemListBody").append(html);
// S/N 데이터 설정 - JSON 객체를 문자열로 변환하여 저장
var snJsonString = JSON.stringify(snJsonData);
// DOM이 완전히 준비된 후 값 설정
setTimeout(function() {
$("#" + itemId + "_sn_list").val(snJsonString);
}, 10);
// 품번/품명 옵션 채우기 (저장된 품번/품명도 함께 전달)
fn_fillPartOptions(itemId, savedPartObjId, savedPartNo, savedPartName);
// datepicker 적용
$("#" + itemId + " .date_icon").datepicker({
changeMonth: true,
changeYear: true
});
// 숫자만 입력 처리 및 콤마 추가
$("#" + itemId + " .item-quantity").on("keyup", function() {
$(this).val(addComma($(this).val().replace(/[^0-9]/g, "")));
});
// 이미 저장된 수량에 콤마 추가
var qtyInput = $("#" + itemId + " .item-quantity");
qtyInput.val(addComma(qtyInput.val()));
// S/N 데이터 설정 - JSON 객체를 문자열로 변환하여 저장
var snJsonString = JSON.stringify(snJsonData);
// DOM이 완전히 준비된 후 값 설정
setTimeout(function() {
$("#" + itemId + "_sn_list").val(snJsonString);
// 반납사유 select 값 설정
if(returnReason) {
$("#" + itemId + " .item-return-reason").val(returnReason).trigger('change');
}
}, 10);
// 품번/품명 옵션 채우기 (저장된 품번/품명도 함께 전달)
fn_fillPartOptions(itemId, savedPartObjId, savedPartNo, savedPartName);
// datepicker 적용
$("#" + itemId + " .date_icon").datepicker({
changeMonth: true,
changeYear: true
});
// 반납사유 옵션 추가 및 select2 초기화
$("#" + itemId + " .item-return-reason").html(returnReasonOptions).select2({
width: '100%'
});
// 고객요청사항 textarea 자동 높이 조절
var $textarea = $("#" + itemId + " .item-customer-request");
$textarea.on('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
// 기존 데이터가 있으면 높이 조절 (약간의 지연 후 실행)
setTimeout(function() {
if($textarea.val()) {
$textarea[0].style.height = 'auto';
$textarea[0].style.height = ($textarea[0].scrollHeight) + 'px';
}
}, 50);
// 숫자만 입력 처리 및 콤마 추가
$("#" + itemId + " .item-quantity").on("keyup", function() {
$(this).val(addComma($(this).val().replace(/[^0-9]/g, "")));
});
// 이미 저장된 수량에 콤마 추가
var qtyInput = $("#" + itemId + " .item-quantity");
qtyInput.val(addComma(qtyInput.val()));
// 품목 정보 저장
itemList.push({
@@ -1180,10 +1215,10 @@
html += '<input type="text" name="item_due_date[]" class="item-due-date date_icon" style="width:90%; padding:5px;" />';
html += '</td>';
html += '<td style="padding:5px; border:1px solid #ddd;">';
html += '<input type="text" name="item_customer_request[]" class="item-customer-request" style="width:95%; padding:5px;" />';
html += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:95%; padding:5px; min-height:34px; resize:vertical; font-family:inherit; font-size:inherit;" rows="1"></textarea>';
html += '</td>';
html += '<td style="padding:5px; border:1px solid #ddd;">';
html += '<input type="text" name="item_return_reason[]" class="item-return-reason" style="width:95%; padding:5px;" />';
html += '<select name="item_return_reason[]" class="item-return-reason select2" style="width:95%;"></select>';
html += '</td>';
html += '<td style="text-align:center; padding:5px; border:1px solid #ddd;">';
html += '<button type="button" onclick="fn_deleteItemRow(\'' + itemId + '\')" class="plm_btns" style="padding:5px 10px; font-size:12px;">삭제</button>';
@@ -1195,18 +1230,29 @@
// 품번/품명 옵션 채우기 (신규 추가)
fn_fillPartOptions(itemId, null, null, null);
// 추가된 행의 날짜 필드에 datepicker 적용
$("#" + itemId + " .date_icon").datepicker({
changeMonth: true,
changeYear: true
});
// 숫자만 입력 처리
$("#" + itemId + " .item-quantity").on("keyup", function() {
$(this).val(addComma($(this).val().replace(/[^0-9]/g, "")));
});
// 품목 정보 저장
// 추가된 행의 날짜 필드에 datepicker 적용
$("#" + itemId + " .date_icon").datepicker({
changeMonth: true,
changeYear: true
});
// 반납사유 옵션 추가 및 select2 초기화
$("#" + itemId + " .item-return-reason").html(returnReasonOptions).select2({
width: '100%'
});
// 고객요청사항 textarea 자동 높이 조절
$("#" + itemId + " .item-customer-request").on('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
// 숫자만 입력 처리
$("#" + itemId + " .item-quantity").on("keyup", function() {
$(this).val(addComma($(this).val().replace(/[^0-9]/g, "")));
});
// 품목 정보 저장
itemList.push({
id: itemId,
snList: []
@@ -1765,18 +1811,24 @@
<input type="hidden" name="actionType" id="actionType" value="${actionType}">
<input type="hidden" name="serial_no_list" id="serial_no_list" value="">
<section class="business_popup_min_width">
<div class="plm_menu_name">
<h2>
<span>영업관리_견적관리_견적요청등록</span>
</h2>
</div>
<!-- 반납사유 공통코드 템플릿 (숨김) -->
<select id="return_reason_template" style="display:none;">
<option value="">선택</option>
${code_map.return_reason_cd}
</select>
<section class="business_popup_min_width">
<div class="plm_menu_name">
<h2>
<span>영업관리_견적관리_견적요청등록</span>
</h2>
</div>
<div id="EntirePopupFormWrap">
<!-- 기본정보 영역 -->
<div class="form_popup_title">
<span>견적요청 기본정보</span>
</div>
<div id="EntirePopupFormWrap">
<!-- 기본정보 영역 -->
<div class="form_popup_title">
<span>견적요청 기본정보</span>
</div>
<table class="">
<colgroup>
<col width="100%" />
@@ -1841,14 +1893,14 @@
<td>
<input type="text" class="date_icon" name="receipt_date" id="receipt_date" reqTitle="접수일" value="${info.RECEIPT_DATE}" required>
</td>
<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 class="input_title"><label for="">견적환율</label></td>
<td>
<input type="text" name="exchange_rate" id="exchange_rate" reqTitle="환율" value="${info.EXCHANGE_RATE}" />
</td>

View File

@@ -4,8 +4,45 @@
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@include file= "/init.jsp" %>
<%
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
String userId = CommonUtils.checkNull(person.getUserId());
// init.jsp에서 이미 connectUserName이 설정되어 있음
String userName = connectUserName;
String userId = connectUserId;
// 전화번호는 별도로 조회 필요
String userPhone = "";
try {
com.pms.common.SqlMapConfig sqlMapConfig = com.pms.common.SqlMapConfig.getInstance();
org.apache.ibatis.session.SqlSession sqlSession = sqlMapConfig.getSqlSession(false);
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("userId", userId);
Map<String, Object> userInfo = (Map<String, Object>) sqlSession.selectOne("login.getUserInfo", paramMap);
if(userInfo != null) {
// MyBatis가 소문자로 변환하므로 소문자 우선 시도
String cellPhone = (String)userInfo.get("cell_phone");
String tel = (String)userInfo.get("tel");
// 소문자로 안되면 대문자 시도 (호환성)
if(cellPhone == null) {
cellPhone = (String)userInfo.get("CELL_PHONE");
}
if(tel == null) {
tel = (String)userInfo.get("TEL");
}
userPhone = CommonUtils.checkNull(cellPhone);
if("".equals(userPhone)) {
userPhone = CommonUtils.checkNull(tel);
}
}
sqlSession.close();
} catch(Exception e) {
System.out.println("전화번호 조회 오류: " + e.getMessage());
e.printStackTrace();
}
String objId = CommonUtils.checkNull(request.getParameter("objId"));
String templateObjId = CommonUtils.checkNull(request.getParameter("templateObjId"));
%>
@@ -34,6 +71,7 @@ body {
font-size: 12pt;
margin: 0;
padding: 20px;
padding-bottom: 100px; /* 고정 버튼 영역을 위한 하단 여백 */
background-color: #f5f5f5;
}
@@ -173,24 +211,48 @@ body {
}
.btn-area {
position: fixed;
bottom: 0;
left: 0;
right: 0;
text-align: right;
margin-top: 20px;
padding: 10px;
padding: 15px 30px;
background-color: #ffffff;
border-top: 3px solid #007bff;
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
z-index: 1000;
}
.plm_btns {
padding: 10px 30px;
margin: 0 5px;
font-size: 14px;
cursor: pointer;
border: 1px solid #ddd;
background-color: #f8f9fa;
transition: background-color 0.2s;
.plm_btns:first-child {
margin-left: 600px;
}
/* .plm_btns {
display: inline-block;
padding: 12px 40px;
margin: 0 5px;
font-size: 15px;
font-weight: bold;
cursor: pointer;
border: 2px solid #007bff;
background-color: #007bff;
color: white;
border-radius: 5px;
transition: all 0.3s;
line-height: 1;
vertical-align: middle;
white-space: nowrap;
} */
.plm_btns:hover {
background-color: #e2e6ea;
border-color: #dae0e5;
background-color: #0056b3;
border-color: #0056b3;
box-shadow: 0 2px 6px rgba(0,123,255,0.4);
}
.plm_btns:active {
background-color: #004085;
border-color: #004085;
box-shadow: 0 1px 3px rgba(0,123,255,0.2);
}
input[type="text"],
@@ -225,9 +287,42 @@ var g_templateObjId = "<%=templateObjId%>";
var g_exchangeRate = 1; // 환율 (기본값 1)
var g_currencyName = "KRW"; // 통화명 (기본값 원화)
var g_apprStatus = ""; // 결재상태
var g_userPhone = "<%=userPhone%>"; // 로그인 사용자 연락처
$(function(){
// 로그인 사용자 정보 디버깅
//console.log("=== 로그인 사용자 정보 ===");
//console.log("g_userPhone:", g_userPhone);
// 로그인 사용자 정보 자동 입력
// HTML에서 이미 초기값이 설정되어 있으므로 연락처만 설정
$("#manager_contact").val(g_userPhone || "");
$("#manager_name").val('<%=connectUserDeptName%> '+' <%=connectUserName%>');
//console.log("manager_contact 설정값:", $("#manager_contact").val());
// 시행일자 datepicker 초기화
$("#executor").datepicker({
changeMonth: true,
changeYear: true,
dateFormat: 'yy-mm-dd'
});
// 수신처(고객사) select2 초기화
$("#recipient").select2({
width: '100%',
placeholder: '고객사 선택'
});
// 수신처 변경 시 수신인 자동 입력
$("#recipient").change(function(){
// 데이터 로드 중이 아닐 때만 수신인 자동 로드
if(!window.isLoadingData) {
fn_loadCustomerContact($(this).val());
}
});
// templateObjId가 있으면 기존 데이터 로드
var templateObjId = "<%=templateObjId%>";
if(templateObjId && templateObjId !== ""){
@@ -262,12 +357,18 @@ $(function(){
fn_calculateTotal(); // 합계 재계산
});
// 금액 필드 직접 수정 시에도 합계 재계산
$(document).on("change keyup", ".item-amount", function(){
fn_calculateTotal(); // 합계 재계산
});
// 콤마 자동 추가 (동적 요소 포함)
$(document).on("blur", ".item-price, .item-amount", function(){
var val = $(this).val().replace(/,/g, "").replace(/₩/g, "");
if(!isNaN(val) && val !== "") {
$(this).val(addComma(val));
}
fn_calculateTotal(); // blur 시에도 합계 재계산
});
// 단가 입력 시 실시간 콤마 처리
@@ -289,33 +390,60 @@ $(function(){
if("<%=objId%>" !== "" && "<%=objId%>" !== "-1") {
fn_loadData();
} else {
// 새 견적서 작성 시 기본 행의 셀렉트박스 초기화
fn_initItemDescSelect('default_item_1');
fn_initItemDescSelect('default_item_2');
// 초기 로드 시 합계 계산
fn_calculateTotal();
// 새로 등록 시 명시적으로 작성중 상태 설정
g_apprStatus = "작성중";
fn_controlButtons();
}
});
// 결재상태에 따라 버튼 표시 제어
function fn_controlButtons() {
console.log("=== fn_controlButtons 호출 ===");
console.log("g_apprStatus:", g_apprStatus);
if(g_apprStatus === "결재완료") {
console.log("결재완료 상태 - 입력 필드 비활성화");
// 결재완료된 경우 행추가, 저장 버튼 숨김
$("#btnAddItem").hide();
$("#btnAddRow").hide();
$("#btnSave").hide();
// 모든 입력 필드를 읽기 전용으로 변경
$("input, textarea").attr("readonly", true);
$("input, textarea").css("background-color", "#f5f5f5");
// select 박스 비활성화 (고객사 선택 등)
$("select").attr("disabled", true);
$("select").css("background-color", "#f5f5f5");
// datepicker 비활성화
$("#executor").datepicker("option", "disabled", true);
// 삭제 버튼 숨김
$(".btn-delete-row").hide();
} else {
console.log("결재완료 아님 - 입력 필드 활성화");
// 결재완료가 아닌 경우 버튼 표시
$("#btnAddItem").show();
$("#btnAddRow").show();
$("#btnSave").show();
// 입력 필드 활성화
$("input, textarea").attr("readonly", false);
$("input, textarea").css("background-color", "");
// select 박스 활성화
$("select").attr("disabled", false);
$("select").css("background-color", "");
// datepicker 활성화
$("#executor").datepicker("option", "disabled", false);
// 삭제 버튼 표시
$(".btn-delete-row").show();
}
@@ -339,14 +467,15 @@ function fn_calculateTotal() {
// 품목 행만 순회 (계 행, 원화환산 행, 비고 행 제외)
$("#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, "");
// 콤마와 통화 기호 제거 후 숫자로 변환
amount = amount.replace(/,/g, "").replace(/₩/g, "").replace(/\$/g, "").replace(/€/g, "").replace(/¥/g, "");
var numAmount = parseInt(amount) || 0;
total += numAmount;
});
// 합계 행에 표시
$("#totalAmount").text(addComma(total));
// 합계 행에 통화 기호와 함께 표시
var currencySymbol = getCurrencySymbol();
$("#totalAmount").text(currencySymbol + addComma(total));
// 원화환산 금액 계산 및 표시
fn_calculateTotalKRW(total);
@@ -355,7 +484,7 @@ function fn_calculateTotal() {
// 원화환산 공급가액 계산
function fn_calculateTotalKRW(total) {
var totalKRW = total * g_exchangeRate;
$("#totalAmountKRW").text(addComma(Math.round(totalKRW)));
$("#totalAmountKRW").text("₩" + addComma(Math.round(totalKRW)));
}
// 콤마 추가
@@ -364,6 +493,90 @@ function addComma(num) {
return num.toString().replace(regexp, ',');
}
// 통화 기호 반환
function getCurrencySymbol() {
if(g_currencyName.indexOf("달러") >= 0 || g_currencyName === "USD") {
return "$";
} else if(g_currencyName.indexOf("유로") >= 0 || g_currencyName === "EUR") {
return "€";
} else if(g_currencyName.indexOf("엔") >= 0 || g_currencyName === "JPY") {
return "¥";
} else if(g_currencyName.indexOf("위안") >= 0 || g_currencyName === "CNY") {
return "¥";
} else {
return "₩"; // 기본값 원화
}
}
// 품명 셀렉트박스 초기화 함수
function fn_initItemDescSelect(itemId) {
$("#" + itemId + " .item-desc-select").select2({
placeholder: "품명 입력하여 검색...",
allowClear: true,
width: '100%',
minimumInputLength: 1,
language: {
inputTooShort: function() {
return "최소 1글자 이상 입력하세요";
},
searching: function() {
return "검색 중...";
},
noResults: function() {
return "검색 결과가 없습니다";
}
},
ajax: {
url: '/contractMgmt/searchPartList.do',
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;
var spec = item.SPECIFICATION || item.specification || '';
return {
id: objId,
text: partName,
partName: partName,
partNo: partNo,
spec: spec
};
});
return {
results: results
};
},
cache: true
}
});
// 품명 선택 시 hidden 필드와 규격 자동 입력
$("#" + itemId + " .item-desc-select").on('change', function() {
var selectedData = $(this).select2('data')[0];
if(selectedData) {
$("#" + itemId + " .item-desc").val(selectedData.text);
$("#" + itemId + " .item-part-objid").val(selectedData.id); // part_objid 저장
if(selectedData.spec) {
$("#" + itemId + " .item-spec").val(selectedData.spec);
}
} else {
$("#" + itemId + " .item-desc").val('');
$("#" + itemId + " .item-part-objid").val(''); // part_objid 초기화
}
});
}
// 행 추가 함수
function fn_addItemRow() {
// 계 행, 원화환산 행, 비고 행 제외하고 품목 행 개수 계산
@@ -371,20 +584,28 @@ function fn_addItemRow() {
var nextNo = itemRows.length + 1;
// 새 행 생성
var newRow = '<tr>' +
var itemId = 'item_' + new Date().getTime();
var newRow = '<tr id="' + itemId + '">' +
'<td>' + nextNo + '</td>' +
'<td class="text-left editable"><input type="text" class="item-desc" value=""></td>' +
'<td class="text-left editable">' +
'<select class="item-desc-select" style="width:100%;"></select>' +
'<input type="hidden" class="item-desc" value="">' +
'<input type="hidden" class="item-part-objid" value="">' +
'</td>' +
'<td class="text-left editable"><textarea class="item-spec"></textarea></td>' +
'<td class="editable"><input type="text" class="item-qty" value=""></td>' +
'<td class="editable"><input type="text" class="item-unit" value="EA"></td>' +
'<td class="text-right editable"><input type="text" class="item-price" value=""></td>' +
'<td class="text-right editable"><input type="text" class="item-amount" value="₩0" readonly></td>' +
'<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>';
// 계 행 바로 위에 추가
$(".total-row").before(newRow);
// 품명 셀렉트박스 초기화
fn_initItemDescSelect(itemId);
// 합계 재계산
fn_calculateTotal();
}
@@ -399,39 +620,69 @@ function fn_loadData() {
},
dataType: "json",
success: function(data) {
if(data && data.estimate) {
// 환율 정보 저장
g_exchangeRate = parseFloat(data.estimate.EXCHANGE_RATE || "1");
g_currencyName = data.estimate.CONTRACT_CURRENCY_NAME || "KRW";
if(data && data.estimate) {
// 환율 정보 저장 (소문자 우선)
var exchangeRate = data.estimate.exchange_rate || data.estimate.EXCHANGE_RATE || "1";
var currencyName = data.estimate.contract_currency_name || data.estimate.CONTRACT_CURRENCY_NAME || "KRW";
g_exchangeRate = parseFloat(exchangeRate);
g_currencyName = currencyName;
// 결재상태 저장
g_apprStatus = data.estimate.APPR_STATUS || "작성중";
// 결재상태 저장
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 || "");
// 데이터 바인딩
$("#executor").val(data.estimate.EXECUTOR || "");
// 데이터 로드 중 플래그 설정 (수신인 자동 로드 방지)
window.isLoadingData = true;
// 수신처 설정
var recipientValue = data.estimate.RECIPIENT || "";
$("#recipient").val(recipientValue).trigger('change');
// 플래그 해제
setTimeout(function() {
window.isLoadingData = false;
}, 100);
$("#estimate_no").val(data.estimate.ESTIMATE_NO || "");
$("#contact_person").val(data.estimate.CONTACT_PERSON || "");
$("#greeting_text").val(data.estimate.GREETING_TEXT || "견적을 요청해 주셔서 대단히 감사합니다.\n하기와 같이 견적서를 제출합니다.");
// 담당자/연락처는 저장된 값이 있을 때만 덮어씀
var managerName = data.estimate.MANAGER_NAME || "";
var managerContact = data.estimate.MANAGER_CONTACT || "";
if(managerName && managerName !== "" && managerName !== "영업부") {
$("#manager_name").val(managerName);
}
if(managerContact && managerContact !== "") {
$("#manager_contact").val(managerContact);
}
// 품목 데이터 로드
if(data.items && data.items.length > 0) {
// 기존 행 초기화 후 데이터 추가
var itemsHtml = "";
for(var i = 0; i < data.items.length; i++) {
var item = data.items[i];
itemsHtml += '<tr>';
itemsHtml += '<td>' + (i + 1) + '</td>';
itemsHtml += '<td class="text-left editable"><input type="text" class="item-desc" value="' + (item.DESCRIPTION || '') + '"></td>';
itemsHtml += '<td class="text-left editable"><textarea class="item-spec">' + (item.SPECIFICATION || '') + '</textarea></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-qty" value="' + (item.QUANTITY || '') + '"></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-unit" value="' + (item.UNIT || 'EA') + '"></td>';
itemsHtml += '<td class="text-right editable"><input type="text" class="item-price" value="' + (item.UNIT_PRICE ? addComma(item.UNIT_PRICE) : '') + '"></td>';
itemsHtml += '<td class="text-right editable"><input type="text" class="item-amount" value="' + (item.AMOUNT ? addComma(item.AMOUNT) : '₩0') + '" readonly></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-note" value="' + (item.NOTE || '') + '"></td>';
itemsHtml += '</tr>';
var item = data.items[i];
var itemId = 'loaded_item_' + i;
itemsHtml += '<tr id="' + itemId + '">';
itemsHtml += '<td>' + (i + 1) + '</td>';
itemsHtml += '<td class="text-left editable">';
itemsHtml += '<select class="item-desc-select" style="width:100%;">';
itemsHtml += '<option value="" selected>' + (item.DESCRIPTION || '') + '</option>';
itemsHtml += '</select>';
itemsHtml += '<input type="hidden" class="item-desc" value="' + (item.DESCRIPTION || '') + '">';
itemsHtml += '<input type="hidden" class="item-part-objid" value="' + (item.PART_OBJID || item.part_objid || '') + '">';
itemsHtml += '</td>';
itemsHtml += '<td class="text-left editable"><textarea class="item-spec">' + (item.SPECIFICATION || '') + '</textarea></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-qty" value="' + (item.QUANTITY || '') + '"></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-unit" value="' + (item.UNIT || 'EA') + '"></td>';
itemsHtml += '<td class="text-right editable"><input type="text" class="item-price" value="' + (item.UNIT_PRICE ? addComma(item.UNIT_PRICE) : '') + '"></td>';
itemsHtml += '<td class="text-right editable"><input type="text" class="item-amount" value="' + (item.AMOUNT ? addComma(item.AMOUNT) : '') + '" readonly></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-note" value="' + (item.NOTE || '') + '"></td>';
itemsHtml += '</tr>';
}
// 계 행 추가
@@ -441,8 +692,8 @@ function fn_loadData() {
itemsHtml += '<td style="background-color: #f0f0f0;"></td>';
itemsHtml += '</tr>';
// 원화환산 공급가액 행 추가
itemsHtml += '<tr class="total-krw-row">';
// 원화환산 공급가액 행 추가 (숨김)
itemsHtml += '<tr class="total-krw-row" style="display: none;">';
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>';
@@ -456,15 +707,58 @@ function fn_loadData() {
itemsHtml += '</td>';
itemsHtml += '</tr>';
$("#itemsTableBody").html(itemsHtml);
$("#itemsTableBody").html(itemsHtml);
// 로드된 품목의 셀렉트박스 초기화 및 데이터 설정
for(var i = 0; i < data.items.length; i++) {
var item = data.items[i];
var itemId = 'loaded_item_' + i;
var partObjId = item.PART_OBJID || item.part_objid || '';
// 비고 로드 (테이블 생성 직후)
$("#note_remarks").val(data.estimate.NOTE_REMARKS || "");
// PART_OBJID가 있으면 해당 품목을 셀렉트박스에 설정
if(partObjId) {
// AJAX로 품목 정보 조회하여 셀렉트박스에 옵션 추가
$.ajax({
url: '/contractMgmt/searchPartList.do',
type: 'POST',
data: { partObjId: partObjId },
dataType: 'json',
async: false, // 동기 처리
success: function(partData) {
if(partData && partData.length > 0) {
var part = partData[0];
var objId = part.OBJID || part.objid || part.objId;
var partName = part.PART_NAME || part.part_name || part.partName;
var spec = part.SPEC || part.spec || '';
// 옵션 생성 및 추가 (selected 상태로)
var newOption = new Option(partName, objId, true, true);
$("#" + itemId + " .item-desc-select").append(newOption);
// hidden 필드 업데이트
$("#" + itemId + " .item-desc").val(partName);
$("#" + itemId + " .item-part-objid").val(objId);
// 규격이 있으면 자동 입력
if(spec) {
$("#" + itemId + " .item-spec").val(spec);
}
}
}
});
}
// 합계 계산
fn_calculateTotal();
// 셀렉트박스 초기화 (옵션 추가 후)
fn_initItemDescSelect(itemId);
}
// 비고 로드 (테이블 생성 직후)
$("#note_remarks").val(data.estimate.NOTE_REMARKS || "");
// 합계 계산
fn_calculateTotal();
}
// 하단 비고 로드
$("#note1").val(data.estimate.NOTE1 || "1. 견적유효기간: 일");
$("#note2").val(data.estimate.NOTE2 || "2. 납품기간: 발주 후 1주 이내");
@@ -500,19 +794,22 @@ 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";
// 환율 정보 저장 (소문자 우선)
var exchangeRate = template.exchange_rate || template.EXCHANGE_RATE || template.exchangeRate || "1";
var currencyName = template.contract_currency_name || template.CONTRACT_CURRENCY_NAME || template.contractCurrencyName || "KRW";
g_exchangeRate = parseFloat(exchangeRate);
g_currencyName = currencyName;
// 결재상태 저장
g_apprStatus = template.APPR_STATUS || template.appr_status || template.apprStatus || "작성중";
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 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 || "";
@@ -520,14 +817,31 @@ function fn_loadTemplateData(templateObjId){
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);
// 기본 정보 채우기
$("#executor").val(executor);
// 데이터 로드 중 플래그 설정 (수신인 자동 로드 방지)
window.isLoadingData = true;
// 수신처 설정
$("#recipient").val(recipient).trigger('change');
// 플래그 해제
setTimeout(function() {
window.isLoadingData = false;
}, 100);
$("#estimate_no").val(estimateNo);
$("#contact_person").val(contactPerson);
$("#greeting_text").val(greetingText);
$("#manager_name").val(managerName);
$("#manager_contact").val(managerContact);
// 담당자/연락처는 저장된 값이 있을 때만 덮어씀
if(managerName && managerName !== "" && managerName !== "영업부") {
$("#manager_name").val(managerName);
}
if(managerContact && managerContact !== "") {
$("#manager_contact").val(managerContact);
}
// 하단 비고 로드
$("#note1").val(note1);
@@ -538,55 +852,111 @@ function fn_loadTemplateData(templateObjId){
// 테이블 내 비고는 나중에 설정 (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){
var description = item.DESCRIPTION || item.description || '';
var specification = item.SPECIFICATION || item.specification || '';
var quantity = item.QUANTITY || item.quantity || '';
var unit = item.UNIT || item.unit || '';
var unitPrice = item.UNIT_PRICE || item.unit_price || item.unitPrice || '';
var amount = item.AMOUNT || item.amount || '';
var note = item.NOTE || item.note || '';
// 단가와 금액에 콤마 추가
var unitPriceFormatted = unitPrice ? addComma(unitPrice) : '';
var amountFormatted = amount ? addComma(amount) : '₩0';
var row = $("<tr>");
row.append('<td>' + (idx + 1) + '</td>');
row.append('<td class="text-left editable"><input type="text" class="item-desc" value="' + description + '"></td>');
row.append('<td class="text-left editable"><textarea class="item-spec">' + specification + '</textarea></td>');
row.append('<td class="editable"><input type="text" class="item-qty" value="' + quantity + '"></td>');
row.append('<td class="editable"><input type="text" class="item-unit" value="' + unit + '"></td>');
row.append('<td class="text-right editable"><input type="text" class="item-price" value="' + unitPriceFormatted + '"></td>');
row.append('<td class="text-right editable"><input type="text" class="item-amount" value="' + amountFormatted + '" readonly></td>');
row.append('<td class="editable"><input type="text" class="item-note" value="' + note + '"></td>');
$("#itemsTableBody").append(row);
});
// 품목 데이터 채우기
if(data.items && data.items.length > 0){
$("#itemsTableBody").empty();
// 품목 HTML 생성
var itemsHtml = "";
for(var i = 0; i < data.items.length; i++) {
var item = data.items[i];
var itemId = 'template_item_' + i;
var description = item.DESCRIPTION || item.description || '';
var specification = item.SPECIFICATION || item.specification || '';
var quantity = item.QUANTITY || item.quantity || '';
var unit = item.UNIT || item.unit || '';
var unitPrice = item.UNIT_PRICE || item.unit_price || item.unitPrice || '';
var amount = item.AMOUNT || item.amount || '';
var note = item.NOTE || item.note || '';
var partObjId = item.PART_OBJID || item.part_objid || '';
// 계 행 추가
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 unitPriceFormatted = unitPrice ? addComma(unitPrice) : '';
var amountFormatted = amount ? addComma(amount) : '';
// 원화환산 공급가액 행 추가
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);
itemsHtml += '<tr id="' + itemId + '">';
itemsHtml += '<td>' + (i + 1) + '</td>';
itemsHtml += '<td class="text-left editable">';
itemsHtml += '<select class="item-desc-select" style="width:100%;"></select>';
itemsHtml += '<input type="hidden" class="item-desc" value="' + description + '">';
itemsHtml += '<input type="hidden" class="item-part-objid" value="' + partObjId + '">';
itemsHtml += '</td>';
itemsHtml += '<td class="text-left editable"><textarea class="item-spec">' + specification + '</textarea></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-qty" value="' + quantity + '"></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-unit" value="' + unit + '"></td>';
itemsHtml += '<td class="text-right editable"><input type="text" class="item-price" value="' + unitPriceFormatted + '"></td>';
itemsHtml += '<td class="text-right editable"><input type="text" class="item-amount" value="' + amountFormatted + '" readonly></td>';
itemsHtml += '<td class="editable"><input type="text" class="item-note" value="' + note + '"></td>';
itemsHtml += '</tr>';
}
// 계 행 추가
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" style="display: none;">';
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;">&lt;비고&gt;</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>';
// HTML 삽입
$("#itemsTableBody").html(itemsHtml);
// 셀렉트박스 초기화 및 데이터 설정
for(var i = 0; i < data.items.length; i++) {
var item = data.items[i];
var itemId = 'template_item_' + i;
var partObjId = item.PART_OBJID || item.part_objid || '';
// 비고 행 추가
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;">&lt;비고&gt;</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);
// PART_OBJID가 있으면 해당 품목을 셀렉트박스에 설정
if(partObjId) {
// AJAX로 품목 정보 조회하여 셀렉트박스에 옵션 추가
$.ajax({
url: '/contractMgmt/searchPartList.do',
type: 'POST',
data: { partObjId: partObjId },
dataType: 'json',
async: false, // 동기 처리
success: function(partData) {
if(partData && partData.length > 0) {
var part = partData[0];
var objId = part.OBJID || part.objid || part.objId;
var partName = part.PART_NAME || part.part_name || part.partName;
var spec = part.SPEC || part.spec || '';
// 옵션 생성 및 추가 (selected 상태로)
var newOption = new Option(partName, objId, true, true);
$("#" + itemId + " .item-desc-select").append(newOption);
// hidden 필드 업데이트
$("#" + itemId + " .item-desc").val(partName);
$("#" + itemId + " .item-part-objid").val(objId);
// 규격이 있으면 자동 입력 (기존 값이 없을 때만)
if(spec && !$("#" + itemId + " .item-spec").val()) {
$("#" + itemId + " .item-spec").val(spec);
}
}
}
});
}
// 셀렉트박스 초기화 (옵션 추가 후)
fn_initItemDescSelect(itemId);
}
// 테이블 내 비고 값 설정 (textarea 생성 직후)
$("#note_remarks").val(noteRemarks);
@@ -610,6 +980,31 @@ function fn_loadTemplateData(templateObjId){
}
// 저장
// 고객사 담당자 정보 로드
function fn_loadCustomerContact(customerObjId) {
if(!customerObjId || customerObjId === "") {
$("#contact_person").val("");
return;
}
$.ajax({
url: "/contractMgmt/getCustomerContactInfo.do",
type: "POST",
data: { customerObjId: customerObjId },
dataType: "json",
success: function(data) {
if(data && data.contactPerson) {
$("#contact_person").val(data.contactPerson + " 귀하");
} else {
$("#contact_person").val("구매 담당자님 귀하");
}
},
error: function() {
$("#contact_person").val("구매 담당자님 귀하");
}
});
}
function fn_save() {
var items = [];
// 계 행, 원화환산 행, 비고 행 제외하고 품목 행만 저장
@@ -621,6 +1016,7 @@ function fn_save() {
items.push({
seq: idx + 1,
part_objid: row.find(".item-part-objid").val() || "", // part_objid 추가
description: row.find(".item-desc").val() || "",
specification: row.find(".item-spec").val() || "",
quantity: quantity.replace(/,/g, ""), // 콤마 제거
@@ -716,37 +1112,40 @@ function fn_save() {
<col width="*" />
<col width="300px" />
</colgroup>
<tr>
<td class="label">시행일자</td>
<td class="editable">
<input type="text" id="executor" value="">
</td>
<td rowspan="4" style="text-align: center; border: none; vertical-align: middle; padding: 0;">
<div style="width: 100%; text-align: center; margin-bottom: 5px;">
<img src="/images/company_stamp.png" alt="회사 도장" style="width: 100%; height: auto;"
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
<div class="company-stamp" style="display: none; width: 100%; height: 250px;">
<div class="company-stamp-text">㈊알피에스<br>RPS CO., LTD<br>대표이사이동준</div>
</div>
<tr>
<td class="label">시행일자</td>
<td class="editable">
<input type="text" id="executor" class="date_icon" value="" style="width: 150px;">
</td>
<td rowspan="4" style="text-align: center; border: none; vertical-align: middle; padding: 0;">
<div style="width: 100%; text-align: center; margin-bottom: 5px;">
<img src="/images/company_stamp.png" alt="회사 도장" style="width: 100%; height: auto;"
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
<div class="company-stamp" style="display: none; width: 100%; height: 250px;">
<div class="company-stamp-text">㈊알피에스<br>RPS CO., LTD<br>대표이사이동준</div>
</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>
<td class="label">수신처</td>
<td class="editable">
<input type="text" id="recipient" value="">
</td>
</tr>
<tr>
<td class="label">수신인</td>
<td class="editable">
<input type="text" id="contact_person" value="구매 담당자님 귀하">
</td>
</tr>
<div style="text-align: left; font-size: 9pt; line-height: 1.8; padding: 0 5px;">
담당자 : <input type="text" id="manager_name" value="" readonly style="width: 120px; border: none; border-bottom: 1px solid #ddd; font-size: 9pt; padding: 2px; background-color: #f5f5f5;"><br>
연락처 : <input type="text" id="manager_contact" value="" readonly style="width: 120px; border: none; border-bottom: 1px solid #ddd; font-size: 9pt; padding: 2px; background-color: #f5f5f5;">
</div>
</td>
</tr>
<tr>
<td class="label">수신처</td>
<td class="editable">
<select id="recipient" style="width: 100%; border: none; font-size: 9pt; padding: 2px;">
<option value="">고객사 선택</option>
${code_map.customer_cd}
</select>
</td>
</tr>
<tr>
<td class="label">수신인</td>
<td class="editable">
<input type="text" id="contact_person" value="구매 담당자님 귀하" readonly style="background-color: #f5f5f5;">
</td>
</tr>
<tr>
<td class="label">견적번호</td>
<td class="editable">
@@ -780,35 +1179,43 @@ function fn_save() {
<th class="col-note">비고</th>
</tr>
</thead>
<tbody id="itemsTableBody">
<tr>
<td>1</td>
<td class="text-left editable"><input type="text" class="item-desc" value=""></td>
<td class="text-left editable"><textarea class="item-spec"></textarea></td>
<td class="editable"><input type="text" class="item-qty" value=""></td>
<td class="editable"><input type="text" class="item-unit" value="EA"></td>
<td class="text-right editable"><input type="text" class="item-price" value=""></td>
<td class="text-right editable"><input type="text" class="item-amount" value="₩0" readonly></td>
<td class="editable"><input type="text" class="item-note" value=""></td>
</tr>
<tr>
<td>2</td>
<td class="text-left editable"><input type="text" class="item-desc" value=""></td>
<td class="text-left editable"><textarea class="item-spec"></textarea></td>
<td class="editable"><input type="text" class="item-qty" value=""></td>
<td class="editable"><input type="text" class="item-unit" value="EA"></td>
<td class="text-right editable"><input type="text" class="item-price" value=""></td>
<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>
<tbody id="itemsTableBody">
<tr id="default_item_1">
<td>1</td>
<td class="text-left editable">
<select class="item-desc-select" style="width:100%;"></select>
<input type="hidden" class="item-desc" value="">
<input type="hidden" class="item-part-objid" value="">
</td>
<td class="text-left editable"><textarea class="item-spec"></textarea></td>
<td class="editable"><input type="text" class="item-qty" value=""></td>
<td class="editable"><input type="text" class="item-unit" value="EA"></td>
<td class="text-right editable"><input type="text" class="item-price" value=""></td>
<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 id="default_item_2">
<td>2</td>
<td class="text-left editable">
<select class="item-desc-select" style="width:100%;"></select>
<input type="hidden" class="item-desc" value="">
<input type="hidden" class="item-part-objid" value="">
</td>
<td class="text-left editable"><textarea class="item-spec"></textarea></td>
<td class="editable"><input type="text" class="item-qty" value=""></td>
<td class="editable"><input type="text" class="item-unit" value="EA"></td>
<td class="text-right editable"><input type="text" class="item-price" value=""></td>
<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 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">
<!-- 원화환산 공급가액 행 (숨김) -->
<tr class="total-krw-row" style="display: none;">
<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>
@@ -840,10 +1247,10 @@ function fn_save() {
<!-- 버튼 영역 -->
<div class="btn-area no-print">
<input type="button" value="행 추가" id="btnAddRow" class="plm_btns">
<input type="button" value="인쇄" id="btnPrint" class="plm_btns">
<input type="button" value="저장" id="btnSave" class="plm_btns">
<input type="button" value="닫기" id="btnClose" class="plm_btns">
<button type="button" id="btnAddRow" class="plm_btns">행 추가</button>
<button type="button" id="btnPrint" class="plm_btns">인쇄</button>
<button type="button" id="btnSave" class="plm_btns">저장</button>
<button type="button" id="btnClose" class="plm_btns">닫기</button>
</div>
</body>
</html>

View File

@@ -1698,6 +1698,7 @@ public class ContractMgmtController {
String target_project_no ="";//대상프로젝트번호
String mechanical_type ="";//기계형식
String overhaul_order ="";//오버홀차수
String return_reason_cd ="";//반납사유
Map info = null;
List<Map<String, Object>> itemList = new ArrayList<Map<String, Object>>();
@@ -1727,7 +1728,7 @@ public class ContractMgmtController {
target_project_no = CommonUtils.nullToEmpty((String)info.get("TARGET_PROJECT_NO"));
mechanical_type = CommonUtils.nullToEmpty((String)info.get("MECHANICAL_TYPE"));
overhaul_order = CommonUtils.nullToEmpty((String)info.get("OVERHAUL_ORDER"));
return_reason_cd = CommonUtils.nullToEmpty((String)info.get("RETURN_REASON_CD"));
// 품목 목록 조회
itemList = contractMgmtService.getContractItemList(objId);
}
@@ -1794,7 +1795,8 @@ public class ContractMgmtController {
code_map.put("project_no",commonService.bizMakeOptionList("", target_project_no,"common.getCusProjectNoList"));
//기계형식
code_map.put("mechanical_type", commonService.bizMakeOptionList("", mechanical_type,"common.getMechanicalTypeList"));
//반납사유
code_map.put("return_reason_cd", commonService.bizMakeOptionList("0001810", return_reason_cd, "common.getCodeselect"));
// 품번 목록은 AJAX로 검색하므로 제거
@@ -1858,6 +1860,7 @@ public class ContractMgmtController {
try{
Map estimate = null;
List<Map> items = new ArrayList<Map>();
Map<String, String> code_map = new HashMap<String, String>();
// templateObjId가 있으면 기존 견적서 조회 (견적현황에서 클릭한 경우)
if(!"".equals(templateObjId) && !"-1".equals(templateObjId)){
@@ -1871,8 +1874,16 @@ public class ContractMgmtController {
items = contractMgmtService.getEstimateTemplateItems(paramMap);
}
// 고객사 코드맵 추가
String customer_cd = "";
if(estimate != null && estimate.get("CUSTOMER_OBJID") != null) {
customer_cd = CommonUtils.nullToEmpty((String)estimate.get("CUSTOMER_OBJID"));
}
code_map.put("customer_cd", commonService.bizMakeOptionList("", customer_cd, "common.getsupplyselect"));
request.setAttribute("estimate", estimate);
request.setAttribute("items", items);
request.setAttribute("code_map", code_map);
} catch (Exception e) {
e.printStackTrace();
@@ -1881,6 +1892,49 @@ public class ContractMgmtController {
return "/contractMgmt/estimateTemplate1";
}
/**
* 고객사 담당자 정보 조회 (AJAX)
*/
@ResponseBody
@RequestMapping(value="/contractMgmt/getCustomerContactInfo.do", method=RequestMethod.POST)
public Map getCustomerContactInfo(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
Map resultMap = new HashMap();
try {
String customerObjId = CommonUtils.checkNull(paramMap.get("customerObjId"));
if(!"".equals(customerObjId)) {
// 고객사 담당자 정보 조회
Map customerInfo = contractMgmtService.getCustomerContactInfo(paramMap);
if(customerInfo != null) {
// 소문자 우선 시도 (MyBatis가 소문자로 변환)
String contactPerson = CommonUtils.checkNull(customerInfo.get("contact_person"));
if("".equals(contactPerson)) {
contactPerson = CommonUtils.checkNull(customerInfo.get("CONTACT_PERSON"));
}
if(!"".equals(contactPerson)) {
resultMap.put("contactPerson", contactPerson);
resultMap.put("result", "success");
} else {
resultMap.put("result", "no_contact");
}
} else {
resultMap.put("result", "no_data");
}
} else {
resultMap.put("result", "no_customer");
}
} catch (Exception e) {
e.printStackTrace();
resultMap.put("result", "error");
}
return resultMap;
}
/**
* 견적서 양식2 (장비 견적서) 팝업
* @param session

View File

@@ -574,7 +574,7 @@
AND DUE_DATE != ''
) AS OTHER_DUE_DATE_COUNT
,(
SELECT RETURN_REASON
SELECT CODE_NAME(RETURN_REASON)
FROM CONTRACT_ITEM
WHERE CONTRACT_OBJID = T.OBJID
AND STATUS = 'ACTIVE'
@@ -942,9 +942,7 @@
,CONTRACT_DEL_DATE
,CONTRACT_COMPANY
,CONTRACT_DATE
,PO_NO
,MANUFACTURE_PLANT
,CONTRACT_RESULT
,PROJECT_NAME
,SPEC_USER_ID
,SPEC_PLAN_DATE
@@ -968,12 +966,7 @@
,QUANTITY
,CUSTOMER_REQUEST
,EXCHANGE_RATE
,ORDER_DATE
,ORDER_UNIT_PRICE
,ORDER_SUPPLY_PRICE
,ORDER_VAT
,ORDER_TOTAL_AMOUNT
)
)
VALUES
(
#{objId}
@@ -1009,9 +1002,7 @@
,#{contract_del_date}
,#{contract_company}
,#{contract_date}
,#{po_no}
,#{manufacture_plant}
,#{contract_result}
,#{project_name}
,#{spec_user_id}
,#{spec_plan_date}
@@ -1035,12 +1026,7 @@
,#{quantity}
,#{customer_request}
,#{exchange_rate}
,#{order_date}
,#{unit_price}
,#{supply_price}
,#{vat}
,#{total_amount}
)
)
ON CONFLICT (OBJID) DO
UPDATE
SET
@@ -1073,11 +1059,9 @@
,CONTRACT_DEL_DATE = #{contract_del_date}
,CONTRACT_COMPANY = #{contract_company}
,CONTRACT_DATE = #{contract_date}
,PO_NO = #{po_no}
,MANUFACTURE_PLANT = #{manufacture_plant}
,CONTRACT_RESULT = #{contract_result}
,PROJECT_NAME = #{project_name}
,SPEC_USER_ID = #{spec_user_id}
,SPEC_USER_ID = #{spec_user_id}
,SPEC_PLAN_DATE = #{spec_plan_date}
,SPEC_COMP_DATE = #{spec_comp_date}
,SPEC_RESULT_CD = #{spec_result_cd}
@@ -1098,12 +1082,7 @@
,SERIAL_NO = #{serial_no}
,QUANTITY = #{quantity}
,CUSTOMER_REQUEST = #{customer_request}
,EXCHANGE_RATE = #{exchange_rate}
,ORDER_DATE = #{order_date}
,ORDER_UNIT_PRICE = #{unit_price}
,ORDER_SUPPLY_PRICE = #{supply_price}
,ORDER_VAT = #{vat}
,ORDER_TOTAL_AMOUNT = #{total_amount}
,EXCHANGE_RATE = #{exchange_rate}
</update>
<update id="saveContractMgmtInfo_old" parameterType="map">
@@ -3979,6 +3958,7 @@ ORDER BY ASM.SUPPLY_NAME
TEMPLATE_OBJID,
SEQ,
CATEGORY,
PART_OBJID,
DESCRIPTION,
SPECIFICATION,
QUANTITY,
@@ -4001,6 +3981,7 @@ ORDER BY ASM.SUPPLY_NAME
TEMPLATE_OBJID,
SEQ,
CATEGORY,
PART_OBJID,
DESCRIPTION,
SPECIFICATION,
QUANTITY,
@@ -4115,6 +4096,7 @@ WHERE
TEMPLATE_OBJID,
SEQ,
CATEGORY,
PART_OBJID,
DESCRIPTION,
SPECIFICATION,
QUANTITY,
@@ -4128,6 +4110,7 @@ WHERE
#{template_objid},
(item->>'seq')::INTEGER,
item->>'category',
item->>'part_objid',
item->>'description',
item->>'specification',
item->>'quantity',
@@ -4701,4 +4684,14 @@ WHERE
WHERE ITEM_OBJID = #{itemObjId}
</update>
<!-- 고객사 담당자 정보 조회 -->
<select id="getCustomerContactInfo" parameterType="map" resultType="map">
SELECT
REG_ID AS CONTACT_PERSON,
SUPPLY_TEL_NO AS CELL_PHONE,
EMAIL
FROM SUPPLY_MNG
WHERE OBJID = #{customerObjId}::NUMERIC
</select>
</mapper>

View File

@@ -1215,6 +1215,27 @@ public class ContractMgmtService {
return resultMap;
}
/**
* 고객사 담당자 정보 조회
* @param paramMap
* @return
*/
public Map getCustomerContactInfo(Map paramMap){
Map resultMap = new HashMap();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
resultMap = (Map) sqlSession.selectOne("contractMgmt.getCustomerContactInfo", paramMap);
} catch(Exception e){
e.printStackTrace();
} finally {
if(sqlSession != null) sqlSession.close();
}
return resultMap;
}
/**
* 견적서 템플릿 기본 정보 조회
* @param paramMap
@@ -1773,7 +1794,7 @@ 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"));
@@ -1782,23 +1803,28 @@ private String makeEstimateMailContents(Map contractInfo, Map estimateTemplate,
totalAmountStr = String.format("%,d", totalAmount);
}
// 통화 기호 가져오기
String currencyName = CommonUtils.checkNull(estimateTemplate.get("contract_currency_name"));
if("".equals(currencyName)) currencyName = CommonUtils.checkNull(estimateTemplate.get("CONTRACT_CURRENCY_NAME"));
String currencySymbol = ""; // 기본값
if(currencyName.indexOf("달러") >= 0 || "USD".equals(currencyName)) {
currencySymbol = "$";
} else if(currencyName.indexOf("유로") >= 0 || "EUR".equals(currencyName)) {
currencySymbol = "";
} else if(currencyName.indexOf("") >= 0 || "JPY".equals(currencyName)) {
currencySymbol = "¥";
} else if(currencyName.indexOf("위안") >= 0 || "CNY".equals(currencyName)) {
currencySymbol = "¥";
}
contents.append("<tr style='background-color:#f0f0f0; font-weight:bold;'>");
contents.append("<td colspan='6' class='text-center'>계</td>");
contents.append("<td class='text-right'>" + totalAmountStr + "</td>");
contents.append("<td class='text-right'>" + currencySymbol + 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"));