테스트 전 저장
This commit is contained in:
@@ -1582,6 +1582,7 @@
|
||||
, COALESCE(SPI.REMARK, '') AS "REMARK"
|
||||
, SPI.DATA_TYPE AS "DATA_TYPE"
|
||||
, COALESCE(SPI.INSPECTION_GROUP_ID, '') AS "INSPECTION_GROUP_ID"
|
||||
, COALESCE(SPI.IS_LOCKED, 'N') AS "IS_LOCKED"
|
||||
<!-- 파일 카운트 조회 -->
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = SPI.OBJID AND AFI.DOC_TYPE = 'SEMI_INSPECTION_IMAGE' AND AFI.STATUS = 'Active') AS "IMAGE_FILE_CNT"
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = SPI.OBJID AND AFI.DOC_TYPE = 'SEMI_INSPECTION_NCR' AND AFI.STATUS = 'Active') AS "NCR_FILE_CNT"
|
||||
@@ -1722,6 +1723,19 @@
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 반제품검사 행 잠금 (IS_LOCKED = 'Y') -->
|
||||
<update id="lockSemiProductInspection" parameterType="map">
|
||||
UPDATE PMS_QUALITY_SEMI_PRODUCT_INSPECTION
|
||||
SET IS_LOCKED = 'Y'
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 반제품검사 데이터 삭제 (OBJID로 단건 삭제) -->
|
||||
<delete id="deleteSemiProductInspectionByObjId" parameterType="map">
|
||||
DELETE FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION
|
||||
WHERE OBJID = #{OBJID}
|
||||
</delete>
|
||||
|
||||
<!-- 반제품검사 데이터 삭제 (특정 OBJID 제외) -->
|
||||
<delete id="deleteSemiProductInspectionExcludeObjIds" parameterType="map">
|
||||
DELETE FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION
|
||||
@@ -1734,6 +1748,19 @@
|
||||
</if>
|
||||
</delete>
|
||||
|
||||
<!-- 반제품검사 데이터 삭제 (타입별, 특정 OBJID 제외) -->
|
||||
<delete id="deleteSemiProductInspectionByType" parameterType="map">
|
||||
DELETE FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION
|
||||
WHERE INSPECTION_GROUP_ID = #{INSPECTION_GROUP_ID}
|
||||
AND DATA_TYPE = #{DATA_TYPE}
|
||||
<if test="EXCLUDE_OBJIDS != null and EXCLUDE_OBJIDS.size() > 0">
|
||||
AND OBJID NOT IN
|
||||
<foreach collection="EXCLUDE_OBJIDS" item="objId" open="(" separator="," close=")">
|
||||
#{objId}
|
||||
</foreach>
|
||||
</if>
|
||||
</delete>
|
||||
|
||||
<!-- =====================================================
|
||||
고객 CS 관리
|
||||
===================================================== -->
|
||||
|
||||
@@ -232,6 +232,7 @@ String loginUserId = CommonUtils.checkNull(person.getUserId());
|
||||
<div class="btn_group">
|
||||
<button type="button" class="btn_add" id="btnAddLeft">+ 행 추가</button>
|
||||
<button type="button" class="btn_del" id="btnDelLeft">- 행 삭제</button>
|
||||
<button type="button" class="btn_save" id="btnSaveLeft" style="margin-left:10px;">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel_body">
|
||||
@@ -246,6 +247,7 @@ String loginUserId = CommonUtils.checkNull(person.getUserId());
|
||||
<div class="btn_group">
|
||||
<button type="button" class="btn_add" id="btnAddRight">+ 행 추가</button>
|
||||
<button type="button" class="btn_del" id="btnDelRight">- 행 삭제</button>
|
||||
<button type="button" class="btn_save" id="btnSaveRight" style="margin-left:10px;">저장</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel_body" id="rightPanelBody">
|
||||
@@ -311,7 +313,9 @@ $(document).ready(function(){
|
||||
}
|
||||
|
||||
// 버튼 이벤트
|
||||
$("#btnSave").click(fn_save);
|
||||
$("#btnSave").click(fn_save); // 하단 저장: 전체 DB 저장
|
||||
$("#btnSaveLeft").click(fn_saveSelectedLeft); // 좌측 저장: UI 잠금만 (DB 저장 X)
|
||||
$("#btnSaveRight").click(fn_saveSelectedRight); // 우측 저장: UI 잠금만 (DB 저장 X)
|
||||
$("#btnClose").click(function(){ window.close(); });
|
||||
$("#btnAddLeft").click(fn_addLeftRow);
|
||||
$("#btnDelLeft").click(fn_delLeftRow);
|
||||
@@ -393,6 +397,11 @@ function createSelect2Editor(options, allowClear) {
|
||||
};
|
||||
}
|
||||
|
||||
// 저장된 행인지 확인하는 함수 (편집 가능 여부 결정)
|
||||
function isEditable(cell){
|
||||
return !cell.getRow().getData().IS_SAVED;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 좌측 그리드 (양품 정보) 초기화
|
||||
// =====================================================
|
||||
@@ -400,14 +409,19 @@ function fn_initLeftGrid(){
|
||||
var columns = [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:30},
|
||||
{title:"품명(모델명)", field:"MODEL_NAME", minWidth:120, headerSort:false,
|
||||
editor: createSelect2Editor(modelNameList)
|
||||
editor: createSelect2Editor(modelNameList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"제품구분", field:"PRODUCT_TYPE", minWidth:80, headerSort:false,
|
||||
editor: createSelect2Editor(productTypeList)
|
||||
editor: createSelect2Editor(productTypeList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"작업지시번호", field:"WORK_ORDER_NO", editor:"input", minWidth:100, headerSort:false,
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"작업지시번호", field:"WORK_ORDER_NO", editor:"input", minWidth:100, headerSort:false},
|
||||
{title:"부품품번", field:"PART_NO", minWidth:100, headerSort:false,
|
||||
editor: createSelect2Editor(partNoList),
|
||||
editable: isEditable,
|
||||
cellEdited: function(cell){
|
||||
var partNo = cell.getValue();
|
||||
if(partNo){
|
||||
@@ -423,6 +437,7 @@ function fn_initLeftGrid(){
|
||||
},
|
||||
{title:"부품명", field:"PART_NAME", minWidth:120, headerSort:false,
|
||||
editor: createSelect2Editor(partNameList),
|
||||
editable: isEditable,
|
||||
cellEdited: function(cell){
|
||||
var partName = cell.getValue();
|
||||
if(partName){
|
||||
@@ -438,6 +453,7 @@ function fn_initLeftGrid(){
|
||||
},
|
||||
{title:"입고수량", field:"RECEIPT_QTY", editor:"number", hozAlign:"right", minWidth:70, headerSort:false,
|
||||
editorParams:{min:0, step:1},
|
||||
editable: isEditable,
|
||||
formatter: function(cell){
|
||||
var val = cell.getValue();
|
||||
return (val !== null && val !== undefined && val !== "") ? Number(val).toLocaleString() : "0";
|
||||
@@ -445,6 +461,7 @@ function fn_initLeftGrid(){
|
||||
},
|
||||
{title:"양품수량", field:"GOOD_QTY", editor:"number", hozAlign:"right", minWidth:70, headerSort:false,
|
||||
editorParams:{min:0, step:1},
|
||||
editable: isEditable,
|
||||
formatter: function(cell){
|
||||
var val = cell.getValue();
|
||||
return (val !== null && val !== undefined && val !== "") ? Number(val).toLocaleString() : "0";
|
||||
@@ -458,7 +475,14 @@ function fn_initLeftGrid(){
|
||||
columns: columns,
|
||||
data: [],
|
||||
placeholder: "행을 추가해주세요.",
|
||||
selectable: 1 // 단일 선택
|
||||
selectable: 1, // 단일 선택
|
||||
// 저장된 행 시각적 표시
|
||||
rowFormatter: function(row){
|
||||
if(row.getData().IS_SAVED){
|
||||
row.getElement().style.backgroundColor = "#e8f5e9"; // 연한 초록색
|
||||
row.getElement().style.color = "#555";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 행 선택 이벤트 - 해당 행의 불량 정보를 우측에 표시
|
||||
@@ -493,65 +517,72 @@ function fn_initRightGrid(){
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:30},
|
||||
{title:"불량수량", field:"DEFECT_QTY", editor:"number", hozAlign:"right", minWidth:70, headerSort:false,
|
||||
editorParams:{min:0, step:1},
|
||||
editable: isEditable,
|
||||
formatter: function(cell){
|
||||
var val = cell.getValue();
|
||||
return (val !== null && val !== undefined && val !== "") ? Number(val).toLocaleString() : "0";
|
||||
}
|
||||
},
|
||||
{title:"불량유형", field:"DEFECT_TYPE", minWidth:85, headerSort:false,
|
||||
editor: createSelect2Editor(defectTypeList)
|
||||
editor: createSelect2Editor(defectTypeList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"불량원인", field:"DEFECT_CAUSE", minWidth:90, headerSort:false,
|
||||
editor: createSelect2Editor(defectCauseList)
|
||||
editor: createSelect2Editor(defectCauseList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"귀책부서", field:"RESPONSIBLE_DEPT", minWidth:80, headerSort:false,
|
||||
editor: createSelect2Editor(responsibleDeptList)
|
||||
editor: createSelect2Editor(responsibleDeptList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"부적합보고서", field:"NCR_FILE_CNT", minWidth:75, headerSort:false, hozAlign:"center",
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
if(objId && !objId.startsWith("DEFECT_")){
|
||||
if(objId){
|
||||
fn_openNCRFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire({icon:'info', title:'알림', text:'먼저 저장 후 파일을 등록할 수 있습니다.'});
|
||||
Swal.fire({icon:'info', title:'알림', text:'행을 추가한 후 파일을 등록할 수 있습니다.'});
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:"처리현황", field:"PROCESS_STATUS", minWidth:75, headerSort:false,
|
||||
editor: createSelect2Editor(processStatusList)
|
||||
editor: createSelect2Editor(processStatusList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"이미지", field:"IMAGE_FILE_CNT", minWidth:60, headerSort:false, hozAlign:"center",
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
if(objId && !objId.startsWith("DEFECT_")){
|
||||
if(objId){
|
||||
fn_openImageFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire({icon:'info', title:'알림', text:'먼저 저장 후 이미지를 등록할 수 있습니다.'});
|
||||
Swal.fire({icon:'info', title:'알림', text:'행을 추가한 후 이미지를 등록할 수 있습니다.'});
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:"검사일", field:"INSPECTION_DATE", minWidth:100, headerSort:false,
|
||||
editor: "input",
|
||||
editorParams: { elementAttributes: { type: "date" } }
|
||||
editorParams: { elementAttributes: { type: "date" } },
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"검사자", field:"INSPECTOR", editor:"input", minWidth:70, headerSort:false},
|
||||
{title:"검사자", field:"INSPECTOR", editor:"input", minWidth:70, headerSort:false, editable: isEditable},
|
||||
{title:"처리결과", field:"DISPOSITION_TYPE", minWidth:75, headerSort:false,
|
||||
editor: createSelect2Editor(dispositionTypeList)
|
||||
editor: createSelect2Editor(dispositionTypeList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"검사성적서", field:"REPORT_FILE_CNT", minWidth:70, headerSort:false, hozAlign:"center",
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
if(objId && !objId.startsWith("DEFECT_")){
|
||||
if(objId){
|
||||
fn_openReportFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire({icon:'info', title:'알림', text:'먼저 저장 후 파일을 등록할 수 있습니다.'});
|
||||
Swal.fire({icon:'info', title:'알림', text:'행을 추가한 후 파일을 등록할 수 있습니다.'});
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:"비고", field:"REMARK", editor:"input", minWidth:100, headerSort:false}
|
||||
{title:"비고", field:"REMARK", editor:"input", minWidth:100, headerSort:false, editable: isEditable}
|
||||
];
|
||||
|
||||
rightGrid = new Tabulator("#rightGrid", {
|
||||
@@ -560,7 +591,14 @@ function fn_initRightGrid(){
|
||||
columns: columns,
|
||||
data: [],
|
||||
placeholder: "좌측에서 양품 정보를 선택하세요.",
|
||||
selectable: true
|
||||
selectable: true,
|
||||
// 저장된 행 시각적 표시
|
||||
rowFormatter: function(row){
|
||||
if(row.getData().IS_SAVED){
|
||||
row.getElement().style.backgroundColor = "#e8f5e9"; // 연한 초록색
|
||||
row.getElement().style.color = "#555";
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -608,22 +646,38 @@ function fn_clearRightGrid(){
|
||||
// 좌측 그리드 행 추가
|
||||
// =====================================================
|
||||
function fn_addLeftRow(){
|
||||
rowSeq++;
|
||||
var newRowId = "NEW_" + rowSeq;
|
||||
|
||||
leftGrid.addRow({
|
||||
ROW_ID: newRowId,
|
||||
MODEL_NAME: "",
|
||||
PRODUCT_TYPE: "",
|
||||
WORK_ORDER_NO: "",
|
||||
PART_NO: "",
|
||||
PART_NAME: "",
|
||||
RECEIPT_QTY: 0,
|
||||
GOOD_QTY: 0
|
||||
// 서버에서 OBJID 미리 생성
|
||||
$.ajax({
|
||||
url: "/quality/generateObjId.do",
|
||||
type: "POST",
|
||||
async: false,
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result){
|
||||
rowSeq++;
|
||||
var newObjId = result.OBJID;
|
||||
|
||||
leftGrid.addRow({
|
||||
ROW_ID: newObjId, // OBJID를 ROW_ID로 사용
|
||||
OBJID: newObjId, // 서버에서 생성한 실제 OBJID
|
||||
MODEL_NAME: "",
|
||||
PRODUCT_TYPE: "",
|
||||
WORK_ORDER_NO: "",
|
||||
PART_NO: "",
|
||||
PART_NAME: "",
|
||||
RECEIPT_QTY: 0,
|
||||
GOOD_QTY: 0
|
||||
});
|
||||
|
||||
// 새 행에 대한 불량 데이터 배열 초기화
|
||||
allDefectData[newObjId] = [];
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.error("OBJID 생성 실패:", error);
|
||||
Swal.fire({ icon: 'error', title: '오류', text: 'OBJID 생성에 실패했습니다.' });
|
||||
}
|
||||
});
|
||||
|
||||
// 새 행에 대한 불량 데이터 배열 초기화
|
||||
allDefectData[newRowId] = [];
|
||||
}
|
||||
|
||||
// 좌측 그리드 행 삭제
|
||||
@@ -645,13 +699,54 @@ function fn_delLeftRow(){
|
||||
cancelButtonText: '취소'
|
||||
}).then(function(result){
|
||||
if(result.isConfirmed){
|
||||
var objIdsToDelete = [];
|
||||
|
||||
selectedRows.forEach(function(row){
|
||||
var rowId = row.getData().ROW_ID;
|
||||
// 해당 행의 불량 데이터도 삭제
|
||||
delete allDefectData[rowId];
|
||||
var rowData = row.getData();
|
||||
var rowId = rowData.ROW_ID;
|
||||
var objId = rowData.OBJID;
|
||||
|
||||
// DB에 저장된 데이터면 삭제 목록에 추가
|
||||
if(objId && !String(objId).startsWith("NEW_")){
|
||||
objIdsToDelete.push(objId);
|
||||
}
|
||||
|
||||
// 해당 행의 불량 데이터도 삭제 목록에 추가
|
||||
if(allDefectData[rowId]){
|
||||
allDefectData[rowId].forEach(function(defect){
|
||||
if(defect.OBJID && !String(defect.OBJID).startsWith("DEFECT_")){
|
||||
objIdsToDelete.push(defect.OBJID);
|
||||
}
|
||||
});
|
||||
delete allDefectData[rowId];
|
||||
}
|
||||
|
||||
row.delete();
|
||||
});
|
||||
|
||||
// DB에서 삭제
|
||||
if(objIdsToDelete.length > 0){
|
||||
$.ajax({
|
||||
url: "/quality/deleteSemiProductInspection.do",
|
||||
type: "POST",
|
||||
data: { objIds: JSON.stringify(objIdsToDelete) },
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result){
|
||||
console.log("DB 삭제 완료:", objIdsToDelete.length + "건");
|
||||
if(window.opener && window.opener.fn_search){
|
||||
window.opener.fn_search();
|
||||
}
|
||||
} else {
|
||||
console.error("DB 삭제 실패:", result.msg);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.error("삭제 오류:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 우측 그리드 초기화
|
||||
selectedLeftRowId = null;
|
||||
selectedLeftRowData = null;
|
||||
@@ -669,22 +764,39 @@ function fn_addRightRow(){
|
||||
return;
|
||||
}
|
||||
|
||||
rowSeq++;
|
||||
rightGrid.addRow({
|
||||
ROW_ID: "DEFECT_" + rowSeq,
|
||||
PARENT_ROW_ID: selectedLeftRowId, // 부모(좌측) 행 ID 연결
|
||||
DEFECT_QTY: 0,
|
||||
DEFECT_TYPE: "",
|
||||
DEFECT_CAUSE: "",
|
||||
RESPONSIBLE_DEPT: "",
|
||||
NCR_FILE_CNT: 0,
|
||||
PROCESS_STATUS: "",
|
||||
IMAGE_FILE_CNT: 0,
|
||||
INSPECTION_DATE: today,
|
||||
INSPECTOR: loginUserName,
|
||||
DISPOSITION_TYPE: "",
|
||||
REPORT_FILE_CNT: 0,
|
||||
REMARK: ""
|
||||
// 서버에서 OBJID 미리 생성 (첨부파일 등록을 위해)
|
||||
$.ajax({
|
||||
url: "/quality/generateObjId.do",
|
||||
type: "POST",
|
||||
async: false,
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result){
|
||||
rowSeq++;
|
||||
rightGrid.addRow({
|
||||
OBJID: result.OBJID, // 서버에서 생성한 실제 OBJID
|
||||
ROW_ID: result.OBJID, // ROW_ID도 동일하게
|
||||
PARENT_ROW_ID: selectedLeftRowId,
|
||||
DEFECT_QTY: 0,
|
||||
DEFECT_TYPE: "",
|
||||
DEFECT_CAUSE: "",
|
||||
RESPONSIBLE_DEPT: "",
|
||||
NCR_FILE_CNT: 0,
|
||||
PROCESS_STATUS: "",
|
||||
IMAGE_FILE_CNT: 0,
|
||||
INSPECTION_DATE: today,
|
||||
INSPECTOR: loginUserName,
|
||||
DISPOSITION_TYPE: "",
|
||||
REPORT_FILE_CNT: 0,
|
||||
REMARK: ""
|
||||
});
|
||||
} else {
|
||||
Swal.fire({icon:'error', title:'오류', text:'행 추가 중 오류가 발생했습니다.'});
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
Swal.fire({icon:'error', title:'오류', text:'서버 통신 오류가 발생했습니다.'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -695,8 +807,52 @@ function fn_delRightRow(){
|
||||
Swal.fire("삭제할 행을 선택해주세요.");
|
||||
return;
|
||||
}
|
||||
selectedRows.forEach(function(row){
|
||||
row.delete();
|
||||
|
||||
Swal.fire({
|
||||
title: '삭제 확인',
|
||||
text: '선택한 불량 정보를 삭제하시겠습니까?',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: '삭제',
|
||||
cancelButtonText: '취소'
|
||||
}).then(function(result){
|
||||
if(result.isConfirmed){
|
||||
var objIdsToDelete = [];
|
||||
|
||||
selectedRows.forEach(function(row){
|
||||
var objId = row.getData().OBJID;
|
||||
// DB에 저장된 데이터면 삭제 목록에 추가
|
||||
if(objId && !String(objId).startsWith("DEFECT_")){
|
||||
objIdsToDelete.push(objId);
|
||||
}
|
||||
row.delete();
|
||||
});
|
||||
|
||||
// DB에서 삭제
|
||||
if(objIdsToDelete.length > 0){
|
||||
$.ajax({
|
||||
url: "/quality/deleteSemiProductInspection.do",
|
||||
type: "POST",
|
||||
data: { objIds: JSON.stringify(objIdsToDelete) },
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result){
|
||||
console.log("DB 삭제 완료:", objIdsToDelete.length + "건");
|
||||
if(window.opener && window.opener.fn_search){
|
||||
window.opener.fn_search();
|
||||
}
|
||||
} else {
|
||||
console.error("DB 삭제 실패:", result.msg);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.error("삭제 오류:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -730,6 +886,7 @@ function fn_openReportFilePopUp(objId) {
|
||||
fn_watchPopupClose(popup, objId, 'REPORT_FILE_CNT', 'SEMI_INSPECTION_REPORT');
|
||||
}
|
||||
|
||||
|
||||
// 팝업 닫힘 감지 및 파일 카운트 업데이트
|
||||
function fn_watchPopupClose(popup, objId, fieldName, docType) {
|
||||
var checkPopup = setInterval(function() {
|
||||
@@ -801,9 +958,11 @@ function fn_loadData(objid, inspectionGroupId){
|
||||
console.log("수정 모드 - INSPECTION_GROUP_ID:", currentInspectionGroupId);
|
||||
}
|
||||
|
||||
// 좌측 데이터에 ROW_ID 부여
|
||||
// 좌측 데이터에 ROW_ID 부여 + IS_LOCKED='Y'인 행만 수정 불가
|
||||
result.leftData.forEach(function(item, idx){
|
||||
if(!item.ROW_ID) item.ROW_ID = item.OBJID || ("EXIST_" + (idx + 1));
|
||||
// IS_LOCKED='Y'인 행만 수정 불가 (IS_SAVED=true)
|
||||
item.IS_SAVED = (item.IS_LOCKED == 'Y');
|
||||
rowSeq = Math.max(rowSeq, idx + 1);
|
||||
});
|
||||
leftGrid.setData(result.leftData);
|
||||
@@ -824,6 +983,8 @@ function fn_loadData(objid, inspectionGroupId){
|
||||
|
||||
if(!allDefectData[parentId]) allDefectData[parentId] = [];
|
||||
defect.PARENT_ROW_ID = parentId;
|
||||
// IS_LOCKED='Y'인 행만 수정 불가 (IS_SAVED=true)
|
||||
defect.IS_SAVED = (defect.IS_LOCKED == 'Y');
|
||||
allDefectData[parentId].push(defect);
|
||||
});
|
||||
}
|
||||
@@ -838,34 +999,124 @@ function fn_loadData(objid, inspectionGroupId){
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 저장
|
||||
// 좌측 행 잠금: 선택된 양품 행을 수정 불가로 변경 (DB에 잠금 상태 저장)
|
||||
// =====================================================
|
||||
function fn_save(){
|
||||
// 현재 우측 데이터 저장
|
||||
fn_saveRightGridData();
|
||||
|
||||
var leftData = leftGrid.getData();
|
||||
|
||||
if(leftData.length == 0){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '저장할 양품 정보가 없습니다.' });
|
||||
function fn_saveSelectedLeft(){
|
||||
if(!selectedLeftRowId){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '잠금할 양품 정보를 선택해주세요.' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 모든 불량 데이터 수집
|
||||
var rightData = [];
|
||||
Object.keys(allDefectData).forEach(function(leftRowId){
|
||||
var defects = allDefectData[leftRowId] || [];
|
||||
defects.forEach(function(defect){
|
||||
defect.PARENT_ROW_ID = leftRowId;
|
||||
rightData.push(defect);
|
||||
});
|
||||
// 선택된 좌측 행
|
||||
var selectedRow = leftGrid.getSelectedRows()[0];
|
||||
if(!selectedRow){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '잠금할 양품 정보를 선택해주세요.' });
|
||||
return;
|
||||
}
|
||||
|
||||
var rowData = selectedRow.getData();
|
||||
var objId = rowData.OBJID;
|
||||
|
||||
// 아직 DB에 저장되지 않은 행은 잠금 불가
|
||||
if(!objId || String(objId).startsWith("NEW_")){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '먼저 하단 저장 버튼을 눌러 DB에 저장한 후 잠금할 수 있습니다.' });
|
||||
return;
|
||||
}
|
||||
|
||||
// DB에 잠금 요청
|
||||
$.ajax({
|
||||
url: "/quality/lockSemiProductInspection.do",
|
||||
type: "POST",
|
||||
data: { objIds: JSON.stringify([objId]) },
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result){
|
||||
// UI에서도 수정 불가 처리
|
||||
selectedRow.update({ IS_SAVED: true, IS_LOCKED: 'Y' });
|
||||
Swal.fire({ icon: 'success', title: '완료', text: '양품 정보가 잠금 처리되었습니다.' });
|
||||
} else {
|
||||
Swal.fire({ icon: 'error', title: '오류', text: result.msg || '잠금 처리에 실패했습니다.' });
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
Swal.fire({ icon: 'error', title: '오류', text: '잠금 처리 중 오류가 발생했습니다.' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 우측 행 잠금: 선택된 불량 행을 수정 불가로 변경 (DB에 잠금 상태 저장)
|
||||
// =====================================================
|
||||
function fn_saveSelectedRight(){
|
||||
if(!selectedLeftRowId){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '좌측에서 양품 정보를 먼저 선택해주세요.' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 선택된 우측 행만 가져오기
|
||||
var selectedRightRows = rightGrid.getSelectedRows();
|
||||
|
||||
if(selectedRightRows.length == 0){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '잠금할 불량 정보를 선택해주세요.' });
|
||||
return;
|
||||
}
|
||||
|
||||
// DB에 저장된 행만 잠금 가능
|
||||
var objIdsToLock = [];
|
||||
var unsavedCount = 0;
|
||||
selectedRightRows.forEach(function(row){
|
||||
var objId = row.getData().OBJID;
|
||||
if(objId && !String(objId).startsWith("DEFECT_") && !String(objId).startsWith("NEW_")){
|
||||
objIdsToLock.push(objId);
|
||||
} else {
|
||||
unsavedCount++;
|
||||
}
|
||||
});
|
||||
|
||||
// 저장 확인
|
||||
if(unsavedCount > 0){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '아직 DB에 저장되지 않은 행이 ' + unsavedCount + '건 있습니다. 먼저 하단 저장 버튼을 눌러 저장해주세요.' });
|
||||
return;
|
||||
}
|
||||
|
||||
if(objIdsToLock.length == 0){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '잠금할 행이 없습니다.' });
|
||||
return;
|
||||
}
|
||||
|
||||
// DB에 잠금 요청
|
||||
$.ajax({
|
||||
url: "/quality/lockSemiProductInspection.do",
|
||||
type: "POST",
|
||||
data: { objIds: JSON.stringify(objIdsToLock) },
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result){
|
||||
// UI에서도 수정 불가 처리
|
||||
selectedRightRows.forEach(function(row){
|
||||
row.update({ IS_SAVED: true, IS_LOCKED: 'Y' });
|
||||
});
|
||||
Swal.fire({ icon: 'success', title: '완료', text: '불량 정보 ' + objIdsToLock.length + '건이 잠금 처리되었습니다.' });
|
||||
} else {
|
||||
Swal.fire({ icon: 'error', title: '오류', text: result.msg || '잠금 처리에 실패했습니다.' });
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
Swal.fire({ icon: 'error', title: '오류', text: '잠금 처리 중 오류가 발생했습니다.' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 실제 저장 실행 함수
|
||||
// saveType: 'left' (좌측만), 'right' (우측만), 'all' (전체)
|
||||
// =====================================================
|
||||
function fn_doSave(leftData, rightData, confirmMsg, saveType){
|
||||
saveType = saveType || 'all'; // 기본값은 전체 저장
|
||||
|
||||
Swal.fire({
|
||||
icon: 'question',
|
||||
title: '저장 확인',
|
||||
text: '양품 ' + leftData.length + '건, 불량 ' + rightData.length + '건을 저장하시겠습니까?',
|
||||
text: confirmMsg,
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '저장',
|
||||
cancelButtonText: '취소'
|
||||
@@ -874,7 +1125,8 @@ function fn_save(){
|
||||
var paramData = {
|
||||
leftData: JSON.stringify(leftData),
|
||||
rightData: JSON.stringify(rightData),
|
||||
INSPECTION_GROUP_ID: currentInspectionGroupId || "" // 수정 모드일 때 기존 그룹 ID 전달
|
||||
INSPECTION_GROUP_ID: currentInspectionGroupId || "",
|
||||
saveType: saveType // 저장 타입 추가
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
@@ -884,15 +1136,23 @@ function fn_save(){
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result == true || result.result == "true"){
|
||||
// 저장된 INSPECTION_GROUP_ID 유지 (다음 저장 시 같은 그룹으로 저장)
|
||||
if(result.inspectionGroupId){
|
||||
currentInspectionGroupId = result.inspectionGroupId;
|
||||
console.log("INSPECTION_GROUP_ID 설정:", currentInspectionGroupId);
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: '저장 완료',
|
||||
text: '저장되었습니다.'
|
||||
}).then(function(){
|
||||
// 부모 창 새로고침
|
||||
if(window.opener && window.opener.fn_search){
|
||||
window.opener.fn_search();
|
||||
}
|
||||
window.close();
|
||||
// 데이터 다시 로드 (OBJID 동기화를 위해)
|
||||
fn_loadData('', currentInspectionGroupId);
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
@@ -913,6 +1173,149 @@ function fn_save(){
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 저장된 행을 읽기 전용으로 마킹하는 함수
|
||||
function fn_markAsSaved(savedLeftData, savedRightData){
|
||||
// 좌측 그리드 행 업데이트
|
||||
if(savedLeftData && savedLeftData.length > 0){
|
||||
savedLeftData.forEach(function(leftItem){
|
||||
var rowId = leftItem.ROW_ID;
|
||||
var rows = leftGrid.getRows();
|
||||
rows.forEach(function(row){
|
||||
if(row.getData().ROW_ID === rowId){
|
||||
row.update({ IS_SAVED: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 우측 그리드 행 업데이트 (현재 표시된 데이터)
|
||||
if(savedRightData && savedRightData.length > 0){
|
||||
savedRightData.forEach(function(rightItem){
|
||||
var objId = rightItem.OBJID;
|
||||
var rows = rightGrid.getRows();
|
||||
rows.forEach(function(row){
|
||||
if(row.getData().OBJID === objId || row.getData().ROW_ID === rightItem.ROW_ID){
|
||||
row.update({ IS_SAVED: true });
|
||||
}
|
||||
});
|
||||
|
||||
// allDefectData에도 IS_SAVED 설정
|
||||
var parentId = rightItem.PARENT_ROW_ID;
|
||||
if(parentId && allDefectData[parentId]){
|
||||
allDefectData[parentId].forEach(function(defect){
|
||||
if(defect.OBJID === objId || defect.ROW_ID === rightItem.ROW_ID){
|
||||
defect.IS_SAVED = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 전체 저장
|
||||
// =====================================================
|
||||
function fn_save(){
|
||||
try {
|
||||
console.log("fn_save 시작");
|
||||
|
||||
// 현재 선택된 좌측 행이 있으면 우측 데이터를 allDefectData에 저장
|
||||
if(selectedLeftRowId){
|
||||
var currentRightData = rightGrid.getData();
|
||||
allDefectData[selectedLeftRowId] = currentRightData;
|
||||
console.log("현재 우측 그리드 데이터 저장:", selectedLeftRowId, currentRightData.length + "건");
|
||||
}
|
||||
|
||||
var leftData = leftGrid.getData();
|
||||
console.log("좌측 데이터 수:", leftData.length);
|
||||
|
||||
if(leftData.length == 0){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '저장할 양품 정보가 없습니다.' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 모든 불량 데이터 수집 (allDefectData에서)
|
||||
var rightData = [];
|
||||
Object.keys(allDefectData).forEach(function(leftRowId){
|
||||
var defects = allDefectData[leftRowId] || [];
|
||||
defects.forEach(function(defect){
|
||||
defect.PARENT_ROW_ID = leftRowId;
|
||||
// 좌측 데이터에서 부모 정보 찾아서 복사
|
||||
var parentLeft = leftData.find(function(l){ return l.ROW_ID == leftRowId; });
|
||||
if(parentLeft){
|
||||
defect.MODEL_NAME = parentLeft.MODEL_NAME || '';
|
||||
defect.PRODUCT_TYPE = parentLeft.PRODUCT_TYPE || '';
|
||||
defect.WORK_ORDER_NO = parentLeft.WORK_ORDER_NO || '';
|
||||
defect.PART_NO = parentLeft.PART_NO || '';
|
||||
defect.PART_NAME = parentLeft.PART_NAME || '';
|
||||
}
|
||||
rightData.push(defect);
|
||||
});
|
||||
});
|
||||
console.log("우측 데이터 수:", rightData.length);
|
||||
|
||||
// 바로 저장 실행 (확인 팝업 생략)
|
||||
console.log("저장 시작 - currentInspectionGroupId:", currentInspectionGroupId);
|
||||
console.log("좌측 데이터:", leftData);
|
||||
console.log("우측 데이터:", rightData);
|
||||
|
||||
var paramData = {
|
||||
leftData: JSON.stringify(leftData),
|
||||
rightData: JSON.stringify(rightData),
|
||||
INSPECTION_GROUP_ID: currentInspectionGroupId || "",
|
||||
saveType: "all"
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: "/quality/saveSemiProductInspection.do",
|
||||
type: "POST",
|
||||
data: paramData,
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
console.log("저장 결과:", result);
|
||||
if(result.result == true || result.result == "true"){
|
||||
// 저장된 INSPECTION_GROUP_ID 유지
|
||||
if(result.inspectionGroupId){
|
||||
currentInspectionGroupId = result.inspectionGroupId;
|
||||
console.log("INSPECTION_GROUP_ID 설정:", currentInspectionGroupId);
|
||||
}
|
||||
|
||||
// 저장된 행에 IS_SAVED 플래그 설정
|
||||
fn_markAsSaved(leftData, rightData);
|
||||
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: '저장 완료',
|
||||
text: '저장되었습니다.'
|
||||
}).then(function(){
|
||||
if(window.opener && window.opener.fn_search){
|
||||
window.opener.fn_search();
|
||||
}
|
||||
window.close();
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: '저장 실패',
|
||||
text: result.msg || '저장에 실패했습니다.'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.error("AJAX 오류:", error);
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: '오류 발생',
|
||||
text: '저장 중 오류가 발생했습니다: ' + error
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
console.error("fn_save 오류:", e);
|
||||
alert("저장 중 오류 발생: " + e.message);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user