fix: 견적서 저장/조회 버그 수정 및 여러 차수 작성 기능 추가
- 견적현황 undefined 문제 해결 (EST_STATUS 필드 추가) - 견적서 목록 팝업 대문자 키 이름 강제 - 견적서 데이터 로드 엔드포인트 추가 (getEstimateTemplateDataByObjId) - 한 영업번호에 여러 견적서 작성 가능하도록 수정 - PostgreSQL 타입 캐스팅 에러 수정 - 품목 저장 시 서브쿼리 다중 행 에러 수정
This commit is contained in:
@@ -486,20 +486,27 @@
|
||||
,CODE_NAME(AREA_CD) AS AREA_NAME
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,PAID_TYPE
|
||||
,CASE
|
||||
WHEN PAID_TYPE = 'paid' THEN '유상'
|
||||
WHEN PAID_TYPE = 'free' THEN '무상'
|
||||
ELSE PAID_TYPE
|
||||
END AS PAID_TYPE
|
||||
,RECEIPT_DATE
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,SERIAL_NO
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
,A.APPR_STATUS
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
LEFT OUTER JOIN
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
,EST_PRICE
|
||||
,EST_SUPPLY_PRICE
|
||||
,(SELECT COUNT(1) FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID) AS EST_STATUS
|
||||
,A.APPR_STATUS
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT
|
||||
B.OBJID AS ROUTE_OBJID,
|
||||
@@ -3678,7 +3685,11 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CUSTOMER_PROJECT_NAME,
|
||||
AREA_CD,
|
||||
CODE_NAME(AREA_CD) AS AREA_NAME,
|
||||
PAID_TYPE,
|
||||
CASE
|
||||
WHEN PAID_TYPE = 'paid' THEN '유상'
|
||||
WHEN PAID_TYPE = 'free' THEN '무상'
|
||||
ELSE PAID_TYPE
|
||||
END AS PAID_TYPE,
|
||||
RECEIPT_DATE,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
@@ -3696,7 +3707,31 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
WHERE
|
||||
OBJID = #{objId}::NUMERIC
|
||||
OBJID::VARCHAR = #{objId}
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 목록 조회 (CONTRACT_OBJID 기준) -->
|
||||
<select id="getEstimateTemplateList" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID AS "OBJID",
|
||||
CONTRACT_OBJID AS "CONTRACT_OBJID",
|
||||
TEMPLATE_TYPE AS "TEMPLATE_TYPE",
|
||||
CASE
|
||||
WHEN TEMPLATE_TYPE = '1' THEN '일반 견적서'
|
||||
WHEN TEMPLATE_TYPE = '2' THEN '장비 견적서'
|
||||
ELSE TEMPLATE_TYPE
|
||||
END AS "TEMPLATE_TYPE_NAME",
|
||||
ESTIMATE_NO AS "ESTIMATE_NO",
|
||||
WRITER AS "WRITER",
|
||||
TO_CHAR(REGDATE, 'YYYY-MM-DD HH24:MI') AS "REGDATE",
|
||||
CHG_USER_ID AS "CHG_USER_ID",
|
||||
TO_CHAR(CHGDATE, 'YYYY-MM-DD HH24:MI') AS "CHGDATE",
|
||||
ROW_NUMBER() OVER (PARTITION BY TEMPLATE_TYPE ORDER BY REGDATE) AS "REVISION"
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}
|
||||
ORDER BY TEMPLATE_TYPE, REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (ESTIMATE_TEMPLATE 테이블) -->
|
||||
@@ -3724,7 +3759,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
CONTRACT_OBJID = #{objId}
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
@@ -3732,6 +3767,56 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (OBJID 기준) -->
|
||||
<select id="getEstimateTemplateByObjId" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
RECIPIENT,
|
||||
ESTIMATE_NO,
|
||||
CONTACT_PERSON,
|
||||
GREETING_TEXT,
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
TO_CHAR(REGDATE, 'YYYY-MM-DD HH24:MI') AS REGDATE,
|
||||
CHG_USER_ID,
|
||||
TO_CHAR(CHGDATE, 'YYYY-MM-DD HH24:MI') AS CHGDATE
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
OBJID = #{templateObjId}
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 품목 조회 (TEMPLATE_OBJID 기준) -->
|
||||
<select id="getEstimateTemplateItemsByTemplateObjId" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
TEMPLATE_OBJID,
|
||||
SEQ,
|
||||
CATEGORY,
|
||||
DESCRIPTION,
|
||||
SPECIFICATION,
|
||||
QUANTITY,
|
||||
UNIT,
|
||||
UNIT_PRICE,
|
||||
AMOUNT,
|
||||
NOTE,
|
||||
REMARK
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID = #{templateObjId}
|
||||
ORDER BY SEQ
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 품목 조회 -->
|
||||
<select id="getEstimateTemplateItems" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
@@ -3753,7 +3838,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
TEMPLATE_OBJID IN (
|
||||
SELECT OBJID
|
||||
FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
WHERE CONTRACT_OBJID = #{objId}
|
||||
)
|
||||
ORDER BY SEQ
|
||||
</select>
|
||||
@@ -3761,6 +3846,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
<!-- 견적서 템플릿 저장 -->
|
||||
<insert id="insertEstimateTemplate" parameterType="map">
|
||||
INSERT INTO ESTIMATE_TEMPLATE (
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
@@ -3780,7 +3866,8 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
) VALUES (
|
||||
#{objId}::NUMERIC,
|
||||
#{template_objid},
|
||||
#{objId},
|
||||
#{template_type},
|
||||
#{executor},
|
||||
#{recipient},
|
||||
@@ -3820,7 +3907,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
CONTRACT_OBJID = #{objId}
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</update>
|
||||
|
||||
@@ -3828,11 +3915,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
<delete id="deleteEstimateTemplateItems" parameterType="map">
|
||||
DELETE FROM ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID IN (
|
||||
SELECT OBJID
|
||||
FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
)
|
||||
TEMPLATE_OBJID = #{template_objid}
|
||||
</delete>
|
||||
|
||||
<!-- 견적서 템플릿 품목 저장 -->
|
||||
@@ -3851,17 +3934,25 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
REMARK
|
||||
)
|
||||
SELECT
|
||||
(SELECT OBJID FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = #{objId}::NUMERIC AND TEMPLATE_TYPE = #{template_type}),
|
||||
(json_array_elements(#{items_json}::json)->>'seq')::INTEGER,
|
||||
json_array_elements(#{items_json}::json)->>'category',
|
||||
json_array_elements(#{items_json}::json)->>'description',
|
||||
json_array_elements(#{items_json}::json)->>'specification',
|
||||
json_array_elements(#{items_json}::json)->>'quantity',
|
||||
json_array_elements(#{items_json}::json)->>'unit',
|
||||
(json_array_elements(#{items_json}::json)->>'unit_price')::NUMERIC,
|
||||
(json_array_elements(#{items_json}::json)->>'amount')::NUMERIC,
|
||||
json_array_elements(#{items_json}::json)->>'note',
|
||||
json_array_elements(#{items_json}::json)->>'remark'
|
||||
#{template_objid},
|
||||
(item->>'seq')::INTEGER,
|
||||
item->>'category',
|
||||
item->>'description',
|
||||
item->>'specification',
|
||||
item->>'quantity',
|
||||
item->>'unit',
|
||||
CASE
|
||||
WHEN item->>'unit_price' = '' THEN NULL
|
||||
ELSE (item->>'unit_price')::NUMERIC
|
||||
END,
|
||||
CASE
|
||||
WHEN item->>'amount' = '' THEN NULL
|
||||
ELSE (item->>'amount')::NUMERIC
|
||||
END,
|
||||
item->>'note',
|
||||
item->>'remark'
|
||||
FROM json_array_elements(#{items_json}::json) AS item
|
||||
WHERE COALESCE(item->>'description', '') != ''
|
||||
</insert>
|
||||
|
||||
<!-- 견적서 템플릿 카테고리 업데이트 (장비 견적서용) -->
|
||||
@@ -3872,7 +3963,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
CONTRACT_OBJID = #{objId}
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</update>
|
||||
|
||||
|
||||
@@ -71,24 +71,25 @@ $(document).ready(function(){
|
||||
// 견적서 양식 선택 팝업
|
||||
Swal.fire({
|
||||
title: '견적서 양식을 선택하세요',
|
||||
icon: 'question',
|
||||
html: '<div style="margin: 20px 0;">' +
|
||||
'<button onclick="window.openTemplate1()" class="swal2-confirm swal2-styled" style="margin: 0 5px; background-color: #3085d6;">일반 견적서</button>' +
|
||||
'<button onclick="window.openTemplate2()" class="swal2-confirm swal2-styled" style="margin: 0 5px; background-color: #28a745;">장비 견적서</button>' +
|
||||
'</div>',
|
||||
showConfirmButton: false,
|
||||
showCancelButton: true,
|
||||
showDenyButton: true,
|
||||
confirmButtonText: '일반 견적서',
|
||||
denyButtonText: '장비 견적서',
|
||||
cancelButtonText: '취소',
|
||||
confirmButtonColor: '#3085d6',
|
||||
denyButtonColor: '#28a745',
|
||||
cancelButtonColor: '#d33',
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
// 일반 견적서 (Template 1)
|
||||
fn_openEstimateTemplate(objId, "1");
|
||||
} else if (result.isDenied) {
|
||||
// 장비 견적서 (Template 2)
|
||||
fn_openEstimateTemplate(objId, "2");
|
||||
}
|
||||
cancelButtonColor: '#d33'
|
||||
});
|
||||
|
||||
// 전역 함수로 등록
|
||||
window.openTemplate1 = function() {
|
||||
Swal.close();
|
||||
fn_openEstimateTemplate(objId, "1");
|
||||
};
|
||||
window.openTemplate2 = function() {
|
||||
Swal.close();
|
||||
fn_openEstimateTemplate(objId, "2");
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -158,71 +159,122 @@ var columns = [
|
||||
fn_projectConceptDetail(objid);
|
||||
}
|
||||
},
|
||||
{title:"영업정보(상세)", headerHozAlign:'center', //고객정보
|
||||
columns:[
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '계약구분', field : 'CATEGORY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '차수', field : 'OVERHAUL_ORDER'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '국내/해외', field : 'AREA_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제품구분', field : 'PRODUCT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '기계형식', field : 'MECHANICAL_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '200', title : '고객사 프로젝트명', field : 'CUSTOMER_PROJECT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '예상납기일', field : 'DUE_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '입고지', field : 'LOCATION' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '셋업지', field : 'SETUP' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '설비방향', field : 'FACILITY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '설비대수', field : 'FACILITY_QTY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '설비타입', field : 'FACILITY_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '설비길이', field : 'FACILITY_DEPTH' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '담당자', field : 'WRITER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '등록일', field : 'REG_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '첨부파일', field : 'CU01_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
var docType = 'contractMgmt01';
|
||||
var docTypeName = 'contractMgmt01';
|
||||
fn_FileRegist(objid, docType, docTypeName);
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{title:"진행사항", headerHozAlign:'center',
|
||||
columns:[
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '검토내용', field : 'CU03_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_projectConceptReviewDetail(objid);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '상태', field : 'CONTRACT_RESULT_NAME' }
|
||||
]
|
||||
},
|
||||
{title:"수주정보", headerHozAlign:'center',
|
||||
columns:[
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '수주일', field : 'CONTRACT_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : 'PO계약 No', field : 'PO_NO' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : 'PM', field : 'PM_USER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '통화', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '수주가', field : 'CONTRACT_PRICE_CURRENCY',
|
||||
formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false,},
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '170', title : '당사프로젝트명', field : 'PROJECT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '계약납기일', field : 'CONTRACT_DEL_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '요청납기일', field : 'REQ_DEL_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '수주회사', field : 'CONTRACT_COMPANY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제작공장', field : 'MANUFACTURE_PLANT_NAME' }
|
||||
]
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '상태', field : 'APPR_STATUS' ,
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '주문유형', field : 'CATEGORY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제품구분', field : 'PRODUCT_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '국내/해외', field : 'AREA_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '접수일', field : 'RECEIPT_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '유/무상', field : 'PAID_TYPE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품번', field : 'PART_NO' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품명', field : 'PART_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '150', title : 'S/N', field : 'SERIAL_NO',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === '') return '';
|
||||
|
||||
// 쉼표로 구분된 S/N 개수 계산
|
||||
var serialNumbers = value.split(',').map(function(s){ return s.trim(); }).filter(function(s){ return s !== ''; });
|
||||
var count = serialNumbers.length;
|
||||
|
||||
if(count === 0) return '';
|
||||
if(count === 1) return '<a href="javascript:void(0);">' + serialNumbers[0] + '</a>';
|
||||
|
||||
// 2개 이상이면 "첫번째 외 N개" 형식
|
||||
var displayText = serialNumbers[0] + ' 외 ' + (count - 1) + '개';
|
||||
return '<a href="javascript:void(0);">' + displayText + '</a>';
|
||||
},
|
||||
cellClick:function(e, cell){
|
||||
var APPROVAL_OBJID = fnc_checkNull(cell.getData().APPROVAL_OBJID);
|
||||
var ROUTE_OBJID = fnc_checkNull(cell.getData().ROUTE_OBJID);
|
||||
approval_form(APPROVAL_OBJID,ROUTE_OBJID);
|
||||
}
|
||||
var serialNo = fnc_checkNull(cell.getData().SERIAL_NO);
|
||||
fn_showSerialNoPopup(serialNo);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '수량', field : 'QUANTITY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '요청납기', field : 'DUE_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객요청사항', field : 'CUSTOMER_REQUEST' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '견적현황', field : 'EST_STATUS',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_showEstimateList(objid);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '결재상태', field : 'APPR_STATUS',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_projectConceptDetail(objid);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '견적단가', field : 'EST_PRICE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '견적공급가액', field : 'EST_SUPPLY_PRICE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '환종', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '환율', field : 'EXCHANGE_RATE' },
|
||||
|
||||
// {title:"영업정보(상세)", headerHozAlign:'center', //고객정보
|
||||
// columns:[
|
||||
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '차수', field : 'OVERHAUL_ORDER'},
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '국내/해외', field : 'AREA_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '기계형식', field : 'MECHANICAL_TYPE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '200', title : '고객사 프로젝트명', field : 'CUSTOMER_PROJECT_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '예상납기일', field : 'DUE_DATE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '입고지', field : 'LOCATION' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '셋업지', field : 'SETUP' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '설비방향', field : 'FACILITY_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '설비대수', field : 'FACILITY_QTY' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '설비타입', field : 'FACILITY_TYPE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '설비길이', field : 'FACILITY_DEPTH' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '담당자', field : 'WRITER_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '등록일', field : 'REG_DATE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '첨부파일', field : 'CU01_CNT',
|
||||
// formatter:fnc_subInfoValueFormatter,
|
||||
// cellClick:function(e, cell){
|
||||
// var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
// var docType = 'contractMgmt01';
|
||||
// var docTypeName = 'contractMgmt01';
|
||||
// fn_FileRegist(objid, docType, docTypeName);
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {title:"진행사항", headerHozAlign:'center',
|
||||
// columns:[
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '검토내용', field : 'CU03_CNT',
|
||||
// formatter:fnc_subInfoValueFormatter,
|
||||
// cellClick:function(e, cell){
|
||||
// var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
// fn_projectConceptReviewDetail(objid);
|
||||
// }
|
||||
// },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '상태', field : 'CONTRACT_RESULT_NAME' }
|
||||
// ]
|
||||
// },
|
||||
// {title:"수주정보", headerHozAlign:'center',
|
||||
// columns:[
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '수주일', field : 'CONTRACT_DATE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : 'PO계약 No', field : 'PO_NO' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '70', title : 'PM', field : 'PM_USER_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '통화', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '수주가', field : 'CONTRACT_PRICE_CURRENCY',
|
||||
// formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false,},
|
||||
// },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '170', title : '당사프로젝트명', field : 'PROJECT_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '계약납기일', field : 'CONTRACT_DEL_DATE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '요청납기일', field : 'REQ_DEL_DATE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '수주회사', field : 'CONTRACT_COMPANY_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제작공장', field : 'MANUFACTURE_PLANT_NAME' }
|
||||
// ]
|
||||
// },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '상태', field : 'APPR_STATUS' ,
|
||||
// formatter:fnc_createGridAnchorTag,
|
||||
// cellClick:function(e, cell){
|
||||
// var APPROVAL_OBJID = fnc_checkNull(cell.getData().APPROVAL_OBJID);
|
||||
// var ROUTE_OBJID = fnc_checkNull(cell.getData().ROUTE_OBJID);
|
||||
// approval_form(APPROVAL_OBJID,ROUTE_OBJID);
|
||||
// }
|
||||
// },
|
||||
];
|
||||
|
||||
//var grid;
|
||||
@@ -322,7 +374,97 @@ function fn_projectConceptReviewDetail(objId){
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
|
||||
//견적서 양식 열기
|
||||
// 견적서 목록 팝업
|
||||
function fn_showEstimateList(contractObjId){
|
||||
$.ajax({
|
||||
url: "/contractMgmt/getEstimateTemplateList.do",
|
||||
type: "POST",
|
||||
data: { objId: contractObjId },
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
console.log("견적서 목록 응답:", data); // 디버깅용
|
||||
|
||||
if(data.result === "success" && data.list && data.list.length > 0){
|
||||
var html = '<div style="max-height: 400px; overflow-y: auto;">';
|
||||
html += '<table style="width: 100%; border-collapse: collapse;">';
|
||||
html += '<thead><tr style="background-color: #f0f0f0;">';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">차수</th>';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">견적서 유형</th>';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">견적번호</th>';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">작성일</th>';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">작성자</th>';
|
||||
html += '</tr></thead><tbody>';
|
||||
|
||||
data.list.forEach(function(item){
|
||||
console.log("견적서 항목:", item); // 디버깅용
|
||||
|
||||
// 대문자/소문자 모두 지원하도록 안전하게 처리
|
||||
var objid = item.OBJID || item.objid || '';
|
||||
var templateType = item.TEMPLATE_TYPE || item.template_type || item.templateType || '';
|
||||
var revision = item.REVISION || item.revision || '';
|
||||
var templateTypeName = item.TEMPLATE_TYPE_NAME || item.template_type_name || item.templateTypeName || '';
|
||||
var estimateNo = item.ESTIMATE_NO || item.estimate_no || item.estimateNo || '-';
|
||||
var regdate = item.REGDATE || item.regdate || '';
|
||||
var writer = item.WRITER || item.writer || '';
|
||||
|
||||
html += '<tr style="cursor: pointer;" onclick="fn_openEstimateByObjId(\'' + objid + '\', \'' + templateType + '\')">';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + revision + '차</td>';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + templateTypeName + '</td>';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + estimateNo + '</td>';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + regdate + '</td>';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + writer + '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
html += '</tbody></table></div>';
|
||||
|
||||
Swal.fire({
|
||||
title: '견적서 목록',
|
||||
html: html,
|
||||
width: '700px',
|
||||
showConfirmButton: false,
|
||||
showCancelButton: true,
|
||||
cancelButtonText: '닫기'
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: '견적서가 없습니다',
|
||||
text: '작성된 견적서가 없습니다.',
|
||||
icon: 'info'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.error("견적서 목록 조회 오류:", xhr, status, error); // 디버깅용
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: '견적서 목록 조회 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// OBJID로 견적서 열기
|
||||
function fn_openEstimateByObjId(templateObjId, templateType){
|
||||
Swal.close();
|
||||
|
||||
var popup_width = 900;
|
||||
var popup_height = 800;
|
||||
var url = "";
|
||||
|
||||
if(templateType === "1"){
|
||||
// 일반 견적서
|
||||
url = "/contractMgmt/estimateTemplate1.do?templateObjId="+templateObjId;
|
||||
} else if(templateType === "2"){
|
||||
// 장비 견적서
|
||||
url = "/contractMgmt/estimateTemplate2.do?templateObjId="+templateObjId;
|
||||
}
|
||||
|
||||
window.open(url, "estimateTemplate_"+templateObjId, "width="+popup_width+",height="+popup_height+",menubar=no,scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
//견적서 양식 열기 (CONTRACT_OBJID로)
|
||||
function fn_openEstimateTemplate(objId, templateType){
|
||||
var popup_width = 900;
|
||||
var popup_height = 800;
|
||||
@@ -339,6 +481,36 @@ function fn_openEstimateTemplate(objId, templateType){
|
||||
window.open(url, "estimateTemplate", "width="+popup_width+",height="+popup_height+",menubar=no,scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
// S/N 목록 팝업 표시
|
||||
function fn_showSerialNoPopup(serialNoString){
|
||||
if(!serialNoString || serialNoString === ''){
|
||||
Swal.fire("S/N 정보가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 쉼표로 구분된 S/N을 배열로 변환
|
||||
var serialNumbers = serialNoString.split(',').map(function(sn){ return sn.trim(); });
|
||||
|
||||
// HTML 리스트 생성
|
||||
var listHtml = '<div style="text-align: left; max-height: 400px; overflow-y: auto;">';
|
||||
listHtml += '<ol style="padding-left: 20px; margin: 10px 0;">';
|
||||
serialNumbers.forEach(function(sn, index){
|
||||
listHtml += '<li style="padding: 5px 0; font-size: 14px;">' + sn + '</li>';
|
||||
});
|
||||
listHtml += '</ol>';
|
||||
listHtml += '</div>';
|
||||
|
||||
// SweetAlert2로 팝업 표시
|
||||
Swal.fire({
|
||||
title: 'S/N 목록',
|
||||
html: listHtml,
|
||||
icon: 'info',
|
||||
width: 500,
|
||||
confirmButtonText: '확인',
|
||||
confirmButtonColor: '#3085d6'
|
||||
});
|
||||
}
|
||||
|
||||
//코드값을 받아와서 동적으로 selectbox 생성
|
||||
function optionJobGroup(code){
|
||||
var val=code;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = CommonUtils.checkNull(person.getUserId());
|
||||
String objId = CommonUtils.checkNull(request.getParameter("objId"));
|
||||
String templateObjId = CommonUtils.checkNull(request.getParameter("templateObjId"));
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -218,8 +219,18 @@ textarea {
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
// 전역 변수로 저장 (데이터 로드 시 설정됨)
|
||||
var g_contractObjId = "<%=objId%>";
|
||||
var g_templateObjId = "<%=templateObjId%>";
|
||||
|
||||
$(function(){
|
||||
|
||||
// templateObjId가 있으면 기존 데이터 로드
|
||||
var templateObjId = "<%=templateObjId%>";
|
||||
if(templateObjId && templateObjId !== ""){
|
||||
fn_loadTemplateData(templateObjId);
|
||||
}
|
||||
|
||||
// 인쇄 버튼
|
||||
$("#btnPrint").click(function(){
|
||||
window.print();
|
||||
@@ -360,25 +371,114 @@ function fn_loadData() {
|
||||
});
|
||||
}
|
||||
|
||||
// 기존 견적서 데이터 로드 (templateObjId 기준)
|
||||
function fn_loadTemplateData(templateObjId){
|
||||
$.ajax({
|
||||
url: "/contractMgmt/getEstimateTemplateDataByObjId.do",
|
||||
type: "POST",
|
||||
data: { templateObjId: templateObjId },
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
console.log("견적서 데이터:", data); // 디버깅용
|
||||
|
||||
if(data.result === "success" && data.template){
|
||||
var template = data.template;
|
||||
|
||||
// CONTRACT_OBJID를 전역 변수에 저장 (저장 시 사용)
|
||||
var contractObjId = template.CONTRACT_OBJID || template.contract_objid || template.contractObjId || "";
|
||||
if(contractObjId) {
|
||||
g_contractObjId = contractObjId;
|
||||
}
|
||||
|
||||
// 대문자/소문자 모두 지원
|
||||
var executor = template.EXECUTOR || template.executor || "";
|
||||
var recipient = template.RECIPIENT || template.recipient || "";
|
||||
var estimateNo = template.ESTIMATE_NO || template.estimate_no || template.estimateNo || "";
|
||||
var contactPerson = template.CONTACT_PERSON || template.contact_person || template.contactPerson || "";
|
||||
var greetingText = template.GREETING_TEXT || template.greeting_text || template.greetingText || "";
|
||||
var note1 = template.NOTE1 || template.note1 || "";
|
||||
var note2 = template.NOTE2 || template.note2 || "";
|
||||
var note3 = template.NOTE3 || template.note3 || "";
|
||||
var note4 = template.NOTE4 || template.note4 || "";
|
||||
|
||||
// 기본 정보 채우기
|
||||
$("#executor").val(executor);
|
||||
$("#recipient").val(recipient);
|
||||
$("#estimate_no").val(estimateNo);
|
||||
$("#contact_person").val(contactPerson);
|
||||
$("#greeting_text").val(greetingText);
|
||||
$("#note1").val(note1);
|
||||
$("#note2").val(note2);
|
||||
$("#note3").val(note3);
|
||||
$("#note4").val(note4);
|
||||
|
||||
// 품목 데이터 채우기
|
||||
if(data.items && data.items.length > 0){
|
||||
$("#itemsTableBody").empty();
|
||||
data.items.forEach(function(item, idx){
|
||||
var description = item.DESCRIPTION || item.description || '';
|
||||
var specification = item.SPECIFICATION || item.specification || '';
|
||||
var quantity = item.QUANTITY || item.quantity || '';
|
||||
var unit = item.UNIT || item.unit || '';
|
||||
var unitPrice = item.UNIT_PRICE || item.unit_price || item.unitPrice || '';
|
||||
var amount = item.AMOUNT || item.amount || '';
|
||||
var note = item.NOTE || item.note || '';
|
||||
|
||||
var row = $("<tr>");
|
||||
row.append('<td>' + (idx + 1) + '</td>');
|
||||
row.append('<td class="text-left editable"><input type="text" class="item-desc" value="' + description + '"></td>');
|
||||
row.append('<td class="text-left editable"><textarea class="item-spec">' + specification + '</textarea></td>');
|
||||
row.append('<td class="editable"><input type="text" class="item-qty" value="' + quantity + '"></td>');
|
||||
row.append('<td class="editable"><input type="text" class="item-unit" value="' + unit + '"></td>');
|
||||
row.append('<td class="text-right editable"><input type="text" class="item-price" value="' + unitPrice + '"></td>');
|
||||
row.append('<td class="text-right editable"><input type="text" class="item-amount" value="' + amount + '" readonly></td>');
|
||||
row.append('<td class="editable"><input type="text" class="item-note" value="' + note + '"></td>');
|
||||
$("#itemsTableBody").append(row);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.error("데이터 로드 실패:", data);
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error){
|
||||
console.error("AJAX 오류:", xhr, status, error);
|
||||
Swal.fire("데이터를 불러오는데 실패했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 저장
|
||||
function fn_save() {
|
||||
var items = [];
|
||||
$("#itemsTableBody tr").each(function(idx) {
|
||||
var row = $(this);
|
||||
var unitPrice = row.find(".item-price").val() || "";
|
||||
var amount = row.find(".item-amount").val() || "";
|
||||
|
||||
items.push({
|
||||
seq: idx + 1,
|
||||
description: row.find(".item-desc").val(),
|
||||
specification: row.find(".item-spec").val(),
|
||||
quantity: row.find(".item-qty").val(),
|
||||
unit: row.find(".item-unit").val(),
|
||||
unit_price: row.find(".item-price").val().replace(/,/g, ""),
|
||||
amount: row.find(".item-amount").val().replace(/,/g, "").replace(/₩/g, ""),
|
||||
note: row.find(".item-note").val()
|
||||
description: row.find(".item-desc").val() || "",
|
||||
specification: row.find(".item-spec").val() || "",
|
||||
quantity: row.find(".item-qty").val() || "",
|
||||
unit: row.find(".item-unit").val() || "",
|
||||
unit_price: unitPrice.replace(/,/g, ""),
|
||||
amount: amount.replace(/,/g, "").replace(/₩/g, ""),
|
||||
note: row.find(".item-note").val() || ""
|
||||
});
|
||||
});
|
||||
|
||||
// objId는 CONTRACT_OBJID를 의미함
|
||||
var contractObjId = g_contractObjId;
|
||||
|
||||
// 유효성 검사
|
||||
if(!contractObjId || contractObjId === "" || contractObjId === "-1") {
|
||||
Swal.fire("견적서를 저장할 수 없습니다. 영업정보가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
var formData = {
|
||||
objId: "<%=objId%>",
|
||||
objId: contractObjId,
|
||||
template_type: "1",
|
||||
executor: $("#executor").val(),
|
||||
recipient: $("#recipient").val(),
|
||||
@@ -392,12 +492,21 @@ function fn_save() {
|
||||
items: JSON.stringify(items)
|
||||
};
|
||||
|
||||
// templateObjId가 있을 때만 추가 (기존 견적서 수정 시에만)
|
||||
if(g_templateObjId && g_templateObjId !== "" && g_templateObjId !== "-1") {
|
||||
formData.templateObjId = g_templateObjId;
|
||||
}
|
||||
|
||||
console.log("저장 데이터:", formData); // 디버깅용
|
||||
console.log("신규 작성:", !formData.templateObjId); // 디버깅용
|
||||
|
||||
$.ajax({
|
||||
url: "/contractMgmt/saveEstimate.do",
|
||||
type: "POST",
|
||||
data: formData,
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
console.log("저장 결과:", data); // 디버깅용
|
||||
if(data.result === "success") {
|
||||
Swal.fire({
|
||||
title: "저장되었습니다.",
|
||||
@@ -409,10 +518,11 @@ function fn_save() {
|
||||
self.close();
|
||||
});
|
||||
} else {
|
||||
Swal.fire("저장에 실패했습니다.");
|
||||
Swal.fire("저장에 실패했습니다." + (data.message ? "\n" + data.message : ""));
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
error: function(xhr, status, error) {
|
||||
console.error("저장 오류:", xhr, status, error); // 디버깅용
|
||||
Swal.fire("저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1774,13 +1774,20 @@ public class ContractMgmtController {
|
||||
@RequestMapping("/contractMgmt/estimateTemplate1.do")
|
||||
public String estimateTemplate1(HttpSession session, HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
String templateObjId = CommonUtils.checkNull(paramMap.get("templateObjId"));
|
||||
|
||||
try{
|
||||
Map estimate = null;
|
||||
List<Map> items = new ArrayList<Map>();
|
||||
|
||||
if(!"".equals(objId) && !"-1".equals(objId)){
|
||||
// 기존 견적서 데이터 조회
|
||||
// templateObjId가 있으면 기존 견적서 조회 (견적현황에서 클릭한 경우)
|
||||
if(!"".equals(templateObjId) && !"-1".equals(templateObjId)){
|
||||
paramMap.put("templateObjId", templateObjId);
|
||||
estimate = contractMgmtService.getEstimateTemplateByObjId(paramMap);
|
||||
items = contractMgmtService.getEstimateTemplateItemsByTemplateObjId(paramMap);
|
||||
}
|
||||
// objId만 있으면 CONTRACT 정보로 견적서 신규 작성
|
||||
else if(!"".equals(objId) && !"-1".equals(objId)){
|
||||
estimate = contractMgmtService.getEstimateTemplateInfo(paramMap);
|
||||
items = contractMgmtService.getEstimateTemplateItems(paramMap);
|
||||
}
|
||||
@@ -1805,12 +1812,20 @@ public class ContractMgmtController {
|
||||
@RequestMapping("/contractMgmt/estimateTemplate2.do")
|
||||
public String estimateTemplate2(HttpSession session, HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
String templateObjId = CommonUtils.checkNull(paramMap.get("templateObjId"));
|
||||
|
||||
try{
|
||||
Map estimate = null;
|
||||
List<Map> items = new ArrayList<Map>();
|
||||
|
||||
if(!"".equals(objId) && !"-1".equals(objId)){
|
||||
// templateObjId가 있으면 기존 견적서 조회 (견적현황에서 클릭한 경우)
|
||||
if(!"".equals(templateObjId) && !"-1".equals(templateObjId)){
|
||||
paramMap.put("templateObjId", templateObjId);
|
||||
estimate = contractMgmtService.getEstimateTemplateByObjId(paramMap);
|
||||
items = contractMgmtService.getEstimateTemplateItemsByTemplateObjId(paramMap);
|
||||
}
|
||||
// objId만 있으면 CONTRACT 정보로 견적서 신규 작성
|
||||
else if(!"".equals(objId) && !"-1".equals(objId)){
|
||||
// 기존 견적서 데이터 조회
|
||||
estimate = contractMgmtService.getEstimateTemplateInfo(paramMap);
|
||||
items = contractMgmtService.getEstimateTemplateItems(paramMap);
|
||||
@@ -1854,6 +1869,43 @@ public class ContractMgmtController {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 목록 조회 (AJAX)
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/contractMgmt/getEstimateTemplateList.do", method=RequestMethod.POST)
|
||||
public Map getEstimateTemplateList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
return contractMgmtService.getEstimateTemplateList(request, paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 데이터 조회 (OBJID로) (AJAX)
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/contractMgmt/getEstimateTemplateDataByObjId.do", method=RequestMethod.POST)
|
||||
public Map getEstimateTemplateDataByObjId(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
// 템플릿 기본 정보 조회
|
||||
Map template = contractMgmtService.getEstimateTemplateByObjId(paramMap);
|
||||
|
||||
// 템플릿 품목 조회
|
||||
List<Map> items = contractMgmtService.getEstimateTemplateItemsByTemplateObjId(paramMap);
|
||||
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("template", template);
|
||||
resultMap.put("items", items);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 저장 (AJAX)
|
||||
* @param request
|
||||
|
||||
@@ -486,20 +486,27 @@
|
||||
,CODE_NAME(AREA_CD) AS AREA_NAME
|
||||
,MECHANICAL_TYPE
|
||||
,OVERHAUL_ORDER
|
||||
,PAID_TYPE
|
||||
,CASE
|
||||
WHEN PAID_TYPE = 'paid' THEN '유상'
|
||||
WHEN PAID_TYPE = 'free' THEN '무상'
|
||||
ELSE PAID_TYPE
|
||||
END AS PAID_TYPE
|
||||
,RECEIPT_DATE
|
||||
,PART_NO
|
||||
,PART_NAME
|
||||
,SERIAL_NO
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
,A.APPR_STATUS
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
LEFT OUTER JOIN
|
||||
,QUANTITY
|
||||
,CUSTOMER_REQUEST
|
||||
,EXCHANGE_RATE
|
||||
,EST_PRICE
|
||||
,EST_SUPPLY_PRICE
|
||||
,(SELECT COUNT(1) FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = T.OBJID) AS EST_STATUS
|
||||
,A.APPR_STATUS
|
||||
,A.APPROVAL_OBJID
|
||||
,A.ROUTE_OBJID
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
LEFT OUTER JOIN
|
||||
(
|
||||
SELECT
|
||||
B.OBJID AS ROUTE_OBJID,
|
||||
@@ -3678,7 +3685,11 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CUSTOMER_PROJECT_NAME,
|
||||
AREA_CD,
|
||||
CODE_NAME(AREA_CD) AS AREA_NAME,
|
||||
PAID_TYPE,
|
||||
CASE
|
||||
WHEN PAID_TYPE = 'paid' THEN '유상'
|
||||
WHEN PAID_TYPE = 'free' THEN '무상'
|
||||
ELSE PAID_TYPE
|
||||
END AS PAID_TYPE,
|
||||
RECEIPT_DATE,
|
||||
PART_NO,
|
||||
PART_NAME,
|
||||
@@ -3696,7 +3707,31 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
WHERE
|
||||
OBJID = #{objId}::NUMERIC
|
||||
OBJID::VARCHAR = #{objId}
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 목록 조회 (CONTRACT_OBJID 기준) -->
|
||||
<select id="getEstimateTemplateList" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID AS "OBJID",
|
||||
CONTRACT_OBJID AS "CONTRACT_OBJID",
|
||||
TEMPLATE_TYPE AS "TEMPLATE_TYPE",
|
||||
CASE
|
||||
WHEN TEMPLATE_TYPE = '1' THEN '일반 견적서'
|
||||
WHEN TEMPLATE_TYPE = '2' THEN '장비 견적서'
|
||||
ELSE TEMPLATE_TYPE
|
||||
END AS "TEMPLATE_TYPE_NAME",
|
||||
ESTIMATE_NO AS "ESTIMATE_NO",
|
||||
WRITER AS "WRITER",
|
||||
TO_CHAR(REGDATE, 'YYYY-MM-DD HH24:MI') AS "REGDATE",
|
||||
CHG_USER_ID AS "CHG_USER_ID",
|
||||
TO_CHAR(CHGDATE, 'YYYY-MM-DD HH24:MI') AS "CHGDATE",
|
||||
ROW_NUMBER() OVER (PARTITION BY TEMPLATE_TYPE ORDER BY REGDATE) AS "REVISION"
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}
|
||||
ORDER BY TEMPLATE_TYPE, REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (ESTIMATE_TEMPLATE 테이블) -->
|
||||
@@ -3724,7 +3759,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
CONTRACT_OBJID = #{objId}
|
||||
<if test="template_type != null and template_type != ''">
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</if>
|
||||
@@ -3732,6 +3767,56 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 데이터 조회 (OBJID 기준) -->
|
||||
<select id="getEstimateTemplateByObjId" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
RECIPIENT,
|
||||
ESTIMATE_NO,
|
||||
CONTACT_PERSON,
|
||||
GREETING_TEXT,
|
||||
MODEL_NAME,
|
||||
MODEL_CODE,
|
||||
EXECUTOR_DATE,
|
||||
NOTE1,
|
||||
NOTE2,
|
||||
NOTE3,
|
||||
NOTE4,
|
||||
WRITER,
|
||||
TO_CHAR(REGDATE, 'YYYY-MM-DD HH24:MI') AS REGDATE,
|
||||
CHG_USER_ID,
|
||||
TO_CHAR(CHGDATE, 'YYYY-MM-DD HH24:MI') AS CHGDATE
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE
|
||||
WHERE
|
||||
OBJID = #{templateObjId}
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 품목 조회 (TEMPLATE_OBJID 기준) -->
|
||||
<select id="getEstimateTemplateItemsByTemplateObjId" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
OBJID,
|
||||
TEMPLATE_OBJID,
|
||||
SEQ,
|
||||
CATEGORY,
|
||||
DESCRIPTION,
|
||||
SPECIFICATION,
|
||||
QUANTITY,
|
||||
UNIT,
|
||||
UNIT_PRICE,
|
||||
AMOUNT,
|
||||
NOTE,
|
||||
REMARK
|
||||
FROM
|
||||
ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID = #{templateObjId}
|
||||
ORDER BY SEQ
|
||||
</select>
|
||||
|
||||
<!-- 견적서 템플릿 품목 조회 -->
|
||||
<select id="getEstimateTemplateItems" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
@@ -3753,7 +3838,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
TEMPLATE_OBJID IN (
|
||||
SELECT OBJID
|
||||
FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
WHERE CONTRACT_OBJID = #{objId}
|
||||
)
|
||||
ORDER BY SEQ
|
||||
</select>
|
||||
@@ -3761,6 +3846,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
<!-- 견적서 템플릿 저장 -->
|
||||
<insert id="insertEstimateTemplate" parameterType="map">
|
||||
INSERT INTO ESTIMATE_TEMPLATE (
|
||||
OBJID,
|
||||
CONTRACT_OBJID,
|
||||
TEMPLATE_TYPE,
|
||||
EXECUTOR,
|
||||
@@ -3780,7 +3866,8 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CHG_USER_ID,
|
||||
CHGDATE
|
||||
) VALUES (
|
||||
#{objId}::NUMERIC,
|
||||
#{template_objid},
|
||||
#{objId},
|
||||
#{template_type},
|
||||
#{executor},
|
||||
#{recipient},
|
||||
@@ -3820,7 +3907,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
CONTRACT_OBJID = #{objId}
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</update>
|
||||
|
||||
@@ -3828,11 +3915,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
<delete id="deleteEstimateTemplateItems" parameterType="map">
|
||||
DELETE FROM ESTIMATE_TEMPLATE_ITEM
|
||||
WHERE
|
||||
TEMPLATE_OBJID IN (
|
||||
SELECT OBJID
|
||||
FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
)
|
||||
TEMPLATE_OBJID = #{template_objid}
|
||||
</delete>
|
||||
|
||||
<!-- 견적서 템플릿 품목 저장 -->
|
||||
@@ -3851,17 +3934,25 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
REMARK
|
||||
)
|
||||
SELECT
|
||||
(SELECT OBJID FROM ESTIMATE_TEMPLATE WHERE CONTRACT_OBJID = #{objId}::NUMERIC AND TEMPLATE_TYPE = #{template_type}),
|
||||
(json_array_elements(#{items_json}::json)->>'seq')::INTEGER,
|
||||
json_array_elements(#{items_json}::json)->>'category',
|
||||
json_array_elements(#{items_json}::json)->>'description',
|
||||
json_array_elements(#{items_json}::json)->>'specification',
|
||||
json_array_elements(#{items_json}::json)->>'quantity',
|
||||
json_array_elements(#{items_json}::json)->>'unit',
|
||||
(json_array_elements(#{items_json}::json)->>'unit_price')::NUMERIC,
|
||||
(json_array_elements(#{items_json}::json)->>'amount')::NUMERIC,
|
||||
json_array_elements(#{items_json}::json)->>'note',
|
||||
json_array_elements(#{items_json}::json)->>'remark'
|
||||
#{template_objid},
|
||||
(item->>'seq')::INTEGER,
|
||||
item->>'category',
|
||||
item->>'description',
|
||||
item->>'specification',
|
||||
item->>'quantity',
|
||||
item->>'unit',
|
||||
CASE
|
||||
WHEN item->>'unit_price' = '' THEN NULL
|
||||
ELSE (item->>'unit_price')::NUMERIC
|
||||
END,
|
||||
CASE
|
||||
WHEN item->>'amount' = '' THEN NULL
|
||||
ELSE (item->>'amount')::NUMERIC
|
||||
END,
|
||||
item->>'note',
|
||||
item->>'remark'
|
||||
FROM json_array_elements(#{items_json}::json) AS item
|
||||
WHERE COALESCE(item->>'description', '') != ''
|
||||
</insert>
|
||||
|
||||
<!-- 견적서 템플릿 카테고리 업데이트 (장비 견적서용) -->
|
||||
@@ -3872,7 +3963,7 @@ ORDER BY ASM.SUPPLY_NAME
|
||||
CHG_USER_ID = #{chg_user_id},
|
||||
CHGDATE = NOW()
|
||||
WHERE
|
||||
CONTRACT_OBJID = #{objId}::NUMERIC
|
||||
CONTRACT_OBJID = #{objId}
|
||||
AND TEMPLATE_TYPE = #{template_type}
|
||||
</update>
|
||||
|
||||
|
||||
@@ -1271,6 +1271,105 @@ public class ContractMgmtService {
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 목록 조회
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
public Map getEstimateTemplateList(HttpServletRequest request, Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
List<Map> list = sqlSession.selectList("contractMgmt.getEstimateTemplateList", paramMap);
|
||||
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("list", list);
|
||||
|
||||
}catch(Exception e){
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("msg", "목록 조회 중 오류가 발생했습니다.");
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 OBJID로 조회 (견적현황 클릭 시)
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
public Map getEstimateTemplateByObjId(Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
String templateObjId = CommonUtils.checkNull(paramMap.get("templateObjId"));
|
||||
|
||||
if(!"".equals(templateObjId) && !"-1".equals(templateObjId)){
|
||||
// ESTIMATE_TEMPLATE 테이블에서 직접 조회
|
||||
resultMap = (Map) sqlSession.selectOne("contractMgmt.getEstimateTemplateByObjId", paramMap);
|
||||
|
||||
// CONTRACT_MGMT 정보도 함께 조회
|
||||
if(resultMap != null && !resultMap.isEmpty()){
|
||||
String contractObjId = CommonUtils.checkNull(resultMap.get("CONTRACT_OBJID"));
|
||||
if(!"".equals(contractObjId)){
|
||||
Map contractInfo = new HashMap();
|
||||
contractInfo.put("objId", contractObjId);
|
||||
Map contractData = (Map) sqlSession.selectOne("contractMgmt.getEstimateTemplateInfo", contractInfo);
|
||||
if(contractData != null && !contractData.isEmpty()){
|
||||
// CONTRACT 정보를 resultMap에 추가 (템플릿 정보가 우선)
|
||||
contractData.putAll(resultMap);
|
||||
resultMap = contractData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 품목 조회 (템플릿 OBJID로)
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
public List<Map> getEstimateTemplateItemsByTemplateObjId(Map paramMap){
|
||||
List<Map> resultList = new ArrayList<Map>();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
String templateObjId = CommonUtils.checkNull(paramMap.get("templateObjId"));
|
||||
|
||||
if(!"".equals(templateObjId) && !"-1".equals(templateObjId)){
|
||||
resultList = sqlSession.selectList("contractMgmt.getEstimateTemplateItemsByTemplateObjId", paramMap);
|
||||
}
|
||||
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 견적서 템플릿 저장
|
||||
* @param request
|
||||
@@ -1287,7 +1386,8 @@ public class ContractMgmtService {
|
||||
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = person.getUserId();
|
||||
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId")); // CONTRACT_OBJID
|
||||
String templateObjId = CommonUtils.checkNull(paramMap.get("templateObjId")); // 기존 템플릿 수정 시
|
||||
String templateType = CommonUtils.checkNull(paramMap.get("template_type"));
|
||||
String itemsJson = CommonUtils.checkNull(paramMap.get("items"));
|
||||
String categoriesJson = CommonUtils.checkNull(paramMap.get("categories"));
|
||||
@@ -1295,14 +1395,28 @@ public class ContractMgmtService {
|
||||
paramMap.put("writer", userId);
|
||||
paramMap.put("chg_user_id", userId);
|
||||
|
||||
// 견적서 템플릿 정보 저장/수정
|
||||
Map existingTemplate = (Map) sqlSession.selectOne("contractMgmt.getEstimateTemplateData", paramMap);
|
||||
// 기존 템플릿 수정인지 신규 작성인지 확인
|
||||
// 중요: templateObjId가 명시적으로 있을 때만 수정, 없으면 항상 신규 작성
|
||||
boolean isUpdate = false;
|
||||
|
||||
if(existingTemplate != null && !existingTemplate.isEmpty()){
|
||||
// 기존 데이터 업데이트
|
||||
if(!"".equals(templateObjId) && !"-1".equals(templateObjId)){
|
||||
// templateObjId가 명시적으로 있으면 해당 템플릿 수정 (견적현황에서 기존 견적서 열어서 수정한 경우)
|
||||
Map existingTemplate = (Map) sqlSession.selectOne("contractMgmt.getEstimateTemplateByObjId", paramMap);
|
||||
if(existingTemplate != null && !existingTemplate.isEmpty()){
|
||||
isUpdate = true;
|
||||
paramMap.put("template_objid", templateObjId);
|
||||
}
|
||||
}
|
||||
// else: templateObjId가 없으면 항상 신규 견적서 작성 (같은 영업번호에 여러 견적서 가능)
|
||||
|
||||
if(isUpdate){
|
||||
// 기존 견적서 수정
|
||||
sqlSession.update("contractMgmt.updateEstimateTemplate", paramMap);
|
||||
} else {
|
||||
// 신규 데이터 삽입
|
||||
// 신규 견적서 작성 - 새로운 OBJID 생성
|
||||
templateObjId = CommonUtils.createObjId();
|
||||
paramMap.put("template_objid", templateObjId);
|
||||
paramMap.put("contract_objid", objId);
|
||||
sqlSession.insert("contractMgmt.insertEstimateTemplate", paramMap);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user