Compare commits

...

2 Commits

Author SHA1 Message Date
leeheejin
122ba638a6 엑셀다운로드 수정 완료 2025-12-29 11:06:39 +09:00
leeheejin
9c27c71dbb auto commit 2025-12-29 09:25:42 +09:00
7 changed files with 401 additions and 332 deletions

View File

@@ -3969,6 +3969,17 @@
ORDER BY REGDATE DESC, MBOM_NO
</select>
<!-- M-BOM 목록 (품명 포함, 원자재소요량/반제품소요량용) -->
<select id="getMbomListWithPartName" parameterType="map" resultType="com.pms.common.UpperKeyMap">
SELECT
OBJID,
MBOM_NO,
COALESCE(PART_NAME, '') AS PART_NAME
FROM MBOM_HEADER
WHERE STATUS = 'Y'
ORDER BY REGDATE DESC, MBOM_NO
</select>
<!-- M-BOM 헤더 정보 조회 (OBJID로) -->
<select id="getMbomHeaderByObjid" parameterType="map" resultType="com.pms.common.UpperKeyMap">
SELECT

View File

@@ -4293,17 +4293,20 @@ SELECT POM.OBJID
,POM.TOTAL_PRICE
,POM.DISCOUNT_PRICE
,POM.TOTAL_SUPPLY_UNIT_PRICE
,POM.TOTAL_SUPPLY_PRICE
-- ,POM.TOTAL_SUPPLY_PRICE
,S1.TOTAL_SUPPLY_PRICE
,POM.NEGO_RATE
,POM.MULTI_MASTER_YN
,POM.MULTI_YN
,CASE WHEN POM.MULTI_MASTER_YN = 'Y' THEN '' ELSE POM.MULTI_YN END MULTI_YN_MAKED
,COALESCE(POM.FORM_TYPE, '') AS FORM_TYPE
<!-- ,S1.TOTAL_PO_QTY -->
,(SELECT SUM(ORDER_QTY::NUMERIC) FROM PURCHASE_ORDER_PART AS O WHERE POM.OBJID::VARCHAR = O.PURCHASE_ORDER_MASTER_OBJID) AS TOTAL_PO_QTY
<!--,(SELECT SUM(REAL_ORDER_QTY::NUMERIC) FROM PURCHASE_ORDER_PART AS O WHERE POM.OBJID::VARCHAR = O.PURCHASE_ORDER_MASTER_OBJID) AS TOTAL_PO_QTY -->
,S1.CUR_DELIVERY_DATE
,S1.TOTAL_DELIVERY_QTY
,S1.TOTAL_DELIVERY_PRICE
,S1.TOTAL_NOT_DELIVERY_PRICE
<!-- ,(S1.TOTAL_PO_QTY - S1.TOTAL_DELIVERY_QTY - S1.TOTAL_DEFECT_QTY) AS NON_DELIVERY_QTY -->
,((SELECT SUM(ORDER_QTY::NUMERIC) FROM PURCHASE_ORDER_PART AS O WHERE POM.OBJID::VARCHAR = O.PURCHASE_ORDER_MASTER_OBJID) - (S1.TOTAL_DELIVERY_QTY <!-- - S1.TOTAL_DEFECT_QTY --> )) AS NON_DELIVERY_QTY
<!-- ,S1.TOTAL_DEFECT_QTY -->
@@ -4355,19 +4358,23 @@ SELECT POM.OBJID
LEFT OUTER JOIN(
SELECT POP.PURCHASE_ORDER_MASTER_OBJID
,SUM(POP.ORDER_QTY::NUMERIC) AS TOTAL_PO_QTY
,MAX(DH.RECEIPT_DATE) AS CUR_DELIVERY_DATE
,SUM(DH.RECEIPT_QTY::NUMERIC) AS TOTAL_DELIVERY_QTY
,SUM(pop.partner_price::NUMERIC * DH.RECEIPT_QTY::NUMERIC) AS TOTAL_DELIVERY_PRICE
<!-- ,SUM(DH.ERROR_QTY::NUMERIC) AS TOTAL_DEFECT_QTY -->
<!-- ,MAX(DH.DELIVERY_DATE) AS CUR_DELIVERY_DATE
,SUM(DH.DELIVERY_QTY::NUMERIC) AS TOTAL_DELIVERY_QTY
,SUM(DH.DEFECT_QTY::NUMERIC) AS TOTAL_DEFECT_QTY -->
,MAX(AP_AGG.MAX_RECEIPT_DATE) AS CUR_DELIVERY_DATE
,SUM(COALESCE(AP_AGG.SUM_RECEIPT_QTY, 0)) AS TOTAL_DELIVERY_QTY
-- 발주금액 = 단가 × 발주수량
,SUM(COALESCE(POP.PARTNER_PRICE::NUMERIC, 0) * COALESCE(POP.ORDER_QTY::NUMERIC, 0)) AS TOTAL_SUPPLY_PRICE
-- 입고금액 = 단가 × 입고수량
,SUM(COALESCE(POP.PARTNER_PRICE::NUMERIC, 0) * COALESCE(AP_AGG.SUM_RECEIPT_QTY, 0)) AS TOTAL_DELIVERY_PRICE
-- 미입고금액 = 단가 × (발주수량 - 입고수량)
,SUM(COALESCE(POP.PARTNER_PRICE::NUMERIC, 0) * (COALESCE(POP.ORDER_QTY::NUMERIC, 0) - COALESCE(AP_AGG.SUM_RECEIPT_QTY, 0))) AS TOTAL_NOT_DELIVERY_PRICE
FROM PURCHASE_ORDER_PART POP
LEFT OUTER JOIN ARRIVAL_PLAN DH
ON POP.OBJID = DH.ORDER_PART_OBJID
<!-- LEFT OUTER JOIN DELIVERY_HISTORY DH -->
<!-- ON POP.PART_OBJID = DH.PART_OBJID -->
LEFT OUTER JOIN (
-- ARRIVAL_PLAN을 ORDER_PART_OBJID별로 먼저 집계
SELECT ORDER_PART_OBJID
,SUM(RECEIPT_QTY::NUMERIC) AS SUM_RECEIPT_QTY
,MAX(RECEIPT_DATE) AS MAX_RECEIPT_DATE
FROM ARRIVAL_PLAN
GROUP BY ORDER_PART_OBJID
) AP_AGG ON POP.OBJID = AP_AGG.ORDER_PART_OBJID
GROUP BY POP.PURCHASE_ORDER_MASTER_OBJID
) AS S1 ON POM.OBJID::VARCHAR = S1.PURCHASE_ORDER_MASTER_OBJID
LEFT OUTER JOIN PROJECT_MGMT AS CM

View File

@@ -1358,30 +1358,32 @@
DELETE FROM PROCESS_INSPECTION_DETAIL WHERE MASTER_OBJID = #{MASTER_OBJID}
</delete>
<!-- 공정검사 목록 조회 (엑셀용) - 상세 정보 포함 -->
<!-- 공정검사 목록 조회 (엑셀용) - 상세 정보 포함 (디테일 기준) -->
<select id="getProcessInspectionListForExcel" parameterType="map" resultType="map">
SELECT
/* 공정검사 마스터 정보 */
PIM.INSPECTION_DATE
, (SELECT U.USER_NAME FROM USER_INFO U WHERE U.USER_ID = PIM.INSPECTOR_ID) AS INSPECTOR_NAME
, PIM.REMARK AS MASTER_REMARK
/* 검사일, 검사자는 디테일에서 가져옴 */
COALESCE(PID.INSPECTION_DATE, '') AS INSPECTION_DATE
, COALESCE((SELECT U.USER_NAME FROM USER_INFO U WHERE U.USER_ID = PID.INSPECTOR_ID), '') AS INSPECTOR_NAME
, COALESCE((SELECT CODE_NAME(PM.PRODUCT) FROM PROJECT_MGMT PM WHERE PM.OBJID = PID.PROJECT_OBJID), '') AS PRODUCT_TYPE
/* 공정검사 디테일 정보 */
, (SELECT CC.CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = PID.PROCESS_CD) AS PROCESS_NAME
, (SELECT PM.PROJECT_NO FROM PROJECT_MGMT PM WHERE PM.OBJID = PID.PROJECT_OBJID) AS PROJECT_NO
, PID.PART_NO
, PID.PART_NAME
, PID.INSPECTION_QTY
, PID.DEFECT_QTY
, COALESCE((SELECT CC.CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = PID.PROCESS_CD), '') AS PROCESS_NAME
, COALESCE((SELECT PM.PROJECT_NO FROM PROJECT_MGMT PM WHERE PM.OBJID = PID.PROJECT_OBJID), '') AS PROJECT_NO
, COALESCE(PID.PART_NO, '') AS PART_NO
, COALESCE(PID.PART_NAME, '') AS PART_NAME
, COALESCE(PID.INSPECTION_QTY, 0) AS INSPECTION_QTY
, COALESCE(PID.DEFECT_QTY, 0) AS DEFECT_QTY
, CASE WHEN COALESCE(PID.INSPECTION_QTY, 0) > 0
THEN ROUND((COALESCE(PID.DEFECT_QTY, 0)::NUMERIC / PID.INSPECTION_QTY::NUMERIC) * 100, 2)
ELSE NULL END AS DEFECT_RATE
, PID.WORK_ENV_STATUS
, PID.MEASURING_DEVICE
, (SELECT DEPT_NAME FROM DEPT_INFO WHERE DEPT_CODE = PID.DEPT_CD) AS DEPT_NAME
, (SELECT U2.USER_NAME FROM USER_INFO U2 WHERE U2.USER_ID = PID.USER_ID) AS USER_NAME
, PID.REMARK AS DETAIL_REMARK
, PID.ACTION_STATUS
, PID.INSPECTION_RESULT
ELSE 0 END AS DEFECT_RATE
, COALESCE(PID.WORK_ENV_STATUS, '') AS WORK_ENV_STATUS
, COALESCE(PID.MEASURING_DEVICE, '') AS MEASURING_DEVICE
, COALESCE((SELECT DI.DEPT_NAME FROM DEPT_INFO DI WHERE DI.DEPT_CODE = PID.DEPT_CD), '') AS DEPT_NAME
, COALESCE((SELECT U2.USER_NAME FROM USER_INFO U2 WHERE U2.USER_ID = PID.USER_ID), '') AS USER_NAME
, COALESCE(PID.REMARK, '') AS DETAIL_REMARK
, COALESCE(PID.ACTION_STATUS, '') AS ACTION_STATUS
, COALESCE(NULLIF(PID.INSPECTION_RESULT, ''),
(SELECT CASE WHEN COUNT(CASE WHEN PID2.INSPECTION_RESULT = 'NG' THEN 1 END) > 0 THEN 'NG' ELSE 'OK' END
FROM PROCESS_INSPECTION_DETAIL PID2 WHERE PID2.MASTER_OBJID = PIM.OBJID), '') AS INSPECTION_RESULT
FROM PROCESS_INSPECTION_MASTER PIM
INNER JOIN PROCESS_INSPECTION_DETAIL PID ON PID.MASTER_OBJID = PIM.OBJID
WHERE 1=1
@@ -1540,96 +1542,62 @@
ORDER BY MIN(T.INSPECTION_DATE) DESC, T.INSPECTION_GROUP_ID
</select>
<!-- 반제품검사 엑셀 다운로드용 데이터 조회 (그룹화 후 쉼표로 나열) -->
<!-- 반제품검사 엑셀 다운로드용 데이터 조회 (전체 풀어서 개별 행으로) -->
<select id="getSemiProductInspectionListForExcel" parameterType="map" resultType="map">
SELECT T.INSPECTION_GROUP_ID
, MIN(T.OBJID) AS OBJID
<!-- 품명(모델명): 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.MODEL_NAME, ''), ', ' ORDER BY NULLIF(T.MODEL_NAME, '')) AS MODEL_NAME
<!-- 제품구분: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.PRODUCT_TYPE, ''), ', ' ORDER BY NULLIF(T.PRODUCT_TYPE, '')) AS PRODUCT_TYPE
<!-- 작업지시번호: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.WORK_ORDER_NO, ''), ', ' ORDER BY NULLIF(T.WORK_ORDER_NO, '')) AS WORK_ORDER_NO
<!-- 부품품번: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.PART_NO, ''), ', ' ORDER BY NULLIF(T.PART_NO, '')) AS PART_NO
<!-- 부품명: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.PART_NAME, ''), ', ' ORDER BY NULLIF(T.PART_NAME, '')) AS PART_NAME
<!-- 수량 집계 -->
, SUM(T.RECEIPT_QTY) AS RECEIPT_QTY
, SUM(T.GOOD_QTY) AS GOOD_QTY
, SUM(T.DEFECT_QTY) AS DEFECT_QTY
SELECT SPI.OBJID
, COALESCE(TO_CHAR(SPI.INSPECTION_DATE, 'YYYY-MM-DD'), TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD')) AS INSPECTION_DATE
, COALESCE((SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.INSPECTOR),
(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.WRITER), '') AS WRITER_NAME
, COALESCE(SPI.MODEL_NAME, '') AS MODEL_NAME
, COALESCE(SPI.PRODUCT_TYPE, '') AS PRODUCT_TYPE
, COALESCE(SPI.WORK_ORDER_NO, '') AS WORK_ORDER_NO
, COALESCE(SPI.PART_NO, '') AS PART_NO
, COALESCE(SPI.PART_NAME, '') AS PART_NAME
, COALESCE(SPI.RECEIPT_QTY, 0) AS RECEIPT_QTY
, COALESCE(SPI.GOOD_QTY, 0) AS GOOD_QTY
, COALESCE(SPI.DEFECT_QTY, 0) AS DEFECT_QTY
, CASE
WHEN SUM(T.RECEIPT_QTY) > 0
THEN ROUND(SUM(T.DEFECT_QTY) * 100.0 / SUM(T.RECEIPT_QTY), 2)
WHEN COALESCE(SPI.RECEIPT_QTY, 0) > 0
THEN ROUND(COALESCE(SPI.DEFECT_QTY, 0) * 100.0 / SPI.RECEIPT_QTY, 2)
ELSE 0
END AS DEFECT_RATE
, SUM(CASE WHEN T.DISPOSITION_TYPE = '수정' THEN T.DEFECT_QTY ELSE 0 END) AS REGENERATION_QTY
, SUM(T.GOOD_QTY) + SUM(CASE WHEN T.DISPOSITION_TYPE = '수정' THEN T.DEFECT_QTY ELSE 0 END) AS FINAL_GOOD_QTY
<!-- 검사일: 쉼표로 나열 -->
, STRING_AGG(DISTINCT T.INSPECTION_DATE_STR, ', ' ORDER BY T.INSPECTION_DATE_STR) AS INSPECTION_DATE
<!-- 검사자: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.WRITER_NAME, ''), ', ' ORDER BY NULLIF(T.WRITER_NAME, '')) AS WRITER_NAME
<!-- 불량유형: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.DEFECT_TYPE, ''), ', ' ORDER BY NULLIF(T.DEFECT_TYPE, '')) AS DEFECT_TYPE
<!-- 불량원인: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.DEFECT_CAUSE, ''), ', ' ORDER BY NULLIF(T.DEFECT_CAUSE, '')) AS DEFECT_CAUSE
<!-- 귀책부서: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.RESPONSIBLE_DEPT, ''), ', ' ORDER BY NULLIF(T.RESPONSIBLE_DEPT, '')) AS RESPONSIBLE_DEPT
<!-- 처리현황: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.PROCESS_STATUS, ''), ', ' ORDER BY NULLIF(T.PROCESS_STATUS, '')) AS PROCESS_STATUS
<!-- 처리결과: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.DISPOSITION_TYPE, ''), ', ' ORDER BY NULLIF(T.DISPOSITION_TYPE, '')) AS DISPOSITION_TYPE
<!-- 비고: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.REMARK, ''), ', ' ORDER BY NULLIF(T.REMARK, '')) AS REMARK
FROM (
SELECT SPI.OBJID
, COALESCE(SPI.INSPECTION_GROUP_ID, SPI.OBJID::VARCHAR) AS INSPECTION_GROUP_ID
, COALESCE(SPI.MODEL_NAME, '') AS MODEL_NAME
, COALESCE(SPI.PRODUCT_TYPE, '') AS PRODUCT_TYPE
, COALESCE(SPI.WORK_ORDER_NO, '') AS WORK_ORDER_NO
, COALESCE(SPI.PART_NO, '') AS PART_NO
, COALESCE(SPI.PART_NAME, '') AS PART_NAME
, COALESCE(SPI.RECEIPT_QTY, 0) AS RECEIPT_QTY
, COALESCE(SPI.GOOD_QTY, 0) AS GOOD_QTY
, COALESCE(SPI.DEFECT_QTY, 0) AS DEFECT_QTY
, COALESCE(TO_CHAR(SPI.INSPECTION_DATE, 'YYYY-MM-DD'), TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD')) AS INSPECTION_DATE_STR
, COALESCE((SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.INSPECTOR),
(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.WRITER), '') AS WRITER_NAME
, COALESCE(SPI.DEFECT_TYPE, '') AS DEFECT_TYPE
, COALESCE(SPI.DEFECT_CAUSE, '') AS DEFECT_CAUSE
, COALESCE(SPI.RESPONSIBLE_DEPT, '') AS RESPONSIBLE_DEPT
, COALESCE(SPI.PROCESS_STATUS, '') AS PROCESS_STATUS
, COALESCE(SPI.DISPOSITION_TYPE, '') AS DISPOSITION_TYPE
, COALESCE(SPI.REMARK, '') AS REMARK
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
WHERE 1=1
<!-- 품명(모델명) 검색 -->
<if test="search_model_name != null and search_model_name != ''">
AND UPPER(SPI.MODEL_NAME) LIKE UPPER('%' || #{search_model_name} || '%')
</if>
<!-- 작업지시번호 검색 -->
<if test="search_work_order_no != null and search_work_order_no != ''">
AND UPPER(SPI.WORK_ORDER_NO) LIKE UPPER('%' || #{search_work_order_no} || '%')
</if>
<!-- 부품품번 검색 -->
<if test="search_part_no != null and search_part_no != ''">
AND UPPER(SPI.PART_NO) LIKE UPPER('%' || #{search_part_no} || '%')
</if>
<!-- 부품명 검색 -->
<if test="search_part_name != null and search_part_name != ''">
AND UPPER(SPI.PART_NAME) LIKE UPPER('%' || #{search_part_name} || '%')
</if>
<!-- 검사일 검색 -->
<if test="search_inspection_date != null and search_inspection_date != ''">
AND TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD') = #{search_inspection_date}
</if>
<!-- 검사자 검색 -->
<if test="search_writer != null and search_writer != ''">
AND SPI.WRITER = #{search_writer}
</if>
) T
GROUP BY T.INSPECTION_GROUP_ID
ORDER BY MIN(T.INSPECTION_DATE_STR) DESC, T.INSPECTION_GROUP_ID
, CASE WHEN SPI.DISPOSITION_TYPE = '수정' THEN COALESCE(SPI.DEFECT_QTY, 0) ELSE 0 END AS REGENERATION_QTY
, COALESCE(SPI.GOOD_QTY, 0) + CASE WHEN SPI.DISPOSITION_TYPE = '수정' THEN COALESCE(SPI.DEFECT_QTY, 0) ELSE 0 END AS FINAL_GOOD_QTY
, COALESCE(SPI.DEFECT_TYPE, '') AS DEFECT_TYPE
, COALESCE(SPI.DEFECT_CAUSE, '') AS DEFECT_CAUSE
, COALESCE(SPI.RESPONSIBLE_DEPT, '') AS RESPONSIBLE_DEPT
, COALESCE(SPI.PROCESS_STATUS, '') AS PROCESS_STATUS
, COALESCE(SPI.DISPOSITION_TYPE, '') AS DISPOSITION_TYPE
, COALESCE(SPI.REMARK, '') AS REMARK
, COALESCE(SPI.DATA_TYPE, '') AS DATA_TYPE
, COALESCE(SPI.INSPECTION_GROUP_ID::VARCHAR, '') AS INSPECTION_GROUP_ID
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
WHERE 1=1
<!-- 품명(모델명) 검색 -->
<if test="search_model_name != null and search_model_name != ''">
AND UPPER(SPI.MODEL_NAME) LIKE UPPER('%' || #{search_model_name} || '%')
</if>
<!-- 작업지시번호 검색 -->
<if test="search_work_order_no != null and search_work_order_no != ''">
AND UPPER(SPI.WORK_ORDER_NO) LIKE UPPER('%' || #{search_work_order_no} || '%')
</if>
<!-- 부품품번 검색 -->
<if test="search_part_no != null and search_part_no != ''">
AND UPPER(SPI.PART_NO) LIKE UPPER('%' || #{search_part_no} || '%')
</if>
<!-- 부품명 검색 -->
<if test="search_part_name != null and search_part_name != ''">
AND UPPER(SPI.PART_NAME) LIKE UPPER('%' || #{search_part_name} || '%')
</if>
<!-- 검사일 검색 -->
<if test="search_inspection_date != null and search_inspection_date != ''">
AND TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD') = #{search_inspection_date}
</if>
<!-- 검사자 검색 -->
<if test="search_writer != null and search_writer != ''">
AND SPI.WRITER = #{search_writer}
</if>
ORDER BY SPI.INSPECTION_DATE DESC, SPI.REG_DATE DESC
</select>
<!-- 반제품검사 품명(모델명) 드롭박스 목록 (CODE, NAME 형태) -->

View File

@@ -83,6 +83,11 @@ $(document).ready(function(){
fn_registPopUp();
});
// 엑셀 다운로드
$("#btnExcel").click(function(){
fn_excelDownload();
});
fn_search();
});
@@ -169,6 +174,126 @@ function fn_openAttachFilePopUp(objId) {
fn_watchPopupClose(popup, objId, 'ATTACH_FILE_CNT', 'PROCESS_INSPECTION_FILE');
}
// 엑셀 다운로드 (전체 데이터 풀어서 - ExcelJS)
function fn_excelDownload(){
var params = {
search_project_no: $("#search_project_no").val() || "",
productType: $("#productType").val() || "",
search_part_no: $("#search_part_no").val() || "",
search_part_name: $("#search_part_name").val() || "",
search_inspection_date_from: $("#search_inspection_date_from").val() || "",
search_inspection_date_to: $("#search_inspection_date_to").val() || "",
search_inspector: $("#search_inspector").val() || "",
search_inspection_result: $("#search_inspection_result").val() || ""
};
$.ajax({
url: "/quality/getProcessInspectionListForExcel.do",
type: "POST",
data: params,
dataType: "json",
success: function(result){
console.log("엑셀 데이터:", result);
if(result && result.list && result.list.length > 0){
fn_createExcelFile(result.list);
} else {
Swal.fire("다운로드할 데이터가 없습니다.");
}
},
error: function(xhr, status, error){
console.error("엑셀 데이터 조회 실패:", error);
console.error("상태:", status);
console.error("응답:", xhr.responseText);
Swal.fire("엑셀 데이터 조회 중 오류가 발생했습니다.");
}
});
}
// ExcelJS로 엑셀 파일 생성 (전체 풀어서)
async function fn_createExcelFile(data){
try {
var pageTitle = "공정검사관리";
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet(pageTitle);
// 헤더 설정 (모든 컬럼 포함: 제품구분, 공정명, 부서, 작업자, 디테일비고, 조치현황)
var headers = ["No", "검사일", "검사자", "제품구분", "공정명", "프로젝트번호", "품번", "품명",
"검사수량", "불량수량", "불량율(%)", "작업환경상태", "측정기", "부서", "작업자", "디테일비고", "조치현황", "검사결과"];
// 열 너비 설정
var colWidths = [6, 12, 12, 15, 12, 18, 18, 22, 12, 12, 10, 14, 10, 12, 12, 15, 12, 10];
colWidths.forEach(function(width, idx){
worksheet.getColumn(idx + 1).width = width;
});
// 헤더 행 추가
var headerRow = worksheet.addRow(headers);
// 헤더 스타일 (노란색 배경)
headerRow.eachCell(function(cell){
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFFFF00' } // 노란색
};
cell.font = { bold: true };
cell.alignment = { vertical: 'middle', horizontal: 'center' };
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
});
// 데이터 추가 (모든 컬럼 포함)
data.forEach(function(item, index){
var row = worksheet.addRow([
index + 1,
item.inspection_date || item.INSPECTION_DATE || "",
item.inspector_name || item.INSPECTOR_NAME || "",
item.product_type || item.PRODUCT_TYPE || "",
item.process_name || item.PROCESS_NAME || "",
item.project_no || item.PROJECT_NO || "",
item.part_no || item.PART_NO || "",
item.part_name || item.PART_NAME || "",
item.inspection_qty || item.INSPECTION_QTY || 0,
item.defect_qty || item.DEFECT_QTY || 0,
item.defect_rate || item.DEFECT_RATE || 0,
item.work_env_status || item.WORK_ENV_STATUS || "",
item.measuring_device || item.MEASURING_DEVICE || "",
item.dept_name || item.DEPT_NAME || "",
item.user_name || item.USER_NAME || "",
item.detail_remark || item.DETAIL_REMARK || "",
item.action_status || item.ACTION_STATUS || "",
item.inspection_result || item.INSPECTION_RESULT || ""
]);
// 데이터 행 스타일
row.eachCell(function(cell){
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
});
});
// 파일명 생성
var today = new Date();
var dateStr = today.getFullYear() + ("0" + (today.getMonth()+1)).slice(-2) + ("0" + today.getDate()).slice(-2);
var fileName = pageTitle + "_" + dateStr + ".xlsx";
// 다운로드
const buffer = await workbook.xlsx.writeBuffer();
saveAs(new Blob([buffer]), fileName);
} catch(e) {
console.error("엑셀 생성 오류:", e);
Swal.fire("엑셀 파일 생성 중 오류가 발생했습니다.");
}
}
</script>
<body>
@@ -187,6 +312,7 @@ function fn_openAttachFilePopUp(objId) {
<div class="btnArea">
<input type="button" class="plm_btns" value="공정검사 등록" id="btnRegist">
<input type="button" class="plm_btns" value="조회" id="btnSearch">
<input type="button" class="plm_btns" value="Excel Download" id="btnExcel">
</div>
</div>

View File

@@ -84,9 +84,8 @@ $(document).ready(function(){
fn_search();
});
// 엑셀 다운로드 (원본 데이터 - 외 N건 풀어서)
// 엑셀 다운로드 (전체 데이터 풀어서 - ExcelJS)
function fn_excelDownload(){
// 서버에서 원본 데이터 가져오기
var params = {
search_model_name: $("#search_model_name").val() || "",
search_work_order_no: $("#search_work_order_no").val() || "",
@@ -102,132 +101,110 @@ function fn_excelDownload(){
data: params,
dataType: "json",
success: function(result){
console.log("엑셀 데이터:", result);
if(result && result.list && result.list.length > 0){
createExcelFile(result.list);
fn_createExcelFile(result.list);
} else {
Swal.fire("다운로드할 데이터가 없습니다.");
}
},
error: function(xhr, status, error){
console.error("엑셀 데이터 조회 실패:", error);
console.error("상태:", status);
console.error("응답:", xhr.responseText);
Swal.fire("엑셀 데이터 조회 중 오류가 발생했습니다.");
}
});
}
// ExcelJS로 원본 데이터 엑셀 파일 생성 (공통 스타일 적용)
async function createExcelFile(data){
var pageTitle = "반제품검사관리";
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet(pageTitle);
// 헤더 설정 (컬럼 순서 변경: 검사일, 검사자를 앞으로)
var headers = ["No", "검사일", "검사자", "품명(모델명)", "작업지시번호", "부품품번", "부품명",
"입고수량 합계", "양품수량 합계", "불량수량 합계", "불량율(%)", "재생수량 합계", "최종양품수량 합계",
"불량유형", "불량원인", "귀책부서", "처리현황", "처리결과", "비고"];
// 열 너비 설정
var colWidths = [6, 12, 12, 25, 18, 20, 25, 15, 15, 15, 12, 15, 18, 15, 15, 12, 12, 12, 20];
colWidths.forEach(function(width, idx){
worksheet.getColumn(idx + 1).width = width;
});
// 제목 행 추가
worksheet.mergeCells('A1:S1');
var titleCell = worksheet.getCell('A1');
titleCell.value = pageTitle;
titleCell.font = { size: 16, bold: true };
titleCell.alignment = { vertical: 'middle', horizontal: 'center' };
worksheet.getRow(1).height = 30;
// 빈 행 추가
worksheet.addRow([]);
// 헤더 행 추가 (3행)
var headerRow = worksheet.addRow(headers);
// 헤더 스타일 (공통 스타일: 파란색 배경, 흰색 글자)
headerRow.eachCell(function(cell){
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FF4472C4' } // 파란색
};
cell.font = {
color: { argb: 'FFFFFFFF' }, // 흰색 글자
bold: true
};
cell.alignment = {
vertical: 'middle',
horizontal: 'center',
wrapText: true
};
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
});
headerRow.height = 25;
// 데이터 추가 (컬럼 순서 변경: 검사일, 검사자를 앞으로)
data.forEach(function(item, index){
var row = worksheet.addRow([
index + 1,
item.inspection_date || item.INSPECTION_DATE || "",
item.writer_name || item.WRITER_NAME || "",
item.model_name || item.MODEL_NAME || "",
item.work_order_no || item.WORK_ORDER_NO || "",
item.part_no || item.PART_NO || "",
item.part_name || item.PART_NAME || "",
item.receipt_qty || item.RECEIPT_QTY || 0,
item.good_qty || item.GOOD_QTY || 0,
item.defect_qty || item.DEFECT_QTY || 0,
item.defect_rate || item.DEFECT_RATE || 0,
item.regeneration_qty || item.REGENERATION_QTY || 0,
item.final_good_qty || item.FINAL_GOOD_QTY || 0,
item.defect_type || item.DEFECT_TYPE || "",
item.defect_cause || item.DEFECT_CAUSE || "",
item.responsible_dept || item.RESPONSIBLE_DEPT || "",
item.process_status || item.PROCESS_STATUS || "",
item.disposition_type || item.DISPOSITION_TYPE || "",
item.remark || item.REMARK || ""
]);
// ExcelJS로 엑셀 파일 생성 (전체 풀어서)
async function fn_createExcelFile(data){
try {
var pageTitle = "반제품검사관리";
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet(pageTitle);
// 데이터 행 스타일 (테두리)
row.eachCell(function(cell, colNumber){
// 헤더 설정 (DATA_TYPE, PRODUCT_TYPE, INSPECTION_GROUP_ID 추가)
var headers = ["No", "검사일", "검사자", "품명(모델명)", "제품구분", "작업지시번호", "부품품번", "부품명",
"입고수량", "양품수량", "불량수량", "불량율(%)", "재생수량", "최종양품수량",
"불량유형", "불량원인", "귀책부서", "처리현황", "처리결과", "비고", "데이터타입", "검사그룹ID"];
// 열 너비 설정
var colWidths = [6, 12, 12, 20, 12, 15, 18, 20, 12, 12, 12, 10, 12, 14, 12, 12, 10, 10, 10, 15, 10, 15];
colWidths.forEach(function(width, idx){
worksheet.getColumn(idx + 1).width = width;
});
// 헤더 행 추가
var headerRow = worksheet.addRow(headers);
// 헤더 스타일 (노란색 배경)
headerRow.eachCell(function(cell){
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFFFF00' } // 노란색
};
cell.font = { bold: true };
cell.alignment = { vertical: 'middle', horizontal: 'center' };
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
// 숫자 컬럼 오른쪽 정렬 (8~13번 컬럼: 수량, 불량율)
if(colNumber >= 8 && colNumber <= 13){
cell.alignment = { horizontal: 'right' };
// 숫자에 천단위 구분자 (불량율 제외)
if(colNumber !== 11 && typeof cell.value === 'number'){
cell.numFmt = '#,##0';
}
} else if(colNumber === 1 || colNumber === 2 || colNumber === 3){
cell.alignment = { horizontal: 'center' };
}
});
});
// 파일명 생성
var date = new Date();
var currentDate = date.getFullYear() +
("0" + (date.getMonth() + 1)).slice(-2) +
("0" + date.getDate()).slice(-2) + "_" +
("0" + date.getHours()).slice(-2) +
("0" + date.getMinutes()).slice(-2);
var fileName = pageTitle + "_" + currentDate + ".xlsx";
// 다운로드
const buffer = await workbook.xlsx.writeBuffer();
saveAs(new Blob([buffer]), fileName);
// 데이터 추가 (DATA_TYPE, PRODUCT_TYPE, INSPECTION_GROUP_ID 추가)
data.forEach(function(item, index){
var row = worksheet.addRow([
index + 1,
item.inspection_date || item.INSPECTION_DATE || "",
item.writer_name || item.WRITER_NAME || "",
item.model_name || item.MODEL_NAME || "",
item.product_type || item.PRODUCT_TYPE || "",
item.work_order_no || item.WORK_ORDER_NO || "",
item.part_no || item.PART_NO || "",
item.part_name || item.PART_NAME || "",
item.receipt_qty || item.RECEIPT_QTY || 0,
item.good_qty || item.GOOD_QTY || 0,
item.defect_qty || item.DEFECT_QTY || 0,
item.defect_rate || item.DEFECT_RATE || 0,
item.regeneration_qty || item.REGENERATION_QTY || 0,
item.final_good_qty || item.FINAL_GOOD_QTY || 0,
item.defect_type || item.DEFECT_TYPE || "",
item.defect_cause || item.DEFECT_CAUSE || "",
item.responsible_dept || item.RESPONSIBLE_DEPT || "",
item.process_status || item.PROCESS_STATUS || "",
item.disposition_type || item.DISPOSITION_TYPE || "",
item.remark || item.REMARK || "",
item.data_type || item.DATA_TYPE || "",
item.inspection_group_id || item.INSPECTION_GROUP_ID || ""
]);
// 데이터 행 스타일
row.eachCell(function(cell){
cell.border = {
top: { style: 'thin' },
left: { style: 'thin' },
bottom: { style: 'thin' },
right: { style: 'thin' }
};
});
});
// 파일명 생성
var today = new Date();
var dateStr = today.getFullYear() + ("0" + (today.getMonth()+1)).slice(-2) + ("0" + today.getDate()).slice(-2);
var fileName = pageTitle + "_" + dateStr + ".xlsx";
// 다운로드
const buffer = await workbook.xlsx.writeBuffer();
saveAs(new Blob([buffer]), fileName);
} catch(e) {
console.error("엑셀 생성 오류:", e);
Swal.fire("엑셀 파일 생성 중 오류가 발생했습니다.");
}
}
// 컬럼: 검사일, 검사자, 품명(모델명), 작업지시번호, 부품품번, 부품명, 입고수량 합계, 양품수량 합계, 불량수량 합계, 불량율, 재생수량 합계, 최종양품수량 합계

View File

@@ -597,7 +597,7 @@ public class QualityController {
}
/**
* 공정검사 엑셀 다운로드
* 공정검사 엑셀 다운로드 (JSP 방식)
*/
@RequestMapping("/quality/processInspectionExcelDownload.do")
public String processInspectionExcelDownload(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
@@ -606,6 +606,18 @@ public class QualityController {
return "/quality/processInspectionExcel";
}
/**
* 공정검사 엑셀 데이터 조회 (AJAX JSON) - 전체 풀어서 다운로드
*/
@ResponseBody
@RequestMapping("/quality/getProcessInspectionListForExcel.do")
public Map getProcessInspectionListForExcel(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
Map result = new HashMap();
List list = service.getProcessInspectionListForExcel(paramMap);
result.put("list", list);
return result;
}
// =====================================================
// 반제품검사 관리
// =====================================================

View File

@@ -1358,30 +1358,32 @@
DELETE FROM PROCESS_INSPECTION_DETAIL WHERE MASTER_OBJID = #{MASTER_OBJID}
</delete>
<!-- 공정검사 목록 조회 (엑셀용) - 상세 정보 포함 -->
<!-- 공정검사 목록 조회 (엑셀용) - 상세 정보 포함 (디테일 기준) -->
<select id="getProcessInspectionListForExcel" parameterType="map" resultType="map">
SELECT
/* 공정검사 마스터 정보 */
PIM.INSPECTION_DATE
, (SELECT U.USER_NAME FROM USER_INFO U WHERE U.USER_ID = PIM.INSPECTOR_ID) AS INSPECTOR_NAME
, PIM.REMARK AS MASTER_REMARK
/* 검사일, 검사자는 디테일에서 가져옴 */
COALESCE(PID.INSPECTION_DATE, '') AS INSPECTION_DATE
, COALESCE((SELECT U.USER_NAME FROM USER_INFO U WHERE U.USER_ID = PID.INSPECTOR_ID), '') AS INSPECTOR_NAME
, COALESCE((SELECT CODE_NAME(PM.PRODUCT) FROM PROJECT_MGMT PM WHERE PM.OBJID = PID.PROJECT_OBJID), '') AS PRODUCT_TYPE
/* 공정검사 디테일 정보 */
, (SELECT CC.CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = PID.PROCESS_CD) AS PROCESS_NAME
, (SELECT PM.PROJECT_NO FROM PROJECT_MGMT PM WHERE PM.OBJID = PID.PROJECT_OBJID) AS PROJECT_NO
, PID.PART_NO
, PID.PART_NAME
, PID.INSPECTION_QTY
, PID.DEFECT_QTY
, COALESCE((SELECT CC.CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = PID.PROCESS_CD), '') AS PROCESS_NAME
, COALESCE((SELECT PM.PROJECT_NO FROM PROJECT_MGMT PM WHERE PM.OBJID = PID.PROJECT_OBJID), '') AS PROJECT_NO
, COALESCE(PID.PART_NO, '') AS PART_NO
, COALESCE(PID.PART_NAME, '') AS PART_NAME
, COALESCE(PID.INSPECTION_QTY, 0) AS INSPECTION_QTY
, COALESCE(PID.DEFECT_QTY, 0) AS DEFECT_QTY
, CASE WHEN COALESCE(PID.INSPECTION_QTY, 0) > 0
THEN ROUND((COALESCE(PID.DEFECT_QTY, 0)::NUMERIC / PID.INSPECTION_QTY::NUMERIC) * 100, 2)
ELSE NULL END AS DEFECT_RATE
, PID.WORK_ENV_STATUS
, PID.MEASURING_DEVICE
, (SELECT DEPT_NAME FROM DEPT_INFO WHERE DEPT_CODE = PID.DEPT_CD) AS DEPT_NAME
, (SELECT U2.USER_NAME FROM USER_INFO U2 WHERE U2.USER_ID = PID.USER_ID) AS USER_NAME
, PID.REMARK AS DETAIL_REMARK
, PID.ACTION_STATUS
, PID.INSPECTION_RESULT
ELSE 0 END AS DEFECT_RATE
, COALESCE(PID.WORK_ENV_STATUS, '') AS WORK_ENV_STATUS
, COALESCE(PID.MEASURING_DEVICE, '') AS MEASURING_DEVICE
, COALESCE((SELECT DI.DEPT_NAME FROM DEPT_INFO DI WHERE DI.DEPT_CODE = PID.DEPT_CD), '') AS DEPT_NAME
, COALESCE((SELECT U2.USER_NAME FROM USER_INFO U2 WHERE U2.USER_ID = PID.USER_ID), '') AS USER_NAME
, COALESCE(PID.REMARK, '') AS DETAIL_REMARK
, COALESCE(PID.ACTION_STATUS, '') AS ACTION_STATUS
, COALESCE(NULLIF(PID.INSPECTION_RESULT, ''),
(SELECT CASE WHEN COUNT(CASE WHEN PID2.INSPECTION_RESULT = 'NG' THEN 1 END) > 0 THEN 'NG' ELSE 'OK' END
FROM PROCESS_INSPECTION_DETAIL PID2 WHERE PID2.MASTER_OBJID = PIM.OBJID), '') AS INSPECTION_RESULT
FROM PROCESS_INSPECTION_MASTER PIM
INNER JOIN PROCESS_INSPECTION_DETAIL PID ON PID.MASTER_OBJID = PIM.OBJID
WHERE 1=1
@@ -1540,96 +1542,62 @@
ORDER BY MIN(T.INSPECTION_DATE) DESC, T.INSPECTION_GROUP_ID
</select>
<!-- 반제품검사 엑셀 다운로드용 데이터 조회 (그룹화 후 쉼표로 나열) -->
<!-- 반제품검사 엑셀 다운로드용 데이터 조회 (전체 풀어서 개별 행으로) -->
<select id="getSemiProductInspectionListForExcel" parameterType="map" resultType="map">
SELECT T.INSPECTION_GROUP_ID
, MIN(T.OBJID) AS OBJID
<!-- 품명(모델명): 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.MODEL_NAME, ''), ', ' ORDER BY NULLIF(T.MODEL_NAME, '')) AS MODEL_NAME
<!-- 제품구분: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.PRODUCT_TYPE, ''), ', ' ORDER BY NULLIF(T.PRODUCT_TYPE, '')) AS PRODUCT_TYPE
<!-- 작업지시번호: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.WORK_ORDER_NO, ''), ', ' ORDER BY NULLIF(T.WORK_ORDER_NO, '')) AS WORK_ORDER_NO
<!-- 부품품번: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.PART_NO, ''), ', ' ORDER BY NULLIF(T.PART_NO, '')) AS PART_NO
<!-- 부품명: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.PART_NAME, ''), ', ' ORDER BY NULLIF(T.PART_NAME, '')) AS PART_NAME
<!-- 수량 집계 -->
, SUM(T.RECEIPT_QTY) AS RECEIPT_QTY
, SUM(T.GOOD_QTY) AS GOOD_QTY
, SUM(T.DEFECT_QTY) AS DEFECT_QTY
SELECT SPI.OBJID
, COALESCE(TO_CHAR(SPI.INSPECTION_DATE, 'YYYY-MM-DD'), TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD')) AS INSPECTION_DATE
, COALESCE((SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.INSPECTOR),
(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.WRITER), '') AS WRITER_NAME
, COALESCE(SPI.MODEL_NAME, '') AS MODEL_NAME
, COALESCE(SPI.PRODUCT_TYPE, '') AS PRODUCT_TYPE
, COALESCE(SPI.WORK_ORDER_NO, '') AS WORK_ORDER_NO
, COALESCE(SPI.PART_NO, '') AS PART_NO
, COALESCE(SPI.PART_NAME, '') AS PART_NAME
, COALESCE(SPI.RECEIPT_QTY, 0) AS RECEIPT_QTY
, COALESCE(SPI.GOOD_QTY, 0) AS GOOD_QTY
, COALESCE(SPI.DEFECT_QTY, 0) AS DEFECT_QTY
, CASE
WHEN SUM(T.RECEIPT_QTY) > 0
THEN ROUND(SUM(T.DEFECT_QTY) * 100.0 / SUM(T.RECEIPT_QTY), 2)
WHEN COALESCE(SPI.RECEIPT_QTY, 0) > 0
THEN ROUND(COALESCE(SPI.DEFECT_QTY, 0) * 100.0 / SPI.RECEIPT_QTY, 2)
ELSE 0
END AS DEFECT_RATE
, SUM(CASE WHEN T.DISPOSITION_TYPE = '수정' THEN T.DEFECT_QTY ELSE 0 END) AS REGENERATION_QTY
, SUM(T.GOOD_QTY) + SUM(CASE WHEN T.DISPOSITION_TYPE = '수정' THEN T.DEFECT_QTY ELSE 0 END) AS FINAL_GOOD_QTY
<!-- 검사일: 쉼표로 나열 -->
, STRING_AGG(DISTINCT T.INSPECTION_DATE_STR, ', ' ORDER BY T.INSPECTION_DATE_STR) AS INSPECTION_DATE
<!-- 검사자: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.WRITER_NAME, ''), ', ' ORDER BY NULLIF(T.WRITER_NAME, '')) AS WRITER_NAME
<!-- 불량유형: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.DEFECT_TYPE, ''), ', ' ORDER BY NULLIF(T.DEFECT_TYPE, '')) AS DEFECT_TYPE
<!-- 불량원인: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.DEFECT_CAUSE, ''), ', ' ORDER BY NULLIF(T.DEFECT_CAUSE, '')) AS DEFECT_CAUSE
<!-- 귀책부서: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.RESPONSIBLE_DEPT, ''), ', ' ORDER BY NULLIF(T.RESPONSIBLE_DEPT, '')) AS RESPONSIBLE_DEPT
<!-- 처리현황: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.PROCESS_STATUS, ''), ', ' ORDER BY NULLIF(T.PROCESS_STATUS, '')) AS PROCESS_STATUS
<!-- 처리결과: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.DISPOSITION_TYPE, ''), ', ' ORDER BY NULLIF(T.DISPOSITION_TYPE, '')) AS DISPOSITION_TYPE
<!-- 비고: 쉼표로 나열 -->
, STRING_AGG(DISTINCT NULLIF(T.REMARK, ''), ', ' ORDER BY NULLIF(T.REMARK, '')) AS REMARK
FROM (
SELECT SPI.OBJID
, COALESCE(SPI.INSPECTION_GROUP_ID, SPI.OBJID::VARCHAR) AS INSPECTION_GROUP_ID
, COALESCE(SPI.MODEL_NAME, '') AS MODEL_NAME
, COALESCE(SPI.PRODUCT_TYPE, '') AS PRODUCT_TYPE
, COALESCE(SPI.WORK_ORDER_NO, '') AS WORK_ORDER_NO
, COALESCE(SPI.PART_NO, '') AS PART_NO
, COALESCE(SPI.PART_NAME, '') AS PART_NAME
, COALESCE(SPI.RECEIPT_QTY, 0) AS RECEIPT_QTY
, COALESCE(SPI.GOOD_QTY, 0) AS GOOD_QTY
, COALESCE(SPI.DEFECT_QTY, 0) AS DEFECT_QTY
, COALESCE(TO_CHAR(SPI.INSPECTION_DATE, 'YYYY-MM-DD'), TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD')) AS INSPECTION_DATE_STR
, COALESCE((SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.INSPECTOR),
(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.WRITER), '') AS WRITER_NAME
, COALESCE(SPI.DEFECT_TYPE, '') AS DEFECT_TYPE
, COALESCE(SPI.DEFECT_CAUSE, '') AS DEFECT_CAUSE
, COALESCE(SPI.RESPONSIBLE_DEPT, '') AS RESPONSIBLE_DEPT
, COALESCE(SPI.PROCESS_STATUS, '') AS PROCESS_STATUS
, COALESCE(SPI.DISPOSITION_TYPE, '') AS DISPOSITION_TYPE
, COALESCE(SPI.REMARK, '') AS REMARK
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
WHERE 1=1
<!-- 품명(모델명) 검색 -->
<if test="search_model_name != null and search_model_name != ''">
AND UPPER(SPI.MODEL_NAME) LIKE UPPER('%' || #{search_model_name} || '%')
</if>
<!-- 작업지시번호 검색 -->
<if test="search_work_order_no != null and search_work_order_no != ''">
AND UPPER(SPI.WORK_ORDER_NO) LIKE UPPER('%' || #{search_work_order_no} || '%')
</if>
<!-- 부품품번 검색 -->
<if test="search_part_no != null and search_part_no != ''">
AND UPPER(SPI.PART_NO) LIKE UPPER('%' || #{search_part_no} || '%')
</if>
<!-- 부품명 검색 -->
<if test="search_part_name != null and search_part_name != ''">
AND UPPER(SPI.PART_NAME) LIKE UPPER('%' || #{search_part_name} || '%')
</if>
<!-- 검사일 검색 -->
<if test="search_inspection_date != null and search_inspection_date != ''">
AND TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD') = #{search_inspection_date}
</if>
<!-- 검사자 검색 -->
<if test="search_writer != null and search_writer != ''">
AND SPI.WRITER = #{search_writer}
</if>
) T
GROUP BY T.INSPECTION_GROUP_ID
ORDER BY MIN(T.INSPECTION_DATE_STR) DESC, T.INSPECTION_GROUP_ID
, CASE WHEN SPI.DISPOSITION_TYPE = '수정' THEN COALESCE(SPI.DEFECT_QTY, 0) ELSE 0 END AS REGENERATION_QTY
, COALESCE(SPI.GOOD_QTY, 0) + CASE WHEN SPI.DISPOSITION_TYPE = '수정' THEN COALESCE(SPI.DEFECT_QTY, 0) ELSE 0 END AS FINAL_GOOD_QTY
, COALESCE(SPI.DEFECT_TYPE, '') AS DEFECT_TYPE
, COALESCE(SPI.DEFECT_CAUSE, '') AS DEFECT_CAUSE
, COALESCE(SPI.RESPONSIBLE_DEPT, '') AS RESPONSIBLE_DEPT
, COALESCE(SPI.PROCESS_STATUS, '') AS PROCESS_STATUS
, COALESCE(SPI.DISPOSITION_TYPE, '') AS DISPOSITION_TYPE
, COALESCE(SPI.REMARK, '') AS REMARK
, COALESCE(SPI.DATA_TYPE, '') AS DATA_TYPE
, COALESCE(SPI.INSPECTION_GROUP_ID::VARCHAR, '') AS INSPECTION_GROUP_ID
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
WHERE 1=1
<!-- 품명(모델명) 검색 -->
<if test="search_model_name != null and search_model_name != ''">
AND UPPER(SPI.MODEL_NAME) LIKE UPPER('%' || #{search_model_name} || '%')
</if>
<!-- 작업지시번호 검색 -->
<if test="search_work_order_no != null and search_work_order_no != ''">
AND UPPER(SPI.WORK_ORDER_NO) LIKE UPPER('%' || #{search_work_order_no} || '%')
</if>
<!-- 부품품번 검색 -->
<if test="search_part_no != null and search_part_no != ''">
AND UPPER(SPI.PART_NO) LIKE UPPER('%' || #{search_part_no} || '%')
</if>
<!-- 부품명 검색 -->
<if test="search_part_name != null and search_part_name != ''">
AND UPPER(SPI.PART_NAME) LIKE UPPER('%' || #{search_part_name} || '%')
</if>
<!-- 검사일 검색 -->
<if test="search_inspection_date != null and search_inspection_date != ''">
AND TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD') = #{search_inspection_date}
</if>
<!-- 검사자 검색 -->
<if test="search_writer != null and search_writer != ''">
AND SPI.WRITER = #{search_writer}
</if>
ORDER BY SPI.INSPECTION_DATE DESC, SPI.REG_DATE DESC
</select>
<!-- 반제품검사 품명(모델명) 드롭박스 목록 (CODE, NAME 형태) -->