Merge origin/main - 원격 변경사항 병합

This commit is contained in:
2025-10-22 21:00:12 +09:00
5 changed files with 269 additions and 466 deletions

View File

@@ -83,7 +83,7 @@ var columns = [
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '주문서첨부', field : 'ORDER_ATTACH',
formatter: fnc_subInfoValueFormatter,
cellClick: function(e, cell){
var objid = cell.getData().PROJECT_NO || cell.getData().SALE_NO;
var objid = cell.getData().CONTRACT_OBJID || cell.getData().SALE_NO;
if(objid){
fn_FileRegist(objid, "ORDER_DOC", "주문서");
}

View File

@@ -1,5 +1,5 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="/init.jsp" %>
<%@ include file="/init_new.jsp" %>
<!DOCTYPE html>
<html>
<head>
@@ -7,26 +7,7 @@
<title>판매 등록</title>
<link rel="stylesheet" href="/css/ions-basic.css">
<script type="text/javascript" src="/js/ions-common.js" ></script>
<style>
/* S/N 입력 필드 placeholder 색상 */
#serialNo::placeholder {
color: #999 !important;
opacity: 1;
}
#serialNo::-webkit-input-placeholder {
color: #999 !important;
}
#serialNo::-moz-placeholder {
color: #999 !important;
opacity: 1;
}
#serialNo:-ms-input-placeholder {
color: #999 !important;
}
</style>
<script>
// S/N 관리 전역 변수
var snList = [];
@@ -50,8 +31,25 @@
fn_openSnManagePopup();
});
// 초기 S/N 데이터 로드
fn_loadSnList();
// 페이지 로드 시 기존 S/N 데이터가 있으면 파싱하여 hidden 필드에 저장
var initialSnValue = $("#serialNo").val();
if(initialSnValue && initialSnValue.trim() != '') {
var snArray = initialSnValue.split(',');
var initialSnList = [];
for(var i = 0; i < snArray.length; i++) {
if(snArray[i].trim() != '') {
initialSnList.push({
id: i + 1,
value: snArray[i].trim()
});
}
}
if(initialSnList.length > 0) {
$("#serialNoList").val(JSON.stringify(initialSnList));
snCounter = initialSnList.length + 1;
console.log("초기 S/N 데이터 로드:", initialSnList);
}
}
// 닫기 버튼
$("#btnClose").click(function() {
@@ -128,126 +126,71 @@
}
}
// S/N 목록 로드
function fn_loadSnList() {
// S/N 화면 표시 업데이트
function fn_updateSnDisplay() {
var count = snList.length;
if(count > 0) {
// 모든 S/N을 쉼표로 연결
var snValues = [];
for(var i = 0; i < snList.length; i++) {
snValues.push(snList[i].value);
}
$("#serialNo").val(snValues.join(', '));
} else {
$("#serialNo").val('');
}
}
// S/N 관리 팝업 열기
function fn_openSnManagePopup() {
// 최신 데이터 다시 로드 (display 업데이트 없이)
var serialNoValue = $("#serialNo").val();
var serialNoListValue = $("#serialNoList").val();
console.log("초기 로드 - serialNo:", serialNoValue);
console.log("초기 로드 - serialNoList:", serialNoListValue);
snList = [];
console.log("팝업 열기 시작");
console.log("serialNoList:", serialNoListValue);
// 데이터가 있을 때만 로드
if(serialNoListValue && serialNoListValue.trim() != '') {
// JSON 형태로 저장된 데이터가 있으면 파싱
try {
var loadedList = JSON.parse(serialNoListValue);
snList = loadedList;
console.log("JSON 파싱 성공:", snList);
snList = JSON.parse(serialNoListValue);
console.log("JSON 파싱 성공, snList:", snList);
// counter 재설정
if(snList.length > 0) {
var maxId = Math.max.apply(Math, snList.map(function(item) { return item.id; }));
snCounter = maxId + 1;
}
} catch(e) {
console.log("JSON 파싱 실패:", e);
// JSON 파싱 실패 시 기존 로직 사용
if(serialNoValue && serialNoValue.trim() != '') {
fn_parseSerialNoValue(serialNoValue);
}
}
} else if(serialNoValue && serialNoValue.trim() != '') {
// hidden 필드가 없고 display 필드만 있는 경우
console.log("display 필드만 있음, 파싱 시작");
fn_parseSerialNoValue(serialNoValue);
}
// 초기 로드 후 hidden 필드에 JSON 저장
if(snList.length > 0) {
$("#serialNoList").val(JSON.stringify(snList));
console.log("hidden 필드에 저장:", $("#serialNoList").val());
}
fn_updateSnDisplay();
}
// S/N 값 파싱 함수
function fn_parseSerialNoValue(serialNoValue) {
// "외 N개" 패턴 제거 및 콤마로 분리
var cleanValue = serialNoValue;
// "외 N개" 패턴 제거 (예: "20251021-007 외 2건" -> "20251021-007")
cleanValue = cleanValue.replace(/\s*외\s*\d+\s*건?\s*$/g, '').trim();
console.log("정제된 값:", cleanValue);
if(cleanValue != '') {
var snArray = cleanValue.split(',');
for(var i = 0; i < snArray.length; i++) {
var sn = snArray[i].trim();
if(sn != '') {
snList.push({
id: snCounter++,
value: sn
});
}
}
console.log("파싱 완료, snList:", snList);
}
}
// S/N 화면 표시 업데이트
function fn_updateSnDisplay() {
if(snList.length === 0) {
$("#serialNo").val('');
} else if(snList.length === 1) {
$("#serialNo").val(snList[0].value);
} else {
$("#serialNo").val(snList[0].value + ' 외 ' + (snList.length - 1) + '개');
}
}
// S/N 관리 팝업 열기
function fn_openSnManagePopup() {
console.log("=== 팝업 열기 시작 ===");
// 최신 데이터 다시 로드
var serialNoValue = $("#serialNo").val();
var serialNoListValue = $("#serialNoList").val();
console.log("팝업 - serialNo:", serialNoValue);
console.log("팝업 - serialNoList:", serialNoListValue);
if(serialNoListValue && serialNoListValue.trim() != '' && serialNoListValue != '[]') {
// JSON 데이터가 있으면 파싱
try {
snList = JSON.parse(serialNoListValue);
console.log("JSON 파싱 성공:", snList);
if(snList.length > 0) {
var maxId = Math.max.apply(Math, snList.map(function(item) { return item.id; }));
snCounter = maxId + 1;
}
} catch(e) {
console.log("JSON 파싱 실패:", e);
// JSON 파싱 실패 시 display 필드 파싱
console.log("JSON 파싱 오류:", e);
snList = [];
if(serialNoValue && serialNoValue.trim() != '') {
fn_parseSerialNoValue(serialNoValue);
}
}
} else if(serialNoValue && serialNoValue.trim() != '') {
// hidden 필드가 없으면 display 필드 파싱
console.log("hidden 필드 없음, display 필드 파싱");
console.log("hidden 필드 없음, display 필드에서 파싱");
snList = [];
fn_parseSerialNoValue(serialNoValue);
var snArray = serialNoValue.split(',');
for(var i = 0; i < snArray.length; i++) {
if(snArray[i].trim() != '') {
snList.push({
id: snCounter++,
value: snArray[i].trim()
});
}
}
} else {
console.log("데이터 없음, 빈 배열로 시작");
console.log("저장된 데이터 없음, 빈 배열로 시작");
snList = [];
}
console.log("최종 snList:", snList);
console.log("로드된 S/N 목록 (복사본):", JSON.parse(JSON.stringify(snList)));
console.log("snList.length:", snList.length);
// 실제 데이터 확인
if(snList.length > 0) {
console.log("첫 번째 아이템:", snList[0]);
}
// 팝업 HTML 생성
var popupHtml = '<div style="padding:10px; color:#333;">';
popupHtml += ' <h3 style="margin:0 0 15px 0; text-align:center; color:#333;">S/N 관리</h3>';
@@ -272,7 +215,7 @@
customClass: {
popup: 'sn-manage-popup'
},
didOpen: function() {
onOpen: function() {
setTimeout(function() {
fn_renderSnList();
// 엔터키로 추가
@@ -289,23 +232,35 @@
// S/N 목록 렌더링
function fn_renderSnList() {
var container = $(".swal2-html-container #snListContainer");
console.log("fn_renderSnList 실행, snList 길이:", snList.length);
console.log("snList 내용:", snList);
if(snList.length === 0) {
container.html('<div style="text-align:center; padding:20px; color:#999;">등록된 S/N이 없습니다.</div>');
return;
var html = '<table style="width:100%; margin-bottom:10px; border-collapse:collapse; border:1px solid #ddd; color:#333;">';
html += '<colgroup><col width="15%"><col width="65%"><col width="20%"></colgroup>';
html += '<thead><tr style="background:#f5f5f5; color:#333;">';
html += '<th style="padding:10px; border:1px solid #ddd; text-align:center; color:#333;">번호</th>';
html += '<th style="padding:10px; border:1px solid #ddd; text-align:center; color:#333;">S/N</th>';
html += '<th style="padding:10px; border:1px solid #ddd; text-align:center; color:#333;">삭제</th>';
html += '</tr></thead>';
html += '<tbody>';
if(snList.length == 0) {
html += '<tr><td colspan="3" style="text-align:center; padding:30px; color:#999; border:1px solid #ddd;">등록된 S/N이 없습니다.</td></tr>';
} else {
for(var i = 0; i < snList.length; i++) {
html += '<tr>';
html += '<td style="text-align:center; padding:8px; border:1px solid #ddd; color:#333;">' + (i+1) + '</td>';
html += '<td style="padding:8px; border:1px solid #ddd; color:#333;">' + snList[i].value + '</td>';
html += '<td style="text-align:center; padding:8px; border:1px solid #ddd;">';
html += '<button type="button" onclick="fn_deleteSn(' + snList[i].id + ')" class="plm_btns" style="padding:4px 8px; font-size:12px;">삭제</button>';
html += '</td>';
html += '</tr>';
}
}
var html = '<div style="display:flex; flex-direction:column; gap:5px;">';
for(var i = 0; i < snList.length; i++) {
html += '<div style="display:flex; align-items:center; padding:8px; background:#f8f9fa; border-radius:4px; color:#333;">';
html += ' <span style="flex:1; color:#333;">' + snList[i].value + '</span>';
html += ' <button type="button" onclick="fn_deleteSn(' + snList[i].id + ')" class="plm_btns" style="padding:4px 8px; font-size:12px; background:#dc3545; color:#fff;">삭제</button>';
html += '</div>';
}
html += '</div>';
html += '</tbody></table>';
container.html(html);
$(".swal2-html-container #snListContainer").html(html);
}
// S/N 추가
@@ -447,13 +402,23 @@
// S/N 목록 확인 및 적용
function fn_confirmSnList() {
// snList를 JSON 문자열로 변환하여 hidden 필드에 저장
$("#serialNoList").val(JSON.stringify(snList));
console.log("확인 버튼 클릭, snList:", snList);
console.log("snList.length:", snList.length);
// S/N 목록을 쉼표로 구분하여 input에 저장
var snValues = [];
for(var i = 0; i < snList.length; i++) {
snValues.push(snList[i].value);
}
// hidden 필드에 전체 목록 저장 (서버 전송용)
var jsonString = JSON.stringify(snList);
console.log("저장할 JSON:", jsonString);
$("#serialNoList").val(jsonString);
console.log("저장 후 확인:", $("#serialNoList").val());
// 화면 표시 업데이트
fn_updateSnDisplay();
// 팝업 닫기
Swal.close();
}
@@ -467,12 +432,34 @@
var isChecked = $("#isShippingOrder").is(":checked");
$("#shippingOrderStatus").val(isChecked ? "출하지시" : "");
// S/N 데이터 최종 정리 (콤마로 구분된 문자열로 변환)
var serialNoValue = '';
if(snList.length > 0) {
serialNoValue = snList.map(function(item) { return item.value; }).join(',');
// S/N 데이터 처리: JSON에서 값만 추출하여 콤마로 연결
var serialNoListValue = $("#serialNoList").val();
console.log("=== 저장 전 S/N 처리 시작 ===");
console.log("serialNoList 값:", serialNoListValue);
if(serialNoListValue && serialNoListValue.trim() != '') {
try {
var snArray = JSON.parse(serialNoListValue);
console.log("파싱된 배열:", snArray);
var snValues = [];
for(var i = 0; i < snArray.length; i++) {
if(snArray[i].value) {
snValues.push(snArray[i].value);
}
}
console.log("추출된 값들:", snValues);
// 콤마로 구분된 문자열로 변환 (서버 저장용, 띄어쓰기 없이)
var finalSnString = snValues.join(',');
console.log("최종 S/N 문자열:", finalSnString);
$("#serialNo").val(finalSnString);
console.log("설정 후 serialNo 필드 값:", $("#serialNo").val());
} catch(e) {
console.error("S/N JSON 파싱 오류:", e);
}
} else {
console.log("serialNoList가 비어있음");
}
$("#serialNo").val(serialNoValue);
console.log("=== S/N 처리 완료 ===");
if(confirm("저장하시겠습니까?")) {
$.ajax({
@@ -500,7 +487,8 @@
<form name="form1" id="form1" action="" method="post">
<input type="hidden" name="orderNo" value="${param.orderNo}">
<input type="hidden" name="saleNo" value="${param.saleNo}">
<input type="hidden" name="serialNoList" id="serialNoList" value="${saleInfo.SERIAL_NO_LIST}" />
<!-- serialNoList는 name 속성 없이 id만 사용 (클라이언트 전용) -->
<input type="hidden" id="serialNoList" value="${saleInfo.SERIAL_NO_LIST}" />
<section>
<div class="plm_menu_name">
<h2>
@@ -597,11 +585,7 @@
<td class="input_sub_title">
<select name="salesCurrency" id="salesCurrency" style="width:100%;" class="select2" onchange="fn_recalculateByExchangeRate()">
<option value="">선택</option>
<option value="KRW" ${saleInfo.SALES_CURRENCY == 'KRW' || empty saleInfo.SALES_CURRENCY ? 'selected' : ''}>KRW</option>
<option value="USD" ${saleInfo.SALES_CURRENCY == 'USD' ? 'selected' : ''}>USD</option>
<option value="EUR" ${saleInfo.SALES_CURRENCY == 'EUR' ? 'selected' : ''}>EUR</option>
<option value="JPY" ${saleInfo.SALES_CURRENCY == 'JPY' ? 'selected' : ''}>JPY</option>
<option value="CNY" ${saleInfo.SALES_CURRENCY == 'CNY' ? 'selected' : ''}>CNY</option>
${codeMap.salesCurrency}
</select>
</td>
<td class="input_title"><label for="salesExchangeRate">판매환율</label></td>