확인전 커밋

This commit is contained in:
leeheejin
2025-12-16 14:52:19 +09:00
parent a0d806d42b
commit 140d87bb82
10 changed files with 2981 additions and 212 deletions

View File

@@ -544,11 +544,14 @@
EFFECTIVE_DATE,
PAYMENT_TERMS,
REMARK,
REQUEST_CONTENT,
WRITER,
REGDATE,
STATUS,
SALES_REQUEST_OBJID,
SALES_MNG_USER_ID
SALES_MNG_USER_ID,
SALES_MNG_USER_ID2,
FORM_TYPE
,TITLE
,PURCHASE_DATE
,CONTRACT_MGMT_OBJID
@@ -562,6 +565,7 @@
,TOTAL_REAL_SUPPLY_PRICE
,DISCOUNT_PRICE
,TOTAL_PRICE
,TOTAL_PRICE_ALL
,NEGO_RATE
,SUPPLY_BUS_NO
,SUPPLY_USER_NAME
@@ -597,14 +601,17 @@
#{EFFECTIVE_DATE},
#{PAYMENT_TERMS},
#{REMARK},
#{REQUEST_CONTENT},
#{WRITER},
NOW(),
#{STATUS},
#{SALES_REQUEST_OBJID},
#{SALES_MNG_USER_ID}
#{SALES_MNG_USER_ID},
#{SALES_MNG_USER_ID2},
#{FORM_TYPE}
,#{TITLE}
,#{PURCHASE_DATE}
,#{CONTRACT_MGMT_OBJID}::NUMERIC
,#{CONTRACT_MGMT_OBJID}
,#{TYPE }
,#{INSPECT_METHOD }
,#{TOTAL_PRICE_TXT }
@@ -615,6 +622,7 @@
,#{TOTAL_REAL_SUPPLY_PRICE}
,#{DISCOUNT_PRICE }
,#{TOTAL_PRICE }
,#{TOTAL_PRICE_ALL }
,#{NEGO_RATE }
,#{SUPPLY_BUS_NO }
,#{SUPPLY_USER_NAME }
@@ -650,12 +658,17 @@
EFFECTIVE_DATE = #{EFFECTIVE_DATE},
PAYMENT_TERMS = #{PAYMENT_TERMS},
REMARK = #{REMARK},
REQUEST_CONTENT = #{REQUEST_CONTENT},
WRITER = #{WRITER},
STATUS = #{STATUS},
SALES_MNG_USER_ID = #{SALES_MNG_USER_ID}
SALES_MNG_USER_ID = #{SALES_MNG_USER_ID},
SALES_MNG_USER_ID2 = #{SALES_MNG_USER_ID2}
<if test="FORM_TYPE != null and FORM_TYPE != ''">
,FORM_TYPE = #{FORM_TYPE}
</if>
,TITLE = #{TITLE}
,PURCHASE_DATE = #{PURCHASE_DATE}
,CONTRACT_MGMT_OBJID = #{CONTRACT_MGMT_OBJID}::NUMERIC
,CONTRACT_MGMT_OBJID = #{CONTRACT_MGMT_OBJID}
,TYPE = #{TYPE }
,INSPECT_METHOD = #{INSPECT_METHOD }
,TOTAL_PRICE_TXT = #{TOTAL_PRICE_TXT }
@@ -669,6 +682,7 @@
,TOTAL_REAL_SUPPLY_PRICE = #{TOTAL_REAL_SUPPLY_PRICE}
,DISCOUNT_PRICE = #{DISCOUNT_PRICE }
,TOTAL_PRICE = #{TOTAL_PRICE }
,TOTAL_PRICE_ALL = #{TOTAL_PRICE_ALL }
,NEGO_RATE = #{NEGO_RATE }
,SUPPLY_BUS_NO = #{SUPPLY_BUS_NO }
,SUPPLY_USER_NAME = #{SUPPLY_USER_NAME }
@@ -736,7 +750,8 @@
REGDATE,
STATUS,
SALES_REQUEST_OBJID,
SALES_MNG_USER_ID
SALES_MNG_USER_ID,
FORM_TYPE
,TITLE
,PURCHASE_DATE
,CONTRACT_MGMT_OBJID
@@ -775,7 +790,8 @@
NOW(),
'create',
#{SALES_REQUEST_OBJID},
#{SALES_MNG_USER_ID}
#{SALES_MNG_USER_ID},
#{FORM_TYPE}
,#{TITLE}
,#{PURCHASE_DATE}
,NULLIF(#{PROJECT_NO}::TEXT, '')::NUMERIC
@@ -813,7 +829,7 @@
SALES_MNG_USER_ID = #{SALES_MNG_USER_ID}
,TITLE = #{TITLE}
,PURCHASE_DATE = #{PURCHASE_DATE}
,CONTRACT_MGMT_OBJID = NULLIF(#{CONTRACT_MGMT_OBJID}::TEXT, '')::NUMERIC
,CONTRACT_MGMT_OBJID = #{CONTRACT_MGMT_OBJID}
,TYPE = #{TYPE }
,INSPECT_METHOD = #{INSPECT_METHOD }
,TOTAL_PRICE_TXT = #{TOTAL_PRICE_TXT }
@@ -970,7 +986,7 @@
#{SALES_MNG_USER_ID}
,#{TITLE}
,#{PURCHASE_DATE}
,#{CONTRACT_MGMT_OBJID}::NUMERIC
,#{CONTRACT_MGMT_OBJID}
,#{TYPE }
,#{INSPECT_METHOD }
,#{TOTAL_PRICE_TXT }
@@ -1157,6 +1173,10 @@
,STOCK_QTY
,REAL_ORDER_QTY
,REAL_SUPPLY_PRICE
,PART_DELIVERY_PLACE
,PRODUCT_NAME
,WORK_ORDER_NO
,DELIVERY_REQUEST_DATE
)
VALUES
(
@@ -1196,6 +1216,10 @@
,REPLACE(#{STOCK_QTY} ::VARCHAR, ',', '')
,REPLACE(#{REAL_ORDER_QTY} ::VARCHAR, ',', '')
,REPLACE(#{REAL_SUPPLY_PRICE} ::VARCHAR, ',', '')
,#{PART_DELIVERY_PLACE}
,#{PRODUCT_NAME}
,#{WORK_ORDER_NO}
,#{DELIVERY_REQUEST_DATE}
) ON CONFLICT (OBJID) DO
UPDATE
SET
@@ -1223,6 +1247,10 @@
,STOCK_QTY = REPLACE(#{STOCK_QTY} ::VARCHAR, ',', '')
,REAL_ORDER_QTY = REPLACE(#{REAL_ORDER_QTY} ::VARCHAR, ',', '')
,REAL_SUPPLY_PRICE = REPLACE(#{REAL_SUPPLY_PRICE} ::VARCHAR, ',', '')
,PART_DELIVERY_PLACE = #{PART_DELIVERY_PLACE}
,PRODUCT_NAME = #{PRODUCT_NAME}
,WORK_ORDER_NO = #{WORK_ORDER_NO}
,DELIVERY_REQUEST_DATE = #{DELIVERY_REQUEST_DATE}
</update>
<select id="getMyCompanyInfo" parameterType="map" resultType="map">
@@ -1377,6 +1405,22 @@
,(SELECT PURCHASE_ORDER_NO FROM PURCHASE_ORDER_MASTER SPOM WHERE SPOM.OBJID = POM.PURCHASE_ORDER_NO_ORG) PURCHASE_ORDER_NO_ORG_NO
,POM.SALES_STATUS
,POM.RECEPTION_STATUS
-- 담당자1 정보 (일반발주서용)
,(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID) AS MANAGER_NAME
,(SELECT POSITION_NAME FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID) AS MANAGER_POSITION
,(SELECT CELL_PHONE FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID) AS MANAGER_PHONE
,(SELECT EMAIL FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID) AS MANAGER_EMAIL
-- 담당자2 정보 (일반발주서용)
,POM.SALES_MNG_USER_ID2
,(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID2) AS MANAGER_NAME2
,(SELECT POSITION_NAME FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID2) AS MANAGER_POSITION2
,(SELECT CELL_PHONE FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID2) AS MANAGER_PHONE2
,(SELECT EMAIL FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID2) AS MANAGER_EMAIL2
-- 요청사항
,POM.REQUEST_CONTENT
FROM
PURCHASE_ORDER_MASTER POM
@@ -2059,6 +2103,7 @@
WHERE OBJID = #{OBJID}
</update>
<!-- 자재(RESOURCE_MNG) 생성 - 중복 시 무시 -->
<insert id="insertResourceMasterMng" parameterType="map">
INSERT INTO RESOURCE_MNG
(
@@ -2074,24 +2119,21 @@
REGDATE,
WRITER
)
SELECT
VALUES
(
#{OBJID}::NUMERIC,
#{PART_OBJID},
#{LD_PART_OBJID},
(SELECT PM.PART_NAME FROM PART_MNG PM WHERE 1=1 AND PM.OBJID::VARCHAR = #{PART_OBJID}::VARCHAR),
(SELECT PM.PART_NAME FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = #{PART_OBJID}::VARCHAR),
#{SPEC},
(SELECT PM.MATERIAL FROM PART_MNG PM WHERE 1=1 AND PM.OBJID::VARCHAR = #{PART_OBJID}::VARCHAR),
(SELECT PM.MATERIAL FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = #{PART_OBJID}::VARCHAR),
#{MAKER},
#{UNIT},
(SELECT PM.WEIGHT FROM PART_MNG PM WHERE 1=1 AND PM.OBJID::VARCHAR = #{PART_OBJID}::VARCHAR),
(SELECT PM.WEIGHT FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = #{PART_OBJID}::VARCHAR),
NOW(),
#{WRITER}
WHERE
NOT EXISTS(
SELECT 1 FROM RESOURCE_MNG WHERE PART_OBJID = #{PART_OBJID}
UNION ALL
SELECT 1 FROM RESOURCE_MNG WHERE LD_PART_OBJID = #{LD_PART_OBJID}
)
)
ON CONFLICT (PART_OBJID) DO NOTHING
</insert>
<!-- 마지막 재고 정보를 가져온다. -->
@@ -2227,6 +2269,8 @@
,(SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = T.UNIT) AS UNIT_NAME
,P.PART_NO P_PART_NO
,POM.BOM_REPORT_OBJID
,POM.PURCHASE_ORDER_NO
,(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::varchar = POM.PARTNER_OBJID) AS PARTNER_NAME
FROM PURCHASE_ORDER_PART T
INNER JOIN PURCHASE_ORDER_MASTER POM
ON POM.OBJID = T.PURCHASE_ORDER_MASTER_OBJID
@@ -2376,25 +2420,20 @@
WHERE OBJID = #{objId} OR MULTI_MASTER_OBJID = #{objId}
</delete>
<!-- 공급처 정보 조회 (CLIENT_MNG 테이블) -->
<select id="purchaseOrderAdminSupplyInfo" parameterType="map" resultType="map">
SELECT
T1.OBJID
,T1.BUS_REG_NO AS SUPPLY_BUS_NO
,(CASE WHEN T2.OBJID IS NULL THEN T1.CHARGE_USER_NAME ELSE T2.CHARGER_NAME END) AS SUPPLY_USER_NAME
,(CASE WHEN T2.OBJID IS NULL THEN T1.SUPPLY_TEL_NO ELSE T2.PHONE END) AS SUPPLY_USER_HP
,(CASE WHEN T2.OBJID IS NULL THEN T1.OFFICE_NO ELSE T2.TEL END) AS SUPPLY_USER_TEL
,(CASE WHEN T2.OBJID IS NULL THEN T1.SUPPLY_FAX_NO ELSE T2.FAX END) AS SUPPLY_USER_FAX
,(CASE WHEN T2.OBJID IS NULL THEN T1.EMAIL ELSE T2.EMAIL END) AS SUPPLY_USER_EMAIL
,T1.SUPPLY_ADDRESS AS SUPPLY_ADDR
FROM ADMIN_SUPPLY_MNG AS T1
LEFT OUTER JOIN
(SELECT * FROM (SELECT DENSE_RANK() OVER(PARTITION BY T.SUPPLY_OBJID ORDER BY T.CHARGER_NAME ASC) AS TOP, T.*
FROM SUPPLY_CHARGER_MNG T WHERE CHARGER_TYPE = '0000330' /*발주서공급처담당*/
) AS T WHERE TOP = 1
) AS T2
ON T1.OBJID = T2.SUPPLY_OBJID::NUMERIC
,T1.CEO_NM AS SUPPLY_USER_NAME
,T1.VENDOR_MOBILE AS SUPPLY_USER_HP
,T1.TEL_NO AS SUPPLY_USER_TEL
,T1.FAX_NO AS SUPPLY_USER_FAX
,T1.EMAIL AS SUPPLY_USER_EMAIL
,CONCAT(COALESCE(T1.ADDR1,''), ' ', COALESCE(T1.ADDR2,'')) AS SUPPLY_ADDR
FROM CLIENT_MNG AS T1
WHERE 1=1
AND T1.OBJID = #{PARTNER_OBJID}::NUMERIC
AND T1.OBJID::VARCHAR = #{PARTNER_OBJID}::VARCHAR
</select>
<select id="purchaseOrderSalesBomPartListByPartnerContract" parameterType="map" resultType="map">
@@ -3164,10 +3203,11 @@ SELECT POM.OBJID
,(SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = POM.TYPE) AS TYPE_NAME
,POM.PARTNER_OBJID
,CASE
,(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = POM.PARTNER_OBJID) AS PARTNER_NAME
<!-- ,CASE
WHEN POM.PARTNER_OBJID LIKE 'C_%' THEN (SELECT CLIENT_NM FROM CLIENT_MNG WHERE 'C_' || OBJID::VARCHAR = POM.PARTNER_OBJID)
ELSE (SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE 1=1 AND OBJID::VARCHAR = POM.PARTNER_OBJID)
END AS PARTNER_NAME
END AS PARTNER_NAME -->
,POM.SALES_MNG_USER_ID
,(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID) AS SALES_MNG_USER_NAME
@@ -3196,6 +3236,7 @@ SELECT POM.OBJID
,POM.MAIL_SEND_YN
,POM.MAIL_SEND_DATE
,POM.STATUS
,COALESCE(POM.FORM_TYPE, 'general') AS FORM_TYPE
,A.APPR_STATUS
,CASE WHEN POM.STATUS = 'cancel' then '취소'
ELSE COALESCE(A.APPR_STATUS_NAME,'작성중')
@@ -3265,7 +3306,7 @@ SELECT POM.OBJID
ON POM.CONTRACT_MGMT_OBJID = CM.OBJID
left outer join SALES_REQUEST_MASTER as SRM
on POM.SALES_REQUEST_OBJID = SRM.OBJID
-- and SRM.DOC_TYPE = 'PROPOSAL' -- DOC_TYPE 컬럼 없음, 주석처리
and SRM.DOC_TYPE = 'PROPOSAL'
<!-- 230907 outer join으로 변경
,PROJECT_MGMT AS CM
WHERE POM.CONTRACT_MGMT_OBJID = CM.OBJID
@@ -3647,7 +3688,7 @@ SELECT OBJID
, FILE_SIZE
, FILE_EXT
, UPPER(FILE_EXT) UPPER_FILE_EXT
, REPLACE(FILE_PATH, '\', '\\') AS FILE_PATH
, REPLACE(FILE_PATH, '\', '/') AS FILE_PATH
, WRITER
, (SELECT USER_NAME FROM USER_INFO USER_INFO_T WHERE USER_INFO_T.USER_ID = WRITER) AS USER_NAME
, (SELECT DEPT_NAME FROM USER_INFO USER_INFO_T WHERE USER_INFO_T.USER_ID = WRITER) AS DEPT_NAME
@@ -4202,10 +4243,29 @@ SELECT POM.OBJID
,POM.DELIVERY_DATE
,POM.PARTNER_OBJID
,CASE
WHEN POM.PARTNER_OBJID LIKE 'C_%' THEN (SELECT CLIENT_NM FROM CLIENT_MNG WHERE 'C_' || OBJID::VARCHAR = POM.PARTNER_OBJID)
ELSE (SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE 1=1 AND OBJID::VARCHAR = POM.PARTNER_OBJID)
END AS PARTNER_NAME
,(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = POM.PARTNER_OBJID) AS PARTNER_NAME
<!-- 품의서 번호 -->
,POM.SALES_REQUEST_OBJID
,(SELECT REQUEST_MNG_NO FROM SALES_REQUEST_MASTER WHERE OBJID::VARCHAR = POM.SALES_REQUEST_OBJID) AS PROPOSAL_NO
<!-- 품번/품명 (첫번째 + 외 N건) -->
,(SELECT
CASE
WHEN COUNT(*) > 1 THEN MIN(POP.PART_NO) || ' 외 ' || (COUNT(*) - 1) || '건'
ELSE MIN(POP.PART_NO)
END
FROM PURCHASE_ORDER_PART POP
WHERE POP.PURCHASE_ORDER_MASTER_OBJID = POM.OBJID::VARCHAR
) AS PART_NO
,(SELECT
CASE
WHEN COUNT(*) > 1 THEN MIN(POP.PART_NAME) || ' 외 ' || (COUNT(*) - 1) || '건'
ELSE MIN(POP.PART_NAME)
END
FROM PURCHASE_ORDER_PART POP
WHERE POP.PURCHASE_ORDER_MASTER_OBJID = POM.OBJID::VARCHAR
) AS PART_NAME
,POM.SALES_MNG_USER_ID
,(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = POM.SALES_MNG_USER_ID) AS SALES_MNG_USER_NAME
@@ -4227,9 +4287,9 @@ SELECT POM.OBJID
<!-- ,S1.TOTAL_DEFECT_QTY -->
<!-- ,(CASE WHEN 0 <![CDATA[ >= ]]> ((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)) THEN '입고완료' -->
<!-- ,((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 -->
,((SELECT SUM(REAL_ORDER_QTY::NUMERIC) FROM PURCHASE_ORDER_PART AS O WHERE POM.OBJID::VARCHAR = O.PURCHASE_ORDER_MASTER_OBJID) - (S1.TOTAL_DELIVERY_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 )) AS NON_DELIVERY_QTY
<!-- ,S1.TOTAL_DEFECT_QTY -->
,(CASE WHEN 0 <![CDATA[ >= ]]> ((SELECT SUM(REAL_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 -->)) THEN '입고완료'
,(CASE WHEN 0 <![CDATA[ >= ]]> ((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 -->)) THEN '입고완료'
WHEN TO_CHAR(NOW(),'YYYY-MM-DD') <![CDATA[ > ]]> POM.DELIVERY_DATE THEN '지연'
ELSE '입고중'
END) AS DELIVERY_STATUS
@@ -4238,6 +4298,7 @@ SELECT POM.OBJID
,POM.ORDER_TYPE_CD
,(SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = POM.ORDER_TYPE_CD) AS ORDER_TYPE_CD_NAME
,(SELECT user_name(RECEIVER_ID) FROM ARRIVAL_PLAN AP WHERE AP.parent_objid = POM.OBJID ORDER BY AP.RECEIPT_DATE desc LIMIT 1) AS CUR_RECEIVER_NAME
,(SELECT COUNT(1) FROM ATTACH_FILE_INFO AF WHERE AF.TARGET_OBJID = POM.OBJID AND AF.DOC_TYPE = 'INSPECTION_FILE' AND UPPER(AF.STATUS) = 'ACTIVE') AS INSPECTION_FILE_CNT
<!-- ,A.APPR_STATUS_NAME -->
FROM PURCHASE_ORDER_MASTER AS POM
<!-- LEFT OUTER JOIN(
@@ -6008,4 +6069,26 @@ FROM(
WHERE OBJID = #{OBJID}
</update>
<!-- 입고관리 데이터 드롭다운용 조회 (반제품검사 팝업에서 사용) -->
<!-- ARRIVAL_PLAN 테이블에서 입고완료된 품목 조회 (1차+2차 합산) -->
<select id="getDeliveryListForDropdown" parameterType="map" resultType="map">
SELECT
AP.ORDER_PART_OBJID AS OBJID
,AP.PART_OBJID
,COALESCE(CASE WHEN POM.TYPE IN ('0001070','0001069') THEN PM.PART_NO ELSE POP.PART_NO END, PM.PART_NO, '') AS PART_NO
,COALESCE(POP.PART_NAME, PM.PART_NAME, '') AS PART_NAME
,COALESCE(POP.PART_NAME, PM.PART_NAME, '') AS MODEL_NAME
,COALESCE(POM.PURCHASE_ORDER_NO, '') AS WORK_ORDER_NO
,COALESCE(SUM(AP.RECEIPT_QTY::NUMERIC), 0) AS RECEIPT_QTY
FROM ARRIVAL_PLAN AP
LEFT JOIN PURCHASE_ORDER_PART POP ON POP.OBJID = AP.ORDER_PART_OBJID
LEFT JOIN PART_MNG PM ON PM.OBJID::VARCHAR = AP.PART_OBJID OR PM.OBJID = POP.PART_OBJID
LEFT JOIN PURCHASE_ORDER_MASTER POM ON POM.OBJID = AP.PARENT_OBJID
WHERE AP.RECEIPT_QTY IS NOT NULL
AND AP.RECEIPT_QTY::NUMERIC > 0
AND AP.INVENTORY_STATUS = 'Y'
GROUP BY AP.ORDER_PART_OBJID, AP.PART_OBJID, POP.PART_NO, POP.PART_NAME, PM.PART_NO, PM.PART_NAME, POM.PURCHASE_ORDER_NO, POM.TYPE
ORDER BY PART_NO
</select>
</mapper>

File diff suppressed because it is too large Load Diff

View File

@@ -6,85 +6,669 @@
<%@include file= "/init.jsp" %>
<%
String menuObjId = request.getParameter("menuObjId");
String menuName = CommonUtils.getMenuName(menuObjId, "반제품검사 등록");
String menuName = CommonUtils.getMenuName(menuObjId, "반제품검사");
String OBJID = CommonUtils.checkNull(request.getParameter("OBJID"));
String INSPECTION_GROUP_ID = CommonUtils.checkNull(request.getParameter("INSPECTION_GROUP_ID"));
String WORK_ORDER_NO = CommonUtils.checkNull(request.getParameter("WORK_ORDER_NO"));
String actionType = CommonUtils.checkNull(request.getParameter("actionType"));
Map info = (Map)request.getAttribute("info");
// 로그인 사용자 정보
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
String loginUserName = CommonUtils.checkNull(person.getUserName());
String loginUserId = CommonUtils.checkNull(person.getUserId());
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><%=Constants.SYSTEM_NAME%></title>
<title><%=Constants.SYSTEM_NAME%></title>
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
<link href="/css/select2/select2.min.css" rel="stylesheet">
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
<script type="text/javascript" src="/js/select2/select2.min.js"></script>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
font-family: 'Malgun Gothic', sans-serif;
}
.popup_wrap {
display: flex;
flex-direction: column;
height: 100vh;
}
.popup_header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background: #f5f5f5;
border-bottom: 1px solid #ddd;
}
.popup_header h2 {
margin: 0;
font-size: 16px;
font-weight: bold;
}
.popup_content {
display: flex;
flex: 1;
overflow: hidden;
}
/* 왼쪽 영역 */
.left_section {
width: 50%;
display: flex;
flex-direction: column;
border-right: 2px solid #ccc;
padding: 10px;
box-sizing: border-box;
}
/* 오른쪽 영역 */
.right_section {
width: 50%;
display: flex;
flex-direction: column;
padding: 10px;
box-sizing: border-box;
}
.section_header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
padding-bottom: 5px;
border-bottom: 1px solid #e0e0e0;
}
.section_header h3 {
margin: 0;
font-size: 14px;
font-weight: bold;
color: #333;
}
.section_header .btn_area {
display: flex;
gap: 5px;
}
.grid_wrap {
flex: 1;
overflow: hidden;
}
/* 버튼 스타일 */
.btn_add {
padding: 4px 12px;
background: #4CAF50;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
}
.btn_add:hover {
background: #45a049;
}
.btn_del {
padding: 4px 12px;
background: #f44336;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
}
.btn_del:hover {
background: #da190b;
}
.btn_save {
padding: 6px 20px;
background: #2196F3;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 13px;
font-weight: bold;
}
.btn_save:hover {
background: #1976D2;
}
.btn_close {
padding: 6px 20px;
background: #757575;
color: white;
border: none;
border-radius: 3px;
cursor: pointer;
font-size: 13px;
font-weight: bold;
}
.btn_close:hover {
background: #616161;
}
/* 헤더 버튼 영역 */
.header_btns {
display: flex;
gap: 8px;
}
/* Tabulator 편집 가능 셀 스타일 */
.tabulator .tabulator-cell.editable-cell {
background-color: #fffde7;
}
/* Select2 스타일 */
.select2-container--open {
z-index: 9999 !important;
}
.select2-results__option {
font-size: 12px;
}
</style>
</head>
<body>
<div class="popup_wrap">
<!-- 헤더 -->
<div class="popup_header">
<h2><%=menuName%></h2>
<div class="header_btns">
<button type="button" class="btn_save" id="btnSave">저장</button>
<button type="button" class="btn_close" id="btnClose">닫기</button>
</div>
</div>
<!-- 컨텐츠 영역 -->
<div class="popup_content">
<!-- 왼쪽 영역: 양품 정보 (입고관리에서 가져옴) -->
<div class="left_section">
<div class="section_header">
<h3>양품 정보 (입고관리)</h3>
<div class="btn_area">
<button type="button" class="btn_add" onclick="fn_addLeftRow()">행추가</button>
<button type="button" class="btn_del" onclick="fn_delLeftRow()">행삭제</button>
</div>
</div>
<div class="grid_wrap" id="leftGridWrap"></div>
</div>
<!-- 오른쪽 영역: 불량 정보 -->
<div class="right_section">
<div class="section_header">
<h3>불량 정보</h3>
<div class="btn_area">
<button type="button" class="btn_add" onclick="fn_addRightRow()">행추가</button>
<button type="button" class="btn_del" onclick="fn_delRightRow()">행삭제</button>
</div>
</div>
<div class="grid_wrap" id="rightGridWrap"></div>
</div>
</div>
</div>
<script type="text/javascript">
var leftGrid; // 왼쪽 그리드 (양품 정보)
var rightGrid; // 오른쪽 그리드 (불량 정보)
var rowSeq = 0; // 행 시퀀스
// 로그인 사용자 정보
var loginUserName = "<%=loginUserName%>";
var loginUserId = "<%=loginUserId%>";
// 입고관리 데이터 (드롭박스용)
var deliveryDataList = []; // 전체 입고관리 데이터
var modelNameList = []; // 품명(모델명) 목록
var partNoList = []; // 부품품번 목록
var partNameList = []; // 부품명 목록
// 코드 목록 (드롭박스용)
var productTypeList = ["Machine", "A/S", "D/S", "S/A", "기타"]; // 제품구분
var defectTypeList = ["외관불량", "치수불량", "기능불량", "재료불량", "조립불량", "도장불량", "용접불량", "기타"]; // 불량유형
var defectCauseList = ["작업자 실수", "설비 이상", "자재 불량", "설계 오류", "공정 이상", "환경 요인", "기타"]; // 불량원인
var responsibleDeptList = ["사용자 정보(부서)", "구매", "생산기술", "제조1팀", "제조2팀", "제조3팀", "연구소", "외주업체", "품질"]; // 귀책부서
var processStatusList = ["Rework", "Scrap"]; // 처리현황
var dispositionTypeList = ["특채", "수정", "폐기"]; // 처리결과
$(document).ready(function(){
// 저장
// 입고관리 데이터 로드
fn_loadDeliveryData();
// 그리드 초기화
fn_initLeftGrid();
fn_initRightGrid();
// 기존 데이터 로드 (수정 모드인 경우)
var objid = "<%=OBJID%>";
var inspectionGroupId = "<%=INSPECTION_GROUP_ID%>";
if((objid && objid != "") || (inspectionGroupId && inspectionGroupId != "")){
fn_loadData(objid, inspectionGroupId);
}
// 저장 버튼
$("#btnSave").click(function(){
fn_save();
});
// 닫기
// 닫기 버튼
$("#btnClose").click(function(){
window.close();
});
});
// 입고관리 데이터 로드
function fn_loadDeliveryData(){
$.ajax({
url: "/purchaseOrder/getDeliveryListForDropdown.do",
type: "POST",
async: false,
dataType: "json",
success: function(result){
if(result && result.list){
deliveryDataList = result.list;
// 중복 제거하여 각 목록 생성
var modelSet = {};
var partNoSet = {};
var partNameSet = {};
deliveryDataList.forEach(function(item){
if(item.MODEL_NAME && item.MODEL_NAME != '') modelSet[item.MODEL_NAME] = item;
if(item.PART_NO && item.PART_NO != '') partNoSet[item.PART_NO] = item;
if(item.PART_NAME && item.PART_NAME != '') partNameSet[item.PART_NAME] = item;
});
modelNameList = Object.keys(modelSet);
partNoList = Object.keys(partNoSet);
partNameList = Object.keys(partNameSet);
console.log("입고관리 데이터 로드 완료:", deliveryDataList.length + "건");
}
},
error: function(xhr, status, error){
console.error("입고관리 데이터 로드 실패:", error);
}
});
}
// Select2 에디터 생성 함수
function createSelect2Editor(options, allowClear) {
return function(cell, onRendered, success, cancel, editorParams) {
var cellValue = cell.getValue() || '';
var container = document.createElement("span");
var select = document.createElement("select");
select.style.width = "100%";
// 빈 옵션 추가
var emptyOption = document.createElement("option");
emptyOption.value = "";
emptyOption.text = "선택";
select.appendChild(emptyOption);
// 옵션 추가
options.forEach(function(opt) {
var option = document.createElement("option");
option.value = opt;
option.text = opt;
if(opt == cellValue) {
option.selected = true;
}
select.appendChild(option);
});
container.appendChild(select);
onRendered(function() {
$(select).select2({
width: '100%',
dropdownAutoWidth: true,
placeholder: '선택',
allowClear: allowClear !== false,
dropdownParent: $('body')
});
$(select).on('select2:select select2:clear', function(e) {
success($(select).val() || '');
});
// Select2 열기
$(select).select2('open');
});
return container;
};
}
// 왼쪽 그리드 초기화 (양품 정보 - 입고관리 연동)
function fn_initLeftGrid(){
var columns = [
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:30},
{title:"품명(모델명)", field:"MODEL_NAME", minWidth:130, headerSort:false,
editor: createSelect2Editor(modelNameList)
},
{title:"제품구분", field:"PRODUCT_TYPE", minWidth:80, headerSort:false,
editor: createSelect2Editor(productTypeList)
},
{title:"작업지시번호", field:"WORK_ORDER_NO", editor:"input", minWidth:110, headerSort:false},
{title:"부품품번", field:"PART_NO", minWidth:110, headerSort:false,
editor: createSelect2Editor(partNoList),
cellEdited: function(cell){
// 부품품번 선택 시 관련 데이터 자동 입력
var partNo = cell.getValue();
if(partNo){
var matched = deliveryDataList.find(function(d){ return d.PART_NO == partNo; });
if(matched){
cell.getRow().update({
PART_NAME: matched.PART_NAME || '',
RECEIPT_QTY: matched.RECEIPT_QTY || matched.DELIVERY_QTY || ''
});
}
}
}
},
{title:"부품명", field:"PART_NAME", minWidth:130, headerSort:false,
editor: createSelect2Editor(partNameList),
cellEdited: function(cell){
// 부품명 선택 시 관련 데이터 자동 입력
var partName = cell.getValue();
if(partName){
var matched = deliveryDataList.find(function(d){ return d.PART_NAME == partName; });
if(matched){
cell.getRow().update({
PART_NO: matched.PART_NO || '',
RECEIPT_QTY: matched.RECEIPT_QTY || matched.DELIVERY_QTY || ''
});
}
}
}
},
{title:"입고수량", field:"RECEIPT_QTY", editor:"number", hozAlign:"right", minWidth:80, headerSort:false,
editorParams:{min:0, step:1},
formatter: function(cell){
var val = cell.getValue();
return (val !== null && val !== undefined && val !== "") ? Number(val).toLocaleString() : "";
}
},
{title:"양품수량", field:"GOOD_QTY", editor:"number", hozAlign:"right", minWidth:80, headerSort:false,
editorParams:{min:0, step:1},
formatter: function(cell){
var val = cell.getValue();
return (val !== null && val !== undefined && val !== "") ? Number(val).toLocaleString() : "";
}
}
];
leftGrid = new Tabulator("#leftGridWrap", {
layout: "fitColumns",
height: "100%",
columns: columns,
data: [],
placeholder: "데이터가 없습니다. 행을 추가해주세요.",
selectable: true
});
}
// 오른쪽 그리드 초기화 (불량 정보)
function fn_initRightGrid(){
var columns = [
{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},
formatter: function(cell){
var val = cell.getValue();
return (val !== null && val !== undefined && val !== "") ? Number(val).toLocaleString() : "";
}
},
{title:"불량유형", field:"DEFECT_TYPE", minWidth:85, headerSort:false,
editor: createSelect2Editor(defectTypeList)
},
{title:"불량원인", field:"DEFECT_CAUSE", minWidth:100, headerSort:false,
editor: createSelect2Editor(defectCauseList)
},
{title:"귀책부서", field:"RESPONSIBLE_DEPT", minWidth:80, headerSort:false,
editor: createSelect2Editor(responsibleDeptList)
},
{title:"부적합보고서", field:"NCR_FILE", minWidth:90, headerSort:false,
formatter: function(cell){
return '<button type="button" onclick="fn_uploadNCR(this)" style="padding:2px 8px;font-size:11px;">첨부</button>';
}
},
{title:"처리현황", field:"PROCESS_STATUS", minWidth:80, headerSort:false,
editor: createSelect2Editor(processStatusList)
},
{title:"이미지파일", field:"IMAGE_FILE", minWidth:80, headerSort:false,
formatter: function(cell){
return '<button type="button" onclick="fn_uploadImage(this)" style="padding:2px 8px;font-size:11px;">첨부</button>';
}
},
{title:"검사일", field:"INSPECTION_DATE", minWidth:100, headerSort:false,
editor: "input",
editorParams: {
elementAttributes: {
type: "date"
}
}
},
{title:"검사자", field:"INSPECTOR", editor:"input", minWidth:80, headerSort:false},
{title:"처리결과", field:"DISPOSITION_TYPE", minWidth:80, headerSort:false,
editor: createSelect2Editor(dispositionTypeList)
},
{title:"검사성적서", field:"INSPECTION_REPORT", minWidth:80, headerSort:false,
formatter: function(cell){
return '<button type="button" onclick="fn_uploadReport(this)" style="padding:2px 8px;font-size:11px;">첨부</button>';
}
},
{title:"비고", field:"REMARK", editor:"input", minWidth:100, headerSort:false}
];
rightGrid = new Tabulator("#rightGridWrap", {
layout: "fitColumns",
height: "100%",
columns: columns,
data: [],
placeholder: "데이터가 없습니다. 행을 추가해주세요.",
selectable: true
});
}
// 왼쪽 그리드 행 추가
function fn_addLeftRow(){
rowSeq++;
leftGrid.addRow({
ROW_ID: "NEW_" + rowSeq,
MODEL_NAME: "",
PRODUCT_TYPE: "",
WORK_ORDER_NO: "",
PART_NO: "",
PART_NAME: "",
RECEIPT_QTY: "",
GOOD_QTY: ""
});
}
// 왼쪽 그리드 행 삭제
function fn_delLeftRow(){
var selectedRows = leftGrid.getSelectedRows();
if(selectedRows.length == 0){
Swal.fire("삭제할 행을 선택해주세요.");
return;
}
selectedRows.forEach(function(row){
row.delete();
});
}
// 오른쪽 그리드 행 추가
function fn_addRightRow(){
rowSeq++;
var today = new Date().toISOString().split('T')[0];
rightGrid.addRow({
ROW_ID: "NEW_" + rowSeq,
DEFECT_QTY: "",
DEFECT_TYPE: "",
DEFECT_CAUSE: "",
RESPONSIBLE_DEPT: "",
NCR_FILE: "",
PROCESS_STATUS: "",
IMAGE_FILE: "",
INSPECTION_DATE: today,
INSPECTOR: loginUserName, // 로그인 사용자 자동 입력
DISPOSITION_TYPE: "",
INSPECTION_REPORT: "",
REMARK: ""
});
}
// 오른쪽 그리드 행 삭제
function fn_delRightRow(){
var selectedRows = rightGrid.getSelectedRows();
if(selectedRows.length == 0){
Swal.fire("삭제할 행을 선택해주세요.");
return;
}
selectedRows.forEach(function(row){
row.delete();
});
}
// 이미지 파일 업로드
function fn_uploadImage(btn){
Swal.fire({
icon: 'info',
title: '이미지 첨부',
text: '이미지 파일 업로드 기능은 추후 구현 예정입니다.'
});
}
// 검사성적서 업로드
function fn_uploadReport(btn){
Swal.fire({
icon: 'info',
title: '검사성적서 첨부',
text: '검사성적서 파일 업로드 기능은 추후 구현 예정입니다.'
});
}
// 부적합보고서 업로드
function fn_uploadNCR(btn){
Swal.fire({
icon: 'info',
title: '부적합보고서 첨부',
text: '부적합보고서 파일 업로드 기능은 추후 구현 예정입니다.'
});
}
// 기존 데이터 로드
function fn_loadData(objid, inspectionGroupId){
$.ajax({
url: "/quality/getSemiProductInspectionDetail.do",
type: "POST",
data: { OBJID: objid, INSPECTION_GROUP_ID: inspectionGroupId },
dataType: "json",
success: function(result){
console.log("상세 데이터 로드:", result);
if(result && result.leftData && result.leftData.length > 0){
leftGrid.setData(result.leftData);
}
if(result && result.rightData && result.rightData.length > 0){
rightGrid.setData(result.rightData);
}
},
error: function(xhr, status, error){
console.error("데이터 로드 오류:", error);
}
});
}
// 저장
function fn_save(){
// TODO: 저장 로직 구현
Swal.fire("저장 기능 준비중입니다.");
var leftData = leftGrid.getData();
var rightData = rightGrid.getData();
// 데이터 검증
if(leftData.length == 0 && rightData.length == 0){
Swal.fire({
icon: 'warning',
title: '알림',
text: '저장할 데이터가 없습니다.'
});
return;
}
// 저장 확인
Swal.fire({
icon: 'question',
title: '저장 확인',
text: '입력한 내용을 저장하시겠습니까?',
showCancelButton: true,
confirmButtonText: '저장',
cancelButtonText: '취소'
}).then(function(result){
if(result.isConfirmed){
var paramData = {
leftData: JSON.stringify(leftData),
rightData: JSON.stringify(rightData)
};
$.ajax({
url: "/quality/saveSemiProductInspection.do",
type: "POST",
data: paramData,
dataType: "json",
success: function(result){
if(result.result == true || result.result == "true"){
Swal.fire({
icon: 'success',
title: '저장 완료',
text: '저장되었습니다.',
confirmButtonText: '확인'
}).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){
Swal.fire({
icon: 'error',
title: '오류 발생',
text: '저장 중 오류가 발생했습니다: ' + error
});
}
});
}
});
}
</script>
<body>
<form name="form1" id="form1" method="post">
<div class="popup_wrap">
<div class="popup_header">
<h2><%=menuName%></h2>
<div class="btnArea">
<input type="button" class="plm_btns" value="저장" id="btnSave">
<input type="button" class="plm_btns" value="닫기" id="btnClose">
</div>
</div>
<div class="popup_content">
<table class="plm_form_table">
<colgroup>
<col width="120px"><col width="*">
<col width="120px"><col width="*">
</colgroup>
<tbody>
<tr>
<td class="label">프로젝트번호</td>
<td><input type="text" name="PROJECT_NO" id="PROJECT_NO"></td>
<td class="label">작업지시번호</td>
<td><input type="text" name="WORK_ORDER_NO" id="WORK_ORDER_NO"></td>
</tr>
<tr>
<td class="label">품번</td>
<td><input type="text" name="PART_NO" id="PART_NO"></td>
<td class="label">품명</td>
<td><input type="text" name="PART_NAME" id="PART_NAME"></td>
</tr>
<tr>
<td class="label">입고수량</td>
<td><input type="text" name="RECEIPT_QTY" id="RECEIPT_QTY"></td>
<td class="label">폐기/수정/특채</td>
<td>
<select name="DISPOSITION_TYPE" id="DISPOSITION_TYPE">
<option value="">선택</option>
<option value="폐기">폐기</option>
<option value="수정">수정</option>
<option value="특채">특채</option>
</select>
</td>
</tr>
<tr>
<td class="label">비고</td>
<td colspan="3"><textarea name="REMARK" id="REMARK" rows="3" style="width:100%;"></textarea></td>
</tr>
</tbody>
</table>
</div>
</div>
</form>
</body>
</html>

View File

@@ -18,15 +18,45 @@ String menuName = CommonUtils.getMenuName(menuObjId, "반제품검사 관리");
</head>
<style>
.select2-selection__choice {
font-size: 11px;
background-color: #fff !important;
border: none !important;
margin-right: 0px !important;
}
.select2-selection__choice__remove {
display: contents !important;
}
.select2-container .select2-selection--multiple {
min-height: 20px !important;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
margin-top: 3.5px !important;
}
.select2-selection__rendered {
height: 18px !important;
}
.select2-container .select2-selection--multiple .select2-selection__rendered {
overflow: auto !important;
}
/* 검사결과 스타일 */
.status-discard { color: #dc3545; font-weight: bold; }
.status-modify { color: #ffc107; font-weight: bold; }
.status-special { color: #28a745; font-weight: bold; }
body, html {
overflow-x: hidden;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script type="text/javascript">
$(document).ready(function(){
fnc_changePaginationAndTotalCountArea();
$('.select2').select2();
fnc_datepick();
$("input").keyup(function(e){
if(e.keyCode == 13){
@@ -54,24 +84,40 @@ $(document).ready(function(){
fn_search();
});
// 컬럼: 프로젝트번호, 작업지시번호, 품번, 품명, 입고수량, 폐기/수정/특채
// 컬럼: 품명(모델명), 작업지시번호, 부품품번, 품명, 입고수량 합계, 양품수량 합계, 불량수량 합계, 불량율, 재생수량 합계, 최종 양품수량 합계, 검사일, 검사자
var columns = [
{headerHozAlign:'center', hozAlign:'center', minWidth:140, widthGrow:1, title:'프로젝트번호', field:'PROJECT_NO'},
{headerHozAlign:'center', hozAlign:'left', minWidth:150, widthGrow:2, title:'품명(모델명)', field:'MODEL_NAME'},
{headerHozAlign:'center', hozAlign:'center', minWidth:140, widthGrow:1, title:'작업지시번호', field:'WORK_ORDER_NO'},
{headerHozAlign:'center', hozAlign:'left', minWidth:150, 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:'RECEIPT_QTY',
{headerHozAlign:'center', hozAlign:'left', minWidth:150, widthGrow:2, title:'부품품번', field:'PART_NO'},
{headerHozAlign:'center', hozAlign:'left', minWidth:200, widthGrow:3, title:'품명', field:'PART_NAME'},
{headerHozAlign:'center', hozAlign:'right', minWidth:120, widthGrow:1, title:'입고수량 합계', field:'RECEIPT_QTY',
formatter:"money", formatterParams:{thousand:",", precision:false}
},
{headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'폐기/수정/특채', field:'DISPOSITION_TYPE',
{headerHozAlign:'center', hozAlign:'right', minWidth:120, widthGrow:1, title:'양품수량 합계', field:'GOOD_QTY',
formatter:"money", formatterParams:{thousand:",", precision:false}
},
{headerHozAlign:'center', hozAlign:'right', minWidth:120, widthGrow:1, title:'불량수량 합계', field:'DEFECTIVE_QTY',
formatter:"money", formatterParams:{thousand:",", precision:false}
},
{headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'불량율', field:'DEFECT_RATE',
formatter: function(cell, formatterParams, onRendered){
var val = fnc_checkNull(cell.getValue());
if(val === '폐기') return '<span class="status-discard">폐기</span>';
if(val === '수정') return '<span class="status-modify">수정</span>';
if(val === '특채') return '<span class="status-special">특채</span>';
return val;
return val != '' ? val + '%' : '';
}
}
},
{headerHozAlign:'center', hozAlign:'right', minWidth:120, widthGrow:1, title:'재생수량 합계', field:'REGENERATION_QTY',
formatter:"money", formatterParams:{thousand:",", precision:false}
},
{headerHozAlign:'center', hozAlign:'right', minWidth:140, widthGrow:1, title:'최종 양품수량 합계', field:'FINAL_GOOD_QTY',
formatter:"money", formatterParams:{thousand:",", precision:false}
},
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'검사일', field:'INSPECTION_DATE',
formatter:fnc_createGridAnchorTag,
cellClick: function(e, cell){
fn_openInspectionPopUp(cell.getData());
}
},
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사자', field:'WRITER_NAME'}
];
// 조회
@@ -79,18 +125,8 @@ function fn_search(){
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/quality/semiProductInspectionGridList.do", columns, true);
}
// 반제품검사 등록 팝업
function fn_registPopUp(){
var selected = _tabulGrid.getSelectedData();
if(selected.length == 0){
Swal.fire("선택된 데이터가 없습니다.");
return;
}
if(selected.length > 1){
Swal.fire("한건씩 등록 가능합니다.");
return;
}
// 검사일 클릭 시 검사결과 확인/수정 팝업
function fn_openInspectionPopUp(rowData){
var popup_width = 1000;
var popup_height = 600;
var hiddenForm = document.hiddenForm;
@@ -100,7 +136,37 @@ function fn_registPopUp(){
fn_centerPopup(popup_width, popup_height, "", target);
hiddenForm.action = url;
hiddenForm.OBJID.value = selected[0].OBJID;
hiddenForm.OBJID.value = rowData.OBJID || '';
hiddenForm.INSPECTION_GROUP_ID.value = rowData.INSPECTION_GROUP_ID || '';
hiddenForm.MODEL_NAME.value = rowData.MODEL_NAME || '';
hiddenForm.WORK_ORDER_NO.value = rowData.WORK_ORDER_NO || '';
hiddenForm.PART_NO.value = rowData.PART_NO || '';
hiddenForm.PART_NAME.value = rowData.PART_NAME || '';
hiddenForm.INSPECTION_DATE.value = rowData.INSPECTION_DATE || '';
hiddenForm.actionType.value = 'view';
hiddenForm.target = target;
hiddenForm.submit();
}
// 반제품검사 등록 팝업 (신규 등록)
function fn_registPopUp(){
var popup_width = 1200;
var popup_height = 700;
var hiddenForm = document.hiddenForm;
var target = "semiProductInspectionPopUp";
var url = "/quality/semiProductInspectionFormPopUp.do";
fn_centerPopup(popup_width, popup_height, "", target);
hiddenForm.action = url;
hiddenForm.OBJID.value = ''; // 신규 등록이므로 빈값
hiddenForm.INSPECTION_GROUP_ID.value = ''; // 신규 등록이므로 빈값
hiddenForm.actionType.value = 'new';
hiddenForm.MODEL_NAME.value = '';
hiddenForm.WORK_ORDER_NO.value = '';
hiddenForm.PART_NO.value = '';
hiddenForm.PART_NAME.value = '';
hiddenForm.INSPECTION_DATE.value = '';
hiddenForm.target = target;
hiddenForm.submit();
}
@@ -117,7 +183,13 @@ function fn_excelDownload(){
<body>
<form name="hiddenForm" id="hiddenForm" method="post">
<input type="hidden" name="OBJID" id="OBJID">
<input type="hidden" name="INSPECTION_GROUP_ID" id="INSPECTION_GROUP_ID">
<input type="hidden" name="actionType" id="actionType">
<input type="hidden" name="MODEL_NAME" id="MODEL_NAME">
<input type="hidden" name="WORK_ORDER_NO" id="WORK_ORDER_NO">
<input type="hidden" name="PART_NO" id="PART_NO">
<input type="hidden" name="PART_NAME" id="PART_NAME">
<input type="hidden" name="INSPECTION_DATE" id="INSPECTION_DATE">
</form>
<form name="form1" id="form1" action="" method="post">
@@ -134,7 +206,55 @@ function fn_excelDownload(){
</div>
</div>
<!-- 검색필터 없음 -->
<!-- 검색필터 -->
<div id="plmSearchZon">
<table>
<tr>
<td><label for="">품명(모델명)</label></td>
<td>
<select name="search_model_name" id="search_model_name" class="select2" style="width:150px;" autocomplete="off">
<option value="">전체</option>
${code_map.model_name}
</select>
</td>
<td><label for="">작업지시번호</label></td>
<td><input type="text" name="search_work_order_no" id="search_work_order_no" style="width:150px;" autocomplete="off" value="${param.search_work_order_no}"></td>
<td><label for="">부품품번</label></td>
<td>
<select name="search_part_no" id="search_part_no" class="select2" style="width:170px;" autocomplete="off">
<option value="">전체</option>
${code_map.part_no}
</select>
</td>
<td><label for="">부품명</label></td>
<td>
<select name="search_part_name" id="search_part_name" class="select2" style="width:180px;" autocomplete="off">
<option value="">전체</option>
${code_map.part_name}
</select>
</td>
<td><label for="">검사일</label></td>
<td>
<select name="search_inspection_date" id="search_inspection_date" class="select2" style="width:150px;" autocomplete="off">
<option value="">전체</option>
${code_map.inspection_date}
</select>
</td>
<td><label for="">검사자</label></td>
<td>
<select name="search_writer" id="search_writer" class="select2" style="width:150px;" autocomplete="off">
<option value="">전체</option>
${code_map.writer}
</select>
</td>
</tr>
</table>
</div>
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
</div>

View File

@@ -2131,4 +2131,28 @@ public class PurchaseOrderController {
return resultMap;
}
/**
* 입고관리 데이터 드롭다운용 조회 (반제품검사 팝업에서 사용)
* @param request
* @param paramMap
* @return
*/
@ResponseBody
@RequestMapping("/purchaseOrder/getDeliveryListForDropdown.do")
public Map getDeliveryListForDropdown(HttpServletRequest request, @RequestParam Map paramMap){
Map resultMap = new HashMap();
try {
List list = purchaseOrderService.getDeliveryListForDropdown(request, paramMap);
resultMap.put("list", list);
resultMap.put("result", true);
} catch (Exception e) {
e.printStackTrace();
resultMap.put("result", false);
resultMap.put("message", e.getMessage());
}
return resultMap;
}
}

View File

@@ -469,16 +469,33 @@ public class QualityController {
*/
@RequestMapping("/quality/semiProductInspectionList.do")
public String semiProductInspectionList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
Map code_map = new HashMap();
try {
// 품명(모델명) 드롭박스
code_map.put("model_name", commonService.bizMakeOptionList("", (String)paramMap.get("search_model_name"), "quality.getSemiProductModelNameList"));
// 부품품번 드롭박스
code_map.put("part_no", commonService.bizMakeOptionList("", (String)paramMap.get("search_part_no"), "quality.getSemiProductPartNoList"));
// 부품명 드롭박스
code_map.put("part_name", commonService.bizMakeOptionList("", (String)paramMap.get("search_part_name"), "quality.getSemiProductPartNameList"));
// 검사일 드롭박스
code_map.put("inspection_date", commonService.bizMakeOptionList("", (String)paramMap.get("search_inspection_date"), "quality.getSemiProductInspectionDateList"));
// 검사자 드롭박스
code_map.put("writer", commonService.bizMakeOptionList("", (String)paramMap.get("search_writer"), "quality.getSemiProductWriterList"));
request.setAttribute("code_map", code_map);
} catch(Exception e) {
e.printStackTrace();
}
return "/quality/semiProductInspectionList";
}
/**
* 반제품검사 관리 그리드 목록 조회
*/
@ResponseBody
@RequestMapping("/quality/semiProductInspectionGridList.do")
public String semiProductInspectionGridList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
request.setAttribute("RESULT", CommonUtils.getJsonArray(service.getSemiProductInspectionList(request, paramMap)));
return "/ajax/ajaxResult";
public Map semiProductInspectionGridList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
commonService.selectListPagingNew("quality.getSemiProductInspectionList", request, paramMap);
return paramMap;
}
/**
@@ -491,12 +508,31 @@ public class QualityController {
return "/quality/semiProductInspectionFormPopUp";
}
/**
* 반제품검사 저장
*/
@RequestMapping("/quality/saveSemiProductInspection.do")
public String saveSemiProductInspection(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
Map map = service.saveSemiProductInspection(request, paramMap);
request.setAttribute("RESULT", CommonUtils.getJsonMap(map));
return "/ajax/ajaxResult";
}
/**
* 반제품검사 상세 조회 (팝업용)
*/
@ResponseBody
@RequestMapping("/quality/getSemiProductInspectionDetail.do")
public Map getSemiProductInspectionDetail(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
return service.getSemiProductInspectionDetail(paramMap);
}
/**
* 반제품검사 엑셀 다운로드
*/
@RequestMapping("/quality/semiProductInspectionExcelDownload.do")
public String semiProductInspectionExcelDownload(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
List list = service.getSemiProductInspectionList(request, paramMap);
List list = service.getSemiProductInspectionListForExcel(paramMap);
request.setAttribute("LIST", list);
return "/quality/semiProductInspectionExcel";
}

View File

@@ -6069,4 +6069,26 @@ FROM(
WHERE OBJID = #{OBJID}
</update>
<!-- 입고관리 데이터 드롭다운용 조회 (반제품검사 팝업에서 사용) -->
<!-- ARRIVAL_PLAN 테이블에서 입고완료된 품목 조회 (1차+2차 합산) -->
<select id="getDeliveryListForDropdown" parameterType="map" resultType="map">
SELECT
AP.ORDER_PART_OBJID AS OBJID
,AP.PART_OBJID
,COALESCE(CASE WHEN POM.TYPE IN ('0001070','0001069') THEN PM.PART_NO ELSE POP.PART_NO END, PM.PART_NO, '') AS PART_NO
,COALESCE(POP.PART_NAME, PM.PART_NAME, '') AS PART_NAME
,COALESCE(POP.PART_NAME, PM.PART_NAME, '') AS MODEL_NAME
,COALESCE(POM.PURCHASE_ORDER_NO, '') AS WORK_ORDER_NO
,COALESCE(SUM(AP.RECEIPT_QTY::NUMERIC), 0) AS RECEIPT_QTY
FROM ARRIVAL_PLAN AP
LEFT JOIN PURCHASE_ORDER_PART POP ON POP.OBJID = AP.ORDER_PART_OBJID
LEFT JOIN PART_MNG PM ON PM.OBJID::VARCHAR = AP.PART_OBJID OR PM.OBJID = POP.PART_OBJID
LEFT JOIN PURCHASE_ORDER_MASTER POM ON POM.OBJID = AP.PARENT_OBJID
WHERE AP.RECEIPT_QTY IS NOT NULL
AND AP.RECEIPT_QTY::NUMERIC > 0
AND AP.INVENTORY_STATUS = 'Y'
GROUP BY AP.ORDER_PART_OBJID, AP.PART_OBJID, POP.PART_NO, POP.PART_NAME, PM.PART_NO, PM.PART_NAME, POM.PURCHASE_ORDER_NO, POM.TYPE
ORDER BY PART_NO
</select>
</mapper>

View File

@@ -1216,18 +1216,231 @@
반제품검사 관리
===================================================== -->
<!-- 반제품검사 목록 조회 -->
<!-- 반제품검사 목록 조회 (영업관리 방식: 작업지시번호 기준 그룹화, 나머지는 "외 N건") -->
<select id="getSemiProductInspectionList" parameterType="map" resultType="map">
SELECT T.INSPECTION_GROUP_ID
, MIN(T.OBJID) AS OBJID
<!-- 작업지시번호: 여러 개면 "XXX 외 N건" (빈값/NULL 제외) -->
, (SELECT CASE
WHEN COUNT(*) = 0 THEN ''
WHEN COUNT(*) = 1 THEN MAX(val)
ELSE MAX(val) || ' 외 ' || (COUNT(*) - 1) || '건'
END
FROM (SELECT DISTINCT T2.WORK_ORDER_NO AS val FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION T2
WHERE T2.INSPECTION_GROUP_ID = T.INSPECTION_GROUP_ID
AND T2.WORK_ORDER_NO IS NOT NULL AND T2.WORK_ORDER_NO != '') sub
) AS WORK_ORDER_NO
<!-- 품명(모델명): 여러 개면 "XXX 외 N건" (빈값/NULL 제외) -->
, (SELECT CASE
WHEN COUNT(*) = 0 THEN ''
WHEN COUNT(*) = 1 THEN MAX(val)
ELSE MAX(val) || ' 외 ' || (COUNT(*) - 1) || '건'
END
FROM (SELECT DISTINCT T2.MODEL_NAME AS val FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION T2
WHERE T2.INSPECTION_GROUP_ID = T.INSPECTION_GROUP_ID
AND T2.MODEL_NAME IS NOT NULL AND T2.MODEL_NAME != '') sub
) AS MODEL_NAME
<!-- 부품품번: 여러 개면 "XXX 외 N건" (빈값/NULL 제외) -->
, (SELECT CASE
WHEN COUNT(*) = 0 THEN ''
WHEN COUNT(*) = 1 THEN MAX(val)
ELSE MAX(val) || ' 외 ' || (COUNT(*) - 1) || '건'
END
FROM (SELECT DISTINCT T2.PART_NO AS val FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION T2
WHERE T2.INSPECTION_GROUP_ID = T.INSPECTION_GROUP_ID
AND T2.PART_NO IS NOT NULL AND T2.PART_NO != '') sub
) AS PART_NO
<!-- 부품명: 여러 개면 "XXX 외 N건" (빈값/NULL 제외) -->
, (SELECT CASE
WHEN COUNT(*) = 0 THEN ''
WHEN COUNT(*) = 1 THEN MAX(val)
ELSE MAX(val) || ' 외 ' || (COUNT(*) - 1) || '건'
END
FROM (SELECT DISTINCT T2.PART_NAME AS val FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION T2
WHERE T2.INSPECTION_GROUP_ID = T.INSPECTION_GROUP_ID
AND T2.PART_NAME IS NOT NULL AND T2.PART_NAME != '') sub
) AS PART_NAME
<!-- 검사일: 여러 개면 "XXX 외 N건" (빈값/NULL 제외) -->
, (SELECT CASE
WHEN COUNT(*) = 0 THEN ''
WHEN COUNT(*) = 1 THEN MAX(val)
ELSE MAX(val) || ' 외 ' || (COUNT(*) - 1) || '건'
END
FROM (SELECT DISTINCT COALESCE(TO_CHAR(T2.INSPECTION_DATE, 'YYYY-MM-DD'), TO_CHAR(T2.REG_DATE, 'YYYY-MM-DD')) AS val
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION T2
WHERE T2.INSPECTION_GROUP_ID = T.INSPECTION_GROUP_ID
AND (T2.INSPECTION_DATE IS NOT NULL OR T2.REG_DATE IS NOT NULL)) sub
) AS INSPECTION_DATE
<!-- 검사자: 여러 개면 "XXX 외 N건" (빈값/NULL 제외) -->
, (SELECT CASE
WHEN COUNT(*) = 0 THEN ''
WHEN COUNT(*) = 1 THEN MAX(val)
ELSE MAX(val) || ' 외 ' || (COUNT(*) - 1) || '건'
END
FROM (SELECT DISTINCT COALESCE((SELECT USER_NAME FROM USER_INFO WHERE USER_ID = T2.INSPECTOR),
(SELECT USER_NAME FROM USER_INFO WHERE USER_ID = T2.WRITER)) AS val
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION T2
WHERE T2.INSPECTION_GROUP_ID = T.INSPECTION_GROUP_ID
AND (T2.INSPECTOR IS NOT NULL OR T2.WRITER IS NOT NULL)) sub
WHERE val IS NOT NULL AND val != ''
) AS WRITER_NAME
<!-- 수량 집계 -->
, SUM(T.RECEIPT_QTY) AS RECEIPT_QTY
, SUM(T.GOOD_QTY) AS GOOD_QTY
, SUM(T.DEFECT_QTY) AS DEFECTIVE_QTY
, CASE
WHEN SUM(T.RECEIPT_QTY) > 0
THEN ROUND(SUM(T.DEFECT_QTY) * 100.0 / SUM(T.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
FROM (
SELECT SPI.OBJID
, COALESCE(SPI.MODEL_NAME, '') AS MODEL_NAME
, 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
, SPI.DISPOSITION_TYPE
, SPI.DATA_TYPE
, 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.INSPECTION_GROUP_ID, SPI.OBJID) 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 SPI.PART_NO = #{search_part_no}
</if>
<!-- 부품명 검색 -->
<if test="search_part_name != null and search_part_name != ''">
AND SPI.PART_NAME = #{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) DESC, T.INSPECTION_GROUP_ID
</select>
<!-- 반제품검사 엑셀 다운로드용 원본 데이터 조회 (그룹화 없이 모든 데이터) -->
<select id="getSemiProductInspectionListForExcel" parameterType="map" resultType="map">
SELECT SPI.OBJID
, SPI.PROJECT_NO
, SPI.WORK_ORDER_NO
, SPI.PART_NO
, SPI.PART_NAME
, SPI.RECEIPT_QTY
, 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 SPI.RECEIPT_QTY > 0
THEN ROUND(COALESCE(SPI.DEFECT_QTY, 0) * 100.0 / SPI.RECEIPT_QTY, 2)
ELSE 0
END AS DEFECT_RATE
, 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(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
, SPI.DEFECT_TYPE
, SPI.DEFECT_CAUSE
, SPI.RESPONSIBLE_DEPT
, SPI.PROCESS_STATUS
, SPI.DISPOSITION_TYPE
, SPI.REMARK
, SPI.DATA_TYPE
, SPI.WRITER
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
WHERE 1=1
ORDER BY SPI.REG_DATE DESC
<!-- 품명(모델명) 검색 -->
<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 SPI.PART_NO = #{search_part_no}
</if>
<!-- 부품명 검색 -->
<if test="search_part_name != null and search_part_name != ''">
AND SPI.PART_NAME = #{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.REG_DATE DESC, MODEL_NAME, SPI.WORK_ORDER_NO, SPI.PART_NO
</select>
<!-- 반제품검사 품명(모델명) 드롭박스 목록 (CODE, NAME 형태) -->
<select id="getSemiProductModelNameList" parameterType="map" resultType="map">
SELECT DISTINCT CODE_NAME(PM.PRODUCT) AS CODE
, CODE_NAME(PM.PRODUCT) AS NAME
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
INNER JOIN PROJECT_MGMT PM ON PM.PROJECT_NO = SPI.PROJECT_NO
WHERE CODE_NAME(PM.PRODUCT) IS NOT NULL AND CODE_NAME(PM.PRODUCT) != ''
ORDER BY CODE
</select>
<!-- 반제품검사 부품품번 드롭박스 목록 (CODE, NAME 형태) -->
<select id="getSemiProductPartNoList" parameterType="map" resultType="map">
SELECT DISTINCT PART_NO AS CODE
, PART_NO AS NAME
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION
WHERE PART_NO IS NOT NULL AND PART_NO != ''
ORDER BY CODE
</select>
<!-- 반제품검사 부품명 드롭박스 목록 (CODE, NAME 형태) -->
<select id="getSemiProductPartNameList" parameterType="map" resultType="map">
SELECT DISTINCT PART_NAME AS CODE
, PART_NAME AS NAME
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION
WHERE PART_NAME IS NOT NULL AND PART_NAME != ''
ORDER BY CODE
</select>
<!-- 반제품검사 검사일 드롭박스 목록 (CODE, NAME 형태) -->
<select id="getSemiProductInspectionDateList" parameterType="map" resultType="map">
SELECT DISTINCT TO_CHAR(REG_DATE, 'YYYY-MM-DD') AS CODE
, TO_CHAR(REG_DATE, 'YYYY-MM-DD') AS NAME
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION
WHERE REG_DATE IS NOT NULL
ORDER BY CODE DESC
</select>
<!-- 반제품검사 검사자 드롭박스 목록 (CODE, NAME 형태) -->
<select id="getSemiProductWriterList" parameterType="map" resultType="map">
SELECT DISTINCT SPI.WRITER AS CODE
, (SELECT USER_NAME FROM USER_INFO WHERE USER_ID = SPI.WRITER) AS NAME
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
WHERE SPI.WRITER IS NOT NULL AND SPI.WRITER != ''
ORDER BY NAME
</select>
<!-- 반제품검사 상세 조회 -->
@@ -1242,10 +1455,140 @@
, SPI.REMARK
, SPI.WRITER
, TO_CHAR(SPI.REG_DATE, 'YYYY-MM-DD') AS REG_DATE
, SPI.INSPECTION_GROUP_ID
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
WHERE SPI.OBJID = #{OBJID}
</select>
<!-- 반제품검사 상세 조회 (타입별) -->
<select id="getSemiProductInspectionByType" parameterType="map" resultType="map">
SELECT SPI.OBJID AS "OBJID"
, 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(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(TO_CHAR(SPI.INSPECTION_DATE, 'YYYY-MM-DD'), '') AS "INSPECTION_DATE"
, COALESCE(SPI.INSPECTOR, '') AS "INSPECTOR"
, COALESCE(SPI.DISPOSITION_TYPE, '') AS "DISPOSITION_TYPE"
, COALESCE(SPI.REMARK, '') AS "REMARK"
, SPI.DATA_TYPE AS "DATA_TYPE"
, COALESCE(SPI.INSPECTION_GROUP_ID, '') AS "INSPECTION_GROUP_ID"
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
WHERE 1=1
<if test="INSPECTION_GROUP_ID != null and INSPECTION_GROUP_ID != ''">
AND (SPI.INSPECTION_GROUP_ID = #{INSPECTION_GROUP_ID} OR SPI.OBJID = #{INSPECTION_GROUP_ID})
</if>
<if test="WORK_ORDER_NO != null and WORK_ORDER_NO != ''">
AND SPI.WORK_ORDER_NO = #{WORK_ORDER_NO}
</if>
<if test="OBJID != null and OBJID != ''">
AND SPI.OBJID = #{OBJID}
</if>
<if test="DATA_TYPE != null and DATA_TYPE != ''">
AND SPI.DATA_TYPE = #{DATA_TYPE}
</if>
ORDER BY SPI.REG_DATE
</select>
<!-- 반제품검사 저장 (INSERT) -->
<insert id="saveSemiProductInspection" parameterType="map">
INSERT INTO PMS_QUALITY_SEMI_PRODUCT_INSPECTION (
OBJID
, PROJECT_NO
, WORK_ORDER_NO
, PART_NO
, PART_NAME
, RECEIPT_QTY
, DISPOSITION_TYPE
, REMARK
, WRITER
, REG_DATE
) VALUES (
#{OBJID}
, #{PROJECT_NO}
, #{WORK_ORDER_NO}
, #{PART_NO}
, #{PART_NAME}
, #{RECEIPT_QTY}::NUMERIC
, #{DISPOSITION_TYPE}
, #{REMARK}
, #{WRITER}
, NOW()
)
</insert>
<!-- 반제품검사 수정 (UPDATE) -->
<update id="updateSemiProductInspection" parameterType="map">
UPDATE PMS_QUALITY_SEMI_PRODUCT_INSPECTION
SET PROJECT_NO = #{PROJECT_NO}
, WORK_ORDER_NO = #{WORK_ORDER_NO}
, PART_NO = #{PART_NO}
, PART_NAME = #{PART_NAME}
, RECEIPT_QTY = #{RECEIPT_QTY}::NUMERIC
, DISPOSITION_TYPE = #{DISPOSITION_TYPE}
, REMARK = #{REMARK}
, WRITER = #{WRITER}
, REG_DATE = NOW()
WHERE OBJID = #{OBJID}
</update>
<!-- 반제품검사 데이터 저장 (새 팝업 형식) -->
<insert id="insertSemiProductInspectionData" parameterType="map">
INSERT INTO PMS_QUALITY_SEMI_PRODUCT_INSPECTION (
OBJID
, MODEL_NAME
, PRODUCT_TYPE
, WORK_ORDER_NO
, PART_NO
, PART_NAME
, RECEIPT_QTY
, GOOD_QTY
, DEFECT_QTY
, DEFECT_TYPE
, DEFECT_CAUSE
, RESPONSIBLE_DEPT
, PROCESS_STATUS
, INSPECTION_DATE
, INSPECTOR
, DISPOSITION_TYPE
, REMARK
, WRITER
, REG_DATE
, DATA_TYPE
, INSPECTION_GROUP_ID
) VALUES (
#{OBJID}
, #{MODEL_NAME}
, #{PRODUCT_TYPE}
, #{WORK_ORDER_NO}
, #{PART_NO}
, #{PART_NAME}
, COALESCE(NULLIF(#{RECEIPT_QTY}, '')::NUMERIC, 0)
, COALESCE(NULLIF(#{GOOD_QTY}, '')::NUMERIC, 0)
, COALESCE(NULLIF(#{DEFECT_QTY}, '')::NUMERIC, 0)
, #{DEFECT_TYPE}
, #{DEFECT_CAUSE}
, #{RESPONSIBLE_DEPT}
, #{PROCESS_STATUS}
, CASE WHEN #{INSPECTION_DATE} = '' THEN NULL ELSE #{INSPECTION_DATE}::DATE END
, #{INSPECTOR}
, #{DISPOSITION_TYPE}
, #{REMARK}
, #{WRITER}
, NOW()
, #{DATA_TYPE}
, #{INSPECTION_GROUP_ID}
)
</insert>
<!-- =====================================================
고객 CS 관리
===================================================== -->

View File

@@ -3134,4 +3134,15 @@ public class PurchaseOrderService {
return sb.toString();
}
/**
* 입고관리 데이터 드롭다운용 조회 (반제품검사 팝업에서 사용)
* @param request
* @param paramMap
* @return
* @throws Exception
*/
public List getDeliveryListForDropdown(HttpServletRequest request, Map paramMap) throws Exception {
return commonService.selectList("purchaseOrder.getDeliveryListForDropdown", request, paramMap);
}
}

View File

@@ -901,6 +901,23 @@ public class QualityService extends BaseService{
return resultList;
}
/**
* 반제품검사 엑셀 다운로드용 원본 데이터 조회
*/
public List getSemiProductInspectionListForExcel(Map paramMap){
List resultList = new ArrayList();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession();
resultList = sqlSession.selectList("quality.getSemiProductInspectionListForExcel", paramMap);
}catch(Exception e){
e.printStackTrace();
}finally{
sqlSession.close();
}
return resultList;
}
/**
* 반제품검사 상세 조회
*/
@@ -918,6 +935,259 @@ public class QualityService extends BaseService{
return resultMap;
}
/**
* 반제품검사 상세 조회 (팝업용 - 양품/불량 데이터 분리)
*/
public Map getSemiProductInspectionDetail(Map paramMap){
Map resultMap = new HashMap();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession();
String inspectionGroupId = CommonUtils.checkNull(paramMap.get("INSPECTION_GROUP_ID"));
String objid = CommonUtils.checkNull(paramMap.get("OBJID"));
Map searchMap = new HashMap();
// INSPECTION_GROUP_ID가 있으면 우선 사용
if(!inspectionGroupId.equals("")) {
searchMap.put("INSPECTION_GROUP_ID", inspectionGroupId);
} else if(!objid.equals("")) {
// OBJID로 해당 행의 INSPECTION_GROUP_ID 조회
Map infoMap = sqlSession.selectOne("quality.getSemiProductInspectionInfo", paramMap);
if(infoMap != null && infoMap.get("inspection_group_id") != null) {
searchMap.put("INSPECTION_GROUP_ID", CommonUtils.checkNull(infoMap.get("inspection_group_id")));
} else if(infoMap != null && infoMap.get("INSPECTION_GROUP_ID") != null) {
searchMap.put("INSPECTION_GROUP_ID", CommonUtils.checkNull(infoMap.get("INSPECTION_GROUP_ID")));
} else {
// 그룹 ID가 없으면 OBJID로 단건 조회
searchMap.put("OBJID", objid);
}
}
// 양품 데이터 (DATA_TYPE = 'GOOD')
searchMap.put("DATA_TYPE", "GOOD");
List leftData = sqlSession.selectList("quality.getSemiProductInspectionByType", searchMap);
resultMap.put("leftData", leftData);
// 불량 데이터 (DATA_TYPE = 'DEFECT')
searchMap.put("DATA_TYPE", "DEFECT");
List rightData = sqlSession.selectList("quality.getSemiProductInspectionByType", searchMap);
resultMap.put("rightData", rightData);
}catch(Exception e){
e.printStackTrace();
}finally{
if(sqlSession != null) sqlSession.close();
}
return resultMap;
}
/**
* 반제품검사 저장 (새로운 팝업 형식)
*/
public Map saveSemiProductInspection(HttpServletRequest request, Map paramMap){
Map resultMap = new HashMap();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
String writer = CommonUtils.checkNull(person.getUserId());
// JSON 데이터 파싱
String leftDataStr = CommonUtils.checkNull(paramMap.get("leftData"));
String rightDataStr = CommonUtils.checkNull(paramMap.get("rightData"));
org.json.simple.parser.JSONParser parser = new org.json.simple.parser.JSONParser();
// 검사 그룹 ID 생성 (이번 저장 건을 묶는 용도)
String inspectionGroupId = CommonUtils.createObjId();
// 양품 정보 (leftData) 저장
if(leftDataStr != null && !leftDataStr.equals("") && !leftDataStr.equals("[]")){
org.json.simple.JSONArray leftArr = (org.json.simple.JSONArray) parser.parse(leftDataStr);
for(int i = 0; i < leftArr.size(); i++){
org.json.simple.JSONObject item = (org.json.simple.JSONObject) leftArr.get(i);
Map sqlParamMap = new HashMap();
sqlParamMap.put("OBJID", CommonUtils.createObjId());
sqlParamMap.put("MODEL_NAME", CommonUtils.checkNull(item.get("MODEL_NAME")));
sqlParamMap.put("PRODUCT_TYPE", CommonUtils.checkNull(item.get("PRODUCT_TYPE")));
sqlParamMap.put("WORK_ORDER_NO", CommonUtils.checkNull(item.get("WORK_ORDER_NO")));
sqlParamMap.put("PART_NO", CommonUtils.checkNull(item.get("PART_NO")));
sqlParamMap.put("PART_NAME", CommonUtils.checkNull(item.get("PART_NAME")));
sqlParamMap.put("RECEIPT_QTY", CommonUtils.checkNull(item.get("RECEIPT_QTY"), "0"));
sqlParamMap.put("GOOD_QTY", CommonUtils.checkNull(item.get("GOOD_QTY"), "0"));
sqlParamMap.put("WRITER", writer);
sqlParamMap.put("DATA_TYPE", "GOOD");
sqlParamMap.put("INSPECTION_GROUP_ID", inspectionGroupId);
// 불량 정보 컬럼은 빈값으로
sqlParamMap.put("DEFECT_QTY", "0");
sqlParamMap.put("DEFECT_TYPE", "");
sqlParamMap.put("DEFECT_CAUSE", "");
sqlParamMap.put("RESPONSIBLE_DEPT", "");
sqlParamMap.put("PROCESS_STATUS", "");
sqlParamMap.put("INSPECTION_DATE", "");
sqlParamMap.put("INSPECTOR", "");
sqlParamMap.put("DISPOSITION_TYPE", "");
sqlParamMap.put("REMARK", "");
sqlSession.insert("quality.insertSemiProductInspectionData", sqlParamMap);
}
}
// 양품 데이터에서 공통 정보 추출 (불량 데이터 연결용)
String commonWorkOrderNo = "";
String commonModelName = "";
String commonProductType = "";
String commonPartNo = "";
String commonPartName = "";
if(leftDataStr != null && !leftDataStr.equals("") && !leftDataStr.equals("[]")){
org.json.simple.JSONArray leftArrForWo = (org.json.simple.JSONArray) parser.parse(leftDataStr);
if(leftArrForWo.size() > 0){
org.json.simple.JSONObject firstItem = (org.json.simple.JSONObject) leftArrForWo.get(0);
commonWorkOrderNo = CommonUtils.checkNull(firstItem.get("WORK_ORDER_NO"));
commonModelName = CommonUtils.checkNull(firstItem.get("MODEL_NAME"));
commonProductType = CommonUtils.checkNull(firstItem.get("PRODUCT_TYPE"));
commonPartNo = CommonUtils.checkNull(firstItem.get("PART_NO"));
commonPartName = CommonUtils.checkNull(firstItem.get("PART_NAME"));
}
}
// 불량 정보 (rightData) 저장
if(rightDataStr != null && !rightDataStr.equals("") && !rightDataStr.equals("[]")){
org.json.simple.JSONArray rightArr = (org.json.simple.JSONArray) parser.parse(rightDataStr);
for(int i = 0; i < rightArr.size(); i++){
org.json.simple.JSONObject item = (org.json.simple.JSONObject) rightArr.get(i);
Map sqlParamMap = new HashMap();
sqlParamMap.put("OBJID", CommonUtils.createObjId());
sqlParamMap.put("DEFECT_QTY", CommonUtils.checkNull(item.get("DEFECT_QTY"), "0"));
sqlParamMap.put("DEFECT_TYPE", CommonUtils.checkNull(item.get("DEFECT_TYPE")));
sqlParamMap.put("DEFECT_CAUSE", CommonUtils.checkNull(item.get("DEFECT_CAUSE")));
sqlParamMap.put("RESPONSIBLE_DEPT", CommonUtils.checkNull(item.get("RESPONSIBLE_DEPT")));
sqlParamMap.put("PROCESS_STATUS", CommonUtils.checkNull(item.get("PROCESS_STATUS")));
sqlParamMap.put("INSPECTION_DATE", CommonUtils.checkNull(item.get("INSPECTION_DATE")));
sqlParamMap.put("INSPECTOR", CommonUtils.checkNull(item.get("INSPECTOR")));
sqlParamMap.put("DISPOSITION_TYPE", CommonUtils.checkNull(item.get("DISPOSITION_TYPE")));
sqlParamMap.put("REMARK", CommonUtils.checkNull(item.get("REMARK")));
sqlParamMap.put("WRITER", writer);
sqlParamMap.put("DATA_TYPE", "DEFECT");
sqlParamMap.put("INSPECTION_GROUP_ID", inspectionGroupId);
// 양품 데이터와 연결 (공통 정보 복사)
sqlParamMap.put("WORK_ORDER_NO", commonWorkOrderNo);
sqlParamMap.put("MODEL_NAME", commonModelName);
sqlParamMap.put("PRODUCT_TYPE", commonProductType);
sqlParamMap.put("PART_NO", commonPartNo);
sqlParamMap.put("PART_NAME", commonPartName);
sqlParamMap.put("RECEIPT_QTY", "0");
sqlParamMap.put("GOOD_QTY", "0");
sqlSession.insert("quality.insertSemiProductInspectionData", sqlParamMap);
}
}
sqlSession.commit();
resultMap.put("result", true);
resultMap.put("msg", "저장되었습니다.");
}catch(Exception e){
resultMap.put("result", false);
resultMap.put("msg", "저장 중 오류가 발생했습니다: " + e.getMessage());
if(sqlSession != null) sqlSession.rollback();
e.printStackTrace();
}finally{
if(sqlSession != null) sqlSession.close();
}
return resultMap;
}
/**
* 반제품검사 품명(모델명) 드롭박스 목록
*/
public List getSemiProductModelNameList(Map paramMap){
List resultList = new ArrayList();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession();
resultList = sqlSession.selectList("quality.getSemiProductModelNameList", paramMap);
}catch(Exception e){
e.printStackTrace();
}finally{
sqlSession.close();
}
return resultList;
}
/**
* 반제품검사 부품품번 드롭박스 목록
*/
public List getSemiProductPartNoList(Map paramMap){
List resultList = new ArrayList();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession();
resultList = sqlSession.selectList("quality.getSemiProductPartNoList", paramMap);
}catch(Exception e){
e.printStackTrace();
}finally{
sqlSession.close();
}
return resultList;
}
/**
* 반제품검사 부품명 드롭박스 목록
*/
public List getSemiProductPartNameList(Map paramMap){
List resultList = new ArrayList();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession();
resultList = sqlSession.selectList("quality.getSemiProductPartNameList", paramMap);
}catch(Exception e){
e.printStackTrace();
}finally{
sqlSession.close();
}
return resultList;
}
/**
* 반제품검사 검사일 드롭박스 목록
*/
public List getSemiProductInspectionDateList(Map paramMap){
List resultList = new ArrayList();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession();
resultList = sqlSession.selectList("quality.getSemiProductInspectionDateList", paramMap);
}catch(Exception e){
e.printStackTrace();
}finally{
sqlSession.close();
}
return resultList;
}
/**
* 반제품검사 검사자 드롭박스 목록
*/
public List getSemiProductWriterList(Map paramMap){
List resultList = new ArrayList();
SqlSession sqlSession = null;
try{
sqlSession = SqlMapConfig.getInstance().getSqlSession();
resultList = sqlSession.selectList("quality.getSemiProductWriterList", paramMap);
}catch(Exception e){
e.printStackTrace();
}finally{
sqlSession.close();
}
return resultList;
}
// =====================================================
// 고객 CS 관리
// =====================================================