Compare commits

..

13 Commits

25 changed files with 1067 additions and 369 deletions

View File

@@ -3969,6 +3969,17 @@
ORDER BY REGDATE DESC, MBOM_NO
</select>
<!-- M-BOM 목록 (품명 포함, 원자재소요량/반제품소요량용) -->
<select id="getMbomListWithPartName" parameterType="map" resultType="com.pms.common.UpperKeyMap">
SELECT
OBJID,
MBOM_NO,
COALESCE(PART_NAME, '') AS PART_NAME
FROM MBOM_HEADER
WHERE STATUS = 'Y'
ORDER BY REGDATE DESC, MBOM_NO
</select>
<!-- M-BOM 헤더 정보 조회 (OBJID로) -->
<select id="getMbomHeaderByObjid" parameterType="map" resultType="com.pms.common.UpperKeyMap">
SELECT
@@ -4500,9 +4511,9 @@
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,
0 AS ASSEMBLY_QTY,
0 AS INSPECTION_QTY,
0 AS SHIP_WAIT_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
@@ -4550,9 +4561,9 @@
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,
0 AS ASSEMBLY_QTY,
0 AS INSPECTION_QTY,
0 AS SHIP_WAIT_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
@@ -4610,31 +4621,54 @@
ORDER BY T.SORT_DATE DESC, T.PROJECT_NO DESC
</select>
<!-- 프로젝트 정보 조회 (생산계획 폼용) -->
<!-- 프로젝트 정보 조회 (생산계획 폼용) - PROJECT_MGMT 또는 PRODUCTION_PLAN에서 조회 -->
<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)
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}
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>
@@ -4754,6 +4788,7 @@
RESULT_TYPE,
RESULT_DATE,
RESULT_QTY,
ROW_SEQ,
SERIAL_NO,
WORKER_ID,
WORKER_NAME,
@@ -4767,6 +4802,7 @@
#{RESULT_TYPE},
#{RESULT_DATE},
#{RESULT_QTY},
#{ROW_SEQ},
#{SERIAL_NO},
#{userId},
#{WORKER_NAME},
@@ -4860,4 +4896,40 @@
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>

View File

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

View File

@@ -41,6 +41,12 @@
.select2-container .select2-selection--multiple .select2-selection__rendered {
overflow: auto !important;
}
body, html {
overflow-x: hidden;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script>
@@ -48,6 +54,9 @@
$('.select2').select2();
fnc_datepick();
// 품번/품명 Select2 AJAX 초기화
initPartSelect2Ajax("#part_no", "#part_name", "#search_part_objid");
//엔터키로 조회
$("input").keyup(function(e){
if(e.keyCode == 13){
@@ -101,8 +110,8 @@
{title:"자재목록", headerHozAlign:'center',
//frozen:false,
columns:[
{headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '프로젝트번호', field : 'PROJECT_NO' },
{headerHozAlign : 'center', hozAlign : 'left', width : '200', title : '유닛명', field : 'UNIT_NAME' },
{headerHozAlign : 'center', hozAlign : 'left', width : '130', title : '프로젝트번호', field : 'PROJECT_NO' },
//{headerHozAlign : 'center', hozAlign : 'left', width : '200', title : '유닛명', field : 'UNIT_NAME' },
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품번', field : 'PART_NO' },
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'PART_NAME' },
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '재질', field : 'MATERIAL' },
@@ -369,10 +378,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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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">

View File

@@ -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>

View File

@@ -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) {
@@ -717,13 +720,18 @@ function fn_openPurchaseListPopup() {
<!-- 품번 -->
<div style="display: flex; align-items: center; gap: 5px;">
<label for="search_part_no">품번</label>
<input type="text" name="search_part_no" id="search_part_no" value="" style="width:150px;">
<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>
<input type="text" name="search_part_name" id="search_part_name" value="" style="width:150px;">
<select name="search_part_name" id="search_part_name" class="select2-part" style="width:150px;">
<option value="">품명 선택</option>
</select>
</div>
<!-- 접수일 -->

View File

@@ -35,6 +35,9 @@ $(function(){
fnc_datepick();
$(".select2").select2();
// 품번/품명 Select2 AJAX 초기화
initPartSelect2();
// 저장 버튼
$("#btnSave").click(function(){
fn_save();
@@ -74,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");
@@ -136,11 +227,19 @@ function fn_loadProjectInfo(projectObjid){
$("#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));
@@ -171,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("");
@@ -353,11 +453,22 @@ 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>

View File

@@ -13,40 +13,107 @@
<title><%=Constants.SYSTEM_NAME%></title>
<style>
.input_title {border-left:1px solid #ccc; background-color:#f5f5f5; font-weight:bold;}
.pmsPopupForm tr:last-child td{border-bottom:1px solid #ccc;}
.pmsPopupForm td { padding: 5px 8px; }
.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" src="/js/tabulator/tabulator_custom.js"></script>
<script>
var grid;
<script type="text/javascript">
var _projectObjid = "${param.projectObjid}";
var _resultType = "${param.resultType}";
// 실적유형 목록
var _RESULT_TYPE_LIST = [
{"CODE": "ASSEMBLY", "NAME": "완조립"},
{"CODE": "INSPECTION", "NAME": "검사"},
{"CODE": "SHIP_WAIT", "NAME": "출하대기"}
];
var _rowIndex = 0;
$(function(){
fnc_datepick();
$(".select2").select2();
// 프로젝트 정보 로드
if(_projectObjid) {
fn_loadProjectInfo();
}
// 그리드 초기화
fn_initGrid();
// 실적 목록 조회
fn_search();
@@ -55,11 +122,6 @@ $(function(){
fn_addRow();
});
// 행삭제 버튼
$("#btnDelRow").click(function(){
fn_delRow();
});
// 저장 버튼
$("#btnSave").click(function(){
fn_save();
@@ -68,14 +130,13 @@ $(function(){
// 날짜 선택기 초기화
function fnc_datepick(){
var $dateinput = $("input.date_icon");
for(var i=0; i<$dateinput.length; i++){
$dateinput.eq(i).attr("size","10");
$dateinput.eq(i).datepicker({
changeMonth:true,
changeYear:true
$(document).on('focus', '.date-input', function(){
$(this).datepicker({
changeMonth: true,
changeYear: true,
dateFormat: 'yy-mm-dd'
});
}
});
}
// 프로젝트 정보 로드
@@ -87,136 +148,152 @@ function fn_loadProjectInfo() {
dataType: "json",
async: false,
success: function(data){
console.log("프로젝트 정보 응답:", data);
if(data && data.result == "success" && data.info){
var info = data.info;
$("#PROJECT_NO").text(fnc_checkNull(info.project_no));
$("#PART_NO").text(fnc_checkNull(info.part_no));
$("#PART_NAME").text(fnc_checkNull(info.part_name));
$("#ORDER_QTY").text(fnc_checkNull(info.order_qty));
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);
}
});
}
// 그리드 컬럼 정의
var columns = [
{formatter:"rowSelection", titleFormatter:"rowSelection", headerHozAlign:'center', hozAlign:"center", headerSort:false, width:30},
{title:'OBJID', field:'OBJID', visible: false},
{title:'실적유형', field:'RESULT_TYPE', headerHozAlign:'center', hozAlign:'center', width:100,
editor: "list",
editorParams: {
values: {"ASSEMBLY":"완조립", "INSPECTION":"검사", "SHIP_WAIT":"출하대기"}
},
formatter: function(cell) {
var val = cell.getValue();
if(val == 'ASSEMBLY') return '완조립';
if(val == 'INSPECTION') return '검사';
if(val == 'SHIP_WAIT') return '출하대기';
return val;
}
},
{title:'실적일자', field:'RESULT_DATE', headerHozAlign:'center', hozAlign:'center', width:110,
editor: "input"
},
{title:'실적수량', field:'RESULT_QTY', headerHozAlign:'center', hozAlign:'right', width:90,
editor: "number",
formatter: "money", formatterParams: {thousand:",", precision:false}
},
{title:'S/N', field:'SERIAL_NO', headerHozAlign:'center', hozAlign:'left', width:120,
editor: "input"
},
{title:'작업자', field:'WORKER_NAME', headerHozAlign:'center', hozAlign:'center', width:100,
editor: "input"
},
{title:'비고', field:'REMARK', headerHozAlign:'center', hozAlign:'left', minWidth:150,
editor: "input"
}
];
// 그리드 초기화
function fn_initGrid() {
grid = new Tabulator("#grid", {
layout: "fitColumns",
height: "calc(100vh - 200px)",
columns: columns,
data: [],
selectableRows: true,
placeholder: "데이터가 없습니다."
});
// 숫자 포맷팅
function fnc_formatNumber(num) {
if(num == null || num == '') return '0';
return parseInt(num).toLocaleString();
}
// 실적 목록 조회
function fn_search() {
var params = {
projectObjid: _projectObjid,
resultType: _resultType
projectObjid: _projectObjid
};
$.ajax({
url: "/productionplanning/getProdResultList.do",
url: "/productionplanning/getProdResultListByDate.do",
type: "POST",
data: params,
dataType: "json",
success: function(data){
if(data && data.list) {
grid.setData(data.list);
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() {
var newRow = {
OBJID: '',
RESULT_TYPE: _resultType || 'ASSEMBLY',
RESULT_DATE: '${today}',
RESULT_QTY: '',
SERIAL_NO: '',
WORKER_NAME: '${connectUserName}',
REMARK: ''
};
grid.addRow(newRow);
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_delRow() {
var selectedRows = grid.getSelectedRows();
if(selectedRows.length === 0) {
Swal.fire('삭제할 행을 선택해주세요.');
return;
}
function fn_deleteRow(rowIndex) {
$("#row_" + rowIndex).remove();
fn_updateTotals();
}
// 총수량 업데이트
function fn_updateTotals() {
var totalAssembly = 0;
var totalInspection = 0;
var totalShipWait = 0;
selectedRows.forEach(function(row) {
row.delete();
$(".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 allData = grid.getData();
var resultList = [];
if(allData.length === 0) {
$("#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 < allData.length; i++) {
var row = allData[i];
if(!row.RESULT_TYPE) {
Swal.fire('실적유형을 선택해주세요. (행 ' + (i+1) + ')');
return;
}
for(var i = 0; i < resultList.length; i++) {
var row = resultList[i];
if(!row.RESULT_DATE) {
Swal.fire('실적일자를 입력해주세요. (행 ' + (i+1) + ')');
return;
}
if(!row.RESULT_QTY || row.RESULT_QTY <= 0) {
Swal.fire('실적수량을 입력해주세요. (행 ' + (i+1) + ')');
Swal.fire('날짜를 입력해주세요. (행 ' + (i+1) + ')');
return;
}
}
@@ -224,12 +301,12 @@ function fn_save() {
if(!confirm('저장하시겠습니까?')) return;
$.ajax({
url: "/productionplanning/saveProdResultList.do",
url: "/productionplanning/saveProdResultByDate.do",
type: "POST",
contentType: "application/json",
data: JSON.stringify({
projectObjid: _projectObjid,
resultList: allData
resultList: resultList
}),
dataType: "json",
success: function(data){
@@ -238,7 +315,7 @@ function fn_save() {
if(opener && opener.fn_search) {
opener.fn_search();
}
fn_search(); // 새로고침
window.close(); // 저장 성공 시 자동 닫기
} else {
Swal.fire(data.msg || "저장에 실패했습니다.");
}
@@ -260,42 +337,77 @@ window.addEventListener('unload', function() {
<body style="overflow-x: hidden;">
<form name="form1" id="form1" method="post">
<input type="hidden" name="PROJECT_OBJID" id="PROJECT_OBJID" value="${param.projectObjid}">
<input type="hidden" name="RESULT_TYPE" id="RESULT_TYPE_HIDDEN" value="${param.resultType}">
<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>
<span style="font-size:20px;">생산실적 등록</span>
</h2>
</div>
<!-- 프로젝트 정보 표시 -->
<div style="padding:10px; background:#f5f5f5; border-bottom:1px solid #ddd;">
<table style="width:100%;">
<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>
<td style="width:70px; font-weight:bold;">프로젝트:</td>
<td style="width:150px;"><span id="PROJECT_NO">-</span></td>
<td style="width:50px; font-weight:bold;">품번:</td>
<td style="width:150px;"><span id="PART_NO">-</span></td>
<td style="width:50px; font-weight:bold;">품명:</td>
<td><span id="PART_NAME">-</span></td>
<td style="width:70px; font-weight:bold;">수주수량:</td>
<td style="width:70px;"><span id="ORDER_QTY">-</span></td>
<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">
<h2><span>실적록</span></h2>
<div class="btnArea">
<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="btnDelRow">
<input type="button" value="저장" class="plm_btns" id="btnSave">
<input type="button" value="닫기" class="plm_btns" onclick="window.close();">
</div>
</div>
<div id="grid" style="margin: 10px;"></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>

View File

@@ -46,8 +46,10 @@ var resultGrid;
var grid;
// 입력 행 번호
var rowSeq = 0;
// M-BOM 옵션 데이터
// M-BOM 옵션 데이터 (셀렉트박스용)
var mbomOptionsData = {};
// M-BOM 품명 데이터 (OBJID -> PART_NAME 매핑)
var mbomPartNameData = {};
$(document).ready(function(){
$('.select2').select2();
@@ -87,7 +89,14 @@ function fn_initMbomOptions() {
mbomOptionsData[val] = text;
}
});
// M-BOM 품명 데이터 초기화 (서버에서 전달받은 데이터)
<c:forEach var="item" items="${mbom_part_name_list}">
mbomPartNameData["${item.OBJID}"] = "${item.PART_NAME}";
</c:forEach>
console.log("M-BOM 옵션:", mbomOptionsData);
console.log("M-BOM 품명:", mbomPartNameData);
}
// 입력 그리드 초기화
@@ -136,12 +145,12 @@ function fn_initInputGrid() {
return mbomOptionsData[value] || "";
},
cellEdited: function(cell) {
// M-BOM 선택 시 품명 자동 입력
// M-BOM 선택 시 품명 자동 입력 (MBOM_HEADER.PART_NAME 사용)
var mbomObjid = cell.getValue();
var row = cell.getRow();
if(mbomObjid) {
var mbomName = mbomOptionsData[mbomObjid] || "";
row.update({PART_NAME: mbomName});
var partName = mbomPartNameData[mbomObjid] || "";
row.update({PART_NAME: partName});
} else {
row.update({PART_NAME: ""});
}

View File

@@ -46,8 +46,10 @@ var resultGrid;
var grid;
// 입력 행 번호
var rowSeq = 0;
// M-BOM 옵션 데이터
// M-BOM 옵션 데이터 (셀렉트박스용)
var mbomOptionsData = {};
// M-BOM 품명 데이터 (OBJID -> PART_NAME 매핑)
var mbomPartNameData = {};
$(document).ready(function(){
$('.select2').select2();
@@ -87,7 +89,14 @@ function fn_initMbomOptions() {
mbomOptionsData[val] = text;
}
});
// M-BOM 품명 데이터 초기화 (서버에서 전달받은 데이터)
<c:forEach var="item" items="${mbom_part_name_list}">
mbomPartNameData["${item.OBJID}"] = "${item.PART_NAME}";
</c:forEach>
console.log("M-BOM 옵션:", mbomOptionsData);
console.log("M-BOM 품명:", mbomPartNameData);
}
// 입력 그리드 초기화
@@ -136,12 +145,12 @@ function fn_initInputGrid() {
return mbomOptionsData[value] || "";
},
cellEdited: function(cell) {
// M-BOM 선택 시 품명 자동 입력
// M-BOM 선택 시 품명 자동 입력 (MBOM_HEADER.PART_NAME 사용)
var mbomObjid = cell.getValue();
var row = cell.getRow();
if(mbomObjid) {
var mbomName = mbomOptionsData[mbomObjid] || "";
row.update({PART_NAME: mbomName});
var partName = mbomPartNameData[mbomObjid] || "";
row.update({PART_NAME: partName});
} else {
row.update({PART_NAME: ""});
}

View File

@@ -53,6 +53,9 @@ 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,
@@ -279,12 +282,17 @@ function openProjectFormPopUp(objId){
<td><label for="product_item_code">품번</label></td>
<td>
<input type="text" name="product_item_code" id="product_item_code" style="width:150px;" autocomplete="off" value="${param.product_item_code}">
<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>
<input type="text" name="product_item_name" id="product_item_name" style="width:150px;" autocomplete="off" value="${param.product_item_name}">
<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>

View File

@@ -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");
@@ -86,7 +89,9 @@ $(document).ready(function(){
var columns = [
// 요구사항: 품의서 No, 발주서 No, 프로젝트번호, 품번, 품명, 공급업체, 발주수량, 입고수량, 미입고수량, 검사성적서, 입고결과
{title:'TOTAL_SUPPLY_PRICE' ,field:'TOTAL_SUPPLY_PRICE' ,visible:false, frozen:true},
{title:'TOTAL_DELIVERY_PRICE' ,field:'TOTAL_DELIVERY_PRICE' ,visible:false, frozen:true},
{title:'TOTAL_DELIVERY_PRICE' ,field:'TOTAL_DELIVERY_PRICE' ,visible:false, frozen:true},
{title:'TOTAL_NOT_DELIVERY_PRICE',field:'TOTAL_NOT_DELIVERY_PRICE',visible:false, frozen:true},
{title:'FORM_TYPE' ,field:'FORM_TYPE' ,visible:false, frozen:true},
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 130, widthGrow : 1, title : '품의서 No', field : 'PROPOSAL_NO',
formatter: fnc_createGridAnchorTag,
cellClick : function(e, cell) {
@@ -97,7 +102,8 @@ var columns = [
formatter:fnc_createGridAnchorTag,
cellClick:function(e, cell){
var objId = fnc_checkNull(cell.getData().OBJID);
fn_formPopUp(objId);
var formType = fnc_checkNull(cell.getData().FORM_TYPE, 'general');
fn_formPopUp(objId, formType);
}
},
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 140, widthGrow : 1, title : '프로젝트번호', field : 'PROJECT_NO'},
@@ -179,17 +185,18 @@ function fn_calculateTotalAmount(){
// 현재 그리드에 표시된 데이터 가져오기
var data = _tabulGrid.getData();
var totalOrderAmount = 0; // 총 발주금액
var totalOrderAmount = 0; // 총 발주금액
var totalDeliveredAmount = 0; // 입고금액
var totalNotDeliveredAmount = 0; // 미입고금액
if(data.length > 0) {
data.forEach(function(row) {
var rowTotalPrice = parseFloat(row.TOTAL_SUPPLY_PRICE || 0);
// SQL에서 계산된 값 사용
var rowSupplyPrice = parseFloat(row.TOTAL_SUPPLY_PRICE || 0);
var rowDeliveredPrice = parseFloat(row.TOTAL_DELIVERY_PRICE || 0);
var rowNotDeliveredPrice = rowTotalPrice - rowDeliveredPrice;
var rowNotDeliveredPrice = parseFloat(row.TOTAL_NOT_DELIVERY_PRICE || 0);
totalOrderAmount += rowTotalPrice;
totalOrderAmount += rowSupplyPrice;
totalDeliveredAmount += rowDeliveredPrice;
totalNotDeliveredAmount += rowNotDeliveredPrice;
});
@@ -323,14 +330,36 @@ function fn_deliveryResultPopUp(objId,purchaseOrderNo){
fn_centerPopup(popup_width, popup_height, url, target);
}
//등록,수정,뷰
function fn_formPopUp(objId){
//등록,수정,뷰 - 발주서 타입에 따라 다른 팝업 열기
function fn_formPopUp(objId, formType){
var popup_width = 1460;
var popup_height = 1050;
var popup_height = 1050;
// 양식 타입에 따라 다른 팝업 열기
formType = fnc_checkNull(formType, 'general');
var hiddenForm = document.hiddenForm;
var target = "purchaseOrderFormPopup_new";
var url = "/purchaseOrder/purchaseOrderFormPopup_new.do";
var target = "";
var url = "";
if(formType == 'outsourcing'){
// 외주가공 발주서 양식
target = "purchaseOrderFormPopup_outsourcing";
url = "/purchaseOrder/purchaseOrderFormPopup_outsourcing.do";
popup_width = 1200;
popup_height = 900;
} else if(formType == 'general'){
// 일반 발주서 양식
target = "purchaseOrderFormPopup_general";
url = "/purchaseOrder/purchaseOrderFormPopup_general.do";
popup_width = 1000;
popup_height = 900;
} else {
// 기존 발주서 양식 (FORM_TYPE이 없거나 기존 데이터)
target = "purchaseOrderFormPopup_new";
url = "/purchaseOrder/purchaseOrderFormPopup_new.do";
}
fn_centerPopup(popup_width, popup_height, "", target);
hiddenForm.PURCHASE_ORDER_MASTER_OBJID.value = objId;
@@ -484,7 +513,9 @@ function fn_purchaseClose(){
<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}">
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:130px;">
<option value="">품명 선택</option>
</select>
</td>
</tr>
<tr>
@@ -516,7 +547,12 @@ function fn_purchaseClose(){
</select>
</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>

View File

@@ -42,6 +42,9 @@ $(document).ready(function(){
$('.select2').select2();
fnc_datepick();
// 품번/품명 Select2 AJAX 초기화
initPartSelect2Ajax("#SEARCH_PART_NO", "#SEARCH_PART_NAME", "#SEARCH_PART_OBJID");
//조회
@@ -872,12 +875,17 @@ function fn_openMailFormPopup(purchaseOrderObjId){
<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}">
<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>
<input type="text" name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" style="" autocomplete="off" value="${param.SEARCH_PART_NAME}">
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:150px;">
<option value="">품명 선택</option>
</select>
</td>
<%-- 발주부품, 발주구분 주석처리

View File

@@ -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>

View File

@@ -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");
@@ -239,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>

View File

@@ -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");
@@ -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>

View File

@@ -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>

View File

@@ -1863,6 +1863,10 @@ public class ProductionPlanningController extends BaseService {
// M-BOM 목록 (셀렉트박스용)
code_map.put("mbom_list", commonService.bizMakeOptionList("", "", "productionplanning.getMbomListForSelect2"));
// M-BOM 목록 (품명 포함) - 품명 자동 입력용
List<Map> mbomListWithPartName = productionPlanningService.getMbomListWithPartName();
request.setAttribute("mbom_part_name_list", mbomListWithPartName);
request.setAttribute("code_map", code_map);
} catch(Exception e) {
e.printStackTrace();
@@ -1902,6 +1906,10 @@ public class ProductionPlanningController extends BaseService {
// M-BOM 목록 (셀렉트박스용)
code_map.put("mbom_list", commonService.bizMakeOptionList("", "", "productionplanning.getMbomListForSelect2"));
// M-BOM 목록 (품명 포함) - 품명 자동 입력용
List<Map> mbomListWithPartName = productionPlanningService.getMbomListWithPartName();
request.setAttribute("mbom_part_name_list", mbomListWithPartName);
request.setAttribute("code_map", code_map);
} catch(Exception e) {
e.printStackTrace();
@@ -1931,4 +1939,60 @@ public class ProductionPlanningController extends BaseService {
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;
}
}

View File

@@ -3969,6 +3969,17 @@
ORDER BY REGDATE DESC, MBOM_NO
</select>
<!-- M-BOM 목록 (품명 포함, 원자재소요량/반제품소요량용) -->
<select id="getMbomListWithPartName" parameterType="map" resultType="com.pms.common.UpperKeyMap">
SELECT
OBJID,
MBOM_NO,
COALESCE(PART_NAME, '') AS PART_NAME
FROM MBOM_HEADER
WHERE STATUS = 'Y'
ORDER BY REGDATE DESC, MBOM_NO
</select>
<!-- M-BOM 헤더 정보 조회 (OBJID로) -->
<select id="getMbomHeaderByObjid" parameterType="map" resultType="com.pms.common.UpperKeyMap">
SELECT
@@ -4500,9 +4511,9 @@
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,
0 AS ASSEMBLY_QTY,
0 AS INSPECTION_QTY,
0 AS SHIP_WAIT_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
@@ -4550,9 +4561,9 @@
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,
0 AS ASSEMBLY_QTY,
0 AS INSPECTION_QTY,
0 AS SHIP_WAIT_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
@@ -4610,31 +4621,54 @@
ORDER BY T.SORT_DATE DESC, T.PROJECT_NO DESC
</select>
<!-- 프로젝트 정보 조회 (생산계획 폼용) -->
<!-- 프로젝트 정보 조회 (생산계획 폼용) - PROJECT_MGMT 또는 PRODUCTION_PLAN에서 조회 -->
<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)
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}
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>
@@ -4754,6 +4788,7 @@
RESULT_TYPE,
RESULT_DATE,
RESULT_QTY,
ROW_SEQ,
SERIAL_NO,
WORKER_ID,
WORKER_NAME,
@@ -4767,6 +4802,7 @@
#{RESULT_TYPE},
#{RESULT_DATE},
#{RESULT_QTY},
#{ROW_SEQ},
#{SERIAL_NO},
#{userId},
#{WORKER_NAME},
@@ -4860,4 +4896,40 @@
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>

View File

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

View File

@@ -2102,4 +2102,141 @@ public class ProductionPlanningService {
return 0.0;
}
}
/**
* M-BOM 목록 조회 (품명 포함)
* 원자재소요량/반제품소요량 화면에서 품명 자동 입력용
* @return M-BOM 목록 (OBJID, MBOM_NO, PART_NAME)
*/
public List<Map> getMbomListWithPartName() {
List<Map> resultList = new ArrayList<>();
SqlSession sqlSession = null;
try {
sqlSession = SqlMapConfig.getInstance().getSqlSession();
resultList = sqlSession.selectList("productionplanning.getMbomListWithPartName", new HashMap<>());
// JSP에서 대문자 키로 접근하므로 변환
resultList = CommonUtils.keyChangeUpperList(resultList);
} catch(Exception e) {
e.printStackTrace();
} finally {
if(sqlSession != null) sqlSession.close();
}
return resultList;
}
/**
* 생산실적 날짜별 조회
*/
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;
}
}

View File

@@ -2955,7 +2955,6 @@ public class PurchaseOrderService {
try {
String targetObjId = CommonUtils.checkNull(paramMap.get("objId"));
String pdfSessionId = CommonUtils.checkNull(paramMap.get("pdfSessionId")); // PDF 세션 ID 추가
String toEmails = CommonUtils.checkNull(paramMap.get("toEmails"));
String ccEmails = CommonUtils.checkNull(paramMap.get("ccEmails"));
String subject = CommonUtils.checkNull(paramMap.get("subject"));
@@ -2988,7 +2987,9 @@ public class PurchaseOrderService {
Calendar cal = Calendar.getInstance();
String todayKor = frm.format(cal.getTime());
String poNo = CommonUtils.checkNull((String)masterInfo.get("PURCHASE_ORDER_NO"));
String excelName = "발주서_" + poNo + "_" + todayKor + ".xls";
String zipName = "도면_" + poNo + "_" + todayKor + ".zip";
masterInfo.put("EXCELFILE_NAME", excelName);
masterInfo.put("APPR_COMPLETE_DATE", frm2.format(cal.getTime()));
// 발주서 테이블 내용 생성
@@ -3028,30 +3029,11 @@ public class PurchaseOrderService {
// 첨부파일 목록 생성
ArrayList<HashMap> attachFileList = new ArrayList<HashMap>();
// 1. 발주서 PDF 파일 첨부
if(!"".equals(pdfSessionId)) {
File pdfFile = getPdfFromSession(pdfSessionId, poNo);
if(pdfFile != null && pdfFile.exists()) {
HashMap<String, String> pdfFileMap = new HashMap<String, String>();
pdfFileMap.put(Constants.Db.COL_FILE_REAL_NAME, pdfFile.getName());
pdfFileMap.put(Constants.Db.COL_FILE_SAVED_NAME, pdfFile.getName());
pdfFileMap.put(Constants.Db.COL_FILE_PATH, pdfFile.getParent());
attachFileList.add(pdfFileMap);
System.out.println("발주서 PDF 파일 첨부 완료: " + pdfFile.getAbsolutePath());
} else {
System.out.println("발주서 PDF 파일을 찾을 수 없습니다: " + pdfSessionId);
}
}
/* 엑셀 첨부 주석처리 - PDF로 대체
// 1. 발주서 엑셀 파일 첨부
String excelName = "발주서_" + poNo + "_" + todayKor + ".xls";
masterInfo.put("EXCELFILE_NAME", excelName);
HashMap excelFile = this.makeMailAttachFileOrderSheet(masterInfo, contents_table);
if(excelFile != null) {
attachFileList.add(excelFile);
}
*/
// 2. 도면 파일 압축 첨부
if(partFileList != null && partFileList.size() > 0) {
@@ -3061,7 +3043,7 @@ public class PurchaseOrderService {
hm.put(Constants.Db.COL_FILE_REAL_NAME, zf.getName());
hm.put(Constants.Db.COL_FILE_SAVED_NAME, zf.getName());
// 파일 경로에서 파일명을 제거하고 디렉토리 경로만 추출 (OS 독립적)
hm.put(Constants.Db.COL_FILE_PATH, zf.getParent());
hm.put(Constants.Db.COL_FILE_PATH, zf.getParent());
attachFileList.add(hm);
}
}
@@ -3076,8 +3058,7 @@ public class PurchaseOrderService {
fromUser = CommonUtils.checkNull((String)masterInfo.get("WRITER"));
}
// 구매팀 계정(PURCHASE) 사용
boolean sendResult = MailUtil.sendMailWithAttachFile(fromUser, fromEmail, toUserIdList, toEmailList, ccEmailList, null, null, subject, mailContents, attachFileList, "PURCHASE_ORDER", Constants.Mail.ACCOUNT_TYPE_PURCHASE);
boolean sendResult = MailUtil.sendMailWithAttachFile(fromUser, fromEmail, toUserIdList, toEmailList, ccEmailList, null, null, subject, mailContents, attachFileList, "PURCHASE_ORDER");
if(sendResult) {
// 메일 발송 성공 시 DB 업데이트
@@ -3138,7 +3119,6 @@ public class PurchaseOrderService {
sb.append(userContents.replace("\n", "<br>"));
sb.append("</div>");
/* 발주서 테이블 본문 표시 주석처리 - PDF 첨부로 대체
// 구분선
sb.append("<hr style='border: 1px solid #ddd; margin: 20px 0;'>");
@@ -3147,7 +3127,6 @@ public class PurchaseOrderService {
sb.append("<h3 style='margin-bottom: 10px;'>[ 발주서 상세 ]</h3>");
sb.append(poContentsTable);
sb.append("</div>");
*/
sb.append("<div style='margin-top: 20px; color: #666;'>※발신전용 메일입니다.</div>");
sb.append("</body>");
@@ -3198,45 +3177,4 @@ public class PurchaseOrderService {
}
return resultMap;
}
/**
* 세션 ID로 저장된 PDF 파일 가져오기
* @param sessionId PDF 세션 ID
* @param poNo 발주번호 (파일명에 사용)
* @return PDF 파일
*/
private File getPdfFromSession(String sessionId, String poNo) {
try {
String tempDir = System.getProperty("java.io.tmpdir");
File pdfFile = new File(tempDir + File.separator + sessionId + ".pdf");
if(pdfFile.exists()) {
// 발주번호로 파일명 변경
if("".equals(poNo)) poNo = "발주서";
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyyMMddHHmmss");
String timestamp = sdf.format(new java.util.Date());
String newFileName = "발주서_" + poNo + "_" + timestamp + ".pdf";
File renamedFile = new File(tempDir + File.separator + newFileName);
// 파일 복사
java.nio.file.Files.copy(pdfFile.toPath(), renamedFile.toPath(),
java.nio.file.StandardCopyOption.REPLACE_EXISTING);
renamedFile.deleteOnExit();
// 원본 파일 삭제
pdfFile.delete();
return renamedFile;
}
return null;
} catch(Exception e) {
System.out.println("PDF 파일 가져오기 중 오류: " + e.getMessage());
e.printStackTrace();
return null;
}
}
}