518 lines
18 KiB
Plaintext
518 lines
18 KiB
Plaintext
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||
pageEncoding="UTF-8"%>
|
||
<%@ page import="com.pms.common.utils.*"%>
|
||
<%@ page import="java.util.*"%>
|
||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||
<%@include file="/init_new.jsp"%>
|
||
<%
|
||
PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN);
|
||
String userId = CommonUtils.checkNull(person.getUserId());
|
||
%>
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
<title><%=Constants.SYSTEM_NAME%></title>
|
||
<style>
|
||
.fileListscrollTbody td {
|
||
font-size: 11px !important;
|
||
}
|
||
|
||
/* 품목 테이블 스타일 */
|
||
#itemListTable {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
}
|
||
|
||
#itemListTable th,
|
||
#itemListTable td {
|
||
border: 1px solid #ddd;
|
||
padding: 8px;
|
||
text-align: center;
|
||
}
|
||
|
||
#itemListTable th {
|
||
background-color: #f5f5f5;
|
||
font-weight: bold;
|
||
}
|
||
|
||
#itemListTable input[type="text"],
|
||
#itemListTable input[type="number"] {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
</style>
|
||
<script type="text/javascript">
|
||
// 품목 관리 변수
|
||
var itemCounter = 1;
|
||
var itemList = [];
|
||
|
||
$(function() {
|
||
// console.log("===== 수주등록 팝업 로드됨 =====");
|
||
// console.log("useEstimateTemplate 값:", "${useEstimateTemplate}");
|
||
|
||
// 숫자 입력 필드에 콤마 자동 추가 및 금액 계산
|
||
$(document).on("keyup", "input:text[numberOnly]", function() {
|
||
$(this).val(addComma($(this).val().replace(/[^0-9]/g, "")));
|
||
|
||
var itemId = $(this).closest("tr").attr("id");
|
||
if(itemId) {
|
||
// 수주수량 또는 수주단가가 변경되면 공급가액, 부가세, 총액 모두 재계산
|
||
if($(this).hasClass("item-quantity") || $(this).hasClass("item-unit-price")) {
|
||
fn_calculateItemAmount(itemId);
|
||
}
|
||
// 수주부가세만 변경되면 총액만 재계산
|
||
else if($(this).hasClass("item-vat")) {
|
||
fn_calculateTotalFromVat(itemId);
|
||
}
|
||
}
|
||
});
|
||
|
||
// 페이지 로드 시 기존 값에 콤마 표시
|
||
$("input:text[numberOnly]").each(function() {
|
||
var val = $(this).val();
|
||
if(val && val !== '') {
|
||
$(this).val(addComma(val.replace(/,/g, "")));
|
||
}
|
||
});
|
||
|
||
$('.select2').select2();
|
||
|
||
// 날짜 선택기 초기화
|
||
_fnc_datepick();
|
||
|
||
// 저장 버튼
|
||
$("#btnSave").click(function() {
|
||
fn_save();
|
||
});
|
||
|
||
// 닫기 버튼
|
||
$("#btnClose").click(function() {
|
||
self.close();
|
||
});
|
||
|
||
// 기존 품목 데이터 로드 (CONTRACT_ITEM에서)
|
||
fn_loadContractItems();
|
||
});
|
||
|
||
// 콤마 추가 함수
|
||
function addComma(data) {
|
||
if(!data) return '';
|
||
return data.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||
}
|
||
|
||
// 콤마 제거 함수
|
||
function removeComma(data) {
|
||
if(!data) return '';
|
||
return data.toString().replace(/,/g, "");
|
||
}
|
||
|
||
// 품목 행 추가 (사용 안함 - CONTRACT_ITEM에서만 로드)
|
||
function fn_addItemRow() {
|
||
alert("품목은 견적요청에서 등록된 항목만 표시됩니다.");
|
||
return;
|
||
}
|
||
|
||
// 품목 행 삭제
|
||
function fn_removeItemRow(itemId) {
|
||
if(confirm("이 품목을 삭제하시겠습니까?")) {
|
||
$("#" + itemId).remove();
|
||
|
||
// itemList에서 제거
|
||
for(var i = 0; i < itemList.length; i++) {
|
||
if(itemList[i].id == itemId) {
|
||
itemList.splice(i, 1);
|
||
break;
|
||
}
|
||
}
|
||
|
||
// 번호 재정렬
|
||
fn_reorderItems();
|
||
|
||
// 품목이 없으면 메시지 표시
|
||
if($("#itemListBody tr.item-row").length == 0) {
|
||
$("#itemListBody").html('<tr id="noItemRow"><td colspan="9" style="text-align:center; padding:30px; color:#999;">품목 추가 버튼을 클릭하여 품목을 등록하세요.</td></tr>');
|
||
}
|
||
}
|
||
}
|
||
|
||
// 품목 번호 재정렬
|
||
function fn_reorderItems() {
|
||
$("#itemListBody tr.item-row").each(function(index) {
|
||
$(this).find("td:first").text(index + 1);
|
||
});
|
||
}
|
||
|
||
// 품목별 금액 계산
|
||
// 수량 × 단가 = 공급가액 (자동)
|
||
// 부가세 입력 가능 (기본값: 공급가액 × 10%)
|
||
// 공급가액 + 부가세 = 총액 (자동)
|
||
function fn_calculateItemAmount(itemId) {
|
||
var quantity = parseInt(removeComma($("#" + itemId + " .item-quantity").val())) || 0;
|
||
var unitPrice = parseInt(removeComma($("#" + itemId + " .item-unit-price").val())) || 0;
|
||
|
||
// 공급가액 계산
|
||
var supplyPrice = quantity * unitPrice;
|
||
$("#" + itemId + " .item-supply-price").val(addComma(supplyPrice));
|
||
|
||
// 부가세 자동 계산 (공급가액의 10%)
|
||
var vat = Math.round(supplyPrice * 0.1);
|
||
$("#" + itemId + " .item-vat").val(addComma(vat));
|
||
|
||
// 총액 계산
|
||
var totalAmount = supplyPrice + vat;
|
||
$("#" + itemId + " .item-total-amount").val(addComma(totalAmount));
|
||
}
|
||
|
||
// 부가세 직접 입력 시 총액만 재계산
|
||
function fn_calculateTotalFromVat(itemId) {
|
||
var supplyPrice = parseInt(removeComma($("#" + itemId + " .item-supply-price").val())) || 0;
|
||
var vat = parseInt(removeComma($("#" + itemId + " .item-vat").val())) || 0;
|
||
|
||
// 총액 계산
|
||
var totalAmount = supplyPrice + vat;
|
||
$("#" + itemId + " .item-total-amount").val(addComma(totalAmount));
|
||
}
|
||
|
||
// 기존 품목 데이터 로드 (결재완료 시 ESTIMATE_TEMPLATE_ITEM, 아니면 CONTRACT_ITEM)
|
||
function fn_loadContractItems() {
|
||
var contractObjId = $("#contractObjId").val();
|
||
if(!contractObjId || contractObjId === '') {
|
||
return;
|
||
}
|
||
|
||
// 결재완료 상태인지 확인
|
||
var useEstimateTemplate = "${useEstimateTemplate}";
|
||
// console.log("=== 품목 로드 디버깅 ===");
|
||
// console.log("contractObjId:", contractObjId);
|
||
// console.log("useEstimateTemplate:", useEstimateTemplate);
|
||
|
||
$.ajax({
|
||
url: "/contractMgmt/getContractItems.do",
|
||
type: "POST",
|
||
data: {
|
||
contractObjId: contractObjId,
|
||
useEstimateTemplate: useEstimateTemplate
|
||
},
|
||
dataType: "json",
|
||
success: function(data) {
|
||
// console.log("품목 데이터:", data);
|
||
if(data && data.items && data.items.length > 0) {
|
||
$("#noItemRow").remove();
|
||
|
||
for(var i = 0; i < data.items.length; i++) {
|
||
var item = data.items[i];
|
||
var itemId = "item_" + itemCounter++;
|
||
|
||
// S/N 처리 (쉼표로 구분된 값)
|
||
var serialNo = item.SERIAL_NO || '';
|
||
var serialNoDisplay = serialNo;
|
||
if(serialNo) {
|
||
var snArray = serialNo.split(',').map(function(s){ return s.trim(); }).filter(function(s){ return s !== ''; });
|
||
if(snArray.length > 1) {
|
||
serialNoDisplay = snArray[0] + ' 외 ' + (snArray.length - 1) + '개';
|
||
}
|
||
}
|
||
|
||
var html = '<tr id="' + itemId + '" class="item-row">';
|
||
html += '<td>' + (i + 1) + '</td>';
|
||
html += '<td><input type="text" class="item-part-no" value="' + (item.PART_NO || '') + '" readonly style="background:#f5f5f5;" /></td>';
|
||
html += '<td><input type="text" class="item-part-name" value="' + (item.PART_NAME || '') + '" readonly style="background:#f5f5f5;" /></td>';
|
||
html += '<td><input type="text" class="item-serial-no" value="' + serialNoDisplay + '" readonly style="background:#f5f5f5;" title="' + serialNo + '" /></td>';
|
||
html += '<td><input type="text" class="item-quantity" value="' + (item.ORDER_QUANTITY || item.QUANTITY || '') + '" numberOnly required /></td>';
|
||
html += '<td><input type="text" class="item-unit-price" value="' + (item.ORDER_UNIT_PRICE || '') + '" numberOnly required /></td>';
|
||
html += '<td><input type="text" class="item-supply-price" value="' + (item.ORDER_SUPPLY_PRICE || '') + '" numberOnly readonly style="background:#f5f5f5;" /></td>';
|
||
html += '<td><input type="text" class="item-vat" value="' + (item.ORDER_VAT || '') + '" numberOnly /></td>'; // readonly 제거
|
||
html += '<td><input type="text" class="item-total-amount" value="' + (item.ORDER_TOTAL_AMOUNT || '') + '" numberOnly readonly style="background:#f5f5f5;" /></td>';
|
||
html += '<td style="text-align:center;">-</td>'; // 삭제 불가
|
||
html += '<input type="hidden" class="item-objid" value="' + (item.OBJID || '') + '" />';
|
||
html += '<input type="hidden" class="item-contract-item-objid" value="' + (item.OBJID || '') + '" />'; // CONTRACT_ITEM의 OBJID
|
||
html += '<input type="hidden" class="item-part-objid" value="' + (item.PART_OBJID || '') + '" />';
|
||
html += '<input type="hidden" class="item-serial-no-full" value="' + serialNo + '" />'; // 전체 S/N
|
||
html += '</tr>';
|
||
|
||
$("#itemListBody").append(html);
|
||
|
||
// 콤마 추가
|
||
$("#" + itemId + " .item-quantity").val(addComma($("#" + itemId + " .item-quantity").val()));
|
||
$("#" + itemId + " .item-unit-price").val(addComma($("#" + itemId + " .item-unit-price").val()));
|
||
$("#" + itemId + " .item-supply-price").val(addComma($("#" + itemId + " .item-supply-price").val()));
|
||
$("#" + itemId + " .item-vat").val(addComma($("#" + itemId + " .item-vat").val()));
|
||
$("#" + itemId + " .item-total-amount").val(addComma($("#" + itemId + " .item-total-amount").val()));
|
||
|
||
// 이벤트 바인딩 (클로저 문제 해결)
|
||
(function(id) {
|
||
// 수량, 단가 변경 시 → 전체 재계산
|
||
$("#" + id + " .item-quantity, #" + id + " .item-unit-price").on("change keyup", function() {
|
||
fn_calculateItemAmount(id);
|
||
});
|
||
// 부가세 변경 시 → 총액만 재계산
|
||
$("#" + id + " .item-vat").on("change keyup", function() {
|
||
fn_calculateTotalFromVat(id);
|
||
});
|
||
})(itemId);
|
||
|
||
// S/N 클릭 시 전체 S/N 보기
|
||
$("#" + itemId + " .item-serial-no").on("click", function() {
|
||
var fullSn = $(this).attr("title");
|
||
if(fullSn && fullSn !== '') {
|
||
var snArray = fullSn.split(',').map(function(s){ return s.trim(); });
|
||
var snList = '<ol style="text-align:left; padding-left:20px;">';
|
||
for(var j = 0; j < snArray.length; j++) {
|
||
snList += '<li>' + snArray[j] + '</li>';
|
||
}
|
||
snList += '</ol>';
|
||
Swal.fire({
|
||
title: 'S/N 목록',
|
||
html: snList,
|
||
width: 500,
|
||
confirmButtonText: '확인'
|
||
});
|
||
}
|
||
});
|
||
|
||
// 품목 정보 저장
|
||
itemList.push({
|
||
id: itemId
|
||
});
|
||
}
|
||
}
|
||
},
|
||
error: function() {
|
||
console.log("품목 데이터 로드 실패");
|
||
}
|
||
});
|
||
}
|
||
|
||
// 저장 함수
|
||
function fn_save() {
|
||
// 품목 검증
|
||
if($("#itemListBody tr.item-row").length == 0) {
|
||
alert("품목을 하나 이상 추가해주세요.");
|
||
return false;
|
||
}
|
||
|
||
// 기본정보 검증
|
||
if (!fnc_valitate("form1")) {
|
||
return false;
|
||
}
|
||
|
||
// 품목 데이터 수집
|
||
var items = [];
|
||
$("#itemListBody tr.item-row").each(function() {
|
||
var $row = $(this);
|
||
items.push({
|
||
contractItemObjId: $row.find(".item-contract-item-objid").val(), // CONTRACT_ITEM의 OBJID
|
||
partObjId: $row.find(".item-part-objid").val(),
|
||
partNo: $row.find(".item-part-no").val(),
|
||
partName: $row.find(".item-part-name").val(),
|
||
serialNo: $row.find(".item-serial-no-full").val(),
|
||
orderQuantity: removeComma($row.find(".item-quantity").val()),
|
||
orderUnitPrice: removeComma($row.find(".item-unit-price").val()),
|
||
orderSupplyPrice: removeComma($row.find(".item-supply-price").val()),
|
||
orderVat: removeComma($row.find(".item-vat").val()),
|
||
orderTotalAmount: removeComma($row.find(".item-total-amount").val())
|
||
});
|
||
});
|
||
|
||
var message = "수정";
|
||
if ("${actionType}" == 'regist') {
|
||
message = "등록";
|
||
}
|
||
|
||
if (confirm(message + "하시겠습니까?")) {
|
||
// 품목 데이터를 JSON으로 변환
|
||
$("#items_json").val(JSON.stringify(items));
|
||
|
||
// 환율에서 콤마 제거
|
||
var exchangeRate = $("#exchange_rate").val();
|
||
if(exchangeRate) {
|
||
$("#exchange_rate").val(exchangeRate.replace(/,/g, ''));
|
||
}
|
||
|
||
$.ajax({
|
||
url : "/contractMgmt/saveOrderInfo.do",
|
||
type : "POST",
|
||
data : $("#form1").serialize(),
|
||
dataType : "json",
|
||
success : function(data) {
|
||
alert(data.msg);
|
||
if(opener && opener.fn_search) {
|
||
opener.fn_search();
|
||
}
|
||
self.close();
|
||
},
|
||
error : function(jqxhr, status, error) {
|
||
alert("저장 중 오류가 발생했습니다.");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
// 날짜 선택기 초기화
|
||
function _fnc_datepick() {
|
||
var $dateinput = $("input.date_icon");
|
||
for (var i = 0; i < $dateinput.length; i++) {
|
||
$dateinput.eq(i).attr("size", "10");
|
||
$dateinput.eq(i).datepicker({
|
||
changeMonth : true,
|
||
changeYear : true
|
||
});
|
||
}
|
||
}
|
||
|
||
</script>
|
||
</head>
|
||
<body>
|
||
<form name="form1" id="form1" action="" method="post">
|
||
<input type="hidden" name="contractObjId" id="contractObjId" value="${contractObjId}">
|
||
<input type="hidden" name="objId" id="objId" value="${objId}">
|
||
<input type="hidden" name="actionType" id="actionType" value="${actionType}">
|
||
<input type="hidden" name="items_json" id="items_json" value="">
|
||
|
||
<section class="business_popup_min_width">
|
||
<div class="plm_menu_name">
|
||
<h2>
|
||
<span>영업관리_주문서관리_수주등록 (영업번호: ${contractInfo.CONTRACT_NO})</span>
|
||
</h2>
|
||
</div>
|
||
|
||
<div id="EntirePopupFormWrap">
|
||
<!-- 기본정보 영역 -->
|
||
<div class="form_popup_title">
|
||
<span>수주 기본정보</span>
|
||
</div>
|
||
<table class="">
|
||
<colgroup>
|
||
<col width="100%" />
|
||
</colgroup>
|
||
<tr>
|
||
<td>
|
||
<table class="pmsPopuptable">
|
||
<colgroup>
|
||
<col width="15%" />
|
||
<col width="35%" />
|
||
<col width="15%" />
|
||
<col width="35%" />
|
||
</colgroup>
|
||
|
||
<!-- 첫번째 행: 수주상태, 발주번호 -->
|
||
<tr>
|
||
<td class="input_title"><label for="">수주상태 <span style="color:red;">*</span></label></td>
|
||
<td>
|
||
<select name="contract_result" id="contract_result" required reqTitle="수주상태" type="select" class="select2">
|
||
<option value="">선택</option>
|
||
${code_map.contract_result}
|
||
</select>
|
||
</td>
|
||
<td class="input_title"><label for="">발주번호</label></td>
|
||
<td>
|
||
<input type="text" name="po_no" id="po_no" value="${info.PO_NO}" />
|
||
</td>
|
||
</tr>
|
||
|
||
<!-- 두번째 행: 발주일, 견적환종 -->
|
||
<tr>
|
||
<td class="input_title"><label for="">발주일 <span style="color:red;">*</span></label></td>
|
||
<td>
|
||
<input type="text" class="date_icon" name="order_date" id="order_date" required reqTitle="발주일" value="${info.ORDER_DATE}">
|
||
</td>
|
||
<td class="input_title"><label for="">견적환종</label></td>
|
||
<td>
|
||
<select name="contract_currency" id="contract_currency" reqTitle="환종" type="select" class="select2">
|
||
<option value="">선택</option>
|
||
${code_map.contract_currency}
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
|
||
<!-- 세번째 행: 견적환율 -->
|
||
<tr>
|
||
<td class="input_title"><label for="">견적환율</label></td>
|
||
<td colspan="3">
|
||
<input type="text" name="exchange_rate" id="exchange_rate" reqTitle="환율" value="${info.EXCHANGE_RATE}" numberOnly />
|
||
</td>
|
||
</tr>
|
||
|
||
</table>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<!-- 품목정보 영역 -->
|
||
<div class="form_popup_title" style="margin-top:15px;">
|
||
<span>품목정보 (견적요청에서 자동 로드)</span>
|
||
</div>
|
||
<table class="">
|
||
<colgroup>
|
||
<col width="100%" />
|
||
</colgroup>
|
||
<tr>
|
||
<td>
|
||
<div style="max-height:300px; overflow-y:auto;">
|
||
<table class="pmsPopuptable" id="itemListTable">
|
||
<colgroup>
|
||
<col width="4%" /> <!-- 번호 -->
|
||
<col width="10%" /> <!-- 품번 -->
|
||
<col width="13%" /> <!-- 품명 -->
|
||
<col width="12%" /> <!-- S/N -->
|
||
<col width="8%" /> <!-- 수주수량 -->
|
||
<col width="11%" /> <!-- 수주단가 -->
|
||
<col width="12%" /> <!-- 수주공급가액 -->
|
||
<col width="11%" /> <!-- 수주부가세 -->
|
||
<col width="12%" /> <!-- 수주총액 -->
|
||
<col width="7%" /> <!-- 삭제 -->
|
||
</colgroup>
|
||
<thead>
|
||
<tr style="background:#f5f5f5;">
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">No</th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">품번</th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">품명</th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">S/N</th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주수량 <span style="color:red;">*</span></th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주단가 <span style="color:red;">*</span></th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주공급가액</th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주부가세</th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">수주총액</th>
|
||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">-</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="itemListBody">
|
||
<!-- 품목 행이 동적으로 추가됩니다 -->
|
||
<tr id="noItemRow">
|
||
<td colspan="10" style="text-align:center; padding:30px; color:#999;">
|
||
견적요청에 등록된 품목이 자동으로 표시됩니다.
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
</div>
|
||
|
||
<div class="btn_wrap">
|
||
<div class="plm_btn_wrap_center">
|
||
<c:choose>
|
||
<c:when test="${actionType eq 'view'}">
|
||
<%-- 조회 모드: 닫기 버튼만 표시 --%>
|
||
</c:when>
|
||
<c:when test="${actionType eq 'regist'}">
|
||
<input type="button" value="저장" id="btnSave" class="plm_btns">
|
||
</c:when>
|
||
<c:otherwise>
|
||
<input type="button" value="수정" id="btnSave" class="plm_btns">
|
||
</c:otherwise>
|
||
</c:choose>
|
||
<input type="button" value="닫기" id="btnClose" class="plm_btns">
|
||
</div>
|
||
</div>
|
||
|
||
</section>
|
||
</form>
|
||
</body>
|
||
</html>
|
||
|