V20260210 #189
@@ -41,11 +41,16 @@
|
||||
section.business_popup_min_width {
|
||||
padding: 0 !important;
|
||||
margin: 0 auto !important;
|
||||
width: calc(100% - 16px) !important;
|
||||
max-width: none !important;
|
||||
width: calc(100% - 8px) !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
#EntirePopupFormWrap {
|
||||
width: 100% !important;
|
||||
margin: 5px 0 0 0 !important;
|
||||
padding: 0 5px 10px 5px !important;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* ===== 품목 그리드 컬럼 리사이즈 ===== */
|
||||
@@ -483,52 +488,52 @@
|
||||
|
||||
// S/N
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_serial_no[]" class="item-serial-no" placeholder="클릭하여 S/N 추가" readonly style="width:95%; padding:5px; cursor:pointer; background-color:#f8f9fa;" onclick="fn_openItemSnPopup(\'' + itemId + '\')" />';
|
||||
html += '<input type="text" name="item_serial_no[]" class="item-serial-no" placeholder="클릭하여 S/N 추가" readonly style="width:100%; padding:5px; cursor:pointer; background-color:#f8f9fa;" onclick="fn_openItemSnPopup(\'' + itemId + '\')" />';
|
||||
html += '<input type="hidden" name="item_serial_no_list[]" id="' + itemId + '_sn_list" value="" />';
|
||||
html += '</td>';
|
||||
|
||||
// 요청납기
|
||||
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;" />';
|
||||
html += '<input type="text" name="item_due_date[]" class="item-due-date date_icon" style="width:100%; padding:5px;" />';
|
||||
html += '</td>';
|
||||
|
||||
// 고객요청사항
|
||||
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 += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:100%; 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 += '<select name="item_return_reason[]" class="item-return-reason select2" style="width:100%;"></select>';
|
||||
html += '</td>';
|
||||
|
||||
// 수주수량 (Machine이고 프로젝트가 있으면 readonly)
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
if(isMachine && hasProject) {
|
||||
html += '<input type="text" name="item_order_quantity[]" class="item-order-quantity" style="width:90%; padding:5px; text-align:right; background:#f5f5f5;" required numberOnly readonly title="Machine 제품은 프로젝트 생성 후 수량 변경이 불가능합니다." />';
|
||||
html += '<input type="text" name="item_order_quantity[]" class="item-order-quantity" style="width:100%; padding:5px; text-align:right; background:#f5f5f5;" required numberOnly readonly title="Machine 제품은 프로젝트 생성 후 수량 변경이 불가능합니다." />';
|
||||
} else {
|
||||
html += '<input type="text" name="item_order_quantity[]" class="item-order-quantity" style="width:90%; padding:5px; text-align:right;" required numberOnly />';
|
||||
html += '<input type="text" name="item_order_quantity[]" class="item-order-quantity" style="width:100%; padding:5px; text-align:right;" required numberOnly />';
|
||||
}
|
||||
html += '</td>';
|
||||
|
||||
// 수주단가
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_order_unit_price[]" class="item-order-unit-price" style="width:90%; padding:5px; text-align:right;" numberOnly />';
|
||||
html += '<input type="text" name="item_order_unit_price[]" class="item-order-unit-price" style="width:100%; padding:5px; text-align:right;" numberOnly />';
|
||||
html += '</td>';
|
||||
|
||||
// 수주공급가액 (자동계산 + 수정가능)
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_order_supply_price[]" class="item-order-supply-price" style="width:90%; padding:5px; text-align:right;" numberOnly />';
|
||||
html += '<input type="text" name="item_order_supply_price[]" class="item-order-supply-price" style="width:100%; padding:5px; text-align:right;" numberOnly />';
|
||||
html += '</td>';
|
||||
|
||||
// 수주부가세 (자동계산 + 수정가능)
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_order_vat[]" class="item-order-vat" style="width:90%; padding:5px; text-align:right;" numberOnly />';
|
||||
html += '<input type="text" name="item_order_vat[]" class="item-order-vat" style="width:100%; padding:5px; text-align:right;" numberOnly />';
|
||||
html += '</td>';
|
||||
|
||||
// 수주총액 (자동계산 + 수정가능)
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_order_total_amount[]" class="item-order-total-amount" style="width:90%; padding:5px; text-align:right;" numberOnly />';
|
||||
html += '<input type="text" name="item_order_total_amount[]" class="item-order-total-amount" style="width:100%; padding:5px; text-align:right;" numberOnly />';
|
||||
html += '</td>';
|
||||
|
||||
// 삭제 버튼
|
||||
@@ -718,46 +723,39 @@
|
||||
var returnReason = "<%= CommonUtils.checkNull(item.get("RETURN_REASON")) %>";
|
||||
var savedProduct = "<%= CommonUtils.checkNull(item.get("PRODUCT")) %>";
|
||||
|
||||
// 제품구분 드롭다운
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<select name="item_product[]" id="PRODUCT_' + itemId + '" class="item-product select2" style="width:100%;" required>';
|
||||
html += '<option value="">선택</option>';
|
||||
html += '</select>';
|
||||
html += '</td>';
|
||||
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_serial_no[]" class="item-serial-no" placeholder="클릭하여 S/N 추가" readonly style="width:95%; padding:5px; cursor:pointer; background-color:#f8f9fa;" onclick="fn_openItemSnPopup(\'' + itemId + '\')" value="' + serialNos + '" />';
|
||||
html += '<input type="text" name="item_serial_no[]" class="item-serial-no" placeholder="클릭하여 S/N 추가" readonly style="width:100%; padding:5px; cursor:pointer; background-color:#f8f9fa;" onclick="fn_openItemSnPopup(\'' + itemId + '\')" value="' + serialNos + '" />';
|
||||
html += '<input type="hidden" name="item_serial_no_list[]" id="' + itemId + '_sn_list" value="" />';
|
||||
html += '</td>';
|
||||
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 += '<input type="text" name="item_due_date[]" class="item-due-date date_icon" style="width:100%; padding:5px;" value="' + dueDate + '" />';
|
||||
html += '</td>';
|
||||
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 += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:100%; 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 += '<select name="item_return_reason[]" class="item-return-reason select2" style="width:100%;"></select>';
|
||||
html += '</td>';
|
||||
|
||||
// 수주 정보 (Machine이고 프로젝트가 있으면 수량 readonly)
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
if(isMachine && hasProject) {
|
||||
html += '<input type="text" name="item_order_quantity[]" class="item-order-quantity" style="width:90%; padding:5px; text-align:right; background:#f5f5f5;" required numberOnly readonly title="Machine 제품은 프로젝트 생성 후 수량 변경이 불가능합니다." value="' + (orderQuantity ? formatInteger(orderQuantity) : '') + '" />';
|
||||
html += '<input type="text" name="item_order_quantity[]" class="item-order-quantity" style="width:100%; padding:5px; text-align:right; background:#f5f5f5;" required numberOnly readonly title="Machine 제품은 프로젝트 생성 후 수량 변경이 불가능합니다." value="' + (orderQuantity ? formatInteger(orderQuantity) : '') + '" />';
|
||||
} else {
|
||||
html += '<input type="text" name="item_order_quantity[]" class="item-order-quantity" style="width:90%; padding:5px; text-align:right;" required numberOnly value="' + (orderQuantity ? formatInteger(orderQuantity) : '') + '" />';
|
||||
html += '<input type="text" name="item_order_quantity[]" class="item-order-quantity" style="width:100%; padding:5px; text-align:right;" required numberOnly value="' + (orderQuantity ? formatInteger(orderQuantity) : '') + '" />';
|
||||
}
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_order_unit_price[]" class="item-order-unit-price" style="width:90%; padding:5px; text-align:right;" numberOnly value="' + (orderUnitPrice ? addComma(orderUnitPrice) : '') + '" />';
|
||||
html += '<input type="text" name="item_order_unit_price[]" class="item-order-unit-price" style="width:100%; padding:5px; text-align:right;" numberOnly value="' + (orderUnitPrice ? addComma(orderUnitPrice) : '') + '" />';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_order_supply_price[]" class="item-order-supply-price" style="width:90%; padding:5px; text-align:right;" numberOnly value="' + (orderSupplyPrice ? addComma(orderSupplyPrice) : '') + '" />';
|
||||
html += '<input type="text" name="item_order_supply_price[]" class="item-order-supply-price" style="width:100%; padding:5px; text-align:right;" numberOnly value="' + (orderSupplyPrice ? addComma(orderSupplyPrice) : '') + '" />';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_order_vat[]" class="item-order-vat" style="width:90%; padding:5px; text-align:right;" numberOnly value="' + (orderVat ? addComma(orderVat) : '') + '" />';
|
||||
html += '<input type="text" name="item_order_vat[]" class="item-order-vat" style="width:100%; padding:5px; text-align:right;" numberOnly value="' + (orderVat ? addComma(orderVat) : '') + '" />';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_order_total_amount[]" class="item-order-total-amount" style="width:90%; padding:5px; text-align:right;" numberOnly value="' + (orderTotalAmount ? addComma(orderTotalAmount) : '') + '" />';
|
||||
html += '<input type="text" name="item_order_total_amount[]" class="item-order-total-amount" style="width:100%; padding:5px; text-align:right;" numberOnly value="' + (orderTotalAmount ? addComma(orderTotalAmount) : '') + '" />';
|
||||
html += '</td>';
|
||||
|
||||
html += '<td style="text-align:center; padding:5px; border:1px solid #ddd;">';
|
||||
@@ -1676,13 +1674,13 @@
|
||||
<table class="pmsPopuptable" id="itemListTable">
|
||||
<colgroup>
|
||||
<col width="3%" /> <!-- 번호 -->
|
||||
<col width="8%" /> <!-- 제품구분 -->
|
||||
<col width="6%" /> <!-- 제품구분 -->
|
||||
<col width="7%" /> <!-- 품번 -->
|
||||
<col width="7%" /> <!-- 품명 -->
|
||||
<col width="10%" /> <!-- 품명 -->
|
||||
<col width="9%" /> <!-- S/N -->
|
||||
<col width="7%" /> <!-- 요청납기 -->
|
||||
<col width="11%" /> <!-- 고객요청사항 -->
|
||||
<col width="7%" /> <!-- 반납사유 -->
|
||||
<col width="6%" /> <!-- 반납사유 -->
|
||||
<col width="6%" /> <!-- 수주수량 -->
|
||||
<col width="7%" /> <!-- 수주단가 -->
|
||||
<col width="7%" /> <!-- 수주공급가액 -->
|
||||
|
||||
@@ -696,13 +696,13 @@
|
||||
html += '<input type="text" name="item_quantity[]" class="item-quantity" style="width:90%; padding:5px;" value="' + quantity + '" required numberOnly />';
|
||||
html += '</td>';
|
||||
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 += '<input type="text" name="item_due_date[]" class="item-due-date date_icon" style="width:100%; padding:5px;" value="' + dueDate + '" />';
|
||||
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="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 += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:100%; padding:5px; min-height:34px; resize:vertical; font-family:inherit; font-size:inherit;" rows="1"></textarea>';
|
||||
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>';
|
||||
@@ -1499,13 +1499,13 @@
|
||||
html += '<input type="text" name="item_quantity[]" class="item-quantity" style="width:90%; padding:5px;" required numberOnly />';
|
||||
html += '</td>';
|
||||
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;" />';
|
||||
html += '<input type="text" name="item_due_date[]" class="item-due-date date_icon" style="width:100%; padding:5px;" />';
|
||||
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="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 += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:100%; padding:5px; min-height:34px; resize:vertical; font-family:inherit; font-size:inherit;" rows="1"></textarea>';
|
||||
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>';
|
||||
@@ -2244,15 +2244,15 @@
|
||||
<div style="max-height:300px; overflow-y:auto;">
|
||||
<table class="pmsPopuptable" id="itemListTable">
|
||||
<colgroup>
|
||||
<col width="4%" /> <!-- 번호 -->
|
||||
<col width="10%" /> <!-- 제품구분 -->
|
||||
<col width="3%" /> <!-- 번호 -->
|
||||
<col width="7%" /> <!-- 제품구분 -->
|
||||
<col width="11%" /> <!-- 품번 -->
|
||||
<col width="11%" /> <!-- 품명 -->
|
||||
<col width="13%" /> <!-- S/N -->
|
||||
<col width="7%" /> <!-- 수량 -->
|
||||
<col width="17%" /> <!-- 품명 -->
|
||||
<col width="11%" /> <!-- S/N -->
|
||||
<col width="6%" /> <!-- 수량 -->
|
||||
<col width="9%" /> <!-- 요청납기 -->
|
||||
<col width="13%" /> <!-- 반납사유 -->
|
||||
<col width="17%" /> <!-- 고객요청사항 -->
|
||||
<col width="8%" /> <!-- 반납사유 -->
|
||||
<col width="18%" /> <!-- 고객요청사항 -->
|
||||
<col width="5%" /> <!-- 삭제 -->
|
||||
</colgroup>
|
||||
<thead>
|
||||
|
||||
@@ -64,6 +64,9 @@ String templateObjId = CommonUtils.checkNull(request.getParameter("templateObjId
|
||||
.no-print {
|
||||
display: none !important;
|
||||
}
|
||||
.delete-btn-cell button {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -160,13 +163,15 @@ body {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 30px;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.items-table th,
|
||||
.items-table td {
|
||||
border: 1px solid #000;
|
||||
padding: 3px 5px;
|
||||
padding: 8px 2px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
font-size: 9pt;
|
||||
line-height: 1.3;
|
||||
}
|
||||
@@ -176,14 +181,15 @@ body {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.items-table .col-no { width: 6%; }
|
||||
.items-table .col-desc { width: 20%; }
|
||||
.items-table .col-no { width: 4%; }
|
||||
.items-table .col-desc { width: 12%; }
|
||||
.items-table .col-spec { width: 22%; }
|
||||
.items-table .col-qty { width: 7%; }
|
||||
.items-table .col-unit { width: 8%; }
|
||||
.items-table .col-price { width: 11%; }
|
||||
.items-table .col-amount { width: 11%; }
|
||||
.items-table .col-note { width: 15%; }
|
||||
.items-table .col-qty { width: 4%; }
|
||||
.items-table .col-unit { width: 5%; }
|
||||
.items-table .col-price { width: 14%; }
|
||||
.items-table .col-amount { width: 15%; }
|
||||
.items-table .col-note { width: 9%; white-space: normal; word-break: break-all; }
|
||||
.items-table td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
|
||||
.items-table .text-left {
|
||||
text-align: left;
|
||||
@@ -191,6 +197,8 @@ body {
|
||||
|
||||
.items-table .text-right {
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.notes-section {
|
||||
@@ -262,6 +270,12 @@ textarea {
|
||||
width: 100%;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.item-price,
|
||||
.item-amount {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.item-amount {
|
||||
@@ -269,9 +283,12 @@ textarea {
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
min-height: 25px;
|
||||
padding: 2px;
|
||||
resize: none;
|
||||
height: 1.3em;
|
||||
min-height: auto;
|
||||
padding: 0 2px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.editable {
|
||||
@@ -373,7 +390,7 @@ $(function(){
|
||||
$(document).on("blur", ".item-price", function(){
|
||||
var val = $(this).val().replace(/,/g, "");
|
||||
if(!isNaN(val) && val !== "") {
|
||||
$(this).val(Number(val).toLocaleString(undefined, {minimumFractionDigits: 0, maximumFractionDigits: 2}));
|
||||
$(this).val(Number(val).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}));
|
||||
}
|
||||
fn_calculateTotal();
|
||||
});
|
||||
@@ -502,10 +519,16 @@ function fn_calculateTotalKRW(total) {
|
||||
$("#totalAmountKRW").text("₩" + addComma(totalKRW));
|
||||
}
|
||||
|
||||
// 금액 포맷 (소수점 2자리 + 천단위 콤마)
|
||||
// 금액 포맷 (항상 소수점 2자리, 천단위 콤마)
|
||||
function addComma(num) {
|
||||
if(num === '' || num === null || num === undefined) return '';
|
||||
return Number(num).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
|
||||
// DB에 콤마가 포함된 값이 저장된 경우를 위해 콤마 제거 후 파싱
|
||||
var n = Number(String(num).replace(/,/g, ''));
|
||||
if(isNaN(n)) return '';
|
||||
return n.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
}
|
||||
|
||||
// 통화 기호 반환
|
||||
@@ -702,7 +725,7 @@ function fn_loadContractItems(contractObjId) {
|
||||
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; text-align: center;"><button type="button" class="btn-delete-total-row" style="padding: 2px 8px; font-size: 9pt; cursor: pointer;">삭제</button></td>';
|
||||
itemsHtml += '<td class="delete-btn-cell" style="background-color: #f0f0f0; text-align: center;"><button type="button" class="btn-delete-total-row" style="padding: 2px 8px; font-size: 9pt; cursor: pointer;">삭제</button></td>';
|
||||
itemsHtml += '</tr>';
|
||||
|
||||
// 원화환산 공급가액 행 추가 (숨김)
|
||||
@@ -864,7 +887,7 @@ function fn_loadData() {
|
||||
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; text-align: center;"><button type="button" class="btn-delete-total-row" style="padding: 2px 8px; font-size: 9pt; cursor: pointer;">삭제</button></td>';
|
||||
itemsHtml += '<td class="delete-btn-cell" style="background-color: #f0f0f0; text-align: center;"><button type="button" class="btn-delete-total-row" style="padding: 2px 8px; font-size: 9pt; cursor: pointer;">삭제</button></td>';
|
||||
itemsHtml += '</tr>';
|
||||
|
||||
// 원화환산 공급가액 행 추가 (숨김)
|
||||
@@ -1082,7 +1105,7 @@ function fn_loadTemplateData(templateObjId){
|
||||
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; text-align: center;"><button type="button" class="btn-delete-total-row" style="padding: 2px 8px; font-size: 9pt; cursor: pointer;">삭제</button></td>';
|
||||
itemsHtml += '<td class="delete-btn-cell" style="background-color: #f0f0f0; text-align: center;"><button type="button" class="btn-delete-total-row" style="padding: 2px 8px; font-size: 9pt; cursor: pointer;">삭제</button></td>';
|
||||
itemsHtml += '</tr>';
|
||||
|
||||
// 원화환산 공급가액 행 추가 (숨김)
|
||||
@@ -1422,7 +1445,7 @@ function fn_save() {
|
||||
<th class="col-spec">규 격<br>SPECIFICATION</th>
|
||||
<th class="col-qty">수량<br>Q'TY</th>
|
||||
<th class="col-unit">단위<br>UNIT</th>
|
||||
<th class="col-price">단 가<br>UNIT<br>PRICE</th>
|
||||
<th class="col-price">단 가<br>UNIT PRICE</th>
|
||||
<th class="col-amount">금 액<br>AMOUNT</th>
|
||||
<th class="col-note">비고</th>
|
||||
</tr>
|
||||
@@ -1458,7 +1481,7 @@ function fn_save() {
|
||||
<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; text-align: center;"><button type="button" class="btn-delete-total-row" style="padding: 2px 8px; font-size: 9pt; cursor: pointer;">삭제</button></td>
|
||||
<td class="delete-btn-cell" style="background-color: #f0f0f0; text-align: center;"><button type="button" class="btn-delete-total-row" style="padding: 2px 8px; font-size: 9pt; cursor: pointer;">삭제</button></td>
|
||||
</tr>
|
||||
<!-- 원화환산 공급가액 행 (숨김) -->
|
||||
<tr class="total-krw-row" style="display: none;">
|
||||
@@ -1521,15 +1544,17 @@ function fn_replaceFormElementsWithText() {
|
||||
$('.estimate-container').find('input[type="text"], textarea, select').each(function(idx) {
|
||||
var $el = $(this);
|
||||
var displayText = '';
|
||||
|
||||
|
||||
if ($el.is('select')) {
|
||||
displayText = $el.find('option:selected').text() || '';
|
||||
} else {
|
||||
displayText = $el.val() || '';
|
||||
}
|
||||
|
||||
|
||||
var computedStyle = window.getComputedStyle(this);
|
||||
var elWidth = $el.outerWidth();
|
||||
// 단가/금액 컬럼이 좁아 잘릴 수 있으므로 부모 td의 내부 너비 사용
|
||||
var parentTd = $el.closest('td');
|
||||
var elWidth = parentTd.length > 0 ? parentTd.innerWidth() : $el.outerWidth();
|
||||
var span = $('<span class="pdf-temp-text"></span>');
|
||||
span.text(displayText);
|
||||
span.css({
|
||||
@@ -1604,29 +1629,31 @@ function fn_generatePdf() {
|
||||
}
|
||||
});
|
||||
|
||||
// 버튼 영역 임시 숨김
|
||||
// 버튼 영역 임시 숨김 (삭제 버튼 셀 전체 숨김으로 PDF에 노출 방지)
|
||||
$('.btn-area').hide();
|
||||
|
||||
$('.btn-delete-row').hide();
|
||||
$('.btn-delete-total-row').hide();
|
||||
|
||||
// 폼 요소를 텍스트로 변환 (html2canvas 글자 잘림 방지)
|
||||
var formBackup = fn_replaceFormElementsWithText();
|
||||
|
||||
|
||||
// PDF 생성을 위해 스타일 조정
|
||||
var container = $('.estimate-container');
|
||||
var originalBg = container.css('background');
|
||||
var originalShadow = container.css('box-shadow');
|
||||
var originalPadding = container.css('padding');
|
||||
|
||||
|
||||
// 깔끔한 PDF를 위해 배경, 그림자, 패딩 제거
|
||||
container.css({
|
||||
'background': 'white',
|
||||
'box-shadow': 'none',
|
||||
'padding': '10mm'
|
||||
});
|
||||
|
||||
|
||||
// body 배경색도 흰색으로
|
||||
var originalBodyBg = $('body').css('background-color');
|
||||
$('body').css('background-color', 'white');
|
||||
|
||||
|
||||
// 견적서 컨테이너 캡처
|
||||
html2canvas(document.querySelector('.estimate-container'), {
|
||||
scale: 2, // 적절한 해상도 (파일 크기 최적화)
|
||||
@@ -1645,6 +1672,8 @@ function fn_generatePdf() {
|
||||
fn_restoreFormElements(formBackup);
|
||||
// 버튼 영역 다시 표시
|
||||
$('.btn-area').show();
|
||||
$('.btn-delete-row').show();
|
||||
$('.btn-delete-total-row').show();
|
||||
|
||||
try {
|
||||
// Canvas를 JPEG 이미지로 변환 (PNG보다 파일 크기 작음)
|
||||
@@ -1696,6 +1725,8 @@ function fn_generatePdf() {
|
||||
}).catch(function(error) {
|
||||
fn_restoreFormElements(formBackup);
|
||||
$('.btn-area').show();
|
||||
$('.btn-delete-row').show();
|
||||
$('.btn-delete-total-row').show();
|
||||
Swal.close();
|
||||
console.error('Canvas 캡처 오류:', error);
|
||||
Swal.fire({
|
||||
@@ -1709,7 +1740,7 @@ function fn_generatePdf() {
|
||||
// PDF를 Base64로 생성하여 서버로 전송하는 함수
|
||||
function fn_generateAndUploadPdf(callback) {
|
||||
console.log('fn_generateAndUploadPdf 호출됨');
|
||||
|
||||
|
||||
// 라이브러리 로드 확인
|
||||
if(typeof html2canvas === 'undefined' || typeof jsPDF === 'undefined') {
|
||||
console.error('필요한 라이브러리가 로드되지 않았습니다.');
|
||||
@@ -1718,30 +1749,32 @@ function fn_generateAndUploadPdf(callback) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 버튼 영역 임시 숨김
|
||||
|
||||
// 버튼 영역 임시 숨김 (삭제 버튼 셀 전체 숨김으로 PDF에 노출 방지)
|
||||
$('.btn-area').hide();
|
||||
|
||||
$('.btn-delete-row').hide();
|
||||
$('.btn-delete-total-row').hide();
|
||||
|
||||
// 폼 요소를 텍스트로 변환 (html2canvas 글자 잘림 방지)
|
||||
var formBackup = fn_replaceFormElementsWithText();
|
||||
|
||||
|
||||
// PDF 생성을 위해 스타일 조정
|
||||
var container = $('.estimate-container');
|
||||
var originalBg = container.css('background');
|
||||
var originalShadow = container.css('box-shadow');
|
||||
var originalPadding = container.css('padding');
|
||||
|
||||
|
||||
// 깔끔한 PDF를 위해 배경, 그림자, 패딩 제거
|
||||
container.css({
|
||||
'background': 'white',
|
||||
'box-shadow': 'none',
|
||||
'padding': '10mm'
|
||||
});
|
||||
|
||||
|
||||
// body 배경색도 흰색으로
|
||||
var originalBodyBg = $('body').css('background-color');
|
||||
$('body').css('background-color', 'white');
|
||||
|
||||
|
||||
// 견적서 컨테이너 캡처
|
||||
html2canvas(document.querySelector('.estimate-container'), {
|
||||
scale: 2, // 적절한 해상도 (파일 크기 최적화)
|
||||
@@ -1750,7 +1783,7 @@ function fn_generateAndUploadPdf(callback) {
|
||||
backgroundColor: '#ffffff'
|
||||
}).then(function(canvas) {
|
||||
console.log('Canvas 캡처 완료');
|
||||
|
||||
|
||||
// 스타일 복원
|
||||
container.css({
|
||||
'background': originalBg,
|
||||
@@ -1758,12 +1791,14 @@ function fn_generateAndUploadPdf(callback) {
|
||||
'padding': originalPadding
|
||||
});
|
||||
$('body').css('background-color', originalBodyBg);
|
||||
|
||||
|
||||
// 폼 요소 복원
|
||||
fn_restoreFormElements(formBackup);
|
||||
|
||||
|
||||
// 버튼 영역 다시 표시
|
||||
$('.btn-area').show();
|
||||
$('.btn-delete-row').show();
|
||||
$('.btn-delete-total-row').show();
|
||||
|
||||
try {
|
||||
// Canvas를 JPEG 이미지로 변환 (PNG보다 파일 크기 작음)
|
||||
@@ -1809,6 +1844,8 @@ function fn_generateAndUploadPdf(callback) {
|
||||
}).catch(function(error) {
|
||||
fn_restoreFormElements(formBackup);
|
||||
$('.btn-area').show();
|
||||
$('.btn-delete-row').show();
|
||||
$('.btn-delete-total-row').show();
|
||||
console.error('Canvas 캡처 오류:', error);
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
|
||||
@@ -29,6 +29,9 @@ boolean isApproved = "결재완료".equals(apprStatus) || "결재중".equals(app
|
||||
.no-print {
|
||||
display: none !important;
|
||||
}
|
||||
.delete-btn-cell button {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -530,10 +533,16 @@ function fn_calculateSubtotal(tbody) {
|
||||
tbody.find(".subtotal-amount").val(addComma(total));
|
||||
}
|
||||
|
||||
// 금액 포맷 (소수점 2자리 + 천단위 콤마)
|
||||
// 금액 포맷 (항상 소수점 2자리, 천단위 콤마)
|
||||
function addComma(num) {
|
||||
if(num === '' || num === null || num === undefined) return '';
|
||||
return Number(num).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
|
||||
// DB에 콤마가 포함된 값이 저장된 경우를 위해 콤마 제거 후 파싱
|
||||
var n = Number(String(num).replace(/,/g, ''));
|
||||
if(isNaN(n)) return '';
|
||||
return n.toLocaleString(undefined, {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
}
|
||||
|
||||
// 카테고리 추가
|
||||
@@ -558,7 +567,7 @@ function fn_addCategory() {
|
||||
'<tr class="category-row">' +
|
||||
'<td rowspan="2" class="category-no">' + newCategoryNo + '</td>' +
|
||||
'<td colspan="4" contenteditable="true">' + newCategoryName + '</td>' +
|
||||
'<td style="text-align: center;">' +
|
||||
'<td class="delete-btn-cell" style="text-align: center;">' +
|
||||
'<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>' +
|
||||
'</td>' +
|
||||
'</tr>' +
|
||||
@@ -622,7 +631,7 @@ function fn_createCategoryFromData(category) {
|
||||
'<tr class="category-row">' +
|
||||
'<td rowspan="2" class="category-no">' + categoryNo + '</td>' +
|
||||
'<td colspan="4" contenteditable="true">' + categoryName + '</td>' +
|
||||
'<td style="text-align: center;">' +
|
||||
'<td class="delete-btn-cell" style="text-align: center;">' +
|
||||
'<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>' +
|
||||
'</td>' +
|
||||
'</tr>' +
|
||||
@@ -1069,9 +1078,10 @@ function fn_generateAndUploadPdf(callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 버튼 영역 임시 숨김
|
||||
// 버튼 영역 임시 숨김 (삭제 버튼 셀 전체 숨김으로 PDF에 노출 방지)
|
||||
$('.estimate-btn-area').hide();
|
||||
|
||||
$('.btn-delete-category').hide();
|
||||
|
||||
// textarea를 div로 변환 (줄바꿈 보존)
|
||||
var textareaBackup = [];
|
||||
$('textarea').each(function(index) {
|
||||
@@ -1140,7 +1150,8 @@ function fn_generateAndUploadPdf(callback) {
|
||||
|
||||
// 버튼 영역 다시 표시
|
||||
$('.estimate-btn-area').show();
|
||||
|
||||
$('.btn-delete-category').show();
|
||||
|
||||
try {
|
||||
// Canvas를 JPEG 이미지로 변환 (PNG보다 파일 크기 작음)
|
||||
var imgData = canvas.toDataURL('image/jpeg', 0.85); // 85% 품질
|
||||
@@ -1189,6 +1200,7 @@ function fn_generateAndUploadPdf(callback) {
|
||||
});
|
||||
|
||||
$('.estimate-btn-area').show();
|
||||
$('.btn-delete-category').show();
|
||||
console.error('Canvas 캡처 오류:', error);
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
@@ -1302,7 +1314,7 @@ function fn_generateAndUploadPdf(callback) {
|
||||
<tr class="category-row">
|
||||
<td rowspan="2" class="category-no">1</td>
|
||||
<td colspan="4" contenteditable="true">기구</td>
|
||||
<td style="text-align: center;">
|
||||
<td class="delete-btn-cell" style="text-align: center;">
|
||||
<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1366,7 +1378,7 @@ Z: SRG25 P급, C0
|
||||
<tr class="category-row">
|
||||
<td rowspan="2" class="category-no">2</td>
|
||||
<td colspan="4" contenteditable="true">초음파 스핀들 모듈</td>
|
||||
<td style="text-align: center;">
|
||||
<td class="delete-btn-cell" style="text-align: center;">
|
||||
<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1407,7 +1419,7 @@ Z: SRG25 P급, C0
|
||||
<tr class="category-row">
|
||||
<td rowspan="2" class="category-no">3</td>
|
||||
<td colspan="4" contenteditable="true">전장</td>
|
||||
<td style="text-align: center;">
|
||||
<td class="delete-btn-cell" style="text-align: center;">
|
||||
<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1451,7 +1463,7 @@ SIEMENS CONTROL PANEL 828D</textarea>
|
||||
<tr class="category-row">
|
||||
<td rowspan="2" class="category-no">4</td>
|
||||
<td colspan="4" contenteditable="true">UTILITY</td>
|
||||
<td style="text-align: center;">
|
||||
<td class="delete-btn-cell" style="text-align: center;">
|
||||
<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1521,7 +1533,7 @@ LUBRICATION
|
||||
<tr class="category-row">
|
||||
<td rowspan="2" class="category-no">5</td>
|
||||
<td colspan="4" contenteditable="true">Option</td>
|
||||
<td style="text-align: center;">
|
||||
<td class="delete-btn-cell" style="text-align: center;">
|
||||
<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1570,7 +1582,7 @@ NV4Blue(Renishaw)
|
||||
<tr class="category-row">
|
||||
<td rowspan="2" class="category-no">6</td>
|
||||
<td colspan="4" contenteditable="true">Set up</td>
|
||||
<td style="text-align: center;">
|
||||
<td class="delete-btn-cell" style="text-align: center;">
|
||||
<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1615,7 +1627,7 @@ NV4Blue(Renishaw)
|
||||
<tr class="category-row">
|
||||
<td rowspan="2" class="category-no">7</td>
|
||||
<td colspan="4" contenteditable="true">포장/물류</td>
|
||||
<td style="text-align: center;">
|
||||
<td class="delete-btn-cell" style="text-align: center;">
|
||||
<button type="button" class="btn-delete-category" onclick="fn_deleteCategory(this)" style="padding: 2px 8px; font-size: 10px; cursor: pointer; background-color: #dc3545; color: white; border: none; border-radius: 3px;">삭제</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -827,7 +827,7 @@ function fn_openOrderConfirmPopup(contractObjId, currentStatus){
|
||||
fn_search();
|
||||
});
|
||||
} else {
|
||||
Swal.fire("수주확정 저장 중 오류가 발생했습니다.");
|
||||
Swal.fire("수주확정 저장 중 오류가 발생했습니다.\n" + (data.message || ""));
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
|
||||
// 품목이 없으면 메시지 표시
|
||||
if($("#itemListBody tr.item-row").length == 0) {
|
||||
$("#itemListBody").html('<tr id="noItemRow"><td colspan="9" style="text-align:center; padding:30px; color:#999;">품목 추가 버튼을 클릭하여 품목을 등록하세요.</td></tr>');
|
||||
$("#itemListBody").html('<tr id="noItemRow"><td colspan="11" style="text-align:center; padding:30px; color:#999;">품목 추가 버튼을 클릭하여 품목을 등록하세요.</td></tr>');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,6 +254,12 @@
|
||||
|
||||
var html = '<tr id="' + itemId + '" class="item-row">';
|
||||
html += '<td>' + (i + 1) + '</td>';
|
||||
// 제품구분 드롭다운
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<select name="item_product[]" id="PRODUCT_' + itemId + '" class="item-product select2" style="width:100%;" required>';
|
||||
html += '<option value="">선택</option>';
|
||||
html += '</select>';
|
||||
html += '</td>';
|
||||
html += '<td><input type="text" class="item-part-no" value="' + (item.PART_NO || '') + '" readonly style="background:#f5f5f5;" /></td>';
|
||||
html += '<td><input type="text" class="item-part-name" value="' + (item.PART_NAME || '') + '" readonly style="background:#f5f5f5;" /></td>';
|
||||
html += '<td><input type="text" class="item-serial-no" value="' + serialNoDisplay + '" readonly style="background:#f5f5f5;" title="' + serialNo + '" /></td>';
|
||||
@@ -281,6 +287,11 @@
|
||||
|
||||
$("#itemListBody").append(html);
|
||||
|
||||
// 제품구분 드롭다운 초기화 (견적요청에서 저장된 값으로 세팅)
|
||||
var savedProduct = item.PRODUCT || '';
|
||||
fnc_getCodeListAppend("0000001", "PRODUCT_" + itemId, savedProduct);
|
||||
$("#PRODUCT_" + itemId).select2({ width: '100%' });
|
||||
|
||||
// 콤마 추가 (수량은 정수, 금액은 소수점 2자리)
|
||||
$("#" + itemId + " .item-quantity").val(addCommaInt(removeComma($("#" + itemId + " .item-quantity").val())));
|
||||
$("#" + itemId + " .item-unit-price").val(addComma($("#" + itemId + " .item-unit-price").val()));
|
||||
@@ -351,6 +362,7 @@
|
||||
var $row = $(this);
|
||||
items.push({
|
||||
contractItemObjId: $row.find(".item-contract-item-objid").val(), // CONTRACT_ITEM의 OBJID
|
||||
product: $row.find(".item-product").val(), // 제품구분
|
||||
partObjId: $row.find(".item-part-objid").val(),
|
||||
partNo: $row.find(".item-part-no").val(),
|
||||
partName: $row.find(".item-part-name").val(),
|
||||
@@ -490,25 +502,27 @@
|
||||
<div style="max-height:300px; overflow-y:auto;">
|
||||
<table class="pmsPopuptable" id="itemListTable">
|
||||
<colgroup>
|
||||
<col width="4%" /> <!-- 번호 -->
|
||||
<col width="10%" /> <!-- 품번 -->
|
||||
<col width="13%" /> <!-- 품명 -->
|
||||
<col width="12%" /> <!-- S/N -->
|
||||
<col width="8%" /> <!-- 수주수량 -->
|
||||
<col width="11%" /> <!-- 수주단가 -->
|
||||
<col width="12%" /> <!-- 수주공급가액 -->
|
||||
<col width="11%" /> <!-- 수주부가세 -->
|
||||
<col width="12%" /> <!-- 수주총액 -->
|
||||
<col width="7%" /> <!-- 삭제 -->
|
||||
<col width="3%" /> <!-- 번호 -->
|
||||
<col width="9%" /> <!-- 제품구분 -->
|
||||
<col width="9%" /> <!-- 품번 -->
|
||||
<col width="12%" /> <!-- 품명 -->
|
||||
<col width="10%" /> <!-- S/N -->
|
||||
<col width="7%" /> <!-- 수주수량 -->
|
||||
<col width="10%" /> <!-- 수주단가 -->
|
||||
<col width="11%" /> <!-- 수주공급가액 -->
|
||||
<col width="10%" /> <!-- 수주부가세 -->
|
||||
<col width="11%" /> <!-- 수주총액 -->
|
||||
<col width="5%" /> <!-- 삭제 -->
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr style="background:#f5f5f5;">
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">No</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">제품구분 <span style="color:red;">*</span></th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">품번</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">품명</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">S/N</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주수량 <span style="color:red;">*</span></th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주단가 </th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주단가</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주공급가액</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주부가세</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주총액</th>
|
||||
@@ -518,7 +532,7 @@
|
||||
<tbody id="itemListBody">
|
||||
<!-- 품목 행이 동적으로 추가됩니다 -->
|
||||
<tr id="noItemRow">
|
||||
<td colspan="10" style="text-align:center; padding:30px; color:#999;">
|
||||
<td colspan="11" style="text-align:center; padding:30px; color:#999;">
|
||||
견적요청에 등록된 품목이 자동으로 표시됩니다.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -7420,7 +7420,7 @@ SELECT
|
||||
,CONTRACT_OBJID
|
||||
,CATEGORY_CD
|
||||
,CUSTOMER_OBJID
|
||||
,PRODUCT
|
||||
,PRODUCT
|
||||
,CUSTOMER_PROJECT_NAME
|
||||
,STATUS_CD
|
||||
,DUE_DATE
|
||||
@@ -7479,7 +7479,7 @@ SELECT
|
||||
,#{objId}
|
||||
,CATEGORY_CD
|
||||
,CUSTOMER_OBJID
|
||||
,PRODUCT
|
||||
,COALESCE(#{product}, PRODUCT)
|
||||
,CUSTOMER_PROJECT_NAME
|
||||
,STATUS_CD
|
||||
,DUE_DATE
|
||||
@@ -7529,8 +7529,8 @@ SELECT
|
||||
WHEN '판매' THEN 'S'
|
||||
ELSE 'T'
|
||||
END || '-' ||
|
||||
-- 제품구분 코드 (PRODUCT를 약어로 매핑)
|
||||
CASE CODE_NAME(PRODUCT)
|
||||
-- 제품구분 코드 (품목별 PRODUCT를 약어로 매핑, 없으면 마스터 PRODUCT)
|
||||
CASE CODE_NAME(COALESCE(#{product}, PRODUCT))
|
||||
WHEN 'Machine' THEN 'MC'
|
||||
WHEN 'A/S' THEN 'AS'
|
||||
WHEN 'D/S' THEN 'DS'
|
||||
@@ -7539,7 +7539,7 @@ SELECT
|
||||
WHEN 'A/C' THEN 'AC'
|
||||
WHEN 'W/M' THEN 'WM'
|
||||
WHEN '기타' THEN '기타'
|
||||
ELSE REPLACE(CODE_NAME(PRODUCT), '/', '')
|
||||
ELSE REPLACE(CODE_NAME(COALESCE(#{product}, PRODUCT)), '/', '')
|
||||
END || '-' ||
|
||||
-- 날짜 (YYMMDD)
|
||||
TO_CHAR(CURRENT_DATE, 'YYMMDD') || '-' ||
|
||||
@@ -7559,7 +7559,7 @@ SELECT
|
||||
WHEN '판매' THEN 'S'
|
||||
ELSE 'T'
|
||||
END || '-' ||
|
||||
CASE CODE_NAME(PRODUCT)
|
||||
CASE CODE_NAME(COALESCE(#{product}, PRODUCT))
|
||||
WHEN 'Machine' THEN 'MC'
|
||||
WHEN 'A/S' THEN 'AS'
|
||||
WHEN 'D/S' THEN 'DS'
|
||||
@@ -7568,7 +7568,7 @@ SELECT
|
||||
WHEN 'A/C' THEN 'AC'
|
||||
WHEN 'W/M' THEN 'WM'
|
||||
WHEN '기타' THEN '기타'
|
||||
ELSE REPLACE(CODE_NAME(PRODUCT), '/', '')
|
||||
ELSE REPLACE(CODE_NAME(COALESCE(#{product}, PRODUCT)), '/', '')
|
||||
END || '-' ||
|
||||
TO_CHAR(CURRENT_DATE, 'YYMMDD') || '-%'
|
||||
),
|
||||
@@ -7766,11 +7766,21 @@ SELECT
|
||||
MANUFACTURE_PLANT = #{manufacture_plant},
|
||||
</if>
|
||||
<if test="quantity != null and quantity != ''">
|
||||
QUANTITY = #{quantity}
|
||||
QUANTITY = #{quantity},
|
||||
</if>
|
||||
<if test="product != null and product != ''">
|
||||
PRODUCT = #{product}
|
||||
</if>
|
||||
</set>
|
||||
WHERE CONTRACT_OBJID = #{objId}
|
||||
AND PART_OBJID = #{part_objid}
|
||||
<choose>
|
||||
<when test="contract_item_objid != null and contract_item_objid != ''">
|
||||
AND CONTRACT_ITEM_OBJID = #{contract_item_objid}
|
||||
</when>
|
||||
<otherwise>
|
||||
AND PART_OBJID = #{part_objid}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</update>
|
||||
|
||||
<delete id="deleteProjectMngInfo" parameterType="map">
|
||||
|
||||
@@ -302,8 +302,15 @@ public class SalesNcollectMgmtController {
|
||||
contractParam.put("objId", contractObjId);
|
||||
Map<String, Object> contractInfo = commonService.selectOne("contractMgmt.getContractInfo", request, contractParam);
|
||||
|
||||
// PROJECT_MGMT에서 품번/품명/S/N/요청납기/고객요청사항/반납사유 조회
|
||||
// PROJECT_MGMT에서 품번/품명/S/N/요청납기/고객요청사항/반납사유/제품구분 조회
|
||||
if(projectInfo != null) {
|
||||
// 제품구분 (프로젝트에 저장된 품목별 제품구분 우선)
|
||||
Object projProduct = projectInfo.get("product") != null ? projectInfo.get("product") : projectInfo.get("PRODUCT");
|
||||
Object projProductName = projectInfo.get("product_name") != null ? projectInfo.get("product_name") : projectInfo.get("PRODUCT_NAME");
|
||||
if(projProduct != null && !"".equals(projProduct.toString())) {
|
||||
contractInfo.put("PRODUCT", projProduct);
|
||||
contractInfo.put("PRODUCT_NAME", projProductName);
|
||||
}
|
||||
// 품번
|
||||
if(contractInfo.get("PART_NO") == null || "".equals(contractInfo.get("PART_NO"))) {
|
||||
contractInfo.put("PART_NO", projectInfo.get("part_no") != null ? projectInfo.get("part_no") : projectInfo.get("PART_NO"));
|
||||
|
||||
@@ -5288,6 +5288,9 @@ WHERE
|
||||
ORDER_SUPPLY_PRICE = #{orderSupplyPrice},
|
||||
ORDER_VAT = #{orderVat},
|
||||
ORDER_TOTAL_AMOUNT = #{orderTotalAmount}
|
||||
<if test="product != null and product != ''">
|
||||
,PRODUCT = #{product}
|
||||
</if>
|
||||
WHERE OBJID = #{contractItemObjId}
|
||||
</update>
|
||||
|
||||
|
||||
@@ -1787,8 +1787,10 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
<!-- 프로젝트 기본 정보 조회 (CONTRACT_OBJID 포함) -->
|
||||
<select id="getProjectInfo" parameterType="map" resultType="map">
|
||||
/* salesNcollectMgmt.getProjectInfo - PROJECT_MGMT의 상세 정보 조회 (최신 1개) */
|
||||
SELECT
|
||||
SELECT
|
||||
PM.CONTRACT_OBJID,
|
||||
PM.PRODUCT,
|
||||
CODE_NAME(PM.PRODUCT) AS PRODUCT_NAME,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
-- 요청납기 (CONTRACT_ITEM의 DUE_DATE 우선, 없으면 PROJECT_MGMT.DUE_DATE)
|
||||
|
||||
@@ -2893,6 +2893,7 @@ private String encodeImageToBase64(String imagePath) {
|
||||
String orderTotalAmount = item.get("orderTotalAmount") != null ? item.get("orderTotalAmount").toString().replace(",", "") : "0";
|
||||
|
||||
itemMap.put("contractItemObjId", item.get("contractItemObjId") != null ? item.get("contractItemObjId").toString() : "");
|
||||
itemMap.put("product", item.get("product") != null ? item.get("product").toString() : "");
|
||||
itemMap.put("orderQuantity", item.get("orderQuantity") != null ? item.get("orderQuantity").toString() : "");
|
||||
itemMap.put("orderUnitPrice", item.get("orderUnitPrice") != null ? item.get("orderUnitPrice").toString() : "");
|
||||
itemMap.put("orderSupplyPrice", orderSupplyPrice);
|
||||
@@ -2928,18 +2929,16 @@ private String encodeImageToBase64(String imagePath) {
|
||||
// 프로젝트가 이미 존재하는 경우에는 수량/납기 등 업데이트 반영
|
||||
resultList = sqlSession.selectOne("contractMgmt.getProjectListBycontractObjid", paramMap);
|
||||
if(resultList != null) {
|
||||
// 제품구분 확인
|
||||
Map<String, Object> contractInfo = (Map<String, Object>) sqlSession.selectOne("contractMgmt.getContractBasicInfo", paramMap);
|
||||
contractInfo = CommonUtils.toUpperCaseMapKey(contractInfo);
|
||||
String product_cd = contractInfo != null ? CommonUtils.checkNull(contractInfo.get("PRODUCT")) : "";
|
||||
boolean isMachine = "0000928".equals(product_cd);
|
||||
|
||||
paramMap.put("contractObjId", contract_objid);
|
||||
List contractItemsRaw2 = sqlSession.selectList("contractMgmt.getContractItems", paramMap);
|
||||
List<Map<String, Object>> contractItems = CommonUtils.toUpperCaseMapKey(contractItemsRaw2);
|
||||
|
||||
if(contractItems != null && !contractItems.isEmpty()) {
|
||||
for(Map item : contractItems) {
|
||||
// 품목별 제품구분 판단
|
||||
String itemProductCd = CommonUtils.checkNull(item.get("PRODUCT"));
|
||||
boolean isMachine = "0000928".equals(itemProductCd);
|
||||
|
||||
Object quantityObj = item.get("ORDER_QUANTITY") != null ? item.get("ORDER_QUANTITY") : item.get("QUANTITY");
|
||||
int itemQuantity = 1;
|
||||
try {
|
||||
@@ -2949,6 +2948,7 @@ private String encodeImageToBase64(String imagePath) {
|
||||
}
|
||||
Map<String, Object> updateParam = new HashMap<String, Object>();
|
||||
updateParam.putAll(paramMap);
|
||||
updateParam.put("contract_item_objid", String.valueOf(item.get("OBJID")));
|
||||
updateParam.put("part_objid", item.get("PART_OBJID"));
|
||||
if(isMachine) {
|
||||
updateParam.remove("quantity");
|
||||
@@ -2956,6 +2956,7 @@ private String encodeImageToBase64(String imagePath) {
|
||||
updateParam.put("quantity", String.valueOf(itemQuantity));
|
||||
}
|
||||
updateParam.put("due_date", item.get("DUE_DATE"));
|
||||
updateParam.put("product", itemProductCd);
|
||||
sqlSession.update("project.ModifyProjectByContract", updateParam);
|
||||
}
|
||||
} else {
|
||||
@@ -3005,13 +3006,7 @@ private String encodeImageToBase64(String imagePath) {
|
||||
Map<String, Object> contractInfo = (Map<String, Object>) sqlSession.selectOne("contractMgmt.getContractBasicInfo", paramMap);
|
||||
contractInfo = CommonUtils.toUpperCaseMapKey(contractInfo);
|
||||
|
||||
String product_cd = contractInfo != null ? CommonUtils.checkNull(contractInfo.get("PRODUCT")) : "";
|
||||
String category_cd = contractInfo != null ? CommonUtils.checkNull(contractInfo.get("CATEGORY_CD")) : "";
|
||||
boolean isMachine = "0000928".equals(product_cd);
|
||||
|
||||
if(isMachine) {
|
||||
System.out.println("[수주확정] 제품구분: Machine(0000928) - 품목별 수량만큼 프로젝트 생성");
|
||||
}
|
||||
|
||||
// 품목별로 프로젝트 생성 또는 업데이트
|
||||
paramMap.put("contractObjId", objId);
|
||||
@@ -3019,9 +3014,13 @@ private String encodeImageToBase64(String imagePath) {
|
||||
List<Map<String, Object>> contractItems = CommonUtils.toUpperCaseMapKey(contractItemsRaw);
|
||||
|
||||
if(contractItems != null && !contractItems.isEmpty()) {
|
||||
System.out.println("[수주확정] 품목 개수: " + contractItems.size() + "개 - 프로젝트 " + (hasProject ? "업데이트" : "생성") + " 시작" + (isMachine ? " (Machine - 수량별 생성)" : ""));
|
||||
System.out.println("[수주확정] 품목 개수: " + contractItems.size() + "개 - 프로젝트 " + (hasProject ? "업데이트" : "생성") + " 시작");
|
||||
|
||||
for(Map item : contractItems) {
|
||||
// 품목별 제품구분 판단
|
||||
String itemProductCd = CommonUtils.checkNull(item.get("PRODUCT"));
|
||||
boolean isMachine = "0000928".equals(itemProductCd);
|
||||
|
||||
// 수량 가져오기 (소수점 형태 "2.00"도 처리)
|
||||
Object quantityObj = item.get("ORDER_QUANTITY") != null ? item.get("ORDER_QUANTITY") : item.get("QUANTITY");
|
||||
int itemQuantity = 1;
|
||||
@@ -3034,6 +3033,10 @@ private String encodeImageToBase64(String imagePath) {
|
||||
// Machine인 경우 수량만큼 반복, 아니면 1번만 실행
|
||||
int loopCount = (isMachine && !hasProject) ? itemQuantity : 1;
|
||||
|
||||
if(isMachine) {
|
||||
System.out.println("[수주확정] 제품구분: Machine(0000928) - 품번: " + item.get("PART_NO") + ", 수량 " + itemQuantity + "만큼 프로젝트 생성");
|
||||
}
|
||||
|
||||
for(int q = 0; q < loopCount; q++) {
|
||||
if(!hasProject) {
|
||||
// 프로젝트가 없으면 모든 품목에 대해 생성
|
||||
@@ -3047,6 +3050,8 @@ private String encodeImageToBase64(String imagePath) {
|
||||
projectParam.put("part_objid", item.get("PART_OBJID"));
|
||||
projectParam.put("part_no", item.get("PART_NO"));
|
||||
projectParam.put("part_name", item.get("PART_NAME"));
|
||||
// 품목별 제품구분 전달 (PROJECT_NO 생성 및 PRODUCT 컬럼에 사용)
|
||||
projectParam.put("product", itemProductCd);
|
||||
// Machine인 경우 각 프로젝트의 수량은 1, 아니면 원래 수량
|
||||
projectParam.put("quantity", isMachine ? "1" : String.valueOf(itemQuantity));
|
||||
projectParam.put("due_date", item.get("DUE_DATE"));
|
||||
@@ -3070,6 +3075,7 @@ private String encodeImageToBase64(String imagePath) {
|
||||
// 프로젝트가 있으면 모든 품목 업데이트 (수량, 금액 등만)
|
||||
Map<String, Object> updateParam = new HashMap<String, Object>();
|
||||
updateParam.putAll(paramMap);
|
||||
updateParam.put("contract_item_objid", String.valueOf(item.get("OBJID")));
|
||||
updateParam.put("part_objid", item.get("PART_OBJID"));
|
||||
// Machine인 경우 수량은 변경하지 않음 (프로젝트별 1로 유지)
|
||||
if(isMachine) {
|
||||
|
||||
Reference in New Issue
Block a user