Merge remote-tracking branch 'origin/main' into V2025121901

This commit is contained in:
2025-12-30 11:50:20 +09:00
7 changed files with 289 additions and 24 deletions

View File

@@ -3958,12 +3958,11 @@
ORDER BY REGDATE DESC, MBOM_NO
</select>
<!-- M-BOM 목록 (bizMakeOptionList용) -->
<!-- M-BOM 목록 (bizMakeOptionList용) - (E-BOM) 텍스트 제거 -->
<select id="getMbomListForSelect2" parameterType="map" resultType="map">
SELECT
OBJID AS CODE,
COALESCE(MBOM_NO, '') ||
CASE WHEN SOURCE_BOM_TYPE IS NOT NULL AND SOURCE_BOM_TYPE != '' THEN ' (' || SOURCE_BOM_TYPE || ')' ELSE '' END AS NAME
COALESCE(MBOM_NO, '') AS NAME
FROM MBOM_HEADER
WHERE STATUS = 'Y'
ORDER BY REGDATE DESC, MBOM_NO

View File

@@ -1398,15 +1398,15 @@
</if>
<if test="search_inspector != null and search_inspector != ''">
AND (
UPPER(PIM.INSPECTOR_ID) LIKE UPPER('%' || #{search_inspector} || '%')
OR UPPER((SELECT USER_NAME FROM USER_INFO WHERE USER_ID = PIM.INSPECTOR_ID)) LIKE UPPER('%' || #{search_inspector} || '%')
UPPER(PID.INSPECTOR_ID) LIKE UPPER('%' || #{search_inspector} || '%')
OR UPPER((SELECT USER_NAME FROM USER_INFO WHERE USER_ID = PID.INSPECTOR_ID)) LIKE UPPER('%' || #{search_inspector} || '%')
)
</if>
<if test="search_inspection_date_from != null and search_inspection_date_from != ''">
AND PIM.INSPECTION_DATE <![CDATA[>=]]> #{search_inspection_date_from}
AND PID.INSPECTION_DATE <![CDATA[>=]]> #{search_inspection_date_from}
</if>
<if test="search_inspection_date_to != null and search_inspection_date_to != ''">
AND PIM.INSPECTION_DATE <![CDATA[<=]]> #{search_inspection_date_to}
AND PID.INSPECTION_DATE <![CDATA[<=]]> #{search_inspection_date_to}
</if>
<if test="search_inspection_result != null and search_inspection_result != ''">
AND PID.INSPECTION_RESULT = #{search_inspection_result}

View File

@@ -28,9 +28,32 @@
.readonly-field {
background-color: #eee !important;
}
/* S/N 입력 필드 placeholder 색상 */
#SERIAL_NO::placeholder {
color: #999 !important;
opacity: 1;
}
#SERIAL_NO::-webkit-input-placeholder {
color: #999 !important;
}
#SERIAL_NO::-moz-placeholder {
color: #999 !important;
opacity: 1;
}
#SERIAL_NO:-ms-input-placeholder {
color: #999 !important;
}
#SERIAL_NO {
cursor: pointer;
}
</style>
</head>
<script>
// S/N 관리 변수
var snList = [];
var snCounter = 1;
$(function(){
fnc_datepick();
$(".select2").select2();
@@ -43,6 +66,30 @@ $(function(){
fn_save();
});
// S/N 클릭 시 팝업 오픈
$("#SERIAL_NO").click(function() {
fn_openSnManagePopup();
}).attr("placeholder", "클릭하여 S/N 추가").attr("readonly", true);
// 페이지 로드 시 기존 S/N 데이터가 있으면 파싱
var initialSnValue = $("#SERIAL_NO").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) {
snList = initialSnList;
snCounter = initialSnList.length + 1;
}
}
// 프로젝트번호 변경 시 관련 정보 자동 로드 (Select2 이벤트)
$("#PROJECT_NO").on("change select2:select", function(){
var projectObjid = $(this).val();
@@ -377,6 +424,216 @@ function fn_save(){
});
}
}
// ========== S/N 관리 함수 ==========
// S/N 관리 팝업 열기
function fn_openSnManagePopup() {
// 기존 데이터 로드
var serialNoValue = $("#SERIAL_NO").val();
if(serialNoValue && serialNoValue.trim() != '' && snList.length == 0) {
var snArray = serialNoValue.split(',');
for(var i = 0; i < snArray.length; i++) {
if(snArray[i].trim() != '') {
snList.push({
id: snCounter++,
value: snArray[i].trim()
});
}
}
}
// 팝업 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>';
popupHtml += ' <div id="snListContainer" style="margin-bottom:15px; max-height:300px; overflow-y:auto; color:#333;"></div>';
popupHtml += ' <div style="margin-bottom:15px; display:flex; gap:5px;">';
popupHtml += ' <input type="text" id="newSnInput" placeholder="S/N 입력" style="flex:1; padding:8px; border:1px solid #ddd; border-radius:4px; color:#333;">';
popupHtml += ' <button type="button" onclick="fn_addSn()" class="plm_btns">추가</button>';
popupHtml += ' </div>';
popupHtml += ' <div style="text-align:center; margin-top:20px; display:flex; gap:10px; justify-content:center;">';
popupHtml += ' <button type="button" onclick="fn_openSequentialSnPopup()" class="plm_btns">연속번호생성</button>';
popupHtml += ' <button type="button" onclick="fn_confirmSnList()" class="plm_btns">확인</button>';
popupHtml += ' <button type="button" onclick="fn_closeSnPopup()" class="plm_btns">취소</button>';
popupHtml += ' </div>';
popupHtml += '</div>';
// 팝업 오픈
Swal.fire({
html: popupHtml,
width: '700px',
showConfirmButton: false,
showCloseButton: true,
didOpen: function() {
setTimeout(function() {
fn_renderSnList();
// 엔터키로 추가
$("#newSnInput").keypress(function(e) {
if(e.which == 13) {
fn_addSn();
return false;
}
});
}, 50);
}
});
}
// S/N 목록 렌더링
function fn_renderSnList() {
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:5px 10px; font-size:12px;">삭제</button>';
html += '</td>';
html += '</tr>';
}
}
html += '</tbody></table>';
$("#snListContainer").html(html);
}
// S/N 추가
function fn_addSn() {
var newSn = $("#newSnInput").val().trim();
if(newSn == '') {
Swal.fire("S/N을 입력해주세요.");
return;
}
// 중복 체크
for(var i = 0; i < snList.length; i++) {
if(snList[i].value == newSn) {
Swal.fire("이미 등록된 S/N입니다.");
return;
}
}
snList.push({
id: snCounter++,
value: newSn
});
$("#newSnInput").val('');
fn_renderSnList();
}
// S/N 삭제
function fn_deleteSn(id) {
for(var i = 0; i < snList.length; i++) {
if(snList[i].id == id) {
snList.splice(i, 1);
break;
}
}
fn_renderSnList();
}
// S/N 목록 확인 및 적용
function fn_confirmSnList() {
var snValues = [];
for(var i = 0; i < snList.length; i++) {
snValues.push(snList[i].value);
}
$("#SERIAL_NO").val(snValues.join(', '));
Swal.close();
}
// S/N 팝업 닫기
function fn_closeSnPopup() {
Swal.close();
}
// 연속번호 생성 팝업
function fn_openSequentialSnPopup() {
var seqHtml = '<div style="padding:10px; color:#333;">';
seqHtml += '<h3 style="margin:0 0 15px 0; text-align:center; color:#333;">연속번호 생성</h3>';
seqHtml += '<table style="width:100%; border-collapse:collapse;">';
seqHtml += '<tr><td style="padding:8px; text-align:right; width:30%;">접두어:</td>';
seqHtml += '<td style="padding:8px;"><input type="text" id="seqPrefix" style="width:100%; padding:5px;" placeholder="예: SN-"></td></tr>';
seqHtml += '<tr><td style="padding:8px; text-align:right;">시작번호:</td>';
seqHtml += '<td style="padding:8px;"><input type="number" id="seqStart" style="width:100%; padding:5px;" value="1"></td></tr>';
seqHtml += '<tr><td style="padding:8px; text-align:right;">종료번호:</td>';
seqHtml += '<td style="padding:8px;"><input type="number" id="seqEnd" style="width:100%; padding:5px;" value="10"></td></tr>';
seqHtml += '<tr><td style="padding:8px; text-align:right;">자릿수:</td>';
seqHtml += '<td style="padding:8px;"><input type="number" id="seqDigits" style="width:100%; padding:5px;" value="3" min="1" max="10"></td></tr>';
seqHtml += '</table>';
seqHtml += '<div style="text-align:center; margin-top:15px;">';
seqHtml += '<button type="button" onclick="fn_generateSequentialSn()" class="plm_btns">생성</button>';
seqHtml += '<button type="button" onclick="fn_closeSeqPopup()" class="plm_btns" style="margin-left:10px;">취소</button>';
seqHtml += '</div></div>';
Swal.fire({
html: seqHtml,
width: '400px',
showConfirmButton: false,
showCloseButton: true
});
}
// 연속번호 생성
function fn_generateSequentialSn() {
var prefix = $("#seqPrefix").val();
var start = parseInt($("#seqStart").val()) || 1;
var end = parseInt($("#seqEnd").val()) || 10;
var digits = parseInt($("#seqDigits").val()) || 3;
if(start > end) {
Swal.fire("시작번호가 종료번호보다 클 수 없습니다.");
return;
}
if(end - start > 999) {
Swal.fire("한 번에 1000개 이상 생성할 수 없습니다.");
return;
}
for(var i = start; i <= end; i++) {
var numStr = String(i).padStart(digits, '0');
var newSn = prefix + numStr;
// 중복 체크
var isDup = false;
for(var j = 0; j < snList.length; j++) {
if(snList[j].value == newSn) {
isDup = true;
break;
}
}
if(!isDup) {
snList.push({
id: snCounter++,
value: newSn
});
}
}
Swal.close();
fn_openSnManagePopup();
}
// 연속번호 팝업 닫기
function fn_closeSeqPopup() {
Swal.close();
fn_openSnManagePopup();
}
</script>
<body>
<form name="form1" id="form1" method="post">

View File

@@ -46,8 +46,9 @@ var resultGrid;
var grid;
// 입력 행 번호
var rowSeq = 0;
// M-BOM 옵션 데이터 (셀렉트박스용)
var mbomOptionsData = {};
// M-BOM 옵션 데이터 (셀렉트박스용) - 배열로 순서 보장
var mbomOptionsData = [];
var mbomOptionsMap = {};
// M-BOM 품명 데이터 (OBJID -> PART_NAME 매핑)
var mbomPartNameData = {};
@@ -81,12 +82,16 @@ $(document).ready(function(){
// M-BOM 옵션 데이터 초기화
function fn_initMbomOptions() {
mbomOptionsData = {"": "선택"};
// 배열로 순서 보장 - "선택"을 맨 위에
mbomOptionsData = [{label: "선택", value: ""}];
mbomOptionsMap = {"": "선택"};
$("#MBOM_SELECT_HIDDEN option").each(function(){
var val = $(this).val();
var text = $(this).text();
if(val !== '') {
mbomOptionsData[val] = text;
mbomOptionsData.push({label: text, value: val});
mbomOptionsMap[val] = text;
}
});
@@ -142,7 +147,7 @@ function fn_initInputGrid() {
},
formatter: function(cell) {
var value = cell.getValue();
return mbomOptionsData[value] || "";
return mbomOptionsMap[value] || "";
},
cellEdited: function(cell) {
// M-BOM 선택 시 품명 자동 입력 (MBOM_HEADER.PART_NAME 사용)

View File

@@ -46,8 +46,9 @@ var resultGrid;
var grid;
// 입력 행 번호
var rowSeq = 0;
// M-BOM 옵션 데이터 (셀렉트박스용)
var mbomOptionsData = {};
// M-BOM 옵션 데이터 (셀렉트박스용) - 배열로 순서 보장
var mbomOptionsData = [];
var mbomOptionsMap = {};
// M-BOM 품명 데이터 (OBJID -> PART_NAME 매핑)
var mbomPartNameData = {};
@@ -81,12 +82,16 @@ $(document).ready(function(){
// M-BOM 옵션 데이터 초기화
function fn_initMbomOptions() {
mbomOptionsData = {"": "선택"};
// 배열로 순서 보장 - "선택"을 맨 위에
mbomOptionsData = [{label: "선택", value: ""}];
mbomOptionsMap = {"": "선택"};
$("#MBOM_SELECT_HIDDEN option").each(function(){
var val = $(this).val();
var text = $(this).text();
if(val !== '') {
mbomOptionsData[val] = text;
mbomOptionsData.push({label: text, value: val});
mbomOptionsMap[val] = text;
}
});
@@ -142,7 +147,7 @@ function fn_initInputGrid() {
},
formatter: function(cell) {
var value = cell.getValue();
return mbomOptionsData[value] || "";
return mbomOptionsMap[value] || "";
},
cellEdited: function(cell) {
// M-BOM 선택 시 품명 자동 입력 (MBOM_HEADER.PART_NAME 사용)