Compare commits
34 Commits
V202512180
...
V202512220
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
969a136179 | ||
|
|
1fa303cc0f | ||
|
|
ac8551c821 | ||
|
|
6dd802feda | ||
|
|
c82ecee980 | ||
| 1b05dce6cd | |||
| f9444e44b9 | |||
| b85dd415fb | |||
| 57b14daf19 | |||
| 60c054f33d | |||
|
|
1e18e3337e | ||
| e1db86179d | |||
|
|
2ab9636a07 | ||
| 1aa7cb5544 | |||
|
|
910cc44293 | ||
|
|
787a077a2f | ||
|
|
d8472dd5a1 | ||
| 4c195a4d4b | |||
| bbc4474d55 | |||
|
|
69f14ac511 | ||
|
|
f040156f88 | ||
| 708393ad7a | |||
| d7f5d45e67 | |||
| 6311f54283 | |||
|
|
3910596bc2 | ||
| fede2e3cef | |||
|
|
3816596694 | ||
| 6025bd2786 | |||
| 1ec25ecc27 | |||
| 546bea7b4c | |||
|
|
d57258df5a | ||
|
|
dfed125ee9 | ||
| d8620a484b | |||
|
|
874910231f |
@@ -2736,6 +2736,24 @@ ORDER BY COALESCE(T.REVISION, '1.0')
|
||||
ORDER BY SUPPLY_NAME
|
||||
</select>
|
||||
|
||||
<!-- 공급업체 + 일반거래처 통합 목록 조회 (발주서 검색용) -->
|
||||
<select id="getAllSupplySelect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID::VARCHAR AS CODE
|
||||
,SUPPLY_NAME AS NAME
|
||||
,OBJID::VARCHAR AS CODE_ID
|
||||
,SUPPLY_NAME AS CODE_NAME
|
||||
FROM ADMIN_SUPPLY_MNG
|
||||
UNION ALL
|
||||
SELECT
|
||||
'C_' || OBJID::VARCHAR AS CODE
|
||||
,CLIENT_NM AS NAME
|
||||
,'C_' || OBJID::VARCHAR AS CODE_ID
|
||||
,CLIENT_NM AS CODE_NAME
|
||||
FROM CLIENT_MNG
|
||||
ORDER BY NAME
|
||||
</select>
|
||||
|
||||
<!-- 일반거래처 목록 조회 (CLIENT_MNG 테이블) - 발주서용 -->
|
||||
<select id="getClientMngSupplySelect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
|
||||
@@ -3039,6 +3039,53 @@
|
||||
WHERE 1=1
|
||||
AND PM.PROJECT_NO IS NOT NULL
|
||||
AND PM.PROJECT_NO != ''
|
||||
<!-- 주문유형 검색 -->
|
||||
<if test="search_category_cd != null and search_category_cd != ''">
|
||||
AND CM.CATEGORY_CD = #{search_category_cd}
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_cd != null and search_product_cd != ''">
|
||||
AND CM.PRODUCT = #{search_product_cd}
|
||||
</if>
|
||||
<!-- 국내/해외 검색 -->
|
||||
<if test="search_area_cd != null and search_area_cd != ''">
|
||||
AND CODE_NAME(CM.AREA_CD) = #{search_area_cd}
|
||||
</if>
|
||||
<!-- 접수일 검색 -->
|
||||
<if test="search_receipt_date_from != null and search_receipt_date_from != ''">
|
||||
<![CDATA[AND PM.REGDATE >= TO_DATE(#{search_receipt_date_from}, 'YYYY-MM-DD')]]>
|
||||
</if>
|
||||
<if test="search_receipt_date_to != null and search_receipt_date_to != ''">
|
||||
<![CDATA[AND PM.REGDATE < TO_DATE(#{search_receipt_date_to}, 'YYYY-MM-DD') + INTERVAL '1 day']]>
|
||||
</if>
|
||||
<!-- 고객사 검색 -->
|
||||
<if test="search_customer_objid != null and search_customer_objid != ''">
|
||||
AND (
|
||||
CM.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
OR CM.CUSTOMER_OBJID = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
OR 'C_' || CM.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
)
|
||||
</if>
|
||||
<!-- 유/무상 검색 -->
|
||||
<if test="search_paid_type != null and search_paid_type != ''">
|
||||
AND CM.PAID_TYPE = #{search_paid_type}
|
||||
</if>
|
||||
<!-- S/N 검색 -->
|
||||
<if test="search_serial_no != null and search_serial_no != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND UPPER(CIS.SERIAL_NO) LIKE '%' || UPPER(#{search_serial_no}) || '%'
|
||||
)
|
||||
</if>
|
||||
<!-- 요청납기 검색 -->
|
||||
<if test="search_req_del_date_from != null and search_req_del_date_from != ''">
|
||||
<![CDATA[AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) >= #{search_req_del_date_from}]]>
|
||||
</if>
|
||||
<if test="search_req_del_date_to != null and search_req_del_date_to != ''">
|
||||
<![CDATA[AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) <= #{search_req_del_date_to}]]>
|
||||
</if>
|
||||
<!-- 품번 검색 (대소문자 구분 없음) -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND (
|
||||
@@ -4406,150 +4453,211 @@
|
||||
|
||||
<!-- 생산계획&실적관리 그리드 목록 조회 -->
|
||||
<select id="prodPlanResultMgmtGridList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
CM.PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
CM.CATEGORY_CD AS CATEGORY_CODE,
|
||||
-- 생산유형 (TODO: 실제 컬럼명 확인 필요)
|
||||
'' AS PRODUCTION_TYPE,
|
||||
'' AS PRODUCTION_TYPE_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
CASE
|
||||
WHEN CM.CUSTOMER_OBJID LIKE 'C_%' THEN
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG AS C WHERE 'C_' || C.OBJID::VARCHAR = CM.CUSTOMER_OBJID LIMIT 1)
|
||||
ELSE
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID::VARCHAR = CM.CUSTOMER_OBJID::VARCHAR LIMIT 1)
|
||||
END,
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
-- 요청납기
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
-- 고객사요청사항
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
-- 품번/품명
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
-- S/N
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO,
|
||||
-- 수주수량
|
||||
COALESCE(PM.QUANTITY::numeric, CI.ORDER_QUANTITY::numeric, 0) AS QUANTITY,
|
||||
-- 추가생산수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS EXTRA_PROD_QTY,
|
||||
-- 총생산수량 (수주수량 + 추가생산수량)
|
||||
COALESCE(PM.QUANTITY::numeric, CI.ORDER_QUANTITY::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
-- 완조립 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS ASSEMBLY_QTY,
|
||||
-- 검사 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS INSPECTION_QTY,
|
||||
-- 출하대기 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS SHIP_WAIT_QTY,
|
||||
-- 장비조립WBS (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
'' AS EQUIPMENT_WBS,
|
||||
-- 생산계획 OBJID (있으면 수정, 없으면 신규)
|
||||
NULL AS PROD_PLAN_OBJID
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT OUTER JOIN CONTRACT_ITEM CI ON PM.CONTRACT_OBJID = CI.CONTRACT_OBJID
|
||||
AND PM.PART_OBJID = CI.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE 1=1
|
||||
AND PM.PROJECT_NO IS NOT NULL
|
||||
AND PM.PROJECT_NO != ''
|
||||
<!-- 프로젝트번호 검색 -->
|
||||
<if test="search_project_no != null and search_project_no != ''">
|
||||
AND UPPER(PM.PROJECT_NO) LIKE '%' || UPPER(#{search_project_no}) || '%'
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_code != null and search_product_code != ''">
|
||||
AND CM.PRODUCT = #{search_product_code}
|
||||
</if>
|
||||
<!-- 주문유형 검색 -->
|
||||
<if test="search_category_code != null and search_category_code != ''">
|
||||
AND CM.CATEGORY_CD = #{search_category_code}
|
||||
</if>
|
||||
<!-- 생산유형 검색 -->
|
||||
<if test="search_production_type != null and search_production_type != ''">
|
||||
AND 1=1 <!-- TODO: 생산유형 컬럼 확인 후 조건 추가 -->
|
||||
</if>
|
||||
<!-- 고객사 검색 -->
|
||||
<if test="search_customer_objid != null and search_customer_objid != ''">
|
||||
AND CM.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
</if>
|
||||
<!-- 요청납기 검색 -->
|
||||
<if test="search_req_del_date_from != null and search_req_del_date_from != ''">
|
||||
AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) >= #{search_req_del_date_from}
|
||||
</if>
|
||||
<if test="search_req_del_date_to != null and search_req_del_date_to != ''">
|
||||
AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) <= #{search_req_del_date_to}
|
||||
</if>
|
||||
<!-- 품번 검색 -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND (
|
||||
UPPER(PM.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
OR UPPER(CI.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
)
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND (
|
||||
UPPER(PM.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
OR UPPER(CI.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
)
|
||||
</if>
|
||||
<!-- S/N 검색 -->
|
||||
<if test="search_serial_no != null and search_serial_no != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND UPPER(CIS.SERIAL_NO) LIKE '%' || UPPER(#{search_serial_no}) || '%'
|
||||
)
|
||||
</if>
|
||||
ORDER BY PM.REGDATE DESC, PM.PROJECT_NO DESC
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트 정보 조회 (생산계획 폼용) -->
|
||||
<select id="getProdPlanProjectInfo" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO) AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME) AS PART_NAME,
|
||||
COALESCE(CM.PRODUCT, PM.PRODUCT) AS PRODUCT_CODE,
|
||||
COALESCE(CM.CATEGORY_CD, '') AS CATEGORY_CODE,
|
||||
COALESCE(CM.CUSTOMER_OBJID, PM.CUSTOMER_OBJID) AS CUSTOMER_OBJID,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
PM.QUANTITY AS ORDER_QTY,
|
||||
CM.CUSTOMER_REQUEST,
|
||||
(
|
||||
SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
SELECT * FROM (
|
||||
-- 1. 프로젝트 기반 데이터 (기존)
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
CM.PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
CM.CATEGORY_CD AS CATEGORY_CODE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.CATEGORY_CD LIMIT 1),
|
||||
CM.CATEGORY_CD
|
||||
) AS CATEGORY_CODE_NAME,
|
||||
COALESCE(PP.PRODUCTION_TYPE, '') AS PRODUCTION_TYPE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCTION_TYPE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCTION_TYPE_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
CASE
|
||||
WHEN CM.CUSTOMER_OBJID LIKE 'C_%' THEN
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG AS C WHERE 'C_' || C.OBJID::VARCHAR = CM.CUSTOMER_OBJID LIMIT 1)
|
||||
ELSE
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID::VARCHAR = CM.CUSTOMER_OBJID::VARCHAR LIMIT 1)
|
||||
END,
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
) AS SERIAL_NO
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE PM.OBJID = #{projectObjid}
|
||||
AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, NULLIF(CI.ORDER_QUANTITY, '')::numeric, 0) AS QUANTITY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, NULLIF(CI.ORDER_QUANTITY, '')::numeric, 0) + COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'ASSEMBLY' AND PR.STATUS = 'active'), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'INSPECTION' AND PR.STATUS = 'active'), 0) AS INSPECTION_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'SHIP_WAIT' AND PR.STATUS = 'active'), 0) AS SHIP_WAIT_QTY,
|
||||
'' AS EQUIPMENT_WBS,
|
||||
PP.OBJID AS PROD_PLAN_OBJID,
|
||||
PM.REGDATE AS SORT_DATE
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT OUTER JOIN CONTRACT_ITEM CI ON PM.CONTRACT_OBJID = CI.CONTRACT_OBJID
|
||||
AND PM.PART_OBJID = CI.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LEFT OUTER JOIN PRODUCTION_PLAN PP ON PP.PROJECT_OBJID = PM.OBJID
|
||||
AND PP.STATUS = 'active'
|
||||
WHERE PM.PROJECT_NO IS NOT NULL AND PM.PROJECT_NO != ''
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 2. 프로젝트 없이 등록한 생산계획
|
||||
SELECT
|
||||
PP.OBJID AS OBJID,
|
||||
'' AS PROJECT_NO,
|
||||
PP.PRODUCT_CODE AS PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCT_CODE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
PP.CATEGORY_CODE AS CATEGORY_CODE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.CATEGORY_CODE LIMIT 1),
|
||||
''
|
||||
) AS CATEGORY_CODE_NAME,
|
||||
COALESCE(PP.PRODUCTION_TYPE, '') AS PRODUCTION_TYPE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCTION_TYPE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCTION_TYPE_NAME,
|
||||
PP.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = PP.CUSTOMER_OBJID LIMIT 1),
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
PP.REQ_DEL_DATE,
|
||||
COALESCE(PP.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(PP.PART_NO, '') AS PART_NO,
|
||||
COALESCE(PP.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(PP.SERIAL_NO, '') AS SERIAL_NO,
|
||||
COALESCE(NULLIF(PP.ORDER_QTY, '')::numeric, 0) AS QUANTITY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(NULLIF(PP.TOTAL_PROD_QTY, '')::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'ASSEMBLY' AND PR.STATUS = 'active'), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'INSPECTION' AND PR.STATUS = 'active'), 0) AS INSPECTION_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'SHIP_WAIT' AND PR.STATUS = 'active'), 0) AS SHIP_WAIT_QTY,
|
||||
'' AS EQUIPMENT_WBS,
|
||||
PP.OBJID AS PROD_PLAN_OBJID,
|
||||
PP.REGDATE AS SORT_DATE
|
||||
FROM PRODUCTION_PLAN PP
|
||||
WHERE PP.STATUS = 'active'
|
||||
AND (PP.PROJECT_OBJID IS NULL OR PP.PROJECT_OBJID = '')
|
||||
) T
|
||||
WHERE 1=1
|
||||
<!-- 프로젝트번호 검색 (multiple select) -->
|
||||
<if test="search_project_nos != null and search_project_nos != ''">
|
||||
AND T.OBJID::VARCHAR IN
|
||||
<foreach item="projNo" collection="search_project_nos.split(',')" open="(" separator="," close=")">
|
||||
#{projNo}
|
||||
</foreach>
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_code != null and search_product_code != ''">
|
||||
AND T.PRODUCT = #{search_product_code}
|
||||
</if>
|
||||
<!-- 주문유형 검색 -->
|
||||
<if test="search_category_code != null and search_category_code != ''">
|
||||
AND T.CATEGORY_CODE = #{search_category_code}
|
||||
</if>
|
||||
<!-- 생산유형 검색 -->
|
||||
<if test="search_production_type != null and search_production_type != ''">
|
||||
AND T.PRODUCTION_TYPE = #{search_production_type}
|
||||
</if>
|
||||
<!-- 고객사 검색 -->
|
||||
<if test="search_customer_objid != null and search_customer_objid != ''">
|
||||
AND (
|
||||
T.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
OR T.CUSTOMER_OBJID = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
OR REPLACE(T.CUSTOMER_OBJID, 'C_', '') = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<!-- 요청납기 검색 -->
|
||||
<if test="search_req_del_date_from != null and search_req_del_date_from != ''">
|
||||
AND T.REQ_DEL_DATE >= #{search_req_del_date_from}
|
||||
</if>
|
||||
<if test="search_req_del_date_to != null and search_req_del_date_to != ''">
|
||||
AND T.REQ_DEL_DATE <= #{search_req_del_date_to}
|
||||
</if>
|
||||
<!-- 품번 검색 -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND UPPER(T.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND UPPER(T.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
</if>
|
||||
<!-- S/N 검색 -->
|
||||
<if test="search_serial_no != null and search_serial_no != ''">
|
||||
AND UPPER(T.SERIAL_NO) LIKE '%' || UPPER(#{search_serial_no}) || '%'
|
||||
</if>
|
||||
ORDER BY T.SORT_DATE DESC, T.PROJECT_NO DESC
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트 정보 조회 (생산계획 폼용) - PROJECT_MGMT 또는 PRODUCTION_PLAN에서 조회 -->
|
||||
<select id="getProdPlanProjectInfo" parameterType="map" resultType="map">
|
||||
SELECT * FROM (
|
||||
-- 1. PROJECT_MGMT 기반 조회
|
||||
SELECT
|
||||
PM.OBJID::VARCHAR AS OBJID,
|
||||
COALESCE(PM.PROJECT_NO, '') AS PROJECT_NO,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(CM.PRODUCT, PM.PRODUCT, '') AS PRODUCT_CODE,
|
||||
COALESCE(CM.CATEGORY_CD, '') AS CATEGORY_CODE,
|
||||
COALESCE(CM.CUSTOMER_OBJID, PM.CUSTOMER_OBJID, '')::VARCHAR AS CUSTOMER_OBJID,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE, '') AS REQ_DEL_DATE,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, 0) AS ORDER_QTY,
|
||||
COALESCE((SELECT NULLIF(PP.EXTRA_PROD_QTY, '')::numeric FROM PRODUCTION_PLAN PP WHERE PP.PROJECT_OBJID = PM.OBJID AND UPPER(PP.STATUS) = 'ACTIVE' LIMIT 1), 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(CM.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE((
|
||||
SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
), '') AS SERIAL_NO
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE PM.OBJID::VARCHAR = #{projectObjid}
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 2. PRODUCTION_PLAN 기반 조회 (OBJID로 직접 조회)
|
||||
SELECT
|
||||
PP.OBJID::VARCHAR AS OBJID,
|
||||
'' AS PROJECT_NO,
|
||||
COALESCE(PP.PART_NO, '') AS PART_NO,
|
||||
COALESCE(PP.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(PP.PRODUCT_CODE, '') AS PRODUCT_CODE,
|
||||
COALESCE(PP.CATEGORY_CODE, '') AS CATEGORY_CODE,
|
||||
COALESCE(PP.CUSTOMER_OBJID, '')::VARCHAR AS CUSTOMER_OBJID,
|
||||
COALESCE(PP.REQ_DEL_DATE, '') AS REQ_DEL_DATE,
|
||||
COALESCE(NULLIF(PP.ORDER_QTY, '')::numeric, 0) AS ORDER_QTY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(PP.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(PP.SERIAL_NO, '') AS SERIAL_NO
|
||||
FROM PRODUCTION_PLAN PP
|
||||
WHERE PP.OBJID::VARCHAR = #{projectObjid}
|
||||
) T
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
@@ -4639,4 +4747,178 @@
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 생산실적 목록 조회 -->
|
||||
<select id="getProdResultList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
OBJID,
|
||||
PROJECT_OBJID,
|
||||
RESULT_TYPE,
|
||||
TO_CHAR(RESULT_DATE::DATE, 'YYYY-MM-DD') AS RESULT_DATE,
|
||||
RESULT_QTY,
|
||||
SERIAL_NO,
|
||||
WORKER_ID,
|
||||
WORKER_NAME,
|
||||
REMARK,
|
||||
STATUS
|
||||
FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND STATUS = 'active'
|
||||
<if test="resultType != null and resultType != ''">
|
||||
AND RESULT_TYPE = #{resultType}
|
||||
</if>
|
||||
ORDER BY RESULT_DATE DESC, REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 등록 -->
|
||||
<insert id="insertProdResult" parameterType="map">
|
||||
INSERT INTO PRODUCTION_RESULT (
|
||||
OBJID,
|
||||
PROJECT_OBJID,
|
||||
RESULT_TYPE,
|
||||
RESULT_DATE,
|
||||
RESULT_QTY,
|
||||
ROW_SEQ,
|
||||
SERIAL_NO,
|
||||
WORKER_ID,
|
||||
WORKER_NAME,
|
||||
REMARK,
|
||||
STATUS,
|
||||
REGDATE,
|
||||
WRITER
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
#{PROJECT_OBJID},
|
||||
#{RESULT_TYPE},
|
||||
#{RESULT_DATE},
|
||||
#{RESULT_QTY},
|
||||
#{ROW_SEQ},
|
||||
#{SERIAL_NO},
|
||||
#{userId},
|
||||
#{WORKER_NAME},
|
||||
#{REMARK},
|
||||
'active',
|
||||
NOW(),
|
||||
#{userId}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 생산실적 수정 -->
|
||||
<update id="updateProdResult" parameterType="map">
|
||||
UPDATE PRODUCTION_RESULT SET
|
||||
RESULT_TYPE = #{RESULT_TYPE},
|
||||
RESULT_DATE = #{RESULT_DATE},
|
||||
RESULT_QTY = #{RESULT_QTY},
|
||||
SERIAL_NO = #{SERIAL_NO},
|
||||
WORKER_NAME = #{WORKER_NAME},
|
||||
REMARK = #{REMARK},
|
||||
MODDATE = NOW(),
|
||||
MODIFIER = #{userId}
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- M-BOM 반제품 항목 조회 (PART_TYPE이 부품(0001812), 조립품(0001813)인 항목만, 1레벨 제외) -->
|
||||
<select id="getMbomSemiProductItems" parameterType="map" resultType="map">
|
||||
/* productionplanning.getMbomSemiProductItems - M-BOM에서 부품/조립품 조회 (1레벨 제외) */
|
||||
SELECT
|
||||
MD.PART_NO,
|
||||
MD.PART_NAME,
|
||||
COALESCE(MD.QTY, '1')::INTEGER AS ITEM_QTY,
|
||||
P.PART_TYPE,
|
||||
COALESCE((SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = P.PART_TYPE LIMIT 1), '') AS CATEGORY_NAME,
|
||||
COALESCE(P.UNIT, '') AS UNIT,
|
||||
COALESCE(P.MATERIAL, '') AS MATERIAL,
|
||||
COALESCE(P.SPEC, '') AS SPEC
|
||||
FROM MBOM_DETAIL MD
|
||||
INNER JOIN PART_MNG P ON P.OBJID::VARCHAR = MD.PART_OBJID
|
||||
WHERE MD.MBOM_HEADER_OBJID = #{mbomHeaderObjid}
|
||||
AND MD.STATUS = 'ACTIVE'
|
||||
AND (MD.PARENT_OBJID IS NOT NULL AND MD.PARENT_OBJID != '') -- 1레벨 제외 (PARENT_OBJID가 있는 항목만)
|
||||
AND P.PART_TYPE IN ('0001812', '0001813') -- 부품, 조립품
|
||||
ORDER BY P.PART_TYPE, MD.PART_NO
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 원자재(구매품) 항목 조회 (PART_TYPE이 구매품(0000063)인 항목만, 1레벨 제외) -->
|
||||
<select id="getMbomRawMaterialItems" parameterType="map" resultType="map">
|
||||
/* productionplanning.getMbomRawMaterialItems - M-BOM에서 구매품 조회 (1레벨 제외) */
|
||||
SELECT
|
||||
MD.PART_NO,
|
||||
MD.PART_NAME,
|
||||
COALESCE(MD.QTY, '1')::INTEGER AS ITEM_QTY,
|
||||
P.PART_TYPE,
|
||||
COALESCE((SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = P.PART_TYPE LIMIT 1), '') AS CATEGORY_NAME,
|
||||
COALESCE(P.UNIT, '') AS UNIT,
|
||||
COALESCE(P.MATERIAL, '') AS MATERIAL,
|
||||
COALESCE(P.SPEC, '') AS SPEC,
|
||||
'' AS RAW_MATERIAL,
|
||||
'' AS RAW_MATERIAL_SIZE,
|
||||
'' AS RAW_MATERIAL_PART_NO,
|
||||
0 AS RAW_MATERIAL_QTY
|
||||
FROM MBOM_DETAIL MD
|
||||
INNER JOIN PART_MNG P ON P.OBJID::VARCHAR = MD.PART_OBJID
|
||||
WHERE MD.MBOM_HEADER_OBJID = #{mbomHeaderObjid}
|
||||
AND MD.STATUS = 'ACTIVE'
|
||||
AND (MD.PARENT_OBJID IS NOT NULL AND MD.PARENT_OBJID != '') -- 1레벨 제외 (PARENT_OBJID가 있는 항목만)
|
||||
AND P.PART_TYPE = '0000063' -- 구매품
|
||||
ORDER BY MD.PART_NO
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 원소재 항목 조회 (RAW_MATERIAL_PART_NO가 있는 항목만) -->
|
||||
<select id="getMbomRawSourceItems" parameterType="map" resultType="map">
|
||||
/* productionplanning.getMbomRawSourceItems - M-BOM에서 원소재 조회 */
|
||||
SELECT
|
||||
MD.RAW_MATERIAL_PART_NO AS PART_NO,
|
||||
MD.RAW_MATERIAL AS PART_NAME,
|
||||
COALESCE(MD.REQUIRED_QTY, '0')::NUMERIC AS ITEM_QTY,
|
||||
'원소재' AS CATEGORY_NAME,
|
||||
'' AS UNIT,
|
||||
MD.RAW_MATERIAL AS MATERIAL,
|
||||
MD.RAW_MATERIAL_SIZE AS SPEC,
|
||||
MD.RAW_MATERIAL,
|
||||
MD.RAW_MATERIAL_SIZE,
|
||||
MD.RAW_MATERIAL_PART_NO,
|
||||
COALESCE(MD.REQUIRED_QTY, '0')::NUMERIC AS RAW_MATERIAL_QTY
|
||||
FROM MBOM_DETAIL MD
|
||||
WHERE MD.MBOM_HEADER_OBJID = #{mbomHeaderObjid}
|
||||
AND MD.STATUS = 'ACTIVE'
|
||||
AND MD.RAW_MATERIAL_PART_NO IS NOT NULL
|
||||
AND MD.RAW_MATERIAL_PART_NO != ''
|
||||
ORDER BY MD.RAW_MATERIAL_PART_NO
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 날짜별 조회 (피봇) -->
|
||||
<select id="getProdResultListByDate" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
ROW_SEQ,
|
||||
RESULT_DATE,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'ASSEMBLY' THEN RESULT_QTY ELSE 0 END), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'INSPECTION' THEN RESULT_QTY ELSE 0 END), 0) AS INSPECTION_QTY,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'SHIP_WAIT' THEN RESULT_QTY ELSE 0 END), 0) AS SHIP_WAIT_QTY,
|
||||
MAX(REMARK) AS REMARK
|
||||
FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND STATUS = 'active'
|
||||
GROUP BY ROW_SEQ, RESULT_DATE
|
||||
ORDER BY ROW_SEQ ASC
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 행별 삭제 -->
|
||||
<delete id="deleteProdResultByRowSeq" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND ROW_SEQ = #{rowSeq}
|
||||
</delete>
|
||||
|
||||
<!-- 생산실적 날짜별 삭제 (기존 데이터 삭제 후 재입력용) -->
|
||||
<delete id="deleteProdResultByDate" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND RESULT_DATE = #{resultDate}
|
||||
</delete>
|
||||
|
||||
<!-- 생산실적 프로젝트 전체 삭제 -->
|
||||
<delete id="deleteProdResultByProject" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -4218,12 +4218,20 @@
|
||||
AND result_cd = #{result_cd}
|
||||
</if>
|
||||
|
||||
<!-- 요청납기일 필터: REQ_DEL_DATE 로직과 동일하게 COALESCE 사용 -->
|
||||
<if test="contract_start_date != null and !''.equals(contract_start_date)">
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{contract_start_date}, 'YYYY-MM-DD')
|
||||
|
||||
AND TO_DATE(COALESCE(
|
||||
(SELECT CI.DUE_DATE FROM CONTRACT_ITEM CI WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID AND CI.PART_OBJID = T.PART_OBJID AND CI.STATUS = 'ACTIVE'),
|
||||
T.DUE_DATE,
|
||||
(SELECT CM.due_date FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID)
|
||||
),'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{contract_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="contract_end_date != null and !''.equals(contract_end_date)">
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{contract_end_date}, 'YYYY-MM-DD')
|
||||
AND TO_DATE(COALESCE(
|
||||
(SELECT CI.DUE_DATE FROM CONTRACT_ITEM CI WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID AND CI.PART_OBJID = T.PART_OBJID AND CI.STATUS = 'ACTIVE'),
|
||||
T.DUE_DATE,
|
||||
(SELECT CM.due_date FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID)
|
||||
),'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{contract_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="pm_user_id !=null and pm_user_id !=''">
|
||||
@@ -4235,6 +4243,38 @@
|
||||
<if test="setup != null and !''.equals(setup)">
|
||||
AND UPPER(SETUP) LIKE UPPER('%${setup}%')
|
||||
</if>
|
||||
<!-- 국내/해외 필터 -->
|
||||
<if test="area_cd != null and area_cd != ''">
|
||||
AND CODE_NAME(AREA_CD) = #{area_cd}
|
||||
</if>
|
||||
<!-- 유/무상 필터 -->
|
||||
<if test="free_of_charge != null and free_of_charge != ''">
|
||||
AND (SELECT
|
||||
CASE
|
||||
WHEN O.PAID_TYPE = 'paid' THEN '유상'
|
||||
WHEN O.PAID_TYPE = 'free' THEN '무상'
|
||||
ELSE O.PAID_TYPE
|
||||
END
|
||||
FROM CONTRACT_MGMT AS O WHERE O.OBJID = T.CONTRACT_OBJID) = #{free_of_charge}
|
||||
</if>
|
||||
<!-- 품번 필터 -->
|
||||
<if test="product_item_code != null and product_item_code != ''">
|
||||
AND UPPER(T.PART_NO) LIKE UPPER('%' || #{product_item_code} || '%')
|
||||
</if>
|
||||
<!-- 품명 필터 -->
|
||||
<if test="product_item_name != null and product_item_name != ''">
|
||||
AND UPPER(T.PART_NAME) LIKE UPPER('%' || #{product_item_name} || '%')
|
||||
</if>
|
||||
<!-- S/N 필터 -->
|
||||
<if test="serial_no != null and serial_no != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM CONTRACT_ITEM AS I
|
||||
LEFT JOIN CONTRACT_ITEM_SERIAL AS S ON S.ITEM_OBJID = I.OBJID AND S.STATUS = 'ACTIVE'
|
||||
WHERE I.CONTRACT_OBJID = T.CONTRACT_OBJID
|
||||
AND I.PART_OBJID = T.PART_OBJID
|
||||
AND UPPER(S.SERIAL_NO) LIKE UPPER('%' || #{serial_no} || '%')
|
||||
)
|
||||
</if>
|
||||
ORDER BY SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1) DESC, OVERHAUL_ORDER DESC NULLS LAST
|
||||
</select>
|
||||
|
||||
|
||||
@@ -1429,6 +1429,9 @@
|
||||
|
||||
-- 요청사항
|
||||
,POM.REQUEST_CONTENT
|
||||
|
||||
-- 양식 타입 (general/outsourcing)
|
||||
,COALESCE(POM.FORM_TYPE, 'general') AS FORM_TYPE
|
||||
FROM
|
||||
PURCHASE_ORDER_MASTER POM
|
||||
|
||||
@@ -2944,7 +2947,7 @@ WHERE 1=1
|
||||
AND EXISTS (
|
||||
SELECT 'E' FROM PROJECT_MGMT AS S_P
|
||||
WHERE POM.CONTRACT_MGMT_OBJID = S_P.OBJID
|
||||
AND S_P.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND S_P.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
@@ -2972,7 +2975,7 @@ WHERE 1=1
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
AND POM.SALES_MNG_USER_ID = #{sales_mng_user_id}
|
||||
@@ -3107,7 +3110,7 @@ SELECT
|
||||
AND EXISTS (
|
||||
SELECT 'E' FROM PROJECT_MGMT AS S_P
|
||||
WHERE POM.CONTRACT_MGMT_OBJID = S_P.OBJID
|
||||
AND S_P.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND S_P.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
@@ -3135,7 +3138,7 @@ SELECT
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
AND POM.SALES_MNG_USER_ID = #{sales_mng_user_id}
|
||||
@@ -3337,7 +3340,7 @@ WHERE 1=1
|
||||
AND EXISTS (
|
||||
SELECT 'E' FROM PROJECT_MGMT AS S_P
|
||||
WHERE POM.CONTRACT_MGMT_OBJID = S_P.OBJID
|
||||
AND S_P.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND S_P.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
@@ -3372,7 +3375,7 @@ WHERE 1=1
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<!--
|
||||
<if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
@@ -3386,12 +3389,21 @@ WHERE 1=1
|
||||
#{value}
|
||||
</foreach>
|
||||
</if>
|
||||
<!-- 주문유형 필터 -->
|
||||
<if test="category_cd != null and category_cd != ''">
|
||||
AND CM.CATEGORY_CD = #{category_cd}
|
||||
</if>
|
||||
<!-- 제품구분 필터 -->
|
||||
<if test="product_cd != null and product_cd != ''">
|
||||
AND CM.PRODUCT = #{product_cd}
|
||||
</if>
|
||||
|
||||
<!-- 발주일 필터: MAIL_SEND_DATE (그리드 컬럼과 일치) -->
|
||||
<if test="reg_start_date !=null and reg_start_date != '' ">
|
||||
AND TO_DATE(TO_CHAR(POM.REGDATE,'YYYY-MM-DD') ,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{reg_start_date}, 'YYYY-MM-DD')
|
||||
AND TO_DATE(POM.MAIL_SEND_DATE, 'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{reg_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="reg_end_date !=null and reg_end_date != '' ">
|
||||
AND TO_DATE(TO_CHAR(POM.REGDATE,'YYYY-MM-DD') ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{reg_end_date}, 'YYYY-MM-DD')
|
||||
AND TO_DATE(POM.MAIL_SEND_DATE, 'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{reg_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="appr_status !=null and appr_status != '' ">
|
||||
<choose>
|
||||
@@ -3564,7 +3576,7 @@ WHERE 1=1
|
||||
AND EXISTS (
|
||||
SELECT 'E' FROM PROJECT_MGMT AS S_P
|
||||
WHERE POM.CONTRACT_MGMT_OBJID = S_P.OBJID
|
||||
AND S_P.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND S_P.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
@@ -3599,7 +3611,7 @@ WHERE 1=1
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<!--
|
||||
<if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
@@ -4374,7 +4386,7 @@ SELECT POM.OBJID
|
||||
AND TO_CHAR(TO_DATE(S1.CUR_DELIVERY_DATE ,'YYYY-MM-DD'), 'YYYY') = #{Year}
|
||||
</if>
|
||||
<if test="customer_cd !=null and customer_cd != '' ">
|
||||
AND CM.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND CM.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
AND TRIM(UPPER(CM.CUSTOMER_PROJECT_NAME)) = TRIM(UPPER(#{customer_project_name}))
|
||||
@@ -4405,7 +4417,7 @@ SELECT POM.OBJID
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<!-- <if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
AND POM.SALES_MNG_USER_ID = #{sales_mng_user_id}
|
||||
@@ -4424,7 +4436,7 @@ SELECT POM.OBJID
|
||||
AND TO_DATE(TO_CHAR(POM.REGDATE,'YYYY-MM-DD') ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{reg_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="delivery_status !=null and delivery_status != '' ">
|
||||
AND (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 '입고완료'
|
||||
AND (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) = #{delivery_status}
|
||||
|
||||
@@ -711,10 +711,9 @@
|
||||
,DEFECT.INSPECTOR_NAME_DISPLAY AS INSPECTOR_NAME
|
||||
/* 검사일: YYYY-MM-DD 외 N건 형태 */
|
||||
,DEFECT.INSPECTION_DATE_DISPLAY AS INSPECTION_DATE
|
||||
/* 검사결과: 하나라도 NG면 NG, 검사 대상(스킵 제외) 모두 검사완료면 OK, 일부만 검사면 검사중 */
|
||||
,(CASE WHEN DEFECT.NG_COUNT > 0 THEN 'NG'
|
||||
WHEN DEFECT.INSPECTION_TARGET_COUNT > 0 AND DEFECT.INSPECTION_TARGET_COUNT = DEFECT.INSPECTED_COUNT THEN 'OK'
|
||||
WHEN DEFECT.INSPECTED_COUNT > 0 THEN '검사중'
|
||||
/* 검사현황: 불량상세 처리결과(ACTION_RESULT)가 전부 있으면 완료, 일부만 있으면 진행중 */
|
||||
,(CASE WHEN DEFECT.DEFECT_TOTAL_COUNT > 0 AND DEFECT.DEFECT_TOTAL_COUNT = DEFECT.ACTION_RESULT_COUNT THEN '완료'
|
||||
WHEN DEFECT.ACTION_RESULT_COUNT > 0 THEN '진행중'
|
||||
ELSE '' END) AS INSPECTION_RESULT
|
||||
|
||||
/* 검사여부: 검사가 하나라도 있으면 '검사', 모두 스킵이면 '스킵', 아무것도 없으면 빈값 */
|
||||
@@ -764,6 +763,10 @@
|
||||
END AS INSPECTION_DATE_DISPLAY
|
||||
/* 검사 대상 건수 (스킵 제외, 검사인 항목만) */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' THEN 1 END) AS INSPECTION_TARGET_COUNT
|
||||
/* 불량상세 테이블 전체 건수 (검사인 항목 기준) */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' THEN IDF.OBJID END) AS DEFECT_TOTAL_COUNT
|
||||
/* 처리결과(ACTION_RESULT) 입력된 건수 */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' AND IDF.ACTION_RESULT IS NOT NULL AND IDF.ACTION_RESULT != '' THEN 1 END) AS ACTION_RESULT_COUNT
|
||||
/* 검사결과 입력된 건수 */
|
||||
,COUNT(CASE WHEN IDF.INSPECTION_RESULT IS NOT NULL AND IDF.INSPECTION_RESULT != '' THEN 1 END) AS INSPECTED_COUNT
|
||||
,COUNT(CASE WHEN IDF.INSPECTION_RESULT = 'NG' THEN 1 END) AS NG_COUNT
|
||||
@@ -827,37 +830,98 @@
|
||||
ELSE '입고중'
|
||||
END) = #{search_delivery_status}
|
||||
</if>
|
||||
<!-- 프로젝트번호 (multi select) -->
|
||||
<!-- 프로젝트번호 (multi select) - OBJID로 검색 -->
|
||||
<if test="project_nos != null and project_nos != ''">
|
||||
AND CM.PROJECT_NO IN
|
||||
AND CM.OBJID::VARCHAR IN
|
||||
<foreach item="item" collection="project_nos.split(',')" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<!-- 검사자 -->
|
||||
<if test="inspector_id != null and inspector_id != ''">
|
||||
AND IID.INSPECTOR_ID = #{inspector_id}
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM INCOMING_INSPECTION_DETAIL IID_SUB
|
||||
LEFT JOIN INCOMING_INSPECTION_DEFECT IDF_SUB ON IDF_SUB.INSPECTION_DETAIL_OBJID = IID_SUB.OBJID
|
||||
WHERE IID_SUB.PURCHASE_ORDER_MASTER_OBJID = POM.OBJID::VARCHAR
|
||||
AND IDF_SUB.INSPECTOR_ID = #{inspector_id}
|
||||
)
|
||||
</if>
|
||||
<!-- 검사일 (시작) -->
|
||||
<if test="inspection_start_date != null and inspection_start_date != ''">
|
||||
AND IID.INSPECTION_DATE <![CDATA[ >= ]]> #{inspection_start_date}
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM INCOMING_INSPECTION_DETAIL IID_SUB
|
||||
LEFT JOIN INCOMING_INSPECTION_DEFECT IDF_SUB ON IDF_SUB.INSPECTION_DETAIL_OBJID = IID_SUB.OBJID
|
||||
WHERE IID_SUB.PURCHASE_ORDER_MASTER_OBJID = POM.OBJID::VARCHAR
|
||||
AND IDF_SUB.INSPECTION_DATE <![CDATA[ >= ]]> TO_DATE(#{inspection_start_date}, 'YYYY-MM-DD')
|
||||
)
|
||||
</if>
|
||||
<!-- 검사일 (종료) -->
|
||||
<if test="inspection_end_date != null and inspection_end_date != ''">
|
||||
AND IID.INSPECTION_DATE <![CDATA[ <= ]]> #{inspection_end_date}
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM INCOMING_INSPECTION_DETAIL IID_SUB
|
||||
LEFT JOIN INCOMING_INSPECTION_DEFECT IDF_SUB ON IDF_SUB.INSPECTION_DETAIL_OBJID = IID_SUB.OBJID
|
||||
WHERE IID_SUB.PURCHASE_ORDER_MASTER_OBJID = POM.OBJID::VARCHAR
|
||||
AND IDF_SUB.INSPECTION_DATE <![CDATA[ <= ]]> TO_DATE(#{inspection_end_date}, 'YYYY-MM-DD')
|
||||
)
|
||||
</if>
|
||||
<!-- 검사결과 -->
|
||||
<if test="search_inspection_result != null and search_inspection_result != ''">
|
||||
AND (CASE WHEN IID.NG_COUNT > 0 THEN 'NG'
|
||||
WHEN IID.TOTAL_COUNT > 0 AND IID.TOTAL_COUNT = IID.INSPECTED_COUNT THEN 'OK'
|
||||
WHEN IID.INSPECTED_COUNT > 0 THEN '검사중'
|
||||
AND (CASE WHEN DEFECT.NG_COUNT > 0 THEN 'NG'
|
||||
WHEN DEFECT.INSPECTION_TARGET_COUNT > 0 AND DEFECT.INSPECTION_TARGET_COUNT = DEFECT.INSPECTED_COUNT THEN 'OK'
|
||||
WHEN DEFECT.INSPECTED_COUNT > 0 THEN '검사중'
|
||||
ELSE '' END) = #{search_inspection_result}
|
||||
</if>
|
||||
<!-- 요청자 -->
|
||||
<if test="request_user_id != null and request_user_id != ''">
|
||||
AND IID.REQUEST_USER_ID = #{request_user_id}
|
||||
</if>
|
||||
<!-- 요청일 (시작) -->
|
||||
<if test="request_start_date != null and request_start_date != ''">
|
||||
AND IID.REQUEST_DATE <![CDATA[ >= ]]> #{request_start_date}
|
||||
</if>
|
||||
<!-- 요청일 (종료) -->
|
||||
<if test="request_end_date != null and request_end_date != ''">
|
||||
AND IID.REQUEST_DATE <![CDATA[ <= ]]> #{request_end_date}
|
||||
</if>
|
||||
<!-- 요청현황 필터 (수입검사 진행 리스트에서 요청완료 건만 조회) -->
|
||||
<if test="request_status_filter != null and request_status_filter == '요청완료'">
|
||||
AND REQ.DELIVERY_TOTAL_COUNT = REQ.SELECTED_COUNT
|
||||
AND REQ.SELECTED_COUNT > 0
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_cd != null and search_product_cd != ''">
|
||||
AND CM.PRODUCT = #{search_product_cd}
|
||||
</if>
|
||||
<!-- 검사여부 검색 -->
|
||||
<if test="search_inspection_yn != null and search_inspection_yn != ''">
|
||||
<if test="search_inspection_yn == '검사'">
|
||||
AND IID.INSPECTION_YN_COUNT > 0
|
||||
</if>
|
||||
<if test="search_inspection_yn == '스킵'">
|
||||
AND IID.SKIP_YN_COUNT > 0 AND IID.INSPECTION_YN_COUNT = 0
|
||||
</if>
|
||||
</if>
|
||||
<!-- 요청현황 검색 -->
|
||||
<if test="search_request_status != null and search_request_status != ''">
|
||||
<if test="search_request_status == '미요청'">
|
||||
AND REQ.DELIVERY_TOTAL_COUNT > 0 AND REQ.SELECTED_COUNT = 0
|
||||
</if>
|
||||
<if test="search_request_status == '요청중'">
|
||||
AND REQ.SELECTED_COUNT > 0 AND REQ.SELECTED_COUNT <![CDATA[ < ]]> REQ.DELIVERY_TOTAL_COUNT
|
||||
</if>
|
||||
<if test="search_request_status == '요청완료'">
|
||||
AND REQ.DELIVERY_TOTAL_COUNT > 0 AND REQ.SELECTED_COUNT = REQ.DELIVERY_TOTAL_COUNT
|
||||
</if>
|
||||
</if>
|
||||
<!-- 검사현황 검색 -->
|
||||
<if test="search_inspection_status != null and search_inspection_status != ''">
|
||||
<if test="search_inspection_status == '완료'">
|
||||
AND DEFECT.DEFECT_TOTAL_COUNT > 0 AND DEFECT.DEFECT_TOTAL_COUNT = DEFECT.ACTION_RESULT_COUNT
|
||||
</if>
|
||||
<if test="search_inspection_status == '진행중'">
|
||||
AND DEFECT.ACTION_RESULT_COUNT > 0 AND DEFECT.DEFECT_TOTAL_COUNT != DEFECT.ACTION_RESULT_COUNT
|
||||
</if>
|
||||
</if>
|
||||
ORDER BY POM.REGDATE DESC
|
||||
</select>
|
||||
|
||||
@@ -1081,6 +1145,7 @@
|
||||
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
) AS INSPECTION_RESULT
|
||||
, PIM.REMARK
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO F WHERE F.TARGET_OBJID = PIM.OBJID AND F.DOC_TYPE = 'PROCESS_INSPECTION_FILE' AND UPPER(F.STATUS) = 'ACTIVE') AS PROCESS_INSPECTION_FILE_CNT
|
||||
FROM PROCESS_INSPECTION_MASTER PIM
|
||||
WHERE 1=1
|
||||
/* 프로젝트번호 */
|
||||
@@ -1096,23 +1161,23 @@
|
||||
WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
AND PM.PRODUCT = #{productType})
|
||||
</if>
|
||||
/* 품번 */
|
||||
/* 품번 (OBJID 또는 품번 텍스트로 검색) */
|
||||
<if test="search_part_objid != null and search_part_objid != ''">
|
||||
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
|
||||
WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
AND PID.PART_OBJID = #{search_part_objid})
|
||||
AND (PID.PART_OBJID = #{search_part_objid} OR UPPER(PID.PART_NO) LIKE '%' || UPPER(#{search_part_objid}) || '%'))
|
||||
</if>
|
||||
/* 품명 */
|
||||
/* 품명 (LIKE 검색) */
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
|
||||
WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
AND PID.PART_OBJID = #{search_part_name})
|
||||
AND UPPER(PID.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%')
|
||||
</if>
|
||||
/* 작업환경상태 */
|
||||
/* 작업환경상태 (화면 표시 로직과 동일하게: 하나라도 불량이면 불량) */
|
||||
<if test="search_work_env_status != null and search_work_env_status != ''">
|
||||
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
|
||||
WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
AND PID.WORK_ENV_STATUS = CASE WHEN #{search_work_env_status} = 'OK' THEN '양호' ELSE '불량' END)
|
||||
AND (SELECT CASE WHEN COUNT(CASE WHEN PID.WORK_ENV_STATUS = '불량' THEN 1 END) > 0 THEN '불량' ELSE '양호' END
|
||||
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
) = CASE WHEN #{search_work_env_status} = 'OK' THEN '양호' ELSE '불량' END
|
||||
</if>
|
||||
/* 측정기 */
|
||||
<if test="search_measuring_device != null and search_measuring_device != ''">
|
||||
@@ -1638,6 +1703,7 @@
|
||||
, COALESCE(SPI.WORK_ORDER_NO, '') AS "WORK_ORDER_NO"
|
||||
, COALESCE(SPI.PART_NO, '') AS "PART_NO"
|
||||
, COALESCE(SPI.PART_NAME, '') AS "PART_NAME"
|
||||
, COALESCE(PM.OBJID::VARCHAR, '') AS "PART_OBJID"
|
||||
, COALESCE(SPI.RECEIPT_QTY, 0) AS "RECEIPT_QTY"
|
||||
, COALESCE(SPI.GOOD_QTY, 0) AS "GOOD_QTY"
|
||||
, COALESCE(SPI.DEFECT_QTY, 0) AS "DEFECT_QTY"
|
||||
@@ -1657,6 +1723,7 @@
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = SPI.OBJID AND AFI.DOC_TYPE = 'SEMI_INSPECTION_NCR' AND AFI.STATUS = 'Active') AS "NCR_FILE_CNT"
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = SPI.OBJID AND AFI.DOC_TYPE = 'SEMI_INSPECTION_REPORT' AND AFI.STATUS = 'Active') AS "REPORT_FILE_CNT"
|
||||
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
|
||||
LEFT JOIN PART_MNG PM ON PM.PART_NO = SPI.PART_NO
|
||||
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})
|
||||
@@ -1802,6 +1869,13 @@
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 반제품검사 행 잠금 해제 (IS_LOCKED = 'N') -->
|
||||
<update id="unlockSemiProductInspection" parameterType="map">
|
||||
UPDATE PMS_QUALITY_SEMI_PRODUCT_INSPECTION
|
||||
SET IS_LOCKED = 'N'
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 반제품검사 데이터 삭제 (OBJID로 단건 삭제) -->
|
||||
<delete id="deleteSemiProductInspectionByObjId" parameterType="map">
|
||||
DELETE FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION
|
||||
@@ -2068,6 +2142,8 @@
|
||||
, ECR.COMPLETE_DATE
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = ECR.OBJID AND AFI.DOC_TYPE = 'ECR_RESULT_IMAGE' AND STATUS = 'Active') AS IMAGE_FILE
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = ECR.OBJID AND AFI.DOC_TYPE = 'ECR_RESULT' AND STATUS = 'Active') AS ATTACH_FILE
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = ECR.OBJID AND AFI.DOC_TYPE = 'ECR_DOC' AND STATUS = 'Active') AS ECR_DOC_FILE
|
||||
, CASE WHEN (ECR.ECR_DOC_SUMMARY IS NOT NULL AND ECR.ECR_DOC_SUMMARY != '') OR (ECR.ECR_DOC_REASON IS NOT NULL AND ECR.ECR_DOC_REASON != '') THEN 1 ELSE 0 END AS ECR_DOC_CNT
|
||||
FROM PMS_QUALITY_ECR ECR
|
||||
WHERE 1=1
|
||||
<if test="search_request_date_from != null and search_request_date_from != ''">
|
||||
@@ -2142,6 +2218,12 @@
|
||||
, ECR.REMARK
|
||||
, ECR.WRITER
|
||||
, TO_CHAR(ECR.REG_DATE, 'YYYY-MM-DD') AS REG_DATE
|
||||
, ECR.ECR_DOC_SUMMARY
|
||||
, ECR.ECR_DOC_REASON
|
||||
, ECR.ECR_REV_NO
|
||||
, ECR.ECR_REV_DATE
|
||||
, ECR.ECR_DOC_FORM_NO
|
||||
, ECR.ECR_DOC_AUTHOR
|
||||
FROM PMS_QUALITY_ECR ECR
|
||||
WHERE ECR.OBJID = #{OBJID}
|
||||
</select>
|
||||
@@ -2219,6 +2301,20 @@
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 설계변경요청서 저장 -->
|
||||
<update id="updateEcrDoc" parameterType="map">
|
||||
UPDATE PMS_QUALITY_ECR SET
|
||||
ECR_DOC_FORM_NO = #{ECR_DOC_FORM_NO}
|
||||
, ECR_REV_NO = #{ECR_REV_NO}
|
||||
, ECR_REV_DATE = #{ECR_REV_DATE}
|
||||
, ECR_DOC_AUTHOR = #{ECR_DOC_AUTHOR}
|
||||
, ECR_DOC_SUMMARY = #{ECR_DOC_SUMMARY}
|
||||
, ECR_DOC_REASON = #{ECR_DOC_REASON}
|
||||
, MODIFIER = #{MODIFIER}
|
||||
, MOD_DATE = NOW()
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- =====================================================
|
||||
수입검사 상세 그리드 목록 (입고 결과 기준)
|
||||
===================================================== -->
|
||||
@@ -2259,6 +2355,14 @@
|
||||
, IID.REMARK
|
||||
, IMI.PURCHASE_ORDER_MASTER_OBJID
|
||||
, POM.PURCHASE_ORDER_NO
|
||||
/* 불량수량 합계 (INCOMING_INSPECTION_DETAIL.DEFECT_QTY에 저장된 값 사용) */
|
||||
, COALESCE(NULLIF(IID.DEFECT_QTY, '')::NUMERIC, 0) AS DEFECT_QTY_SUM
|
||||
/* 불량율 (불량수량합계 / 입고수량 * 100) */
|
||||
, CASE WHEN IMI.RECEIPT_QTY::NUMERIC > 0
|
||||
THEN ROUND(COALESCE(NULLIF(IID.DEFECT_QTY, '')::NUMERIC, 0) / IMI.RECEIPT_QTY::NUMERIC * 100, 2)
|
||||
ELSE NULL END AS LEFT_DEFECT_RATE
|
||||
/* 검사성적서 파일 수 */
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = IID.OBJID AND AFI.DOC_TYPE = 'INSPECTION_REPORT' AND UPPER(AFI.STATUS) = 'ACTIVE') AS INSPECTION_FILE_CNT
|
||||
FROM INVENTORY_MGMT_IN IMI
|
||||
INNER JOIN INVENTORY_MGMT IM ON IM.OBJID = IMI.PARENT_OBJID
|
||||
INNER JOIN PART_MNG PM ON PM.OBJID::VARCHAR = IM.PART_OBJID
|
||||
|
||||
@@ -665,6 +665,9 @@ VALUES
|
||||
SRM.PROJECT_NO,
|
||||
PM.PROJECT_NO AS PROJECT_NUMBER,
|
||||
PM.PROJECT_NAME,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
PM.DUE_DATE,
|
||||
COALESCE(
|
||||
PM.OBJID,
|
||||
(SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1)
|
||||
@@ -718,9 +721,9 @@ VALUES
|
||||
COALESCE(NULLIF(SRM.AREA_CD, ''), SM.AREA_CD) AS AREA_CD, -- 국내/해외
|
||||
COALESCE(NULLIF(SRM.CUSTOMER_OBJID, ''), SM.OBJID::VARCHAR) AS CUSTOMER_OBJID, -- 고객사
|
||||
COALESCE(NULLIF(SRM.PAID_TYPE, ''), CM.PAID_TYPE) AS PAID_TYPE, -- 유/무상
|
||||
CM.CATEGORY_CD AS CATEGORY_CD, -- 제품유형 코드 ID (드롭다운 선택용)
|
||||
CM.CATEGORY_CD AS CATEGORY_CD -- 제품유형 코드 ID (드롭다운 선택용)
|
||||
-- 품번/품명: 첫 번째 품목 + 외 N건 형태
|
||||
(SELECT
|
||||
<!-- (SELECT
|
||||
CASE
|
||||
WHEN (SELECT COUNT(*) FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID) > 1 THEN
|
||||
COALESCE((SELECT PM2.PART_NO FROM PART_MNG PM2 WHERE PM2.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)), '') || ' 외 ' || ((SELECT COUNT(*) FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID) - 1)::TEXT || '건'
|
||||
@@ -735,7 +738,7 @@ VALUES
|
||||
ELSE
|
||||
COALESCE((SELECT PM2.PART_NAME FROM PART_MNG PM2 WHERE PM2.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)), '')
|
||||
END
|
||||
) AS PART_NAME
|
||||
) AS PART_NAME -->
|
||||
|
||||
FROM
|
||||
SALES_REQUEST_MASTER SRM
|
||||
@@ -3084,7 +3087,7 @@ UPDATE SET
|
||||
0 AS ORDER_QTY,
|
||||
0 AS ITEM_QTY2,
|
||||
0 AS PRODUCTION_QTY,
|
||||
'' AS PROCESSING_VENDOR,
|
||||
COALESCE(SRP.PROCESSING_VENDOR, '') AS PROCESSING_VENDOR,
|
||||
NULL AS PROCESSING_DEADLINE,
|
||||
NULL AS GRINDING_DEADLINE,
|
||||
-- 구매 관련 컬럼 (SALES_REQUEST_PART에서 조회)
|
||||
@@ -3376,6 +3379,7 @@ ORDER BY V.PATH2
|
||||
NET_QTY = COALESCE(NULLIF(TRIM(#{NET_QTY}::TEXT), '')::NUMERIC, 0),
|
||||
PO_QTY = COALESCE(NULLIF(TRIM(#{PO_QTY}::TEXT), '')::NUMERIC, 0),
|
||||
VENDOR = #{VENDOR_PM},
|
||||
PROCESSING_VENDOR = #{PROCESSING_VENDOR},
|
||||
UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
EDITER = #{EDITER},
|
||||
@@ -3390,6 +3394,7 @@ ORDER BY V.PATH2
|
||||
NET_QTY = COALESCE(NULLIF(TRIM(#{NET_QTY}::TEXT), '')::NUMERIC, 0),
|
||||
PO_QTY = COALESCE(NULLIF(TRIM(#{PO_QTY}::TEXT), '')::NUMERIC, 0),
|
||||
VENDOR_PM = #{VENDOR_PM},
|
||||
PROCESSING_VENDOR = #{PROCESSING_VENDOR},
|
||||
UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
WRITER = #{EDITER}
|
||||
|
||||
@@ -1047,7 +1047,7 @@
|
||||
SELECT 1 FROM shipment_log SL
|
||||
WHERE SL.target_objid = T.PROJECT_NO
|
||||
AND SL.shipping_date IS NOT NULL
|
||||
AND SL.shipping_date >= TO_DATE(#{shippingDateFrom}, 'YYYY-MM-DD')
|
||||
AND SL.shipping_date <![CDATA[>=]]> TO_DATE(#{shippingDateFrom}, 'YYYY-MM-DD')
|
||||
)
|
||||
</if>
|
||||
<if test="shippingDateTo != null and shippingDateTo != ''">
|
||||
@@ -1055,7 +1055,7 @@
|
||||
SELECT 1 FROM shipment_log SL
|
||||
WHERE SL.target_objid = T.PROJECT_NO
|
||||
AND SL.shipping_date IS NOT NULL
|
||||
AND SL.shipping_date <= TO_DATE(#{shippingDateTo}, 'YYYY-MM-DD') + INTERVAL '1 day'
|
||||
AND SL.shipping_date <![CDATA[<=]]> TO_DATE(#{shippingDateTo}, 'YYYY-MM-DD') + INTERVAL '1 day'
|
||||
)
|
||||
</if>
|
||||
<if test="shippingMethod != null and shippingMethod != ''">
|
||||
@@ -1216,7 +1216,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
SELECT 1 FROM shipment_log SL
|
||||
WHERE SL.target_objid = T.PROJECT_NO
|
||||
AND SL.shipping_date IS NOT NULL
|
||||
AND SL.shipping_date >= TO_DATE(#{shippingDateFrom}, 'YYYY-MM-DD')
|
||||
AND SL.shipping_date <![CDATA[>=]]> TO_DATE(#{shippingDateFrom}, 'YYYY-MM-DD')
|
||||
)
|
||||
</if>
|
||||
<if test="shippingDateTo != null and shippingDateTo != ''">
|
||||
@@ -1224,7 +1224,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
SELECT 1 FROM shipment_log SL
|
||||
WHERE SL.target_objid = T.PROJECT_NO
|
||||
AND SL.shipping_date IS NOT NULL
|
||||
AND SL.shipping_date <= TO_DATE(#{shippingDateTo}, 'YYYY-MM-DD') + INTERVAL '1 day'
|
||||
AND SL.shipping_date <![CDATA[<=]]> TO_DATE(#{shippingDateTo}, 'YYYY-MM-DD') + INTERVAL '1 day'
|
||||
)
|
||||
</if>
|
||||
<if test="shippingMethod != null and shippingMethod != ''">
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
$('.select2').select2();
|
||||
fnc_datepick();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#part_no", "#part_name", "#search_part_objid");
|
||||
|
||||
//엔터키로 조회
|
||||
$("input").keyup(function(e){
|
||||
if(e.keyCode == 13){
|
||||
@@ -369,10 +372,19 @@ function fn_move(){
|
||||
</td>
|
||||
|
||||
<td><label for="">품번</label></td>
|
||||
<td><input type="text" name="part_no" id="part_no" autocomplete="off" value="${param.part_no}" style="width:150px;"/></td>
|
||||
<td>
|
||||
<select name="part_no" id="part_no" class="select2-part" style="width:150px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_part_objid" id="search_part_objid" value="">
|
||||
</td>
|
||||
|
||||
<td><label for="">품명</label></td>
|
||||
<td><input type="text" name="part_name" id="part_name" autocomplete="off" value="${param.part_name}" style="width:170px;"/></td>
|
||||
<td>
|
||||
<select name="part_name" id="part_name" class="select2-part" style="width:170px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">PART 구분</label></td>
|
||||
<td><select name="part_type" id="part_type" class="select2" autocomplete="off" style="width:110px;"><option value="">선택</option>${code_map.part_type}</select></td>
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
$('.select2').select2();
|
||||
fnc_datepick();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#part_no", "#part_name", "#search_part_objid");
|
||||
|
||||
//엔터키로 조회
|
||||
$("input").keyup(function(e){
|
||||
if(e.keyCode == 13){
|
||||
@@ -379,10 +382,19 @@
|
||||
</td> --%>
|
||||
|
||||
<td><label for="">품번</label></td>
|
||||
<td><input type="text" name="part_no" id="part_no" autocomplete="off" value="${param.part_no}" style="width:150px;"/></td>
|
||||
<td>
|
||||
<select name="part_no" id="part_no" class="select2-part" style="width:150px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_part_objid" id="search_part_objid" value="">
|
||||
</td>
|
||||
|
||||
<td><label for="">품명</label></td>
|
||||
<td><input type="text" name="part_name" id="part_name" autocomplete="off" value="${param.part_name}" style="width:150px;"/></td>
|
||||
<td>
|
||||
<select name="part_name" id="part_name" class="select2-part" style="width:150px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td class=""><label>불출의뢰일</label></td>
|
||||
<td>
|
||||
|
||||
@@ -20,6 +20,9 @@ $(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
fnc_datepick();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#part_no", "#part_name", "#search_part_objid");
|
||||
|
||||
//fnc_getCodeListAppend("CUST_CD","CUSTOMER_CD","${param.CUSTOMER_CD}");
|
||||
//$("#Year").val("${sysYear}");
|
||||
|
||||
@@ -149,10 +152,19 @@ function fn_partMngHisDetail(objId){
|
||||
<td><select name="unit_code" id="unit_code" style="width:250px" class="select2" autocomplete="off"></select></td>
|
||||
|
||||
<td><label for="">품번</label></td>
|
||||
<td><input type="text" name="part_no" id="part_no" autocomplete="off" value="${param.part_no }" /></td>
|
||||
<td>
|
||||
<select name="part_no" id="part_no" class="select2-part" style="width:150px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_part_objid" id="search_part_objid" value="">
|
||||
</td>
|
||||
|
||||
<td><label for="">품명</label></td>
|
||||
<td><input type="text" name="part_name" id="part_name" autocomplete="off" value="${param.part_name}" /></td>
|
||||
<td>
|
||||
<select name="part_name" id="part_name" class="select2-part" style="width:150px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">EO사유</label></td>
|
||||
<td><select name="change_option" id="change_option" class="select2" autocomplete="off"><option value="">선택</option>${code_map.change_option}</select></td>
|
||||
|
||||
@@ -101,6 +101,9 @@ String connector = person.getUserId();
|
||||
}
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#SEARCH_PART_NO", "#SEARCH_PART_NAME", "#SEARCH_PART_OBJID");
|
||||
|
||||
//첨부팝업
|
||||
$(".File").click(function(){
|
||||
@@ -513,14 +516,19 @@ String connector = person.getUserId();
|
||||
<!-- <td> -->
|
||||
<!-- <select name="upg_no" id="upg_no" class="select2" style="width:250px;" autocomplete="off"></select> -->
|
||||
<!-- </td> -->
|
||||
<td><label for="">품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NO" id="SEARCH_PART_NO" style="width:150px;" autocomplete="off" value="${param.SEARCH_PART_NO}">
|
||||
</td>
|
||||
<td><label for="">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" style="width:150px;" autocomplete="off" value="${param.SEARCH_PART_NAME}">
|
||||
</td>
|
||||
<td><label for="">품번</label></td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NO" id="SEARCH_PART_NO" class="select2-part" style="width:150px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="SEARCH_PART_OBJID" id="SEARCH_PART_OBJID" value="">
|
||||
</td>
|
||||
<td><label for="">품명</label></td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:150px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">Revision</label></td>
|
||||
<td>
|
||||
|
||||
@@ -91,6 +91,9 @@ ui-jqgrid tr.jqgrow td {
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#SEARCH_PART_NO", "#SEARCH_PART_NAME", "#SEARCH_PART_OBJID");
|
||||
|
||||
fn_search();
|
||||
|
||||
|
||||
@@ -610,14 +613,19 @@ ui-jqgrid tr.jqgrow td {
|
||||
</c:forEach>
|
||||
</select>
|
||||
</td> -->
|
||||
<td><label for="">품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NO" id="SEARCH_PART_NO" style="width:194px;" autocomplete="off" value="${param.SEARCH_PART_NO}">
|
||||
</td>
|
||||
<td><label for="">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" style="width:150px;" autocomplete="off" value="${param.SEARCH_PART_NAME}">
|
||||
</td>
|
||||
<td><label for="">품번</label></td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NO" id="SEARCH_PART_NO" class="select2-part" style="width:194px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="SEARCH_PART_OBJID" id="SEARCH_PART_OBJID" value="">
|
||||
</td>
|
||||
<td><label for="">품명</label></td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:150px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
<!-- <td><label for="">등록자</label></td>
|
||||
<td>
|
||||
<select name="WRITER" id="WRITER" required reqTitle="작성자" type="select" class="select2" autocomplete="off">
|
||||
|
||||
@@ -176,6 +176,9 @@ $(document).ready(function(){
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#SEARCH_PART_NO", "#SEARCH_PART_NAME", "#SEARCH_PART_OBJID");
|
||||
|
||||
fn_search();
|
||||
});
|
||||
|
||||
@@ -731,12 +734,17 @@ function saveexcelpop() {
|
||||
|
||||
<td class="label"><label for="">품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NO" id="SEARCH_PART_NO" style="width:250px;">
|
||||
<select name="SEARCH_PART_NO" id="SEARCH_PART_NO" class="select2-part" style="width:250px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="SEARCH_PART_OBJID" id="SEARCH_PART_OBJID" value="">
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" style="width:250px;">
|
||||
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:250px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,9 @@ $(document).ready(function(){
|
||||
_fnc_datepick(); // 날짜 선택기 초기화
|
||||
$('.select2').select2(); // select2 초기화
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#search_part_no", "#search_part_name", "#search_part_objid");
|
||||
|
||||
// Enter 키로 검색
|
||||
$("input").keyup(function(e) {
|
||||
if (e.keyCode == 13) {
|
||||
@@ -660,25 +663,92 @@ function fn_openPurchaseListPopup() {
|
||||
|
||||
<!-- 검색 영역 -->
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
<tr>
|
||||
<td class="label"><label for="search_part_no">품번</label></td>
|
||||
<td><input type="text" name="search_part_no" id="search_part_no" value=""></td>
|
||||
|
||||
<td class="label"><label for="search_part_name">품명</label></td>
|
||||
<td><input type="text" name="search_part_name" id="search_part_name" value=""></td>
|
||||
</tr>
|
||||
<%--
|
||||
<tr>
|
||||
<td class="label"><label for="search_mbom_part_no">M-BOM 품번</label></td>
|
||||
<td><input type="text" name="search_mbom_part_no" id="search_mbom_part_no" value="${param.search_mbom_part_no}"></td>
|
||||
|
||||
<td class="label"><label for="search_save_date">저장일</label></td>
|
||||
<td><input type="date" name="search_save_date" id="search_save_date" value="${param.search_save_date}"></td>
|
||||
</tr>
|
||||
--%>
|
||||
</table>
|
||||
</div>
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 10px 15px; align-items: center;">
|
||||
<!-- 주문유형 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_category_cd">주문유형</label>
|
||||
<select name="search_category_cd" id="search_category_cd" style="width:120px" class="select2">
|
||||
<option value="">선택</option>
|
||||
${code_map.category_cd}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 제품구분 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_product_cd">제품구분</label>
|
||||
<select name="search_product_cd" id="search_product_cd" style="width:120px" class="select2">
|
||||
<option value="">선택</option>
|
||||
${code_map.product_cd}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 국내/해외 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_area_cd">국내/해외</label>
|
||||
<select name="search_area_cd" id="search_area_cd" style="width:100px" class="select2">
|
||||
<option value="">선택</option>
|
||||
<option value="국내">국내</option>
|
||||
<option value="해외">해외</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 고객사 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_customer_objid">고객사</label>
|
||||
<select name="search_customer_objid" id="search_customer_objid" style="width:150px" class="select2">
|
||||
<option value="">선택</option>
|
||||
${code_map.customer_cd}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 유/무상 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_paid_type">유/무상</label>
|
||||
<select name="search_paid_type" id="search_paid_type" style="width:80px" class="select2">
|
||||
<option value="">선택</option>
|
||||
<option value="paid">유상</option>
|
||||
<option value="free">무상</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- S/N -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_serial_no">S/N</label>
|
||||
<input type="text" name="search_serial_no" id="search_serial_no" value="" style="width:100px;">
|
||||
</div>
|
||||
|
||||
<!-- 품번 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_part_no">품번</label>
|
||||
<select name="search_part_no" id="search_part_no" class="select2-part" style="width:150px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_part_objid" id="search_part_objid" value="">
|
||||
</div>
|
||||
|
||||
<!-- 품명 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_part_name">품명</label>
|
||||
<select name="search_part_name" id="search_part_name" class="select2-part" style="width:150px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 접수일 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label>접수일</label>
|
||||
<input type="text" name="search_receipt_date_from" id="search_receipt_date_from" autocomplete="off" value="" class="date_icon" style="width:90px;"> ~
|
||||
<input type="text" name="search_receipt_date_to" id="search_receipt_date_to" autocomplete="off" value="" class="date_icon" style="width:90px;">
|
||||
</div>
|
||||
|
||||
<!-- 요청납기 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label>요청납기</label>
|
||||
<input type="text" name="search_req_del_date_from" id="search_req_del_date_from" autocomplete="off" value="" class="date_icon" style="width:90px;"> ~
|
||||
<input type="text" name="search_req_del_date_to" id="search_req_del_date_to" autocomplete="off" value="" class="date_icon" style="width:90px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 그리드 영역 -->
|
||||
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
|
||||
|
||||
@@ -35,6 +35,9 @@ $(function(){
|
||||
fnc_datepick();
|
||||
$(".select2").select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2();
|
||||
|
||||
// 저장 버튼
|
||||
$("#btnSave").click(function(){
|
||||
fn_save();
|
||||
@@ -44,6 +47,8 @@ $(function(){
|
||||
$("#PROJECT_NO").on("change select2:select", function(){
|
||||
var projectObjid = $(this).val();
|
||||
console.log("프로젝트번호 변경됨:", projectObjid);
|
||||
// PROJECT_OBJID hidden 필드에도 값 설정
|
||||
$("#PROJECT_OBJID").val(projectObjid);
|
||||
if(fnc_checkNull(projectObjid) != ""){
|
||||
fn_loadProjectInfo(projectObjid);
|
||||
} else {
|
||||
@@ -72,6 +77,94 @@ $(function(){
|
||||
<% } %>
|
||||
});
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
function initPartSelect2() {
|
||||
// 품번 Select2
|
||||
$("#PART_NO").select2({
|
||||
placeholder: "품번 검색...",
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
minimumInputLength: 1,
|
||||
language: {
|
||||
inputTooShort: function() { return "1글자 이상 입력하세요"; },
|
||||
searching: function() { return "검색 중..."; },
|
||||
noResults: function() { return "검색 결과가 없습니다"; }
|
||||
},
|
||||
ajax: {
|
||||
url: '/contractMgmt/searchPartList.do',
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
delay: 250,
|
||||
data: function(params) { return { searchTerm: params.term }; },
|
||||
processResults: function(data) {
|
||||
return {
|
||||
results: $.map(data, function(item) {
|
||||
return {
|
||||
id: item.PART_NO || item.part_no,
|
||||
text: item.PART_NO || item.part_no,
|
||||
partName: item.PART_NAME || item.part_name,
|
||||
partObjid: item.OBJID || item.objid
|
||||
};
|
||||
})
|
||||
};
|
||||
},
|
||||
cache: true
|
||||
}
|
||||
}).on('select2:select', function(e) {
|
||||
var data = e.params.data;
|
||||
// 품명 자동 설정
|
||||
if(data.partName) {
|
||||
// 품명 Select2에 옵션 추가 및 선택
|
||||
var newOption = new Option(data.partName, data.partName, true, true);
|
||||
$("#PART_NAME").append(newOption).trigger('change');
|
||||
}
|
||||
// hidden 필드에 OBJID 저장
|
||||
$("#PART_OBJID").val(data.partObjid);
|
||||
});
|
||||
|
||||
// 품명 Select2
|
||||
$("#PART_NAME").select2({
|
||||
placeholder: "품명 검색...",
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
minimumInputLength: 1,
|
||||
language: {
|
||||
inputTooShort: function() { return "1글자 이상 입력하세요"; },
|
||||
searching: function() { return "검색 중..."; },
|
||||
noResults: function() { return "검색 결과가 없습니다"; }
|
||||
},
|
||||
ajax: {
|
||||
url: '/contractMgmt/searchPartList.do',
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
delay: 250,
|
||||
data: function(params) { return { searchTerm: params.term }; },
|
||||
processResults: function(data) {
|
||||
return {
|
||||
results: $.map(data, function(item) {
|
||||
return {
|
||||
id: item.PART_NAME || item.part_name,
|
||||
text: item.PART_NAME || item.part_name,
|
||||
partNo: item.PART_NO || item.part_no,
|
||||
partObjid: item.OBJID || item.objid
|
||||
};
|
||||
})
|
||||
};
|
||||
},
|
||||
cache: true
|
||||
}
|
||||
}).on('select2:select', function(e) {
|
||||
var data = e.params.data;
|
||||
// 품번 자동 설정
|
||||
if(data.partNo) {
|
||||
var newOption = new Option(data.partNo, data.partNo, true, true);
|
||||
$("#PART_NO").append(newOption).trigger('change');
|
||||
}
|
||||
// hidden 필드에 OBJID 저장
|
||||
$("#PART_OBJID").val(data.partObjid);
|
||||
});
|
||||
}
|
||||
|
||||
// 날짜 선택기 초기화
|
||||
function fnc_datepick(){
|
||||
var $dateinput = $("input.date_icon");
|
||||
@@ -113,18 +206,40 @@ function fn_loadProjectInfo(projectObjid){
|
||||
$("#CATEGORY_CODE").val(info.category_code).trigger("change.select2");
|
||||
}
|
||||
|
||||
// 고객사 (C_ 접두어 제거)
|
||||
// 고객사 설정 (C_ 접두어 유무 모두 시도)
|
||||
if(fnc_checkNull(info.customer_objid) != ""){
|
||||
var customerObjid = info.customer_objid.replace("C_", "");
|
||||
console.log("고객사 설정:", customerObjid);
|
||||
$("#CUSTOMER_OBJID").val(customerObjid).trigger("change.select2");
|
||||
var customerObjid = info.customer_objid;
|
||||
console.log("고객사 원본값:", customerObjid);
|
||||
|
||||
// 먼저 원본값으로 시도
|
||||
$("#CUSTOMER_OBJID").val(customerObjid);
|
||||
if($("#CUSTOMER_OBJID").val() != customerObjid) {
|
||||
// C_ 제거 후 시도
|
||||
customerObjid = info.customer_objid.replace("C_", "");
|
||||
$("#CUSTOMER_OBJID").val(customerObjid);
|
||||
}
|
||||
if($("#CUSTOMER_OBJID").val() != customerObjid) {
|
||||
// C_ 추가 후 시도
|
||||
customerObjid = "C_" + info.customer_objid.replace("C_", "");
|
||||
$("#CUSTOMER_OBJID").val(customerObjid);
|
||||
}
|
||||
console.log("고객사 최종설정:", $("#CUSTOMER_OBJID").val());
|
||||
$("#CUSTOMER_OBJID").trigger("change.select2");
|
||||
}
|
||||
|
||||
// 품번
|
||||
$("#PART_NO").val(fnc_checkNull(info.part_no));
|
||||
// 품번 (Select2)
|
||||
var partNo = fnc_checkNull(info.part_no);
|
||||
if(partNo != "") {
|
||||
var newOption = new Option(partNo, partNo, true, true);
|
||||
$("#PART_NO").append(newOption).trigger('change');
|
||||
}
|
||||
|
||||
// 품명
|
||||
$("#PART_NAME").val(fnc_checkNull(info.part_name));
|
||||
// 품명 (Select2)
|
||||
var partName = fnc_checkNull(info.part_name);
|
||||
if(partName != "") {
|
||||
var newOption = new Option(partName, partName, true, true);
|
||||
$("#PART_NAME").append(newOption).trigger('change');
|
||||
}
|
||||
|
||||
// 요청납기
|
||||
$("#REQ_DEL_DATE").val(fnc_checkNull(info.req_del_date));
|
||||
@@ -155,8 +270,9 @@ function fn_clearProjectInfo(){
|
||||
$("#PRODUCT_CODE").val("").trigger("change");
|
||||
$("#CATEGORY_CODE").val("").trigger("change");
|
||||
$("#CUSTOMER_OBJID").val("").trigger("change");
|
||||
$("#PART_NO").val("");
|
||||
$("#PART_NAME").val("");
|
||||
$("#PART_NO").val(null).trigger("change");
|
||||
$("#PART_NAME").val(null).trigger("change");
|
||||
$("#PART_OBJID").val("");
|
||||
$("#REQ_DEL_DATE").val("");
|
||||
$("#SERIAL_NO").val("");
|
||||
$("#ORDER_QTY").val("");
|
||||
@@ -166,11 +282,21 @@ function fn_clearProjectInfo(){
|
||||
|
||||
// 기존 데이터 로드 (수정 모드)
|
||||
function fn_loadExistingData(){
|
||||
// JSP EL로 기존 데이터 설정
|
||||
// JSP EL로 기존 데이터 설정 (resultMap 키는 소문자)
|
||||
<% if(info != null) { %>
|
||||
$("#PRODUCT_CODE").val("${resultMap.PRODUCT_CODE}").trigger("change");
|
||||
$("#CATEGORY_CODE").val("${resultMap.CATEGORY_CODE}").trigger("change");
|
||||
$("#CUSTOMER_OBJID").val("${resultMap.CUSTOMER_OBJID}").trigger("change");
|
||||
// 프로젝트번호 설정
|
||||
var projectObjid = "${resultMap.project_objid}";
|
||||
if(projectObjid) {
|
||||
$("#PROJECT_NO").val(projectObjid).trigger("change.select2");
|
||||
}
|
||||
// 제품구분
|
||||
$("#PRODUCT_CODE").val("${resultMap.product_code}").trigger("change.select2");
|
||||
// 주문유형
|
||||
$("#CATEGORY_CODE").val("${resultMap.category_code}").trigger("change.select2");
|
||||
// 생산유형
|
||||
$("#PRODUCTION_TYPE").val("${resultMap.production_type}").trigger("change.select2");
|
||||
// 고객사
|
||||
$("#CUSTOMER_OBJID").val("${resultMap.customer_objid}").trigger("change.select2");
|
||||
fn_calcTotalQty();
|
||||
<% } %>
|
||||
}
|
||||
@@ -254,8 +380,8 @@ function fn_save(){
|
||||
</script>
|
||||
<body>
|
||||
<form name="form1" id="form1" method="post">
|
||||
<input type="hidden" name="OBJID" id="OBJID" value="${resultMap.OBJID}">
|
||||
<input type="hidden" name="PROJECT_OBJID" id="PROJECT_OBJID" value="${resultMap.PROJECT_OBJID}">
|
||||
<input type="hidden" name="OBJID" id="OBJID" value="${resultMap.objid}">
|
||||
<input type="hidden" name="PROJECT_OBJID" id="PROJECT_OBJID" value="${resultMap.project_objid}">
|
||||
<input type="hidden" name="actionType" id="actionType" value="${actionType}">
|
||||
|
||||
<section>
|
||||
@@ -319,7 +445,7 @@ function fn_save(){
|
||||
</td>
|
||||
<td class="input_title"><label>요청납기<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="REQ_DEL_DATE" id="REQ_DEL_DATE" class="date_icon" value="${resultMap.REQ_DEL_DATE}">
|
||||
<input type="text" name="REQ_DEL_DATE" id="REQ_DEL_DATE" class="date_icon" value="${resultMap.req_del_date}">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -327,15 +453,26 @@ function fn_save(){
|
||||
<tr>
|
||||
<td class="input_title"><label>품번<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="PART_NO" id="PART_NO" value="${resultMap.PART_NO}">
|
||||
<select name="PART_NO" id="PART_NO" style="width:100%;">
|
||||
<option value="">선택</option>
|
||||
<c:if test="${not empty resultMap.part_no}">
|
||||
<option value="${resultMap.part_no}" selected>${resultMap.part_no}</option>
|
||||
</c:if>
|
||||
</select>
|
||||
<input type="hidden" name="PART_OBJID" id="PART_OBJID" value="${resultMap.part_objid}">
|
||||
</td>
|
||||
<td class="input_title"><label>품명<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="PART_NAME" id="PART_NAME" value="${resultMap.PART_NAME}">
|
||||
<select name="PART_NAME" id="PART_NAME" style="width:100%;">
|
||||
<option value="">선택</option>
|
||||
<c:if test="${not empty resultMap.part_name}">
|
||||
<option value="${resultMap.part_name}" selected>${resultMap.part_name}</option>
|
||||
</c:if>
|
||||
</select>
|
||||
</td>
|
||||
<td class="input_title"><label>S/N</label></td>
|
||||
<td>
|
||||
<input type="text" name="SERIAL_NO" id="SERIAL_NO" value="${resultMap.SERIAL_NO}">
|
||||
<input type="text" name="SERIAL_NO" id="SERIAL_NO" value="${resultMap.serial_no}">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -343,15 +480,15 @@ function fn_save(){
|
||||
<tr>
|
||||
<td class="input_title"><label>수주수량<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<input type="number" name="ORDER_QTY" id="ORDER_QTY" min="0" value="${resultMap.ORDER_QTY}">
|
||||
<input type="number" name="ORDER_QTY" id="ORDER_QTY" min="0" value="${resultMap.order_qty}">
|
||||
</td>
|
||||
<td class="input_title"><label>추가생산수량</label></td>
|
||||
<td>
|
||||
<input type="number" name="EXTRA_PROD_QTY" id="EXTRA_PROD_QTY" min="0" value="${resultMap.EXTRA_PROD_QTY}" placeholder="0">
|
||||
<input type="number" name="EXTRA_PROD_QTY" id="EXTRA_PROD_QTY" min="0" value="${resultMap.extra_prod_qty}" placeholder="0">
|
||||
</td>
|
||||
<td class="input_title"><label>총생산수량</label></td>
|
||||
<td>
|
||||
<input type="text" name="TOTAL_PROD_QTY" id="TOTAL_PROD_QTY" class="readonly-field" readonly value="${resultMap.TOTAL_PROD_QTY}">
|
||||
<input type="text" name="TOTAL_PROD_QTY" id="TOTAL_PROD_QTY" class="readonly-field" readonly value="${resultMap.total_prod_qty}">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -359,7 +496,7 @@ function fn_save(){
|
||||
<tr>
|
||||
<td class="input_title"><label>고객사 요청사항</label></td>
|
||||
<td colspan="5">
|
||||
<input type="text" name="CUSTOMER_REQUEST" id="CUSTOMER_REQUEST" value="${resultMap.CUSTOMER_REQUEST}" style="width:100%;">
|
||||
<input type="text" name="CUSTOMER_REQUEST" id="CUSTOMER_REQUEST" value="${resultMap.customer_request}" style="width:100%;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -138,7 +138,7 @@ var columns = [
|
||||
hozAlign: 'center',
|
||||
width: 80,
|
||||
title: '주문유형',
|
||||
field: 'CATEGORY_CODE'
|
||||
field: 'CATEGORY_CODE_NAME'
|
||||
},
|
||||
|
||||
// 5. 생산유형
|
||||
@@ -244,11 +244,9 @@ var columns = [
|
||||
width: 80,
|
||||
title: '완조립',
|
||||
field: 'ASSEMBLY_QTY',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell) {
|
||||
if(cell.getValue() > 0) {
|
||||
fn_openQtyDetailPopup(cell.getData().OBJID, 'ASSEMBLY');
|
||||
}
|
||||
fn_openProdResultPopup(cell.getData().OBJID, 'ASSEMBLY');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -259,11 +257,9 @@ var columns = [
|
||||
width: 70,
|
||||
title: '검사',
|
||||
field: 'INSPECTION_QTY',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell) {
|
||||
if(cell.getValue() > 0) {
|
||||
fn_openQtyDetailPopup(cell.getData().OBJID, 'INSPECTION');
|
||||
}
|
||||
fn_openProdResultPopup(cell.getData().OBJID, 'INSPECTION');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -274,11 +270,9 @@ var columns = [
|
||||
width: 90,
|
||||
title: '출하대기',
|
||||
field: 'SHIP_WAIT_QTY',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell) {
|
||||
if(cell.getValue() > 0) {
|
||||
fn_openQtyDetailPopup(cell.getData().OBJID, 'SHIP_WAIT');
|
||||
}
|
||||
fn_openProdResultPopup(cell.getData().OBJID, 'SHIP_WAIT');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -299,6 +293,23 @@ var columns = [
|
||||
|
||||
// 검색 함수
|
||||
function fn_search(){
|
||||
// multiple select 값을 콤마로 join해서 hidden input에 설정
|
||||
var projectNos = $("#search_project_no").val();
|
||||
console.log("=== 프로젝트번호 검색 디버그 ===");
|
||||
console.log("projectNos:", projectNos);
|
||||
console.log("projectNos type:", typeof projectNos);
|
||||
console.log("projectNos length:", projectNos ? projectNos.length : 0);
|
||||
|
||||
if(projectNos && projectNos.length > 0) {
|
||||
var joinedVal = projectNos.join(",");
|
||||
console.log("joined value:", joinedVal);
|
||||
$("#search_project_nos_hidden").val(joinedVal);
|
||||
} else {
|
||||
$("#search_project_nos_hidden").val("");
|
||||
}
|
||||
console.log("hidden input value:", $("#search_project_nos_hidden").val());
|
||||
console.log("================================");
|
||||
|
||||
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/productionplanning/prodPlanResultMgmtGridList.do", columns, true);
|
||||
}
|
||||
|
||||
@@ -315,7 +326,7 @@ function fn_createProdPlan() {
|
||||
var checkedRows = getCheckedRows();
|
||||
|
||||
var popup_width = 900;
|
||||
var popup_height = 500;
|
||||
var popup_height = 400;
|
||||
var url = "/productionplanning/prodPlanFormPopup.do";
|
||||
|
||||
if(checkedRows.length === 1) {
|
||||
@@ -382,18 +393,16 @@ function fn_registProdResult() {
|
||||
}
|
||||
|
||||
var rowData = checkedRows[0];
|
||||
var popup_width = 1000;
|
||||
var popup_height = 700;
|
||||
var url = "/productionplanning/prodResultFormPopup.do?projectObjid=" + rowData.OBJID;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'prodResultPopup');
|
||||
// 실적유형 선택 없이 팝업 열기 (팝업에서 선택 가능)
|
||||
fn_openProdResultPopup(rowData.OBJID, '');
|
||||
}
|
||||
|
||||
// 수량 상세 팝업 (완조립, 검사, 출하대기 클릭 시)
|
||||
function fn_openQtyDetailPopup(projectObjid, qtyType) {
|
||||
var popup_width = 800;
|
||||
var popup_height = 500;
|
||||
var url = "/productionplanning/prodQtyDetailPopup.do?projectObjid=" + projectObjid + "&qtyType=" + qtyType;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'qtyDetailPopup');
|
||||
// 생산실적 등록/수정 팝업 (완조립, 검사, 출하대기 클릭 시)
|
||||
function fn_openProdResultPopup(projectObjid, resultType) {
|
||||
var popup_width = 1000;
|
||||
var popup_height = 700;
|
||||
var url = "/productionplanning/prodResultFormPopup.do?projectObjid=" + projectObjid + "&resultType=" + resultType;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'prodResultPopup');
|
||||
}
|
||||
|
||||
// 선택된 행 가져오기 (Tabulator 선택 기능 사용)
|
||||
@@ -413,6 +422,7 @@ function getCheckedRows() {
|
||||
|
||||
<form name="form1" id="form1" method="post">
|
||||
<input type="hidden" name="actionType" id="actionType">
|
||||
<input type="hidden" name="search_project_nos" id="search_project_nos_hidden">
|
||||
<div class="content-box">
|
||||
<div class="content-box-s">
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
@@ -422,7 +432,7 @@ function getCheckedRows() {
|
||||
<div class="btnArea">
|
||||
<input type="button" class="plm_btns" value="조회" id="btnSearch">
|
||||
<input type="button" class="plm_btns" value="생산계획 생성" id="btnCreateProdPlan">
|
||||
<input type="button" class="plm_btns" value="작업지시 생성" id="btnCreateWorkOrder">
|
||||
<!-- <input type="button" class="plm_btns" value="작업지시 생성" id="btnCreateWorkOrder"> -->
|
||||
<input type="button" class="plm_btns" value="생산실적 등록" id="btnRegistProdResult">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init_new.jsp" %>
|
||||
<c:set var="now" value="<%=new java.util.Date()%>" />
|
||||
<c:set var="today"><fmt:formatDate value="${now}" pattern="yyyy-MM-dd" /></c:set>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
.input_title {border-left:1px solid #ccc; background-color:#f5f5f5; font-weight:bold;}
|
||||
.required-mark { color: red; font-weight: bold; margin-left: 2px; }
|
||||
.readonly-field { background-color: #eee !important; }
|
||||
/* 공통 버튼 숨기기 */
|
||||
.resetBtn, .excelBtn { display: none !important; }
|
||||
body { min-height: auto !important; }
|
||||
|
||||
/* 정보 테이블 스타일 */
|
||||
.info-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.info-table th {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px 15px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
width: 12%;
|
||||
}
|
||||
.info-table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px 15px;
|
||||
text-align: left;
|
||||
width: 21%;
|
||||
}
|
||||
.info-value {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 실적등록 테이블 스타일 */
|
||||
.result-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.result-table th {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #ccc;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.result-table td {
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
.result-table input[type="text"],
|
||||
.result-table input[type="number"] {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
border: 1px solid #ddd;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
.result-table input[type="number"] {
|
||||
text-align: right;
|
||||
}
|
||||
.result-table .total-row {
|
||||
background-color: #f8f9fa;
|
||||
font-weight: bold;
|
||||
}
|
||||
.result-table .total-row td {
|
||||
padding: 10px 5px;
|
||||
}
|
||||
.result-table .total-label {
|
||||
background-color: #e9ecef;
|
||||
font-weight: bold;
|
||||
}
|
||||
.result-table .total-value {
|
||||
color: #0066cc;
|
||||
font-weight: bold;
|
||||
}
|
||||
.result-table .delete-btn {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 3px 8px;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.result-table .delete-btn:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<script type="text/javascript">
|
||||
var _projectObjid = "${param.projectObjid}";
|
||||
var _rowIndex = 0;
|
||||
|
||||
$(function(){
|
||||
fnc_datepick();
|
||||
|
||||
// 프로젝트 정보 로드
|
||||
if(_projectObjid) {
|
||||
fn_loadProjectInfo();
|
||||
}
|
||||
|
||||
// 실적 목록 조회
|
||||
fn_search();
|
||||
|
||||
// 행추가 버튼
|
||||
$("#btnAddRow").click(function(){
|
||||
fn_addRow();
|
||||
});
|
||||
|
||||
// 저장 버튼
|
||||
$("#btnSave").click(function(){
|
||||
fn_save();
|
||||
});
|
||||
});
|
||||
|
||||
// 날짜 선택기 초기화
|
||||
function fnc_datepick(){
|
||||
$(document).on('focus', '.date-input', function(){
|
||||
$(this).datepicker({
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dateFormat: 'yy-mm-dd'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 프로젝트 정보 로드
|
||||
function fn_loadProjectInfo() {
|
||||
$.ajax({
|
||||
url: "/productionplanning/getProdPlanProjectInfo.do",
|
||||
type: "POST",
|
||||
data: { "projectObjid": _projectObjid },
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(data){
|
||||
console.log("프로젝트 정보 응답:", data);
|
||||
if(data && data.result == "success" && data.info){
|
||||
var info = data.info;
|
||||
console.log("info 데이터:", info);
|
||||
|
||||
// 대소문자 모두 체크
|
||||
var partNo = info.part_no || info.PART_NO || '-';
|
||||
var partName = info.part_name || info.PART_NAME || '-';
|
||||
var orderQty = info.order_qty || info.ORDER_QTY || 0;
|
||||
var extraProdQty = info.extra_prod_qty || info.EXTRA_PROD_QTY || 0;
|
||||
|
||||
$("#PART_NO").text(partNo);
|
||||
$("#PART_NAME").text(partName);
|
||||
$("#ORDER_QTY").text(fnc_formatNumber(orderQty));
|
||||
$("#EXTRA_PROD_QTY").text(fnc_formatNumber(extraProdQty));
|
||||
|
||||
// 총생산수량 = 수주수량 + 추가생산수량
|
||||
var orderQtyNum = parseInt(orderQty) || 0;
|
||||
var extraProdQtyNum = parseInt(extraProdQty) || 0;
|
||||
$("#TOTAL_PROD_QTY").text(fnc_formatNumber(orderQtyNum + extraProdQtyNum));
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("프로젝트 정보 조회 실패:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 숫자 포맷팅
|
||||
function fnc_formatNumber(num) {
|
||||
if(num == null || num == '') return '0';
|
||||
return parseInt(num).toLocaleString();
|
||||
}
|
||||
|
||||
// 실적 목록 조회
|
||||
function fn_search() {
|
||||
var params = {
|
||||
projectObjid: _projectObjid
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/getProdResultListByDate.do",
|
||||
type: "POST",
|
||||
data: params,
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
console.log("실적 데이터 응답:", data);
|
||||
if(data && data.list && data.list.length > 0) {
|
||||
// 기존 데이터 로드
|
||||
for(var i = 0; i < data.list.length; i++) {
|
||||
var row = data.list[i];
|
||||
// 대소문자 모두 체크
|
||||
var resultDate = row.result_date || row.RESULT_DATE || '';
|
||||
var assemblyQty = row.assembly_qty || row.ASSEMBLY_QTY || 0;
|
||||
var inspectionQty = row.inspection_qty || row.INSPECTION_QTY || 0;
|
||||
var shipWaitQty = row.ship_wait_qty || row.SHIP_WAIT_QTY || 0;
|
||||
fn_addRow(resultDate, assemblyQty, inspectionQty, shipWaitQty);
|
||||
}
|
||||
} else {
|
||||
// 데이터 없으면 빈 행 하나 추가
|
||||
fn_addRow();
|
||||
}
|
||||
fn_updateTotals();
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("실적 조회 실패:", error);
|
||||
fn_addRow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 행 추가
|
||||
function fn_addRow(resultDate, assemblyQty, inspectionQty, shipWaitQty) {
|
||||
_rowIndex++;
|
||||
var today = '${today}';
|
||||
|
||||
var html = '<tr id="row_' + _rowIndex + '" data-row-index="' + _rowIndex + '">';
|
||||
html += '<td><input type="text" class="date-input" name="RESULT_DATE_' + _rowIndex + '" value="' + (resultDate || today) + '" placeholder="YYYY-MM-DD"></td>';
|
||||
html += '<td><input type="number" class="qty-input assembly-qty" name="ASSEMBLY_QTY_' + _rowIndex + '" value="' + (assemblyQty || 0) + '" min="0" onchange="fn_updateTotals()"></td>';
|
||||
html += '<td><input type="number" class="qty-input inspection-qty" name="INSPECTION_QTY_' + _rowIndex + '" value="' + (inspectionQty || 0) + '" min="0" onchange="fn_updateTotals()"></td>';
|
||||
html += '<td><input type="number" class="qty-input ship-wait-qty" name="SHIP_WAIT_QTY_' + _rowIndex + '" value="' + (shipWaitQty || 0) + '" min="0" onchange="fn_updateTotals()"></td>';
|
||||
html += '<td><button type="button" class="delete-btn" onclick="fn_deleteRow(' + _rowIndex + ')">삭제</button></td>';
|
||||
html += '</tr>';
|
||||
|
||||
$("#resultTableBody").append(html);
|
||||
fn_updateTotals();
|
||||
}
|
||||
|
||||
// 행 삭제
|
||||
function fn_deleteRow(rowIndex) {
|
||||
$("#row_" + rowIndex).remove();
|
||||
fn_updateTotals();
|
||||
}
|
||||
|
||||
// 총수량 업데이트
|
||||
function fn_updateTotals() {
|
||||
var totalAssembly = 0;
|
||||
var totalInspection = 0;
|
||||
var totalShipWait = 0;
|
||||
|
||||
$(".assembly-qty").each(function() {
|
||||
totalAssembly += parseInt($(this).val()) || 0;
|
||||
});
|
||||
$(".inspection-qty").each(function() {
|
||||
totalInspection += parseInt($(this).val()) || 0;
|
||||
});
|
||||
$(".ship-wait-qty").each(function() {
|
||||
totalShipWait += parseInt($(this).val()) || 0;
|
||||
});
|
||||
|
||||
$("#TOTAL_ASSEMBLY").text(totalAssembly.toLocaleString());
|
||||
$("#TOTAL_INSPECTION").text(totalInspection.toLocaleString());
|
||||
$("#TOTAL_SHIP_WAIT").text(totalShipWait.toLocaleString());
|
||||
}
|
||||
|
||||
// 저장
|
||||
function fn_save() {
|
||||
var resultList = [];
|
||||
|
||||
$("#resultTableBody tr").each(function() {
|
||||
var rowIndex = $(this).data('row-index');
|
||||
var resultDate = $("input[name='RESULT_DATE_" + rowIndex + "']").val();
|
||||
var assemblyQty = parseInt($("input[name='ASSEMBLY_QTY_" + rowIndex + "']").val()) || 0;
|
||||
var inspectionQty = parseInt($("input[name='INSPECTION_QTY_" + rowIndex + "']").val()) || 0;
|
||||
var shipWaitQty = parseInt($("input[name='SHIP_WAIT_QTY_" + rowIndex + "']").val()) || 0;
|
||||
|
||||
if(resultDate) {
|
||||
resultList.push({
|
||||
RESULT_DATE: resultDate,
|
||||
ASSEMBLY_QTY: assemblyQty,
|
||||
INSPECTION_QTY: inspectionQty,
|
||||
SHIP_WAIT_QTY: shipWaitQty
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if(resultList.length === 0) {
|
||||
Swal.fire('저장할 데이터가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 유효성 검사
|
||||
for(var i = 0; i < resultList.length; i++) {
|
||||
var row = resultList[i];
|
||||
if(!row.RESULT_DATE) {
|
||||
Swal.fire('날짜를 입력해주세요. (행 ' + (i+1) + ')');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!confirm('저장하시겠습니까?')) return;
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/saveProdResultByDate.do",
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
projectObjid: _projectObjid,
|
||||
resultList: resultList
|
||||
}),
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if(data.result == "success") {
|
||||
alert(data.msg || "저장되었습니다.");
|
||||
if(opener && opener.fn_search) {
|
||||
opener.fn_search();
|
||||
}
|
||||
window.close(); // 저장 성공 시 자동 닫기
|
||||
} else {
|
||||
Swal.fire(data.msg || "저장에 실패했습니다.");
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
Swal.fire("저장 중 오류가 발생했습니다.");
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 팝업 닫힐 때 부모 새로고침
|
||||
window.addEventListener('unload', function() {
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<body style="overflow-x: hidden;">
|
||||
<form name="form1" id="form1" method="post">
|
||||
<input type="hidden" name="PROJECT_OBJID" id="PROJECT_OBJID" value="${param.projectObjid}">
|
||||
|
||||
<section>
|
||||
<div class="plm_menu_name" style="display:flex;">
|
||||
<h2 style="width:100%;height:50px;text-align:center;margin-top:10px;">
|
||||
<span style="font-size:20px;">생산실적 등록</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<!-- 프로젝트 정보 표시 -->
|
||||
<div style="padding:10px 10px 0 10px;">
|
||||
<table class="info-table">
|
||||
<colgroup>
|
||||
<col width="15%" />
|
||||
<col width="35%" />
|
||||
<col width="15%" />
|
||||
<col width="35%" />
|
||||
</colgroup>
|
||||
<tr>
|
||||
<th>품번 <span style="color:red;">*</span></th>
|
||||
<td><span id="PART_NO" class="info-value">-</span></td>
|
||||
<th>품명 <span style="color:red;">*</span></th>
|
||||
<td><span id="PART_NAME" class="info-value">-</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>수주수량 <span style="color:red;">*</span></th>
|
||||
<td><span id="ORDER_QTY" class="info-value">0</span></td>
|
||||
<th>추가생산수량 <span style="color:red;">*</span></th>
|
||||
<td><span id="EXTRA_PROD_QTY" class="info-value">0</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>총생산수량 <span style="color:red;">*</span></th>
|
||||
<td colspan="3"><span id="TOTAL_PROD_QTY" class="info-value" style="color:#0066cc;">0</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="plm_menu_name_gdnsi" style="display:flex; justify-content:space-between; align-items:center; padding:0 10px; margin:10px 0;">
|
||||
<h2 style="margin:0;"><span>실적등록</span></h2>
|
||||
<div class="btnArea" style="margin:0;">
|
||||
<input type="button" value="행추가" class="plm_btns" id="btnAddRow">
|
||||
<input type="button" value="저장" class="plm_btns" id="btnSave">
|
||||
<input type="button" value="닫기" class="plm_btns" onclick="window.close();">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 실적등록 테이블 -->
|
||||
<div style="padding: 0 10px 10px 10px;">
|
||||
<table class="result-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:150px;">날짜</th>
|
||||
<th style="width:120px;">완조립</th>
|
||||
<th style="width:120px;">검사</th>
|
||||
<th style="width:120px;">출하대기</th>
|
||||
<th style="width:60px;">삭제</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="resultTableBody">
|
||||
<!-- 동적으로 행 추가 -->
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="total-row">
|
||||
<td class="total-label">총수량</td>
|
||||
<td class="total-value"><span id="TOTAL_ASSEMBLY">0</span></td>
|
||||
<td class="total-value"><span id="TOTAL_INSPECTION">0</span></td>
|
||||
<td class="total-value"><span id="TOTAL_SHIP_WAIT">0</span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,394 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<%
|
||||
// DB에서 메뉴명 조회 (공통 유틸 사용)
|
||||
String menuObjId = request.getParameter("menuObjId");
|
||||
String menuName = CommonUtils.getMenuName(menuObjId, "원자재소요량");
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
|
||||
<style>
|
||||
body, html {
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.section-title {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
margin: 10px 0 8px 0;
|
||||
color: #333;
|
||||
border-left: 3px solid #3498db;
|
||||
padding-left: 8px;
|
||||
}
|
||||
#inputGrid {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
// 입력 그리드 (M-BOM 선택 + 수량 입력)
|
||||
var inputGrid;
|
||||
// 결과 그리드 (소요량 목록)
|
||||
var resultGrid;
|
||||
// 공통 엑셀 다운로드용 grid 변수 (resultGrid를 참조)
|
||||
var grid;
|
||||
// 입력 행 번호
|
||||
var rowSeq = 0;
|
||||
// M-BOM 옵션 데이터
|
||||
var mbomOptionsData = {};
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
|
||||
// M-BOM 옵션 데이터 초기화
|
||||
fn_initMbomOptions();
|
||||
|
||||
// 입력 그리드 초기화
|
||||
fn_initInputGrid();
|
||||
|
||||
// 결과 그리드 초기화
|
||||
fn_initResultGrid();
|
||||
|
||||
// 조회 버튼
|
||||
$("#btnSearch").click(function(){
|
||||
fn_search();
|
||||
});
|
||||
|
||||
// 행 추가 버튼
|
||||
$("#btnAddRow").click(function(){
|
||||
fn_addInputRow();
|
||||
});
|
||||
|
||||
// 행 삭제 버튼
|
||||
$("#btnDeleteRow").click(function(){
|
||||
fn_deleteInputRow();
|
||||
});
|
||||
});
|
||||
|
||||
// M-BOM 옵션 데이터 초기화
|
||||
function fn_initMbomOptions() {
|
||||
mbomOptionsData = {"": "선택"};
|
||||
$("#MBOM_SELECT_HIDDEN option").each(function(){
|
||||
var val = $(this).val();
|
||||
var text = $(this).text();
|
||||
if(val !== '') {
|
||||
mbomOptionsData[val] = text;
|
||||
}
|
||||
});
|
||||
console.log("M-BOM 옵션:", mbomOptionsData);
|
||||
}
|
||||
|
||||
// 입력 그리드 초기화
|
||||
function fn_initInputGrid() {
|
||||
// 초기 데이터 1행 포함
|
||||
var initialData = [{
|
||||
ROW_ID: 1,
|
||||
MBOM_OBJID: "",
|
||||
PART_NAME: "",
|
||||
QTY: 1
|
||||
}];
|
||||
rowSeq = 1;
|
||||
|
||||
inputGrid = new Tabulator("#inputGrid", {
|
||||
data: initialData,
|
||||
layout: "fitColumns",
|
||||
height: "180px",
|
||||
columns: [
|
||||
{
|
||||
title: '',
|
||||
field: 'CHK',
|
||||
width: 40,
|
||||
headerSort: false,
|
||||
hozAlign: 'center',
|
||||
formatter: function(cell) {
|
||||
return '<input type="checkbox" class="row-check">';
|
||||
}
|
||||
},
|
||||
{title: 'ROW_ID', field: 'ROW_ID', visible: false},
|
||||
{
|
||||
title: 'M-BOM 선택',
|
||||
field: 'MBOM_OBJID',
|
||||
headerHozAlign: 'center',
|
||||
headerSort: false,
|
||||
editor: "list",
|
||||
editorParams: function(cell) {
|
||||
return {
|
||||
values: mbomOptionsData,
|
||||
autocomplete: true,
|
||||
clearable: true,
|
||||
listOnEmpty: true
|
||||
};
|
||||
},
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
return mbomOptionsData[value] || "";
|
||||
},
|
||||
cellEdited: function(cell) {
|
||||
// M-BOM 선택 시 품명 자동 입력
|
||||
var mbomObjid = cell.getValue();
|
||||
var row = cell.getRow();
|
||||
if(mbomObjid) {
|
||||
var mbomName = mbomOptionsData[mbomObjid] || "";
|
||||
row.update({PART_NAME: mbomName});
|
||||
} else {
|
||||
row.update({PART_NAME: ""});
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '품명',
|
||||
field: 'PART_NAME',
|
||||
headerHozAlign: 'center',
|
||||
headerSort: false,
|
||||
editor: false
|
||||
},
|
||||
{
|
||||
title: '수량',
|
||||
field: 'QTY',
|
||||
width: 200,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: false,
|
||||
hozAlign: 'right',
|
||||
editor: "number",
|
||||
editorParams: {
|
||||
min: 1,
|
||||
step: 1
|
||||
}
|
||||
}
|
||||
],
|
||||
placeholder: "M-BOM을 선택하고 수량을 입력하세요."
|
||||
});
|
||||
}
|
||||
|
||||
// 결과 그리드 초기화
|
||||
function fn_initResultGrid() {
|
||||
grid = resultGrid = new Tabulator("#resultGrid", {
|
||||
data: [],
|
||||
layout: "fitColumns",
|
||||
height: "calc(100vh - 450px)",
|
||||
pagination: false, // 페이지네이션 비활성화 (전체 데이터 표시)
|
||||
columns: [
|
||||
{
|
||||
title: '구분',
|
||||
field: 'CATEGORY_NAME',
|
||||
width: 150,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'center'
|
||||
},
|
||||
{
|
||||
title: '품번',
|
||||
field: 'PART_NO',
|
||||
width: 320,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'left'
|
||||
},
|
||||
{
|
||||
title: '품명',
|
||||
field: 'PART_NAME',
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'left'
|
||||
},
|
||||
{
|
||||
title: '소요량',
|
||||
field: 'REQUIRED_QTY',
|
||||
width: 150,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'right',
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val != null && val !== '') {
|
||||
return Number(val).toLocaleString();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '소재',
|
||||
field: 'MATERIAL',
|
||||
width: 150,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'center'
|
||||
},
|
||||
{
|
||||
title: '사이즈',
|
||||
field: 'SPEC',
|
||||
width: 150,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'center'
|
||||
},
|
||||
{
|
||||
title: '소재품번',
|
||||
field: 'MATERIAL_PART_NO',
|
||||
width: 250,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'left'
|
||||
},
|
||||
{
|
||||
title: '소재소요량',
|
||||
field: 'MATERIAL_REQUIRED_QTY',
|
||||
width: 150,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'right',
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val != null && val !== '') {
|
||||
return Number(val).toLocaleString();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
],
|
||||
placeholder: "조회 결과가 없습니다."
|
||||
});
|
||||
}
|
||||
|
||||
// 입력 행 추가
|
||||
function fn_addInputRow() {
|
||||
rowSeq++;
|
||||
inputGrid.addRow({
|
||||
ROW_ID: rowSeq,
|
||||
MBOM_OBJID: "",
|
||||
PART_NAME: "",
|
||||
QTY: 1
|
||||
});
|
||||
}
|
||||
|
||||
// 입력 행 삭제
|
||||
function fn_deleteInputRow() {
|
||||
var rows = inputGrid.getRows();
|
||||
var deleteRows = [];
|
||||
|
||||
rows.forEach(function(row) {
|
||||
var el = row.getElement();
|
||||
var checkbox = el.querySelector('.row-check');
|
||||
if(checkbox && checkbox.checked) {
|
||||
deleteRows.push(row);
|
||||
}
|
||||
});
|
||||
|
||||
if(deleteRows.length === 0) {
|
||||
Swal.fire('삭제할 행을 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
deleteRows.forEach(function(row) {
|
||||
row.delete();
|
||||
});
|
||||
}
|
||||
|
||||
// 조회
|
||||
function fn_search() {
|
||||
var inputData = inputGrid.getData();
|
||||
|
||||
// 유효한 입력만 필터링
|
||||
var mbomItems = [];
|
||||
inputData.forEach(function(row) {
|
||||
if(row.MBOM_OBJID && row.QTY > 0) {
|
||||
mbomItems.push({
|
||||
mbomObjid: row.MBOM_OBJID,
|
||||
qty: row.QTY
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if(mbomItems.length === 0) {
|
||||
Swal.fire('M-BOM을 선택하고 수량을 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX 조회
|
||||
$.ajax({
|
||||
url: "/productionplanning/getRawMaterialRequirementList.do",
|
||||
type: "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
data: JSON.stringify({mbomItems: mbomItems}),
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
console.log("=== 서버 응답 데이터 ===");
|
||||
console.log("전체 응답:", data);
|
||||
console.log("리스트 개수:", data.list ? data.list.length : 0);
|
||||
console.log("리스트 데이터:", data.list);
|
||||
|
||||
if(data.result === "success") {
|
||||
resultGrid.setData(data.list || []);
|
||||
var cnt = data.list ? data.list.length : 0;
|
||||
$("#resultCnt").text(cnt);
|
||||
|
||||
console.log("그리드 데이터 개수:", resultGrid.getData().length);
|
||||
if(cnt === 0) {
|
||||
Swal.fire({
|
||||
title: '조회 결과 없음',
|
||||
text: '구매품 항목이 없습니다.',
|
||||
icon: 'info'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Swal.fire('조회 실패: ' + (data.msg || ''));
|
||||
resultGrid.setData([]);
|
||||
$("#resultCnt").text("0");
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('조회 오류:', error);
|
||||
Swal.fire('조회 중 오류가 발생했습니다.');
|
||||
resultGrid.setData([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<form name="form1" id="form1" method="post">
|
||||
<!-- M-BOM 옵션을 위한 숨김 select -->
|
||||
<select id="MBOM_SELECT_HIDDEN" style="display:none;">
|
||||
<option value="">선택</option>
|
||||
${code_map.mbom_list}
|
||||
</select>
|
||||
|
||||
<div class="content-box">
|
||||
<div class="content-box-s">
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2>
|
||||
<span><%=menuName%></span>
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" class="plm_btns" value="행 추가" id="btnAddRow">
|
||||
<input type="button" class="plm_btns" value="행 삭제" id="btnDeleteRow">
|
||||
<input type="button" class="plm_btns" value="조회" id="btnSearch">
|
||||
<input type="button" class="plm_btns excelBtn" value="Excel Download" id="btnExcel">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 입력 영역 -->
|
||||
<div id="plmSearchZon">
|
||||
<div class="section-title">M-BOM 선택 및 수량 입력</div>
|
||||
<div id="inputGrid" style="margin-right: 16px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- 결과 그리드 영역 -->
|
||||
<div class="section-title" style="margin-left: 16px;">원자재 소요량 (구매품, 원소재) - 조회결과: <span id="resultCnt">0</span>건</div>
|
||||
<div id="resultGrid" style="margin: 0 16px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,347 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<%
|
||||
// DB에서 메뉴명 조회 (공통 유틸 사용)
|
||||
String menuObjId = request.getParameter("menuObjId");
|
||||
String menuName = CommonUtils.getMenuName(menuObjId, "반제품소요량");
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
|
||||
<style>
|
||||
body, html {
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.section-title {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
margin: 10px 0 8px 0;
|
||||
color: #333;
|
||||
border-left: 3px solid #3498db;
|
||||
padding-left: 8px;
|
||||
}
|
||||
#inputGrid {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
// 입력 그리드 (M-BOM 선택 + 수량 입력)
|
||||
var inputGrid;
|
||||
// 결과 그리드 (소요량 목록)
|
||||
var resultGrid;
|
||||
// 공통 엑셀 다운로드용 grid 변수 (resultGrid를 참조)
|
||||
var grid;
|
||||
// 입력 행 번호
|
||||
var rowSeq = 0;
|
||||
// M-BOM 옵션 데이터
|
||||
var mbomOptionsData = {};
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
|
||||
// M-BOM 옵션 데이터 초기화
|
||||
fn_initMbomOptions();
|
||||
|
||||
// 입력 그리드 초기화
|
||||
fn_initInputGrid();
|
||||
|
||||
// 결과 그리드 초기화
|
||||
fn_initResultGrid();
|
||||
|
||||
// 조회 버튼
|
||||
$("#btnSearch").click(function(){
|
||||
fn_search();
|
||||
});
|
||||
|
||||
// 행 추가 버튼
|
||||
$("#btnAddRow").click(function(){
|
||||
fn_addInputRow();
|
||||
});
|
||||
|
||||
// 행 삭제 버튼
|
||||
$("#btnDeleteRow").click(function(){
|
||||
fn_deleteInputRow();
|
||||
});
|
||||
});
|
||||
|
||||
// M-BOM 옵션 데이터 초기화
|
||||
function fn_initMbomOptions() {
|
||||
mbomOptionsData = {"": "선택"};
|
||||
$("#MBOM_SELECT_HIDDEN option").each(function(){
|
||||
var val = $(this).val();
|
||||
var text = $(this).text();
|
||||
if(val !== '') {
|
||||
mbomOptionsData[val] = text;
|
||||
}
|
||||
});
|
||||
console.log("M-BOM 옵션:", mbomOptionsData);
|
||||
}
|
||||
|
||||
// 입력 그리드 초기화
|
||||
function fn_initInputGrid() {
|
||||
// 초기 데이터 1행 포함
|
||||
var initialData = [{
|
||||
ROW_ID: 1,
|
||||
MBOM_OBJID: "",
|
||||
PART_NAME: "",
|
||||
QTY: 1
|
||||
}];
|
||||
rowSeq = 1;
|
||||
|
||||
inputGrid = new Tabulator("#inputGrid", {
|
||||
data: initialData,
|
||||
layout: "fitColumns",
|
||||
height: "180px",
|
||||
columns: [
|
||||
{
|
||||
title: '',
|
||||
field: 'CHK',
|
||||
width: 40,
|
||||
headerSort: false,
|
||||
hozAlign: 'center',
|
||||
formatter: function(cell) {
|
||||
return '<input type="checkbox" class="row-check">';
|
||||
}
|
||||
},
|
||||
{title: 'ROW_ID', field: 'ROW_ID', visible: false},
|
||||
{
|
||||
title: 'M-BOM 선택',
|
||||
field: 'MBOM_OBJID',
|
||||
headerHozAlign: 'center',
|
||||
headerSort: false,
|
||||
editor: "list",
|
||||
editorParams: function(cell) {
|
||||
return {
|
||||
values: mbomOptionsData,
|
||||
autocomplete: true,
|
||||
clearable: true,
|
||||
listOnEmpty: true
|
||||
};
|
||||
},
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
return mbomOptionsData[value] || "";
|
||||
},
|
||||
cellEdited: function(cell) {
|
||||
// M-BOM 선택 시 품명 자동 입력
|
||||
var mbomObjid = cell.getValue();
|
||||
var row = cell.getRow();
|
||||
if(mbomObjid) {
|
||||
var mbomName = mbomOptionsData[mbomObjid] || "";
|
||||
row.update({PART_NAME: mbomName});
|
||||
} else {
|
||||
row.update({PART_NAME: ""});
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '품명',
|
||||
field: 'PART_NAME',
|
||||
headerHozAlign: 'center',
|
||||
headerSort: false,
|
||||
editor: false
|
||||
},
|
||||
{
|
||||
title: '수량',
|
||||
field: 'QTY',
|
||||
width: 200,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: false,
|
||||
hozAlign: 'right',
|
||||
editor: "number",
|
||||
editorParams: {
|
||||
min: 1,
|
||||
step: 1
|
||||
}
|
||||
}
|
||||
],
|
||||
placeholder: "M-BOM을 선택하고 수량을 입력하세요."
|
||||
});
|
||||
}
|
||||
|
||||
// 결과 그리드 초기화
|
||||
function fn_initResultGrid() {
|
||||
grid = resultGrid = new Tabulator("#resultGrid", {
|
||||
data: [],
|
||||
layout: "fitColumns",
|
||||
height: "calc(100vh - 450px)",
|
||||
columns: [
|
||||
{
|
||||
title: '구분',
|
||||
field: 'CATEGORY_NAME',
|
||||
width: 200,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'center'
|
||||
},
|
||||
{
|
||||
title: '품번',
|
||||
field: 'PART_NO',
|
||||
width: 320,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'left'
|
||||
},
|
||||
{
|
||||
title: '품명',
|
||||
field: 'PART_NAME',
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'left'
|
||||
},
|
||||
{
|
||||
title: '소요량',
|
||||
field: 'REQUIRED_QTY',
|
||||
width: 200,
|
||||
headerHozAlign: 'center',
|
||||
headerSort: true,
|
||||
hozAlign: 'right',
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val != null && val !== '') {
|
||||
return Number(val).toLocaleString();
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
],
|
||||
placeholder: "조회 결과가 없습니다."
|
||||
});
|
||||
}
|
||||
|
||||
// 입력 행 추가
|
||||
function fn_addInputRow() {
|
||||
rowSeq++;
|
||||
inputGrid.addRow({
|
||||
ROW_ID: rowSeq,
|
||||
MBOM_OBJID: "",
|
||||
PART_NAME: "",
|
||||
QTY: 1
|
||||
});
|
||||
}
|
||||
|
||||
// 입력 행 삭제
|
||||
function fn_deleteInputRow() {
|
||||
var rows = inputGrid.getRows();
|
||||
var deleteRows = [];
|
||||
|
||||
rows.forEach(function(row) {
|
||||
var el = row.getElement();
|
||||
var checkbox = el.querySelector('.row-check');
|
||||
if(checkbox && checkbox.checked) {
|
||||
deleteRows.push(row);
|
||||
}
|
||||
});
|
||||
|
||||
if(deleteRows.length === 0) {
|
||||
Swal.fire('삭제할 행을 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
deleteRows.forEach(function(row) {
|
||||
row.delete();
|
||||
});
|
||||
}
|
||||
|
||||
// 조회
|
||||
function fn_search() {
|
||||
var inputData = inputGrid.getData();
|
||||
|
||||
// 유효한 입력만 필터링
|
||||
var mbomItems = [];
|
||||
inputData.forEach(function(row) {
|
||||
if(row.MBOM_OBJID && row.QTY > 0) {
|
||||
mbomItems.push({
|
||||
mbomObjid: row.MBOM_OBJID,
|
||||
qty: row.QTY
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if(mbomItems.length === 0) {
|
||||
Swal.fire('M-BOM을 선택하고 수량을 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// AJAX 조회
|
||||
$.ajax({
|
||||
url: "/productionplanning/getSemiProductRequirementList.do",
|
||||
type: "POST",
|
||||
contentType: "application/json;charset=UTF-8",
|
||||
data: JSON.stringify({mbomItems: mbomItems}),
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data.result === "success") {
|
||||
resultGrid.setData(data.list || []);
|
||||
var cnt = data.list ? data.list.length : 0;
|
||||
$("#resultCnt").text(cnt);
|
||||
if(cnt === 0) {
|
||||
Swal.fire({
|
||||
title: '조회 결과 없음',
|
||||
text: '부품 또는 조립품 항목이 없습니다.',
|
||||
icon: 'info'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Swal.fire('조회 실패: ' + (data.msg || ''));
|
||||
resultGrid.setData([]);
|
||||
$("#resultCnt").text("0");
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('조회 오류:', error);
|
||||
Swal.fire('조회 중 오류가 발생했습니다.');
|
||||
resultGrid.setData([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<form name="form1" id="form1" method="post">
|
||||
<!-- M-BOM 옵션을 위한 숨김 select -->
|
||||
<select id="MBOM_SELECT_HIDDEN" style="display:none;">
|
||||
<option value="">선택</option>
|
||||
${code_map.mbom_list}
|
||||
</select>
|
||||
|
||||
<div class="content-box">
|
||||
<div class="content-box-s">
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2>
|
||||
<span><%=menuName%></span>
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" class="plm_btns" value="행 추가" id="btnAddRow">
|
||||
<input type="button" class="plm_btns" value="행 삭제" id="btnDeleteRow">
|
||||
<input type="button" class="plm_btns" value="조회" id="btnSearch">
|
||||
<input type="button" class="plm_btns excelBtn" value="Excel Download" id="btnExcel">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 입력 영역 -->
|
||||
<div id="plmSearchZon">
|
||||
<div class="section-title">M-BOM 선택 및 수량 입력</div>
|
||||
<div id="inputGrid" style="margin-right: 16px;"></div>
|
||||
</div>
|
||||
|
||||
<!-- 결과 그리드 영역 -->
|
||||
<div class="section-title" style="margin-left: 16px;">반제품 소요량 (부품/조립품) - 조회결과: <span id="resultCnt">0</span>건</div>
|
||||
<div id="resultGrid" style="margin: 0 16px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -58,7 +58,13 @@ String connector = person.getUserId();
|
||||
$(document).ready(function(){
|
||||
|
||||
//날짜
|
||||
_fnc_datepick();
|
||||
fnc_datepick();
|
||||
|
||||
// 예상납기일 datepicker 명시적 적용
|
||||
$('#contract_start_date, #contract_end_date').datepicker({
|
||||
changeMonth: true,
|
||||
changeYear: true
|
||||
});
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
@@ -155,7 +161,7 @@ var columns = [
|
||||
//{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '설비길이', field : 'FACILITY_DEPTH' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : 'PM', field : 'PM_USER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '제작공장', field : 'MANUFACTURE_PLANT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '예상납기일', field : 'CONTRACT_DEL_DATE' }
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '요청납기일', field : 'CONTRACT_DEL_DATE' }
|
||||
],
|
||||
},
|
||||
|
||||
@@ -535,14 +541,14 @@ function setup_wbs_popup(objId){
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="align_r">
|
||||
<label>예상납기일</label>
|
||||
<label>요청납기일</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="contract_start_date" id="contract_start_date" style="width:90px;" autocomplete="off" value="${param.contract_start_date}" class="date_icon">~
|
||||
<input type="text" name="contract_end_date" id="contract_end_date" style="width:90px;" autocomplete="off" value="${param.contract_end_date}" class="date_icon">
|
||||
</td>
|
||||
|
||||
<td class="align_r">
|
||||
<td class="align_r">
|
||||
<label>입고지</label>
|
||||
</td>
|
||||
<td>
|
||||
@@ -555,7 +561,7 @@ function setup_wbs_popup(objId){
|
||||
<td>
|
||||
<input type="text" name="setup" id="setup" style="" autocomplete="off" value="${param.setup}">
|
||||
</td>
|
||||
|
||||
|
||||
<td><label for="pm_user_id">PM</label></td>
|
||||
<td>
|
||||
<select name="pm_user_id" id="pm_user_id" style="width:200px;" class="select2" autocomplete="off">
|
||||
|
||||
@@ -52,6 +52,15 @@ String connector = person.getUserId();
|
||||
|
||||
$(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#product_item_code", "#product_item_name", "#search_part_objid");
|
||||
|
||||
// 요청납기일 datepicker 적용
|
||||
$('#contract_start_date, #contract_end_date').datepicker({
|
||||
changeMonth: true,
|
||||
changeYear: true
|
||||
});
|
||||
//$('#Year' ).select2();
|
||||
|
||||
$("#btnSearch").click(function(){
|
||||
@@ -62,6 +71,14 @@ $(document).ready(function(){
|
||||
//fn_apply("","regist");
|
||||
});
|
||||
|
||||
// 엔터키로 조회
|
||||
$('#plmSearchZon input[type="text"]').keypress(function(e){
|
||||
if(e.which == 13){
|
||||
$("#page").val("1");
|
||||
fn_search();
|
||||
}
|
||||
});
|
||||
|
||||
fn_search();
|
||||
});
|
||||
|
||||
@@ -212,7 +229,7 @@ function openProjectFormPopUp(objId){
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="category_cd">계약구분</label></td>
|
||||
<td><label for="category_cd">주문유형</label></td>
|
||||
<td>
|
||||
<select name="category_cd" id="category_cd" style="" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
@@ -237,14 +254,54 @@ function openProjectFormPopUp(objId){
|
||||
</select>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label>예상납기일</label>
|
||||
<label>요청납기일</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="contract_start_date" id="contract_start_date" style="width:90px;" autocomplete="off" value="${param.contract_start_date}" class="date_icon">~
|
||||
<input type="text" name="contract_end_date" id="contract_end_date" style="width:90px;" autocomplete="off" value="${param.contract_end_date}" class="date_icon">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="area_cd">국내/해외</label></td>
|
||||
<td>
|
||||
<select name="area_cd" id="area_cd" style="" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
<option value="국내"${param.area_cd eq '국내' ? ' selected':'' }>국내</option>
|
||||
<option value="해외"${param.area_cd eq '해외' ? ' selected':'' }>해외</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="free_of_charge">유/무상</label></td>
|
||||
<td>
|
||||
<select name="free_of_charge" id="free_of_charge" style="" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
<option value="유상"${param.free_of_charge eq '유상' ? ' selected':'' }>유상</option>
|
||||
<option value="무상"${param.free_of_charge eq '무상' ? ' selected':'' }>무상</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="product_item_code">품번</label></td>
|
||||
<td>
|
||||
<select name="product_item_code" id="product_item_code" class="select2-part" style="width:150px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_part_objid" id="search_part_objid" value="">
|
||||
</td>
|
||||
|
||||
<td><label for="product_item_name">품명</label></td>
|
||||
<td>
|
||||
<select name="product_item_name" id="product_item_name" class="select2-part" style="width:150px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="serial_no">S/N</label></td>
|
||||
<td>
|
||||
<input type="text" name="serial_no" id="serial_no" style="width:150px;" autocomplete="off" value="${param.serial_no}">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<%-- 입고지, 셋업지, PM 검색필터 주석처리
|
||||
<tr>
|
||||
<td class="align_r">
|
||||
<label>입고지</label>
|
||||
@@ -268,6 +325,7 @@ function openProjectFormPopUp(objId){
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
--%>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -48,6 +48,9 @@ $(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
fnc_datepick();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#SEARCH_PART_NO", "#SEARCH_PART_NAME", "#SEARCH_PART_OBJID");
|
||||
|
||||
$("input").keyup(function(e){
|
||||
if(e.keyCode == 13){
|
||||
$("#page").val("1");
|
||||
@@ -475,10 +478,19 @@ function fn_purchaseClose(){
|
||||
<td><label for="">발주No.</label></td>
|
||||
<td><input type="text" name="purchase_order_no" id="purchase_order_no" autocomplete="off" value="${param.purchase_order_no}" style="width:185px;"/></td>
|
||||
|
||||
<%-- 부품구분 주석처리
|
||||
<td><label for="">부품구분</label></td>
|
||||
<td><select name="type" id="type" class="select2" autocomplete="off" style="width:130px;"><option value="">선택</option>${code_map.type}</select></td>
|
||||
<td><label for="">규격</label></td>
|
||||
<td><select name="type" id="type" class="select2" autocomplete="off" style="width:130px;"><option value="">선택</option>${code_map.type}</select></td>
|
||||
--%>
|
||||
<td><label for="">규격</label></td>
|
||||
<td><input type="text" name="SEARCH_PART_SPEC" id="SEARCH_PART_SPEC" autocomplete="off" value="${param.SEARCH_PART_SPEC }" style="width:120px;"/></td>
|
||||
|
||||
<td><label for="">품명</label></td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:130px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="">공급업체</label></td>
|
||||
@@ -508,12 +520,13 @@ function fn_purchaseClose(){
|
||||
<option value="지연">지연</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><label for="">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" style="width:130px;" autocomplete="off" value="${param.SEARCH_PART_NAME}">
|
||||
</td>
|
||||
<td><label for="">품번</label></td>
|
||||
<td><input type="text" name="SEARCH_PART_NO" id="SEARCH_PART_NO" autocomplete="off" value="${param.SEARCH_PART_NO }" style="width:120px;"/></td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NO" id="SEARCH_PART_NO" class="select2-part" style="width:120px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="SEARCH_PART_OBJID" id="SEARCH_PART_OBJID" value="">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -201,8 +201,12 @@ input.date_icon {
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var grid;
|
||||
// PDF 생성용 플래그
|
||||
window.dataLoaded = false;
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
@@ -526,6 +530,199 @@ var gridFn = {
|
||||
$("#TOTAL_PRICE_ALL").val(numberWithCommas(totalWithVat));
|
||||
}
|
||||
}
|
||||
|
||||
// 라이브러리 로드 완료 후 dataLoaded 플래그 설정
|
||||
$(window).on('load', function() {
|
||||
setTimeout(function() {
|
||||
if(typeof html2canvas !== 'undefined' && typeof jspdf !== 'undefined') {
|
||||
window.dataLoaded = true;
|
||||
console.log('발주서 일반양식 - dataLoaded = true');
|
||||
} else {
|
||||
// jsPDF 전역 객체 확인
|
||||
if(typeof html2canvas !== 'undefined' && typeof window.jspdf !== 'undefined') {
|
||||
window.dataLoaded = true;
|
||||
console.log('발주서 일반양식 - dataLoaded = true (jspdf)');
|
||||
} else {
|
||||
console.log('라이브러리 로드 대기중...');
|
||||
setTimeout(function() {
|
||||
window.dataLoaded = true;
|
||||
console.log('발주서 일반양식 - dataLoaded = true (지연)');
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// PDF를 Base64로 생성하여 콜백으로 전달하는 함수
|
||||
function fn_generateAndUploadPdf(callback) {
|
||||
console.log('fn_generateAndUploadPdf 호출됨 (일반 발주서)');
|
||||
|
||||
// 라이브러리 로드 확인
|
||||
if(typeof html2canvas === 'undefined') {
|
||||
console.error('html2canvas 라이브러리가 로드되지 않았습니다.');
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var jsPDF = window.jspdf ? window.jspdf.jsPDF : null;
|
||||
if(!jsPDF) {
|
||||
console.error('jsPDF 라이브러리가 로드되지 않았습니다.');
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 버튼 영역 임시 숨김
|
||||
$('#btnSave, #btnDown, input[value="닫기"]').closest('div').hide();
|
||||
|
||||
// select2 컨테이너 숨김 (중복 표시 방지)
|
||||
$('.select2-container').hide();
|
||||
|
||||
// input/select 값을 텍스트로 변환 (html2canvas가 input value를 캡처하지 못하는 문제 해결)
|
||||
var inputBackups = [];
|
||||
|
||||
// input 요소 처리 (form1 내부 + 그리드 포함)
|
||||
$('input[type="text"], input:not([type])').each(function(){
|
||||
var $input = $(this);
|
||||
var value = $input.val();
|
||||
if(value) {
|
||||
inputBackups.push({
|
||||
element: $input,
|
||||
html: $input[0].outerHTML,
|
||||
parent: $input.parent()
|
||||
});
|
||||
var $span = $('<span class="pdf-temp-span">').text(value).css({
|
||||
'display': 'inline-block',
|
||||
'white-space': 'nowrap',
|
||||
'text-align': $input.css('text-align') || 'left',
|
||||
'font-size': $input.css('font-size') || '12px',
|
||||
'font-weight': $input.css('font-weight') || 'normal',
|
||||
'padding': '2px 5px',
|
||||
'color': $input.css('color') || '#000',
|
||||
'background': 'transparent'
|
||||
});
|
||||
$input.replaceWith($span);
|
||||
inputBackups[inputBackups.length - 1].span = $span;
|
||||
}
|
||||
});
|
||||
|
||||
// select 요소 처리 (select2 포함)
|
||||
$('select').each(function(){
|
||||
var $select = $(this);
|
||||
var value = $select.find('option:selected').text();
|
||||
if(value && value.trim() !== '' && value !== '선택') {
|
||||
inputBackups.push({
|
||||
element: $select,
|
||||
html: $select[0].outerHTML,
|
||||
parent: $select.parent(),
|
||||
wasHidden: $select.is(':hidden')
|
||||
});
|
||||
var $span = $('<span class="pdf-temp-span">').text(value).css({
|
||||
'display': 'inline-block',
|
||||
'white-space': 'nowrap',
|
||||
'text-align': 'left',
|
||||
'font-size': '12px',
|
||||
'padding': '2px 5px',
|
||||
'color': '#000',
|
||||
'background': 'transparent'
|
||||
});
|
||||
$select.after($span).hide();
|
||||
inputBackups[inputBackups.length - 1].span = $span;
|
||||
}
|
||||
});
|
||||
|
||||
// 캡처할 영역 (form1)
|
||||
var captureElement = document.getElementById('form1');
|
||||
|
||||
// html2canvas로 캡처
|
||||
html2canvas(captureElement, {
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
logging: false,
|
||||
backgroundColor: '#ffffff',
|
||||
windowWidth: captureElement.scrollWidth,
|
||||
windowHeight: captureElement.scrollHeight
|
||||
}).then(function(canvas) {
|
||||
console.log('Canvas 캡처 완료');
|
||||
|
||||
// 임시 span 제거 및 원본 복원
|
||||
$('.pdf-temp-span').remove();
|
||||
for(var i = 0; i < inputBackups.length; i++) {
|
||||
var backup = inputBackups[i];
|
||||
if(backup.element && backup.element.is('select')) {
|
||||
// select는 숨겨둔 것만 다시 표시
|
||||
backup.element.show();
|
||||
} else if(backup.span && backup.parent) {
|
||||
// input은 span을 원본으로 교체
|
||||
backup.span.replaceWith(backup.html);
|
||||
}
|
||||
}
|
||||
|
||||
// select2 컨테이너 다시 표시
|
||||
$('.select2-container').show();
|
||||
|
||||
// 버튼 영역 다시 표시
|
||||
$('#btnSave, #btnDown, input[value="닫기"]').closest('div').show();
|
||||
|
||||
try {
|
||||
// Canvas를 JPEG 이미지로 변환
|
||||
var imgData = canvas.toDataURL('image/jpeg', 0.85);
|
||||
console.log('이미지 변환 완료');
|
||||
|
||||
// PDF 생성
|
||||
var pdf = new jsPDF('p', 'mm', 'a4');
|
||||
var imgWidth = 210;
|
||||
var pageHeight = 297;
|
||||
var imgHeight = canvas.height * imgWidth / canvas.width;
|
||||
var heightLeft = imgHeight;
|
||||
var position = 0;
|
||||
|
||||
// 이미지 추가
|
||||
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight, undefined, 'FAST');
|
||||
heightLeft -= pageHeight;
|
||||
|
||||
while (heightLeft >= 0) {
|
||||
position = heightLeft - imgHeight;
|
||||
pdf.addPage();
|
||||
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight, undefined, 'FAST');
|
||||
heightLeft -= pageHeight;
|
||||
}
|
||||
|
||||
console.log('PDF 생성 완료');
|
||||
|
||||
// PDF를 Base64로 변환
|
||||
var pdfBase64 = pdf.output('dataurlstring').split(',')[1];
|
||||
console.log('PDF Base64 생성 완료, 길이:', pdfBase64.length);
|
||||
|
||||
// 콜백 함수 호출
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(pdfBase64);
|
||||
}
|
||||
} catch(pdfError) {
|
||||
console.error('PDF 생성 중 오류:', pdfError);
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
}
|
||||
}
|
||||
|
||||
}).catch(function(error) {
|
||||
// span을 다시 input으로 복원
|
||||
for(var i = 0; i < inputBackups.length; i++) {
|
||||
var backup = inputBackups[i];
|
||||
if(backup.span) {
|
||||
backup.span.replaceWith(backup.html);
|
||||
}
|
||||
}
|
||||
$('#btnSave, #btnDown, input[value="닫기"]').closest('div').show();
|
||||
console.error('Canvas 캡처 오류:', error);
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -180,8 +180,12 @@ input.date_icon {
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var grid;
|
||||
// PDF 생성용 플래그
|
||||
window.dataLoaded = false;
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
@@ -484,6 +488,198 @@ var gridFn = {
|
||||
$("#TOTAL_SUPPLY_PRICE").val(numberWithCommas(totalSupplyPrice));
|
||||
}
|
||||
}
|
||||
|
||||
// 라이브러리 로드 완료 후 dataLoaded 플래그 설정
|
||||
$(window).on('load', function() {
|
||||
setTimeout(function() {
|
||||
if(typeof html2canvas !== 'undefined' && typeof jspdf !== 'undefined') {
|
||||
window.dataLoaded = true;
|
||||
console.log('발주서 외주양식 - dataLoaded = true');
|
||||
} else {
|
||||
if(typeof html2canvas !== 'undefined' && typeof window.jspdf !== 'undefined') {
|
||||
window.dataLoaded = true;
|
||||
console.log('발주서 외주양식 - dataLoaded = true (jspdf)');
|
||||
} else {
|
||||
console.log('라이브러리 로드 대기중...');
|
||||
setTimeout(function() {
|
||||
window.dataLoaded = true;
|
||||
console.log('발주서 외주양식 - dataLoaded = true (지연)');
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// PDF를 Base64로 생성하여 콜백으로 전달하는 함수
|
||||
function fn_generateAndUploadPdf(callback) {
|
||||
console.log('fn_generateAndUploadPdf 호출됨 (외주 발주서)');
|
||||
|
||||
// 라이브러리 로드 확인
|
||||
if(typeof html2canvas === 'undefined') {
|
||||
console.error('html2canvas 라이브러리가 로드되지 않았습니다.');
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var jsPDF = window.jspdf ? window.jspdf.jsPDF : null;
|
||||
if(!jsPDF) {
|
||||
console.error('jsPDF 라이브러리가 로드되지 않았습니다.');
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 버튼 영역 임시 숨김
|
||||
$('.btn-area, #btnSave, #btnDown, input[value="닫기"]').closest('div').hide();
|
||||
|
||||
// select2 컨테이너 숨김 (중복 표시 방지)
|
||||
$('.select2-container').hide();
|
||||
|
||||
// input/select 값을 텍스트로 변환 (html2canvas가 input value를 캡처하지 못하는 문제 해결)
|
||||
var inputBackups = [];
|
||||
|
||||
// input 요소 처리 (form1 내부 + 그리드 포함)
|
||||
$('input[type="text"], input:not([type])').each(function(){
|
||||
var $input = $(this);
|
||||
var value = $input.val();
|
||||
if(value) {
|
||||
inputBackups.push({
|
||||
element: $input,
|
||||
html: $input[0].outerHTML,
|
||||
parent: $input.parent()
|
||||
});
|
||||
var $span = $('<span class="pdf-temp-span">').text(value).css({
|
||||
'display': 'inline-block',
|
||||
'white-space': 'nowrap',
|
||||
'text-align': $input.css('text-align') || 'left',
|
||||
'font-size': $input.css('font-size') || '12px',
|
||||
'font-weight': $input.css('font-weight') || 'normal',
|
||||
'padding': '2px 5px',
|
||||
'color': $input.css('color') || '#000',
|
||||
'background': 'transparent'
|
||||
});
|
||||
$input.replaceWith($span);
|
||||
inputBackups[inputBackups.length - 1].span = $span;
|
||||
}
|
||||
});
|
||||
|
||||
// select 요소 처리 (select2 포함)
|
||||
$('select').each(function(){
|
||||
var $select = $(this);
|
||||
var value = $select.find('option:selected').text();
|
||||
if(value && value.trim() !== '' && value !== '선택') {
|
||||
inputBackups.push({
|
||||
element: $select,
|
||||
html: $select[0].outerHTML,
|
||||
parent: $select.parent(),
|
||||
wasHidden: $select.is(':hidden')
|
||||
});
|
||||
var $span = $('<span class="pdf-temp-span">').text(value).css({
|
||||
'display': 'inline-block',
|
||||
'white-space': 'nowrap',
|
||||
'text-align': 'left',
|
||||
'font-size': '12px',
|
||||
'padding': '2px 5px',
|
||||
'color': '#000',
|
||||
'background': 'transparent'
|
||||
});
|
||||
$select.after($span).hide();
|
||||
inputBackups[inputBackups.length - 1].span = $span;
|
||||
}
|
||||
});
|
||||
|
||||
// 캡처할 영역 (form1)
|
||||
var captureElement = document.getElementById('form1');
|
||||
|
||||
// html2canvas로 캡처
|
||||
html2canvas(captureElement, {
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
logging: false,
|
||||
backgroundColor: '#ffffff',
|
||||
windowWidth: captureElement.scrollWidth,
|
||||
windowHeight: captureElement.scrollHeight
|
||||
}).then(function(canvas) {
|
||||
console.log('Canvas 캡처 완료');
|
||||
|
||||
// 임시 span 제거 및 원본 복원
|
||||
$('.pdf-temp-span').remove();
|
||||
for(var i = 0; i < inputBackups.length; i++) {
|
||||
var backup = inputBackups[i];
|
||||
if(backup.element && backup.element.is('select')) {
|
||||
// select는 숨겨둔 것만 다시 표시
|
||||
backup.element.show();
|
||||
} else if(backup.span && backup.parent) {
|
||||
// input은 span을 원본으로 교체
|
||||
backup.span.replaceWith(backup.html);
|
||||
}
|
||||
}
|
||||
|
||||
// select2 컨테이너 다시 표시
|
||||
$('.select2-container').show();
|
||||
|
||||
// 버튼 영역 다시 표시
|
||||
$('.btn-area, #btnSave, #btnDown, input[value="닫기"]').closest('div').show();
|
||||
|
||||
try {
|
||||
// Canvas를 JPEG 이미지로 변환
|
||||
var imgData = canvas.toDataURL('image/jpeg', 0.85);
|
||||
console.log('이미지 변환 완료');
|
||||
|
||||
// PDF 생성
|
||||
var pdf = new jsPDF('p', 'mm', 'a4');
|
||||
var imgWidth = 210;
|
||||
var pageHeight = 297;
|
||||
var imgHeight = canvas.height * imgWidth / canvas.width;
|
||||
var heightLeft = imgHeight;
|
||||
var position = 0;
|
||||
|
||||
// 이미지 추가
|
||||
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight, undefined, 'FAST');
|
||||
heightLeft -= pageHeight;
|
||||
|
||||
while (heightLeft >= 0) {
|
||||
position = heightLeft - imgHeight;
|
||||
pdf.addPage();
|
||||
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight, undefined, 'FAST');
|
||||
heightLeft -= pageHeight;
|
||||
}
|
||||
|
||||
console.log('PDF 생성 완료');
|
||||
|
||||
// PDF를 Base64로 변환
|
||||
var pdfBase64 = pdf.output('dataurlstring').split(',')[1];
|
||||
console.log('PDF Base64 생성 완료, 길이:', pdfBase64.length);
|
||||
|
||||
// 콜백 함수 호출
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(pdfBase64);
|
||||
}
|
||||
} catch(pdfError) {
|
||||
console.error('PDF 생성 중 오류:', pdfError);
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
}
|
||||
}
|
||||
|
||||
}).catch(function(error) {
|
||||
// span을 다시 input으로 복원
|
||||
for(var i = 0; i < inputBackups.length; i++) {
|
||||
var backup = inputBackups[i];
|
||||
if(backup.span) {
|
||||
backup.span.replaceWith(backup.html);
|
||||
}
|
||||
}
|
||||
$('.btn-area, #btnSave, #btnDown, input[value="닫기"]').closest('div').show();
|
||||
console.error('Canvas 캡처 오류:', error);
|
||||
if(callback && typeof callback === 'function') {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -42,6 +42,9 @@ $(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
fnc_datepick();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#SEARCH_PART_NO", "#SEARCH_PART_NAME", "#SEARCH_PART_OBJID");
|
||||
|
||||
//조회
|
||||
|
||||
|
||||
@@ -867,11 +870,31 @@ function fn_openMailFormPopup(purchaseOrderObjId){
|
||||
<td><label for="">발주No.</label></td>
|
||||
<td><input type="text" name="purchase_order_no" id="purchase_order_no" autocomplete="off" value="${param.purchase_order_no}" style=""/></td>
|
||||
|
||||
<td><label for="">공급업체</label></td>
|
||||
<td><select name="partner_objid" id="partner_objid" class="select2" autocomplete="off" style=""><option value="">선택</option>${code_map.partner_objid}</select></td>
|
||||
|
||||
<td><label for="">품번</label></td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NO" id="SEARCH_PART_NO" class="select2-part" style="width:150px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="SEARCH_PART_OBJID" id="SEARCH_PART_OBJID" value="">
|
||||
</td>
|
||||
|
||||
<td><label for="">품명</label></td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:150px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<%-- 발주부품, 발주구분 주석처리
|
||||
<td><label for="">발주부품</label></td>
|
||||
<td><select name="type" id="type" class="select2" autocomplete="off" style=""><option value="">선택</option>${code_map.type}</select></td>
|
||||
|
||||
<td><label for="">발주구분</label></td>
|
||||
<td><select name="order_type_cd" id="order_type_cd" class="select2" autocomplete="off" style=""><option value="">선택</option>${code_map.order_type_cd}</select></td>
|
||||
--%>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -881,27 +904,17 @@ function fn_openMailFormPopup(purchaseOrderObjId){
|
||||
<input type="text" name="delivery_end_date" id="delivery_end_date" style="width:77px;" autocomplete="off" value="${param.delivery_end_date }" class="date_icon">
|
||||
</td>
|
||||
|
||||
<td><label for="">공급업체</label></td>
|
||||
<td><select name="partner_objid" id="partner_objid" class="select2" autocomplete="off" style=""><option value="">선택</option>${code_map.partner_objid}</select></td>
|
||||
|
||||
<td><label for="">구매담당자</label></td>
|
||||
<td><select name="sales_mng_user_id" id="sales_mng_user_id" class="select2" autocomplete="off" style="width:190px;" multiple="multiple" ><option value="">선택</option>${code_map.sales_mng_user_id}</select></td>
|
||||
|
||||
<td><label>발주일</label></td>
|
||||
<td>
|
||||
<input type="text" name="reg_start_date" id="reg_start_date" style="width:77px;" autocomplete="off" value="${param.reg_start_date}" class="date_icon">~
|
||||
<input type="text" name="reg_end_date" id="reg_end_date" style="width:77px;" autocomplete="off" value="${param.reg_end_date }" class="date_icon">
|
||||
</td>
|
||||
|
||||
<td><label for="">품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NO" id="SEARCH_PART_NO" style="" autocomplete="off" value="${param.SEARCH_PART_NO}">
|
||||
</td>
|
||||
|
||||
<td><label for="">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" style="" autocomplete="off" value="${param.SEARCH_PART_NAME}">
|
||||
</td>
|
||||
|
||||
<td><label for="">주문유형</label></td>
|
||||
<td><select name="category_cd" id="category_cd" class="select2" autocomplete="off" style=""><option value="">선택</option>${code_map.category_cd}</select></td>
|
||||
|
||||
<td><label for="">제품구분</label></td>
|
||||
<td><select name="product_cd" id="product_cd" class="select2" autocomplete="off" style=""><option value="">선택</option>${code_map.product_cd}</select></td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -190,12 +190,13 @@ String purchaseOrderObjId = request.getParameter("purchaseOrderObjId");
|
||||
</div>
|
||||
|
||||
<div class="attachment-status">
|
||||
<i class="fa fa-file-excel-o"></i>
|
||||
<strong>첨부파일:</strong> 발주서 및 도면 파일이 자동으로 첨부됩니다.
|
||||
<i class="fa fa-file-pdf-o"></i>
|
||||
<strong>첨부파일:</strong> 발주서(PDF) 및 도면 파일이 자동으로 첨부됩니다.
|
||||
</div>
|
||||
|
||||
<form id="mailForm">
|
||||
<input type="hidden" id="purchaseOrderObjId" name="purchaseOrderObjId" value="<%=purchaseOrderObjId%>"/>
|
||||
<input type="hidden" id="pdfSessionId" name="pdfSessionId" value=""/>
|
||||
|
||||
<!-- 공급업체 담당자 선택 -->
|
||||
<div class="form-group">
|
||||
@@ -261,6 +262,9 @@ function fn_loadPurchaseOrderInfo(){
|
||||
if(data.result === "success" && data.purchaseOrderInfo){
|
||||
purchaseOrderInfo = data.purchaseOrderInfo;
|
||||
|
||||
// 양식 타입 확인 (디버깅용)
|
||||
console.log("발주서 양식 타입 (FORM_TYPE):", purchaseOrderInfo.FORM_TYPE);
|
||||
|
||||
// 발주서 정보 표시
|
||||
$("#displayPoNo").text(fnc_checkNull(purchaseOrderInfo.PURCHASE_ORDER_NO) || '-');
|
||||
$("#displayPartnerName").text(fnc_checkNull(purchaseOrderInfo.PARTNER_NAME) || '-');
|
||||
@@ -471,24 +475,197 @@ function fn_sendMail(){
|
||||
cancelButtonText: '취소'
|
||||
}).then((result) => {
|
||||
if(result.isConfirmed){
|
||||
fn_submitMailForm();
|
||||
// PDF 생성 및 발송 시작
|
||||
fn_generatePdfAndSend();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 메일 발송 요청
|
||||
function fn_submitMailForm(){
|
||||
// PDF 생성 및 발송
|
||||
function fn_generatePdfAndSend(){
|
||||
var purchaseOrderObjId = $("#purchaseOrderObjId").val();
|
||||
|
||||
Swal.fire({
|
||||
title: '발송 중...',
|
||||
text: '발주서 메일을 발송하고 있습니다.',
|
||||
title: 'PDF 생성 중...',
|
||||
text: '발주서를 PDF로 변환하고 있습니다.',
|
||||
allowOutsideClick: false,
|
||||
onOpen: () => {
|
||||
Swal.showLoading();
|
||||
}
|
||||
});
|
||||
|
||||
// 발주서 양식 타입 확인 (일반/외주)
|
||||
var formType = fnc_checkNull(purchaseOrderInfo.FORM_TYPE) || 'general';
|
||||
var url = "";
|
||||
|
||||
if(formType === 'outsourcing') {
|
||||
url = "/purchaseOrder/purchaseOrderFormPopup_outsourcing.do?actType=VIEW&PURCHASE_ORDER_MASTER_OBJID=" + purchaseOrderObjId;
|
||||
} else {
|
||||
url = "/purchaseOrder/purchaseOrderFormPopup_general.do?actType=VIEW&PURCHASE_ORDER_MASTER_OBJID=" + purchaseOrderObjId;
|
||||
}
|
||||
|
||||
// 숨겨진 iframe으로 발주서 페이지 로드
|
||||
var iframe = $('<iframe>', {
|
||||
id: 'pdfGeneratorFrame',
|
||||
src: url,
|
||||
style: 'position:absolute;width:0;height:0;border:none;'
|
||||
}).appendTo('body');
|
||||
|
||||
// iframe 로드 완료 대기
|
||||
iframe.on('load', function(){
|
||||
try {
|
||||
var iframeWindow = this.contentWindow;
|
||||
|
||||
// 데이터 로딩 완료 대기 (최대 60초)
|
||||
var checkDataLoaded = function(attempts) {
|
||||
if(attempts > 600) {
|
||||
$('#pdfGeneratorFrame').remove();
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
title: '타임아웃',
|
||||
text: '발주서 데이터 로딩 시간이 초과되었습니다. (60초)',
|
||||
icon: 'error'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if(iframeWindow.dataLoaded === true) {
|
||||
// PDF 생성 함수 호출
|
||||
if(typeof iframeWindow.fn_generateAndUploadPdf === 'function'){
|
||||
iframeWindow.fn_generateAndUploadPdf(function(pdfBase64){
|
||||
$('#pdfGeneratorFrame').remove();
|
||||
|
||||
if(pdfBase64){
|
||||
// PDF 업로드 후 메일 발송
|
||||
fn_uploadPdfAndSendMail(purchaseOrderObjId, pdfBase64);
|
||||
} else {
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: 'PDF 생성에 실패했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$('#pdfGeneratorFrame').remove();
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: '발주서 페이지 로드에 실패했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
checkDataLoaded(attempts + 1);
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
|
||||
checkDataLoaded(0);
|
||||
} catch(e) {
|
||||
console.error('PDF 생성 오류:', e);
|
||||
$('#pdfGeneratorFrame').remove();
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: 'PDF 생성 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// 타임아웃 설정 (120초)
|
||||
setTimeout(function(){
|
||||
if($('#pdfGeneratorFrame').length > 0){
|
||||
$('#pdfGeneratorFrame').remove();
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
title: '타임아웃',
|
||||
text: 'PDF 생성 시간이 초과되었습니다. (120초)',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
}, 120000);
|
||||
}
|
||||
|
||||
// PDF 업로드 및 메일 발송
|
||||
function fn_uploadPdfAndSendMail(purchaseOrderObjId, pdfBase64){
|
||||
Swal.update({
|
||||
text: 'PDF 업로드 중...'
|
||||
});
|
||||
|
||||
// 청크 업로드
|
||||
var chunkSize = 100 * 1024;
|
||||
var totalChunks = Math.ceil(pdfBase64.length / chunkSize);
|
||||
var uploadedChunks = 0;
|
||||
var sessionId = 'pdf_po_' + purchaseOrderObjId + '_' + new Date().getTime();
|
||||
|
||||
function uploadChunk(chunkIndex) {
|
||||
var start = chunkIndex * chunkSize;
|
||||
var end = Math.min(start + chunkSize, pdfBase64.length);
|
||||
var chunk = pdfBase64.substring(start, end);
|
||||
|
||||
$.ajax({
|
||||
url: "/purchaseOrder/uploadPdfChunk.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
sessionId: sessionId,
|
||||
chunkIndex: chunkIndex,
|
||||
totalChunks: totalChunks,
|
||||
chunk: chunk
|
||||
},
|
||||
dataType: "json",
|
||||
timeout: 30000,
|
||||
success: function(data){
|
||||
if(data.result === "success"){
|
||||
uploadedChunks++;
|
||||
|
||||
var progress = Math.round((uploadedChunks / totalChunks) * 100);
|
||||
Swal.update({
|
||||
text: 'PDF 업로드 중... ' + progress + '%'
|
||||
});
|
||||
|
||||
if(chunkIndex + 1 < totalChunks){
|
||||
uploadChunk(chunkIndex + 1);
|
||||
} else {
|
||||
// 모든 청크 업로드 완료, 메일 발송
|
||||
$("#pdfSessionId").val(sessionId);
|
||||
fn_submitMailForm();
|
||||
}
|
||||
} else {
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
title: '업로드 실패',
|
||||
text: 'PDF 업로드 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
Swal.close();
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: 'PDF 업로드 중 시스템 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
uploadChunk(0);
|
||||
}
|
||||
|
||||
// 메일 발송 요청
|
||||
function fn_submitMailForm(){
|
||||
Swal.update({
|
||||
text: '메일 발송 중...'
|
||||
});
|
||||
|
||||
var formData = {
|
||||
objId: $("#purchaseOrderObjId").val(),
|
||||
pdfSessionId: $("#pdfSessionId").val(),
|
||||
toEmails: $("#toEmails").val(),
|
||||
ccEmails: $("#ccEmails").val(),
|
||||
subject: $("#subject").val(),
|
||||
|
||||
@@ -147,8 +147,10 @@ function fn_reset(){
|
||||
$("#search_receipt_date_to").val("");
|
||||
$("#search_customer_name").val("");
|
||||
$("#search_model_name").val("");
|
||||
$("#search_product_no").val("");
|
||||
$("#search_product_name").val("");
|
||||
$("#search_part_no").val("");
|
||||
$("#search_part_name").val("");
|
||||
$("#search_serial_no").val("");
|
||||
$("#search_manufacturer").val("");
|
||||
$("#search_blame_decision").val("");
|
||||
@@ -276,9 +278,9 @@ function fn_FileRegist(objId, docType, docTypeName){
|
||||
</select>
|
||||
</td> -->
|
||||
<td><label>품번</label></td>
|
||||
<td><input type="text" name="search_product_no" id="search_product_no" style="" autocomplete="off"></td>
|
||||
<td><input type="text" name="search_product_no" id="search_product_no" style="width:150px;" autocomplete="off"></td>
|
||||
<td><label>품명</label></td>
|
||||
<td><input type="text" name="search_product_name" id="search_product_name" style="" autocomplete="off"></td>
|
||||
<td><input type="text" name="search_product_name" id="search_product_name" style="width:150px;" autocomplete="off"></td>
|
||||
<td><label>부품품번</label></td>
|
||||
<td><input type="text" name="search_part_no" id="search_part_no" style="width:215px;" autocomplete="off"></td>
|
||||
<td><label>부품품명</label></td>
|
||||
@@ -296,9 +298,9 @@ function fn_FileRegist(objId, docType, docTypeName){
|
||||
<td>
|
||||
<select name="search_blame_decision" id="search_blame_decision" class="select2" autocomplete="off" style="">
|
||||
<option value="">전체</option>
|
||||
<option value="R">R</option>
|
||||
<option value="C">C</option>
|
||||
<option value="O">O</option>
|
||||
<option value="R">RPS</option>
|
||||
<option value="C">고객사</option>
|
||||
<option value="O">외주업체</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><label>상태</label></td>
|
||||
|
||||
257
WebContent/WEB-INF/view/quality/ecrDocFormPopUp.jsp
Normal file
257
WebContent/WEB-INF/view/quality/ecrDocFormPopUp.jsp
Normal file
@@ -0,0 +1,257 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@include file="/init.jsp"%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>ECR - Engineering Change Request</title>
|
||||
<link rel="stylesheet" type="text/css" href="/css/basic.css">
|
||||
<script src="/js/jquery-3.2.1.min.js"></script>
|
||||
<script src="/js/sweetalert2.all.min.js"></script>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
font-family: 'Malgun Gothic', 'Arial', sans-serif;
|
||||
background: #fff;
|
||||
padding: 0;
|
||||
}
|
||||
.ecr_container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
/* 헤더 영역 */
|
||||
.ecr_header {
|
||||
display: table;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
.ecr_header_left {
|
||||
display: table-cell;
|
||||
width: 180px;
|
||||
vertical-align: middle;
|
||||
padding: 10px 15px;
|
||||
border-right: 1px solid #333;
|
||||
}
|
||||
.ecr_logo {
|
||||
display: block;
|
||||
width: 150px;
|
||||
height: 40px;
|
||||
background: url(/images/logo.png) center center no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
.ecr_header_center {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
background: #1565a0;
|
||||
color: white;
|
||||
padding: 15px;
|
||||
}
|
||||
.ecr_header_center h1 {
|
||||
font-size: 28px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.ecr_header_center p {
|
||||
font-size: 14px;
|
||||
}
|
||||
.ecr_header_right {
|
||||
display: table-cell;
|
||||
width: 180px;
|
||||
vertical-align: top;
|
||||
border-left: 1px solid #333;
|
||||
}
|
||||
.ecr_header_right table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.ecr_header_right td {
|
||||
padding: 5px 8px;
|
||||
font-size: 12px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.ecr_header_right td:first-child {
|
||||
font-weight: bold;
|
||||
width: 70px;
|
||||
}
|
||||
.ecr_header_right input {
|
||||
border: none;
|
||||
width: 80px;
|
||||
font-size: 12px;
|
||||
}
|
||||
/* 본문 영역 */
|
||||
.ecr_body {
|
||||
padding: 20px;
|
||||
min-height: 500px;
|
||||
border-bottom: 1px dashed #999;
|
||||
}
|
||||
.ecr_section {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.ecr_section_title {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
margin-bottom: 5px;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.ecr_section_title_kr {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
text-decoration: underline;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.ecr_textarea {
|
||||
width: 100%;
|
||||
min-height: 120px;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
font-size: 13px;
|
||||
resize: vertical;
|
||||
font-family: inherit;
|
||||
}
|
||||
.ecr_textarea:focus {
|
||||
outline: 2px solid #1565a0;
|
||||
}
|
||||
/* 푸터 영역 */
|
||||
.ecr_footer {
|
||||
background: #fff;
|
||||
color: #333;
|
||||
padding: 10px 15px;
|
||||
font-size: 11px;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
/* 버튼 영역 */
|
||||
.btn_area {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
padding: 15px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input type="hidden" id="OBJID" value="${resultMap.objid}">
|
||||
|
||||
<div class="ecr_container">
|
||||
<!-- 헤더 -->
|
||||
<div class="ecr_header">
|
||||
<div class="ecr_header_left">
|
||||
<span class="ecr_logo"></span>
|
||||
</div>
|
||||
<div class="ecr_header_center">
|
||||
<h1>ECR</h1>
|
||||
<p>(Engineering Change Request)</p>
|
||||
</div>
|
||||
<div class="ecr_header_right">
|
||||
<table>
|
||||
<tr>
|
||||
<td>Form no.</td>
|
||||
<td><input type="text" id="ECR_DOC_FORM_NO" value="${resultMap.ecr_doc_form_no}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rev.no</td>
|
||||
<td><input type="text" id="ECR_REV_NO" value="${resultMap.ecr_rev_no}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rev. date</td>
|
||||
<td><input type="text" id="ECR_REV_DATE" value="${resultMap.ecr_rev_date}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Author</td>
|
||||
<td><input type="text" id="ECR_DOC_AUTHOR" value="${resultMap.ecr_doc_author}"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 본문 -->
|
||||
<div class="ecr_body">
|
||||
<div class="ecr_section">
|
||||
<%-- <div class="ecr_section_title">Fill out clearly, concisely</div> --%>
|
||||
<div class="ecr_section_title_kr">명확하고 간결하게 작성</div>
|
||||
<textarea class="ecr_textarea" id="ECR_DOC_SUMMARY">${resultMap.ecr_doc_summary}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="ecr_section">
|
||||
<%-- <div class="ecr_section_title">Description of the change (reason / background)</div> --%>
|
||||
<div class="ecr_section_title_kr">변경사항 설명 (이유 / 배경)</div>
|
||||
<textarea class="ecr_textarea" id="ECR_DOC_REASON" style="min-height:150px;">${resultMap.ecr_doc_reason}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 푸터 -->
|
||||
<div class="ecr_footer">
|
||||
<p>Confidential! © RPS reserves all rights even in the event of industrial property rights.</p>
|
||||
<p>We reserve all rights of disposal such as copying and passing on to third parties!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 버튼 영역 -->
|
||||
<div class="btn_area">
|
||||
<input type="button" class="plm_btns" value="저장" onclick="fn_save()">
|
||||
<input type="button" class="plm_btns" value="닫기" onclick="self.close()">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
console.log("ECR 팝업 로드됨");
|
||||
console.log("OBJID:", "${resultMap.OBJID}");
|
||||
console.log("ECR_NO:", "${resultMap.ECR_NO}");
|
||||
console.log("REQUESTER_NAME:", "${resultMap.REQUESTER_NAME}");
|
||||
console.log("resultMap 전체:", "${resultMap}");
|
||||
});
|
||||
|
||||
function fn_save(){
|
||||
var objId = $("#OBJID").val();
|
||||
var formNo = $("#ECR_DOC_FORM_NO").val();
|
||||
var revNo = $("#ECR_REV_NO").val();
|
||||
var revDate = $("#ECR_REV_DATE").val();
|
||||
var author = $("#ECR_DOC_AUTHOR").val();
|
||||
var summary = $("#ECR_DOC_SUMMARY").val();
|
||||
var reason = $("#ECR_DOC_REASON").val();
|
||||
|
||||
if(!summary && !reason){
|
||||
Swal.fire({icon:'warning', title:'알림', text:'내용을 입력해주세요.'});
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "/quality/saveEcrDoc.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
OBJID: objId,
|
||||
ECR_DOC_FORM_NO: formNo,
|
||||
ECR_REV_NO: revNo,
|
||||
ECR_REV_DATE: revDate,
|
||||
ECR_DOC_AUTHOR: author,
|
||||
ECR_DOC_SUMMARY: summary,
|
||||
ECR_DOC_REASON: reason
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result == "success"){
|
||||
Swal.fire({icon:'success', title:'저장완료', text:'설계변경요청서가 저장되었습니다.'}).then(function(){
|
||||
self.close();
|
||||
});
|
||||
} else {
|
||||
Swal.fire({icon:'error', title:'오류', text:'저장에 실패했습니다: ' + (result.message || '')});
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.log("AJAX 에러:", xhr.responseText);
|
||||
Swal.fire({icon:'error', title:'오류', text:'저장 중 오류가 발생했습니다.'});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -75,9 +75,9 @@ $(document).ready(function(){
|
||||
fn_search();
|
||||
});
|
||||
|
||||
// 컬럼: ECR No, 요청일, 요청자, 품번, 품명, 이슈사항, 완료요청일, 조치부서, 조치담당자, 조치자, 조치내용, 완료일, 첨부파일
|
||||
// 컬럼: ECR No, 요청일, 요청자, 품번, 품명, 이슈사항, 완료요청일, 조치부서, 조치담당자, 조치자, 조치내용, 완료일, 이미지파일, 첨부파일, 설계변경요청서
|
||||
var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'ECR No', field:'ECR_NO',
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:130, widthGrow:1, title:'ECR No', field:'ECR_NO',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
@@ -91,11 +91,11 @@ var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:150, widthGrow:2, title:'이슈사항', field:'ISSUE_CONTENT'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'완료요청일', field:'DUE_DATE'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:90, widthGrow:1, title:'조치부서', field:'ACTION_DEPT_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:90, widthGrow:1, title:'조치담당자', field:'ACTION_MANAGER_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'조치담당자', field:'ACTION_MANAGER_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'조치자', field:'ACTION_USER_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:150, widthGrow:2, title:'조치내용', field:'ACTION_CONTENT'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'완료일', field:'COMPLETE_DATE'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'이미지', field:'IMAGE_FILE',
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:85, widthGrow:1, title:'이미지파일', field:'IMAGE_FILE',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
@@ -108,6 +108,13 @@ var columns = [
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_FileRegist(objid,"ECR_RESULT","ECR결과첨부");
|
||||
}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'설계변경요청서', field:'ECR_DOC_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_openEcrDocPopUp(objid);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -223,6 +230,22 @@ function fn_FileRegist(objId, docType, docTypeName){
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
|
||||
// 설계변경요청서 팝업
|
||||
function fn_openEcrDocPopUp(objId){
|
||||
var popup_width = 600;
|
||||
var popup_height = 750;
|
||||
var url = "/quality/ecrDocFormPopUp.do?OBJID=" + objId;
|
||||
var popup = window.open(url, "ecrDocPopUp", "width="+popup_width+",height="+popup_height+",scrollbars=yes,resizable=yes");
|
||||
|
||||
// 팝업 닫힘 감지 및 그리드 새로고침
|
||||
var checkPopup = setInterval(function(){
|
||||
if(popup.closed){
|
||||
clearInterval(checkPopup);
|
||||
fn_search(); // 그리드 새로고침
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// 결재상신
|
||||
function fn_approval(){
|
||||
var selected = _tabulGrid.getSelectedData();
|
||||
|
||||
@@ -58,6 +58,9 @@ $(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
fnc_datepick();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#search_part_no", "#search_part_name", "#search_part_objid");
|
||||
|
||||
$("input").keyup(function(e){
|
||||
if(e.keyCode == 13){
|
||||
$("#page").val("1");
|
||||
@@ -116,13 +119,14 @@ var columns = [
|
||||
|
||||
// 조회
|
||||
function fn_search(){
|
||||
// 프로젝트번호 multi select 처리
|
||||
// 프로젝트번호 multi select 처리 (배열을 콤마로 join)
|
||||
var selectedProjectNos = $("#project_no").val();
|
||||
$('input[name="project_nos"]').remove();
|
||||
var projectNosValue = (selectedProjectNos && selectedProjectNos.length > 0) ? selectedProjectNos.join(',') : '';
|
||||
$('<input>').attr({
|
||||
type: 'hidden',
|
||||
name: 'project_nos',
|
||||
value: selectedProjectNos
|
||||
value: projectNosValue
|
||||
}).appendTo('#form1');
|
||||
|
||||
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/quality/incomingInspectionGridList.do", columns, true);
|
||||
@@ -238,10 +242,19 @@ function fn_deliveryAcceptanceViewPopUp(objId,DELIVERY_STATUS){
|
||||
</td>
|
||||
|
||||
<td><label for="">품번</label></td>
|
||||
<td><input type="text" name="search_part_no" id="search_part_no" style="width:170px;" autocomplete="off" value="${param.search_part_no}"></td>
|
||||
<td>
|
||||
<select name="search_part_no" id="search_part_no" class="select2-part" style="width:170px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_part_objid" id="search_part_objid" value="">
|
||||
</td>
|
||||
|
||||
<td><label for="">품명</label></td>
|
||||
<td><input type="text" name="search_part_name" id="search_part_name" style="width:170px;" autocomplete="off" value="${param.search_part_name}"></td>
|
||||
<td>
|
||||
<select name="search_part_name" id="search_part_name" class="select2-part" style="width:170px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">공급업체</label></td>
|
||||
<td><select name="search_partner" id="search_partner" class="select2" autocomplete="off" style="width:250px;"><option value="">선택</option>${code_map.partner_objid}</select></td>
|
||||
@@ -254,6 +267,34 @@ function fn_deliveryAcceptanceViewPopUp(objId,DELIVERY_STATUS){
|
||||
<option value="">전체</option>
|
||||
<option value="입고중">입고중</option>
|
||||
<option value="입고완료">입고완료</option>
|
||||
<option value="지연">지연</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">제품구분</label></td>
|
||||
<td>
|
||||
<select name="search_product_cd" id="search_product_cd" class="select2" autocomplete="off" style="width:120px;">
|
||||
<option value="">전체</option>
|
||||
${code_map.product_cd}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">검사여부</label></td>
|
||||
<td>
|
||||
<select name="search_inspection_yn" id="search_inspection_yn" class="select2" autocomplete="off" style="width:120px;">
|
||||
<option value="">전체</option>
|
||||
<option value="검사">검사</option>
|
||||
<option value="스킵">스킵</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">요청현황</label></td>
|
||||
<td>
|
||||
<select name="search_request_status" id="search_request_status" class="select2" autocomplete="off" style="width:120px;">
|
||||
<option value="">전체</option>
|
||||
<option value="미요청">미요청</option>
|
||||
<option value="요청중">요청중</option>
|
||||
<option value="요청완료">요청완료</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ $(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
fnc_datepick();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#search_part_no", "#search_part_name", "#search_part_objid");
|
||||
|
||||
$("input").keyup(function(e){
|
||||
if(e.keyCode == 13){
|
||||
$("#page").val("1");
|
||||
@@ -86,6 +89,8 @@ $(document).ready(function(){
|
||||
|
||||
// 컬럼: 품의서 No, 발주서 No, 프로젝트번호, 품번, 품명, 공급업체, 입고결과, 요청일, 요청자, 검사자, 검사일, 검사결과
|
||||
var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사일', field:'INSPECTION_DATE'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'품의서 No', field:'PROPOSAL_NO'
|
||||
// formatter:fnc_createGridAnchorTag,
|
||||
// cellClick:function(e, cell){
|
||||
@@ -103,7 +108,7 @@ var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:130, widthGrow:1, title:'프로젝트번호', field:'PROJECT_NO'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'제품구분', field:'PRODUCT_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:120, widthGrow:2, title:'품번', field:'PART_NO'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:150, widthGrow:3, title:'품명', field:'PART_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:130, widthGrow:3, title:'품명', field:'PART_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:130, widthGrow:2, title:'공급업체', field:'PARTNER_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'입고결과', field:'DELIVERY_STATUS',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
@@ -115,28 +120,26 @@ var columns = [
|
||||
},
|
||||
// {headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'요청일', field:'REQUEST_DATE'},
|
||||
// {headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'요청자', field:'REQUEST_USER_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사일', field:'INSPECTION_DATE'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 100, widthGrow : 1, title : '업체성적서', field : 'INSPECTION_FILE_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_FileRegist(objid,"INSPECTION_FILE","검사성적서");
|
||||
}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'검사결과', field:'INSPECTION_RESULT',
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'검사현황', field:'INSPECTION_RESULT',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var val = fnc_checkNull(cell.getValue());
|
||||
if(val === 'NG') return '<span class="inspection-ng">NG</span>';
|
||||
if(val === 'OK') return '<span class="inspection-ok">OK</span>';
|
||||
if(val === '검사중') return '<span style="color:#ffc107;font-weight:bold;">검사중</span>';
|
||||
// 처리결과 기준: 전부 입력 = 완료, 일부만 입력 = 진행중, 없으면 미검사
|
||||
if(val === '완료') return '<span class="inspection-ok">완료</span>';
|
||||
if(val === '진행중') return '<span style="color:#ffc107;font-weight:bold;">진행중</span>';
|
||||
return '<span style="color:#999;cursor:pointer;">미검사</span>';
|
||||
},
|
||||
cellClick:function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_inspectionPopUp(objId);
|
||||
}
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 100, widthGrow : 1, title : '업체성적서', field : 'INSPECTION_FILE_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_FileRegist(objid,"INSPECTION_FILE","검사성적서");
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// 조회
|
||||
@@ -300,10 +303,19 @@ function fn_deliveryAcceptanceViewPopUp(objId,DELIVERY_STATUS){
|
||||
</td>
|
||||
|
||||
<td><label for="">품번</label></td>
|
||||
<td><input type="text" name="search_part_no" id="search_part_no" style="width:170px;" autocomplete="off" value="${param.search_part_no}"></td>
|
||||
<td>
|
||||
<select name="search_part_no" id="search_part_no" class="select2-part" style="width:170px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_part_objid" id="search_part_objid" value="">
|
||||
</td>
|
||||
|
||||
<td><label for="">품명</label></td>
|
||||
<td><input type="text" name="search_part_name" id="search_part_name" style="width:170px;" autocomplete="off" value="${param.search_part_name}"></td>
|
||||
<td>
|
||||
<select name="search_part_name" id="search_part_name" class="select2-part" style="width:170px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">공급업체</label></td>
|
||||
<td><select name="search_partner" id="search_partner" class="select2" autocomplete="off" style="width:250px;"><option value="">선택</option>${code_map.partner_objid}</select></td>
|
||||
@@ -316,6 +328,15 @@ function fn_deliveryAcceptanceViewPopUp(objId,DELIVERY_STATUS){
|
||||
<option value="">전체</option>
|
||||
<option value="입고중">입고중</option>
|
||||
<option value="입고완료">입고완료</option>
|
||||
<option value="지연">지연</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td><label for="">제품구분</label></td>
|
||||
<td>
|
||||
<select name="search_product_cd" id="search_product_cd" class="select2" autocomplete="off" style="width:120px;">
|
||||
<option value="">전체</option>
|
||||
${code_map.product_cd}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
@@ -328,12 +349,12 @@ function fn_deliveryAcceptanceViewPopUp(objId,DELIVERY_STATUS){
|
||||
<input type="text" name="inspection_end_date" id="inspection_end_date" style="width:100px;" autocomplete="off" value="${param.inspection_end_date }" class="date_icon">
|
||||
</td>
|
||||
|
||||
<td><label for="">검사결과</label></td>
|
||||
<td><label for="">검사현황</label></td>
|
||||
<td>
|
||||
<select name="search_inspection_result" id="search_inspection_result" class="select2" autocomplete="off" style="width:120px;">
|
||||
<select name="search_inspection_status" id="search_inspection_status" class="select2" autocomplete="off" style="width:120px;">
|
||||
<option value="">전체</option>
|
||||
<option value="OK">OK</option>
|
||||
<option value="NG">NG</option>
|
||||
<option value="완료">완료</option>
|
||||
<option value="진행중">진행중</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -136,15 +136,15 @@ var _DEFECT_TYPE_LIST = [];
|
||||
// 처리현황 목록
|
||||
var _ACTION_STATUS_LIST = [
|
||||
{"CODE": "", "NAME": "선택"},
|
||||
{"CODE": "Rework", "NAME": "Rework"},
|
||||
{"CODE": "Scrap", "NAME": "Scrap"}
|
||||
{"CODE": "Rework", "NAME": "수정"},
|
||||
{"CODE": "Scrap", "NAME": "폐기"}
|
||||
];
|
||||
// 처리결과 목록
|
||||
var _ACTION_RESULT_LIST = [
|
||||
{"CODE": "", "NAME": "선택"},
|
||||
{"CODE": "수정", "NAME": "수정"},
|
||||
{"CODE": "수정", "NAME": "수정완료"},
|
||||
{"CODE": "폐기", "NAME": "폐기"},
|
||||
{"CODE": "특채", "NAME": "특채"}
|
||||
{"CODE": "특채", "NAME": "특채완료"}
|
||||
];
|
||||
// 검사자 목록
|
||||
var _INSPECTOR_LIST = [];
|
||||
@@ -208,8 +208,8 @@ $(document).ready(function(){
|
||||
// =====================================================
|
||||
function fn_initLeftGrid() {
|
||||
var columns = [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", headerHozAlign:"center", hozAlign:"center", headerSort:false, width:30},
|
||||
{title:'품번', field:'PART_NO', headerHozAlign:'center', hozAlign:'left', width:150,
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", headerHozAlign:"center", hozAlign:"center", headerSort:false, width:30, frozen: true},
|
||||
{title:'품번', field:'PART_NO', headerHozAlign:'center', hozAlign:'left', width:150, frozen: true,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell) {
|
||||
// 품번 클릭 시 품목상세 팝업
|
||||
@@ -218,18 +218,52 @@ function fn_initLeftGrid() {
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:'품명', field:'PART_NAME', headerHozAlign:'center', hozAlign:'left', width:150},
|
||||
{title:'품명', field:'PART_NAME', headerHozAlign:'center', hozAlign:'left', width:150, frozen: true},
|
||||
{title:'입고일', field:'DELIVERY_DATE', headerHozAlign:'center', hozAlign:'center', width:90},
|
||||
{title:'입고수량', field:'DELIVERY_QTY', headerHozAlign:'center', hozAlign:'right', width:90,
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
{title:'검사여부', field:'INSPECTION_YN', headerHozAlign:'center', hozAlign:'center', width:70,
|
||||
{title:'검사여부', field:'INSPECTION_YN', headerHozAlign:'center', hozAlign:'center', width:80,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === '검사') return '<span style="color:#007bff;font-weight:bold;">검사</span>';
|
||||
if(val === '스킵') return '<span style="color:#999;">스킵</span>';
|
||||
return val;
|
||||
}
|
||||
},
|
||||
{title:'검사수량', field:'INSPECTION_QTY', headerHozAlign:'center', hozAlign:'right', width:85,
|
||||
editor:"number",
|
||||
editorParams: {min:0, step:1},
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '';
|
||||
return parseInt(val).toLocaleString();
|
||||
}
|
||||
},
|
||||
{title:'불량수량', field:'DEFECT_QTY_SUM', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '0';
|
||||
return parseInt(val).toLocaleString();
|
||||
}
|
||||
},
|
||||
{title:'불량율', field:'LEFT_DEFECT_RATE', headerHozAlign:'center', hozAlign:'right', width:70,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '';
|
||||
return val + '%';
|
||||
}
|
||||
},
|
||||
{title:'검사성적서', field:'INSPECTION_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell) {
|
||||
var objId = fnc_checkNull(cell.getData().INSPECTION_DETAIL_OBJID);
|
||||
if(objId) {
|
||||
fn_openInspectionFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire("먼저 저장 후 파일을 등록할 수 있습니다.");
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -272,7 +306,75 @@ function fn_initLeftGrid() {
|
||||
|
||||
// 셀 편집 이벤트
|
||||
leftGrid.on("cellEdited", function(cell) {
|
||||
cell.getData().GRID_STATUS = 'U';
|
||||
var row = cell.getRow();
|
||||
var data = row.getData();
|
||||
var field = cell.getField();
|
||||
|
||||
// 검사수량 변경 시 불량율 재계산
|
||||
if (field === 'INSPECTION_QTY') {
|
||||
fn_calcLeftGridDefectRate(row);
|
||||
}
|
||||
|
||||
data.GRID_STATUS = 'U';
|
||||
});
|
||||
}
|
||||
|
||||
// 좌측 그리드 불량율 계산 (불량수량합계 / 입고수량 * 100)
|
||||
function fn_calcLeftGridDefectRate(row) {
|
||||
var data = row.getData();
|
||||
var deliveryQty = parseInt(data.DELIVERY_QTY) || 0;
|
||||
var defectQtySum = parseInt(data.DEFECT_QTY_SUM) || 0;
|
||||
|
||||
if (deliveryQty > 0) {
|
||||
var rate = (defectQtySum / deliveryQty * 100).toFixed(2);
|
||||
row.update({"LEFT_DEFECT_RATE": rate});
|
||||
} else {
|
||||
row.update({"LEFT_DEFECT_RATE": ""});
|
||||
}
|
||||
}
|
||||
|
||||
// 검사성적서 파일 팝업
|
||||
function fn_openInspectionFilePopUp(objId) {
|
||||
var popup_width = 800;
|
||||
var popup_height = 300;
|
||||
var params = "?targetObjId=" + objId + "&docType=INSPECTION_REPORT&docTypeName=검사성적서";
|
||||
var url = "/common/FileRegistPopup.do" + params;
|
||||
window.open(url, "inspectionFilePopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
// 좌측 그리드 불량수량 합계/불량율 실시간 업데이트 (우측 그리드 변경 시)
|
||||
function fn_updateLeftGridDefectSum() {
|
||||
if(!selectedRowData) return;
|
||||
|
||||
// 우측 그리드의 불량수량 합계 계산
|
||||
var rightGridData = rightGrid.getData();
|
||||
var defectQtySum = 0;
|
||||
rightGridData.forEach(function(row) {
|
||||
if(row.GRID_STATUS !== 'D') { // 삭제 표시된 행 제외
|
||||
defectQtySum += parseInt(row.DEFECT_QTY) || 0;
|
||||
}
|
||||
});
|
||||
|
||||
// 좌측 그리드에서 현재 선택된 행 찾기
|
||||
var leftRows = leftGrid.getRows();
|
||||
leftRows.forEach(function(row) {
|
||||
var data = row.getData();
|
||||
if(data.INSPECTION_DETAIL_OBJID === selectedDetailObjid) {
|
||||
// 불량수량 합계 업데이트
|
||||
row.update({"DEFECT_QTY_SUM": defectQtySum});
|
||||
|
||||
// 불량율 재계산 (불량수량합계 / 입고수량 * 100)
|
||||
var deliveryQty = parseInt(data.DELIVERY_QTY) || 0;
|
||||
if(deliveryQty > 0) {
|
||||
var rate = (defectQtySum / deliveryQty * 100).toFixed(2);
|
||||
row.update({"LEFT_DEFECT_RATE": rate});
|
||||
} else {
|
||||
row.update({"LEFT_DEFECT_RATE": ""});
|
||||
}
|
||||
|
||||
// 변경 표시
|
||||
data.GRID_STATUS = 'U';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -334,29 +436,30 @@ function fn_initRightGrid() {
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_ACTION_STATUS_LIST}
|
||||
},
|
||||
{title:'검사수량', field:'INSPECTION_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
editor:"input",
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '';
|
||||
return parseInt(val);
|
||||
}
|
||||
},
|
||||
// {title:'검사수량', field:'INSPECTION_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
// editor:"input",
|
||||
// formatter: function(cell) {
|
||||
// var val = cell.getValue();
|
||||
// if(val === null || val === '' || val === undefined) return '';
|
||||
// return parseInt(val);
|
||||
// }
|
||||
// },
|
||||
{title:'불량수량', field:'DEFECT_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
editor:"input",
|
||||
editor:"number",
|
||||
editorParams: {min:0, step:1},
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '';
|
||||
return parseInt(val);
|
||||
}
|
||||
},
|
||||
{title:'불량율', field:'DEFECT_RATE', headerHozAlign:'center', hozAlign:'right', width:70, editor:false,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if (val) return val + '%';
|
||||
return '';
|
||||
}
|
||||
},
|
||||
// {title:'불량율', field:'DEFECT_RATE', headerHozAlign:'center', hozAlign:'right', width:70, editor:false,
|
||||
// formatter: function(cell) {
|
||||
// var val = cell.getValue();
|
||||
// if (val) return val + '%';
|
||||
// return '';
|
||||
// }
|
||||
// },
|
||||
{title:'검사일', field:'INSPECTION_DATE', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor:"date"
|
||||
},
|
||||
@@ -427,25 +530,33 @@ function fn_initRightGrid() {
|
||||
rightGrid.on("cellEdited", function(cell) {
|
||||
var row = cell.getRow();
|
||||
var data = row.getData();
|
||||
var field = cell.getField();
|
||||
|
||||
// 불량유형 변경 시 불량원인 초기화
|
||||
if (cell.getField() === 'DEFECT_TYPE') {
|
||||
if (field === 'DEFECT_TYPE') {
|
||||
row.update({"DEFECT_REASON": ""});
|
||||
}
|
||||
|
||||
// 검사수량, 불량수량 변경 시 불량율 자동 계산
|
||||
if (cell.getField() === 'INSPECTION_QTY' || cell.getField() === 'DEFECT_QTY') {
|
||||
// 불량수량 변경 시 정수로 변환
|
||||
if (field === 'DEFECT_QTY') {
|
||||
var defectQty = parseInt(data.DEFECT_QTY) || 0;
|
||||
row.update({"DEFECT_QTY": defectQty});
|
||||
// 불량율 계산
|
||||
fn_calcDefectRate(row);
|
||||
// 검사결과 자동 설정
|
||||
fn_updateInspectionResult(row);
|
||||
// 좌측 그리드 불량수량 합계/불량율 업데이트
|
||||
fn_updateLeftGridDefectSum();
|
||||
}
|
||||
|
||||
// 검사수량 변경 시 불량율 자동 계산
|
||||
if (field === 'INSPECTION_QTY') {
|
||||
fn_calcDefectRate(row);
|
||||
}
|
||||
|
||||
// 불량수량 변경 시 검사결과 자동 설정
|
||||
if (cell.getField() === 'DEFECT_QTY') {
|
||||
var defectQty = parseInt(data.DEFECT_QTY) || 0;
|
||||
if (defectQty > 0) {
|
||||
row.update({"INSPECTION_RESULT": "NG"});
|
||||
} else {
|
||||
row.update({"INSPECTION_RESULT": "OK"});
|
||||
}
|
||||
// 처리결과 변경 시 검사결과 자동 설정
|
||||
if (field === 'ACTION_RESULT') {
|
||||
fn_updateInspectionResult(row);
|
||||
}
|
||||
|
||||
data.GRID_STATUS = data.GRID_STATUS === 'I' ? 'I' : 'U';
|
||||
@@ -466,6 +577,28 @@ function fn_calcDefectRate(row) {
|
||||
}
|
||||
}
|
||||
|
||||
// 검사결과 자동 설정
|
||||
// 처리결과가 '수정' 또는 '특채'이면 OK, 불량수량 > 0 이면 NG, 그 외 OK
|
||||
function fn_updateInspectionResult(row) {
|
||||
var data = row.getData();
|
||||
var defectQty = parseInt(data.DEFECT_QTY) || 0;
|
||||
var actionResult = fnc_checkNull(data.ACTION_RESULT);
|
||||
|
||||
console.log("[검사결과 자동설정] 불량수량:", defectQty, ", 처리결과:", actionResult);
|
||||
|
||||
var newResult = "OK";
|
||||
// 처리결과가 '수정' 또는 '특채'이면 불량수량 있어도 OK
|
||||
if (actionResult === '수정' || actionResult === '특채') {
|
||||
newResult = "OK";
|
||||
} else if (defectQty > 0) {
|
||||
// 불량수량 있으면 NG
|
||||
newResult = "NG";
|
||||
}
|
||||
|
||||
console.log("[검사결과 자동설정] 결과:", newResult);
|
||||
row.update({"INSPECTION_RESULT": newResult});
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 좌측 그리드 조회
|
||||
// =====================================================
|
||||
@@ -609,6 +742,8 @@ function fn_deleteDefectRow() {
|
||||
row.getElement().style.display = 'none';
|
||||
}
|
||||
});
|
||||
// 좌측 그리드 불량수량 합계/불량율 업데이트
|
||||
fn_updateLeftGridDefectSum();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ String connector = person.getUserId();
|
||||
/* 검사결과 스타일 */
|
||||
.inspection-ng { color: #dc3545; font-weight: bold; }
|
||||
.inspection-ok { color: #28a745; font-weight: bold; }
|
||||
/* 공통에서 추가되는 초기화, Excel Download 버튼 숨기기 */
|
||||
.resetBtn, .excelBtn { display: none !important; }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -170,6 +172,16 @@ function fn_search(){
|
||||
|
||||
var columns = [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:30},
|
||||
{title:'검사일', field:'INSPECTION_DATE', headerHozAlign:'center', hozAlign:'center', width:110,
|
||||
editor:"date"
|
||||
},
|
||||
{title:'검사자', field:'INSPECTOR_ID', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST});
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST}
|
||||
},
|
||||
{title:'진행공정', field:'PROCESS_CD', headerHozAlign:'center', hozAlign:'center', width:130,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
@@ -259,10 +271,10 @@ function fn_search(){
|
||||
editor:"input",
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
{title:'불량수량', field:'DEFECT_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
editor:"input",
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
// {title:'불량수량', field:'DEFECT_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
// editor:"input",
|
||||
// formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
// },
|
||||
{title:'작업환경상태', field:'WORK_ENV_STATUS', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
@@ -277,6 +289,16 @@ function fn_search(){
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_MEASURING_DEVICE_LIST}
|
||||
},
|
||||
{title:'검사결과', field:'INSPECTION_RESULT', headerHozAlign:'center', hozAlign:'center', width:80,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === 'NG') return '<span class="inspection-ng">NG</span>';
|
||||
if(val === 'OK') return '<span class="inspection-ok">OK</span>';
|
||||
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST});
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST}
|
||||
},
|
||||
{title:'담당팀', field:'DEPT_CD', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
@@ -291,32 +313,14 @@ function fn_search(){
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_USER_LIST}
|
||||
},
|
||||
{title:'검사일', field:'INSPECTION_DATE', headerHozAlign:'center', hozAlign:'center', width:110,
|
||||
editor:"date"
|
||||
},
|
||||
{title:'검사자', field:'INSPECTOR_ID', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST});
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST}
|
||||
},
|
||||
|
||||
{title:'특이사항', field:'REMARK', headerHozAlign:'center', hozAlign:'left', width:150,
|
||||
editor:"input"
|
||||
},
|
||||
{title:'조치현황', field:'ACTION_STATUS', headerHozAlign:'center', hozAlign:'left', width:150,
|
||||
editor:"input"
|
||||
},
|
||||
{title:'검사결과', field:'INSPECTION_RESULT', headerHozAlign:'center', hozAlign:'center', width:80,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === 'NG') return '<span class="inspection-ng">NG</span>';
|
||||
if(val === 'OK') return '<span class="inspection-ok">OK</span>';
|
||||
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST});
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST}
|
||||
},
|
||||
|
||||
{title:'이미지파일', field:'IMAGE_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell) {
|
||||
@@ -327,18 +331,18 @@ function fn_search(){
|
||||
Swal.fire("먼저 저장 후 이미지를 등록할 수 있습니다.");
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:'첨부파일', field:'ATTACH_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell) {
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
if(objId) {
|
||||
fn_openAttachFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire("먼저 저장 후 파일을 등록할 수 있습니다.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// {title:'첨부파일', field:'ATTACH_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
|
||||
// formatter: fnc_subInfoValueFormatter,
|
||||
// cellClick: function(e, cell) {
|
||||
// var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
// if(objId) {
|
||||
// fn_openAttachFilePopUp(objId);
|
||||
// } else {
|
||||
// Swal.fire("먼저 저장 후 파일을 등록할 수 있습니다.");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
];
|
||||
|
||||
// 그리드가 없으면 생성
|
||||
|
||||
@@ -88,7 +88,8 @@ $(document).ready(function(){
|
||||
|
||||
// 컬럼: 검사일, 프로젝트번호, 품번, 품명, 불량수량, 작업환경상태, 측정기, 검사자, 검사결과
|
||||
var columns = [
|
||||
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'검사일', field:'INSPECTION_DATE' },
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:150, widthGrow:2, title:'프로젝트번호', field:'PROJECT_NO'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'제품구분', field:'PRODUCT_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:180, widthGrow:2, title:'품번', field:'PART_NO'},
|
||||
@@ -96,24 +97,28 @@ var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'검사수량 합계', field:'INSPECTION_QTY',
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'불량수량 합계', field:'DEFECT_QTY',
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'작업환경상태', field:'WORK_ENV_STATUS'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'측정기', field:'MEASURING_DEVICE'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'검사일', field:'INSPECTION_DATE',
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell){
|
||||
fn_openFormPopUp(cell.getData().OBJID);
|
||||
}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
|
||||
// {headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'불량수량 합계', field:'DEFECT_QTY',
|
||||
// formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
// },
|
||||
// {headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'작업환경상태', field:'WORK_ENV_STATUS'},
|
||||
// {headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'측정기', field:'MEASURING_DEVICE'},
|
||||
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사결과', field:'INSPECTION_RESULT',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var val = fnc_checkNull(cell.getValue());
|
||||
if(val === 'NG') return '<span class="inspection-ng">NG</span>';
|
||||
if(val === 'OK') return '<span class="inspection-ok">OK</span>';
|
||||
return val;
|
||||
},
|
||||
cellClick: function(e, cell){
|
||||
fn_openFormPopUp(cell.getData().OBJID);
|
||||
}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'첨부파일', field:'PROCESS_INSPECTION_FILE_CNT',
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_openAttachFilePopUp(objId);
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -151,6 +156,19 @@ function fn_registPopUp(){
|
||||
window.open(url, "processInspectionPopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
function fn_openAttachFilePopUp(objId) {
|
||||
_filePopupOpen = true; // 파일 팝업 열림 플래그 설정
|
||||
|
||||
var popup_width = 800;
|
||||
var popup_height = 300;
|
||||
var params = "?targetObjId=" + objId + "&docType=PROCESS_INSPECTION_FILE&docTypeName=공정검사첨부";
|
||||
var url = "/common/FileRegistPopup.do" + params;
|
||||
var popup = window.open(url, "attachFilePopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
|
||||
|
||||
// 팝업 닫힘 감지하여 해당 행의 파일 카운트만 업데이트
|
||||
fn_watchPopupClose(popup, objId, 'ATTACH_FILE_CNT', 'PROCESS_INSPECTION_FILE');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -39,6 +39,7 @@ String loginUserId = CommonUtils.checkNull(person.getUserId());
|
||||
font-family: 'Malgun Gothic', sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.popup_wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -158,6 +159,20 @@ String loginUserId = CommonUtils.checkNull(person.getUserId());
|
||||
background: #2b6cb0;
|
||||
}
|
||||
|
||||
.btn_edit {
|
||||
padding: 6px 20px;
|
||||
background: #e67e22;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.btn_edit:hover {
|
||||
background: #d35400;
|
||||
}
|
||||
|
||||
.btn_close {
|
||||
padding: 6px 20px;
|
||||
background: #718096;
|
||||
@@ -232,7 +247,8 @@ String loginUserId = CommonUtils.checkNull(person.getUserId());
|
||||
<div class="btn_group">
|
||||
<button type="button" class="btn_add" id="btnAddLeft">+ 행 추가</button>
|
||||
<button type="button" class="btn_del" id="btnDelLeft">- 행 삭제</button>
|
||||
<button type="button" class="btn_save" id="btnSaveLeft" style="margin-left:10px;">저장</button>
|
||||
<button type="button" class="btn_save" id="btnSaveLeft" style="margin-left:10px;">행잠금</button>
|
||||
<button type="button" class="btn_edit" id="btnEditLeft" style="margin-left:5px;">잠금해제</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel_body">
|
||||
@@ -247,7 +263,9 @@ String loginUserId = CommonUtils.checkNull(person.getUserId());
|
||||
<div class="btn_group">
|
||||
<button type="button" class="btn_add" id="btnAddRight">+ 행 추가</button>
|
||||
<button type="button" class="btn_del" id="btnDelRight">- 행 삭제</button>
|
||||
<!-- 불량상세 저장버튼 주석처리
|
||||
<button type="button" class="btn_save" id="btnSaveRight" style="margin-left:10px;">저장</button>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel_body" id="rightPanelBody">
|
||||
@@ -294,8 +312,8 @@ var productTypeList = ["Machine", "A/S", "D/S", "B/S", "C/T", "A/C", "W/M", "기
|
||||
var defectTypeList = ["외관불량", "치수불량", "기능불량", "재료불량", "조립불량", "도장불량", "용접불량", "기타"];
|
||||
var defectCauseList = ["작업자 실수", "설비 이상", "자재 불량", "설계 오류", "공정 이상", "환경 요인", "기타"];
|
||||
var responsibleDeptList = ["사용자 정보(부서)", "구매", "생산기술", "제조1팀", "제조2팀", "제조3팀", "연구소", "외주업체", "품질"];
|
||||
var processStatusList = ["Rework", "Scrap"];
|
||||
var dispositionTypeList = ["특채", "수정", "폐기"];
|
||||
var processStatusList = ["수정", "폐기"];
|
||||
var dispositionTypeList = ["수정완료", "폐기", "특채완료"];
|
||||
|
||||
$(document).ready(function(){
|
||||
// 입고관리 데이터 로드
|
||||
@@ -314,8 +332,9 @@ $(document).ready(function(){
|
||||
|
||||
// 버튼 이벤트
|
||||
$("#btnSave").click(fn_save); // 하단 저장: 전체 DB 저장
|
||||
$("#btnSaveLeft").click(fn_saveSelectedLeft); // 좌측 저장: UI 잠금만 (DB 저장 X)
|
||||
$("#btnSaveRight").click(fn_saveSelectedRight); // 우측 저장: UI 잠금만 (DB 저장 X)
|
||||
$("#btnSaveLeft").click(fn_saveSelectedLeft); // 좌측 행저장: 락 처리
|
||||
$("#btnEditLeft").click(fn_editSelectedLeft); // 좌측 행수정: 락 해제
|
||||
// $("#btnSaveRight").click(fn_saveSelectedRight); // 우측 저장: 주석처리
|
||||
$("#btnClose").click(function(){ window.close(); });
|
||||
$("#btnAddLeft").click(fn_addLeftRow);
|
||||
$("#btnDelLeft").click(fn_delLeftRow);
|
||||
@@ -404,11 +423,18 @@ function isEditable(cell){
|
||||
|
||||
// =====================================================
|
||||
// 좌측 그리드 (양품 정보) 초기화
|
||||
// 컬럼순서: 검사일, 검사자, 품명(모델명), 제품구분, 작업지시번호, 부품품번, 부품명, 입고수량, 양품수량, 검사성적서
|
||||
// =====================================================
|
||||
function fn_initLeftGrid(){
|
||||
var columns = [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:30},
|
||||
{title:"품명(모델명)", field:"MODEL_NAME", minWidth:120, headerSort:false,
|
||||
{title:"검사일", field:"INSPECTION_DATE", minWidth:90, headerSort:false,
|
||||
editor: "input",
|
||||
editorParams: { elementAttributes: { type: "date" } },
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"검사자", field:"INSPECTOR", editor:"input", minWidth:70, headerSort:false, editable: isEditable},
|
||||
{title:"품명(모델명)", field:"MODEL_NAME", minWidth:110, headerSort:false,
|
||||
editor: createSelect2Editor(modelNameList),
|
||||
editable: isEditable
|
||||
},
|
||||
@@ -419,9 +445,23 @@ function fn_initLeftGrid(){
|
||||
{title:"작업지시번호", field:"WORK_ORDER_NO", editor:"input", minWidth:100, headerSort:false,
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"부품품번", field:"PART_NO", minWidth:100, headerSort:false,
|
||||
{title:"부품품번", field:"PART_NO", minWidth:90, headerSort:false,
|
||||
editor: createSelect2Editor(partNoList),
|
||||
editable: isEditable,
|
||||
formatter: function(cell){
|
||||
var val = cell.getValue();
|
||||
if(val){
|
||||
return "<a href='javascript:void(0);' style='color:#2196F3; text-decoration:underline;'>" + val + "</a>";
|
||||
}
|
||||
return val || "";
|
||||
},
|
||||
cellClick: function(e, cell){
|
||||
var partNo = cell.getValue();
|
||||
var rowData = cell.getRow().getData();
|
||||
if(partNo && rowData.PART_OBJID){
|
||||
fn_openPartInfoPopUp(rowData.PART_OBJID);
|
||||
}
|
||||
},
|
||||
cellEdited: function(cell){
|
||||
var partNo = cell.getValue();
|
||||
if(partNo){
|
||||
@@ -429,6 +469,7 @@ function fn_initLeftGrid(){
|
||||
if(matched){
|
||||
cell.getRow().update({
|
||||
PART_NAME: matched.PART_NAME || '',
|
||||
PART_OBJID: matched.PART_OBJID || '',
|
||||
RECEIPT_QTY: matched.RECEIPT_QTY || matched.DELIVERY_QTY || ''
|
||||
});
|
||||
}
|
||||
@@ -451,7 +492,7 @@ function fn_initLeftGrid(){
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:"입고수량", field:"RECEIPT_QTY", editor:"number", hozAlign:"right", minWidth:70, headerSort:false,
|
||||
{title:"입고수량", field:"RECEIPT_QTY", editor:"number", hozAlign:"right", minWidth:80, headerSort:false,
|
||||
editorParams:{min:0, step:1},
|
||||
editable: isEditable,
|
||||
formatter: function(cell){
|
||||
@@ -459,13 +500,24 @@ function fn_initLeftGrid(){
|
||||
return (val !== null && val !== undefined && val !== "") ? Number(val).toLocaleString() : "0";
|
||||
}
|
||||
},
|
||||
{title:"양품수량", field:"GOOD_QTY", editor:"number", hozAlign:"right", minWidth:70, headerSort:false,
|
||||
{title:"양품수량", field:"GOOD_QTY", editor:"number", hozAlign:"right", minWidth:80, headerSort:false,
|
||||
editorParams:{min:0, step:1},
|
||||
editable: isEditable,
|
||||
formatter: function(cell){
|
||||
var val = cell.getValue();
|
||||
return (val !== null && val !== undefined && val !== "") ? Number(val).toLocaleString() : "0";
|
||||
}
|
||||
},
|
||||
{title:"검사성적서", field:"REPORT_FILE_CNT", minWidth:85, headerSort:false, hozAlign:"center",
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
if(objId){
|
||||
fn_openReportFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire({icon:'info', title:'알림', text:'행을 추가한 후 파일을 등록할 수 있습니다.'});
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -478,9 +530,13 @@ function fn_initLeftGrid(){
|
||||
selectable: 1, // 단일 선택
|
||||
// 저장된 행 시각적 표시
|
||||
rowFormatter: function(row){
|
||||
if(row.getData().IS_SAVED){
|
||||
var data = row.getData();
|
||||
if(data.IS_SAVED || data.IS_LOCKED === 'Y'){
|
||||
row.getElement().style.backgroundColor = "#e8f5e9"; // 연한 초록색
|
||||
row.getElement().style.color = "#555";
|
||||
} else {
|
||||
row.getElement().style.backgroundColor = ""; // 원래 색상
|
||||
row.getElement().style.color = "";
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -511,11 +567,12 @@ function fn_initLeftGrid(){
|
||||
|
||||
// =====================================================
|
||||
// 우측 그리드 (불량 정보) 초기화
|
||||
// 컬럼순서: 불량수량, 불량유형, 불량원인, 귀책부서, 부적합보고서, 처리현황, 이미지파일, 처리결과, 비고
|
||||
// =====================================================
|
||||
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,
|
||||
{title:"불량수량", field:"DEFECT_QTY", editor:"number", hozAlign:"right", minWidth:80, headerSort:false,
|
||||
editorParams:{min:0, step:1},
|
||||
editable: isEditable,
|
||||
formatter: function(cell){
|
||||
@@ -527,7 +584,7 @@ function fn_initRightGrid(){
|
||||
editor: createSelect2Editor(defectTypeList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"불량원인", field:"DEFECT_CAUSE", minWidth:90, headerSort:false,
|
||||
{title:"불량원인", field:"DEFECT_CAUSE", minWidth:85, headerSort:false,
|
||||
editor: createSelect2Editor(defectCauseList),
|
||||
editable: isEditable
|
||||
},
|
||||
@@ -535,7 +592,7 @@ function fn_initRightGrid(){
|
||||
editor: createSelect2Editor(responsibleDeptList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"부적합보고서", field:"NCR_FILE_CNT", minWidth:75, headerSort:false, hozAlign:"center",
|
||||
{title:"부적합보고서", field:"NCR_FILE_CNT", minWidth:95, headerSort:false, hozAlign:"center",
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
@@ -546,11 +603,11 @@ function fn_initRightGrid(){
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:"처리현황", field:"PROCESS_STATUS", minWidth:75, headerSort:false,
|
||||
{title:"처리현황", field:"PROCESS_STATUS", minWidth:80, headerSort:false,
|
||||
editor: createSelect2Editor(processStatusList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"이미지", field:"IMAGE_FILE_CNT", minWidth:60, headerSort:false, hozAlign:"center",
|
||||
{title:"이미지파일", field:"IMAGE_FILE_CNT", minWidth:85, headerSort:false, hozAlign:"center",
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
@@ -561,27 +618,10 @@ function fn_initRightGrid(){
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:"검사일", field:"INSPECTION_DATE", minWidth:100, headerSort:false,
|
||||
editor: "input",
|
||||
editorParams: { elementAttributes: { type: "date" } },
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"검사자", field:"INSPECTOR", editor:"input", minWidth:70, headerSort:false, editable: isEditable},
|
||||
{title:"처리결과", field:"DISPOSITION_TYPE", minWidth:75, headerSort:false,
|
||||
{title:"처리결과", field:"DISPOSITION_TYPE", minWidth:80, headerSort:false,
|
||||
editor: createSelect2Editor(dispositionTypeList),
|
||||
editable: isEditable
|
||||
},
|
||||
{title:"검사성적서", field:"REPORT_FILE_CNT", minWidth:70, headerSort:false, hozAlign:"center",
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
if(objId){
|
||||
fn_openReportFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire({icon:'info', title:'알림', text:'행을 추가한 후 파일을 등록할 수 있습니다.'});
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:"비고", field:"REMARK", editor:"input", minWidth:100, headerSort:false, editable: isEditable}
|
||||
];
|
||||
|
||||
@@ -594,9 +634,13 @@ function fn_initRightGrid(){
|
||||
selectable: true,
|
||||
// 저장된 행 시각적 표시
|
||||
rowFormatter: function(row){
|
||||
if(row.getData().IS_SAVED){
|
||||
var data = row.getData();
|
||||
if(data.IS_SAVED || data.IS_LOCKED === 'Y'){
|
||||
row.getElement().style.backgroundColor = "#e8f5e9"; // 연한 초록색
|
||||
row.getElement().style.color = "#555";
|
||||
} else {
|
||||
row.getElement().style.backgroundColor = ""; // 원래 색상
|
||||
row.getElement().style.color = "";
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -886,6 +930,17 @@ function fn_openReportFilePopUp(objId) {
|
||||
fn_watchPopupClose(popup, objId, 'REPORT_FILE_CNT', 'SEMI_INSPECTION_REPORT');
|
||||
}
|
||||
|
||||
// 파트정보 팝업 (도면 포함)
|
||||
function fn_openPartInfoPopUp(partObjId) {
|
||||
if(!partObjId) {
|
||||
Swal.fire({icon:'info', title:'알림', text:'파트 정보가 없습니다.'});
|
||||
return;
|
||||
}
|
||||
var popup_width = 1200;
|
||||
var popup_height = 800;
|
||||
var url = "/partMng/partMngDetailPopUp.do?OBJID=" + partObjId;
|
||||
window.open(url, "partMngPopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
// 팝업 닫힘 감지 및 파일 카운트 업데이트
|
||||
function fn_watchPopupClose(popup, objId, fieldName, docType) {
|
||||
@@ -998,6 +1053,68 @@ function fn_loadData(objid, inspectionGroupId){
|
||||
});
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 좌측 행수정: 락이 걸린 행을 수정 가능하도록 해제
|
||||
// =====================================================
|
||||
function fn_editSelectedLeft(){
|
||||
console.log("===== fn_editSelectedLeft 호출됨 =====");
|
||||
|
||||
if(!selectedLeftRowId){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '수정할 양품 정보를 선택해주세요.' });
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedRow = leftGrid.getSelectedRows()[0];
|
||||
if(!selectedRow){
|
||||
Swal.fire({ icon: 'warning', title: '알림', text: '수정할 양품 정보를 선택해주세요.' });
|
||||
return;
|
||||
}
|
||||
|
||||
var rowData = selectedRow.getData();
|
||||
|
||||
// 락이 걸려있지 않으면 이미 수정 가능 상태
|
||||
if(rowData.IS_LOCKED !== 'Y' && !rowData.IS_SAVED){
|
||||
Swal.fire({ icon: 'info', title: '알림', text: '이미 수정 가능한 상태입니다.' });
|
||||
return;
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
icon: 'question',
|
||||
title: '행수정',
|
||||
text: '선택한 행의 잠금을 해제하고 수정 가능하게 하시겠습니까?',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '확인',
|
||||
cancelButtonText: '취소'
|
||||
}).then((result) => {
|
||||
if(result.isConfirmed){
|
||||
var objId = rowData.OBJID;
|
||||
|
||||
// DB에 잠금 해제 요청
|
||||
$.ajax({
|
||||
url: "/quality/unlockSemiProductInspection.do",
|
||||
type: "POST",
|
||||
data: { objIds: JSON.stringify([objId]) },
|
||||
dataType: "json",
|
||||
success: function(result){
|
||||
if(result.result){
|
||||
// UI에서 잠금 해제
|
||||
selectedRow.update({ IS_SAVED: false, IS_LOCKED: 'N' });
|
||||
// 행 스타일 원래대로 (초록색 -> 기본색)
|
||||
selectedRow.getElement().style.backgroundColor = "";
|
||||
selectedRow.getElement().style.color = "";
|
||||
Swal.fire({ icon: 'success', title: '완료', text: '잠금이 해제되어 수정 가능합니다.' });
|
||||
} else {
|
||||
Swal.fire({ icon: 'error', title: '오류', text: result.msg || '잠금 해제에 실패했습니다.' });
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
Swal.fire({ icon: 'error', title: '오류', text: '잠금 해제 중 오류가 발생했습니다.' });
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 좌측 행 저장+잠금: 선택된 양품 행을 DB에 저장하고 수정 불가로 변경
|
||||
// =====================================================
|
||||
|
||||
@@ -121,19 +121,19 @@ async function createExcelFile(data){
|
||||
const workbook = new ExcelJS.Workbook();
|
||||
const worksheet = workbook.addWorksheet(pageTitle);
|
||||
|
||||
// 헤더 설정
|
||||
var headers = ["No", "품명(모델명)", "제품구분", "작업지시번호", "부품품번", "부품명",
|
||||
// 헤더 설정 (컬럼 순서 변경: 검사일, 검사자를 앞으로)
|
||||
var headers = ["No", "검사일", "검사자", "품명(모델명)", "작업지시번호", "부품품번", "부품명",
|
||||
"입고수량 합계", "양품수량 합계", "불량수량 합계", "불량율(%)", "재생수량 합계", "최종양품수량 합계",
|
||||
"검사일", "검사자", "불량유형", "불량원인", "귀책부서", "처리현황", "처리결과", "비고"];
|
||||
"불량유형", "불량원인", "귀책부서", "처리현황", "처리결과", "비고"];
|
||||
|
||||
// 열 너비 설정
|
||||
var colWidths = [6, 25, 12, 18, 20, 25, 15, 15, 15, 12, 15, 18, 12, 12, 15, 15, 12, 12, 12, 20];
|
||||
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:T1');
|
||||
worksheet.mergeCells('A1:S1');
|
||||
var titleCell = worksheet.getCell('A1');
|
||||
titleCell.value = pageTitle;
|
||||
titleCell.font = { size: 16, bold: true };
|
||||
@@ -171,12 +171,13 @@ async function createExcelFile(data){
|
||||
});
|
||||
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.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 || "",
|
||||
@@ -186,8 +187,6 @@ async function createExcelFile(data){
|
||||
item.defect_rate || item.DEFECT_RATE || 0,
|
||||
item.regeneration_qty || item.REGENERATION_QTY || 0,
|
||||
item.final_good_qty || item.FINAL_GOOD_QTY || 0,
|
||||
item.inspection_date || item.INSPECTION_DATE || "",
|
||||
item.writer_name || item.WRITER_NAME || "",
|
||||
item.defect_type || item.DEFECT_TYPE || "",
|
||||
item.defect_cause || item.DEFECT_CAUSE || "",
|
||||
item.responsible_dept || item.RESPONSIBLE_DEPT || "",
|
||||
@@ -204,14 +203,14 @@ async function createExcelFile(data){
|
||||
bottom: { style: 'thin' },
|
||||
right: { style: 'thin' }
|
||||
};
|
||||
// 숫자 컬럼 오른쪽 정렬 (7~12번 컬럼: 수량, 불량율)
|
||||
if(colNumber >= 7 && colNumber <= 12){
|
||||
// 숫자 컬럼 오른쪽 정렬 (8~13번 컬럼: 수량, 불량율)
|
||||
if(colNumber >= 8 && colNumber <= 13){
|
||||
cell.alignment = { horizontal: 'right' };
|
||||
// 숫자에 천단위 구분자 (불량율 제외)
|
||||
if(colNumber !== 10 && typeof cell.value === 'number'){
|
||||
if(colNumber !== 11 && typeof cell.value === 'number'){
|
||||
cell.numFmt = '#,##0';
|
||||
}
|
||||
} else if(colNumber === 1){
|
||||
} else if(colNumber === 1 || colNumber === 2 || colNumber === 3){
|
||||
cell.alignment = { horizontal: 'center' };
|
||||
}
|
||||
});
|
||||
@@ -231,8 +230,15 @@ async function createExcelFile(data){
|
||||
saveAs(new Blob([buffer]), fileName);
|
||||
}
|
||||
|
||||
// 컬럼: 품명(모델명), 작업지시번호, 부품품번, 부품명, 입고수량 합계, 양품수량 합계, 불량수량 합계, 불량율, 재생수량 합계, 최종 양품수량 합계, 검사일, 검사자
|
||||
// 컬럼: 검사일, 검사자, 품명(모델명), 작업지시번호, 부품품번, 부품명, 입고수량 합계, 양품수량 합계, 불량수량 합계, 불량율, 재생수량 합계, 최종양품수량 합계
|
||||
var columns = [
|
||||
{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'},
|
||||
{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'},
|
||||
@@ -255,16 +261,9 @@ var columns = [
|
||||
{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',
|
||||
{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'}
|
||||
}
|
||||
];
|
||||
|
||||
// 조회
|
||||
|
||||
@@ -85,7 +85,7 @@ body, html {
|
||||
<tr>
|
||||
<td>
|
||||
<label>프로젝트번호:</label>
|
||||
<span id="infoProjectNo">${resultMap.PROJECT_NO}</span>
|
||||
<span id="infoProjectNo">${resultMap.PROJECT_NUMBER}</span>
|
||||
</td>
|
||||
<td>
|
||||
<label>고객사:</label>
|
||||
@@ -115,7 +115,7 @@ body, html {
|
||||
</td>
|
||||
<td>
|
||||
<label>입고요청일:</label>
|
||||
<span id="infoDeliveryDate">${resultMap.DELIVERY_REQUEST_DATE}</span>
|
||||
<span id="infoDeliveryDate">${resultMap.DUE_DATE}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -134,6 +134,7 @@ var projectMgmtObjid = "${resolvedProjectId}";
|
||||
var bomReportObjid = "${resolvedBomReportObjid}";
|
||||
var mbomHeaderObjid = "${resolvedMbomHeaderObjid}"; // MBOM_HEADER.OBJID (M-BOM 관리 화면에서 사용하는 ID)
|
||||
var vendorList = []; // 공급업체 목록
|
||||
var processingVendorList = []; // 가공업체 목록 (Select2용 배열)
|
||||
|
||||
// 디버그: resultMap 내용 확인 (주석처리)
|
||||
// console.log("=== JSP resultMap 디버그 ===");
|
||||
@@ -156,8 +157,17 @@ function logError(){
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
// 공급업체 목록 먼저 로드
|
||||
// 공급업체 목록 로드 (가공업체도 동일 테이블 사용)
|
||||
fn_loadVendorList(function(){
|
||||
// vendorList에서 processingVendorList 변환 (Select2용 배열 형태)
|
||||
processingVendorList = [];
|
||||
for(var key in vendorList) {
|
||||
if(key !== '') { // 빈 값 제외
|
||||
processingVendorList.push({id: key, text: vendorList[key]});
|
||||
}
|
||||
}
|
||||
console.log("가공업체 목록 변환 완료:", processingVendorList.length + "개");
|
||||
|
||||
fn_initGrid();
|
||||
logDebug("purchaseListFormPopUp :: grid initialized");
|
||||
fn_loadInitialData();
|
||||
@@ -196,6 +206,7 @@ function fn_loadVendorList(callback) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function fn_loadInitialData(){
|
||||
logDebug("purchaseListFormPopUp :: fn_loadInitialData start",
|
||||
"projectMgmtObjid=", projectMgmtObjid,
|
||||
@@ -224,6 +235,62 @@ function fn_loadInitialData(){
|
||||
}
|
||||
}
|
||||
|
||||
// Select2 커스텀 에디터 생성 함수
|
||||
function createSelect2Editor(options) {
|
||||
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");
|
||||
if(typeof opt === 'object') {
|
||||
option.value = opt.id || opt.value || '';
|
||||
option.text = opt.text || opt.label || '';
|
||||
} else {
|
||||
option.value = opt;
|
||||
option.text = opt;
|
||||
}
|
||||
if(option.value == cellValue) {
|
||||
option.selected = true;
|
||||
}
|
||||
select.appendChild(option);
|
||||
});
|
||||
|
||||
container.appendChild(select);
|
||||
|
||||
onRendered(function() {
|
||||
$(select).select2({
|
||||
width: '100%',
|
||||
dropdownAutoWidth: true,
|
||||
allowClear: true,
|
||||
placeholder: '선택'
|
||||
});
|
||||
$(select).select2('open');
|
||||
});
|
||||
|
||||
$(select).on('select2:select select2:clear', function(e) {
|
||||
success($(select).val());
|
||||
});
|
||||
|
||||
$(select).on('select2:close', function() {
|
||||
setTimeout(function() {
|
||||
success($(select).val());
|
||||
}, 100);
|
||||
});
|
||||
|
||||
return container;
|
||||
};
|
||||
}
|
||||
|
||||
// Tabulator 그리드 초기화
|
||||
function fn_initGrid() {
|
||||
var columns = [
|
||||
@@ -462,13 +529,34 @@ function fn_initGrid() {
|
||||
return value ? Number(value).toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
// 24. 가공업체
|
||||
// 24. 가공업체 (수정가능 - Select2 에디터)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 150,
|
||||
title: '가공업체',
|
||||
field: 'PROCESSING_VENDOR'
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">가공업체</span>',
|
||||
field: 'PROCESSING_VENDOR',
|
||||
editor: function(cell, onRendered, success, cancel, editorParams) {
|
||||
// Select2 에디터
|
||||
return createSelect2Editor(processingVendorList)(cell, onRendered, success, cancel, editorParams);
|
||||
},
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
|
||||
// 저장된 값이 없으면 기본값 '5001'(RPS) 설정
|
||||
if(value === undefined || value === null || value === '') {
|
||||
value = '5001';
|
||||
cell.getRow().update({PROCESSING_VENDOR: value}, false);
|
||||
}
|
||||
|
||||
// OBJID로 업체명 조회하여 표시
|
||||
for(var i = 0; i < processingVendorList.length; i++) {
|
||||
if(processingVendorList[i].id == value) {
|
||||
return processingVendorList[i].text;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
/* // 25. 가공납기 - 주석처리
|
||||
{
|
||||
@@ -550,28 +638,27 @@ function fn_initGrid() {
|
||||
return value ? Number(value).toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
// 30. 공급업체 (수정가능 - 기준정보에서 선택)
|
||||
// 30. 공급업체 (수정가능 - Select2 에디터)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 150,
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">공급업체</span>',
|
||||
field: 'VENDOR_PM',
|
||||
editor: 'list',
|
||||
editorParams: function(cell) {
|
||||
return {
|
||||
values: vendorList,
|
||||
autocomplete: true,
|
||||
listOnEmpty: true,
|
||||
freetext: true,
|
||||
allowEmpty: true
|
||||
};
|
||||
editor: function(cell, onRendered, success, cancel, editorParams) {
|
||||
// Select2 에디터 (가공업체와 동일한 목록 사용)
|
||||
return createSelect2Editor(processingVendorList)(cell, onRendered, success, cancel, editorParams);
|
||||
},
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value) return '';
|
||||
// vendorList에서 해당 값의 이름 찾기
|
||||
return vendorList[value] || value;
|
||||
// processingVendorList에서 해당 값의 이름 찾기
|
||||
for(var i = 0; i < processingVendorList.length; i++) {
|
||||
if(processingVendorList[i].id == value) {
|
||||
return processingVendorList[i].text;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
// 31. 단가 (수정가능)
|
||||
|
||||
@@ -45,6 +45,9 @@ String menuName = CommonUtils.getMenuName(menuObjId, "구매관리_구매요청
|
||||
$(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#SEARCH_PART_NO", "#SEARCH_PART_NAME", "#SEARCH_PART_OBJID");
|
||||
|
||||
$("input[type=text]").keyup(function(e){
|
||||
if(e.keyCode == 13){
|
||||
$("#btnSearch").trigger("click");
|
||||
@@ -710,20 +713,25 @@ function fn_executeCreateProposal(salesRequestObjid, targetParts) {
|
||||
<select name="SEARCH_PRODUCT_CODE" id="SEARCH_PRODUCT_CODE" style="" class="select2" autocomplete="off"></select>
|
||||
</td> -->
|
||||
|
||||
<%-- 품번 활성화 --%>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NO" id="SEARCH_PART_NO" value="${param.SEARCH_PART_NO}" style="width:200px;"/>
|
||||
</td>
|
||||
<%-- 품명 활성화 --%>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" value="${param.SEARCH_PART_NAME}" style="width:200px;"/>
|
||||
</td>
|
||||
<%-- 품번 활성화 --%>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NO" id="SEARCH_PART_NO" class="select2-part" style="width:200px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="SEARCH_PART_OBJID" id="SEARCH_PART_OBJID" value="">
|
||||
</td>
|
||||
<%-- 품명 활성화 --%>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:200px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
<%-- 상태 주석처리
|
||||
<td class="align_r">
|
||||
<label for="" class="">상태</label>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
/* 기본 바디 스타일 - 깔끔한 배경 */
|
||||
body {
|
||||
background: var(--background);
|
||||
min-height: 100vh;
|
||||
/* min-height: 100vh; */
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.6;
|
||||
|
||||
@@ -461,7 +461,7 @@ public class Constants {
|
||||
}
|
||||
|
||||
//Mail 관련
|
||||
public class Mail{
|
||||
public static class Mail{
|
||||
public static final String TEMPLATE_FILE_PATH = applicationRootDir+"\\WebContent\\mailTemplate\\"; //메일내용 템플릿 위치
|
||||
public static final boolean sendMailSwitch = true; //메일발송 사용여부
|
||||
public static final boolean dbLogWrite = true; //메일발송시 DB로그 사용여부
|
||||
@@ -469,19 +469,67 @@ public class Constants {
|
||||
public static final String FILE_PATH = FILE_STORAGE+"\\MAIL";
|
||||
public static final String CHARSET = SYSTEM_CHARSET;
|
||||
|
||||
/* SMTP 메일정보 - RPS */
|
||||
public static final String SMTP_USER = "erp@rps-korea.com";//SMTP USER ID (전체 이메일 주소)
|
||||
public static final String SMTP_USER_PW = "Plmrps123!!"; //SMTP USER PASSWORD
|
||||
public static final String SMTP_HOST = "gwa.rps-korea.com";
|
||||
// public static final String SMTP_USER = "sales@rps-korea.com";//SMTP USER ID (전체 이메일 주소)
|
||||
// public static final String SMTP_USER_PW = "rpstech6125!!"; //SMTP USER PASSWORD
|
||||
// public static final String SMTP_HOST = "wblock.rps-korea.com"; //SMTP HOST (gw.rps-korea.com IP)
|
||||
//public static final String SMTP_HOST = "220.123.92.226"; //SMTP HOST (gw.rps-korea.com IP)
|
||||
public static final int SMTP_PORT = 25; //SMTP PORT (SSL 사용안함)
|
||||
// public static final String SMTP_USER = "admin@wsse.co.kr";//SMTP USER ID [mail.gdnsi.com]
|
||||
// public static final String SMTP_USER_PW = "admin123!@#"; //SMTP USER PASSWORD
|
||||
// public static final String SMTP_HOST = "smtps.hiworks.com"; //SMTP HOST
|
||||
// public static final int SMTP_PORT = 465; //SMTP PORT
|
||||
// SMTP 계정 타입
|
||||
public static final String ACCOUNT_TYPE_ERP = "ERP"; // 일반 (기본값)
|
||||
public static final String ACCOUNT_TYPE_SALES = "SALES"; // 영업팀 (견적서 등)
|
||||
public static final String ACCOUNT_TYPE_PURCHASE = "PURCHASE"; // 구매팀 (발주서 등)
|
||||
|
||||
/* SMTP 메일정보 - ERP (일반/기본) */
|
||||
public static final String SMTP_USER = "erp@rps-korea.com";
|
||||
public static final String SMTP_USER_PW = "Plmrps123!!";
|
||||
public static final String SMTP_HOST = "gwa.rps-korea.com";
|
||||
public static final int SMTP_PORT = 25;
|
||||
|
||||
/* SMTP 메일정보 - 영업팀 (견적서 등) */
|
||||
public static final String SMTP_USER_SALES = "sales@rps-korea.com";
|
||||
public static final String SMTP_USER_PW_SALES = "rpstech6125!!";
|
||||
public static final String SMTP_HOST_SALES = "wblock.rps-korea.com";
|
||||
public static final int SMTP_PORT_SALES = 25;
|
||||
|
||||
/* SMTP 메일정보 - 구매팀 (발주서 등) */
|
||||
public static final String SMTP_USER_PURCHASE = "erp@rps-korea.com";
|
||||
public static final String SMTP_USER_PW_PURCHASE = "Plmrps123!!";
|
||||
public static final String SMTP_HOST_PURCHASE = "gwa.rps-korea.com";
|
||||
public static final int SMTP_PORT_PURCHASE = 25;
|
||||
|
||||
/**
|
||||
* 계정 타입에 따른 SMTP 정보 반환
|
||||
*/
|
||||
public static String getSmtpUser(String accountType) {
|
||||
if (ACCOUNT_TYPE_SALES.equals(accountType)) {
|
||||
return SMTP_USER_SALES;
|
||||
} else if (ACCOUNT_TYPE_PURCHASE.equals(accountType)) {
|
||||
return SMTP_USER_PURCHASE;
|
||||
}
|
||||
return SMTP_USER; // 기본값: ERP
|
||||
}
|
||||
|
||||
public static String getSmtpUserPw(String accountType) {
|
||||
if (ACCOUNT_TYPE_SALES.equals(accountType)) {
|
||||
return SMTP_USER_PW_SALES;
|
||||
} else if (ACCOUNT_TYPE_PURCHASE.equals(accountType)) {
|
||||
return SMTP_USER_PW_PURCHASE;
|
||||
}
|
||||
return SMTP_USER_PW; // 기본값: ERP
|
||||
}
|
||||
|
||||
public static String getSmtpHost(String accountType) {
|
||||
if (ACCOUNT_TYPE_SALES.equals(accountType)) {
|
||||
return SMTP_HOST_SALES;
|
||||
} else if (ACCOUNT_TYPE_PURCHASE.equals(accountType)) {
|
||||
return SMTP_HOST_PURCHASE;
|
||||
}
|
||||
return SMTP_HOST; // 기본값: ERP
|
||||
}
|
||||
|
||||
public static int getSmtpPort(String accountType) {
|
||||
if (ACCOUNT_TYPE_SALES.equals(accountType)) {
|
||||
return SMTP_PORT_SALES;
|
||||
} else if (ACCOUNT_TYPE_PURCHASE.equals(accountType)) {
|
||||
return SMTP_PORT_PURCHASE;
|
||||
}
|
||||
return SMTP_PORT; // 기본값: ERP
|
||||
}
|
||||
}
|
||||
|
||||
//스마트공장 사후관리시스템 로그 수집 API key
|
||||
|
||||
@@ -545,7 +545,7 @@ public class MailUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일포함 메일전송
|
||||
* 파일포함 메일전송 (기본 ERP 계정 사용)
|
||||
* @author 악당밧밧이
|
||||
* @param fromUserId 보내는사람ID
|
||||
* @param fromEmail 보내는사람Email주소
|
||||
@@ -566,23 +566,58 @@ public class MailUtil {
|
||||
, ArrayList<HashMap> attachFileList
|
||||
, String mailType
|
||||
) {
|
||||
// 기본 ERP 계정 사용
|
||||
return sendMailWithAttachFile(fromUserId, fromEmail, toUserIdList, toEmailList, ccEmailList, bccEmailList,
|
||||
important, subject, contents, attachFileList, mailType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일포함 메일전송 (계정 타입 지정 가능)
|
||||
* @param fromUserId 보내는사람ID
|
||||
* @param fromEmail 보내는사람Email주소
|
||||
* @param toUserIdList 받는사람ID목록
|
||||
* @param toEmailList 받는사람Email목록
|
||||
* @param ccEmailList 참조Email목록
|
||||
* @param bccEmailList 숨은참조Email목록
|
||||
* @param important 메일중요구분(normal | ??? )
|
||||
* @param subject 메일제목
|
||||
* @param contents 메일내용
|
||||
* @param attachFileList 메일첨부파일목록
|
||||
* @param mailType 업무구분
|
||||
* @param accountType SMTP 계정 타입 (Constants.Mail.ACCOUNT_TYPE_ERP/SALES/PURCHASE)
|
||||
* @return
|
||||
*/
|
||||
public static boolean sendMailWithAttachFile(String fromUserId, String fromEmail
|
||||
, ArrayList<String> toUserIdList, ArrayList<String> toEmailList, ArrayList<String> ccEmailList, ArrayList<String> bccEmailList
|
||||
, String important, String subject, String contents
|
||||
, ArrayList<HashMap> attachFileList
|
||||
, String mailType
|
||||
, String accountType
|
||||
) {
|
||||
|
||||
if(Constants.Mail.sendMailSwitch == false){
|
||||
System.out.println("MailUtil.sendMailaddAttachFile ::: Constants.Mail.sendMailSwitch is FALSE");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 계정 타입에 따른 SMTP 정보 결정
|
||||
final String smtpUser = Constants.Mail.getSmtpUser(accountType);
|
||||
final String smtpUserPw = Constants.Mail.getSmtpUserPw(accountType);
|
||||
final String smtpHost = Constants.Mail.getSmtpHost(accountType);
|
||||
final int smtpPort = Constants.Mail.getSmtpPort(accountType);
|
||||
|
||||
try {
|
||||
/*변수 초기화*/
|
||||
fromUserId = CommonUtils.checkNull(fromUserId, "admin");
|
||||
fromEmail = Constants.Mail.SMTP_USER; //fromEmail : SMTP설정계정 외 다른주소 지정불가
|
||||
//fromEmail = CommonUtils.checkNull(fromEmail, Constants.Mail.SMTP_USER); //fromEmail : SMTP설정계정 외 다른주소 지정불가
|
||||
fromEmail = smtpUser; //fromEmail : SMTP설정계정 외 다른주소 지정불가
|
||||
important = CommonUtils.checkNull(important); //중요도
|
||||
subject = CommonUtils.checkNull(subject , "empty subject" ); //제목
|
||||
contents = CommonUtils.checkNull(contents, "empty contents"); //내용
|
||||
mailType = CommonUtils.checkNull(mailType, "empty mailType");
|
||||
|
||||
System.out.println("MailUtil.sendMailaddAttachFile()..");
|
||||
System.out.println("MailUtil.sendMailaddAttachFile(accountType ):"+accountType);
|
||||
System.out.println("MailUtil.sendMailaddAttachFile(smtpUser ):"+smtpUser);
|
||||
System.out.println("MailUtil.sendMailaddAttachFile(fromUserId ):"+fromUserId);
|
||||
System.out.println("MailUtil.sendMailaddAttachFile(fromEmail ):"+fromEmail);
|
||||
System.out.println("MailUtil.sendMailaddAttachFile(toUserIdList):"+toUserIdList);
|
||||
@@ -597,8 +632,8 @@ public class MailUtil {
|
||||
|
||||
//◆◆◆ 1. mail session ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆
|
||||
Properties prop = new Properties();
|
||||
prop.put("mail.smtp.host", Constants.Mail.SMTP_HOST);
|
||||
prop.put("mail.smtp.port", Constants.Mail.SMTP_PORT);
|
||||
prop.put("mail.smtp.host", smtpHost);
|
||||
prop.put("mail.smtp.port", smtpPort);
|
||||
prop.put("mail.smtp.auth" , "true");
|
||||
prop.put("mail.debug" , "true");
|
||||
prop.put("mail.transport.protocol" , "smtp");
|
||||
@@ -608,11 +643,11 @@ public class MailUtil {
|
||||
// hiworks SSL 설정 (포트 465)
|
||||
//prop.put("mail.smtp.ssl.enable" , "true");
|
||||
//prop.put("mail.smtp.socketFactory.class" , "javax.net.ssl.SSLSocketFactory");
|
||||
//prop.put("mail.smtp.socketFactory.port" , Constants.Mail.SMTP_PORT);
|
||||
//prop.put("mail.smtp.socketFactory.port" , smtpPort);
|
||||
|
||||
Session mailSession = Session.getInstance(prop, new javax.mail.Authenticator() {
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(Constants.Mail.SMTP_USER, Constants.Mail.SMTP_USER_PW);
|
||||
return new PasswordAuthentication(smtpUser, smtpUserPw);
|
||||
}
|
||||
});
|
||||
mailSession.setDebug(true);
|
||||
@@ -769,7 +804,7 @@ public class MailUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* UTF-8 인코딩으로 메일 발송 (견적서 등 한글 내용이 많은 경우)
|
||||
* UTF-8 인코딩으로 메일 발송 (견적서 등 한글 내용이 많은 경우) - 기본 ERP 계정 사용
|
||||
* 기존 sendMailWithAttachFile과 동일하지만 UTF-8 인코딩 사용
|
||||
*/
|
||||
public static boolean sendMailWithAttachFileUTF8(String fromUserId, String fromEmail
|
||||
@@ -778,13 +813,13 @@ public class MailUtil {
|
||||
, ArrayList<HashMap> attachFileList
|
||||
, String mailType
|
||||
) {
|
||||
// 기본적으로 실제 제목을 mail_log에도 사용
|
||||
// 기본적으로 실제 제목을 mail_log에도 사용, 기본 ERP 계정 사용
|
||||
return sendMailWithAttachFileUTF8(fromUserId, fromEmail, toUserIdList, toEmailList, ccEmailList, bccEmailList,
|
||||
important, subject, contents, attachFileList, mailType, subject);
|
||||
important, subject, contents, attachFileList, mailType, subject, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 메일 발송 (UTF-8, 파일 첨부 가능) - mail_log용 제목 별도 지정 가능
|
||||
* 메일 발송 (UTF-8, 파일 첨부 가능) - mail_log용 제목 별도 지정 가능, 기본 ERP 계정 사용
|
||||
*/
|
||||
public static boolean sendMailWithAttachFileUTF8(String fromUserId, String fromEmail
|
||||
, ArrayList<String> toUserIdList, ArrayList<String> toEmailList, ArrayList<String> ccEmailList, ArrayList<String> bccEmailList
|
||||
@@ -793,16 +828,39 @@ public class MailUtil {
|
||||
, String mailType
|
||||
, String subjectForLog // mail_log에 저장될 제목 (OBJID 포함)
|
||||
) {
|
||||
// 기본 ERP 계정 사용
|
||||
return sendMailWithAttachFileUTF8(fromUserId, fromEmail, toUserIdList, toEmailList, ccEmailList, bccEmailList,
|
||||
important, subject, contents, attachFileList, mailType, subjectForLog, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 메일 발송 (UTF-8, 파일 첨부 가능) - 계정 타입 지정 가능
|
||||
* @param accountType SMTP 계정 타입 (Constants.Mail.ACCOUNT_TYPE_ERP/SALES/PURCHASE)
|
||||
*/
|
||||
public static boolean sendMailWithAttachFileUTF8(String fromUserId, String fromEmail
|
||||
, ArrayList<String> toUserIdList, ArrayList<String> toEmailList, ArrayList<String> ccEmailList, ArrayList<String> bccEmailList
|
||||
, String important, String subject, String contents
|
||||
, ArrayList<HashMap> attachFileList
|
||||
, String mailType
|
||||
, String subjectForLog // mail_log에 저장될 제목 (OBJID 포함)
|
||||
, String accountType // SMTP 계정 타입
|
||||
) {
|
||||
|
||||
if(Constants.Mail.sendMailSwitch == false){
|
||||
System.out.println("MailUtil.sendMailWithAttachFileUTF8 ::: Constants.Mail.sendMailSwitch is FALSE");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 계정 타입에 따른 SMTP 정보 결정
|
||||
final String smtpUser = Constants.Mail.getSmtpUser(accountType);
|
||||
final String smtpUserPw = Constants.Mail.getSmtpUserPw(accountType);
|
||||
final String smtpHost = Constants.Mail.getSmtpHost(accountType);
|
||||
final int smtpPort = Constants.Mail.getSmtpPort(accountType);
|
||||
|
||||
try {
|
||||
/*변수 초기화*/
|
||||
fromUserId = CommonUtils.checkNull(fromUserId, "admin");
|
||||
fromEmail = Constants.Mail.SMTP_USER;
|
||||
fromEmail = smtpUser;
|
||||
important = CommonUtils.checkNull(important);
|
||||
subject = CommonUtils.checkNull(subject , "empty subject" );
|
||||
contents = CommonUtils.checkNull(contents, "empty contents");
|
||||
@@ -814,6 +872,8 @@ public class MailUtil {
|
||||
}
|
||||
|
||||
System.out.println("MailUtil.sendMailWithAttachFileUTF8()..");
|
||||
System.out.println("MailUtil.sendMailWithAttachFileUTF8(accountType ):"+accountType);
|
||||
System.out.println("MailUtil.sendMailWithAttachFileUTF8(smtpUser ):"+smtpUser);
|
||||
System.out.println("MailUtil.sendMailWithAttachFileUTF8(fromUserId ):"+fromUserId);
|
||||
System.out.println("MailUtil.sendMailWithAttachFileUTF8(fromEmail ):"+fromEmail);
|
||||
System.out.println("MailUtil.sendMailWithAttachFileUTF8(toEmailList ):"+toEmailList);
|
||||
@@ -824,8 +884,8 @@ public class MailUtil {
|
||||
|
||||
//◆◆◆ 1. mail session ◆◆◆
|
||||
Properties prop = new Properties();
|
||||
prop.put("mail.smtp.host", Constants.Mail.SMTP_HOST);
|
||||
prop.put("mail.smtp.port", Constants.Mail.SMTP_PORT);
|
||||
prop.put("mail.smtp.host", smtpHost);
|
||||
prop.put("mail.smtp.port", smtpPort);
|
||||
prop.put("mail.smtp.auth" , "true");
|
||||
prop.put("mail.debug" , "true");
|
||||
prop.put("mail.transport.protocol" , "smtp");
|
||||
@@ -835,11 +895,11 @@ public class MailUtil {
|
||||
// hiworks SSL 설정 (포트 465)
|
||||
//prop.put("mail.smtp.ssl.enable" , "true");
|
||||
//prop.put("mail.smtp.socketFactory.class" , "javax.net.ssl.SSLSocketFactory");
|
||||
//prop.put("mail.smtp.socketFactory.port" , Constants.Mail.SMTP_PORT);
|
||||
//prop.put("mail.smtp.socketFactory.port" , smtpPort);
|
||||
|
||||
Session mailSession = Session.getInstance(prop, new javax.mail.Authenticator() {
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(Constants.Mail.SMTP_USER, Constants.Mail.SMTP_USER_PW);
|
||||
return new PasswordAuthentication(smtpUser, smtpUserPw);
|
||||
}
|
||||
});
|
||||
mailSession.setDebug(true);
|
||||
|
||||
@@ -889,6 +889,15 @@ public class ProductionPlanningController extends BaseService {
|
||||
public String mBomMgmt(HttpServletRequest request, @RequestParam Map paramMap){
|
||||
Map code_map = new HashMap();
|
||||
try{
|
||||
// 주문유형 (0000167)
|
||||
code_map.put("category_cd", commonService.bizMakeOptionList("0000167", (String)paramMap.get("search_category_cd"), "common.getCodeselect"));
|
||||
// 제품구분 (0000001)
|
||||
code_map.put("product_cd", commonService.bizMakeOptionList("0000001", (String)paramMap.get("search_product_cd"), "common.getCodeselect"));
|
||||
// 국내/해외 (0000172)
|
||||
code_map.put("area_cd", commonService.bizMakeOptionList("0000172", (String)paramMap.get("search_area_cd"), "common.getCodeselect"));
|
||||
// 고객사 (SUPPLY_MNG + CLIENT_MNG)
|
||||
code_map.put("customer_cd", commonService.bizMakeOptionList("", (String)paramMap.get("search_customer_objid"), "common.getAllSupplySelect"));
|
||||
|
||||
request.setAttribute("code_map", code_map);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
@@ -1655,8 +1664,8 @@ public class ProductionPlanningController extends BaseService {
|
||||
// 생산유형
|
||||
code_map.put("production_type_cd", commonService.bizMakeOptionList("0001832", CommonUtils.nullToEmpty((String)paramMap.get("production_type")), "common.getCodeselect"));
|
||||
|
||||
// 고객사
|
||||
code_map.put("customer_cd", commonService.bizMakeOptionList("", CommonUtils.nullToEmpty((String)paramMap.get("customer_objid")), "common.getClientMngSupplySelect"));
|
||||
// 고객사 (SUPPLY_MNG + CLIENT_MNG 통합)
|
||||
code_map.put("customer_cd", commonService.bizMakeOptionList("", CommonUtils.nullToEmpty((String)paramMap.get("customer_objid")), "common.getsupplyselect"));
|
||||
|
||||
request.setAttribute("code_map", code_map);
|
||||
}catch(Exception e){
|
||||
@@ -1674,6 +1683,17 @@ public class ProductionPlanningController extends BaseService {
|
||||
@ResponseBody
|
||||
@RequestMapping("/productionplanning/prodPlanResultMgmtGridList.do")
|
||||
public Map prodPlanResultMgmtGridList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
// 프로젝트번호 multiple select 처리 (Java 7 호환)
|
||||
String[] projectNos = request.getParameterValues("search_project_no");
|
||||
if(projectNos != null && projectNos.length > 0) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(int i = 0; i < projectNos.length; i++) {
|
||||
if(i > 0) sb.append(",");
|
||||
sb.append(projectNos[i]);
|
||||
}
|
||||
paramMap.put("search_project_nos", sb.toString());
|
||||
}
|
||||
|
||||
commonService.selectListPagingNew("productionplanning.prodPlanResultMgmtGridList", request, paramMap);
|
||||
return paramMap;
|
||||
}
|
||||
@@ -1777,4 +1797,194 @@ public class ProductionPlanningController extends BaseService {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 등록/수정 팝업
|
||||
*/
|
||||
@RequestMapping("/productionplanning/prodResultFormPopup.do")
|
||||
public String prodResultFormPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
return "/productionplanning/prodResultFormPopup";
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 목록 조회
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/productionplanning/getProdResultList.do")
|
||||
public Map getProdResultList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try {
|
||||
List list = productionPlanningService.getProdResultList(paramMap);
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("list", list);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "조회 실패");
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 저장 (JSON)
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/productionplanning/saveProdResultList.do", produces="application/json;charset=UTF-8")
|
||||
public Map saveProdResultList(HttpServletRequest request, @RequestBody Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try {
|
||||
HttpSession session = request.getSession();
|
||||
PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN);
|
||||
paramMap.put("userId", person.getUserId());
|
||||
paramMap.put("userName", person.getUserName());
|
||||
|
||||
boolean success = productionPlanningService.saveProdResultList(paramMap);
|
||||
if(success) {
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("msg", "저장되었습니다.");
|
||||
} else {
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "저장에 실패했습니다.");
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 반제품소요량 조회 화면
|
||||
*/
|
||||
@RequestMapping("/productionplanning/semiProductRequirementList.do")
|
||||
public String semiProductRequirementList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map code_map = new HashMap();
|
||||
try {
|
||||
// M-BOM 목록 (셀렉트박스용)
|
||||
code_map.put("mbom_list", commonService.bizMakeOptionList("", "", "productionplanning.getMbomListForSelect2"));
|
||||
|
||||
request.setAttribute("code_map", code_map);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "/productionplanning/semiProductRequirementList";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 기준 반제품 소요량 조회
|
||||
* @param request
|
||||
* @param paramMap - mbomItems: [{mbomObjid, qty}, ...]
|
||||
* @return 품번별 합산된 소요량 목록
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/productionplanning/getSemiProductRequirementList.do", produces="application/json;charset=UTF-8")
|
||||
public Map getSemiProductRequirementList(HttpServletRequest request, @RequestBody Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try {
|
||||
List list = productionPlanningService.getSemiProductRequirementList(paramMap);
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("list", list);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "조회 실패: " + e.getMessage());
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 원자재소요량 조회 화면
|
||||
*/
|
||||
@RequestMapping("/productionplanning/rawMaterialRequirementList.do")
|
||||
public String rawMaterialRequirementList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map code_map = new HashMap();
|
||||
try {
|
||||
// M-BOM 목록 (셀렉트박스용)
|
||||
code_map.put("mbom_list", commonService.bizMakeOptionList("", "", "productionplanning.getMbomListForSelect2"));
|
||||
|
||||
request.setAttribute("code_map", code_map);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "/productionplanning/rawMaterialRequirementList";
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 기준 원자재(구매품) 소요량 조회
|
||||
* @param request
|
||||
* @param paramMap - mbomItems: [{mbomObjid, qty}, ...]
|
||||
* @return 품번별 합산된 소요량 목록
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/productionplanning/getRawMaterialRequirementList.do", produces="application/json;charset=UTF-8")
|
||||
public Map getRawMaterialRequirementList(HttpServletRequest request, @RequestBody Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try {
|
||||
List list = productionPlanningService.getRawMaterialRequirementList(paramMap);
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("list", list);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "조회 실패: " + e.getMessage());
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 날짜별 조회
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/productionplanning/getProdResultListByDate.do")
|
||||
public Map getProdResultListByDate(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try {
|
||||
List list = productionPlanningService.getProdResultListByDate(paramMap);
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("list", list);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "조회 실패");
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 날짜별 저장
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/productionplanning/saveProdResultByDate.do", produces="application/json;charset=UTF-8")
|
||||
public Map saveProdResultByDate(HttpServletRequest request, @RequestBody Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try {
|
||||
HttpSession session = request.getSession();
|
||||
PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN);
|
||||
|
||||
// 세션 정보가 없는 경우 기본값 설정
|
||||
String userId = "";
|
||||
String userName = "";
|
||||
if(person != null) {
|
||||
userId = person.getUserId();
|
||||
userName = person.getUserName();
|
||||
}
|
||||
paramMap.put("userId", userId);
|
||||
paramMap.put("userName", userName);
|
||||
|
||||
boolean success = productionPlanningService.saveProdResultByDate(paramMap);
|
||||
if(success) {
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("msg", "저장되었습니다.");
|
||||
} else {
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "저장에 실패했습니다.");
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.pms.controller;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -11,6 +12,7 @@ import javax.servlet.http.HttpSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@@ -1116,14 +1118,18 @@ public class PurchaseOrderController {
|
||||
code_map.put("part_type",commonService.bizMakeOptionList(Constants.PART_TYPE_CODE, (String)paramMap.get("part_type"),"common.getCodeselect"));
|
||||
//발주부품
|
||||
code_map.put("type",commonService.bizMakeOptionList("0001068", (String)paramMap.get("type"),"common.getCodeselect"));
|
||||
//공급업체
|
||||
code_map.put("partner_objid",commonService.bizMakeOptionList("", (String)paramMap.get("partner_objid"),"common.getmatersupplyselect"));
|
||||
//공급업체 (공급업체 + 일반거래처 통합)
|
||||
code_map.put("partner_objid",commonService.bizMakeOptionList("", (String)paramMap.get("partner_objid"),"common.getAllSupplySelect"));
|
||||
//조치담당자
|
||||
code_map.put("sales_mng_user_id", commonService.bizMakeOptionList("", (String)paramMap.get("sales_mng_user_id"),"common.getUserselect"));
|
||||
//상태코드
|
||||
code_map.put("appr_status",commonService.bizMakeOptionList("0000099", (String)paramMap.get("appr_status"),"common.getCodeselect"));
|
||||
//발주구분
|
||||
code_map.put("order_type_cd" , commonService.bizMakeOptionList("0001406", (String)paramMap.get("order_type_cd"),"common.getCodeselect"));
|
||||
//주문유형
|
||||
code_map.put("category_cd", commonService.bizMakeOptionList("0000167", CommonUtils.nullToEmpty((String)paramMap.get("category_cd")),"common.getCodeselect"));
|
||||
//제품구분
|
||||
code_map.put("product_cd", commonService.bizMakeOptionList("0000001", CommonUtils.nullToEmpty((String)paramMap.get("product_cd")),"common.getCodeselect"));
|
||||
|
||||
if("excel".equals(actionType)){
|
||||
list = commonService.selectList("purchaseOrder.purchaseOrderMasterList_new", request, paramMap);
|
||||
@@ -1292,8 +1298,8 @@ public class PurchaseOrderController {
|
||||
code_map.put("part_type",commonService.bizMakeOptionList(Constants.PART_TYPE_CODE, (String)paramMap.get("part_type"),"common.getCodeselect"));
|
||||
//발주구분
|
||||
code_map.put("type",commonService.bizMakeOptionList("0001068", (String)paramMap.get("type"),"common.getCodeselect"));
|
||||
//공급업체
|
||||
code_map.put("partner_objid",commonService.bizMakeOptionList("", (String)paramMap.get("partner_objid"),"common.getmatersupplyselect"));
|
||||
//공급업체 (공급업체 + 일반거래처 통합)
|
||||
code_map.put("partner_objid",commonService.bizMakeOptionList("", (String)paramMap.get("partner_objid"),"common.getAllSupplySelect"));
|
||||
//조치담당자
|
||||
code_map.put("sales_mng_user_id", commonService.bizMakeOptionList("", (String)paramMap.get("sales_mng_user_id"),"common.getUserselect"));
|
||||
//상태코드
|
||||
@@ -2106,11 +2112,73 @@ public class PurchaseOrderController {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* PDF 청크 업로드 (AJAX)
|
||||
* @param request
|
||||
* @param paramMap - sessionId, chunkIndex, totalChunks, chunk
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/purchaseOrder/uploadPdfChunk.do", method=RequestMethod.POST)
|
||||
public Map uploadPdfChunk(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
String sessionId = CommonUtils.checkNull(paramMap.get("sessionId"));
|
||||
int chunkIndex = Integer.parseInt(CommonUtils.checkNull(paramMap.get("chunkIndex"), "0"));
|
||||
int totalChunks = Integer.parseInt(CommonUtils.checkNull(paramMap.get("totalChunks"), "1"));
|
||||
String chunk = CommonUtils.checkNull(paramMap.get("chunk"));
|
||||
|
||||
// 임시 디렉토리에 청크 저장
|
||||
String tempDir = System.getProperty("java.io.tmpdir");
|
||||
File chunkFile = new File(tempDir + File.separator + sessionId + "_chunk_" + chunkIndex);
|
||||
|
||||
// 청크 데이터 저장
|
||||
java.io.FileOutputStream fos = new java.io.FileOutputStream(chunkFile);
|
||||
fos.write(chunk.getBytes("UTF-8"));
|
||||
fos.close();
|
||||
|
||||
// 모든 청크가 업로드되면 합치기
|
||||
if(chunkIndex == totalChunks - 1) {
|
||||
StringBuilder fullBase64 = new StringBuilder();
|
||||
for(int i = 0; i < totalChunks; i++) {
|
||||
File cf = new File(tempDir + File.separator + sessionId + "_chunk_" + i);
|
||||
if(cf.exists()) {
|
||||
byte[] data = java.nio.file.Files.readAllBytes(cf.toPath());
|
||||
fullBase64.append(new String(data, "UTF-8"));
|
||||
cf.delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Base64 디코딩하여 PDF 파일 생성 (Apache Commons Codec 사용 - Java 7 호환)
|
||||
byte[] pdfBytes = org.apache.commons.codec.binary.Base64.decodeBase64(fullBase64.toString());
|
||||
File pdfFile = new File(tempDir + File.separator + sessionId + ".pdf");
|
||||
java.io.FileOutputStream pdfFos = new java.io.FileOutputStream(pdfFile);
|
||||
pdfFos.write(pdfBytes);
|
||||
pdfFos.close();
|
||||
|
||||
pdfFile.deleteOnExit();
|
||||
|
||||
System.out.println("발주서 PDF 파일 생성 완료: " + pdfFile.getAbsolutePath() + " (" + pdfBytes.length + " bytes)");
|
||||
}
|
||||
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("chunkIndex", chunkIndex);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", "청크 업로드 중 오류가 발생했습니다: " + e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 발주서 메일 발송 (AJAX)
|
||||
* @param session
|
||||
* @param request
|
||||
* @param paramMap - objId, toEmails, ccEmails, subject, contents
|
||||
* @param paramMap - objId, pdfSessionId, toEmails, ccEmails, subject, contents
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
|
||||
@@ -276,6 +276,8 @@ public class QualityController {
|
||||
code_map.put("partner_objid", commonService.bizMakeOptionList("", (String)paramMap.get("partner_objid"), "common.getClientMngSupplySelect"));
|
||||
// 요청자
|
||||
code_map.put("request_user_id", commonService.bizMakeOptionList("", (String)paramMap.get("request_user_id"), "common.getUserselect"));
|
||||
// 제품구분
|
||||
code_map.put("product_cd", commonService.bizMakeOptionList("0000001", (String)paramMap.get("search_product_cd"), "common.getCodeselect"));
|
||||
|
||||
list = commonService.selectListPaging("quality.getIncomingInspectionList", request, paramMap);
|
||||
} catch(Exception e) {
|
||||
@@ -306,6 +308,8 @@ public class QualityController {
|
||||
code_map.put("partner_objid", commonService.bizMakeOptionList("", (String)paramMap.get("partner_objid"), "common.getClientMngSupplySelect"));
|
||||
// 검사자
|
||||
code_map.put("inspector_id", commonService.bizMakeOptionList("", (String)paramMap.get("inspector_id"), "common.getUserselect"));
|
||||
// 제품구분
|
||||
code_map.put("product_cd", commonService.bizMakeOptionList("0000001", (String)paramMap.get("search_product_cd"), "common.getCodeselect"));
|
||||
|
||||
list = commonService.selectListPaging("quality.getIncomingInspectionList", request, paramMap);
|
||||
} catch(Exception e) {
|
||||
@@ -696,6 +700,15 @@ public class QualityController {
|
||||
return service.lockSemiProductInspection(paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 반제품검사 잠금 해제
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/quality/unlockSemiProductInspection.do")
|
||||
public Map unlockSemiProductInspection(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
return service.unlockSemiProductInspection(paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 반제품검사 엑셀 다운로드 (JSP 방식)
|
||||
*/
|
||||
@@ -919,6 +932,29 @@ public class QualityController {
|
||||
return service.saveEcrResult(request, paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 설계변경요청서 팝업
|
||||
*/
|
||||
@RequestMapping("/quality/ecrDocFormPopUp.do")
|
||||
public String ecrDocFormPopUp(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
try {
|
||||
Map resultMap = service.getEcrInfo(paramMap);
|
||||
request.setAttribute("resultMap", resultMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "/quality/ecrDocFormPopUp";
|
||||
}
|
||||
|
||||
/**
|
||||
* 설계변경요청서 저장
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/quality/saveEcrDoc.do")
|
||||
public Map saveEcrDoc(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
return service.saveEcrDoc(request, paramMap);
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 수입검사 불량상세 관련
|
||||
// =====================================================
|
||||
|
||||
@@ -2736,6 +2736,24 @@ ORDER BY COALESCE(T.REVISION, '1.0')
|
||||
ORDER BY SUPPLY_NAME
|
||||
</select>
|
||||
|
||||
<!-- 공급업체 + 일반거래처 통합 목록 조회 (발주서 검색용) -->
|
||||
<select id="getAllSupplySelect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID::VARCHAR AS CODE
|
||||
,SUPPLY_NAME AS NAME
|
||||
,OBJID::VARCHAR AS CODE_ID
|
||||
,SUPPLY_NAME AS CODE_NAME
|
||||
FROM ADMIN_SUPPLY_MNG
|
||||
UNION ALL
|
||||
SELECT
|
||||
'C_' || OBJID::VARCHAR AS CODE
|
||||
,CLIENT_NM AS NAME
|
||||
,'C_' || OBJID::VARCHAR AS CODE_ID
|
||||
,CLIENT_NM AS CODE_NAME
|
||||
FROM CLIENT_MNG
|
||||
ORDER BY NAME
|
||||
</select>
|
||||
|
||||
<!-- 일반거래처 목록 조회 (CLIENT_MNG 테이블) - 발주서용 -->
|
||||
<select id="getClientMngSupplySelect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
|
||||
@@ -3039,6 +3039,53 @@
|
||||
WHERE 1=1
|
||||
AND PM.PROJECT_NO IS NOT NULL
|
||||
AND PM.PROJECT_NO != ''
|
||||
<!-- 주문유형 검색 -->
|
||||
<if test="search_category_cd != null and search_category_cd != ''">
|
||||
AND CM.CATEGORY_CD = #{search_category_cd}
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_cd != null and search_product_cd != ''">
|
||||
AND CM.PRODUCT = #{search_product_cd}
|
||||
</if>
|
||||
<!-- 국내/해외 검색 -->
|
||||
<if test="search_area_cd != null and search_area_cd != ''">
|
||||
AND CODE_NAME(CM.AREA_CD) = #{search_area_cd}
|
||||
</if>
|
||||
<!-- 접수일 검색 -->
|
||||
<if test="search_receipt_date_from != null and search_receipt_date_from != ''">
|
||||
<![CDATA[AND PM.REGDATE >= TO_DATE(#{search_receipt_date_from}, 'YYYY-MM-DD')]]>
|
||||
</if>
|
||||
<if test="search_receipt_date_to != null and search_receipt_date_to != ''">
|
||||
<![CDATA[AND PM.REGDATE < TO_DATE(#{search_receipt_date_to}, 'YYYY-MM-DD') + INTERVAL '1 day']]>
|
||||
</if>
|
||||
<!-- 고객사 검색 -->
|
||||
<if test="search_customer_objid != null and search_customer_objid != ''">
|
||||
AND (
|
||||
CM.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
OR CM.CUSTOMER_OBJID = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
OR 'C_' || CM.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
)
|
||||
</if>
|
||||
<!-- 유/무상 검색 -->
|
||||
<if test="search_paid_type != null and search_paid_type != ''">
|
||||
AND CM.PAID_TYPE = #{search_paid_type}
|
||||
</if>
|
||||
<!-- S/N 검색 -->
|
||||
<if test="search_serial_no != null and search_serial_no != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND UPPER(CIS.SERIAL_NO) LIKE '%' || UPPER(#{search_serial_no}) || '%'
|
||||
)
|
||||
</if>
|
||||
<!-- 요청납기 검색 -->
|
||||
<if test="search_req_del_date_from != null and search_req_del_date_from != ''">
|
||||
<![CDATA[AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) >= #{search_req_del_date_from}]]>
|
||||
</if>
|
||||
<if test="search_req_del_date_to != null and search_req_del_date_to != ''">
|
||||
<![CDATA[AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) <= #{search_req_del_date_to}]]>
|
||||
</if>
|
||||
<!-- 품번 검색 (대소문자 구분 없음) -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND (
|
||||
@@ -4406,150 +4453,211 @@
|
||||
|
||||
<!-- 생산계획&실적관리 그리드 목록 조회 -->
|
||||
<select id="prodPlanResultMgmtGridList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
CM.PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
CM.CATEGORY_CD AS CATEGORY_CODE,
|
||||
-- 생산유형 (TODO: 실제 컬럼명 확인 필요)
|
||||
'' AS PRODUCTION_TYPE,
|
||||
'' AS PRODUCTION_TYPE_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
CASE
|
||||
WHEN CM.CUSTOMER_OBJID LIKE 'C_%' THEN
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG AS C WHERE 'C_' || C.OBJID::VARCHAR = CM.CUSTOMER_OBJID LIMIT 1)
|
||||
ELSE
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID::VARCHAR = CM.CUSTOMER_OBJID::VARCHAR LIMIT 1)
|
||||
END,
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
-- 요청납기
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
-- 고객사요청사항
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
-- 품번/품명
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
-- S/N
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO,
|
||||
-- 수주수량
|
||||
COALESCE(PM.QUANTITY::numeric, CI.ORDER_QUANTITY::numeric, 0) AS QUANTITY,
|
||||
-- 추가생산수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS EXTRA_PROD_QTY,
|
||||
-- 총생산수량 (수주수량 + 추가생산수량)
|
||||
COALESCE(PM.QUANTITY::numeric, CI.ORDER_QUANTITY::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
-- 완조립 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS ASSEMBLY_QTY,
|
||||
-- 검사 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS INSPECTION_QTY,
|
||||
-- 출하대기 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS SHIP_WAIT_QTY,
|
||||
-- 장비조립WBS (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
'' AS EQUIPMENT_WBS,
|
||||
-- 생산계획 OBJID (있으면 수정, 없으면 신규)
|
||||
NULL AS PROD_PLAN_OBJID
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT OUTER JOIN CONTRACT_ITEM CI ON PM.CONTRACT_OBJID = CI.CONTRACT_OBJID
|
||||
AND PM.PART_OBJID = CI.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE 1=1
|
||||
AND PM.PROJECT_NO IS NOT NULL
|
||||
AND PM.PROJECT_NO != ''
|
||||
<!-- 프로젝트번호 검색 -->
|
||||
<if test="search_project_no != null and search_project_no != ''">
|
||||
AND UPPER(PM.PROJECT_NO) LIKE '%' || UPPER(#{search_project_no}) || '%'
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_code != null and search_product_code != ''">
|
||||
AND CM.PRODUCT = #{search_product_code}
|
||||
</if>
|
||||
<!-- 주문유형 검색 -->
|
||||
<if test="search_category_code != null and search_category_code != ''">
|
||||
AND CM.CATEGORY_CD = #{search_category_code}
|
||||
</if>
|
||||
<!-- 생산유형 검색 -->
|
||||
<if test="search_production_type != null and search_production_type != ''">
|
||||
AND 1=1 <!-- TODO: 생산유형 컬럼 확인 후 조건 추가 -->
|
||||
</if>
|
||||
<!-- 고객사 검색 -->
|
||||
<if test="search_customer_objid != null and search_customer_objid != ''">
|
||||
AND CM.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
</if>
|
||||
<!-- 요청납기 검색 -->
|
||||
<if test="search_req_del_date_from != null and search_req_del_date_from != ''">
|
||||
AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) >= #{search_req_del_date_from}
|
||||
</if>
|
||||
<if test="search_req_del_date_to != null and search_req_del_date_to != ''">
|
||||
AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) <= #{search_req_del_date_to}
|
||||
</if>
|
||||
<!-- 품번 검색 -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND (
|
||||
UPPER(PM.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
OR UPPER(CI.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
)
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND (
|
||||
UPPER(PM.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
OR UPPER(CI.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
)
|
||||
</if>
|
||||
<!-- S/N 검색 -->
|
||||
<if test="search_serial_no != null and search_serial_no != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND UPPER(CIS.SERIAL_NO) LIKE '%' || UPPER(#{search_serial_no}) || '%'
|
||||
)
|
||||
</if>
|
||||
ORDER BY PM.REGDATE DESC, PM.PROJECT_NO DESC
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트 정보 조회 (생산계획 폼용) -->
|
||||
<select id="getProdPlanProjectInfo" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO) AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME) AS PART_NAME,
|
||||
COALESCE(CM.PRODUCT, PM.PRODUCT) AS PRODUCT_CODE,
|
||||
COALESCE(CM.CATEGORY_CD, '') AS CATEGORY_CODE,
|
||||
COALESCE(CM.CUSTOMER_OBJID, PM.CUSTOMER_OBJID) AS CUSTOMER_OBJID,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
PM.QUANTITY AS ORDER_QTY,
|
||||
CM.CUSTOMER_REQUEST,
|
||||
(
|
||||
SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
SELECT * FROM (
|
||||
-- 1. 프로젝트 기반 데이터 (기존)
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
CM.PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
CM.CATEGORY_CD AS CATEGORY_CODE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.CATEGORY_CD LIMIT 1),
|
||||
CM.CATEGORY_CD
|
||||
) AS CATEGORY_CODE_NAME,
|
||||
COALESCE(PP.PRODUCTION_TYPE, '') AS PRODUCTION_TYPE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCTION_TYPE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCTION_TYPE_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
CASE
|
||||
WHEN CM.CUSTOMER_OBJID LIKE 'C_%' THEN
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG AS C WHERE 'C_' || C.OBJID::VARCHAR = CM.CUSTOMER_OBJID LIMIT 1)
|
||||
ELSE
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID::VARCHAR = CM.CUSTOMER_OBJID::VARCHAR LIMIT 1)
|
||||
END,
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
) AS SERIAL_NO
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE PM.OBJID = #{projectObjid}
|
||||
AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, NULLIF(CI.ORDER_QUANTITY, '')::numeric, 0) AS QUANTITY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, NULLIF(CI.ORDER_QUANTITY, '')::numeric, 0) + COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'ASSEMBLY' AND PR.STATUS = 'active'), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'INSPECTION' AND PR.STATUS = 'active'), 0) AS INSPECTION_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'SHIP_WAIT' AND PR.STATUS = 'active'), 0) AS SHIP_WAIT_QTY,
|
||||
'' AS EQUIPMENT_WBS,
|
||||
PP.OBJID AS PROD_PLAN_OBJID,
|
||||
PM.REGDATE AS SORT_DATE
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT OUTER JOIN CONTRACT_ITEM CI ON PM.CONTRACT_OBJID = CI.CONTRACT_OBJID
|
||||
AND PM.PART_OBJID = CI.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LEFT OUTER JOIN PRODUCTION_PLAN PP ON PP.PROJECT_OBJID = PM.OBJID
|
||||
AND PP.STATUS = 'active'
|
||||
WHERE PM.PROJECT_NO IS NOT NULL AND PM.PROJECT_NO != ''
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 2. 프로젝트 없이 등록한 생산계획
|
||||
SELECT
|
||||
PP.OBJID AS OBJID,
|
||||
'' AS PROJECT_NO,
|
||||
PP.PRODUCT_CODE AS PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCT_CODE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
PP.CATEGORY_CODE AS CATEGORY_CODE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.CATEGORY_CODE LIMIT 1),
|
||||
''
|
||||
) AS CATEGORY_CODE_NAME,
|
||||
COALESCE(PP.PRODUCTION_TYPE, '') AS PRODUCTION_TYPE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCTION_TYPE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCTION_TYPE_NAME,
|
||||
PP.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = PP.CUSTOMER_OBJID LIMIT 1),
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
PP.REQ_DEL_DATE,
|
||||
COALESCE(PP.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(PP.PART_NO, '') AS PART_NO,
|
||||
COALESCE(PP.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(PP.SERIAL_NO, '') AS SERIAL_NO,
|
||||
COALESCE(NULLIF(PP.ORDER_QTY, '')::numeric, 0) AS QUANTITY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(NULLIF(PP.TOTAL_PROD_QTY, '')::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'ASSEMBLY' AND PR.STATUS = 'active'), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'INSPECTION' AND PR.STATUS = 'active'), 0) AS INSPECTION_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'SHIP_WAIT' AND PR.STATUS = 'active'), 0) AS SHIP_WAIT_QTY,
|
||||
'' AS EQUIPMENT_WBS,
|
||||
PP.OBJID AS PROD_PLAN_OBJID,
|
||||
PP.REGDATE AS SORT_DATE
|
||||
FROM PRODUCTION_PLAN PP
|
||||
WHERE PP.STATUS = 'active'
|
||||
AND (PP.PROJECT_OBJID IS NULL OR PP.PROJECT_OBJID = '')
|
||||
) T
|
||||
WHERE 1=1
|
||||
<!-- 프로젝트번호 검색 (multiple select) -->
|
||||
<if test="search_project_nos != null and search_project_nos != ''">
|
||||
AND T.OBJID::VARCHAR IN
|
||||
<foreach item="projNo" collection="search_project_nos.split(',')" open="(" separator="," close=")">
|
||||
#{projNo}
|
||||
</foreach>
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_code != null and search_product_code != ''">
|
||||
AND T.PRODUCT = #{search_product_code}
|
||||
</if>
|
||||
<!-- 주문유형 검색 -->
|
||||
<if test="search_category_code != null and search_category_code != ''">
|
||||
AND T.CATEGORY_CODE = #{search_category_code}
|
||||
</if>
|
||||
<!-- 생산유형 검색 -->
|
||||
<if test="search_production_type != null and search_production_type != ''">
|
||||
AND T.PRODUCTION_TYPE = #{search_production_type}
|
||||
</if>
|
||||
<!-- 고객사 검색 -->
|
||||
<if test="search_customer_objid != null and search_customer_objid != ''">
|
||||
AND (
|
||||
T.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
OR T.CUSTOMER_OBJID = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
OR REPLACE(T.CUSTOMER_OBJID, 'C_', '') = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<!-- 요청납기 검색 -->
|
||||
<if test="search_req_del_date_from != null and search_req_del_date_from != ''">
|
||||
AND T.REQ_DEL_DATE >= #{search_req_del_date_from}
|
||||
</if>
|
||||
<if test="search_req_del_date_to != null and search_req_del_date_to != ''">
|
||||
AND T.REQ_DEL_DATE <= #{search_req_del_date_to}
|
||||
</if>
|
||||
<!-- 품번 검색 -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND UPPER(T.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND UPPER(T.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
</if>
|
||||
<!-- S/N 검색 -->
|
||||
<if test="search_serial_no != null and search_serial_no != ''">
|
||||
AND UPPER(T.SERIAL_NO) LIKE '%' || UPPER(#{search_serial_no}) || '%'
|
||||
</if>
|
||||
ORDER BY T.SORT_DATE DESC, T.PROJECT_NO DESC
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트 정보 조회 (생산계획 폼용) - PROJECT_MGMT 또는 PRODUCTION_PLAN에서 조회 -->
|
||||
<select id="getProdPlanProjectInfo" parameterType="map" resultType="map">
|
||||
SELECT * FROM (
|
||||
-- 1. PROJECT_MGMT 기반 조회
|
||||
SELECT
|
||||
PM.OBJID::VARCHAR AS OBJID,
|
||||
COALESCE(PM.PROJECT_NO, '') AS PROJECT_NO,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(CM.PRODUCT, PM.PRODUCT, '') AS PRODUCT_CODE,
|
||||
COALESCE(CM.CATEGORY_CD, '') AS CATEGORY_CODE,
|
||||
COALESCE(CM.CUSTOMER_OBJID, PM.CUSTOMER_OBJID, '')::VARCHAR AS CUSTOMER_OBJID,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE, '') AS REQ_DEL_DATE,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, 0) AS ORDER_QTY,
|
||||
COALESCE((SELECT NULLIF(PP.EXTRA_PROD_QTY, '')::numeric FROM PRODUCTION_PLAN PP WHERE PP.PROJECT_OBJID = PM.OBJID AND UPPER(PP.STATUS) = 'ACTIVE' LIMIT 1), 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(CM.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE((
|
||||
SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
), '') AS SERIAL_NO
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE PM.OBJID::VARCHAR = #{projectObjid}
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 2. PRODUCTION_PLAN 기반 조회 (OBJID로 직접 조회)
|
||||
SELECT
|
||||
PP.OBJID::VARCHAR AS OBJID,
|
||||
'' AS PROJECT_NO,
|
||||
COALESCE(PP.PART_NO, '') AS PART_NO,
|
||||
COALESCE(PP.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(PP.PRODUCT_CODE, '') AS PRODUCT_CODE,
|
||||
COALESCE(PP.CATEGORY_CODE, '') AS CATEGORY_CODE,
|
||||
COALESCE(PP.CUSTOMER_OBJID, '')::VARCHAR AS CUSTOMER_OBJID,
|
||||
COALESCE(PP.REQ_DEL_DATE, '') AS REQ_DEL_DATE,
|
||||
COALESCE(NULLIF(PP.ORDER_QTY, '')::numeric, 0) AS ORDER_QTY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(PP.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(PP.SERIAL_NO, '') AS SERIAL_NO
|
||||
FROM PRODUCTION_PLAN PP
|
||||
WHERE PP.OBJID::VARCHAR = #{projectObjid}
|
||||
) T
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
@@ -4639,4 +4747,178 @@
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 생산실적 목록 조회 -->
|
||||
<select id="getProdResultList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
OBJID,
|
||||
PROJECT_OBJID,
|
||||
RESULT_TYPE,
|
||||
TO_CHAR(RESULT_DATE::DATE, 'YYYY-MM-DD') AS RESULT_DATE,
|
||||
RESULT_QTY,
|
||||
SERIAL_NO,
|
||||
WORKER_ID,
|
||||
WORKER_NAME,
|
||||
REMARK,
|
||||
STATUS
|
||||
FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND STATUS = 'active'
|
||||
<if test="resultType != null and resultType != ''">
|
||||
AND RESULT_TYPE = #{resultType}
|
||||
</if>
|
||||
ORDER BY RESULT_DATE DESC, REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 등록 -->
|
||||
<insert id="insertProdResult" parameterType="map">
|
||||
INSERT INTO PRODUCTION_RESULT (
|
||||
OBJID,
|
||||
PROJECT_OBJID,
|
||||
RESULT_TYPE,
|
||||
RESULT_DATE,
|
||||
RESULT_QTY,
|
||||
ROW_SEQ,
|
||||
SERIAL_NO,
|
||||
WORKER_ID,
|
||||
WORKER_NAME,
|
||||
REMARK,
|
||||
STATUS,
|
||||
REGDATE,
|
||||
WRITER
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
#{PROJECT_OBJID},
|
||||
#{RESULT_TYPE},
|
||||
#{RESULT_DATE},
|
||||
#{RESULT_QTY},
|
||||
#{ROW_SEQ},
|
||||
#{SERIAL_NO},
|
||||
#{userId},
|
||||
#{WORKER_NAME},
|
||||
#{REMARK},
|
||||
'active',
|
||||
NOW(),
|
||||
#{userId}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 생산실적 수정 -->
|
||||
<update id="updateProdResult" parameterType="map">
|
||||
UPDATE PRODUCTION_RESULT SET
|
||||
RESULT_TYPE = #{RESULT_TYPE},
|
||||
RESULT_DATE = #{RESULT_DATE},
|
||||
RESULT_QTY = #{RESULT_QTY},
|
||||
SERIAL_NO = #{SERIAL_NO},
|
||||
WORKER_NAME = #{WORKER_NAME},
|
||||
REMARK = #{REMARK},
|
||||
MODDATE = NOW(),
|
||||
MODIFIER = #{userId}
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- M-BOM 반제품 항목 조회 (PART_TYPE이 부품(0001812), 조립품(0001813)인 항목만, 1레벨 제외) -->
|
||||
<select id="getMbomSemiProductItems" parameterType="map" resultType="map">
|
||||
/* productionplanning.getMbomSemiProductItems - M-BOM에서 부품/조립품 조회 (1레벨 제외) */
|
||||
SELECT
|
||||
MD.PART_NO,
|
||||
MD.PART_NAME,
|
||||
COALESCE(MD.QTY, '1')::INTEGER AS ITEM_QTY,
|
||||
P.PART_TYPE,
|
||||
COALESCE((SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = P.PART_TYPE LIMIT 1), '') AS CATEGORY_NAME,
|
||||
COALESCE(P.UNIT, '') AS UNIT,
|
||||
COALESCE(P.MATERIAL, '') AS MATERIAL,
|
||||
COALESCE(P.SPEC, '') AS SPEC
|
||||
FROM MBOM_DETAIL MD
|
||||
INNER JOIN PART_MNG P ON P.OBJID::VARCHAR = MD.PART_OBJID
|
||||
WHERE MD.MBOM_HEADER_OBJID = #{mbomHeaderObjid}
|
||||
AND MD.STATUS = 'ACTIVE'
|
||||
AND (MD.PARENT_OBJID IS NOT NULL AND MD.PARENT_OBJID != '') -- 1레벨 제외 (PARENT_OBJID가 있는 항목만)
|
||||
AND P.PART_TYPE IN ('0001812', '0001813') -- 부품, 조립품
|
||||
ORDER BY P.PART_TYPE, MD.PART_NO
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 원자재(구매품) 항목 조회 (PART_TYPE이 구매품(0000063)인 항목만, 1레벨 제외) -->
|
||||
<select id="getMbomRawMaterialItems" parameterType="map" resultType="map">
|
||||
/* productionplanning.getMbomRawMaterialItems - M-BOM에서 구매품 조회 (1레벨 제외) */
|
||||
SELECT
|
||||
MD.PART_NO,
|
||||
MD.PART_NAME,
|
||||
COALESCE(MD.QTY, '1')::INTEGER AS ITEM_QTY,
|
||||
P.PART_TYPE,
|
||||
COALESCE((SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = P.PART_TYPE LIMIT 1), '') AS CATEGORY_NAME,
|
||||
COALESCE(P.UNIT, '') AS UNIT,
|
||||
COALESCE(P.MATERIAL, '') AS MATERIAL,
|
||||
COALESCE(P.SPEC, '') AS SPEC,
|
||||
'' AS RAW_MATERIAL,
|
||||
'' AS RAW_MATERIAL_SIZE,
|
||||
'' AS RAW_MATERIAL_PART_NO,
|
||||
0 AS RAW_MATERIAL_QTY
|
||||
FROM MBOM_DETAIL MD
|
||||
INNER JOIN PART_MNG P ON P.OBJID::VARCHAR = MD.PART_OBJID
|
||||
WHERE MD.MBOM_HEADER_OBJID = #{mbomHeaderObjid}
|
||||
AND MD.STATUS = 'ACTIVE'
|
||||
AND (MD.PARENT_OBJID IS NOT NULL AND MD.PARENT_OBJID != '') -- 1레벨 제외 (PARENT_OBJID가 있는 항목만)
|
||||
AND P.PART_TYPE = '0000063' -- 구매품
|
||||
ORDER BY MD.PART_NO
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 원소재 항목 조회 (RAW_MATERIAL_PART_NO가 있는 항목만) -->
|
||||
<select id="getMbomRawSourceItems" parameterType="map" resultType="map">
|
||||
/* productionplanning.getMbomRawSourceItems - M-BOM에서 원소재 조회 */
|
||||
SELECT
|
||||
MD.RAW_MATERIAL_PART_NO AS PART_NO,
|
||||
MD.RAW_MATERIAL AS PART_NAME,
|
||||
COALESCE(MD.REQUIRED_QTY, '0')::NUMERIC AS ITEM_QTY,
|
||||
'원소재' AS CATEGORY_NAME,
|
||||
'' AS UNIT,
|
||||
MD.RAW_MATERIAL AS MATERIAL,
|
||||
MD.RAW_MATERIAL_SIZE AS SPEC,
|
||||
MD.RAW_MATERIAL,
|
||||
MD.RAW_MATERIAL_SIZE,
|
||||
MD.RAW_MATERIAL_PART_NO,
|
||||
COALESCE(MD.REQUIRED_QTY, '0')::NUMERIC AS RAW_MATERIAL_QTY
|
||||
FROM MBOM_DETAIL MD
|
||||
WHERE MD.MBOM_HEADER_OBJID = #{mbomHeaderObjid}
|
||||
AND MD.STATUS = 'ACTIVE'
|
||||
AND MD.RAW_MATERIAL_PART_NO IS NOT NULL
|
||||
AND MD.RAW_MATERIAL_PART_NO != ''
|
||||
ORDER BY MD.RAW_MATERIAL_PART_NO
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 날짜별 조회 (피봇) -->
|
||||
<select id="getProdResultListByDate" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
ROW_SEQ,
|
||||
RESULT_DATE,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'ASSEMBLY' THEN RESULT_QTY ELSE 0 END), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'INSPECTION' THEN RESULT_QTY ELSE 0 END), 0) AS INSPECTION_QTY,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'SHIP_WAIT' THEN RESULT_QTY ELSE 0 END), 0) AS SHIP_WAIT_QTY,
|
||||
MAX(REMARK) AS REMARK
|
||||
FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND STATUS = 'active'
|
||||
GROUP BY ROW_SEQ, RESULT_DATE
|
||||
ORDER BY ROW_SEQ ASC
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 행별 삭제 -->
|
||||
<delete id="deleteProdResultByRowSeq" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND ROW_SEQ = #{rowSeq}
|
||||
</delete>
|
||||
|
||||
<!-- 생산실적 날짜별 삭제 (기존 데이터 삭제 후 재입력용) -->
|
||||
<delete id="deleteProdResultByDate" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND RESULT_DATE = #{resultDate}
|
||||
</delete>
|
||||
|
||||
<!-- 생산실적 프로젝트 전체 삭제 -->
|
||||
<delete id="deleteProdResultByProject" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -4218,12 +4218,20 @@
|
||||
AND result_cd = #{result_cd}
|
||||
</if>
|
||||
|
||||
<!-- 요청납기일 필터: REQ_DEL_DATE 로직과 동일하게 COALESCE 사용 -->
|
||||
<if test="contract_start_date != null and !''.equals(contract_start_date)">
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{contract_start_date}, 'YYYY-MM-DD')
|
||||
|
||||
AND TO_DATE(COALESCE(
|
||||
(SELECT CI.DUE_DATE FROM CONTRACT_ITEM CI WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID AND CI.PART_OBJID = T.PART_OBJID AND CI.STATUS = 'ACTIVE'),
|
||||
T.DUE_DATE,
|
||||
(SELECT CM.due_date FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID)
|
||||
),'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{contract_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="contract_end_date != null and !''.equals(contract_end_date)">
|
||||
AND TO_DATE(DUE_DATE,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{contract_end_date}, 'YYYY-MM-DD')
|
||||
AND TO_DATE(COALESCE(
|
||||
(SELECT CI.DUE_DATE FROM CONTRACT_ITEM CI WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID AND CI.PART_OBJID = T.PART_OBJID AND CI.STATUS = 'ACTIVE'),
|
||||
T.DUE_DATE,
|
||||
(SELECT CM.due_date FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID)
|
||||
),'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{contract_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
|
||||
<if test="pm_user_id !=null and pm_user_id !=''">
|
||||
@@ -4235,6 +4243,38 @@
|
||||
<if test="setup != null and !''.equals(setup)">
|
||||
AND UPPER(SETUP) LIKE UPPER('%${setup}%')
|
||||
</if>
|
||||
<!-- 국내/해외 필터 -->
|
||||
<if test="area_cd != null and area_cd != ''">
|
||||
AND CODE_NAME(AREA_CD) = #{area_cd}
|
||||
</if>
|
||||
<!-- 유/무상 필터 -->
|
||||
<if test="free_of_charge != null and free_of_charge != ''">
|
||||
AND (SELECT
|
||||
CASE
|
||||
WHEN O.PAID_TYPE = 'paid' THEN '유상'
|
||||
WHEN O.PAID_TYPE = 'free' THEN '무상'
|
||||
ELSE O.PAID_TYPE
|
||||
END
|
||||
FROM CONTRACT_MGMT AS O WHERE O.OBJID = T.CONTRACT_OBJID) = #{free_of_charge}
|
||||
</if>
|
||||
<!-- 품번 필터 -->
|
||||
<if test="product_item_code != null and product_item_code != ''">
|
||||
AND UPPER(T.PART_NO) LIKE UPPER('%' || #{product_item_code} || '%')
|
||||
</if>
|
||||
<!-- 품명 필터 -->
|
||||
<if test="product_item_name != null and product_item_name != ''">
|
||||
AND UPPER(T.PART_NAME) LIKE UPPER('%' || #{product_item_name} || '%')
|
||||
</if>
|
||||
<!-- S/N 필터 -->
|
||||
<if test="serial_no != null and serial_no != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM CONTRACT_ITEM AS I
|
||||
LEFT JOIN CONTRACT_ITEM_SERIAL AS S ON S.ITEM_OBJID = I.OBJID AND S.STATUS = 'ACTIVE'
|
||||
WHERE I.CONTRACT_OBJID = T.CONTRACT_OBJID
|
||||
AND I.PART_OBJID = T.PART_OBJID
|
||||
AND UPPER(S.SERIAL_NO) LIKE UPPER('%' || #{serial_no} || '%')
|
||||
)
|
||||
</if>
|
||||
ORDER BY SUBSTRING(PROJECT_NO,POSITION('-' IN PROJECT_NO)+1) DESC, OVERHAUL_ORDER DESC NULLS LAST
|
||||
</select>
|
||||
|
||||
|
||||
@@ -1429,6 +1429,9 @@
|
||||
|
||||
-- 요청사항
|
||||
,POM.REQUEST_CONTENT
|
||||
|
||||
-- 양식 타입 (general/outsourcing)
|
||||
,COALESCE(POM.FORM_TYPE, 'general') AS FORM_TYPE
|
||||
FROM
|
||||
PURCHASE_ORDER_MASTER POM
|
||||
|
||||
@@ -2944,7 +2947,7 @@ WHERE 1=1
|
||||
AND EXISTS (
|
||||
SELECT 'E' FROM PROJECT_MGMT AS S_P
|
||||
WHERE POM.CONTRACT_MGMT_OBJID = S_P.OBJID
|
||||
AND S_P.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND S_P.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
@@ -2972,7 +2975,7 @@ WHERE 1=1
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
AND POM.SALES_MNG_USER_ID = #{sales_mng_user_id}
|
||||
@@ -3107,7 +3110,7 @@ SELECT
|
||||
AND EXISTS (
|
||||
SELECT 'E' FROM PROJECT_MGMT AS S_P
|
||||
WHERE POM.CONTRACT_MGMT_OBJID = S_P.OBJID
|
||||
AND S_P.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND S_P.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
@@ -3135,7 +3138,7 @@ SELECT
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
AND POM.SALES_MNG_USER_ID = #{sales_mng_user_id}
|
||||
@@ -3337,7 +3340,7 @@ WHERE 1=1
|
||||
AND EXISTS (
|
||||
SELECT 'E' FROM PROJECT_MGMT AS S_P
|
||||
WHERE POM.CONTRACT_MGMT_OBJID = S_P.OBJID
|
||||
AND S_P.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND S_P.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
@@ -3372,7 +3375,7 @@ WHERE 1=1
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<!--
|
||||
<if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
@@ -3386,12 +3389,21 @@ WHERE 1=1
|
||||
#{value}
|
||||
</foreach>
|
||||
</if>
|
||||
<!-- 주문유형 필터 -->
|
||||
<if test="category_cd != null and category_cd != ''">
|
||||
AND CM.CATEGORY_CD = #{category_cd}
|
||||
</if>
|
||||
<!-- 제품구분 필터 -->
|
||||
<if test="product_cd != null and product_cd != ''">
|
||||
AND CM.PRODUCT = #{product_cd}
|
||||
</if>
|
||||
|
||||
<!-- 발주일 필터: MAIL_SEND_DATE (그리드 컬럼과 일치) -->
|
||||
<if test="reg_start_date !=null and reg_start_date != '' ">
|
||||
AND TO_DATE(TO_CHAR(POM.REGDATE,'YYYY-MM-DD') ,'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{reg_start_date}, 'YYYY-MM-DD')
|
||||
AND TO_DATE(POM.MAIL_SEND_DATE, 'YYYY-MM-DD') <![CDATA[ >= ]]> TO_DATE(#{reg_start_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="reg_end_date !=null and reg_end_date != '' ">
|
||||
AND TO_DATE(TO_CHAR(POM.REGDATE,'YYYY-MM-DD') ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{reg_end_date}, 'YYYY-MM-DD')
|
||||
AND TO_DATE(POM.MAIL_SEND_DATE, 'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{reg_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="appr_status !=null and appr_status != '' ">
|
||||
<choose>
|
||||
@@ -3564,7 +3576,7 @@ WHERE 1=1
|
||||
AND EXISTS (
|
||||
SELECT 'E' FROM PROJECT_MGMT AS S_P
|
||||
WHERE POM.CONTRACT_MGMT_OBJID = S_P.OBJID
|
||||
AND S_P.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND S_P.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
@@ -3599,7 +3611,7 @@ WHERE 1=1
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<!--
|
||||
<if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
@@ -4374,7 +4386,7 @@ SELECT POM.OBJID
|
||||
AND TO_CHAR(TO_DATE(S1.CUR_DELIVERY_DATE ,'YYYY-MM-DD'), 'YYYY') = #{Year}
|
||||
</if>
|
||||
<if test="customer_cd !=null and customer_cd != '' ">
|
||||
AND CM.CUSTOMER_OBJID = #{customer_cd}
|
||||
AND CM.CUSTOMER_OBJID = REPLACE(#{customer_cd}, 'C_', '')
|
||||
</if>
|
||||
<if test="customer_project_name !=null and customer_project_name != '' ">
|
||||
AND TRIM(UPPER(CM.CUSTOMER_PROJECT_NAME)) = TRIM(UPPER(#{customer_project_name}))
|
||||
@@ -4405,7 +4417,7 @@ SELECT POM.OBJID
|
||||
AND TO_DATE(POM.DELIVERY_DATE ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{delivery_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="partner_objid !=null and partner_objid != '' ">
|
||||
AND POM.PARTNER_OBJID = #{partner_objid}
|
||||
AND POM.PARTNER_OBJID = REPLACE(#{partner_objid}, 'C_', '')
|
||||
</if>
|
||||
<!-- <if test="sales_mng_user_id !=null and sales_mng_user_id != '' ">
|
||||
AND POM.SALES_MNG_USER_ID = #{sales_mng_user_id}
|
||||
@@ -4424,7 +4436,7 @@ SELECT POM.OBJID
|
||||
AND TO_DATE(TO_CHAR(POM.REGDATE,'YYYY-MM-DD') ,'YYYY-MM-DD') <![CDATA[ <= ]]> TO_DATE(#{reg_end_date}, 'YYYY-MM-DD')
|
||||
</if>
|
||||
<if test="delivery_status !=null and delivery_status != '' ">
|
||||
AND (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 '입고완료'
|
||||
AND (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) = #{delivery_status}
|
||||
|
||||
@@ -711,10 +711,9 @@
|
||||
,DEFECT.INSPECTOR_NAME_DISPLAY AS INSPECTOR_NAME
|
||||
/* 검사일: YYYY-MM-DD 외 N건 형태 */
|
||||
,DEFECT.INSPECTION_DATE_DISPLAY AS INSPECTION_DATE
|
||||
/* 검사결과: 하나라도 NG면 NG, 검사 대상(스킵 제외) 모두 검사완료면 OK, 일부만 검사면 검사중 */
|
||||
,(CASE WHEN DEFECT.NG_COUNT > 0 THEN 'NG'
|
||||
WHEN DEFECT.INSPECTION_TARGET_COUNT > 0 AND DEFECT.INSPECTION_TARGET_COUNT = DEFECT.INSPECTED_COUNT THEN 'OK'
|
||||
WHEN DEFECT.INSPECTED_COUNT > 0 THEN '검사중'
|
||||
/* 검사현황: 불량상세 처리결과(ACTION_RESULT)가 전부 있으면 완료, 일부만 있으면 진행중 */
|
||||
,(CASE WHEN DEFECT.DEFECT_TOTAL_COUNT > 0 AND DEFECT.DEFECT_TOTAL_COUNT = DEFECT.ACTION_RESULT_COUNT THEN '완료'
|
||||
WHEN DEFECT.ACTION_RESULT_COUNT > 0 THEN '진행중'
|
||||
ELSE '' END) AS INSPECTION_RESULT
|
||||
|
||||
/* 검사여부: 검사가 하나라도 있으면 '검사', 모두 스킵이면 '스킵', 아무것도 없으면 빈값 */
|
||||
@@ -764,6 +763,10 @@
|
||||
END AS INSPECTION_DATE_DISPLAY
|
||||
/* 검사 대상 건수 (스킵 제외, 검사인 항목만) */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' THEN 1 END) AS INSPECTION_TARGET_COUNT
|
||||
/* 불량상세 테이블 전체 건수 (검사인 항목 기준) */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' THEN IDF.OBJID END) AS DEFECT_TOTAL_COUNT
|
||||
/* 처리결과(ACTION_RESULT) 입력된 건수 */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' AND IDF.ACTION_RESULT IS NOT NULL AND IDF.ACTION_RESULT != '' THEN 1 END) AS ACTION_RESULT_COUNT
|
||||
/* 검사결과 입력된 건수 */
|
||||
,COUNT(CASE WHEN IDF.INSPECTION_RESULT IS NOT NULL AND IDF.INSPECTION_RESULT != '' THEN 1 END) AS INSPECTED_COUNT
|
||||
,COUNT(CASE WHEN IDF.INSPECTION_RESULT = 'NG' THEN 1 END) AS NG_COUNT
|
||||
@@ -827,37 +830,98 @@
|
||||
ELSE '입고중'
|
||||
END) = #{search_delivery_status}
|
||||
</if>
|
||||
<!-- 프로젝트번호 (multi select) -->
|
||||
<!-- 프로젝트번호 (multi select) - OBJID로 검색 -->
|
||||
<if test="project_nos != null and project_nos != ''">
|
||||
AND CM.PROJECT_NO IN
|
||||
AND CM.OBJID::VARCHAR IN
|
||||
<foreach item="item" collection="project_nos.split(',')" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<!-- 검사자 -->
|
||||
<if test="inspector_id != null and inspector_id != ''">
|
||||
AND IID.INSPECTOR_ID = #{inspector_id}
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM INCOMING_INSPECTION_DETAIL IID_SUB
|
||||
LEFT JOIN INCOMING_INSPECTION_DEFECT IDF_SUB ON IDF_SUB.INSPECTION_DETAIL_OBJID = IID_SUB.OBJID
|
||||
WHERE IID_SUB.PURCHASE_ORDER_MASTER_OBJID = POM.OBJID::VARCHAR
|
||||
AND IDF_SUB.INSPECTOR_ID = #{inspector_id}
|
||||
)
|
||||
</if>
|
||||
<!-- 검사일 (시작) -->
|
||||
<if test="inspection_start_date != null and inspection_start_date != ''">
|
||||
AND IID.INSPECTION_DATE <![CDATA[ >= ]]> #{inspection_start_date}
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM INCOMING_INSPECTION_DETAIL IID_SUB
|
||||
LEFT JOIN INCOMING_INSPECTION_DEFECT IDF_SUB ON IDF_SUB.INSPECTION_DETAIL_OBJID = IID_SUB.OBJID
|
||||
WHERE IID_SUB.PURCHASE_ORDER_MASTER_OBJID = POM.OBJID::VARCHAR
|
||||
AND IDF_SUB.INSPECTION_DATE <![CDATA[ >= ]]> TO_DATE(#{inspection_start_date}, 'YYYY-MM-DD')
|
||||
)
|
||||
</if>
|
||||
<!-- 검사일 (종료) -->
|
||||
<if test="inspection_end_date != null and inspection_end_date != ''">
|
||||
AND IID.INSPECTION_DATE <![CDATA[ <= ]]> #{inspection_end_date}
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM INCOMING_INSPECTION_DETAIL IID_SUB
|
||||
LEFT JOIN INCOMING_INSPECTION_DEFECT IDF_SUB ON IDF_SUB.INSPECTION_DETAIL_OBJID = IID_SUB.OBJID
|
||||
WHERE IID_SUB.PURCHASE_ORDER_MASTER_OBJID = POM.OBJID::VARCHAR
|
||||
AND IDF_SUB.INSPECTION_DATE <![CDATA[ <= ]]> TO_DATE(#{inspection_end_date}, 'YYYY-MM-DD')
|
||||
)
|
||||
</if>
|
||||
<!-- 검사결과 -->
|
||||
<if test="search_inspection_result != null and search_inspection_result != ''">
|
||||
AND (CASE WHEN IID.NG_COUNT > 0 THEN 'NG'
|
||||
WHEN IID.TOTAL_COUNT > 0 AND IID.TOTAL_COUNT = IID.INSPECTED_COUNT THEN 'OK'
|
||||
WHEN IID.INSPECTED_COUNT > 0 THEN '검사중'
|
||||
AND (CASE WHEN DEFECT.NG_COUNT > 0 THEN 'NG'
|
||||
WHEN DEFECT.INSPECTION_TARGET_COUNT > 0 AND DEFECT.INSPECTION_TARGET_COUNT = DEFECT.INSPECTED_COUNT THEN 'OK'
|
||||
WHEN DEFECT.INSPECTED_COUNT > 0 THEN '검사중'
|
||||
ELSE '' END) = #{search_inspection_result}
|
||||
</if>
|
||||
<!-- 요청자 -->
|
||||
<if test="request_user_id != null and request_user_id != ''">
|
||||
AND IID.REQUEST_USER_ID = #{request_user_id}
|
||||
</if>
|
||||
<!-- 요청일 (시작) -->
|
||||
<if test="request_start_date != null and request_start_date != ''">
|
||||
AND IID.REQUEST_DATE <![CDATA[ >= ]]> #{request_start_date}
|
||||
</if>
|
||||
<!-- 요청일 (종료) -->
|
||||
<if test="request_end_date != null and request_end_date != ''">
|
||||
AND IID.REQUEST_DATE <![CDATA[ <= ]]> #{request_end_date}
|
||||
</if>
|
||||
<!-- 요청현황 필터 (수입검사 진행 리스트에서 요청완료 건만 조회) -->
|
||||
<if test="request_status_filter != null and request_status_filter == '요청완료'">
|
||||
AND REQ.DELIVERY_TOTAL_COUNT = REQ.SELECTED_COUNT
|
||||
AND REQ.SELECTED_COUNT > 0
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_cd != null and search_product_cd != ''">
|
||||
AND CM.PRODUCT = #{search_product_cd}
|
||||
</if>
|
||||
<!-- 검사여부 검색 -->
|
||||
<if test="search_inspection_yn != null and search_inspection_yn != ''">
|
||||
<if test="search_inspection_yn == '검사'">
|
||||
AND IID.INSPECTION_YN_COUNT > 0
|
||||
</if>
|
||||
<if test="search_inspection_yn == '스킵'">
|
||||
AND IID.SKIP_YN_COUNT > 0 AND IID.INSPECTION_YN_COUNT = 0
|
||||
</if>
|
||||
</if>
|
||||
<!-- 요청현황 검색 -->
|
||||
<if test="search_request_status != null and search_request_status != ''">
|
||||
<if test="search_request_status == '미요청'">
|
||||
AND REQ.DELIVERY_TOTAL_COUNT > 0 AND REQ.SELECTED_COUNT = 0
|
||||
</if>
|
||||
<if test="search_request_status == '요청중'">
|
||||
AND REQ.SELECTED_COUNT > 0 AND REQ.SELECTED_COUNT <![CDATA[ < ]]> REQ.DELIVERY_TOTAL_COUNT
|
||||
</if>
|
||||
<if test="search_request_status == '요청완료'">
|
||||
AND REQ.DELIVERY_TOTAL_COUNT > 0 AND REQ.SELECTED_COUNT = REQ.DELIVERY_TOTAL_COUNT
|
||||
</if>
|
||||
</if>
|
||||
<!-- 검사현황 검색 -->
|
||||
<if test="search_inspection_status != null and search_inspection_status != ''">
|
||||
<if test="search_inspection_status == '완료'">
|
||||
AND DEFECT.DEFECT_TOTAL_COUNT > 0 AND DEFECT.DEFECT_TOTAL_COUNT = DEFECT.ACTION_RESULT_COUNT
|
||||
</if>
|
||||
<if test="search_inspection_status == '진행중'">
|
||||
AND DEFECT.ACTION_RESULT_COUNT > 0 AND DEFECT.DEFECT_TOTAL_COUNT != DEFECT.ACTION_RESULT_COUNT
|
||||
</if>
|
||||
</if>
|
||||
ORDER BY POM.REGDATE DESC
|
||||
</select>
|
||||
|
||||
@@ -1081,6 +1145,7 @@
|
||||
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
) AS INSPECTION_RESULT
|
||||
, PIM.REMARK
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO F WHERE F.TARGET_OBJID = PIM.OBJID AND F.DOC_TYPE = 'PROCESS_INSPECTION_FILE' AND UPPER(F.STATUS) = 'ACTIVE') AS PROCESS_INSPECTION_FILE_CNT
|
||||
FROM PROCESS_INSPECTION_MASTER PIM
|
||||
WHERE 1=1
|
||||
/* 프로젝트번호 */
|
||||
@@ -1096,23 +1161,23 @@
|
||||
WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
AND PM.PRODUCT = #{productType})
|
||||
</if>
|
||||
/* 품번 */
|
||||
/* 품번 (OBJID 또는 품번 텍스트로 검색) */
|
||||
<if test="search_part_objid != null and search_part_objid != ''">
|
||||
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
|
||||
WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
AND PID.PART_OBJID = #{search_part_objid})
|
||||
AND (PID.PART_OBJID = #{search_part_objid} OR UPPER(PID.PART_NO) LIKE '%' || UPPER(#{search_part_objid}) || '%'))
|
||||
</if>
|
||||
/* 품명 */
|
||||
/* 품명 (LIKE 검색) */
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
|
||||
WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
AND PID.PART_OBJID = #{search_part_name})
|
||||
AND UPPER(PID.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%')
|
||||
</if>
|
||||
/* 작업환경상태 */
|
||||
/* 작업환경상태 (화면 표시 로직과 동일하게: 하나라도 불량이면 불량) */
|
||||
<if test="search_work_env_status != null and search_work_env_status != ''">
|
||||
AND EXISTS (SELECT 1 FROM PROCESS_INSPECTION_DETAIL PID
|
||||
WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
AND PID.WORK_ENV_STATUS = CASE WHEN #{search_work_env_status} = 'OK' THEN '양호' ELSE '불량' END)
|
||||
AND (SELECT CASE WHEN COUNT(CASE WHEN PID.WORK_ENV_STATUS = '불량' THEN 1 END) > 0 THEN '불량' ELSE '양호' END
|
||||
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
) = CASE WHEN #{search_work_env_status} = 'OK' THEN '양호' ELSE '불량' END
|
||||
</if>
|
||||
/* 측정기 */
|
||||
<if test="search_measuring_device != null and search_measuring_device != ''">
|
||||
@@ -1638,6 +1703,7 @@
|
||||
, COALESCE(SPI.WORK_ORDER_NO, '') AS "WORK_ORDER_NO"
|
||||
, COALESCE(SPI.PART_NO, '') AS "PART_NO"
|
||||
, COALESCE(SPI.PART_NAME, '') AS "PART_NAME"
|
||||
, COALESCE(PM.OBJID::VARCHAR, '') AS "PART_OBJID"
|
||||
, COALESCE(SPI.RECEIPT_QTY, 0) AS "RECEIPT_QTY"
|
||||
, COALESCE(SPI.GOOD_QTY, 0) AS "GOOD_QTY"
|
||||
, COALESCE(SPI.DEFECT_QTY, 0) AS "DEFECT_QTY"
|
||||
@@ -1657,6 +1723,7 @@
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = SPI.OBJID AND AFI.DOC_TYPE = 'SEMI_INSPECTION_NCR' AND AFI.STATUS = 'Active') AS "NCR_FILE_CNT"
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = SPI.OBJID AND AFI.DOC_TYPE = 'SEMI_INSPECTION_REPORT' AND AFI.STATUS = 'Active') AS "REPORT_FILE_CNT"
|
||||
FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION SPI
|
||||
LEFT JOIN PART_MNG PM ON PM.PART_NO = SPI.PART_NO
|
||||
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})
|
||||
@@ -1802,6 +1869,13 @@
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 반제품검사 행 잠금 해제 (IS_LOCKED = 'N') -->
|
||||
<update id="unlockSemiProductInspection" parameterType="map">
|
||||
UPDATE PMS_QUALITY_SEMI_PRODUCT_INSPECTION
|
||||
SET IS_LOCKED = 'N'
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 반제품검사 데이터 삭제 (OBJID로 단건 삭제) -->
|
||||
<delete id="deleteSemiProductInspectionByObjId" parameterType="map">
|
||||
DELETE FROM PMS_QUALITY_SEMI_PRODUCT_INSPECTION
|
||||
@@ -2068,6 +2142,8 @@
|
||||
, ECR.COMPLETE_DATE
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = ECR.OBJID AND AFI.DOC_TYPE = 'ECR_RESULT_IMAGE' AND STATUS = 'Active') AS IMAGE_FILE
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = ECR.OBJID AND AFI.DOC_TYPE = 'ECR_RESULT' AND STATUS = 'Active') AS ATTACH_FILE
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = ECR.OBJID AND AFI.DOC_TYPE = 'ECR_DOC' AND STATUS = 'Active') AS ECR_DOC_FILE
|
||||
, CASE WHEN (ECR.ECR_DOC_SUMMARY IS NOT NULL AND ECR.ECR_DOC_SUMMARY != '') OR (ECR.ECR_DOC_REASON IS NOT NULL AND ECR.ECR_DOC_REASON != '') THEN 1 ELSE 0 END AS ECR_DOC_CNT
|
||||
FROM PMS_QUALITY_ECR ECR
|
||||
WHERE 1=1
|
||||
<if test="search_request_date_from != null and search_request_date_from != ''">
|
||||
@@ -2142,6 +2218,12 @@
|
||||
, ECR.REMARK
|
||||
, ECR.WRITER
|
||||
, TO_CHAR(ECR.REG_DATE, 'YYYY-MM-DD') AS REG_DATE
|
||||
, ECR.ECR_DOC_SUMMARY
|
||||
, ECR.ECR_DOC_REASON
|
||||
, ECR.ECR_REV_NO
|
||||
, ECR.ECR_REV_DATE
|
||||
, ECR.ECR_DOC_FORM_NO
|
||||
, ECR.ECR_DOC_AUTHOR
|
||||
FROM PMS_QUALITY_ECR ECR
|
||||
WHERE ECR.OBJID = #{OBJID}
|
||||
</select>
|
||||
@@ -2219,6 +2301,20 @@
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 설계변경요청서 저장 -->
|
||||
<update id="updateEcrDoc" parameterType="map">
|
||||
UPDATE PMS_QUALITY_ECR SET
|
||||
ECR_DOC_FORM_NO = #{ECR_DOC_FORM_NO}
|
||||
, ECR_REV_NO = #{ECR_REV_NO}
|
||||
, ECR_REV_DATE = #{ECR_REV_DATE}
|
||||
, ECR_DOC_AUTHOR = #{ECR_DOC_AUTHOR}
|
||||
, ECR_DOC_SUMMARY = #{ECR_DOC_SUMMARY}
|
||||
, ECR_DOC_REASON = #{ECR_DOC_REASON}
|
||||
, MODIFIER = #{MODIFIER}
|
||||
, MOD_DATE = NOW()
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- =====================================================
|
||||
수입검사 상세 그리드 목록 (입고 결과 기준)
|
||||
===================================================== -->
|
||||
@@ -2259,6 +2355,14 @@
|
||||
, IID.REMARK
|
||||
, IMI.PURCHASE_ORDER_MASTER_OBJID
|
||||
, POM.PURCHASE_ORDER_NO
|
||||
/* 불량수량 합계 (INCOMING_INSPECTION_DETAIL.DEFECT_QTY에 저장된 값 사용) */
|
||||
, COALESCE(NULLIF(IID.DEFECT_QTY, '')::NUMERIC, 0) AS DEFECT_QTY_SUM
|
||||
/* 불량율 (불량수량합계 / 입고수량 * 100) */
|
||||
, CASE WHEN IMI.RECEIPT_QTY::NUMERIC > 0
|
||||
THEN ROUND(COALESCE(NULLIF(IID.DEFECT_QTY, '')::NUMERIC, 0) / IMI.RECEIPT_QTY::NUMERIC * 100, 2)
|
||||
ELSE NULL END AS LEFT_DEFECT_RATE
|
||||
/* 검사성적서 파일 수 */
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = IID.OBJID AND AFI.DOC_TYPE = 'INSPECTION_REPORT' AND UPPER(AFI.STATUS) = 'ACTIVE') AS INSPECTION_FILE_CNT
|
||||
FROM INVENTORY_MGMT_IN IMI
|
||||
INNER JOIN INVENTORY_MGMT IM ON IM.OBJID = IMI.PARENT_OBJID
|
||||
INNER JOIN PART_MNG PM ON PM.OBJID::VARCHAR = IM.PART_OBJID
|
||||
|
||||
@@ -665,6 +665,9 @@ VALUES
|
||||
SRM.PROJECT_NO,
|
||||
PM.PROJECT_NO AS PROJECT_NUMBER,
|
||||
PM.PROJECT_NAME,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
PM.DUE_DATE,
|
||||
COALESCE(
|
||||
PM.OBJID,
|
||||
(SELECT OBJID FROM PROJECT_MGMT WHERE PROJECT_NO = SRM.PROJECT_NO LIMIT 1)
|
||||
@@ -718,9 +721,9 @@ VALUES
|
||||
COALESCE(NULLIF(SRM.AREA_CD, ''), SM.AREA_CD) AS AREA_CD, -- 국내/해외
|
||||
COALESCE(NULLIF(SRM.CUSTOMER_OBJID, ''), SM.OBJID::VARCHAR) AS CUSTOMER_OBJID, -- 고객사
|
||||
COALESCE(NULLIF(SRM.PAID_TYPE, ''), CM.PAID_TYPE) AS PAID_TYPE, -- 유/무상
|
||||
CM.CATEGORY_CD AS CATEGORY_CD, -- 제품유형 코드 ID (드롭다운 선택용)
|
||||
CM.CATEGORY_CD AS CATEGORY_CD -- 제품유형 코드 ID (드롭다운 선택용)
|
||||
-- 품번/품명: 첫 번째 품목 + 외 N건 형태
|
||||
(SELECT
|
||||
<!-- (SELECT
|
||||
CASE
|
||||
WHEN (SELECT COUNT(*) FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID) > 1 THEN
|
||||
COALESCE((SELECT PM2.PART_NO FROM PART_MNG PM2 WHERE PM2.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)), '') || ' 외 ' || ((SELECT COUNT(*) FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID) - 1)::TEXT || '건'
|
||||
@@ -735,7 +738,7 @@ VALUES
|
||||
ELSE
|
||||
COALESCE((SELECT PM2.PART_NAME FROM PART_MNG PM2 WHERE PM2.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)), '')
|
||||
END
|
||||
) AS PART_NAME
|
||||
) AS PART_NAME -->
|
||||
|
||||
FROM
|
||||
SALES_REQUEST_MASTER SRM
|
||||
@@ -3084,7 +3087,7 @@ UPDATE SET
|
||||
0 AS ORDER_QTY,
|
||||
0 AS ITEM_QTY2,
|
||||
0 AS PRODUCTION_QTY,
|
||||
'' AS PROCESSING_VENDOR,
|
||||
COALESCE(SRP.PROCESSING_VENDOR, '') AS PROCESSING_VENDOR,
|
||||
NULL AS PROCESSING_DEADLINE,
|
||||
NULL AS GRINDING_DEADLINE,
|
||||
-- 구매 관련 컬럼 (SALES_REQUEST_PART에서 조회)
|
||||
@@ -3376,6 +3379,7 @@ ORDER BY V.PATH2
|
||||
NET_QTY = COALESCE(NULLIF(TRIM(#{NET_QTY}::TEXT), '')::NUMERIC, 0),
|
||||
PO_QTY = COALESCE(NULLIF(TRIM(#{PO_QTY}::TEXT), '')::NUMERIC, 0),
|
||||
VENDOR = #{VENDOR_PM},
|
||||
PROCESSING_VENDOR = #{PROCESSING_VENDOR},
|
||||
UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
EDITER = #{EDITER},
|
||||
@@ -3390,6 +3394,7 @@ ORDER BY V.PATH2
|
||||
NET_QTY = COALESCE(NULLIF(TRIM(#{NET_QTY}::TEXT), '')::NUMERIC, 0),
|
||||
PO_QTY = COALESCE(NULLIF(TRIM(#{PO_QTY}::TEXT), '')::NUMERIC, 0),
|
||||
VENDOR_PM = #{VENDOR_PM},
|
||||
PROCESSING_VENDOR = #{PROCESSING_VENDOR},
|
||||
UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
WRITER = #{EDITER}
|
||||
|
||||
@@ -1047,7 +1047,7 @@
|
||||
SELECT 1 FROM shipment_log SL
|
||||
WHERE SL.target_objid = T.PROJECT_NO
|
||||
AND SL.shipping_date IS NOT NULL
|
||||
AND SL.shipping_date >= TO_DATE(#{shippingDateFrom}, 'YYYY-MM-DD')
|
||||
AND SL.shipping_date <![CDATA[>=]]> TO_DATE(#{shippingDateFrom}, 'YYYY-MM-DD')
|
||||
)
|
||||
</if>
|
||||
<if test="shippingDateTo != null and shippingDateTo != ''">
|
||||
@@ -1055,7 +1055,7 @@
|
||||
SELECT 1 FROM shipment_log SL
|
||||
WHERE SL.target_objid = T.PROJECT_NO
|
||||
AND SL.shipping_date IS NOT NULL
|
||||
AND SL.shipping_date <= TO_DATE(#{shippingDateTo}, 'YYYY-MM-DD') + INTERVAL '1 day'
|
||||
AND SL.shipping_date <![CDATA[<=]]> TO_DATE(#{shippingDateTo}, 'YYYY-MM-DD') + INTERVAL '1 day'
|
||||
)
|
||||
</if>
|
||||
<if test="shippingMethod != null and shippingMethod != ''">
|
||||
@@ -1216,7 +1216,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
SELECT 1 FROM shipment_log SL
|
||||
WHERE SL.target_objid = T.PROJECT_NO
|
||||
AND SL.shipping_date IS NOT NULL
|
||||
AND SL.shipping_date >= TO_DATE(#{shippingDateFrom}, 'YYYY-MM-DD')
|
||||
AND SL.shipping_date <![CDATA[>=]]> TO_DATE(#{shippingDateFrom}, 'YYYY-MM-DD')
|
||||
)
|
||||
</if>
|
||||
<if test="shippingDateTo != null and shippingDateTo != ''">
|
||||
@@ -1224,7 +1224,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
|
||||
SELECT 1 FROM shipment_log SL
|
||||
WHERE SL.target_objid = T.PROJECT_NO
|
||||
AND SL.shipping_date IS NOT NULL
|
||||
AND SL.shipping_date <= TO_DATE(#{shippingDateTo}, 'YYYY-MM-DD') + INTERVAL '1 day'
|
||||
AND SL.shipping_date <![CDATA[<=]]> TO_DATE(#{shippingDateTo}, 'YYYY-MM-DD') + INTERVAL '1 day'
|
||||
)
|
||||
</if>
|
||||
<if test="shippingMethod != null and shippingMethod != ''">
|
||||
|
||||
@@ -1924,6 +1924,7 @@ public class ContractMgmtService {
|
||||
boolean mailSent = false;
|
||||
try {
|
||||
// UTF-8 인코딩 메서드 사용 (견적서는 한글 내용이 많음)
|
||||
// 영업팀 계정(SALES) 사용
|
||||
mailSent = MailUtil.sendMailWithAttachFileUTF8(
|
||||
fromUserId,
|
||||
null, // fromEmail (자동으로 SMTP 설정 사용)
|
||||
@@ -1936,7 +1937,8 @@ public class ContractMgmtService {
|
||||
contents,
|
||||
attachFileList.size() > 0 ? attachFileList : null, // PDF 첨부
|
||||
"CONTRACT_ESTIMATE",
|
||||
subjectForLog // mail_log용 제목 (OBJID 포함)
|
||||
subjectForLog, // mail_log용 제목 (OBJID 포함)
|
||||
Constants.Mail.ACCOUNT_TYPE_SALES // 영업팀 계정 사용
|
||||
);
|
||||
|
||||
System.out.println("메일 발송 결과: " + mailSent);
|
||||
@@ -3633,6 +3635,7 @@ private String encodeImageToBase64(String imagePath) {
|
||||
|
||||
boolean mailSent = false;
|
||||
try {
|
||||
// 영업팀 계정(SALES) 사용
|
||||
mailSent = MailUtil.sendMailWithAttachFileUTF8(
|
||||
fromUserId,
|
||||
null, // fromEmail (자동으로 SMTP 설정 사용)
|
||||
@@ -3645,7 +3648,8 @@ private String encodeImageToBase64(String imagePath) {
|
||||
htmlContents,
|
||||
attachFileList.size() > 0 ? attachFileList : null,
|
||||
"CONTRACT_ESTIMATE",
|
||||
subjectForLog // mail_log용 제목 (OBJID 포함)
|
||||
subjectForLog, // mail_log용 제목 (OBJID 포함)
|
||||
Constants.Mail.ACCOUNT_TYPE_SALES // 영업팀 계정 사용
|
||||
);
|
||||
|
||||
System.out.println("메일 발송 결과: " + mailSent);
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.pms.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -1758,4 +1759,461 @@ public class ProductionPlanningService {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 목록 조회
|
||||
*/
|
||||
public List getProdResultList(Map<String, Object> paramMap) {
|
||||
List resultList = new ArrayList();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
resultList = sqlSession.selectList("productionplanning.getProdResultList", paramMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 저장 (리스트)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean saveProdResultList(Map<String, Object> paramMap) {
|
||||
boolean result = false;
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
String projectObjid = CommonUtils.nullToEmpty((String)paramMap.get("projectObjid"));
|
||||
String userId = CommonUtils.nullToEmpty((String)paramMap.get("userId"));
|
||||
List<Map<String, Object>> resultList = (List<Map<String, Object>>)paramMap.get("resultList");
|
||||
|
||||
if(resultList != null && resultList.size() > 0) {
|
||||
for(Map<String, Object> row : resultList) {
|
||||
row.put("PROJECT_OBJID", projectObjid);
|
||||
row.put("userId", userId);
|
||||
|
||||
String objid = CommonUtils.nullToEmpty((String)row.get("OBJID"));
|
||||
if("".equals(objid)) {
|
||||
// 신규 등록
|
||||
row.put("OBJID", CommonUtils.createObjId());
|
||||
sqlSession.insert("productionplanning.insertProdResult", row);
|
||||
} else {
|
||||
// 수정
|
||||
sqlSession.update("productionplanning.updateProdResult", row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
result = true;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
if(sqlSession != null) {
|
||||
sqlSession.rollback();
|
||||
}
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 기준 반제품 소요량 조회
|
||||
* - 여러 M-BOM을 입력받아 범주가 '부품', '조립품'인 항목만 조회
|
||||
* - 동일 품번은 합산하여 반환
|
||||
* @param paramMap - mbomItems: [{mbomObjid, qty}, ...]
|
||||
* @return 품번별 합산된 소요량 목록
|
||||
*/
|
||||
public List getSemiProductRequirementList(Map paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
List resultList = new ArrayList();
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
// 입력받은 M-BOM 목록
|
||||
List<Map<String, Object>> mbomItems = (List<Map<String, Object>>) paramMap.get("mbomItems");
|
||||
if(mbomItems == null || mbomItems.isEmpty()) {
|
||||
return resultList;
|
||||
}
|
||||
|
||||
// 품번별 소요량을 합산하기 위한 Map (key: PART_NO, value: {품번정보, 소요량합계})
|
||||
Map<String, Map<String, Object>> partNoMap = new LinkedHashMap<>();
|
||||
|
||||
// 각 M-BOM별로 조회하여 합산
|
||||
for(Map<String, Object> mbomItem : mbomItems) {
|
||||
String mbomObjid = CommonUtils.nullToEmpty((String)mbomItem.get("mbomObjid"));
|
||||
int inputQty = 0;
|
||||
Object qtyObj = mbomItem.get("qty");
|
||||
if(qtyObj != null) {
|
||||
if(qtyObj instanceof Number) {
|
||||
inputQty = ((Number)qtyObj).intValue();
|
||||
} else {
|
||||
try {
|
||||
inputQty = Integer.parseInt(qtyObj.toString());
|
||||
} catch(NumberFormatException e) {
|
||||
inputQty = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if("".equals(mbomObjid) || inputQty <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// M-BOM 항목 조회 (범주가 '부품', '조립품'인 것만)
|
||||
Map<String, Object> queryParam = new HashMap<>();
|
||||
queryParam.put("mbomHeaderObjid", mbomObjid);
|
||||
List<Map<String, Object>> bomItems = sqlSession.selectList("productionplanning.getMbomSemiProductItems", queryParam);
|
||||
|
||||
// 소요량 합산 (PostgreSQL은 소문자 키로 반환)
|
||||
for(Map<String, Object> bomItem : bomItems) {
|
||||
String partNo = CommonUtils.nullToEmpty((String)bomItem.get("part_no"));
|
||||
if("".equals(partNo)) continue;
|
||||
|
||||
// M-BOM의 항목수량
|
||||
int itemQty = 0;
|
||||
Object itemQtyObj = bomItem.get("item_qty");
|
||||
if(itemQtyObj != null) {
|
||||
if(itemQtyObj instanceof Number) {
|
||||
itemQty = ((Number)itemQtyObj).intValue();
|
||||
} else {
|
||||
try {
|
||||
itemQty = Integer.parseInt(itemQtyObj.toString());
|
||||
} catch(NumberFormatException e) {
|
||||
itemQty = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 소요량 = 입력수량 × 항목수량
|
||||
int requiredQty = inputQty * itemQty;
|
||||
|
||||
if(partNoMap.containsKey(partNo)) {
|
||||
// 기존 품번이면 소요량만 합산
|
||||
Map<String, Object> existingItem = partNoMap.get(partNo);
|
||||
int existingQty = (Integer)existingItem.get("REQUIRED_QTY");
|
||||
existingItem.put("REQUIRED_QTY", existingQty + requiredQty);
|
||||
} else {
|
||||
// 새로운 품번이면 추가
|
||||
Map<String, Object> newItem = new LinkedHashMap<>();
|
||||
newItem.put("PART_NO", partNo);
|
||||
newItem.put("PART_NAME", bomItem.get("part_name"));
|
||||
newItem.put("CATEGORY_NAME", bomItem.get("category_name"));
|
||||
newItem.put("UNIT", bomItem.get("unit"));
|
||||
newItem.put("MATERIAL", bomItem.get("material"));
|
||||
newItem.put("SPEC", bomItem.get("spec"));
|
||||
newItem.put("REQUIRED_QTY", requiredQty);
|
||||
partNoMap.put(partNo, newItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Map -> List 변환
|
||||
resultList = new ArrayList(partNoMap.values());
|
||||
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* M-BOM 기준 원자재(구매품 + 원소재) 소요량 조회
|
||||
* - 여러 M-BOM을 입력받아 PART_TYPE이 '0000063'(구매품)인 항목 조회
|
||||
* - RAW_MATERIAL_PART_NO가 있는 항목은 "원소재"로 별도 조회
|
||||
* - 동일 품번은 합산하여 반환
|
||||
* @param paramMap - mbomItems: [{mbomObjid, qty}, ...]
|
||||
* @return 품번별 합산된 소요량 목록
|
||||
*/
|
||||
public List getRawMaterialRequirementList(Map paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
List resultList = new ArrayList();
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
// 입력받은 M-BOM 목록
|
||||
List<Map<String, Object>> mbomItems = (List<Map<String, Object>>) paramMap.get("mbomItems");
|
||||
if(mbomItems == null || mbomItems.isEmpty()) {
|
||||
return resultList;
|
||||
}
|
||||
|
||||
// 구매품 품번별 소요량 Map
|
||||
Map<String, Map<String, Object>> purchasePartNoMap = new LinkedHashMap<>();
|
||||
// 원소재 품번별 소요량 Map
|
||||
Map<String, Map<String, Object>> rawSourcePartNoMap = new LinkedHashMap<>();
|
||||
|
||||
// 각 M-BOM별로 조회하여 합산
|
||||
for(Map<String, Object> mbomItem : mbomItems) {
|
||||
String mbomObjid = CommonUtils.nullToEmpty((String)mbomItem.get("mbomObjid"));
|
||||
int inputQty = 0;
|
||||
Object qtyObj = mbomItem.get("qty");
|
||||
if(qtyObj != null) {
|
||||
if(qtyObj instanceof Number) {
|
||||
inputQty = ((Number)qtyObj).intValue();
|
||||
} else {
|
||||
try {
|
||||
inputQty = Integer.parseInt(qtyObj.toString());
|
||||
} catch(NumberFormatException e) {
|
||||
inputQty = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if("".equals(mbomObjid) || inputQty <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, Object> queryParam = new HashMap<>();
|
||||
queryParam.put("mbomHeaderObjid", mbomObjid);
|
||||
|
||||
// 1. 구매품 조회
|
||||
List<Map<String, Object>> purchaseItems = sqlSession.selectList("productionplanning.getMbomRawMaterialItems", queryParam);
|
||||
for(Map<String, Object> bomItem : purchaseItems) {
|
||||
String partNo = CommonUtils.nullToEmpty((String)bomItem.get("part_no"));
|
||||
if("".equals(partNo)) continue;
|
||||
|
||||
int itemQty = getIntValue(bomItem.get("item_qty"));
|
||||
int requiredQty = inputQty * itemQty;
|
||||
|
||||
if(purchasePartNoMap.containsKey(partNo)) {
|
||||
Map<String, Object> existingItem = purchasePartNoMap.get(partNo);
|
||||
int existingQty = (Integer)existingItem.get("REQUIRED_QTY");
|
||||
existingItem.put("REQUIRED_QTY", existingQty + requiredQty);
|
||||
} else {
|
||||
Map<String, Object> newItem = new LinkedHashMap<>();
|
||||
newItem.put("PART_NO", partNo);
|
||||
newItem.put("PART_NAME", bomItem.get("part_name"));
|
||||
newItem.put("CATEGORY_NAME", bomItem.get("category_name"));
|
||||
newItem.put("UNIT", bomItem.get("unit"));
|
||||
// 구매품은 소재 관련 컬럼 전부 빈값
|
||||
newItem.put("MATERIAL", "");
|
||||
newItem.put("SPEC", "");
|
||||
newItem.put("REQUIRED_QTY", requiredQty);
|
||||
newItem.put("RAW_MATERIAL", "");
|
||||
newItem.put("RAW_MATERIAL_SIZE", "");
|
||||
newItem.put("MATERIAL_PART_NO", "");
|
||||
newItem.put("MATERIAL_REQUIRED_QTY", "");
|
||||
purchasePartNoMap.put(partNo, newItem);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 원소재 조회 (RAW_MATERIAL_PART_NO가 있는 항목)
|
||||
// 원소재는 소재품번 기준으로 합산 (소수점 합산 후 올림)
|
||||
List<Map<String, Object>> rawSourceItems = sqlSession.selectList("productionplanning.getMbomRawSourceItems", queryParam);
|
||||
for(Map<String, Object> bomItem : rawSourceItems) {
|
||||
String materialPartNo = CommonUtils.nullToEmpty((String)bomItem.get("raw_material_part_no"));
|
||||
if("".equals(materialPartNo)) continue;
|
||||
|
||||
double itemQty = getDoubleValue(bomItem.get("item_qty"));
|
||||
double requiredQty = inputQty * itemQty;
|
||||
|
||||
if(rawSourcePartNoMap.containsKey(materialPartNo)) {
|
||||
Map<String, Object> existingItem = rawSourcePartNoMap.get(materialPartNo);
|
||||
double existingQty = (Double)existingItem.get("MATERIAL_REQUIRED_QTY_RAW");
|
||||
existingItem.put("MATERIAL_REQUIRED_QTY_RAW", existingQty + requiredQty);
|
||||
} else {
|
||||
Map<String, Object> newItem = new LinkedHashMap<>();
|
||||
// 원소재는 품번, 품명, 소요량 빈값
|
||||
newItem.put("PART_NO", "");
|
||||
newItem.put("PART_NAME", "");
|
||||
newItem.put("CATEGORY_NAME", "원소재");
|
||||
newItem.put("UNIT", "");
|
||||
newItem.put("MATERIAL", bomItem.get("raw_material"));
|
||||
newItem.put("SPEC", bomItem.get("raw_material_size"));
|
||||
newItem.put("REQUIRED_QTY", "");
|
||||
// 원소재 관련 컬럼만 표시
|
||||
newItem.put("RAW_MATERIAL", bomItem.get("raw_material"));
|
||||
newItem.put("RAW_MATERIAL_SIZE", bomItem.get("raw_material_size"));
|
||||
newItem.put("MATERIAL_PART_NO", materialPartNo);
|
||||
newItem.put("MATERIAL_REQUIRED_QTY_RAW", requiredQty); // 합산용 (소수점)
|
||||
rawSourcePartNoMap.put(materialPartNo, newItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 구매품 먼저 추가
|
||||
resultList.addAll(purchasePartNoMap.values());
|
||||
|
||||
// 원소재는 소수점 합산 후 올림 처리하여 추가
|
||||
for(Map<String, Object> item : rawSourcePartNoMap.values()) {
|
||||
double rawQty = (Double)item.get("MATERIAL_REQUIRED_QTY_RAW");
|
||||
int ceilQty = (int)Math.ceil(rawQty); // 올림 처리
|
||||
item.put("MATERIAL_REQUIRED_QTY", ceilQty);
|
||||
item.remove("MATERIAL_REQUIRED_QTY_RAW"); // 임시 필드 제거
|
||||
resultList.add(item);
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object를 int로 변환하는 유틸 메서드
|
||||
*/
|
||||
private int getIntValue(Object obj) {
|
||||
if(obj == null) return 0;
|
||||
if(obj instanceof Number) {
|
||||
return ((Number)obj).intValue();
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(obj.toString());
|
||||
} catch(NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Object를 double로 변환하는 유틸 메서드
|
||||
*/
|
||||
private double getDoubleValue(Object obj) {
|
||||
if(obj == null) return 0.0;
|
||||
if(obj instanceof Number) {
|
||||
return ((Number)obj).doubleValue();
|
||||
}
|
||||
try {
|
||||
return Double.parseDouble(obj.toString());
|
||||
} catch(NumberFormatException e) {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 날짜별 조회
|
||||
*/
|
||||
public List getProdResultListByDate(Map<String, Object> paramMap) {
|
||||
List resultList = new ArrayList();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
resultList = sqlSession.selectList("productionplanning.getProdResultListByDate", paramMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 날짜별 저장
|
||||
* - 기존 데이터 전체 삭제 후 새로 입력
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean saveProdResultByDate(Map<String, Object> paramMap) {
|
||||
boolean result = false;
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
String projectObjid = CommonUtils.nullToEmpty((String)paramMap.get("projectObjid"));
|
||||
String userId = CommonUtils.nullToEmpty((String)paramMap.get("userId"));
|
||||
String userName = CommonUtils.nullToEmpty((String)paramMap.get("userName"));
|
||||
List<Map<String, Object>> resultList = (List<Map<String, Object>>)paramMap.get("resultList");
|
||||
|
||||
// 기존 데이터 전체 삭제
|
||||
Map<String, Object> deleteParam = new HashMap<String, Object>();
|
||||
deleteParam.put("projectObjid", projectObjid);
|
||||
sqlSession.delete("productionplanning.deleteProdResultByProject", deleteParam);
|
||||
|
||||
// 새로 입력 (행별로 ROW_SEQ 부여)
|
||||
if(resultList != null && resultList.size() > 0) {
|
||||
int rowSeq = 1; // 행 순번
|
||||
for(Map<String, Object> row : resultList) {
|
||||
String resultDate = CommonUtils.nullToEmpty((String)row.get("RESULT_DATE"));
|
||||
if("".equals(resultDate)) continue;
|
||||
|
||||
int assemblyQty = getIntValue(row.get("ASSEMBLY_QTY"));
|
||||
int inspectionQty = getIntValue(row.get("INSPECTION_QTY"));
|
||||
int shipWaitQty = getIntValue(row.get("SHIP_WAIT_QTY"));
|
||||
String remark = CommonUtils.nullToEmpty((String)row.get("REMARK"));
|
||||
|
||||
// 완조립 수량 입력 (0이어도 입력)
|
||||
Map<String, Object> insertParam = new HashMap<String, Object>();
|
||||
insertParam.put("OBJID", CommonUtils.createObjId());
|
||||
insertParam.put("PROJECT_OBJID", projectObjid);
|
||||
insertParam.put("RESULT_TYPE", "ASSEMBLY");
|
||||
insertParam.put("RESULT_DATE", resultDate);
|
||||
insertParam.put("RESULT_QTY", assemblyQty);
|
||||
insertParam.put("ROW_SEQ", rowSeq);
|
||||
insertParam.put("WORKER_NAME", userName);
|
||||
insertParam.put("REMARK", remark);
|
||||
insertParam.put("userId", userId);
|
||||
sqlSession.insert("productionplanning.insertProdResult", insertParam);
|
||||
|
||||
// 검사 수량 입력 (0이어도 입력)
|
||||
insertParam = new HashMap<String, Object>();
|
||||
insertParam.put("OBJID", CommonUtils.createObjId());
|
||||
insertParam.put("PROJECT_OBJID", projectObjid);
|
||||
insertParam.put("RESULT_TYPE", "INSPECTION");
|
||||
insertParam.put("RESULT_DATE", resultDate);
|
||||
insertParam.put("RESULT_QTY", inspectionQty);
|
||||
insertParam.put("ROW_SEQ", rowSeq);
|
||||
insertParam.put("WORKER_NAME", userName);
|
||||
insertParam.put("REMARK", remark);
|
||||
insertParam.put("userId", userId);
|
||||
sqlSession.insert("productionplanning.insertProdResult", insertParam);
|
||||
|
||||
// 출하대기 수량 입력 (0이어도 입력)
|
||||
insertParam = new HashMap<String, Object>();
|
||||
insertParam.put("OBJID", CommonUtils.createObjId());
|
||||
insertParam.put("PROJECT_OBJID", projectObjid);
|
||||
insertParam.put("RESULT_TYPE", "SHIP_WAIT");
|
||||
insertParam.put("RESULT_DATE", resultDate);
|
||||
insertParam.put("RESULT_QTY", shipWaitQty);
|
||||
insertParam.put("ROW_SEQ", rowSeq);
|
||||
insertParam.put("WORKER_NAME", userName);
|
||||
insertParam.put("REMARK", remark);
|
||||
insertParam.put("userId", userId);
|
||||
sqlSession.insert("productionplanning.insertProdResult", insertParam);
|
||||
|
||||
rowSeq++; // 다음 행
|
||||
}
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
result = true;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
if(sqlSession != null) {
|
||||
sqlSession.rollback();
|
||||
}
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1086,6 +1086,46 @@ public class QualityService extends BaseService{
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 반제품검사 행 잠금 해제 (IS_LOCKED = 'N')
|
||||
*/
|
||||
public Map unlockSemiProductInspection(Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
String objIdsJson = CommonUtils.checkNull(paramMap.get("objIds"));
|
||||
|
||||
if(!objIdsJson.equals("") && !objIdsJson.equals("[]")){
|
||||
org.json.simple.parser.JSONParser parser = new org.json.simple.parser.JSONParser();
|
||||
org.json.simple.JSONArray objIdArr = (org.json.simple.JSONArray) parser.parse(objIdsJson);
|
||||
|
||||
for(int i = 0; i < objIdArr.size(); i++){
|
||||
String objId = CommonUtils.checkNull(objIdArr.get(i));
|
||||
if(!objId.equals("")){
|
||||
Map unlockParam = new HashMap();
|
||||
unlockParam.put("OBJID", objId);
|
||||
sqlSession.update("quality.unlockSemiProductInspection", unlockParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
resultMap.put("result", true);
|
||||
resultMap.put("msg", "잠금 해제되었습니다.");
|
||||
|
||||
}catch(Exception e){
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("msg", "잠금 해제에 실패했습니다.");
|
||||
if(sqlSession != null) sqlSession.rollback();
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 반제품검사 삭제 (OBJID 목록으로 삭제)
|
||||
*/
|
||||
@@ -1674,6 +1714,39 @@ public class QualityService extends BaseService{
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 설계변경요청서 저장
|
||||
*/
|
||||
public Map saveEcrDoc(HttpServletRequest request, Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
// 작성자 정보 설정
|
||||
PersonBean person = (PersonBean) request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
String writer = person != null ? person.getUserId() : "";
|
||||
paramMap.put("MODIFIER", writer);
|
||||
|
||||
sqlSession.update("quality.updateEcrDoc", paramMap);
|
||||
|
||||
sqlSession.commit();
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("message", "저장되었습니다.");
|
||||
|
||||
}catch(Exception e){
|
||||
if(sqlSession != null) sqlSession.rollback();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", e.getMessage());
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/*edhwang start*/
|
||||
|
||||
/*edhwang end*/
|
||||
@@ -1733,6 +1806,8 @@ public class QualityService extends BaseService{
|
||||
sqlParamMap.put("INSPECTION_TYPE", CommonUtils.checkNull(data.get("INSPECTION_TYPE")));
|
||||
sqlParamMap.put("INSPECTION_DATE", inspectionDate);
|
||||
sqlParamMap.put("INSPECTOR_ID", inspectorId);
|
||||
sqlParamMap.put("INSPECTION_QTY", CommonUtils.checkNull(data.get("INSPECTION_QTY"))); // 검사수량
|
||||
sqlParamMap.put("DEFECT_QTY", CommonUtils.checkNull(data.get("DEFECT_QTY_SUM"))); // 불량수량 합계
|
||||
sqlParamMap.put("WRITER", writer);
|
||||
|
||||
sqlSession.update("quality.saveIncomingInspectionDetail", sqlParamMap);
|
||||
@@ -1748,7 +1823,7 @@ public class QualityService extends BaseService{
|
||||
|
||||
for(Map defect : defectList) {
|
||||
String gridStatus = CommonUtils.checkNull(defect.get("GRID_STATUS"));
|
||||
|
||||
|
||||
Map sqlParamMap = new HashMap();
|
||||
sqlParamMap.put("OBJID", CommonUtils.checkNull(defect.get("OBJID")));
|
||||
sqlParamMap.put("INSPECTION_DETAIL_OBJID", selectedDetailObjid);
|
||||
@@ -1764,7 +1839,7 @@ public class QualityService extends BaseService{
|
||||
sqlParamMap.put("INSPECTION_RESULT", CommonUtils.checkNull(defect.get("INSPECTION_RESULT")));
|
||||
sqlParamMap.put("REMARK", CommonUtils.checkNull(defect.get("REMARK")));
|
||||
sqlParamMap.put("WRITER", writer);
|
||||
|
||||
|
||||
if("D".equals(gridStatus)) {
|
||||
// 삭제
|
||||
sqlSession.delete("quality.deleteIncomingInspectionDefect", sqlParamMap);
|
||||
|
||||
Reference in New Issue
Block a user