Compare commits

...

2 Commits

Author SHA1 Message Date
805d0da1df 공정검사관리 검색조건 수정 2025-12-16 18:06:04 +09:00
8336def8cc 공정검사관리 수정 2025-12-16 17:33:39 +09:00
7 changed files with 409 additions and 117 deletions

View File

@@ -358,7 +358,7 @@ function fn_initRightGrid() {
}
},
{title:'검사일', field:'INSPECTION_DATE', headerHozAlign:'center', hozAlign:'center', width:100,
editor:"input"
editor:"date"
},
{title:'검사자', field:'INSPECTOR_ID', headerHozAlign:'center', hozAlign:'center', width:100,
editor: fnc_customSelectEditor,

View File

@@ -48,6 +48,7 @@ String connector = person.getUserId();
var _editable = true;
var grid;
var rowIndex = 0;
var _filePopupOpen = false; // 파일 팝업 열림 여부
// 진행공정 목록
var _PROCESS_LIST = [];
@@ -69,6 +70,8 @@ var _MEASURING_DEVICE_LIST = [
var _DEPT_LIST = [];
// 담당자 목록
var _USER_LIST = [];
// 검사자 목록
var _INSPECTOR_LIST = [];
// 검사결과 목록
var _INSPECTION_RESULT_LIST = [
{"CODE": "", "NAME": "선택"},
@@ -85,9 +88,9 @@ $(document).ready(function(){
fnc_getJsonAllDataListBySqlId({"sqlId": "common.getCodeselect", "code": "0001870"})
);
// 프로젝트 목록 조회
_PROJECT_LIST = [{"CODE": "", "NAME": "선택"}].concat(
fnc_getJsonAllDataListBySqlId({"sqlId": "common.getProjectNameList"})
// 프로젝트 목록 조회 (제품구분 포함)
_PROJECT_LIST = [{"CODE": "", "NAME": "선택", "PRODUCT_NAME": ""}].concat(
fnc_getJsonAllDataListBySqlId({"sqlId": "common.getProjectNameListWithProduct"})
);
// 담당팀 목록 조회
@@ -100,6 +103,11 @@ $(document).ready(function(){
fnc_getJsonAllDataListBySqlId({"sqlId": "common.getUserselect"})
);
// 검사자 목록 조회
_INSPECTOR_LIST = [{"CODE": "", "NAME": "선택"}].concat(
fnc_getJsonAllDataListBySqlId({"sqlId": "common.getUserselect"})
);
// 검사일 기본 설정 (저장된 값 없으면 오늘 날짜)
var savedInspectionDate = "${info.inspection_date}";
if(savedInspectionDate != '' && savedInspectionDate != 'null'){
@@ -157,6 +165,9 @@ function fn_getPartListByProject(projectNo) {
// 그리드 초기화 및 조회
function fn_search(){
// 파일 팝업이 열려있는 동안에는 새로고침 방지
if(_filePopupOpen) return;
var columns = [
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:30},
{title:'진행공정', field:'PROCESS_CD', headerHozAlign:'center', hozAlign:'center', width:130,
@@ -167,11 +178,66 @@ function fn_search(){
editorParams: {valueId:"CODE", labelId:"NAME", values:_PROCESS_LIST}
},
{title:'프로젝트번호', field:'PROJECT_OBJID', headerHozAlign:'center', hozAlign:'center', width:130,
editor: fnc_customSelectEditor,
editor: function(cell, onRendered, success, cancel, editorParams) {
var cellValue = cell.getValue();
var select = document.createElement("select");
select.style.width = "100%";
select.style.boxSizing = "border-box";
// 옵션 생성
_PROJECT_LIST.forEach(function(item) {
var option = document.createElement("option");
option.value = item.CODE;
option.text = item.NAME;
if(item.CODE == cellValue) option.selected = true;
select.appendChild(option);
});
// 선택 변경 시 즉시 적용 및 제품구분 업데이트
select.addEventListener("change", function() {
var selectedValue = select.value;
var productName = "";
// 제품구분 찾기
for(var i = 0; i < _PROJECT_LIST.length; i++) {
if(_PROJECT_LIST[i].CODE == selectedValue) {
productName = _PROJECT_LIST[i].PRODUCT_NAME || "";
break;
}
}
// 파트 목록 미리 로드
if(selectedValue) {
fn_getPartListByProject(selectedValue);
}
// 제품구분 및 파트 초기화
cell.getRow().update({
"PART_OBJID": "",
"PART_NO": "",
"PART_NAME": "",
"PRODUCT_NAME": productName
});
success(selectedValue);
});
select.addEventListener("blur", function() {
success(select.value);
});
onRendered(function() {
select.focus();
});
return select;
},
formatter: function(cell) {
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_PROJECT_LIST});
},
editorParams: {valueId:"CODE", labelId:"NAME", values:_PROJECT_LIST}
}
},
{title:'제품구분', field:'PRODUCT_NAME', headerHozAlign:'center', hozAlign:'center', width:130,
editor: false
},
{title:'품번', field:'PART_OBJID', headerHozAlign:'center', hozAlign:'left', width:250,
editor: fnc_customSelectEditor,
@@ -225,6 +291,16 @@ function fn_search(){
},
editorParams: {valueId:"CODE", labelId:"NAME", values:_USER_LIST}
},
{title:'검사일', field:'INSPECTION_DATE', headerHozAlign:'center', hozAlign:'center', width:110,
editor:"date"
},
{title:'검사자', field:'INSPECTOR_ID', headerHozAlign:'center', hozAlign:'center', width:100,
editor: fnc_customSelectEditor,
formatter: function(cell) {
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST});
},
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST}
},
{title:'특이사항', field:'REMARK', headerHozAlign:'center', hozAlign:'left', width:150,
editor:"input"
},
@@ -240,6 +316,28 @@ function fn_search(){
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST});
},
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST}
},
{title:'이미지파일', field:'IMAGE_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
formatter: fnc_subInfoValueFormatter,
cellClick: function(e, cell) {
var objId = fnc_checkNull(cell.getData().OBJID);
if(objId) {
fn_openImageFilePopUp(objId);
} else {
Swal.fire("먼저 저장 후 이미지를 등록할 수 있습니다.");
}
}
},
{title:'첨부파일', field:'ATTACH_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
formatter: fnc_subInfoValueFormatter,
cellClick: function(e, cell) {
var objId = fnc_checkNull(cell.getData().OBJID);
if(objId) {
fn_openAttachFilePopUp(objId);
} else {
Swal.fire("먼저 저장 후 파일을 등록할 수 있습니다.");
}
}
}
];
@@ -259,23 +357,6 @@ function fn_search(){
var row = cell.getRow();
var field = cell.getField();
// 프로젝트 변경 시 파트 초기화 및 목록 갱신
if (field === 'PROJECT_OBJID') {
var projectObjid = cell.getValue();
// 파트 목록 미리 로드 (캐시에 저장)
if (projectObjid) {
fn_getPartListByProject(projectObjid);
}
// 파트 초기화
row.update({
"PART_OBJID": "",
"PART_NO": "",
"PART_NAME": ""
});
// 행 다시 렌더링
row.reformat();
}
// 파트 선택 시 품번/품명 자동 설정
if (field === 'PART_OBJID') {
var partObjid = cell.getValue();
@@ -318,9 +399,11 @@ function fn_search(){
function fn_addRow(){
rowIndex++;
var newRow = {
"OBJID": fnc_createObjId(), // OBJID 미리 생성 (파일 첨부 가능하도록)
"ROW_INDEX": rowIndex,
"PROCESS_CD": "",
"PROJECT_OBJID": "",
"PRODUCT_NAME": "",
"PART_OBJID": "",
"PART_NO": "",
"PART_NAME": "",
@@ -330,9 +413,14 @@ function fn_addRow(){
"MEASURING_DEVICE": "",
"DEPT_CD": "",
"USER_ID": "",
"INSPECTION_DATE": "${today}", // 검사일 기본값: 오늘
"INSPECTOR_ID": "<%=connector%>", // 검사자 기본값: 접속자
"REMARK": "",
"ACTION_STATUS": "",
"INSPECTION_RESULT": ""
"INSPECTION_RESULT": "",
"IMAGE_FILE_CNT": 0,
"ATTACH_FILE_CNT": 0,
"GRID_STATUS": "I" // 신규 행 표시
};
grid.addRow(newRow, false);
}
@@ -362,20 +450,6 @@ function fn_deleteRow(){
// 저장
function fn_save(){
var inspectionDate = $("#INSPECTION_DATE").val();
var inspectorId = $("#INSPECTOR_ID").val();
if(inspectionDate == ''){
Swal.fire("검사일을 입력하세요.");
$("#INSPECTION_DATE").focus();
return;
}
if(inspectorId == ''){
Swal.fire("검사자를 선택하세요.");
$("#INSPECTOR_ID").focus();
return;
}
var gridData = grid.getData();
if(gridData.length == 0){
Swal.fire("저장할 데이터가 없습니다.");
@@ -407,8 +481,6 @@ function fn_save(){
type: "POST",
data: {
"MASTER_OBJID": $("#MASTER_OBJID").val(),
"INSPECTION_DATE": inspectionDate,
"INSPECTOR_ID": inspectorId,
"dataList": JSON.stringify(gridData)
},
dataType: "json",
@@ -446,6 +518,79 @@ function fn_save(){
});
}
// 이미지 파일 팝업
function fn_openImageFilePopUp(objId) {
_filePopupOpen = true; // 파일 팝업 열림 플래그 설정
var popup_width = 650;
var popup_height = 550;
var url = "/common/ImageRegistPopup.do?targetObjId=" + objId + "&docType=PROCESS_INSPECTION_IMAGE&docTypeName=공정검사이미지";
var popup = window.open(url, "imageFilePopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
// 팝업 닫힘 감지하여 해당 행의 파일 카운트만 업데이트
fn_watchPopupClose(popup, objId, 'IMAGE_FILE_CNT', 'PROCESS_INSPECTION_IMAGE');
}
// 첨부파일 팝업
function fn_openAttachFilePopUp(objId) {
_filePopupOpen = true; // 파일 팝업 열림 플래그 설정
var popup_width = 800;
var popup_height = 300;
var params = "?targetObjId=" + objId + "&docType=PROCESS_INSPECTION_FILE&docTypeName=공정검사첨부";
var url = "/common/FileRegistPopup.do" + params;
var popup = window.open(url, "attachFilePopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
// 팝업 닫힘 감지하여 해당 행의 파일 카운트만 업데이트
fn_watchPopupClose(popup, objId, 'ATTACH_FILE_CNT', 'PROCESS_INSPECTION_FILE');
}
// 팝업 닫힘 감지 및 파일 카운트 업데이트
function fn_watchPopupClose(popup, objId, fieldName, docType) {
var checkPopup = setInterval(function() {
if(popup.closed) {
clearInterval(checkPopup);
_filePopupOpen = false; // 파일 팝업 닫힘 플래그 해제
// 파일 카운트 조회 후 해당 행만 업데이트
fn_updateGridFileCnt(objId, fieldName, docType);
}
}, 500);
}
// 그리드 파일 카운트 업데이트
function fn_updateGridFileCnt(objId, fieldName, docType) {
$.ajax({
url: "/common/getFileList.do",
type: "POST",
data: { targetObjId: objId, docType: docType },
dataType: "json",
success: function(data) {
var cnt = data ? data.length : 0;
var rows = grid.getRows();
rows.forEach(function(row) {
if(row.getData().OBJID === objId) {
var updateData = {};
updateData[fieldName] = cnt;
row.update(updateData);
}
});
}
});
}
// 공통 fnc_tabulCallbackFnc 오버라이드 (이 페이지에서는 grid 사용)
function fnc_tabulCallbackFnc(objId, docType, columnField, fileCnt) {
var rows = grid.getRows();
rows.forEach(function(row) {
if(row.getData().OBJID === objId) {
var updateData = {};
var targetField = (columnField && columnField !== '') ? columnField : 'FILE_CNT';
updateData[targetField] = fileCnt;
row.update(updateData);
}
});
}
// 팝업 닫힐 때 부모 새로고침
window.addEventListener('unload', function() {
if(window.opener && window.opener.fn_search) {
@@ -468,7 +613,7 @@ window.addEventListener('unload', function() {
</div>
</div>
<div class="form-header">
<!-- <div class="form-header">
<div>
<label>검사일<span class="required">*</span></label>
<input type="text" name="INSPECTION_DATE" id="INSPECTION_DATE" class="date_icon" style="width:120px;" value="${info.inspection_date}">
@@ -480,7 +625,7 @@ window.addEventListener('unload', function() {
${code_map.inspector_id}
</select>
</div>
</div>
</div> -->
<div id="grid" style="margin: 10px;"></div>
</form>

View File

@@ -45,14 +45,13 @@ String menuName = CommonUtils.getMenuName(menuObjId, "공정검사 관리");
.select2-container .select2-selection--multiple .select2-selection__rendered {
overflow: auto !important;
}
#search_part_no + .select2-container,
#search_part_name + .select2-container {
width: 210px !important;
}
/* 검사결과 스타일 */
.inspection-ng { color: #dc3545; font-weight: bold; }
.inspection-ok { color: #28a745; font-weight: bold; }
/* 검색필터 아이템 스타일 */
.search-item { display: flex; align-items: center; gap: 5px; }
.search-item label { font-weight: bold; white-space: nowrap; min-width: 50px; }
.search-item input, .search-item select { height: 28px; }
</style>
<script type="text/javascript">
@@ -67,7 +66,12 @@ $(document).ready(function(){
fn_search();
}
});
// 품번/품명 Select2 AJAX 초기화
initPartSelect2Ajax("#search_part_no", "#search_part_name", "#search_part_objid", {
debug: false,
partNoPlaceholder: "품번 검색...",
partNamePlaceholder: "품명 검색..."
});
// 조회
$("#btnSearch").click(function(){
$("#page").val("1");
@@ -89,20 +93,25 @@ $(document).ready(function(){
// 컬럼: 검사일, 프로젝트번호, 품번, 품명, 불량수량, 작업환경상태, 측정기, 검사자, 검사결과
var columns = [
{headerHozAlign:'center', hozAlign:'center', minWidth:150, widthGrow:2, title:'프로젝트번호', field:'PROJECT_NO'},
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'제품구분', field:'PRODUCT_NAME'},
{headerHozAlign:'center', hozAlign:'left', minWidth:180, widthGrow:2, title:'품번', field:'PART_NO'},
{headerHozAlign:'center', hozAlign:'left', minWidth:200, widthGrow:3, title:'품명', field:'PART_NAME'},
{headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'검사수량 합계', field:'INSPECTION_QTY',
formatter:"money", formatterParams:{thousand:",", precision:false}
},
{headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'불량수량 합계', field:'DEFECT_QTY',
formatter:"money", formatterParams:{thousand:",", precision:false}
},
{headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'작업환경상태', field:'WORK_ENV_STATUS'},
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'측정기', field:'MEASURING_DEVICE'},
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'검사일', field:'INSPECTION_DATE',
formatter: fnc_createGridAnchorTag,
cellClick: function(e, cell){
fn_openFormPopUp(cell.getData().OBJID);
}
},
{headerHozAlign:'center', hozAlign:'center', minWidth:150, widthGrow:2, title:'프로젝트번호', field:'PROJECT_NO'},
{headerHozAlign:'center', hozAlign:'left', minWidth:180, widthGrow:2, title:'품번', field:'PART_NO'},
{headerHozAlign:'center', hozAlign:'left', minWidth:200, widthGrow:3, title:'품명', field:'PART_NAME'},
{headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'불량수량 합계', field:'DEFECT_QTY',
formatter:"money", formatterParams:{thousand:",", precision:false}
},
{headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'작업환경상태', field:'WORK_ENV_STATUS'},
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'측정기', field:'MEASURING_DEVICE'},
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사결과', field:'INSPECTION_RESULT',
formatter: function(cell, formatterParams, onRendered){
@@ -177,38 +186,81 @@ function fn_excelDownload(){
</div>
<div id="plmSearchZon">
<div style="display:flex; flex-wrap:wrap; gap:10px; align-items:center;">
<div class="search-item">
<label>검사일</label>
<input type="text" name="search_inspection_date_from" id="search_inspection_date_from" class="date_icon" style="width:110px;" autocomplete="off">
<span>~</span>
<input type="text" name="search_inspection_date_to" id="search_inspection_date_to" class="date_icon" style="width:110px;" autocomplete="off">
</div>
<div class="search-item">
<label>검사자</label>
<input type="text" name="search_inspector" id="search_inspector" style="width:120px;" autocomplete="off">
</div>
<div class="search-item">
<label>프로젝트번호</label>
<input type="text" name="search_project_no" id="search_project_no" style="width:120px;" autocomplete="off">
</div>
<div class="search-item">
<label>품번</label>
<input type="text" name="search_part_no" id="search_part_no" style="width:120px;" autocomplete="off">
</div>
<div class="search-item">
<label>품명</label>
<input type="text" name="search_part_name" id="search_part_name" style="width:120px;" autocomplete="off">
</div>
<div class="search-item">
<label>검사결과</label>
<select name="search_inspection_result" id="search_inspection_result" style="width:100px;">
<option value="">전체</option>
<option value="OK">OK</option>
<option value="NG">NG</option>
</select>
</div>
</div>
<table>
<tr>
<td><label for="">프로젝트번호</label></td>
<td>
<select name="search_project_no" id="search_project_no" style="width:215px;" class="select2" autocomplete="off">
<option value="">전체</option>
${code_map.project_no}
</select>
</td>
<td><label for="">제품구분</label></td>
<td>
<select name="productType" id="productType" style="width:150px;" class="select2" autocomplete="off">
<option value="">전체</option>
${code_map.product_cd}
</select>
</td>
<td><label>품번</label></td>
<td>
<select name="search_part_no" id="search_part_no" class="select2-part" style="">
<option value="">품번 선택</option>
</select>
<input type="hidden" name="search_part_objid" id="search_part_objid" value="">
</td>
<td><label>품명</label></td>
<td>
<select name="search_part_name" id="search_part_name" class="select2-part" style="">
<option value="">품명 선택</option>
</select>
</td>
<td><label for="">작업환경상태</label></td>
<td>
<select name="search_work_env_status" id="search_work_env_status" style="">
<option value="">전체</option>
<option value="OK">양호</option>
<option value="NG">불량</option>
</select>
</td>
<td><label for="">측정기</label></td>
<td>
<select name="search_measuring_device" id="search_measuring_device" style="">
<option value="">전체</option>
<option value="OK">양호</option>
<option value="NG">불량</option>
</select>
</td>
</tr>
<tr>
<td class=""><label>검사일</label></td>
<td>
<input type="text" name="search_inspection_date_from" id="search_inspection_date_from" style="width:100px;" autocomplete="off" value="${param.search_inspection_date_from}" class="date_icon">~
<input type="text" name="search_inspection_date_to" id="search_inspection_date_to" style="width:100px;" autocomplete="off" value="${param.search_inspection_date_to}" class="date_icon">
</td>
<td><label for="">검사자</label></td>
<td>
<select name="search_inspector" id="search_inspector" style="width:150px;" class="select2" autocomplete="off">
<option value="">전체</option>
${code_map.inspector_id}
</select>
</td>
<td><label for="">검사결과</label></td>
<td>
<select name="search_inspection_result" id="search_inspection_result" style="width:210px;">
<option value="">전체</option>
<option value="OK">OK</option>
<option value="NG">NG</option>
</select>
</td>
</tr>
</table>
</div>
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>

View File

@@ -513,6 +513,20 @@ public class QualityController {
*/
@RequestMapping("/quality/processInspectionList.do")
public String processInspectionList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
Map code_map = new HashMap();
try {
// 프로젝트번호 목록
code_map.put("project_no", commonService.bizMakeOptionList("", (String)paramMap.get("search_project_no"), "common.getProjectNameList"));
// 검사자 목록
code_map.put("inspector_id", commonService.bizMakeOptionList("", (String)paramMap.get("search_inspector"), "common.getUserselect"));
//제품구분
code_map.put("product_cd", commonService.bizMakeOptionList("0000001", (String)paramMap.get("productType"),"common.getCodeselect"));
} catch(Exception e) {
e.printStackTrace();
}
request.setAttribute("code_map", code_map);
return "/quality/processInspectionList";
}

View File

@@ -2529,7 +2529,6 @@ SELECT option_objid::VARCHAR AS CODE
</select>
<select id="getPartInfo" parameterType="map" resultType="map">
SELECT
PART_NO
@@ -2785,6 +2784,16 @@ ORDER BY COALESCE(T.REVISION, '1.0')
-->
</select>
<!-- 프로젝트 목록 조회 (제품구분 포함) -->
<select id="getProjectNameListWithProduct" parameterType="map" resultType="map">
SELECT
OBJID::VARCHAR AS CODE
,PROJECT_NO AS NAME
,CODE_NAME(PRODUCT) AS PRODUCT_NAME
FROM PROJECT_MGMT
ORDER BY SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1) DESC
</select>
<select id="getCodeselectAllLevel" parameterType="map" resultType="map">
WITH RECURSIVE V_CODE AS (
SELECT CODE_ID

View File

@@ -1012,10 +1012,35 @@
<!-- 공정검사 마스터 목록 조회 -->
<select id="getProcessInspectionList" parameterType="map" resultType="map">
SELECT PIM.OBJID
, PIM.INSPECTION_DATE
, PIM.INSPECTOR_ID
, (SELECT USER_NAME FROM USER_INFO WHERE USER_ID = PIM.INSPECTOR_ID) AS INSPECTOR_NAME
<!-- 프로젝트명 (외 N건) -->
/* 검사일 (외 N건) - 디테일 테이블에서 집계 */
, (SELECT
CASE WHEN COUNT(DISTINCT PID.INSPECTION_DATE) > 1
THEN MIN(PID.INSPECTION_DATE) || ' 외 ' || (COUNT(DISTINCT PID.INSPECTION_DATE) - 1) || '건'
WHEN COUNT(DISTINCT PID.INSPECTION_DATE) = 1
THEN MIN(PID.INSPECTION_DATE)
ELSE ''
END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID AND PID.INSPECTION_DATE IS NOT NULL AND PID.INSPECTION_DATE != ''
) AS INSPECTION_DATE
/* 검사자 (외 N건) - 디테일 테이블에서 집계 */
, (SELECT
CASE WHEN COUNT(DISTINCT PID.INSPECTOR_ID) > 1
THEN (SELECT USER_NAME FROM USER_INFO WHERE USER_ID = MIN(PID.INSPECTOR_ID)) || ' 외 ' || (COUNT(DISTINCT PID.INSPECTOR_ID) - 1) || '건'
WHEN COUNT(DISTINCT PID.INSPECTOR_ID) = 1
THEN (SELECT USER_NAME FROM USER_INFO WHERE USER_ID = MIN(PID.INSPECTOR_ID))
ELSE ''
END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID AND PID.INSPECTOR_ID IS NOT NULL AND PID.INSPECTOR_ID != ''
) AS INSPECTOR_NAME
/* 제품구분 (외 N건) */
, (SELECT
CASE WHEN COUNT(DISTINCT PID.PROJECT_OBJID) > 1
THEN (SELECT CODE_NAME(PRODUCT) FROM PROJECT_MGMT WHERE OBJID = MIN(PID.PROJECT_OBJID)) || ' 외 ' || (COUNT(DISTINCT PID.PROJECT_OBJID) - 1) || '건'
ELSE (SELECT CODE_NAME(PRODUCT) FROM PROJECT_MGMT WHERE OBJID = MIN(PID.PROJECT_OBJID))
END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
) AS PRODUCT_NAME
/* 프로젝트명 (외 N건) */
, (SELECT
CASE WHEN COUNT(DISTINCT PID.PROJECT_OBJID) > 1
THEN (SELECT PROJECT_NO FROM PROJECT_MGMT WHERE OBJID = MIN(PID.PROJECT_OBJID)) || ' 외 ' || (COUNT(DISTINCT PID.PROJECT_OBJID) - 1) || '건'
@@ -1023,7 +1048,7 @@
END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
) AS PROJECT_NO
<!-- 품번 (외 N건) -->
/* 품번 (외 N건) */
, (SELECT
CASE WHEN COUNT(*) > 1
THEN MIN(PID.PART_NO) || ' 외 ' || (COUNT(*) - 1) || '건'
@@ -1031,7 +1056,7 @@
END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
) AS PART_NO
<!-- 품명 (외 N건) -->
/* 품명 (외 N건) */
, (SELECT
CASE WHEN COUNT(*) > 1
THEN MIN(PID.PART_NAME) || ' 외 ' || (COUNT(*) - 1) || '건'
@@ -1039,56 +1064,86 @@
END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
) AS PART_NAME
<!-- 불량수량 합계 -->
, (SELECT COALESCE(SUM(PID.DEFECT_QTY), 0) FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID) AS DEFECT_QTY
<!-- 작업환경상태 (하나라도 불량이면 불량) -->
/* 검사수량 합계 */
, (SELECT COALESCE(SUM(PID.INSPECTION_QTY), 0) FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID) AS INSPECTION_QTY
/* 불량수량 합계 */
, (SELECT COALESCE(SUM(PID.DEFECT_QTY), 0) FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID) AS DEFECT_QTY
/* 작업환경상태 (하나라도 불량이면 불량) */
, (SELECT CASE WHEN COUNT(CASE WHEN PID.WORK_ENV_STATUS = '불량' THEN 1 END) > 0 THEN '불량' ELSE '양호' END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
) AS WORK_ENV_STATUS
<!-- 측정기 (하나라도 불량이면 불량) -->
/* 측정기 (하나라도 불량이면 불량) */
, (SELECT CASE WHEN COUNT(CASE WHEN PID.MEASURING_DEVICE = '불량' THEN 1 END) > 0 THEN '불량' ELSE '양호' END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
) AS MEASURING_DEVICE
<!-- 검사결과 (하나라도 NG면 NG) -->
/* 검사결과 (하나라도 NG면 NG) */
, (SELECT CASE WHEN COUNT(CASE WHEN PID.INSPECTION_RESULT = 'NG' THEN 1 END) > 0 THEN 'NG' ELSE 'OK' END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
) AS INSPECTION_RESULT
, PIM.REMARK
FROM PROCESS_INSPECTION_MASTER PIM
WHERE 1=1
/* 프로젝트번호 */
<if test="search_project_no != null and search_project_no != ''">
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = PIM.OBJID
AND PID.PROJECT_OBJID = #{search_project_no})
</if>
/* 제품구분 */
<if test="productType != null and productType != ''">
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
JOIN PROJECT_MGMT PM ON PM.OBJID = PID.PROJECT_OBJID
WHERE PID.MASTER_OBJID = PIM.OBJID
AND UPPER(PM.PROJECT_NO) LIKE UPPER('%' || #{search_project_no} || '%'))
AND PM.PRODUCT = #{productType})
</if>
<if test="search_part_no != null and search_part_no != ''">
/* 품번 */
<if test="search_part_objid != null and search_part_objid != ''">
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = PIM.OBJID
AND UPPER(PID.PART_NO) LIKE UPPER('%' || #{search_part_no} || '%'))
AND PID.PART_OBJID = #{search_part_objid})
</if>
/* 품명 */
<if test="search_part_name != null and search_part_name != ''">
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = PIM.OBJID
AND UPPER(PID.PART_NAME) LIKE UPPER('%' || #{search_part_name} || '%'))
AND PID.PART_OBJID = #{search_part_name})
</if>
/* 작업환경상태 */
<if test="search_work_env_status != null and search_work_env_status != ''">
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = PIM.OBJID
AND PID.WORK_ENV_STATUS = CASE WHEN #{search_work_env_status} = 'OK' THEN '양호' ELSE '불량' END)
</if>
/* 측정기 */
<if test="search_measuring_device != null and search_measuring_device != ''">
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = PIM.OBJID
AND PID.MEASURING_DEVICE = CASE WHEN #{search_measuring_device} = 'OK' THEN '양호' ELSE '불량' END)
</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} || '%')
)
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = PIM.OBJID
AND PID.INSPECTOR_ID = #{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 EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = PIM.OBJID
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 EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = PIM.OBJID
AND PID.INSPECTION_DATE <![CDATA[<=]]> #{search_inspection_date_to})
</if>
/* 검사결과 */
<if test="search_inspection_result != null and search_inspection_result != ''">
AND (SELECT CASE WHEN COUNT(CASE WHEN PID.INSPECTION_RESULT = 'NG' THEN 1 END) > 0 THEN 'NG' ELSE 'OK' END
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID) = #{search_inspection_result}
</if>
ORDER BY PIM.INSPECTION_DATE DESC, PIM.REG_DATE DESC
ORDER BY PIM.REG_DATE DESC
</select>
<!-- 공정검사 마스터 상세 조회 -->
@@ -1112,6 +1167,7 @@
, (SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PID.PROCESS_CD) AS PROCESS_NAME
, PID.PROJECT_OBJID
, (SELECT PROJECT_NO FROM PROJECT_MGMT WHERE OBJID = PID.PROJECT_OBJID) AS PROJECT_NO
, (SELECT CODE_NAME(PRODUCT) FROM PROJECT_MGMT WHERE OBJID = PID.PROJECT_OBJID) AS PRODUCT_NAME
, PID.PART_OBJID
, PID.PART_NO
, PID.PART_NAME
@@ -1123,9 +1179,16 @@
, (SELECT DEPT_NAME FROM DEPT_INFO WHERE OBJID::VARCHAR = PID.DEPT_CD) AS DEPT_NAME
, PID.USER_ID
, (SELECT USER_NAME FROM USER_INFO WHERE USER_ID = PID.USER_ID) AS USER_NAME
, PID.INSPECTION_DATE
, PID.INSPECTOR_ID
, (SELECT USER_NAME FROM USER_INFO WHERE USER_ID = PID.INSPECTOR_ID) AS INSPECTOR_NAME
, PID.REMARK
, PID.ACTION_STATUS
, PID.INSPECTION_RESULT
/* 이미지파일 카운트 */
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO F WHERE F.TARGET_OBJID = PID.OBJID AND F.DOC_TYPE = 'PROCESS_INSPECTION_IMAGE' AND UPPER(F.STATUS) = 'ACTIVE') AS IMAGE_FILE_CNT
/* 첨부파일 카운트 */
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO F WHERE F.TARGET_OBJID = PID.OBJID AND F.DOC_TYPE = 'PROCESS_INSPECTION_FILE' AND UPPER(F.STATUS) = 'ACTIVE') AS ATTACH_FILE_CNT
FROM PROCESS_INSPECTION_DETAIL PID
WHERE PID.MASTER_OBJID = #{MASTER_OBJID}
ORDER BY PID.REG_DATE
@@ -1176,6 +1239,8 @@
, MEASURING_DEVICE
, DEPT_CD
, USER_ID
, INSPECTION_DATE
, INSPECTOR_ID
, REMARK
, ACTION_STATUS
, INSPECTION_RESULT
@@ -1195,6 +1260,8 @@
, #{MEASURING_DEVICE}
, #{DEPT_CD}
, #{USER_ID}
, #{INSPECTION_DATE}
, #{INSPECTOR_ID}
, #{REMARK}
, #{ACTION_STATUS}
, #{INSPECTION_RESULT}
@@ -1213,6 +1280,8 @@
, MEASURING_DEVICE = #{MEASURING_DEVICE}
, DEPT_CD = #{DEPT_CD}
, USER_ID = #{USER_ID}
, INSPECTION_DATE = #{INSPECTION_DATE}
, INSPECTOR_ID = #{INSPECTOR_ID}
, REMARK = #{REMARK}
, ACTION_STATUS = #{ACTION_STATUS}
, INSPECTION_RESULT = #{INSPECTION_RESULT}

View File

@@ -888,10 +888,7 @@ public class QualityService extends BaseService{
// 수정
masterParamMap.put("OBJID", masterObjId);
sqlSession.update("quality.updateProcessInspectionMaster", masterParamMap);
// 기존 디테일 삭제 후 재등록
Map<String, Object> deleteParamMap = new HashMap<String, Object>();
deleteParamMap.put("MASTER_OBJID", masterObjId);
sqlSession.delete("quality.deleteProcessInspectionDetailByMaster", deleteParamMap);
// 디테일 삭제하지 않고 UPSERT로 처리 (파일 첨부 연동 유지)
}
// 디테일 저장
@@ -903,7 +900,11 @@ public class QualityService extends BaseService{
for(Map<String, Object> rowData : dataList){
Map<String, Object> sqlParamMap = new HashMap<String, Object>();
String detailObjId = CommonUtils.checkNull(CommonUtils.createObjId());
// 클라이언트에서 전달한 OBJID 사용 (파일 첨부 연동을 위해)
String detailObjId = CommonUtils.checkNull(rowData.get("OBJID"));
if(detailObjId.isEmpty()) {
detailObjId = CommonUtils.checkNull(CommonUtils.createObjId());
}
sqlParamMap.put("OBJID", detailObjId);
sqlParamMap.put("MASTER_OBJID", masterObjId);
@@ -918,6 +919,8 @@ public class QualityService extends BaseService{
sqlParamMap.put("MEASURING_DEVICE", CommonUtils.checkNull(rowData.get("MEASURING_DEVICE")));
sqlParamMap.put("DEPT_CD", CommonUtils.checkNull(rowData.get("DEPT_CD")));
sqlParamMap.put("USER_ID", CommonUtils.checkNull(rowData.get("USER_ID")));
sqlParamMap.put("INSPECTION_DATE", CommonUtils.checkNull(rowData.get("INSPECTION_DATE")));
sqlParamMap.put("INSPECTOR_ID", CommonUtils.checkNull(rowData.get("INSPECTOR_ID")));
sqlParamMap.put("REMARK", CommonUtils.checkNull(rowData.get("REMARK")));
sqlParamMap.put("ACTION_STATUS", CommonUtils.checkNull(rowData.get("ACTION_STATUS")));
sqlParamMap.put("INSPECTION_RESULT", CommonUtils.checkNull(rowData.get("INSPECTION_RESULT")));