견적요청등록까지 수정한 부분
This commit is contained in:
@@ -1692,6 +1692,7 @@ SELECT
|
||||
,A.CONTRACT_PRICE
|
||||
,A.CONTRACT_PRICE_CURRENCY
|
||||
,A.CONTRACT_CURRENCY
|
||||
,CODE_NAME(A.CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME
|
||||
,A.REGDATE
|
||||
,A.WRITER
|
||||
,A.CONTRACT_NO
|
||||
@@ -5434,4 +5435,122 @@ WHERE
|
||||
WHERE OBJID = #{customerObjId}::NUMERIC
|
||||
</select>
|
||||
|
||||
<!-- 결재 필요 여부 확인 (재오더/신규수주/가격인하 체크) -->
|
||||
<select id="checkApprovalRequired" parameterType="map" resultType="map">
|
||||
/* contractMgmt.checkApprovalRequired */
|
||||
WITH current_items AS (
|
||||
SELECT
|
||||
ETI.PART_OBJID,
|
||||
COALESCE(PM.PART_NO, ETI.PART_NO) AS PART_NO,
|
||||
CAST(COALESCE(NULLIF(ETI.SUPPLY_UNIT_PRICE, ''), '0') AS NUMERIC) AS CURRENT_PRICE
|
||||
FROM ESTIMATE_TEMPLATE ET
|
||||
INNER JOIN ESTIMATE_TEMPLATE_ITEM ETI ON ET.OBJID = ETI.TEMPLATE_OBJID
|
||||
LEFT JOIN PART_MNG PM ON ETI.PART_OBJID = PM.OBJID
|
||||
WHERE ET.CONTRACT_OBJID = #{contractObjId}::NUMERIC
|
||||
AND ET.OBJID = (
|
||||
SELECT OBJID FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{contractObjId}::NUMERIC
|
||||
ORDER BY REGDATE DESC LIMIT 1
|
||||
)
|
||||
),
|
||||
previous_orders AS (
|
||||
SELECT
|
||||
CI.PART_OBJID,
|
||||
COALESCE(PM.PART_NO, CI.PART_NO) AS PART_NO,
|
||||
MAX(CAST(COALESCE(NULLIF(ETI.SUPPLY_UNIT_PRICE, ''), '0') AS NUMERIC)) AS PREV_MAX_PRICE
|
||||
FROM CONTRACT_MGMT CM
|
||||
INNER JOIN CONTRACT_ITEM CI ON CM.OBJID = CI.CONTRACT_OBJID AND CI.STATUS = 'ACTIVE'
|
||||
LEFT JOIN PART_MNG PM ON CI.PART_OBJID = PM.OBJID
|
||||
LEFT JOIN ESTIMATE_TEMPLATE ET ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN ESTIMATE_TEMPLATE_ITEM ETI ON ET.OBJID = ETI.TEMPLATE_OBJID
|
||||
AND (ETI.PART_OBJID = CI.PART_OBJID OR ETI.PART_NO = CI.PART_NO)
|
||||
WHERE CM.CUSTOMER_OBJID = #{customerObjId}
|
||||
AND CM.OBJID != #{contractObjId}::NUMERIC
|
||||
AND CM.STATUS != 'cancel'
|
||||
AND CM.CONTRACT_RESULT = '0000964'
|
||||
GROUP BY CI.PART_OBJID, COALESCE(PM.PART_NO, CI.PART_NO)
|
||||
)
|
||||
SELECT
|
||||
CASE
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM current_items CI
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM previous_orders PO
|
||||
WHERE (PO.PART_OBJID = CI.PART_OBJID AND CI.PART_OBJID IS NOT NULL)
|
||||
OR (PO.PART_NO = CI.PART_NO AND CI.PART_NO IS NOT NULL AND CI.PART_NO != '')
|
||||
)
|
||||
) THEN 'Y'
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM current_items CI
|
||||
INNER JOIN previous_orders PO
|
||||
ON (PO.PART_OBJID = CI.PART_OBJID AND CI.PART_OBJID IS NOT NULL)
|
||||
OR (PO.PART_NO = CI.PART_NO AND CI.PART_NO IS NOT NULL AND CI.PART_NO != '')
|
||||
WHERE CI.CURRENT_PRICE < PO.PREV_MAX_PRICE
|
||||
) THEN 'Y'
|
||||
ELSE 'N'
|
||||
END AS APPROVAL_REQUIRED,
|
||||
CASE
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM current_items CI
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM previous_orders PO
|
||||
WHERE (PO.PART_OBJID = CI.PART_OBJID AND CI.PART_OBJID IS NOT NULL)
|
||||
OR (PO.PART_NO = CI.PART_NO AND CI.PART_NO IS NOT NULL AND CI.PART_NO != '')
|
||||
)
|
||||
) THEN 'NEW_ORDER'
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM current_items CI
|
||||
INNER JOIN previous_orders PO
|
||||
ON (PO.PART_OBJID = CI.PART_OBJID AND CI.PART_OBJID IS NOT NULL)
|
||||
OR (PO.PART_NO = CI.PART_NO AND CI.PART_NO IS NOT NULL AND CI.PART_NO != '')
|
||||
WHERE CI.CURRENT_PRICE < PO.PREV_MAX_PRICE
|
||||
) THEN 'PRICE_DOWN'
|
||||
ELSE 'REORDER'
|
||||
END AS REASON
|
||||
</select>
|
||||
|
||||
<!-- 결재불필요 - APPROVAL 테이블 레코드 생성 -->
|
||||
<insert id="insertApprovalNotRequired" parameterType="map">
|
||||
/* contractMgmt.insertApprovalNotRequired */
|
||||
INSERT INTO APPROVAL (
|
||||
OBJID,
|
||||
TARGET_TYPE,
|
||||
TARGET_OBJID,
|
||||
APPROVAL_TITLE,
|
||||
WRITER,
|
||||
REGDATE
|
||||
) VALUES (
|
||||
#{OBJID}::NUMERIC,
|
||||
#{TARGET_TYPE},
|
||||
#{TARGET_OBJID}::NUMERIC,
|
||||
#{APPROVAL_TITLE},
|
||||
#{WRITER},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 결재불필요 - ROUTE 테이블 레코드 생성 -->
|
||||
<insert id="insertRouteNotRequired" parameterType="map">
|
||||
/* contractMgmt.insertRouteNotRequired */
|
||||
INSERT INTO ROUTE (
|
||||
OBJID,
|
||||
APPROVAL_OBJID,
|
||||
TARGET_OBJID,
|
||||
TARGET_TYPE,
|
||||
STATUS,
|
||||
ROUTE_SEQ,
|
||||
WRITER,
|
||||
REGDATE
|
||||
) VALUES (
|
||||
#{OBJID}::NUMERIC,
|
||||
#{APPROVAL_OBJID}::NUMERIC,
|
||||
#{TARGET_OBJID}::NUMERIC,
|
||||
#{TARGET_TYPE},
|
||||
#{STATUS},
|
||||
#{ROUTE_SEQ}::NUMERIC,
|
||||
#{WRITER},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
@@ -165,6 +165,8 @@ $(document).ready(function(){
|
||||
var targetStatus = fnc_checkNull(selectedData[0].APPR_STATUS);
|
||||
var status = fnc_checkNull(selectedData[0].STATUS);
|
||||
var estObjId = fnc_checkNull(selectedData[0].EST_OBJID);
|
||||
var contractObjId = fnc_checkNull(selectedData[0].OBJID);
|
||||
var customerObjId = fnc_checkNull(selectedData[0].CUSTOMER_OBJID);
|
||||
|
||||
// 견적서 작성 여부 확인
|
||||
if(estObjId == ""){
|
||||
@@ -172,16 +174,92 @@ $(document).ready(function(){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(targetStatus == "결재완료" || targetStatus == "결재중" || status == "cancel"){
|
||||
if(targetStatus == "결재완료" || targetStatus == "결재중" || targetStatus == "결재불필요" || status == "cancel"){
|
||||
Swal.fire("작성중/결재반려인 상태만 결재상신 가능합니다.");
|
||||
return false;
|
||||
}else{
|
||||
if(confirm("결재상신 하시겠습니까?")){
|
||||
//var objId = fnc_checkNull(selectedData[0].OBJID);
|
||||
var objId = estObjId;
|
||||
var title = encodeURIComponent(fnc_checkNull(selectedData[0].CONTRACT_NO));
|
||||
window.open("/approval/registApproval.do?targetType=CONTRACT_ESTIMATE&targetObjId="+objId+"&approvalTitle="+title,"registApproval","width=700,height=700");
|
||||
}
|
||||
// 결재 필요 여부 체크 (재오더/신규수주/가격인하)
|
||||
$.ajax({
|
||||
url: "/contractMgmt/checkApprovalRequired.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
contractObjId: contractObjId,
|
||||
customerObjId: customerObjId
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
if(response.result == "success") {
|
||||
var approvalRequired = response.approvalRequired;
|
||||
var reason = response.reason;
|
||||
|
||||
if(approvalRequired == "N") {
|
||||
// 재오더 + 가격동일/인상 → 결재불필요
|
||||
Swal.fire({
|
||||
title: '결재 불필요',
|
||||
text: '재오더(가격동일/인상)로 결재가 필요하지 않습니다. 결재불필요로 처리하시겠습니까?',
|
||||
icon: 'info',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '확인',
|
||||
cancelButtonText: '취소'
|
||||
}).then((result) => {
|
||||
if(result.isConfirmed) {
|
||||
// 결재불필요 처리
|
||||
$.ajax({
|
||||
url: "/contractMgmt/setApprovalNotRequired.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
estObjId: estObjId
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(res) {
|
||||
if(res.result == "success") {
|
||||
Swal.fire("결재불필요로 처리되었습니다.");
|
||||
fn_search(); // 목록 새로고침
|
||||
} else {
|
||||
Swal.fire("오류: " + res.message);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire("결재불필요 처리 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 신규수주 또는 가격인하 → 결재필요
|
||||
var confirmMsg = "결재상신 하시겠습니까?";
|
||||
if(reason == "신규수주") {
|
||||
confirmMsg = "신규수주입니다. 결재상신 하시겠습니까?";
|
||||
} else if(reason == "가격인하") {
|
||||
confirmMsg = "가격인하 건입니다. 결재상신 하시겠습니까?";
|
||||
}
|
||||
|
||||
if(confirm(confirmMsg)){
|
||||
var objId = estObjId;
|
||||
var title = encodeURIComponent(fnc_checkNull(selectedData[0].CONTRACT_NO));
|
||||
window.open("/approval/registApproval.do?targetType=CONTRACT_ESTIMATE&targetObjId="+objId+"&approvalTitle="+title,"registApproval","width=700,height=700");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// API 오류 시 기존 방식으로 진행
|
||||
if(confirm("결재상신 하시겠습니까?")){
|
||||
var objId = estObjId;
|
||||
var title = encodeURIComponent(fnc_checkNull(selectedData[0].CONTRACT_NO));
|
||||
window.open("/approval/registApproval.do?targetType=CONTRACT_ESTIMATE&targetObjId="+objId+"&approvalTitle="+title,"registApproval","width=700,height=700");
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
// AJAX 오류 시 기존 방식으로 진행
|
||||
if(confirm("결재상신 하시겠습니까?")){
|
||||
var objId = estObjId;
|
||||
var title = encodeURIComponent(fnc_checkNull(selectedData[0].CONTRACT_NO));
|
||||
window.open("/approval/registApproval.do?targetType=CONTRACT_ESTIMATE&targetObjId="+objId+"&approvalTitle="+title,"registApproval","width=700,height=700");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -200,9 +278,9 @@ $(document).ready(function(){
|
||||
var objId = fnc_checkNull(selectedData[0].OBJID);
|
||||
var estStatus = fnc_checkNull(selectedData[0].EST_STATUS);
|
||||
|
||||
// 결재완료 상태 확인
|
||||
if(apprStatus !== "결재완료"){
|
||||
Swal.fire("결재완료된 견적서만 발송 가능합니다.");
|
||||
// 결재완료 또는 결재불필요 상태 확인
|
||||
if(apprStatus !== "결재완료" && apprStatus !== "결재불필요"){
|
||||
Swal.fire("결재완료 또는 결재불필요 상태의 견적서만 발송 가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -229,16 +307,30 @@ function addComma(num) {
|
||||
|
||||
var columns = [
|
||||
{title:'EST_OBJID' ,field:'EST_OBJID' ,visible:false, frozen:true},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '90', title : '영업번호', field : 'CONTRACT_NO', frozen:true,
|
||||
// 1. 영업번호
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 70, widthGrow: 0.9, title : '영업번호', field : 'CONTRACT_NO', frozen:true,
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_projectConceptDetail(objid);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '주문유형', field : 'CATEGORY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '접수일', field : 'RECEIPT_DATE' },
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '120', title : '요청납기', field : 'EARLIEST_DUE_DATE',
|
||||
// 2. 주문유형
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 60, widthGrow: 0.8, title : '주문유형', field : 'CATEGORY_NAME' },
|
||||
// 3. 제품구분
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 60, widthGrow: 0.8, title : '제품구분', field : 'PRODUCT_NAME' },
|
||||
// 4. 국내/해외
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 55, widthGrow: 0.7, title : '국내/해외', field : 'AREA_NAME' },
|
||||
// 5. 접수일
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 75, widthGrow: 0.9, title : '접수일', field : 'RECEIPT_DATE' },
|
||||
// 6. 고객사
|
||||
{headerHozAlign : 'center', hozAlign : 'left', minWidth: 90, widthGrow: 1.5, title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
// 7. 유/무상
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 45, widthGrow: 0.6, title : '유/무상', field : 'PAID_TYPE' },
|
||||
// 8. 품명 (품번으로 표시)
|
||||
{headerHozAlign : 'center', hozAlign : 'left', minWidth: 90, widthGrow: 1.5, title : '품명', field : 'PART_NO' },
|
||||
// 9. 요청납기
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 75, widthGrow: 0.9, title : '요청납기', field : 'EARLIEST_DUE_DATE',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var dueDate = fnc_checkNull(cell.getValue());
|
||||
var otherCount = fnc_checkNull(cell.getData().OTHER_DUE_DATE_COUNT);
|
||||
@@ -253,88 +345,18 @@ var columns = [
|
||||
return dueDate;
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객사', field : 'CUSTOMER_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '180', title : '품명', field : 'ITEM_SUMMARY' },
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '견적수량', field : 'ESTIMATE_QUANTITY',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
/* 수주수량 컬럼 주석처리
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '수주수량', field : 'ORDER_QUANTITY',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
*/
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '유/무상', field : 'PAID_TYPE' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '제품구분', field : 'PRODUCT_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '88', title : '국내/해외', field : 'AREA_NAME' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품번', field : 'PART_NO' },
|
||||
// {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 serialNo = fnc_checkNull(cell.getData().SERIAL_NO);
|
||||
// fn_showSerialNoPopup(serialNo);
|
||||
// }
|
||||
// },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '수량', field : 'QUANTITY' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '120', title : '반납사유', field : 'RETURN_REASON_SUMMARY' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '고객요청사항', field : 'CUSTOMER_REQUEST' },
|
||||
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '130', title : '공급가액', field : 'EST_TOTAL_AMOUNT',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === '' || value === '0') return '';
|
||||
var rowData = cell.getRow().getData();
|
||||
var currencyName = fnc_checkNull(rowData.CONTRACT_CURRENCY_NAME) || '';
|
||||
// 통화 이름을 기호로 변환
|
||||
var currencySymbol = '';
|
||||
if(currencyName.includes('원') || currencyName === 'KRW') currencySymbol = '₩';
|
||||
else if(currencyName.includes('달러') || currencyName === 'USD') currencySymbol = '$';
|
||||
else if(currencyName.includes('유로') || currencyName === 'EUR') currencySymbol = '€';
|
||||
else if(currencyName.includes('엔') || currencyName === 'JPY') currencySymbol = '¥';
|
||||
else if(currencyName.includes('위안') || currencyName === 'CNY') currencySymbol = '¥';
|
||||
// 통화 기호 제거 후 콤마 추가
|
||||
var numericValue = String(value).replace(/[^0-9.]/g, '');
|
||||
return currencySymbol + addComma(numericValue);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '150', title : '원화환산공급가액', field : 'EST_TOTAL_AMOUNT_KRW',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === '' || value === '0') return '';
|
||||
// 통화 기호 제거 후 콤마 추가
|
||||
var numericValue = String(value).replace(/[^0-9.]/g, '');
|
||||
return '₩' + addComma(numericValue);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '견적현황', field : 'EST_STATUS',
|
||||
// 10. 반납사유
|
||||
{headerHozAlign : 'center', hozAlign : 'left', minWidth: 60, widthGrow: 0.8, title : '반납사유', field : 'RETURN_REASON_SUMMARY' },
|
||||
// 11. 견적현황
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 50, widthGrow: 0.7, 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',
|
||||
// 12. 결재상태
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 50, widthGrow: 0.7, title : '결재상태', field : 'APPR_STATUS',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
cellClick:function(e, cell){
|
||||
var APPROVAL_OBJID = fnc_checkNull(cell.getData().APPROVAL_OBJID);
|
||||
@@ -342,11 +364,10 @@ var columns = [
|
||||
approval_form(APPROVAL_OBJID,ROUTE_OBJID);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '메일발송', field : 'MAIL_SEND_STATUS',
|
||||
// 13. 메일발송
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 50, widthGrow: 0.7, title : '메일발송', field : 'MAIL_SEND_STATUS',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var status = fnc_checkNull(cell.getValue());
|
||||
var sendDate = fnc_checkNull(cell.getData().MAIL_SEND_DATE);
|
||||
|
||||
if(status === 'Y'){
|
||||
return '<span style="color:green;">발송완료</span>';
|
||||
} else if(status === 'N'){
|
||||
@@ -354,36 +375,65 @@ var columns = [
|
||||
} else {
|
||||
return '<span style="color:#999;">미발송</span>';
|
||||
}
|
||||
// if(status === 'Y'){
|
||||
// return '<span style="color:green;">발송완료</span><br/><span style="font-size:11px;">' + sendDate + '</span>';
|
||||
// } else if(status === 'N'){
|
||||
// return '<span style="color:red;">발송실패</span><br/><span style="font-size:11px;">' + sendDate + '</span>';
|
||||
// } else {
|
||||
// return '<span style="color:#999;">미발송</span>';
|
||||
// }
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', width : '80', title : '환종', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '80', title : '환율', field : 'EXCHANGE_RATE',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
|
||||
}
|
||||
},
|
||||
// 14. 견적공급가액
|
||||
{headerHozAlign : 'center', hozAlign : 'right', minWidth: 80, widthGrow: 1, title : '견적공급가액', field : 'EST_TOTAL_AMOUNT',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === '' || value === '0') return '';
|
||||
var rowData = cell.getRow().getData();
|
||||
var currencyName = fnc_checkNull(rowData.CONTRACT_CURRENCY_NAME) || '';
|
||||
// 통화 이름을 기호로 변환
|
||||
var currencySymbol = '';
|
||||
if(currencyName.includes('원') || currencyName === 'KRW') currencySymbol = '₩';
|
||||
else if(currencyName.includes('달러') || currencyName === 'USD') currencySymbol = '$';
|
||||
else if(currencyName.includes('유로') || currencyName === 'EUR') currencySymbol = '€';
|
||||
else if(currencyName.includes('엔') || currencyName === 'JPY') currencySymbol = '¥';
|
||||
else if(currencyName.includes('위안') || currencyName === 'CNY') currencySymbol = '¥';
|
||||
// 통화 기호 제거 후 콤마 추가
|
||||
var numericValue = String(value).replace(/[^0-9.]/g, '');
|
||||
return currencySymbol + addComma(numericValue);
|
||||
}
|
||||
},
|
||||
// 15. 견적원화환산공급가액
|
||||
{headerHozAlign : 'center', hozAlign : 'right', minWidth: 110, widthGrow: 1, title : '견적원화환산공급가액', field : 'EST_TOTAL_AMOUNT_KRW',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === '' || value === '0') return '';
|
||||
// 통화 기호 제거 후 콤마 추가
|
||||
var numericValue = String(value).replace(/[^0-9.]/g, '');
|
||||
return '₩' + addComma(numericValue);
|
||||
}
|
||||
},
|
||||
// 16. 견적환종
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth: 45, widthGrow: 0.6, title : '견적환종', field : 'CONTRACT_CURRENCY_NAME' },
|
||||
// 17. 견적환율
|
||||
{headerHozAlign : 'center', hozAlign : 'right', minWidth: 50, widthGrow: 0.7, title : '견적환율', field : 'EXCHANGE_RATE',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
|
||||
}
|
||||
},
|
||||
|
||||
/* 아래는 주석처리된 컬럼들 - 필요시 활성화 */
|
||||
/*
|
||||
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '견적수량', field : 'ESTIMATE_QUANTITY',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === '0') return '';
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
{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>';
|
||||
},
|
||||
@@ -392,20 +442,7 @@ var columns = [
|
||||
fn_showSerialNoPopup(serialNo);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'left', width : '100', title : '품번', field : 'PART_NO' },
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '견적단가', field : 'EST_PRICE' },
|
||||
|
||||
// {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' },
|
||||
@@ -631,6 +668,8 @@ function fn_showEstimateList(contractObjId){
|
||||
statusColor = 'red';
|
||||
} else if(apprStatus === '작성중') {
|
||||
statusColor = '#999';
|
||||
} else if(apprStatus === '결재불필요') {
|
||||
statusColor = '#6c757d'; // 회색
|
||||
}
|
||||
|
||||
html += '<tr style="cursor: pointer;" onclick="fn_openEstimateByObjId(\'' + objid + '\', \'' + templateType + '\')">';
|
||||
@@ -922,113 +961,106 @@ function openProjectFormPopUp(objId){
|
||||
</div>
|
||||
</div>
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="category_cd">주문유형</label></td>
|
||||
<td>
|
||||
<select name="category_cd" id="category_cd" style="width:150px" class="select2" autocomplete="off">
|
||||
<div style="display: flex; flex-wrap: wrap; gap: 10px 15px; align-items: center;">
|
||||
<!-- 주문유형 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="category_cd">주문유형</label>
|
||||
<select name="category_cd" id="category_cd" style="width:130px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
${code_map.category_cd}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<%--
|
||||
<td><label for="product">제품구분</label></td>
|
||||
<td>
|
||||
</div>
|
||||
|
||||
<!-- 제품구분 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="product">제품구분</label>
|
||||
<select name="product" id="product" style="width:130px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
${code_map.product_cd}
|
||||
</select>
|
||||
</td>
|
||||
</div>
|
||||
|
||||
<td><label for="area_cd">국내/해외</label></td>
|
||||
<td>
|
||||
<select name="area_cd" id="area_cd" style="width:130px" class="select2" autocomplete="off">
|
||||
<!-- 국내/해외 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="area_cd">국내/해외</label>
|
||||
<select name="area_cd" id="area_cd" style="width:100px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
<option value="0001220">국내</option>
|
||||
<option value="0001221">해외</option>
|
||||
</select>
|
||||
</td>
|
||||
--%>
|
||||
|
||||
<td><label for="customer_objid">고객사</label></td>
|
||||
<td>
|
||||
<select name="customer_objid" id="customer_objid" style="width:190px" class="select2" autocomplete="off">
|
||||
</div>
|
||||
|
||||
<!-- 고객사 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="customer_objid">고객사</label>
|
||||
<select name="customer_objid" id="customer_objid" style="width:180px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
${code_map.customer_cd}
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<%--
|
||||
<td><label for="paid_type">유/무상</label></td>
|
||||
<td>
|
||||
<select name="paid_type" id="paid_type" style="width:130px" class="select2" autocomplete="off">
|
||||
</div>
|
||||
|
||||
<!-- 유/무상 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="paid_type">유/무상</label>
|
||||
<select name="paid_type" id="paid_type" style="width:100px" class="select2" autocomplete="off">
|
||||
<option value="">선택</option>
|
||||
<option value="paid">유상</option>
|
||||
<option value="free">무상</option>
|
||||
</select>
|
||||
</td>
|
||||
--%>
|
||||
</div>
|
||||
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name="search_partNo" id="search_partNo" class="select2-part" style="width: 100%;">
|
||||
<!-- 품번 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_partNo">품번</label>
|
||||
<select name="search_partNo" id="search_partNo" class="select2-part" style="width:130px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="search_partObjId" id="search_partObjId" value=""/>
|
||||
</td>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name="search_partName" id="search_partName" class="select2-part" style="width: 100%;">
|
||||
</div>
|
||||
|
||||
<!-- 품명 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_partName">품명</label>
|
||||
<select name="search_partName" id="search_partName" class="select2-part" style="width:130px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
</div>
|
||||
|
||||
<td class="">
|
||||
<label for="" class="">S/N</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="search_serialNo" id="search_serialNo" value="${param.search_serialNo}"/>
|
||||
</td>
|
||||
<!-- S/N -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="search_serialNo">S/N</label>
|
||||
<input type="text" name="search_serialNo" id="search_serialNo" style="width:120px;" value="${param.search_serialNo}"/>
|
||||
</div>
|
||||
|
||||
<td><label for="">결재상태</label></td>
|
||||
<td>
|
||||
<select name="appr_status" id="appr_status" class="select2" autocomplete="off" style="width:130px">
|
||||
<!-- 결재상태 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label for="appr_status">결재상태</label>
|
||||
<select name="appr_status" id="appr_status" class="select2" autocomplete="off" style="width:100px">
|
||||
<option value="">선택</option>
|
||||
<%-- ${code_map.appr_status} --%>
|
||||
<option value="작성중">작성중</option>
|
||||
<option value="결재중">결재중</option>
|
||||
<option value="반려">반려</option>
|
||||
<option value="결재완료">결재완료</option>
|
||||
<option value="결재불필요">결재불필요</option>
|
||||
<option value="취소">취소</option>
|
||||
</select>
|
||||
</td>
|
||||
</div>
|
||||
|
||||
<td class="">
|
||||
<!-- 접수일 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label>접수일</label>
|
||||
</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="receipt_start_date" id="receipt_start_date" style="width:90px;" autocomplete="off" value="${param.receipt_start_date}" class="date_icon">~
|
||||
<input type="text" name="receipt_end_date" id="receipt_end_date" style="width:90px;" autocomplete="off" value="${param.receipt_end_date}" class="date_icon">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<%--<tr>
|
||||
<td class="">
|
||||
</div>
|
||||
|
||||
<!-- 요청납기 -->
|
||||
<div style="display: flex; align-items: center; gap: 5px;">
|
||||
<label>요청납기</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="due_start_date" id="due_start_date" style="width:90px;" autocomplete="off" value="${param.due_start_date}" class="date_icon">~
|
||||
<input type="text" name="due_end_date" id="due_end_date" style="width:90px;" autocomplete="off" value="${param.due_end_date}" class="date_icon">
|
||||
</td>
|
||||
</tr>--%>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
|
||||
</div>
|
||||
|
||||
@@ -63,11 +63,11 @@
|
||||
$(".SELECT").show();
|
||||
}
|
||||
|
||||
if("${info.CONTRACT_RESULT}" == "0000964"){//수주
|
||||
$("#category_cd,#area_cd,#target_project_no,#customer_objid,#product,#contract_result,#overhaul_order").prop("disabled","disabled");
|
||||
$("#mechanical_type,#facility_qty,#target_project_no_direct").prop("readonly", true);
|
||||
//$("#overhaul_order,#mechanical_type,#facility_qty,#target_project_no_direct").prop("readonly", true);
|
||||
}
|
||||
// 수주 확정 후에도 정보 수정 가능하도록 주석처리
|
||||
// if("${info.CONTRACT_RESULT}" == "0000964"){//수주
|
||||
// $("#category_cd,#area_cd,#target_project_no,#customer_objid,#product,#contract_result,#overhaul_order").prop("disabled","disabled");
|
||||
// $("#mechanical_type,#facility_qty,#target_project_no_direct").prop("readonly", true);
|
||||
// }
|
||||
|
||||
if ("${actionType}" == "U") {
|
||||
$("#btnSave").remove();
|
||||
@@ -506,23 +506,23 @@
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_due_date[]" class="item-due-date date_icon" style="width:90%; padding:5px;" value="' + dueDate + '" />';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:95%; padding:5px; min-height:34px; resize:vertical; font-family:inherit; font-size:inherit;" rows="1"></textarea>';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<select name="item_return_reason[]" class="item-return-reason select2" style="width:95%;"></select>';
|
||||
html += '</td>';
|
||||
html += '<td style="text-align:center; padding:5px; border:1px solid #ddd;">';
|
||||
html += '<button type="button" onclick="fn_deleteItemRow(\'' + itemId + '\')" class="plm_btns" style="padding:5px 10px; font-size:12px;">삭제</button>';
|
||||
html += '</td>';
|
||||
html += '</tr>';
|
||||
|
||||
$("#itemListBody").append(html);
|
||||
|
||||
// 고객요청사항 값 설정 (안전하게 text로 설정)
|
||||
if(customerRequest) {
|
||||
$("#" + itemId + " .item-customer-request").val(customerRequest);
|
||||
}
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<select name="item_return_reason[]" class="item-return-reason select2" style="width:95%;"></select>';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:95%; padding:5px; min-height:34px; resize:vertical; font-family:inherit; font-size:inherit;" rows="1"></textarea>';
|
||||
html += '</td>';
|
||||
html += '<td style="text-align:center; padding:5px; border:1px solid #ddd;">';
|
||||
html += '<button type="button" onclick="fn_deleteItemRow(\'' + itemId + '\')" class="plm_btns" style="padding:5px 10px; font-size:12px;">삭제</button>';
|
||||
html += '</td>';
|
||||
html += '</tr>';
|
||||
|
||||
$("#itemListBody").append(html);
|
||||
|
||||
// 고객요청사항 값 설정 (안전하게 text로 설정)
|
||||
if(customerRequest) {
|
||||
$("#" + itemId + " .item-customer-request").val(customerRequest);
|
||||
}
|
||||
|
||||
// S/N 데이터 설정 - JSON 객체를 문자열로 변환하여 저장
|
||||
var snJsonString = JSON.stringify(snJsonData);
|
||||
@@ -1289,21 +1289,21 @@
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<input type="text" name="item_due_date[]" class="item-due-date date_icon" style="width:90%; padding:5px;" />';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:95%; padding:5px; min-height:34px; resize:vertical; font-family:inherit; font-size:inherit;" rows="1"></textarea>';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<select name="item_return_reason[]" class="item-return-reason select2" style="width:95%;"></select>';
|
||||
html += '</td>';
|
||||
html += '<td style="text-align:center; padding:5px; border:1px solid #ddd;">';
|
||||
html += '<button type="button" onclick="fn_deleteItemRow(\'' + itemId + '\')" class="plm_btns" style="padding:5px 10px; font-size:12px;">삭제</button>';
|
||||
html += '</td>';
|
||||
html += '</tr>';
|
||||
|
||||
$("#itemListBody").append(html);
|
||||
|
||||
// 품번/품명 옵션 채우기 (신규 추가)
|
||||
fn_fillPartOptions(itemId, null, null, null);
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<select name="item_return_reason[]" class="item-return-reason select2" style="width:95%;"></select>';
|
||||
html += '</td>';
|
||||
html += '<td style="padding:5px; border:1px solid #ddd;">';
|
||||
html += '<textarea name="item_customer_request[]" class="item-customer-request" style="width:95%; padding:5px; min-height:34px; resize:vertical; font-family:inherit; font-size:inherit;" rows="1"></textarea>';
|
||||
html += '</td>';
|
||||
html += '<td style="text-align:center; padding:5px; border:1px solid #ddd;">';
|
||||
html += '<button type="button" onclick="fn_deleteItemRow(\'' + itemId + '\')" class="plm_btns" style="padding:5px 10px; font-size:12px;">삭제</button>';
|
||||
html += '</td>';
|
||||
html += '</tr>';
|
||||
|
||||
$("#itemListBody").append(html);
|
||||
|
||||
// 품번/품명 옵션 채우기 (신규 추가)
|
||||
fn_fillPartOptions(itemId, null, null, null);
|
||||
|
||||
// 추가된 행의 날짜 필드에 datepicker 적용
|
||||
$("#" + itemId + " .date_icon").datepicker({
|
||||
@@ -2015,8 +2015,8 @@
|
||||
<col width="15%" /> <!-- S/N -->
|
||||
<col width="7%" /> <!-- 수량 -->
|
||||
<col width="10%" /> <!-- 요청납기 -->
|
||||
<col width="20%" /> <!-- 고객요청사항 -->
|
||||
<col width="15%" /> <!-- 반납사유 -->
|
||||
<col width="15%" /> <!-- 반납사유 -->
|
||||
<col width="20%" /> <!-- 고객요청사항 -->
|
||||
<col width="5%" /> <!-- 삭제 -->
|
||||
</colgroup>
|
||||
<thead>
|
||||
@@ -2027,8 +2027,8 @@
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">S/N</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">견적수량 <span style="color:red;">*</span></th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">요청납기</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">고객요청사항</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">반납사유</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">반납사유</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">고객요청사항</th>
|
||||
<th style="text-align:center; padding:8px; border:1px solid #ddd;">삭제</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -67,16 +67,18 @@
|
||||
|
||||
.item-table thead th {
|
||||
background-color: #f8f9fa;
|
||||
padding: 10px;
|
||||
padding: 6px;
|
||||
text-align: center;
|
||||
border: 1px solid #dee2e6;
|
||||
font-weight: bold;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.item-table tbody td {
|
||||
padding: 8px;
|
||||
padding: 5px;
|
||||
border: 1px solid #dee2e6;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.item-table tbody td.text-left {
|
||||
@@ -113,7 +115,7 @@ $(function() {
|
||||
</head>
|
||||
<body>
|
||||
<div class="popup-container">
|
||||
<!-- 영업정보 섹션 -->
|
||||
<%-- 영업정보 섹션 (품목정보에서 다 표시하므로 주석처리)
|
||||
<div class="section-title">영업정보</div>
|
||||
<table class="info-table">
|
||||
<colgroup>
|
||||
@@ -122,68 +124,97 @@ $(function() {
|
||||
<col width="15%">
|
||||
<col width="35%">
|
||||
</colgroup>
|
||||
<tr>
|
||||
<th>주문유형</th>
|
||||
<td>${info.CATEGORY_NAME}</td>
|
||||
<th>제품구분</th>
|
||||
<td>${info.PRODUCT_NAME}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>유/무상</th>
|
||||
<td>${info.PAID_TYPE_NAME}</td>
|
||||
<th>접수일</th>
|
||||
<td>${info.RECEIPT_DATE}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>국내/해외</th>
|
||||
<td>${info.AREA_NAME}</td>
|
||||
<th>고객사</th>
|
||||
<td>${info.CUSTOMER_NAME}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>주문유형</th>
|
||||
<td>${info.CATEGORY_NAME}</td>
|
||||
<th>제품구분</th>
|
||||
<td>${info.PRODUCT_NAME}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>국내/해외</th>
|
||||
<td>${info.AREA_NAME}</td>
|
||||
<th>고객사</th>
|
||||
<td>${info.CUSTOMER_NAME}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>유/무상</th>
|
||||
<td>${info.PAID_TYPE_NAME}</td>
|
||||
<th>견적환종</th>
|
||||
<td>${info.CONTRACT_CURRENCY_NAME}</td>
|
||||
</tr>
|
||||
</table>
|
||||
--%>
|
||||
|
||||
<!-- 품목정보 섹션 -->
|
||||
<div class="section-title">품목정보</div>
|
||||
<table class="item-table">
|
||||
<colgroup>
|
||||
<col width="3%">
|
||||
<col width="7%">
|
||||
<col width="7%">
|
||||
<col width="6%">
|
||||
<col width="10%">
|
||||
<col width="5%">
|
||||
<col width="15%">
|
||||
<col width="25%">
|
||||
<col width="15%">
|
||||
<col width="6%">
|
||||
<col width="10%">
|
||||
<col width="15%">
|
||||
<col width="15%">
|
||||
<col width="8%">
|
||||
<col width="8%">
|
||||
<col width="7%">
|
||||
<col width="8%">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>주문유형</th>
|
||||
<th>제품구분</th>
|
||||
<th>국내/해외</th>
|
||||
<th>고객사</th>
|
||||
<th>유/무상</th>
|
||||
<th>견적환종</th>
|
||||
<th>품번</th>
|
||||
<th>품명</th>
|
||||
<th>S/N</th>
|
||||
<th>요청납기</th>
|
||||
<th>고객요청사항</th>
|
||||
<th>반납사유</th>
|
||||
<th>고객요청사항</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<c:choose>
|
||||
<c:when test="${empty itemList}">
|
||||
<tr>
|
||||
<td colspan="7" style="text-align:center; padding:30px; color:#999;">
|
||||
등록된 품목이 없습니다.
|
||||
</td>
|
||||
<td>1</td>
|
||||
<td>${info["CATEGORY_NAME"]}</td>
|
||||
<td>${info["PRODUCT_NAME"]}</td>
|
||||
<td>${info["AREA_NAME"]}</td>
|
||||
<td>${info["CUSTOMER_NAME"]}</td>
|
||||
<td>${info["PAID_TYPE_NAME"]}</td>
|
||||
<td>${info["CONTRACT_CURRENCY_NAME"]}</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<c:forEach items="${itemList}" var="item" varStatus="status">
|
||||
<tr>
|
||||
<td>${status.count}</td>
|
||||
<td>${info["CATEGORY_NAME"]}</td>
|
||||
<td>${info["PRODUCT_NAME"]}</td>
|
||||
<td>${info["AREA_NAME"]}</td>
|
||||
<td>${info["CUSTOMER_NAME"]}</td>
|
||||
<td>${info["PAID_TYPE_NAME"]}</td>
|
||||
<td>${info["CONTRACT_CURRENCY_NAME"]}</td>
|
||||
<td>${item.part_no}</td>
|
||||
<td class="text-left">${item.part_name}</td>
|
||||
<td>${item.serial_nos}</td>
|
||||
<td>${item.due_date}</td>
|
||||
<td class="text-left">${item.customer_request}</td>
|
||||
<td>${item.return_reason}</td>
|
||||
<td class="text-left">${item.customer_request}</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
</c:otherwise>
|
||||
|
||||
@@ -2794,4 +2794,98 @@ public class ContractMgmtController {
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 결재 필요 여부 확인 (재오더/신규수주/가격인하 체크)
|
||||
* - 재오더 + 가격동일/인상: 결재불필요
|
||||
* - 신규수주 또는 가격인하: 결재필요
|
||||
* @param request
|
||||
* @param paramMap - contractObjId, customerObjId
|
||||
* @return approvalRequired (Y/N), reason (신규수주/가격인하/재오더)
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/contractMgmt/checkApprovalRequired.do", method=RequestMethod.POST)
|
||||
public Map<String, Object> checkApprovalRequired(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
String contractObjId = CommonUtils.checkNull(paramMap.get("contractObjId"));
|
||||
String customerObjId = CommonUtils.checkNull(paramMap.get("customerObjId"));
|
||||
|
||||
if(StringUtils.isBlank(contractObjId)) {
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", "견적 OBJID가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
if(StringUtils.isBlank(customerObjId)) {
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", "고객사 OBJID가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
paramMap.put("contractObjId", contractObjId);
|
||||
paramMap.put("customerObjId", customerObjId);
|
||||
|
||||
Map<String, Object> checkResult = contractMgmtService.checkApprovalRequired(paramMap);
|
||||
|
||||
if(checkResult != null) {
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("approvalRequired", CommonUtils.checkNull(checkResult.get("APPROVAL_REQUIRED")));
|
||||
resultMap.put("reason", CommonUtils.checkNull(checkResult.get("REASON")));
|
||||
} else {
|
||||
// 조회 결과가 없으면 신규수주로 간주 → 결재필요
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("approvalRequired", "Y");
|
||||
resultMap.put("reason", "신규수주");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 결재불필요 처리 (재오더 + 가격동일/인상인 경우)
|
||||
* 결재 프로세스 없이 바로 결재불필요 상태로 변경
|
||||
* @param request
|
||||
* @param paramMap - estObjId (견적서 OBJID)
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/contractMgmt/setApprovalNotRequired.do", method=RequestMethod.POST)
|
||||
public Map<String, Object> setApprovalNotRequired(HttpSession session, HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = CommonUtils.checkNull(person.getUserId());
|
||||
String estObjId = CommonUtils.checkNull(paramMap.get("estObjId"));
|
||||
|
||||
if(StringUtils.isBlank(estObjId)) {
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", "견적서 OBJID가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
paramMap.put("estObjId", estObjId);
|
||||
paramMap.put("userId", userId);
|
||||
|
||||
contractMgmtService.setApprovalNotRequired(paramMap);
|
||||
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("message", "결재불필요로 처리되었습니다.");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1692,6 +1692,7 @@ SELECT
|
||||
,A.CONTRACT_PRICE
|
||||
,A.CONTRACT_PRICE_CURRENCY
|
||||
,A.CONTRACT_CURRENCY
|
||||
,CODE_NAME(A.CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME
|
||||
,A.REGDATE
|
||||
,A.WRITER
|
||||
,A.CONTRACT_NO
|
||||
@@ -5434,4 +5435,122 @@ WHERE
|
||||
WHERE OBJID = #{customerObjId}::NUMERIC
|
||||
</select>
|
||||
|
||||
<!-- 결재 필요 여부 확인 (재오더/신규수주/가격인하 체크) -->
|
||||
<select id="checkApprovalRequired" parameterType="map" resultType="map">
|
||||
/* contractMgmt.checkApprovalRequired */
|
||||
WITH current_items AS (
|
||||
SELECT
|
||||
ETI.PART_OBJID,
|
||||
COALESCE(PM.PART_NO, ETI.PART_NO) AS PART_NO,
|
||||
CAST(COALESCE(NULLIF(ETI.SUPPLY_UNIT_PRICE, ''), '0') AS NUMERIC) AS CURRENT_PRICE
|
||||
FROM ESTIMATE_TEMPLATE ET
|
||||
INNER JOIN ESTIMATE_TEMPLATE_ITEM ETI ON ET.OBJID = ETI.TEMPLATE_OBJID
|
||||
LEFT JOIN PART_MNG PM ON ETI.PART_OBJID = PM.OBJID
|
||||
WHERE ET.CONTRACT_OBJID = #{contractObjId}::NUMERIC
|
||||
AND ET.OBJID = (
|
||||
SELECT OBJID FROM ESTIMATE_TEMPLATE
|
||||
WHERE CONTRACT_OBJID = #{contractObjId}::NUMERIC
|
||||
ORDER BY REGDATE DESC LIMIT 1
|
||||
)
|
||||
),
|
||||
previous_orders AS (
|
||||
SELECT
|
||||
CI.PART_OBJID,
|
||||
COALESCE(PM.PART_NO, CI.PART_NO) AS PART_NO,
|
||||
MAX(CAST(COALESCE(NULLIF(ETI.SUPPLY_UNIT_PRICE, ''), '0') AS NUMERIC)) AS PREV_MAX_PRICE
|
||||
FROM CONTRACT_MGMT CM
|
||||
INNER JOIN CONTRACT_ITEM CI ON CM.OBJID = CI.CONTRACT_OBJID AND CI.STATUS = 'ACTIVE'
|
||||
LEFT JOIN PART_MNG PM ON CI.PART_OBJID = PM.OBJID
|
||||
LEFT JOIN ESTIMATE_TEMPLATE ET ON ET.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN ESTIMATE_TEMPLATE_ITEM ETI ON ET.OBJID = ETI.TEMPLATE_OBJID
|
||||
AND (ETI.PART_OBJID = CI.PART_OBJID OR ETI.PART_NO = CI.PART_NO)
|
||||
WHERE CM.CUSTOMER_OBJID = #{customerObjId}
|
||||
AND CM.OBJID != #{contractObjId}::NUMERIC
|
||||
AND CM.STATUS != 'cancel'
|
||||
AND CM.CONTRACT_RESULT = '0000964'
|
||||
GROUP BY CI.PART_OBJID, COALESCE(PM.PART_NO, CI.PART_NO)
|
||||
)
|
||||
SELECT
|
||||
CASE
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM current_items CI
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM previous_orders PO
|
||||
WHERE (PO.PART_OBJID = CI.PART_OBJID AND CI.PART_OBJID IS NOT NULL)
|
||||
OR (PO.PART_NO = CI.PART_NO AND CI.PART_NO IS NOT NULL AND CI.PART_NO != '')
|
||||
)
|
||||
) THEN 'Y'
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM current_items CI
|
||||
INNER JOIN previous_orders PO
|
||||
ON (PO.PART_OBJID = CI.PART_OBJID AND CI.PART_OBJID IS NOT NULL)
|
||||
OR (PO.PART_NO = CI.PART_NO AND CI.PART_NO IS NOT NULL AND CI.PART_NO != '')
|
||||
WHERE CI.CURRENT_PRICE < PO.PREV_MAX_PRICE
|
||||
) THEN 'Y'
|
||||
ELSE 'N'
|
||||
END AS APPROVAL_REQUIRED,
|
||||
CASE
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM current_items CI
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM previous_orders PO
|
||||
WHERE (PO.PART_OBJID = CI.PART_OBJID AND CI.PART_OBJID IS NOT NULL)
|
||||
OR (PO.PART_NO = CI.PART_NO AND CI.PART_NO IS NOT NULL AND CI.PART_NO != '')
|
||||
)
|
||||
) THEN 'NEW_ORDER'
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM current_items CI
|
||||
INNER JOIN previous_orders PO
|
||||
ON (PO.PART_OBJID = CI.PART_OBJID AND CI.PART_OBJID IS NOT NULL)
|
||||
OR (PO.PART_NO = CI.PART_NO AND CI.PART_NO IS NOT NULL AND CI.PART_NO != '')
|
||||
WHERE CI.CURRENT_PRICE < PO.PREV_MAX_PRICE
|
||||
) THEN 'PRICE_DOWN'
|
||||
ELSE 'REORDER'
|
||||
END AS REASON
|
||||
</select>
|
||||
|
||||
<!-- 결재불필요 - APPROVAL 테이블 레코드 생성 -->
|
||||
<insert id="insertApprovalNotRequired" parameterType="map">
|
||||
/* contractMgmt.insertApprovalNotRequired */
|
||||
INSERT INTO APPROVAL (
|
||||
OBJID,
|
||||
TARGET_TYPE,
|
||||
TARGET_OBJID,
|
||||
APPROVAL_TITLE,
|
||||
WRITER,
|
||||
REGDATE
|
||||
) VALUES (
|
||||
#{OBJID}::NUMERIC,
|
||||
#{TARGET_TYPE},
|
||||
#{TARGET_OBJID}::NUMERIC,
|
||||
#{APPROVAL_TITLE},
|
||||
#{WRITER},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 결재불필요 - ROUTE 테이블 레코드 생성 -->
|
||||
<insert id="insertRouteNotRequired" parameterType="map">
|
||||
/* contractMgmt.insertRouteNotRequired */
|
||||
INSERT INTO ROUTE (
|
||||
OBJID,
|
||||
APPROVAL_OBJID,
|
||||
TARGET_OBJID,
|
||||
TARGET_TYPE,
|
||||
STATUS,
|
||||
ROUTE_SEQ,
|
||||
WRITER,
|
||||
REGDATE
|
||||
) VALUES (
|
||||
#{OBJID}::NUMERIC,
|
||||
#{APPROVAL_OBJID}::NUMERIC,
|
||||
#{TARGET_OBJID}::NUMERIC,
|
||||
#{TARGET_TYPE},
|
||||
#{STATUS},
|
||||
#{ROUTE_SEQ}::NUMERIC,
|
||||
#{WRITER},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
@@ -3629,4 +3629,80 @@ private String encodeImageToBase64(String imagePath) {
|
||||
System.out.println("Service 최종 반환값: " + projectInfo);
|
||||
return projectInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 결재 필요 여부 확인 (재오더/신규수주/가격인하 체크)
|
||||
* @param paramMap - contractObjId, customerObjId
|
||||
* @return approvalRequired (Y/N), reason (신규수주/가격인하/재오더)
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Map<String, Object> checkApprovalRequired(Map paramMap) {
|
||||
SqlSession sqlSession = null;
|
||||
Map<String, Object> result = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(true);
|
||||
|
||||
result = sqlSession.selectOne("contractMgmt.checkApprovalRequired", paramMap);
|
||||
|
||||
if(result != null) {
|
||||
result = CommonUtils.keyChangeUpperMap(result);
|
||||
}
|
||||
|
||||
} catch(Exception e) {
|
||||
System.out.println("❌ checkApprovalRequired 오류: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 결재불필요 처리 (재오더 + 가격동일/인상인 경우)
|
||||
* APPROVAL 테이블에 결재불필요 상태로 레코드 생성
|
||||
* @param paramMap - estObjId, userId
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void setApprovalNotRequired(Map paramMap) throws Exception {
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
String estObjId = CommonUtils.checkNull(paramMap.get("estObjId"));
|
||||
String userId = CommonUtils.checkNull(paramMap.get("userId"));
|
||||
|
||||
// APPROVAL 테이블에 결재불필요 레코드 생성
|
||||
Map<String, Object> approvalParam = new HashMap<String, Object>();
|
||||
approvalParam.put("OBJID", CommonUtils.createObjId());
|
||||
approvalParam.put("TARGET_TYPE", "CONTRACT_ESTIMATE");
|
||||
approvalParam.put("TARGET_OBJID", estObjId);
|
||||
approvalParam.put("APPROVAL_TITLE", "결재불필요");
|
||||
approvalParam.put("WRITER", userId);
|
||||
|
||||
sqlSession.insert("contractMgmt.insertApprovalNotRequired", approvalParam);
|
||||
|
||||
// ROUTE 테이블에 결재불필요 상태 레코드 생성
|
||||
Map<String, Object> routeParam = new HashMap<String, Object>();
|
||||
routeParam.put("OBJID", CommonUtils.createObjId());
|
||||
routeParam.put("APPROVAL_OBJID", approvalParam.get("OBJID"));
|
||||
routeParam.put("TARGET_OBJID", estObjId);
|
||||
routeParam.put("TARGET_TYPE", "CONTRACT_ESTIMATE");
|
||||
routeParam.put("STATUS", "notRequired"); // 결재불필요 상태
|
||||
routeParam.put("ROUTE_SEQ", "1");
|
||||
routeParam.put("WRITER", userId);
|
||||
|
||||
sqlSession.insert("contractMgmt.insertRouteNotRequired", routeParam);
|
||||
|
||||
sqlSession.commit();
|
||||
|
||||
} catch(Exception e) {
|
||||
if(sqlSession != null) sqlSession.rollback();
|
||||
throw e;
|
||||
} finally {
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user