Merge pull request 'V2025121901' (#121) from V2025121901 into main
Reviewed-on: #121
This commit was merged in pull request #121.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<%String objId = com.pms.common.utils.CommonUtils.checkNull(request.getParameter("objId"));%>
|
||||
<frameset cols="60%, 100px, 40%" border="0" noresize>
|
||||
<frameset cols="70%, 80px, 30%" border="0" noresize>
|
||||
<frame src="/productionplanning/mBomPopupLeft.do?objId=<%=objId%>" name="leftFrame">
|
||||
<frame src="/productionplanning/mBomPopupCenter.do?objId=<%=objId%>" name="centerFrame">
|
||||
<frame src="/productionplanning/mBomPopupRight.do?objId=<%=objId%>" name="rightFrame">
|
||||
|
||||
@@ -372,7 +372,7 @@ function fn_initGrid() {
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 60,
|
||||
width: 50,
|
||||
title: 'PDF',
|
||||
field: 'CU03_CNT',
|
||||
visible: true,
|
||||
@@ -416,7 +416,7 @@ function fn_initGrid() {
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 150,
|
||||
width: 100,
|
||||
title: '메이커',
|
||||
field: 'MAKER',
|
||||
visible: true
|
||||
@@ -424,7 +424,7 @@ function fn_initGrid() {
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 100,
|
||||
width: 70,
|
||||
title: '범주이름',
|
||||
field: 'PART_TYPE_TITLE',
|
||||
visible: true
|
||||
@@ -470,9 +470,9 @@ function fn_initGrid() {
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 100,
|
||||
title: '소재',
|
||||
title: '소재재질',
|
||||
field: 'RAW_MATERIAL',
|
||||
titleFormatter: function() { return '<span class="editable-header">소재</span>'; },
|
||||
titleFormatter: function() { return '<span class="editable-header">소재재질</span>'; },
|
||||
editor: function(cell, onRendered, success, cancel, editorParams) {
|
||||
// 소재 목록을 Select2용 형태로 변환
|
||||
var options = materialList.map(function(m) { return {id: m, text: m}; });
|
||||
@@ -499,9 +499,9 @@ function fn_initGrid() {
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 100,
|
||||
title: '사이즈',
|
||||
title: '규격',
|
||||
field: 'SIZE',
|
||||
titleFormatter: function() { return '<span class="editable-header">사이즈</span>'; },
|
||||
titleFormatter: function() { return '<span class="editable-header">규격</span>'; },
|
||||
editor: function(cell, onRendered, success, cancel, editorParams) {
|
||||
// 선택된 소재에 따라 동적으로 사이즈 목록 로드
|
||||
var data = cell.getRow().getData();
|
||||
@@ -578,14 +578,15 @@ function fn_initGrid() {
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
width: 90,
|
||||
title: '소재소요량',
|
||||
field: 'REQUIRED_QTY',
|
||||
titleFormatter: function() { return '<span class="editable-header">소재소요량</span>'; },
|
||||
editor: 'number',
|
||||
editorParams: {
|
||||
min: 0,
|
||||
step: 0.01 // 소수 가능
|
||||
step: 0.01,
|
||||
selectContents: true // 편집 시 기존 값 전체 선택
|
||||
},
|
||||
editable: function(cell) {
|
||||
return cell.getRow().getData().SUPPLY_TYPE === '사급';
|
||||
@@ -600,7 +601,7 @@ function fn_initGrid() {
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 120,
|
||||
width: 90,
|
||||
title: '소재발주수량',
|
||||
field: 'ORDER_QTY',
|
||||
editor: false,
|
||||
@@ -628,20 +629,22 @@ function fn_initGrid() {
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
width: 80,
|
||||
title: '제작수량',
|
||||
field: 'PRODUCTION_QTY',
|
||||
titleFormatter: function() { return '<span class="editable-header">제작수량</span>'; },
|
||||
editor: 'number',
|
||||
editorParams: {
|
||||
min: 0,
|
||||
step: 1
|
||||
step: 1,
|
||||
selectContents: true // 편집 시 기존 값 전체 선택
|
||||
},
|
||||
formatter: function(cell) {
|
||||
// 저장된 값이 있으면 그대로 사용, 없으면 항목수량 × 수주수량으로 계산
|
||||
var value = cell.getValue();
|
||||
|
||||
if(value === undefined || value === null || value === '' || value === 0) {
|
||||
// 0은 유효한 값이므로 제외 (undefined, null, '' 만 기본값 계산)
|
||||
if(value === undefined || value === null || value === '') {
|
||||
var data = cell.getRow().getData();
|
||||
var itemQty = parseFloat(data.ITEM_QTY) || 0;
|
||||
value = itemQty * projectQuantity;
|
||||
@@ -681,6 +684,18 @@ function fn_initGrid() {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
title: '가공단가',
|
||||
field: 'PROCESSING_UNIT_PRICE',
|
||||
editor: false, // 구매쪽에서 입력
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
return value ? Number(value).toLocaleString() : '-';
|
||||
}
|
||||
},
|
||||
/* 주석처리: 가공납기, 연삭납기 컬럼
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
@@ -736,30 +751,30 @@ function fn_initGrid() {
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
title: '단가',
|
||||
title: '소재단가',
|
||||
field: 'UNIT_PRICE',
|
||||
editor: false, // 구매쪽에서 입력
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
return value ? Number(value).toLocaleString() : '-';
|
||||
}
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
title: '금액',
|
||||
field: 'TOTAL_PRICE',
|
||||
editor: false,
|
||||
formatter: function(cell) {
|
||||
// 항목수량 × 단가
|
||||
var data = cell.getRow().getData();
|
||||
var itemQty = parseFloat(data.ITEM_QTY) || 0;
|
||||
var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
|
||||
var totalPrice = itemQty * unitPrice;
|
||||
return totalPrice > 0 ? totalPrice.toLocaleString() : '-';
|
||||
}
|
||||
}
|
||||
// {
|
||||
// headerHozAlign: 'center',
|
||||
// hozAlign: 'right',
|
||||
// width: 100,
|
||||
// title: '금액',
|
||||
// field: 'TOTAL_PRICE',
|
||||
// editor: false,
|
||||
// formatter: function(cell) {
|
||||
// // 항목수량 × 단가
|
||||
// var data = cell.getRow().getData();
|
||||
// var itemQty = parseFloat(data.ITEM_QTY) || 0;
|
||||
// var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
|
||||
// var totalPrice = itemQty * unitPrice;
|
||||
// return totalPrice > 0 ? totalPrice.toLocaleString() : '-';
|
||||
// }
|
||||
// }
|
||||
]
|
||||
});
|
||||
|
||||
@@ -1103,7 +1118,8 @@ function getMbomTreeData() {
|
||||
|
||||
// 구매 정보
|
||||
vendor: row.VENDOR || row.VENDOR_PM, // 공급업체 코드/OBJID (기존 값 유지)
|
||||
unitPrice: toNumber(row.UNIT_PRICE),
|
||||
unitPrice: toNumber(row.UNIT_PRICE), // 소재단가
|
||||
processingUnitPrice: toNumber(row.PROCESSING_UNIT_PRICE), // 가공단가
|
||||
// totalPrice 계산: 항목수량 × 단가
|
||||
totalPrice: (function() {
|
||||
var itemQty = parseFloat(row.ITEM_QTY) || 0;
|
||||
@@ -1130,19 +1146,35 @@ function getMbomTreeData() {
|
||||
|
||||
return mbomData;
|
||||
}
|
||||
|
||||
// 엑셀 다운로드 (CSV 형식)
|
||||
function fn_excel() {
|
||||
if(!_tabulGrid) {
|
||||
Swal.fire('데이터가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 파일명 생성 (현재 날짜 포함)
|
||||
var today = new Date();
|
||||
var dateStr = today.getFullYear() + '_' +
|
||||
String(today.getMonth() + 1).padStart(2, '0') + '_' +
|
||||
String(today.getDate()).padStart(2, '0') + '_' +
|
||||
String(today.getHours()).padStart(2, '0') + '_' +
|
||||
String(today.getMinutes()).padStart(2, '0');
|
||||
var fileName = 'M-BOM_' + dateStr + '.csv';
|
||||
|
||||
// Tabulator 내장 다운로드 기능 사용 (CSV)
|
||||
_tabulGrid.download("csv", fileName, {
|
||||
delimiter: ",",
|
||||
bom: true // 한글 깨짐 방지 (UTF-8 BOM)
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- <div id="mBomName">
|
||||
<c:choose>
|
||||
<c:when test="${not empty ebomInfo}">
|
||||
E-BOM: ${ebomInfo.PART_NO} - ${ebomInfo.PART_NAME}
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
할당된 E-BOM이 없습니다.
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</div> -->
|
||||
<div>
|
||||
<input type="button" value="Excel Download" class="plm_btns" id="btnExcel" style="float:right; margin-right: 5px; margin-bottom: 5px;" onclick="fn_excel();">
|
||||
</div>
|
||||
<div id="mBomTableWrap"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -51,8 +51,11 @@ body, html {
|
||||
<td>
|
||||
<input type="text" name="search_part_name" id="search_part_name" style="width: 98%;"value="">
|
||||
</td>
|
||||
<td>
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<!-- <tr>
|
||||
<td><label for="search_material">재료</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_material" id="search_material" style="width: 100%;" value="">
|
||||
@@ -63,10 +66,8 @@ body, html {
|
||||
<input type="text" name="search_supplier" id="search_supplier" style="width: 98%;" value="">
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</tr> -->
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -126,8 +127,8 @@ function initEbomTable() {
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", vertAlign:"middle", headerSort:false, width: 40},
|
||||
{title: "품번", field: "PART_NO", widthGrow: 1.5, vertAlign:"middle"},
|
||||
{title: "품명", field: "PART_NAME", widthGrow: 2, vertAlign:"middle"},
|
||||
{title: "재료", field: "MATERIAL", widthGrow: 1.2, vertAlign:"middle"},
|
||||
{title: "메이커", field: "MAKER", widthGrow: 1.5, vertAlign:"middle"}
|
||||
//{title: "재료", field: "MATERIAL", widthGrow: 1.2, vertAlign:"middle"},
|
||||
//{title: "메이커", field: "MAKER", widthGrow: 1.5, vertAlign:"middle"}
|
||||
],
|
||||
placeholder: "검색 결과가 없습니다."
|
||||
});
|
||||
|
||||
@@ -88,6 +88,7 @@ $(document).ready(function(){
|
||||
|
||||
var columns = [
|
||||
// 요구사항: 품의서 No, 발주서 No, 프로젝트번호, 품번, 품명, 공급업체, 발주수량, 입고수량, 미입고수량, 검사성적서, 입고결과
|
||||
{title:'STATUS' ,field:'STATUS' ,visible:false, frozen:true},
|
||||
{title:'TOTAL_SUPPLY_PRICE' ,field:'TOTAL_SUPPLY_PRICE' ,visible:false, frozen:true},
|
||||
{title:'TOTAL_DELIVERY_PRICE' ,field:'TOTAL_DELIVERY_PRICE' ,visible:false, frozen:true},
|
||||
{title:'TOTAL_NOT_DELIVERY_PRICE',field:'TOTAL_NOT_DELIVERY_PRICE',visible:false, frozen:true},
|
||||
@@ -127,15 +128,36 @@ var columns = [
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 90, widthGrow : 1, title : '입고결과', field : 'DELIVERY_STATUS',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
cellClick:function(e, cell){
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var status = fnc_checkNull(cell.getData().STATUS);
|
||||
var deliveryStatus = fnc_checkNull(cell.getValue());
|
||||
|
||||
// 발주취소 상태인 경우
|
||||
if(status === 'orderCancel'){
|
||||
return '<span style="color:red; font-weight:bold;">발주취소</span>';
|
||||
}
|
||||
|
||||
// 일반 상태 - 링크로 표시
|
||||
if(deliveryStatus != ''){
|
||||
return '<a href="#none" style="color:#0000EE">' + deliveryStatus + '</a>';
|
||||
}
|
||||
return deliveryStatus;
|
||||
},
|
||||
cellClick:function(e, cell){
|
||||
var status = fnc_checkNull(cell.getData().STATUS);
|
||||
|
||||
// 발주취소 상태인 경우 팝업 열지 않음
|
||||
if(status === 'orderCancel'){
|
||||
return;
|
||||
}
|
||||
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
var DELIVERY_STATUS = fnc_checkNull(cell.getData().DELIVERY_STATUS);
|
||||
var purchaseOrderNo = fnc_checkNull(cell.getData().PURCHASE_ORDER_NO);
|
||||
fn_deliveryAcceptanceViewPopUp(objId,DELIVERY_STATUS);
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 140, widthGrow : 1, title : '매입마감', field : 'PURCHASE_CLOSE_DATE'}
|
||||
}
|
||||
// {headerHozAlign : 'center', hozAlign : 'center', minWidth : 140, widthGrow : 1, title : '매입마감', field : 'PURCHASE_CLOSE_DATE'}
|
||||
];
|
||||
|
||||
//var grid;
|
||||
@@ -219,7 +241,14 @@ function fn_deliveryAcceptancePopUp(){
|
||||
if(selected.length > 1){
|
||||
Swal.fire("한건씩 등록 가능합니다.");
|
||||
return;
|
||||
}else{
|
||||
}else{
|
||||
// 발주취소 상태 체크
|
||||
var status = fnc_checkNull(selected[0].STATUS);
|
||||
if(status === 'orderCancel'){
|
||||
Swal.fire("발주취소된 건은 입고등록할 수 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
var MULTI_MASTER_YN = fnc_checkNull(selected[0].MULTI_MASTER_YN);
|
||||
var MULTI_YN = fnc_checkNull(selected[0].MULTI_YN);
|
||||
|
||||
@@ -472,7 +501,7 @@ function fn_purchaseClose(){
|
||||
<div class="btnArea">
|
||||
<input type="button" class="plm_btns" value="조회" id="btnSearch">
|
||||
<input type="button" class="plm_btns" value="입고등록" id="btnAccept">
|
||||
<input type="button" class="plm_btns" value="매입마감" id="btnClose">
|
||||
<!-- <input type="button" class="plm_btns" value="매입마감" id="btnClose"> -->
|
||||
<%-- <input type="button" class="plm_btns" value="부적합등록" id="btnInvaild"> --%>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -76,6 +76,11 @@ $(document).ready(function(){
|
||||
fn_sendPurchaseOrder();
|
||||
});
|
||||
|
||||
// 발주 취소 버튼 클릭
|
||||
$("#btnOrderCancel").click(function(){
|
||||
fn_orderCancel();
|
||||
});
|
||||
|
||||
//수주활동 복사 팝업
|
||||
$("#btnCopy").click(function(){
|
||||
var checkedObj = _tabulGrid.getSelectedData();
|
||||
@@ -352,7 +357,11 @@ var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'center', widthGrow:1, title:'메일발송', field:'MAIL_SEND_YN',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var value = fnc_checkNull(cell.getValue());
|
||||
if(value === 'Y'){
|
||||
var status = fnc_checkNull(cell.getData().STATUS);
|
||||
// 발주취소 상태인 경우
|
||||
if(status === 'orderCancel'){
|
||||
return '<span style="color:red; font-weight:bold;">발주취소</span>';
|
||||
} else if(value === 'Y'){
|
||||
return '<span style="color:green;">발송완료</span>';
|
||||
} else {
|
||||
return '';
|
||||
@@ -771,7 +780,7 @@ function fn_sendPurchaseOrder(){
|
||||
var mailSendYn = fnc_checkNull(selectedData[0].MAIL_SEND_YN);
|
||||
|
||||
// 취소 상태 확인
|
||||
if(status === "cancel"){
|
||||
if(status === "cancel" || status === "orderCancel"){
|
||||
Swal.fire("취소된 발주서는 발송할 수 없습니다.");
|
||||
return false;
|
||||
}
|
||||
@@ -817,6 +826,119 @@ function fn_openMailFormPopup(purchaseOrderObjId){
|
||||
window.open(url, "purchaseOrderMailForm", "width="+popup_width+",height="+popup_height+",menubar=no,scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
// 발주 취소
|
||||
function fn_orderCancel(){
|
||||
var selectedData = _tabulGrid.getSelectedData();
|
||||
|
||||
if(selectedData.length < 1){
|
||||
Swal.fire("발주 취소할 행을 선택해주세요.");
|
||||
return false;
|
||||
} else if(selectedData.length > 1){
|
||||
Swal.fire("한번에 한 개의 발주서만 취소 가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var objId = fnc_checkNull(selectedData[0].OBJID);
|
||||
var status = fnc_checkNull(selectedData[0].STATUS);
|
||||
var MULTI_YN = fnc_checkNull(selectedData[0].MULTI_YN);
|
||||
var MULTI_MASTER_YN = fnc_checkNull(selectedData[0].MULTI_MASTER_YN);
|
||||
var purchaseOrderNo = fnc_checkNull(selectedData[0].PURCHASE_ORDER_NO);
|
||||
|
||||
// 이미 취소된 상태 확인
|
||||
if(status === 'cancel'){
|
||||
Swal.fire("이미 취소된 발주서입니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 이미 발주취소된 상태 확인
|
||||
if(status === 'orderCancel'){
|
||||
Swal.fire("이미 발주취소된 발주서입니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 동시발주 하위건 확인
|
||||
if(MULTI_YN === 'Y' && MULTI_MASTER_YN !== 'Y'){
|
||||
Swal.fire("동시발주 하위건은 마스터건으로 취소해주세요.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 입고 여부 확인 후 취소 진행
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/purchaseOrder/checkReceiptForCancel.do",
|
||||
data: { PURCHASE_ORDER_MASTER_OBJID: objId },
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if(data.hasReceipt){
|
||||
// 입고된 항목이 있는 경우
|
||||
Swal.fire({
|
||||
title: '취소 불가',
|
||||
html: '입고된 항목이 있어 발주 취소가 불가합니다.<br/><br/>' +
|
||||
'<span style="color:#666;">입고수량: ' + data.totalReceiptQty + '개</span>',
|
||||
icon: 'error'
|
||||
});
|
||||
} else {
|
||||
// 입고된 항목이 없는 경우 - 취소 확인
|
||||
Swal.fire({
|
||||
title: '발주 취소',
|
||||
html: '발주서 <strong>' + purchaseOrderNo + '</strong>을(를) 취소하시겠습니까?<br/><br/>' +
|
||||
'<span style="color:#666; font-size:12px;">취소 후에도 목록에서 확인 가능하며, 메일발송 컬럼에 "발주취소"로 표시됩니다.</span>',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
confirmButtonText: '취소하기',
|
||||
cancelButtonText: '닫기'
|
||||
}).then((result) => {
|
||||
if(result.isConfirmed){
|
||||
fn_executeOrderCancel(objId);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("입고 확인 오류:", error);
|
||||
Swal.fire("입고 확인 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 발주 취소 실행
|
||||
function fn_executeOrderCancel(objId){
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/purchaseOrder/executeOrderCancel.do",
|
||||
data: { PURCHASE_ORDER_MASTER_OBJID: objId },
|
||||
dataType: "json",
|
||||
beforeSend: function(){
|
||||
_startLoading("처리중입니다.");
|
||||
},
|
||||
complete: function(){
|
||||
_endLoading();
|
||||
},
|
||||
success: function(data){
|
||||
if(data.result){
|
||||
Swal.fire({
|
||||
title: '완료',
|
||||
text: '발주가 취소되었습니다.',
|
||||
icon: 'success'
|
||||
}).then(() => {
|
||||
fn_search();
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: data.message || '발주 취소 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("발주 취소 오류:", error);
|
||||
Swal.fire("발주 취소 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
<body class="<%--bodyNoScrollX--%>">
|
||||
<form name="hiddenForm" id="hiddenForm" method="post">
|
||||
@@ -842,6 +964,7 @@ function fn_openMailFormPopup(purchaseOrderObjId){
|
||||
<input type="button" class="plm_btns" value="삭제" id="btnDelete">
|
||||
<input type="button" class="plm_btns" value="저장" id="btnSave"> -->
|
||||
<input type="button" class="plm_btns" value="발주서 송부" id="btnSend">
|
||||
<input type="button" class="plm_btns" value="발주 취소" id="btnOrderCancel" style="background-color:#dc3545; border-color:#dc3545;">
|
||||
<input type="button" class="plm_btns" value="조회" id="btnSearch">
|
||||
</div>
|
||||
|
||||
|
||||
@@ -191,7 +191,14 @@ String purchaseOrderObjId = request.getParameter("purchaseOrderObjId");
|
||||
|
||||
<div class="attachment-status">
|
||||
<i class="fa fa-file-pdf-o"></i>
|
||||
<strong>첨부파일:</strong> 발주서(PDF) 및 도면 파일이 자동으로 첨부됩니다.
|
||||
<strong>첨부파일:</strong> 발주서(PDF)가 자동으로 첨부됩니다.
|
||||
<div style="margin-top: 8px;">
|
||||
<label style="display: inline-flex; align-items: center; cursor: pointer; font-weight: normal;">
|
||||
<input type="checkbox" id="includeDrawingFiles" name="includeDrawingFiles" checked style="width: 16px; height: 16px; margin-right: 6px;">
|
||||
<span>도면 파일 첨부</span>
|
||||
</label>
|
||||
<span id="drawingFileCount" style="margin-left: 10px; color: #666; font-size: 12px;"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="mailForm">
|
||||
@@ -291,6 +298,9 @@ function fn_loadPurchaseOrderInfo(){
|
||||
} else {
|
||||
$("#managerListContainer").html('<div class="no-managers">공급업체 정보가 없습니다.</div>');
|
||||
}
|
||||
|
||||
// 도면 파일 개수 조회
|
||||
fn_loadDrawingFileCount(purchaseOrderObjId);
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
@@ -313,6 +323,31 @@ function fn_loadPurchaseOrderInfo(){
|
||||
});
|
||||
}
|
||||
|
||||
// 도면 파일 개수 조회
|
||||
function fn_loadDrawingFileCount(purchaseOrderObjId){
|
||||
$.ajax({
|
||||
url: "/purchaseOrder/getDrawingFileCount.do",
|
||||
type: "POST",
|
||||
data: { objId: purchaseOrderObjId },
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if(data.result === "success"){
|
||||
var count = parseInt(data.count) || 0;
|
||||
if(count > 0){
|
||||
$("#drawingFileCount").text("(" + count + "개 파일)");
|
||||
} else {
|
||||
$("#drawingFileCount").text("(파일 없음)");
|
||||
$("#includeDrawingFiles").prop("checked", false);
|
||||
$("#includeDrawingFiles").prop("disabled", true);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
$("#drawingFileCount").text("(조회 실패)");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 공급업체 담당자 목록 로드
|
||||
function fn_loadPartnerManagers(partnerObjId){
|
||||
$.ajax({
|
||||
@@ -669,7 +704,8 @@ function fn_submitMailForm(){
|
||||
toEmails: $("#toEmails").val(),
|
||||
ccEmails: $("#ccEmails").val(),
|
||||
subject: $("#subject").val(),
|
||||
contents: $("#contents").val()
|
||||
contents: $("#contents").val(),
|
||||
includeDrawingFiles: $("#includeDrawingFiles").is(":checked") ? "Y" : "N"
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
|
||||
@@ -461,32 +461,8 @@ function fn_initGrid() {
|
||||
title: '지급/사급',
|
||||
field: 'SUPPLY_TYPE'
|
||||
},
|
||||
// 17. 소재
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 100,
|
||||
title: '소재',
|
||||
field: 'RAW_MATERIAL'
|
||||
},
|
||||
// 18. 사이즈
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 100,
|
||||
title: '사이즈',
|
||||
field: 'SIZE'
|
||||
},
|
||||
// 19. 소재품번
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 120,
|
||||
title: '소재품번',
|
||||
field: 'RAW_MATERIAL_NO'
|
||||
},
|
||||
// 20. 소재소요량
|
||||
{
|
||||
// 20. 소재소요량
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
@@ -529,27 +505,46 @@ function fn_initGrid() {
|
||||
return value ? Number(value).toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
// 24. 가공업체 (수정가능 - Select2 에디터)
|
||||
|
||||
// 17. 소재 -> 소재재질
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 100,
|
||||
title: '소재재질',
|
||||
field: 'RAW_MATERIAL'
|
||||
},
|
||||
// 18. 사이즈 -> 규격
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 100,
|
||||
title: '규격',
|
||||
field: 'SIZE'
|
||||
},
|
||||
// 19. 소재품번
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 120,
|
||||
title: '소재품번',
|
||||
field: 'RAW_MATERIAL_NO'
|
||||
},
|
||||
// 30. 공급업체 (수정가능 - Select2 에디터)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 150,
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">가공업체</span>',
|
||||
field: 'PROCESSING_VENDOR',
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">공급업체</span>',
|
||||
field: 'VENDOR_PM',
|
||||
editor: function(cell, onRendered, success, cancel, editorParams) {
|
||||
// Select2 에디터
|
||||
// Select2 에디터 (가공업체와 동일한 목록 사용)
|
||||
return createSelect2Editor(processingVendorList)(cell, onRendered, success, cancel, editorParams);
|
||||
},
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
|
||||
// 저장된 값이 없으면 기본값 '5001'(RPS) 설정
|
||||
if(value === undefined || value === null || value === '') {
|
||||
value = '5001';
|
||||
cell.getRow().update({PROCESSING_VENDOR: value}, false);
|
||||
}
|
||||
|
||||
// OBJID로 업체명 조회하여 표시
|
||||
if(!value) return '';
|
||||
// processingVendorList에서 해당 값의 이름 찾기
|
||||
for(var i = 0; i < processingVendorList.length; i++) {
|
||||
if(processingVendorList[i].id == value) {
|
||||
return processingVendorList[i].text;
|
||||
@@ -558,27 +553,41 @@ function fn_initGrid() {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
/* // 25. 가공납기 - 주석처리
|
||||
// 31. 단가 (수정가능) -> 소재단가
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
title: '가공납기',
|
||||
field: 'PROCESSING_DEADLINE'
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">소재단가</span>',
|
||||
field: 'UNIT_PRICE',
|
||||
editor: 'number',
|
||||
editable: true,
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
return value ? Number(value).toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
// 26. 연삭납기
|
||||
// 32. 총단가 -> 소재총단가
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
title: '연삭납기',
|
||||
field: 'GRINDING_DEADLINE'
|
||||
}, */
|
||||
title: '소재총단가',
|
||||
field: 'TOTAL_PRICE',
|
||||
formatter: function(cell) {
|
||||
var data = cell.getRow().getData();
|
||||
var qty = parseFloat(data.PO_QTY) || 0;
|
||||
var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
|
||||
var totalPrice = qty * unitPrice;
|
||||
return totalPrice > 0 ? totalPrice.toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
|
||||
// 27. 사용여부 (수정가능)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 80,
|
||||
width: 90,
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">사용여부</span>',
|
||||
field: 'USE_YN',
|
||||
editor: 'list',
|
||||
@@ -638,21 +647,28 @@ function fn_initGrid() {
|
||||
return value ? Number(value).toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
// 30. 공급업체 (수정가능 - Select2 에디터)
|
||||
|
||||
// 24. 가공업체 (수정가능 - Select2 에디터)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'left',
|
||||
width: 150,
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">공급업체</span>',
|
||||
field: 'VENDOR_PM',
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">가공업체</span>',
|
||||
field: 'PROCESSING_VENDOR',
|
||||
editor: function(cell, onRendered, success, cancel, editorParams) {
|
||||
// Select2 에디터 (가공업체와 동일한 목록 사용)
|
||||
// Select2 에디터
|
||||
return createSelect2Editor(processingVendorList)(cell, onRendered, success, cancel, editorParams);
|
||||
},
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value) return '';
|
||||
// processingVendorList에서 해당 값의 이름 찾기
|
||||
|
||||
// 저장된 값이 없으면 기본값 '5001'(RPS) 설정
|
||||
if(value === undefined || value === null || value === '') {
|
||||
value = '5001';
|
||||
cell.getRow().update({PROCESSING_VENDOR: value}, false);
|
||||
}
|
||||
|
||||
// OBJID로 업체명 조회하여 표시
|
||||
for(var i = 0; i < processingVendorList.length; i++) {
|
||||
if(processingVendorList[i].id == value) {
|
||||
return processingVendorList[i].text;
|
||||
@@ -661,13 +677,13 @@ function fn_initGrid() {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
// 31. 단가 (수정가능)
|
||||
// 가공단가 (수정가능)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">단가</span>',
|
||||
field: 'UNIT_PRICE',
|
||||
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">가공단가</span>',
|
||||
field: 'PROCESSING_UNIT_PRICE',
|
||||
editor: 'number',
|
||||
editable: true,
|
||||
formatter: function(cell) {
|
||||
@@ -675,28 +691,94 @@ function fn_initGrid() {
|
||||
return value ? Number(value).toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
// 32. 총단가
|
||||
// 가공총단가 (가공단가 × 제작수량)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
title: '총단가',
|
||||
field: 'TOTAL_PRICE',
|
||||
title: '가공총단가',
|
||||
field: 'PROCESSING_TOTAL_PRICE',
|
||||
formatter: function(cell) {
|
||||
var data = cell.getRow().getData();
|
||||
var qty = parseFloat(data.PO_QTY) || 0;
|
||||
var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
|
||||
var totalPrice = qty * unitPrice;
|
||||
return totalPrice > 0 ? totalPrice.toLocaleString() : '0';
|
||||
var productionQty = parseFloat(data.PRODUCTION_QTY) || 0;
|
||||
var processingUnitPrice = parseFloat(data.PROCESSING_UNIT_PRICE) || 0;
|
||||
var processingTotalPrice = productionQty * processingUnitPrice;
|
||||
return processingTotalPrice > 0 ? processingTotalPrice.toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
// 33. 품의서작성일
|
||||
// 총합계 (소재총단가 + 가공총단가)
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
width: 100,
|
||||
title: '총합계',
|
||||
field: 'GRAND_TOTAL_PRICE',
|
||||
formatter: function(cell) {
|
||||
var data = cell.getRow().getData();
|
||||
// 소재총단가: 발주수량 × 소재단가
|
||||
var poQty = parseFloat(data.PO_QTY) || 0;
|
||||
var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
|
||||
var materialTotalPrice = poQty * unitPrice;
|
||||
// 가공총단가: 제작수량 × 가공단가
|
||||
var productionQty = parseFloat(data.PRODUCTION_QTY) || 0;
|
||||
var processingUnitPrice = parseFloat(data.PROCESSING_UNIT_PRICE) || 0;
|
||||
var processingTotalPrice = productionQty * processingUnitPrice;
|
||||
// 총합계
|
||||
var grandTotal = materialTotalPrice + processingTotalPrice;
|
||||
return grandTotal > 0 ? grandTotal.toLocaleString() : '0';
|
||||
}
|
||||
},
|
||||
/* // 25. 가공납기 - 주석처리
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: '품의서작성일',
|
||||
field: 'PROPOSAL_DATE'
|
||||
title: '가공납기',
|
||||
field: 'PROCESSING_DEADLINE'
|
||||
},
|
||||
// 26. 연삭납기
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 100,
|
||||
title: '연삭납기',
|
||||
field: 'GRINDING_DEADLINE'
|
||||
}, */
|
||||
|
||||
|
||||
// 33. 소재 품의서작성일
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 110,
|
||||
title: '소재품의서일',
|
||||
field: 'PROPOSAL_DATE',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value) return '';
|
||||
// YYYY-MM-DD 형식으로 표시
|
||||
if(value.length >= 10) {
|
||||
return value.substring(0, 10);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
// 34. 가공 품의서작성일
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'center',
|
||||
width: 110,
|
||||
title: '가공품의서일',
|
||||
field: 'PROCESSING_PROPOSAL_DATE',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value) return '';
|
||||
// YYYY-MM-DD 형식으로 표시
|
||||
if(value.length >= 10) {
|
||||
return value.substring(0, 10);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -719,8 +801,8 @@ function fn_initGrid() {
|
||||
var row = cell.getRow();
|
||||
var data = row.getData();
|
||||
|
||||
// 발주수량 또는 단가 변경 시 총단가 자동 계산
|
||||
if(field === 'PO_QTY' || field === 'UNIT_PRICE') {
|
||||
// 발주수량, 소재단가, 가공단가 변경 시 총단가 자동 계산
|
||||
if(field === 'PO_QTY' || field === 'UNIT_PRICE' || field === 'PROCESSING_UNIT_PRICE') {
|
||||
row.reformat();
|
||||
}
|
||||
});
|
||||
@@ -856,11 +938,19 @@ function fn_save() {
|
||||
|
||||
// 저장 전 데이터 가공
|
||||
gridData.forEach(function(item) {
|
||||
// TOTAL_PRICE 계산 (PO_QTY * UNIT_PRICE)
|
||||
// 소재총단가 계산 (PO_QTY * UNIT_PRICE)
|
||||
var poQty = parseFloat(item.PO_QTY) || 0;
|
||||
var unitPrice = parseFloat(item.UNIT_PRICE) || 0;
|
||||
item.TOTAL_PRICE = poQty * unitPrice;
|
||||
|
||||
// 가공총단가 계산 (PRODUCTION_QTY * PROCESSING_UNIT_PRICE)
|
||||
var productionQty = parseFloat(item.PRODUCTION_QTY) || 0;
|
||||
var processingUnitPrice = parseFloat(item.PROCESSING_UNIT_PRICE) || 0;
|
||||
item.PROCESSING_TOTAL_PRICE = productionQty * processingUnitPrice;
|
||||
|
||||
// 총합계 계산 (소재총단가 + 가공총단가)
|
||||
item.GRAND_TOTAL_PRICE = item.TOTAL_PRICE + item.PROCESSING_TOTAL_PRICE;
|
||||
|
||||
// 사용여부 변환: 사용/미사용 → Y/N
|
||||
if(item.USE_YN === '사용') {
|
||||
item.USE_YN = 'Y';
|
||||
|
||||
714
WebContent/WEB-INF/view/salesMng/purchaseRequestRegList.jsp
Normal file
714
WebContent/WEB-INF/view/salesMng/purchaseRequestRegList.jsp
Normal file
@@ -0,0 +1,714 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init.jsp" %>
|
||||
<c:set var="now" value="<%=new java.util.Date() %>"/>
|
||||
<c:set var="sysYear"><fmt:formatDate value="${now}" pattern="yyyy" /></c:set>
|
||||
<%
|
||||
// DB에서 메뉴명 조회 (공통 유틸 사용)
|
||||
String menuObjId = request.getParameter("menuObjId");
|
||||
String menuName = CommonUtils.getMenuName(menuObjId, "구매관리_구매요청서작성");
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
.pmsPopupForm tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
.select2-selection__choice {
|
||||
font-size: 11px;
|
||||
background-color: #fff !important;
|
||||
border: none !important;
|
||||
margin-right: 0px !important;
|
||||
}
|
||||
.select2-selection__choice__remove {
|
||||
display: contents !important;
|
||||
}
|
||||
.select2-container .select2-selection--multiple {
|
||||
min-height: 20px !important;
|
||||
}
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
margin-top: 3.5px !important;
|
||||
}
|
||||
.select2-selection__rendered {
|
||||
height: 18px !important;
|
||||
}
|
||||
.select2-container .select2-selection--multiple .select2-selection__rendered {
|
||||
/* overflow: auto !important; */
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('.select2').select2();
|
||||
|
||||
// 품번/품명 Select2 AJAX 초기화
|
||||
initPartSelect2Ajax("#SEARCH_PART_NO", "#SEARCH_PART_NAME", "#SEARCH_PART_OBJID");
|
||||
|
||||
$("input[type=text]").keyup(function(e){
|
||||
if(e.keyCode == 13){
|
||||
$("#btnSearch").trigger("click");
|
||||
}
|
||||
});
|
||||
|
||||
$("#btnSearch").click(function(){
|
||||
fn_search();
|
||||
});
|
||||
|
||||
$("#btnRelease").click(function(){
|
||||
var targetObj = $("input[name=REQUEST_OBJID]:checked");
|
||||
|
||||
if(0 < targetObj.length){
|
||||
fn_releaseSalesRequest();
|
||||
}else{
|
||||
Swal.fire("선택된 내용이 없습니다.");
|
||||
}
|
||||
});
|
||||
|
||||
//접수
|
||||
$("#btnRec").click(function(){
|
||||
var selectedRowIds = _tabulGrid.getSelectedData();
|
||||
if(selectedRowIds.length<1){
|
||||
Swal.fire("접수할 행을 선택해주십시오.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var targetStatus = fnc_checkNull(selectedRowIds[0].STATUS_TITLE);
|
||||
if(targetStatus != "결재완료"){
|
||||
Swal.fire("결재완료일 경우 접수가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
let partIds = selectedRowIds.map(function(o,i){
|
||||
return fnc_checkNull(selectedRowIds[i].OBJID);
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url:"/salesMng/receiptSalesRequestInfo.do"
|
||||
,type:"POST"
|
||||
,data: "partIds="+partIds.join(",")
|
||||
,dataType:"json"
|
||||
,async:false
|
||||
,success:function(data){
|
||||
Swal.fire(data.message);
|
||||
fn_search();
|
||||
self.close();
|
||||
}
|
||||
,error: function(jqxhr, status, error){
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#btnExcel").click(function(){
|
||||
fn_excelExport($("#mainGrid"),"BOM_REPORT_역전개");
|
||||
});
|
||||
|
||||
// 구매요청서 작성 버튼 - 활성화됨
|
||||
$("#btnOrderReg").click(function(){
|
||||
fn_openSalesRequestFormPopUp("");
|
||||
});
|
||||
|
||||
// 품의서 생성
|
||||
$("#btnReg").click(function(){
|
||||
fn_createProposal();
|
||||
});
|
||||
|
||||
$("#btnOrderBOMReg").click(function(){
|
||||
fn_salesRequestTargetBOMListPopUp();
|
||||
});
|
||||
|
||||
$("#btnDelete").click(function(){
|
||||
fn_delete();
|
||||
});
|
||||
|
||||
$("#btnApproval").click(function(){
|
||||
var checkedObj = $("input[name=REQUEST_OBJID]:checked");
|
||||
var title = "";
|
||||
if(1 < checkedObj){
|
||||
Swal.fire("한번에 한개의 결재만 가능합니다.");
|
||||
return false;
|
||||
}else{
|
||||
var targetStatus = checkedObj.attr("data-STATUS");
|
||||
var objId = checkedObj.val();
|
||||
|
||||
var targeType = "SALES_REQUEST";
|
||||
|
||||
if(targetStatus == "create" || targetStatus == "reception" || targetStatus == "reject"){
|
||||
window.open("/approval/registApproval.do?targetType="+targeType+"&targetObjId="+objId+"&approvalTitle="+title+"&callbackFnc=fn_search","registApproval","width=700,height=700");
|
||||
}else{
|
||||
Swal.fire("이미 결재완료 또는 결재중 상태입니다.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(".btnApprovalDetail").click(function(){
|
||||
var approvalObjId = $(this).attr("data-APPROVAL_OBJID");
|
||||
var routeObjId = $(this).attr("data-ROUTE_OBJID");
|
||||
var params = "?approvalObjId="+approvalObjId;
|
||||
params += "&routeObjId="+routeObjId;
|
||||
//Swal.fire("params : "+params);
|
||||
window.open("/approval/approvalDetail.do"+params,"approvalDetailPopup","width=650 height=400 menubar=no status=no");
|
||||
});
|
||||
|
||||
fnc_getAjaxProductMgmtList("SEARCH_PRODUCT_CODE", "", "", "${param.SEARCH_PRODUCT_CODE}");
|
||||
|
||||
fn_search();
|
||||
//날짜
|
||||
_fnc_datepick();
|
||||
});
|
||||
|
||||
var columns = [
|
||||
{title:'OBJID' , field:'OBJID' ,visible: false},
|
||||
{title:'SPC_OBJID' , field:'SPC_OBJID' ,visible: false},
|
||||
{title:'PURCHASE_ORDER_MASTER_OBJID', field:'PURCHASE_ORDER_MASTER_OBJID' ,visible: false},
|
||||
{title:'APPROVAL_OBJID' , field:'APPROVAL_OBJID' ,visible:false},
|
||||
{title:'ROUTE_OBJID' , field:'ROUTE_OBJID' ,visible:false},
|
||||
{title:'MBOM_HEADER_OBJID' , field:'MBOM_HEADER_OBJID' ,visible:false},
|
||||
{title:'DOC_TYPE' , field:'DOC_TYPE' ,visible:false},
|
||||
{title:'HAS_PURCHASE_REQUEST' , field:'HAS_PURCHASE_REQUEST' ,visible:false}
|
||||
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "요청번호", field :"REQUEST_MNG_NO" , widthGrow:1.3
|
||||
// formatter: fnc_createGridAnchorTag,
|
||||
// cellClick : function(e, cell) {
|
||||
// fn_openSalesRequestPopUp(cell.getData().OBJID);
|
||||
// }
|
||||
}
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "구매유형", field :"PURCHASE_TYPE_NAME" , widthGrow:1.1 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'left' , title : "프로젝트번호", field :"PROJECT_NUMBER" , widthGrow:1.4,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell){
|
||||
var orderNo = fnc_checkNull(cell.getData().PROJECT_NUMBER);
|
||||
// 프로젝트 번호가 없으면 팝업 열지 않음
|
||||
if(orderNo == '' || orderNo == null) {
|
||||
return;
|
||||
}
|
||||
// 프로젝트 번호 클릭 시: 결재 정보 조회 모드 (saleNo에 "detail" 전달)
|
||||
fn_openSaleRegPopup(orderNo, "detail");
|
||||
}
|
||||
}
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "주문유형", field :"ORDER_TYPE_NAME" , widthGrow:1.1 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "제품구분", field :"PRODUCT_NAME_FULL" , widthGrow:1.1}
|
||||
,{headerHozAlign : 'center', hozAlign : 'left' , title : "고객사", field :"CUSTOMER_NAME" , widthGrow:1.5 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "유/무상", field :"PAID_TYPE_NAME" , widthGrow:0.9 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'left', title : "품번", field :"PART_NO" , widthGrow:1.4}
|
||||
,{headerHozAlign : 'center', hozAlign : 'left' , title : "품명", field :"PART_NAME" , widthGrow:1.8 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "구매요청서", field :"HAS_PURCHASE_REQUEST" , widthGrow:1.1,
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick : function(e, cell) {
|
||||
var data = cell.getData();
|
||||
fn_openSalesRequestFormPopUp(data.OBJID);
|
||||
}
|
||||
}
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "요청인", field :"REQUEST_USER_NAME" , widthGrow:1.1,
|
||||
// 요청인: 구매요청서 작성 시에만 표시
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var data = cell.getData();
|
||||
var hasPurchaseRequest = fnc_checkNull(data.HAS_PURCHASE_REQUEST);
|
||||
if(hasPurchaseRequest == 'Y') {
|
||||
return fnc_checkNull(data.REQUEST_USER_NAME);
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "입고요청일", field :"DELIVERY_REQUEST_DATE" , widthGrow:1.1,
|
||||
// 입고요청일: 구매요청서 작성 시에만 표시
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var data = cell.getData();
|
||||
var hasPurchaseRequest = fnc_checkNull(data.HAS_PURCHASE_REQUEST);
|
||||
if(hasPurchaseRequest == 'Y') {
|
||||
return fnc_checkNull(data.DELIVERY_REQUEST_DATE);
|
||||
}
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "작성일", field :"REGDATE_TITLE" , widthGrow:1.1 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "상태", field :"STATUS_TITLE" , widthGrow:1.1 }
|
||||
];
|
||||
|
||||
//var grid;
|
||||
function fn_search(){
|
||||
var selectedValues = $("#project_no").val();
|
||||
|
||||
$('<input>').attr({
|
||||
type: 'hidden',
|
||||
name: 'project_nos',
|
||||
value: selectedValues
|
||||
}).appendTo('#form1');
|
||||
|
||||
// 구매요청서 작성 페이지용 API 호출
|
||||
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/salesMng/purchaseRequestRegGridList.do", columns, true);
|
||||
}
|
||||
|
||||
function fn_delete(){
|
||||
var selectedObj = $("input[name=REQUEST_OBJID]:checked");
|
||||
|
||||
if(0 < selectedObj.length){
|
||||
if(confirm("선택된 정보를 삭제하시겠습니까?")){
|
||||
|
||||
$.ajax({
|
||||
url:"/salesMng/deleteSalesRequestMng.do",
|
||||
type:"POST",
|
||||
data:$("#form1").serialize(),
|
||||
dataType:"json",
|
||||
success:function(data){
|
||||
Swal.fire(data.msg);
|
||||
fn_search();
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
}
|
||||
});
|
||||
}
|
||||
}else{
|
||||
Swal.fire("선택된 정보가 없습니다.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//구매의뢰서(BOM) 작성 시 사용
|
||||
function fn_salesRequestTargetBOMListPopUp(){
|
||||
var url = "/salesMng/salesRequestTargetBOMList.do";
|
||||
|
||||
window.open(url,"salesRequestTargetBOMListPopUp","width=1300,height=550");
|
||||
}
|
||||
|
||||
//구매의뢰 요청 팝업 (요청번호 클릭 시 - 구매리스트 화면)
|
||||
function fn_openSalesRequestPopUp(objId){
|
||||
// 그리드에서 선택된 행의 MBOM_HEADER_OBJID 가져오기
|
||||
var selectedRow = _tabulGrid.searchRows("OBJID", "=", objId);
|
||||
var mbomHeaderObjid = '';
|
||||
if(selectedRow && selectedRow.length > 0) {
|
||||
mbomHeaderObjid = fnc_checkNull(selectedRow[0].getData().MBOM_HEADER_OBJID);
|
||||
}
|
||||
|
||||
var url = "/salesMng/purchaseListFormPopUp.do?SALES_REQUEST_MASTER_OBJID="+objId;
|
||||
if(mbomHeaderObjid) {
|
||||
url += "&MBOM_HEADER_OBJID=" + mbomHeaderObjid;
|
||||
}
|
||||
window.open(url,"purchaseListPopUp","width=1400,height=800,scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
// 구매요청서 작성 팝업 (구매요청서 파일 아이콘 클릭 시)
|
||||
// DOC_TYPE 파라미터 추가하여 새 페이지에서 생성된 데이터임을 표시
|
||||
function fn_openSalesRequestFormPopUp(objId){
|
||||
var url = "/salesMng/salesRequestFormPopUp.do?SALES_REQUEST_MASTER_OBJID="+objId+"&DOC_TYPE=PURCHASE_REG";
|
||||
window.open(url,"salesRequestFormPopUp","width=1100,height=630");
|
||||
}
|
||||
|
||||
function fn_releaseSalesRequest(){
|
||||
var checkArr = new Array();
|
||||
var ngCnt = 0;
|
||||
$("input[name=REQUEST_OBJID]:checked").each(function(){
|
||||
var objId = $(this).val();
|
||||
var status = $(this).attr("data-STATUS");
|
||||
|
||||
if("create" != status){
|
||||
ngCnt++;
|
||||
}
|
||||
|
||||
checkArr.push(objId);
|
||||
});
|
||||
|
||||
if(0 < ngCnt){
|
||||
Swal.fire("이미 제출된 정보입니다.\n대상을 확인하시기 바랍니다.");
|
||||
return false;
|
||||
}else{
|
||||
if(confirm("선택된 정보를 구매당당자에게 제출 하시겠습니까?")){
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
url : "/salesMng/releaseSalesRequest.do",
|
||||
data: {"checkArr":checkArr.join(),"status":"release"},
|
||||
dataType:"json",
|
||||
success:function(data){
|
||||
Swal.fire(data.msg);
|
||||
if(data.result){
|
||||
fn_search();
|
||||
}
|
||||
}
|
||||
,error: function(jqxhr, status, error){
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//양산제품에 해당하는 SPEC 정보 목록을 가져온다.
|
||||
function fn_productSpecList(productObjId,selectboxId,selectedVal){
|
||||
$("#"+selectboxId).empty();
|
||||
|
||||
$("#"+selectboxId).append("<option value=''>선택</option>");
|
||||
|
||||
if("" != productObjId){
|
||||
$.ajax({
|
||||
url:"/common/getProductSPECList.do",
|
||||
type:"POST",
|
||||
data:{"isJson":true,"TARGET_OBJID":productObjId},
|
||||
dataType:"json",
|
||||
async:false,
|
||||
success:function(data){
|
||||
resultList = data
|
||||
|
||||
if(0 < resultList.length){
|
||||
for (var i = 0; i < resultList.length; i++) {
|
||||
var commonCodeId = resultList[i].OBJID;
|
||||
var commonCodeName = resultList[i].SPEC_NAME;
|
||||
|
||||
$("#"+selectboxId).append("<option value='"+commonCodeId+"'>"+commonCodeName+"</option>");
|
||||
}
|
||||
$("#"+selectboxId).val(selectedVal);
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function fn_approvalDetail(approvalObjId,routeObjId){
|
||||
var params = "?approvalObjId="+approvalObjId;
|
||||
params += "&routeObjId="+routeObjId;
|
||||
window.open("/approval/approvalDetail.do"+params,"approvalDetailPopup","width=650 height=400 menubar=no status=no");
|
||||
}
|
||||
|
||||
function fn_excelExport(pGridObj,pFileName){
|
||||
var mya = pGridObj.getDataIDs();
|
||||
var data = pGridObj.getRowData(mya[0]);
|
||||
var colNames=new Array();
|
||||
var ii=0;
|
||||
for (var d in data){ colNames[ii++] = d; }
|
||||
|
||||
//컬럼 헤더 가져오기
|
||||
var columnHeader = pGridObj.jqGrid('getGridParam','colNames') + '';
|
||||
var arrHeader = columnHeader.split(',');
|
||||
var html="<table border=1><tr>";
|
||||
for ( var y = 0; y < arrHeader.length; y++ ) {
|
||||
var hName = arrHeader[y];
|
||||
if("PART_OBJID" == hName || "EO_OBJID" == hName){
|
||||
continue;
|
||||
}
|
||||
|
||||
html = html + "<td><b>" + arrHeader[y] + "</b></td>";
|
||||
}
|
||||
|
||||
|
||||
html = html + "</tr>";
|
||||
|
||||
//값 불러오기
|
||||
for(var i=0;i< mya.length;i++) {
|
||||
var datac= pGridObj.getRowData(mya[i]);
|
||||
html = html +"<tr>";
|
||||
for(var j=0; j< colNames.length;j++){
|
||||
if("PART_OBJID" == colNames[j] || "EO_OBJID" == colNames[j]){
|
||||
continue;
|
||||
}
|
||||
html=html + '<td>' + datac[colNames[j]]+"</td>";
|
||||
}
|
||||
html = html+"</tr>";
|
||||
}
|
||||
|
||||
|
||||
html=html+"</table>"; // end of line at the end
|
||||
document.EXCEL_.csvBuffer.value = html;
|
||||
document.EXCEL_.fileName.value = pFileName;
|
||||
document.EXCEL_.target='_new';
|
||||
document.EXCEL_.submit();
|
||||
}
|
||||
|
||||
function fn_str_openPopup(bom_report_objid, product_code, product_mgmt_spec, upg_no, search_partNo, search_partName){
|
||||
var param = "actionType=search"
|
||||
+"&bom_report_objid=" + bom_report_objid
|
||||
+"&product_code=" + product_code
|
||||
+"&product_mgmt_spec=" + product_mgmt_spec
|
||||
+"&upg_no=" + upg_no
|
||||
+"&search_partNo=" + search_partNo
|
||||
+"&search_partName=" + search_partName
|
||||
;
|
||||
window.open("/partmgmt/structureAscendingListPopup.do?"+param, "_strListPopup", "width=1200, height=800, toolbar=no, status=no, menubar=no, location=no, scrollbars=yes, resizable=yes");
|
||||
}
|
||||
|
||||
//구매 BOM 팝업
|
||||
function fn_salesMngBOMOpenPopUp(bom_report_objid){
|
||||
var param = "actionType=search"
|
||||
+"&bom_report_objid=" + bom_report_objid
|
||||
;
|
||||
window.open("/salesMng/salesMngBOMListPopUp.do?"+param, "_strListPopup", "width=1200, height=800, toolbar=no, status=no, menubar=no, location=no, scrollbars=yes, resizable=yes");
|
||||
}
|
||||
|
||||
function fn_salesMngBOMOpenPopUp(bom_report_objid){
|
||||
var param = "actionType=search"
|
||||
+"&bom_report_objid=" + bom_report_objid
|
||||
;
|
||||
window.open("/salesMng/salesRequestDetailPopUp.do?"+param, "_strListPopup", "width=1200, height=800, toolbar=no, status=no, menubar=no, location=no, scrollbars=yes, resizable=yes");
|
||||
}
|
||||
|
||||
function fn_openSaleRegPopup(orderNo, saleNo){
|
||||
var popup_width = 1000;
|
||||
var popup_height = 550;
|
||||
// 한글 프로젝트 번호 인코딩 처리
|
||||
var url = "/salesMgmt/salesRegForm.do?orderNo=" + encodeURIComponent(orderNo) + "&saleNo=" + (saleNo ? encodeURIComponent(saleNo) : "");
|
||||
fn_centerPopup(popup_width, popup_height, url);
|
||||
}
|
||||
|
||||
function _fnc_datepick(){
|
||||
var $dateinput = $("input.date_icon");
|
||||
for(var i=0; i<$dateinput.length; i++){
|
||||
$dateinput.eq(i).attr("size","10");
|
||||
$dateinput.eq(i).datepicker({
|
||||
changeMonth:true,
|
||||
changeYear:true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//품의서 생성
|
||||
function fn_formPopUp(objId,sales_request_objid){
|
||||
var popup_width = 1260;
|
||||
var popup_height = 1050;
|
||||
|
||||
//var hiddenForm = document.hiddenForm;
|
||||
var target = "purchaseOrderFormPopup_salesRequest";
|
||||
var url = "/purchaseOrder/purchaseOrderFormPopup_new.do?ObjId="+objId+"&sales_request_objid="+sales_request_objid;
|
||||
fn_centerPopup(popup_width, popup_height, url, target);
|
||||
|
||||
/* hiddenForm.PURCHASE_ORDER_MASTER_OBJID.value = objId;
|
||||
hiddenForm.action = url;
|
||||
hiddenForm.target = target;
|
||||
hiddenForm.submit(); */
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 생성 함수
|
||||
* - 선택된 구매요청서에서 단가가 입력된 품목만 필터링
|
||||
* - 이미 품의서가 생성된 품목은 제외
|
||||
* - 하나의 품의서로 생성
|
||||
*/
|
||||
function fn_createProposal() {
|
||||
// 1. 선택된 행 확인
|
||||
var selectedRows = _tabulGrid.getSelectedData();
|
||||
|
||||
if(selectedRows.length == 0) {
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
text: '품의서를 생성할 구매요청서를 선택해주세요.',
|
||||
icon: 'info'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if(selectedRows.length > 1) {
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
text: '한 번에 하나의 구매요청서만 선택해주세요.',
|
||||
icon: 'info'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedRow = selectedRows[0];
|
||||
var salesRequestObjid = fnc_checkNull(selectedRow.OBJID);
|
||||
|
||||
// 2. 구매요청서의 품목 중 단가가 입력되고 품의서 미생성된 품목 조회
|
||||
$.ajax({
|
||||
url: "/salesMng/getProposalTargetParts.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
SALES_REQUEST_MASTER_OBJID: salesRequestObjid
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
if(response.resultFlag === "S") {
|
||||
var targetParts = response.data;
|
||||
var excludedParts = response.excludedParts || []; // 공급업체 미입력 품목
|
||||
|
||||
// 3. 대상 품목 확인
|
||||
if(!targetParts || targetParts.length == 0) {
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
text: '품의서를 생성할 품목이 없습니다.\n(단가와 공급업체가 모두 입력되고 품의서가 생성되지 않은 품목만 대상)',
|
||||
icon: 'info'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 품의서 생성 확인
|
||||
var partCount = targetParts.length;
|
||||
var partListHtml = targetParts.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
|
||||
// 공급업체 미입력으로 제외된 품목이 있는 경우 알림 추가
|
||||
var excludedHtml = '';
|
||||
if(excludedParts && excludedParts.length > 0) {
|
||||
var excludedListHtml = excludedParts.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
|
||||
excludedHtml = '<div style="margin-top:15px; padding:10px; background-color:#fff3cd; border:1px solid #ffc107; border-radius:4px;">' +
|
||||
'<p style="color:#856404; font-weight:bold; margin-bottom:5px;">⚠️ 공급업체 미입력으로 제외된 품목 (' + excludedParts.length + '건)</p>' +
|
||||
'<div style="max-height:100px; overflow-y:auto; font-size:11px; color:#856404;">' +
|
||||
excludedListHtml +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
title: '품의서 생성',
|
||||
html: '<div style="text-align:left;">' +
|
||||
'<p>총 <strong>' + partCount + '건</strong>의 품목으로 품의서를 생성합니다.</p>' +
|
||||
'<div style="max-height:150px; overflow-y:auto; border:1px solid #ddd; padding:10px; margin-top:10px; font-size:12px;">' +
|
||||
partListHtml +
|
||||
'</div>' +
|
||||
excludedHtml +
|
||||
'</div>',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '생성',
|
||||
cancelButtonText: '취소'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fn_executeCreateProposal(salesRequestObjid, targetParts);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 실패 시에도 공급업체 미입력 품목 정보 표시
|
||||
var excludedParts = response.excludedParts || [];
|
||||
var excludedHtml = '';
|
||||
|
||||
if(excludedParts && excludedParts.length > 0) {
|
||||
var excludedListHtml = excludedParts.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
|
||||
excludedHtml = '<br/><br/><div style="text-align:left; padding:10px; background-color:#fff3cd; border:1px solid #ffc107; border-radius:4px;">' +
|
||||
'<p style="color:#856404; font-weight:bold; margin-bottom:5px;">⚠️ 공급업체 미입력 품목 (' + excludedParts.length + '건)</p>' +
|
||||
'<div style="max-height:150px; overflow-y:auto; font-size:11px; color:#856404;">' +
|
||||
excludedListHtml +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
html: (response.message || '품목 조회 중 오류가 발생했습니다.') + excludedHtml,
|
||||
icon: 'info'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: '서버 통신 중 오류가 발생했습니다.22',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 생성 실행
|
||||
*/
|
||||
function fn_executeCreateProposal(salesRequestObjid, targetParts) {
|
||||
$.ajax({
|
||||
url: "/salesMng/createProposalFromPurchaseList.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
SALES_REQUEST_MASTER_OBJID: salesRequestObjid,
|
||||
TARGET_PARTS: JSON.stringify(targetParts)
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
if(response.resultFlag === "S") {
|
||||
Swal.fire({
|
||||
title: '생성 완료',
|
||||
text: '품의서가 생성되었습니다.\n품의서 관리에서 확인하세요.',
|
||||
icon: 'success'
|
||||
}).then(() => {
|
||||
fn_search(); // 목록 새로고침
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: response.message || '품의서 생성 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: '서버 통신 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body class="backcolor">
|
||||
<form name="hiddenForm" id="hiddenForm" method="post">
|
||||
<input type="hidden" name="OBJID" id="OBJID">
|
||||
</form>
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<input type="hidden" name="actionType" id="actionType" value="" />
|
||||
<div class="min_part_enroll">
|
||||
<div class="content-box">
|
||||
<div class="content-box-s">
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2>
|
||||
<span><%=menuName%></span>
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
<input type="button" value="구매요청서작성" class="plm_btns" id="btnOrderReg">
|
||||
<input type="button" value="품의서생성" class="plm_btns" id="btnReg">
|
||||
</div>
|
||||
</div>
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<%-- 품번 활성화 --%>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품번</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NO" id="SEARCH_PART_NO" class="select2-part" style="width:200px;">
|
||||
<option value="">품번 선택</option>
|
||||
</select>
|
||||
<input type="hidden" name="SEARCH_PART_OBJID" id="SEARCH_PART_OBJID" value="">
|
||||
</td>
|
||||
<%-- 품명 활성화 --%>
|
||||
<td class="align_r">
|
||||
<label for="" class="">품명</label>
|
||||
</td>
|
||||
<td>
|
||||
<select name="SEARCH_PART_NAME" id="SEARCH_PART_NAME" class="select2-part" style="width:200px;">
|
||||
<option value="">품명 선택</option>
|
||||
</select>
|
||||
</td>
|
||||
<%-- 작성일 활성화 --%>
|
||||
<td class="align_r"><label>작성일</label></td>
|
||||
<td>
|
||||
<input type="text" name="regdate_start" id="regdate_start" style="width:120px;" autocomplete="off" value="${param.regdate_start}" class="date_icon">~
|
||||
<input type="text" name="regdate_end" id="regdate_end" style="width:120px;" autocomplete="off" value="${param.regdate_end}" class="date_icon">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
<style>
|
||||
.container::-webkit-scrollbar-thumb {background: linear-gradient(to bottom, #f5d78e, #f5d78e) !important;}
|
||||
.container::-webkit-scrollbar-track {background-color: white !important;}
|
||||
.container::-webkit-scrollbar-button { display: none !important;}
|
||||
</style>
|
||||
</html>
|
||||
@@ -10,6 +10,7 @@
|
||||
( CommonUtils.checkNull(info.get("STATUS_TITLE")).equals( "결재중" )
|
||||
||CommonUtils.checkNull(info.get("STATUS_TITLE")).equals( "결재완료" )
|
||||
||CommonUtils.checkNull(info.get("STATUS_TITLE")).equals( "접수" )
|
||||
||CommonUtils.checkNull(info.get("STATUS")).equals( "confirmed" )
|
||||
)
|
||||
){
|
||||
isModify = false; //수정불가
|
||||
@@ -84,6 +85,11 @@ $(function(){
|
||||
fn_deleteRow();
|
||||
});
|
||||
|
||||
// 확정 버튼 클릭
|
||||
$("#btnConfirm").click(function(){
|
||||
fn_confirm();
|
||||
});
|
||||
|
||||
$("#btnAppr").click(function(){ //결재상신
|
||||
if(fnc_valitate("form1")){
|
||||
var objId = "${resultMap.OBJID}";
|
||||
@@ -285,17 +291,16 @@ function fn_getSalesRequestTargetPartList(masterObjId,bomObjId){
|
||||
appendText += " <td class='align_c' type='number'>";
|
||||
appendText += " <input type='number' name='QTY_"+rowObjId+"' value='"+QTY+"' reqTitle='수량' required style='text-align: center;'>";
|
||||
appendText += " </td>";
|
||||
//appendText += " <td class='input_title'><label>공급업체</label></td>";
|
||||
//appendText += " <td class='align_l'>";
|
||||
//appendText += " <select name='PARTNER_OBJID_"+rowObjId+"' id='PARTNER_OBJID_"+rowObjId+"' reqTitle='공급업체' type='select' class='select2' >";
|
||||
//appendText += " </select>";
|
||||
//appendText += " </td>";
|
||||
//appendText += " <td class='align_l'>";
|
||||
//appendText += " <input type='date' name='DELIVERY_REQUEST_DATE_"+rowObjId+"' value='"+DELIVERY_REQUEST_DATE+"'>";
|
||||
//appendText += " </td>";
|
||||
//appendText += " <td class='align_l'>";
|
||||
//appendText += " <input type='text' name='REMARK_"+rowObjId+"' value='"+REMARK+"'>";
|
||||
//appendText += " </td>";
|
||||
// 공급업체
|
||||
appendText += " <td class='align_l'>";
|
||||
appendText += " <select name='PARTNER_OBJID_"+rowObjId+"' id='PARTNER_OBJID_"+rowObjId+"' type='select' class='select2' style='width:100%;'>";
|
||||
appendText += " </select>";
|
||||
appendText += " </td>";
|
||||
// 단가
|
||||
var PARTNER_PRICE = fnc_checkNull(resultData[i].PARTNER_PRICE);
|
||||
appendText += " <td class='align_r'>";
|
||||
appendText += " <input type='text' name='PARTNER_PRICE_"+rowObjId+"' id='PARTNER_PRICE_"+rowObjId+"' value='"+PARTNER_PRICE+"' style='text-align: right; width:100%;'>";
|
||||
appendText += " </td>";
|
||||
appendText += " </tr>";
|
||||
|
||||
|
||||
@@ -316,10 +321,9 @@ function fn_getSalesRequestTargetPartList(masterObjId,bomObjId){
|
||||
var PART_NO = fnc_checkNull(resultData[i].PART_NO);
|
||||
var PART_NAME = fnc_checkNull(resultData[i].PART_NAME);
|
||||
|
||||
// 공급업체 제거로 주석처리
|
||||
// var PARTNER_OBJID = fnc_checkNull(resultData[i].PARTNER_OBJID);
|
||||
// fnc_getAdminSupCdListAppend("", "PARTNER_OBJID_"+rowObjId, PARTNER_OBJID);
|
||||
// $("#PARTNER_OBJID_"+rowObjId).val(PARTNER_OBJID);
|
||||
// 공급업체 셋팅 (CLIENT_MNG 테이블)
|
||||
var PARTNER_OBJID = fnc_checkNull(resultData[i].PARTNER_OBJID);
|
||||
fnc_getClientMngListAppend("PARTNER_OBJID_"+rowObjId, PARTNER_OBJID);
|
||||
|
||||
fn_addBomPart("PART_OBJID_"+rowObjId, PART_OBJID, "PART_NAME_"+rowObjId,"");
|
||||
|
||||
@@ -377,31 +381,29 @@ function fn_AddRow(){
|
||||
//appendText += " <td class='align_l' value='SPEC' title='UNIT_TITLE'>";
|
||||
//appendText += " <input type='text' name='SPEC_"+rowObjId+"'>";
|
||||
//appendText += " </td>";
|
||||
//appendText += " <td class='input_title'><label>수량</label></td>";
|
||||
appendText += " <td class='align_c' value='QTY' type='number' readonly>";
|
||||
appendText += " <input type='number' name='QTY_"+rowObjId+"' reqTitle='수량' required style='text-align: center;'>";
|
||||
appendText += " </td>";
|
||||
//appendText += " <td class='input_title'><label>공급업체</label></td>";
|
||||
//appendText += " <td class='align_l' value='PARTNER_OBJID'>";
|
||||
//appendText += " <select name='PARTNER_OBJID_"+rowObjId+"' id='PARTNER_OBJID_"+rowObjId+"' reqTitle='공급업체' type='select' class='select2'>";
|
||||
//appendText += " </select>";
|
||||
//appendText += " </td>";
|
||||
//appendText += " <td class='align_l' value='DELIVERY_REQUEST_DATE'>";
|
||||
//appendText += " <input type='date' name='DELIVERY_REQUEST_DATE_"+rowObjId+"'>";
|
||||
//appendText += " </td>";
|
||||
//appendText += " <td class='align_l' value='REMARK'>";
|
||||
//appendText += " <input type='text' name='REMARK_"+rowObjId+"'>";
|
||||
//appendText += " </td>";
|
||||
appendText += " </tr>";
|
||||
|
||||
if(0 < $("#partListArea tr:first").lenght || typeof $("#partListArea tr:first").lenght != "undefined") {
|
||||
$("#partListArea tr:first").before(appendText);
|
||||
}else{
|
||||
$("#partListArea").append(appendText);
|
||||
}
|
||||
// 공급업체 제거로 주석처리
|
||||
// fnc_getAdminSupCdListAppend("", "PARTNER_OBJID_"+rowObjId, "");
|
||||
fn_addBomPart("PART_OBJID_"+rowObjId, "", "PART_NAME_"+rowObjId, "");
|
||||
//appendText += " <td class='input_title'><label>수량</label></td>";
|
||||
appendText += " <td class='align_c' value='QTY' type='number' readonly>";
|
||||
appendText += " <input type='number' name='QTY_"+rowObjId+"' reqTitle='수량' required style='text-align: center;'>";
|
||||
appendText += " </td>";
|
||||
// 공급업체
|
||||
appendText += " <td class='align_l' value='PARTNER_OBJID'>";
|
||||
appendText += " <select name='PARTNER_OBJID_"+rowObjId+"' id='PARTNER_OBJID_"+rowObjId+"' type='select' class='select2' style='width:100%;'>";
|
||||
appendText += " </select>";
|
||||
appendText += " </td>";
|
||||
// 단가
|
||||
appendText += " <td class='align_r' value='PARTNER_PRICE'>";
|
||||
appendText += " <input type='text' name='PARTNER_PRICE_"+rowObjId+"' id='PARTNER_PRICE_"+rowObjId+"' style='text-align: right; width:100%;'>";
|
||||
appendText += " </td>";
|
||||
appendText += " </tr>";
|
||||
|
||||
if(0 < $("#partListArea tr:first").lenght || typeof $("#partListArea tr:first").lenght != "undefined") {
|
||||
$("#partListArea tr:first").before(appendText);
|
||||
}else{
|
||||
$("#partListArea").append(appendText);
|
||||
}
|
||||
// 공급업체 셋팅 (CLIENT_MNG 테이블)
|
||||
fnc_getClientMngListAppend("PARTNER_OBJID_"+rowObjId, "");
|
||||
fn_addBomPart("PART_OBJID_"+rowObjId, "", "PART_NAME_"+rowObjId, "");
|
||||
fnc_datepick();
|
||||
$(".select2").select2();
|
||||
}
|
||||
@@ -498,6 +500,61 @@ function fn_Supply_save(){
|
||||
}
|
||||
}
|
||||
|
||||
// 구매요청서 확정 처리
|
||||
function fn_confirm(){
|
||||
var masterObjId = $("#SALES_REQUEST_MASTER_OBJID").val();
|
||||
|
||||
if(fnc_checkNull(masterObjId) == ""){
|
||||
Swal.fire("먼저 저장해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 품목이 있는지 확인
|
||||
if($("#partListArea tr").length < 1){
|
||||
Swal.fire("품목이 없습니다. 먼저 품목을 추가하고 저장해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
title: '확정',
|
||||
text: '확정하시겠습니까? 확정 후에는 수정이 불가능합니다.',
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#5cb85c',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: '확정',
|
||||
cancelButtonText: '취소'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/salesMng/confirmSalesRequest.do",
|
||||
data: { "SALES_REQUEST_MASTER_OBJID": masterObjId },
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if(data.result){
|
||||
Swal.fire({
|
||||
title: '완료',
|
||||
text: '확정되었습니다.',
|
||||
icon: 'success'
|
||||
}).then(() => {
|
||||
if(typeof opener.fn_search == "function"){
|
||||
opener.fn_search();
|
||||
}
|
||||
self.close();
|
||||
});
|
||||
} else {
|
||||
Swal.fire('오류', data.msg || '확정 처리 중 오류가 발생했습니다.', 'error');
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
Swal.fire('오류', '서버 통신 중 오류가 발생했습니다.', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ★★★ 프로젝트 선택 시 M-BOM 품목 자동 로드 ★★★
|
||||
function fn_loadMbomParts(projectObjId){
|
||||
if(fnc_checkNull(projectObjId) == "") return;
|
||||
@@ -539,12 +596,23 @@ function fn_loadMbomParts(projectObjId){
|
||||
appendText += " <td class='align_c'>";
|
||||
appendText += " <input type='number' name='QTY_"+rowObjId+"' value='"+QTY+"' reqTitle='수량' required style='text-align: center;'>";
|
||||
appendText += " </td>";
|
||||
// 공급업체
|
||||
appendText += " <td class='align_l'>";
|
||||
appendText += " <select name='PARTNER_OBJID_"+rowObjId+"' id='PARTNER_OBJID_"+rowObjId+"' type='select' class='select2' style='width:100%;'>";
|
||||
appendText += " </select>";
|
||||
appendText += " </td>";
|
||||
// 단가
|
||||
appendText += " <td class='align_r'>";
|
||||
appendText += " <input type='text' name='PARTNER_PRICE_"+rowObjId+"' id='PARTNER_PRICE_"+rowObjId+"' style='text-align: right; width:100%;'>";
|
||||
appendText += " </td>";
|
||||
appendText += "</tr>";
|
||||
|
||||
$("#partListArea").append(appendText);
|
||||
|
||||
// 품번 드롭다운에 M-BOM 전체 품목 옵션 추가
|
||||
fn_addBomPart("PART_OBJID_"+rowObjId, PART_OBJID, "PART_NAME_"+rowObjId, "");
|
||||
// 공급업체 셋팅 (CLIENT_MNG 테이블)
|
||||
fnc_getClientMngListAppend("PARTNER_OBJID_"+rowObjId, "");
|
||||
});
|
||||
|
||||
$(".select2").select2();
|
||||
@@ -633,6 +701,7 @@ function fn_callbackFnc(){
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<input type="hidden" name="SALES_REQUEST_MASTER_OBJID" id="SALES_REQUEST_MASTER_OBJID" value="${resultMap.OBJID}">
|
||||
<input type="hidden" name="STATUS" id="STATUS" value="${resultMap.STATUS}">
|
||||
<input type="hidden" name="DOC_TYPE" id="DOC_TYPE" value="${param.DOC_TYPE}">
|
||||
<input type="hidden" name="TARGET_DRAWING_DOWNLOAD" id="TARGET_DRAWING_DOWNLOAD">
|
||||
<section>
|
||||
<div class="plm_menu_name" style="display:flex;">
|
||||
@@ -668,27 +737,27 @@ function fn_callbackFnc(){
|
||||
<option value="">선택</option> ${code_map.project_no}
|
||||
</select>
|
||||
</td>
|
||||
<td class="input_title"><label for="">구매유형<span class="required-mark">*</span></label></td>
|
||||
<!-- <td class="input_title"><label for="">구매유형<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<select name="PURCHASE_TYPE2" id="PURCHASE_TYPE2" reqTitle="구매유형" required type="select" class="select2" style="width: 100%;">
|
||||
<option value="">선택</option> ${code_map.purchase_type}
|
||||
</select>
|
||||
</td>
|
||||
</td> -->
|
||||
<td class="input_title"><label for="">주문유형<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<select name="ORDER_TYPE" id="ORDER_TYPE" reqTitle="주문유형" required type="select" class="select2" style="width: 100%;">
|
||||
<option value="">선택</option> ${code_map.category_cd}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 2행: 제품구분, 국내/해외, 고객사, 유/무상 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="">제품구분<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<select name="PRODUCT_NAME" id="PRODUCT_NAME" reqTitle="제품구분" required type="select" class="select2" style="width: 100%;">
|
||||
<option value="">선택</option> ${code_map.product_name}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 2행: 제품구분, 국내/해외, 고객사, 유/무상 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="">국내/해외<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<select name="AREA_CD" id="AREA_CD" reqTitle="국내/해외" required type="select" class="select2" style="width: 100%;">
|
||||
@@ -707,21 +776,22 @@ function fn_callbackFnc(){
|
||||
<option value="">선택</option> ${code_map.paid_type}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- 3행: 입고요청일 -->
|
||||
<tr>
|
||||
<td class="input_title"><label for="">입고요청일</label></td>
|
||||
<td>
|
||||
<input type="text" class="date_icon" name="DELIVERY_REQUEST_DATE" id="DELIVERY_REQUEST_DATE" reqTitle="입고요청일" value="${resultMap.DELIVERY_REQUEST_DATE}">
|
||||
<input type="hidden" name="REQUEST_USER_ID" id="REQUEST_USER_ID" value="${resultMap.REQUEST_USER_ID}">
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<!-- 3행: 입고요청일 -->
|
||||
<!-- <tr>
|
||||
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr> -->
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -731,12 +801,14 @@ function fn_callbackFnc(){
|
||||
<input type="button" value="행추가" class="plm_btns" id="btnAddRow" name="btnAddRow">
|
||||
<input type="button" value="행삭제" class="plm_btns" id="btnDeleteRow" name="btnDeleteRow">
|
||||
<input type="button" value="저장" class="plm_btns" id="btnReg">
|
||||
<% }else{ %>
|
||||
<!-- <input type="button" value="공급업체저장" class="plm_btns" id="btnSupplySave"> -->
|
||||
<% } %>
|
||||
<input type="button" value="닫기" class="plm_btns" onclick="window.close();">
|
||||
<input type="button" value="닫기" class="plm_btns" onclick="window.close();">
|
||||
<input type="button" value="확정" class="plm_btns" id="btnConfirm" style="background-color:#5cb85c; color:white;">
|
||||
</div>
|
||||
|
||||
<% }else{ %>
|
||||
<div class="plm_btn_wrap" style="padding:0 8 0 8; text-align: right;">
|
||||
<input type="button" value="닫기" class="plm_btns" onclick="window.close();">
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div id="businessPopupFormWrap" style="z-index:99;">
|
||||
@@ -748,36 +820,42 @@ function fn_callbackFnc(){
|
||||
</tr> -->
|
||||
<tr>
|
||||
<td style="border-top:1px solid #ccc;">
|
||||
<div class="in_table_scroll_wrap _table1" style="height:22px;width:99.5%;">
|
||||
<table class="plm_table">
|
||||
<colgroup>
|
||||
<col width="30px">
|
||||
<col width="200px">
|
||||
<col width="200px">
|
||||
<col width="100px">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr class="plm_thead">
|
||||
<td><input type="checkbox" name="allCheck" id="allCheck"></td>
|
||||
<td>품번</td>
|
||||
<td>품명</td>
|
||||
<td>수량</td>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
<div class="in_table_scroll_wrap _table2" style="height:250px;width:100%;">
|
||||
<table class="plm_table">
|
||||
<colgroup>
|
||||
<col width="30px">
|
||||
<col width="200px">
|
||||
<col width="200px">
|
||||
<col width="100px">
|
||||
</colgroup>
|
||||
<tbody id="partListArea">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="in_table_scroll_wrap _table1" style="height:40px;width:100%;">
|
||||
<table class="plm_table">
|
||||
<colgroup>
|
||||
<col width="30px">
|
||||
<col width="180px">
|
||||
<col width="180px">
|
||||
<col width="80px">
|
||||
<col width="150px">
|
||||
<col width="100px">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr class="plm_thead">
|
||||
<td><input type="checkbox" name="allCheck" id="allCheck"></td>
|
||||
<td>품번</td>
|
||||
<td>품명</td>
|
||||
<td>수량</td>
|
||||
<td>공급업체</td>
|
||||
<td>단가</td>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
<div class="in_table_scroll_wrap _table2" style="height:250px;width:100%;">
|
||||
<table class="plm_table">
|
||||
<colgroup>
|
||||
<col width="30px">
|
||||
<col width="180px">
|
||||
<col width="180px">
|
||||
<col width="80px">
|
||||
<col width="150px">
|
||||
<col width="100px">
|
||||
</colgroup>
|
||||
<tbody id="partListArea">
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -196,7 +196,7 @@ var columns = [
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "유/무상", field :"PAID_TYPE_NAME" , widthGrow:0.9 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'left', title : "품번", field :"PART_NO" , widthGrow:1.4}
|
||||
,{headerHozAlign : 'center', hozAlign : 'left' , title : "품명", field :"PART_NAME" , widthGrow:1.8 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "구매요청서", field :"HAS_PURCHASE_REQUEST" , widthGrow:1.1,
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "견적요청서", field :"HAS_PURCHASE_REQUEST" , widthGrow:1.1,
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
// 구매요청서 작성 여부: HAS_PURCHASE_REQUEST가 'Y'이면 구매요청서 작성됨
|
||||
var data = cell.getData();
|
||||
@@ -214,6 +214,24 @@ var columns = [
|
||||
}
|
||||
}
|
||||
}
|
||||
// ,{headerHozAlign : 'center', hozAlign : 'center', title : "구매요청서", field :"HAS_PURCHASE_REQUEST" , widthGrow:1.1,
|
||||
// formatter: function(cell, formatterParams, onRendered){
|
||||
// // 구매요청서 작성 여부: HAS_PURCHASE_REQUEST가 'Y'이면 구매요청서 작성됨
|
||||
// var data = cell.getData();
|
||||
// var hasPurchaseRequest = fnc_checkNull(data.HAS_PURCHASE_REQUEST);
|
||||
// var iconClass = (hasPurchaseRequest == 'Y') ? 'file_icon' : 'file_empty_icon';
|
||||
// return '<a href="#" class="File ' + iconClass + '" style="width:20px; height:20px; display:inline-block;"></a>';
|
||||
// },
|
||||
// cellClick : function(e, cell) {
|
||||
// var data = cell.getData();
|
||||
// var hasPurchaseRequest = fnc_checkNull(data.HAS_PURCHASE_REQUEST);
|
||||
|
||||
// // 구매요청서가 작성된 경우(파란색 아이콘)만 팝업 열기
|
||||
// if(hasPurchaseRequest == 'Y') {
|
||||
// fn_openSalesRequestFormPopUp(data.OBJID);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "요청인", field :"REQUEST_USER_NAME" , widthGrow:1.1,
|
||||
// 요청인: 구매요청서 작성 시에만 표시
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
@@ -297,7 +315,7 @@ function fn_openSalesRequestPopUp(objId){
|
||||
if(mbomHeaderObjid) {
|
||||
url += "&MBOM_HEADER_OBJID=" + mbomHeaderObjid;
|
||||
}
|
||||
window.open(url,"purchaseListPopUp","width=1400,height=800,scrollbars=yes,resizable=yes");
|
||||
window.open(url,"purchaseListPopUp","width=1800,height=800,scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
//구매요청서 작성 팝업 (구매요청서 파일 아이콘 클릭 시)
|
||||
@@ -489,9 +507,9 @@ function fn_formPopUp(objId,sales_request_objid){
|
||||
|
||||
/**
|
||||
* 품의서 생성 함수
|
||||
* - 선택된 구매요청서에서 단가가 입력된 품목만 필터링
|
||||
* - 선택된 구매요청서에서 소재단가/가공단가가 입력된 품목만 필터링
|
||||
* - 이미 품의서가 생성된 품목은 제외
|
||||
* - 하나의 품의서로 생성
|
||||
* - 소재/가공 각각 별도 품의서 생성
|
||||
*/
|
||||
function fn_createProposal() {
|
||||
// 1. 선택된 행 확인
|
||||
@@ -528,79 +546,73 @@ function fn_createProposal() {
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
if(response.resultFlag === "S") {
|
||||
var targetParts = response.data;
|
||||
var excludedParts = response.excludedParts || []; // 공급업체 미입력 품목
|
||||
var materialParts = response.materialTargetParts || [];
|
||||
var processingParts = response.processingTargetParts || [];
|
||||
var materialExcluded = response.materialExcludedParts || [];
|
||||
var processingExcluded = response.processingExcludedParts || [];
|
||||
|
||||
// 3. 대상 품목 확인
|
||||
if(!targetParts || targetParts.length == 0) {
|
||||
if(materialParts.length == 0 && processingParts.length == 0) {
|
||||
var excludedHtml = fn_buildExcludedHtml(materialExcluded, processingExcluded);
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
text: '품의서를 생성할 품목이 없습니다.\n(단가와 공급업체가 모두 입력되고 품의서가 생성되지 않은 품목만 대상)',
|
||||
html: '품의서를 생성할 품목이 없습니다.<br/>(소재단가+공급업체 또는 가공단가+가공업체가 입력되고 품의서가 생성되지 않은 품목만 대상)' + excludedHtml,
|
||||
icon: 'info'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 품의서 생성 확인
|
||||
var partCount = targetParts.length;
|
||||
var partListHtml = targetParts.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
// 4. 품의서 생성 확인 - 소재/가공 구분 표시
|
||||
var confirmHtml = '<div style="text-align:left;">';
|
||||
|
||||
// 공급업체 미입력으로 제외된 품목이 있는 경우 알림 추가
|
||||
var excludedHtml = '';
|
||||
if(excludedParts && excludedParts.length > 0) {
|
||||
var excludedListHtml = excludedParts.map(function(part) {
|
||||
// 소재 품의서 대상
|
||||
if(materialParts.length > 0) {
|
||||
var materialListHtml = materialParts.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
|
||||
excludedHtml = '<div style="margin-top:15px; padding:10px; background-color:#fff3cd; border:1px solid #ffc107; border-radius:4px;">' +
|
||||
'<p style="color:#856404; font-weight:bold; margin-bottom:5px;">⚠️ 공급업체 미입력으로 제외된 품목 (' + excludedParts.length + '건)</p>' +
|
||||
'<div style="max-height:100px; overflow-y:auto; font-size:11px; color:#856404;">' +
|
||||
excludedListHtml +
|
||||
'</div>' +
|
||||
confirmHtml += '<div style="margin-bottom:15px; padding:10px; background-color:#e3f2fd; border:1px solid #2196F3; border-radius:4px;">' +
|
||||
'<p style="color:#1565C0; font-weight:bold; margin-bottom:5px;">📦 소재 품의서 (' + materialParts.length + '건)</p>' +
|
||||
'<div style="max-height:100px; overflow-y:auto; font-size:11px;">' + materialListHtml + '</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// 가공 품의서 대상
|
||||
if(processingParts.length > 0) {
|
||||
var processingListHtml = processingParts.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
|
||||
confirmHtml += '<div style="margin-bottom:15px; padding:10px; background-color:#fff3e0; border:1px solid #FF9800; border-radius:4px;">' +
|
||||
'<p style="color:#E65100; font-weight:bold; margin-bottom:5px;">⚙️ 가공 품의서 (' + processingParts.length + '건)</p>' +
|
||||
'<div style="max-height:100px; overflow-y:auto; font-size:11px;">' + processingListHtml + '</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// 제외된 품목 표시
|
||||
confirmHtml += fn_buildExcludedHtml(materialExcluded, processingExcluded);
|
||||
confirmHtml += '</div>';
|
||||
|
||||
// 생성될 품의서 개수 표시
|
||||
var proposalCount = (materialParts.length > 0 ? 1 : 0) + (processingParts.length > 0 ? 1 : 0);
|
||||
|
||||
Swal.fire({
|
||||
title: '품의서 생성',
|
||||
html: '<div style="text-align:left;">' +
|
||||
'<p>총 <strong>' + partCount + '건</strong>의 품목으로 품의서를 생성합니다.</p>' +
|
||||
'<div style="max-height:150px; overflow-y:auto; border:1px solid #ddd; padding:10px; margin-top:10px; font-size:12px;">' +
|
||||
partListHtml +
|
||||
'</div>' +
|
||||
excludedHtml +
|
||||
'</div>',
|
||||
html: '<p style="margin-bottom:10px;"><strong>' + proposalCount + '개</strong>의 품의서가 생성됩니다.</p>' + confirmHtml,
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '생성',
|
||||
cancelButtonText: '취소'
|
||||
cancelButtonText: '취소',
|
||||
width: '600px'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fn_executeCreateProposal(salesRequestObjid, targetParts);
|
||||
fn_executeCreateProposal(salesRequestObjid, null);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 실패 시에도 공급업체 미입력 품목 정보 표시
|
||||
var excludedParts = response.excludedParts || [];
|
||||
var excludedHtml = '';
|
||||
|
||||
if(excludedParts && excludedParts.length > 0) {
|
||||
var excludedListHtml = excludedParts.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
|
||||
excludedHtml = '<br/><br/><div style="text-align:left; padding:10px; background-color:#fff3cd; border:1px solid #ffc107; border-radius:4px;">' +
|
||||
'<p style="color:#856404; font-weight:bold; margin-bottom:5px;">⚠️ 공급업체 미입력 품목 (' + excludedParts.length + '건)</p>' +
|
||||
'<div style="max-height:150px; overflow-y:auto; font-size:11px; color:#856404;">' +
|
||||
excludedListHtml +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
html: (response.message || '품목 조회 중 오류가 발생했습니다.') + excludedHtml,
|
||||
html: response.message || '품목 조회 중 오류가 발생했습니다.',
|
||||
icon: 'info'
|
||||
});
|
||||
}
|
||||
@@ -608,13 +620,44 @@ function fn_createProposal() {
|
||||
error: function(xhr, status, error) {
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: '서버 통신 중 오류가 발생했습니다.22',
|
||||
text: '서버 통신 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 제외된 품목 HTML 생성
|
||||
*/
|
||||
function fn_buildExcludedHtml(materialExcluded, processingExcluded) {
|
||||
var html = '';
|
||||
|
||||
if(materialExcluded && materialExcluded.length > 0) {
|
||||
var listHtml = materialExcluded.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
|
||||
html += '<div style="margin-top:10px; padding:10px; background-color:#fff3cd; border:1px solid #ffc107; border-radius:4px;">' +
|
||||
'<p style="color:#856404; font-weight:bold; margin-bottom:5px;">⚠️ 소재 - 공급업체 미입력 (' + materialExcluded.length + '건)</p>' +
|
||||
'<div style="max-height:80px; overflow-y:auto; font-size:11px; color:#856404;">' + listHtml + '</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
if(processingExcluded && processingExcluded.length > 0) {
|
||||
var listHtml = processingExcluded.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('<br/>');
|
||||
|
||||
html += '<div style="margin-top:10px; padding:10px; background-color:#fff3cd; border:1px solid #ffc107; border-radius:4px;">' +
|
||||
'<p style="color:#856404; font-weight:bold; margin-bottom:5px;">⚠️ 가공 - 가공업체 미입력 (' + processingExcluded.length + '건)</p>' +
|
||||
'<div style="max-height:80px; overflow-y:auto; font-size:11px; color:#856404;">' + listHtml + '</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 생성 실행
|
||||
*/
|
||||
@@ -623,15 +666,16 @@ function fn_executeCreateProposal(salesRequestObjid, targetParts) {
|
||||
url: "/salesMng/createProposalFromPurchaseList.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
SALES_REQUEST_MASTER_OBJID: salesRequestObjid,
|
||||
TARGET_PARTS: JSON.stringify(targetParts)
|
||||
SALES_REQUEST_MASTER_OBJID: salesRequestObjid
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(response) {
|
||||
if(response.resultFlag === "S") {
|
||||
// 서버에서 반환한 메시지 사용 (소재/가공 품의서 번호 포함)
|
||||
var message = response.message || '품의서가 생성되었습니다.';
|
||||
Swal.fire({
|
||||
title: '생성 완료',
|
||||
text: '품의서가 생성되었습니다.\n품의서 관리에서 확인하세요.',
|
||||
html: message.replace(/\n/g, '<br/>'),
|
||||
icon: 'success'
|
||||
}).then(() => {
|
||||
fn_search(); // 목록 새로고침
|
||||
@@ -639,12 +683,13 @@ function fn_executeCreateProposal(salesRequestObjid, targetParts) {
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: response.message || '품의서 생성 중 오류가 발생했습니다.',
|
||||
html: (response.message || '품의서 생성 중 오류가 발생했습니다.').replace(/\n/g, '<br/>'),
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error("품의서 생성 오류:", status, error);
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: '서버 통신 중 오류가 발생했습니다.',
|
||||
@@ -670,7 +715,7 @@ function fn_executeCreateProposal(salesRequestObjid, targetParts) {
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
<input type="button" value="구매요청서작성" class="plm_btns" id="btnOrderReg">
|
||||
<!-- <input type="button" value="구매요청서작성" class="plm_btns" id="btnOrderReg"> -->
|
||||
<input type="button" value="품의서생성" class="plm_btns" id="btnReg">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1165,7 +1165,7 @@ function fnc_getSupplyCodeListAppend2(supplyCode,selectboxId,selectedVal){
|
||||
});
|
||||
}
|
||||
|
||||
//공급업체 정보목록을 가져온다.
|
||||
//공급업체 정보목록을 가져온다. (ADMIN_SUPPLY_MNG 테이블)
|
||||
function fnc_getAdminSupCdListAppend(supplyCode,selectboxId,selectedVal){
|
||||
$.ajax({
|
||||
url:"/common/getAdminSupCdList.do",
|
||||
@@ -1195,6 +1195,37 @@ function fnc_getAdminSupCdListAppend(supplyCode,selectboxId,selectedVal){
|
||||
});
|
||||
}
|
||||
|
||||
// 일반거래처(공급업체) 정보목록을 가져온다. (CLIENT_MNG 테이블)
|
||||
function fnc_getClientMngListAppend(selectboxId, selectedVal){
|
||||
$.ajax({
|
||||
url:"/common/getClientMngList.do",
|
||||
type:"POST",
|
||||
data:{},
|
||||
dataType:"json",
|
||||
async:false,
|
||||
success:function(data){
|
||||
var resultList = data;
|
||||
|
||||
$("#"+selectboxId).empty();
|
||||
$("#"+selectboxId).append("<option value=''>선택</option>");
|
||||
|
||||
if(resultList && resultList.length > 0){
|
||||
for (var i = 0; i < resultList.length; i++) {
|
||||
var commonCodeId = resultList[i].CODE_ID;
|
||||
var commonCodeName = resultList[i].CODE_NAME || resultList[i].NAME;
|
||||
$("#"+selectboxId).append("<option value='"+commonCodeId+"'>"+commonCodeName+"</option>");
|
||||
}
|
||||
if(selectedVal){
|
||||
$("#"+selectboxId).val(selectedVal);
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("일반거래처 목록 조회 실패");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//targetCode에 해당하는 대상구분명을 반환한다.
|
||||
function fnc_getApprovalTargetName(targetCode){
|
||||
var targetTypeTitle = "";
|
||||
|
||||
@@ -2112,6 +2112,44 @@ public class PurchaseOrderController {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 도면 파일 개수 조회 (AJAX)
|
||||
* @param request
|
||||
* @param paramMap - objId (PURCHASE_ORDER_MASTER_OBJID)
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/purchaseOrder/getDrawingFileCount.do")
|
||||
public Map getDrawingFileCount(HttpServletRequest request, @RequestParam Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
String objId = CommonUtils.checkNull(paramMap.get("objId"));
|
||||
|
||||
if("".equals(objId)){
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", "잘못된 요청입니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 도면 파일 개수 조회
|
||||
paramMap.put("PURCHASE_ORDER_MASTER_OBJID", objId);
|
||||
paramMap.put("MULTI_MASTER_OBJID", objId);
|
||||
List fileList = commonService.selectList("purchaseOrder.purchaseOrderPartFileListForMail", null, paramMap);
|
||||
|
||||
int count = (fileList != null) ? fileList.size() : 0;
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("count", count);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "error");
|
||||
resultMap.put("message", "도면 파일 조회 중 오류가 발생했습니다.");
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* PDF 청크 업로드 (AJAX)
|
||||
* @param request
|
||||
@@ -2234,4 +2272,48 @@ public class PurchaseOrderController {
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 발주 취소 전 입고 여부 확인
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/purchaseOrder/checkReceiptForCancel.do")
|
||||
public Map checkReceiptForCancel(HttpServletRequest request, @RequestParam Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
resultMap = purchaseOrderService.checkReceiptForCancel(request, paramMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("hasReceipt", true);
|
||||
resultMap.put("message", "입고 확인 중 오류가 발생했습니다.");
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 발주 취소 실행 (입고가 없는 경우만)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/purchaseOrder/executeOrderCancel.do")
|
||||
public Map executeOrderCancel(HttpServletRequest request, @RequestParam Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
resultMap = purchaseOrderService.executeOrderCancel(request, paramMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("message", "발주 취소 중 오류가 발생했습니다: " + e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3294,6 +3294,7 @@
|
||||
0 AS PO_QTY,
|
||||
'' AS VENDOR,
|
||||
0 AS UNIT_PRICE,
|
||||
0 AS PROCESSING_UNIT_PRICE,
|
||||
0 AS TOTAL_PRICE,
|
||||
1 AS LEVEL
|
||||
FROM
|
||||
@@ -3374,6 +3375,7 @@
|
||||
0 AS PO_QTY,
|
||||
'' AS VENDOR,
|
||||
0 AS UNIT_PRICE,
|
||||
0 AS PROCESSING_UNIT_PRICE,
|
||||
0 AS TOTAL_PRICE,
|
||||
1 AS LEVEL
|
||||
FROM
|
||||
@@ -3850,7 +3852,7 @@
|
||||
PROCESSING_VENDOR, PROCESSING_DEADLINE, GRINDING_DEADLINE,
|
||||
REQUIRED_QTY, ORDER_QTY, PRODUCTION_QTY, STOCK_QTY, SHORTAGE_QTY,
|
||||
NET_QTY, PO_QTY,
|
||||
VENDOR, UNIT_PRICE, TOTAL_PRICE, CURRENCY, LEAD_TIME, MIN_ORDER_QTY,
|
||||
VENDOR, UNIT_PRICE, PROCESSING_UNIT_PRICE, TOTAL_PRICE, CURRENCY, LEAD_TIME, MIN_ORDER_QTY,
|
||||
<if test="proposalDate != null">
|
||||
PROPOSAL_DATE,
|
||||
</if>
|
||||
@@ -3863,7 +3865,7 @@
|
||||
#{processingVendor}, #{processingDeadline}, #{grindingDeadline},
|
||||
#{requiredQty}, #{orderQty}, #{productionQty}, #{stockQty}, #{shortageQty},
|
||||
#{netQty}, #{poQty},
|
||||
#{vendor}, #{unitPrice}, #{totalPrice}, #{currency}, #{leadTime}, #{minOrderQty},
|
||||
#{vendor}, #{unitPrice}, #{processingUnitPrice}, #{totalPrice}, #{currency}, #{leadTime}, #{minOrderQty},
|
||||
<if test="proposalDate != null">
|
||||
#{proposalDate},
|
||||
</if>
|
||||
@@ -4049,6 +4051,7 @@
|
||||
MD.PO_QTY,
|
||||
MD.VENDOR,
|
||||
MD.UNIT_PRICE,
|
||||
MD.PROCESSING_UNIT_PRICE,
|
||||
MD.TOTAL_PRICE,
|
||||
MD.CURRENCY,
|
||||
MD.LEAD_TIME,
|
||||
@@ -4102,6 +4105,7 @@
|
||||
SHORTAGE_QTY,
|
||||
VENDOR,
|
||||
UNIT_PRICE,
|
||||
PROCESSING_UNIT_PRICE,
|
||||
TOTAL_PRICE,
|
||||
CURRENCY,
|
||||
LEAD_TIME,
|
||||
@@ -4146,6 +4150,7 @@
|
||||
A.SHORTAGE_QTY,
|
||||
A.VENDOR,
|
||||
A.UNIT_PRICE,
|
||||
A.PROCESSING_UNIT_PRICE,
|
||||
A.TOTAL_PRICE,
|
||||
A.CURRENCY,
|
||||
A.LEAD_TIME,
|
||||
@@ -4198,6 +4203,7 @@
|
||||
B.SHORTAGE_QTY,
|
||||
B.VENDOR,
|
||||
B.UNIT_PRICE,
|
||||
B.PROCESSING_UNIT_PRICE,
|
||||
B.TOTAL_PRICE,
|
||||
B.CURRENCY,
|
||||
B.LEAD_TIME,
|
||||
@@ -4250,6 +4256,7 @@
|
||||
V.VENDOR,
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = V.VENDOR) AS VENDOR_NAME,
|
||||
V.UNIT_PRICE,
|
||||
V.PROCESSING_UNIT_PRICE,
|
||||
V.TOTAL_PRICE,
|
||||
V.CURRENCY,
|
||||
V.LEAD_TIME,
|
||||
@@ -4412,6 +4419,7 @@
|
||||
NULL AS SHORTAGE_QTY,
|
||||
NULL AS VENDOR,
|
||||
NULL AS UNIT_PRICE,
|
||||
NULL AS PROCESSING_UNIT_PRICE,
|
||||
NULL AS TOTAL_PRICE,
|
||||
NULL AS CURRENCY,
|
||||
NULL AS LEAD_TIME,
|
||||
|
||||
@@ -4246,6 +4246,7 @@ SELECT T.*
|
||||
|
||||
<select id="deliveryMngList_new" parameterType="map" resultType="map">
|
||||
SELECT POM.OBJID
|
||||
,POM.STATUS
|
||||
<!-- ,TO_CHAR(CM.REGDATE, 'YYYY') AS CM_YEAR -->
|
||||
,TO_CHAR(POM.REGDATE,'YYYY') AS POM_YEAR
|
||||
,(SELECT SUPPLY_NAME FROM SUPPLY_MNG AS O WHERE O.OBJID::VARCHAR = CM.CUSTOMER_OBJID) AS CUSTOMER_NAME
|
||||
@@ -6123,4 +6124,31 @@ FROM(
|
||||
ORDER BY PART_NO
|
||||
</select>
|
||||
|
||||
<!-- 발주 취소를 위한 입고 수량 조회 (ARRIVAL_PLAN 테이블) -->
|
||||
<select id="getTotalReceiptQtyForCancel" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
COALESCE(SUM(
|
||||
CASE
|
||||
WHEN AP.RECEIPT_QTY IS NULL OR AP.RECEIPT_QTY = '' THEN 0
|
||||
ELSE AP.RECEIPT_QTY::NUMERIC
|
||||
END
|
||||
), 0) AS TOTAL_RECEIPT_QTY
|
||||
FROM ARRIVAL_PLAN AP
|
||||
WHERE AP.PARENT_OBJID = #{PURCHASE_ORDER_MASTER_OBJID}
|
||||
</select>
|
||||
|
||||
<!-- 발주 취소 상태 업데이트 -->
|
||||
<update id="updateOrderCancelStatus" parameterType="map">
|
||||
UPDATE PURCHASE_ORDER_MASTER
|
||||
SET STATUS = #{STATUS}
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 동시발주 하위건 발주 취소 상태 업데이트 -->
|
||||
<update id="updateOrderCancelStatusMulti" parameterType="map">
|
||||
UPDATE PURCHASE_ORDER_MASTER
|
||||
SET STATUS = #{STATUS}
|
||||
WHERE MULTI_MASTER_OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -613,7 +613,7 @@
|
||||
VALUES
|
||||
(
|
||||
#{SALES_REQUEST_MASTER_OBJID },
|
||||
(SELECT 'R'||TO_CHAR(NOW(),'YYYYMMDD')||'-'||LPAD((COALESCE(MAX(SUBSTR(REQUEST_MNG_NO,11,13)),'0')::INTEGER+1)::TEXT,3,'0') FROM SALES_REQUEST_MASTER WHERE DOC_TYPE = 'PURCHASE_REQUEST' OR DOC_TYPE IS NULL),
|
||||
(SELECT 'R'||TO_CHAR(NOW(),'YYYYMMDD')||'-'||LPAD((COALESCE(MAX(SUBSTR(REQUEST_MNG_NO,11,13)),'0')::INTEGER+1)::TEXT,3,'0') FROM SALES_REQUEST_MASTER WHERE DOC_TYPE IN ('PURCHASE_REQUEST', 'PURCHASE_REG') OR DOC_TYPE IS NULL),
|
||||
#{REQUEST_CD },
|
||||
#{PROJECT_NO },
|
||||
#{RELEASE },
|
||||
@@ -633,7 +633,7 @@ VALUES
|
||||
#{AREA_CD },
|
||||
#{CUSTOMER_OBJID },
|
||||
#{PAID_TYPE },
|
||||
'PURCHASE_REQUEST'
|
||||
COALESCE(NULLIF(#{DOC_TYPE}, ''), 'PURCHASE_REQUEST')
|
||||
) ON CONFLICT (OBJID) DO
|
||||
UPDATE
|
||||
SET
|
||||
@@ -757,7 +757,7 @@ VALUES
|
||||
|
||||
<update id="mergeSalesRequestPartInfo" parameterType="map">
|
||||
INSERT INTO SALES_REQUEST_PART
|
||||
(
|
||||
(
|
||||
OBJID,
|
||||
SALES_BOM_QTY_OBJID,
|
||||
PART_OBJID,
|
||||
@@ -771,8 +771,8 @@ VALUES
|
||||
REGDATE,
|
||||
STATUS
|
||||
<!-- REMARK -->
|
||||
)
|
||||
VALUES
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
#{SALES_REQUEST_PART_OBJID },
|
||||
#{SALES_BOM_QTY_OBJID },
|
||||
@@ -788,8 +788,8 @@ VALUES
|
||||
#{STATUS}
|
||||
<!-- #{REMARK} -->
|
||||
) ON CONFLICT (OBJID) DO
|
||||
UPDATE
|
||||
SET
|
||||
UPDATE
|
||||
SET
|
||||
SALES_BOM_QTY_OBJID = #{SALES_BOM_QTY_OBJID },
|
||||
PART_OBJID = #{PART_OBJID },
|
||||
SALES_REQUEST_MASTER_OBJID = #{SALES_REQUEST_MASTER_OBJID},
|
||||
@@ -1117,6 +1117,15 @@ VALUES
|
||||
(SELECT O.UNIT_NO || '-' || O.TASK_NAME FROM PMS_WBS_TASK AS O WHERE O.OBJID = SRM.UNIT_NAME) AS UNIT_CODE_NAME,
|
||||
SRM.STATUS,
|
||||
CASE
|
||||
-- PURCHASE_REG(구매요청서작성) 페이지용 상태
|
||||
WHEN SRM.DOC_TYPE = 'PURCHASE_REG' THEN
|
||||
CASE
|
||||
-- 품의서 생성 여부 확인 (PROPOSAL 타입의 SALES_REQUEST_MASTER가 연결되어 있는지)
|
||||
WHEN EXISTS (SELECT 1 FROM SALES_REQUEST_MASTER P WHERE P.DOC_TYPE = 'PROPOSAL' AND P.PROJECT_NO = SRM.OBJID::VARCHAR) THEN '품의서생성'
|
||||
WHEN SRM.STATUS = 'confirmed' THEN '확정'
|
||||
ELSE '작성중'
|
||||
END
|
||||
-- 기존 PURCHASE_REQUEST용 상태
|
||||
WHEN ((SELECT COUNT(1) FROM PURCHASE_ORDER_MASTER AS O WHERE O.SALES_REQUEST_OBJID IN (SRM.OBJID)) >= (SELECT COUNT(1) FROM SALES_REQUEST_PART AS SRP WHERE srp.SALES_REQUEST_master_OBJID = SRM.OBJID )) and ((SELECT COUNT(1) FROM PURCHASE_ORDER_MASTER AS O WHERE O.SALES_REQUEST_OBJID IN (SRM.OBJID)) > 0) THEN '발주완료'
|
||||
WHEN ((SELECT COUNT(1) FROM PURCHASE_ORDER_MASTER AS O WHERE O.SALES_REQUEST_OBJID IN (SRM.OBJID)) < (SELECT COUNT(1) FROM SALES_REQUEST_PART AS SRP WHERE srp.SALES_REQUEST_master_OBJID = SRM.OBJID )) and ((SELECT COUNT(1) FROM PURCHASE_ORDER_MASTER AS O WHERE O.SALES_REQUEST_OBJID IN (SRM.OBJID)) > 0) THEN '발주부분완료'
|
||||
WHEN SRM.STATUS = 'create' THEN '등록'
|
||||
@@ -1125,7 +1134,7 @@ VALUES
|
||||
WHEN SRM.STATUS = 'approvalRequest' THEN '결재중'
|
||||
WHEN SRM.STATUS = 'approvalComplete' THEN '결재완료'
|
||||
WHEN SRM.STATUS = 'reject' THEN '반려'
|
||||
<!-- WHEN 'orderComplete' THEN '발주완료' -->
|
||||
WHEN SRM.STATUS = 'confirmed' THEN '확정'
|
||||
ELSE ''
|
||||
END STATUS_TITLE,
|
||||
SRM.RECEIPT_USER_ID,
|
||||
@@ -1224,7 +1233,15 @@ VALUES
|
||||
AND SRP.SUB_RNUM = 1 -->
|
||||
WHERE 1=1
|
||||
-- 구매요청서만 조회 (품의서 제외)
|
||||
AND (SRM.DOC_TYPE = 'PURCHASE_REQUEST' OR SRM.DOC_TYPE IS NULL)
|
||||
-- DOC_TYPE_FILTER가 있으면 해당 값으로 필터링, 없으면 기존 조건 적용
|
||||
<choose>
|
||||
<when test="DOC_TYPE_FILTER != null and !''.equals(DOC_TYPE_FILTER)">
|
||||
AND SRM.DOC_TYPE = #{DOC_TYPE_FILTER}
|
||||
</when>
|
||||
<otherwise>
|
||||
AND (SRM.DOC_TYPE = 'PURCHASE_REQUEST' OR SRM.DOC_TYPE IS NULL)
|
||||
</otherwise>
|
||||
</choose>
|
||||
<if test="Year !=null and Year != '' ">
|
||||
AND TO_CHAR(REGDATE,'YYYY') = #{Year}
|
||||
</if>
|
||||
@@ -1403,24 +1420,24 @@ VALUES
|
||||
|
||||
<select id="SalesBomPartListByProjectUnit" parameterType="map" resultType="map">
|
||||
<!-- M-BOM 데이터 조회: getMbomList와 동일한 조인 방식 사용 (BPQ.PART_NO = PM.PART_NO) -->
|
||||
SELECT
|
||||
SELECT
|
||||
BPQ.BOM_REPORT_OBJID
|
||||
,BPQ.PART_NO AS PART_OBJID
|
||||
,COALESCE(PM.PART_NO, BPQ.PART_NO, '') AS PART_NO
|
||||
,COALESCE(PM.PART_NAME, '') AS PART_NAME
|
||||
,COALESCE(PM.PART_NAME, '') AS PART_FULL_NAME
|
||||
,COALESCE(PM.STANDARD, '') AS SPEC
|
||||
,COALESCE(PM.SPEC, '') AS SPEC
|
||||
,BPQ.QTY AS ORDER_QTY
|
||||
,COALESCE(PM.MAKER, '') AS MAKER
|
||||
,'' AS REMARK
|
||||
,'' AS UNIT
|
||||
,NULL AS SUPPLY_OBJID
|
||||
,NULL AS WRITER
|
||||
FROM
|
||||
FROM
|
||||
PROJECT_MGMT AS PJT
|
||||
INNER JOIN BOM_PART_QTY AS BPQ
|
||||
INNER JOIN BOM_PART_QTY AS BPQ
|
||||
ON PJT.BOM_REPORT_OBJID::VARCHAR = BPQ.BOM_REPORT_OBJID::VARCHAR
|
||||
LEFT JOIN PART_MNG AS PM
|
||||
LEFT JOIN PART_MNG AS PM
|
||||
ON BPQ.PART_NO = PM.PART_NO
|
||||
WHERE 1=1
|
||||
AND PJT.OBJID::VARCHAR = #{PROJECT_OBJID}
|
||||
@@ -3097,7 +3114,11 @@ UPDATE SET
|
||||
COALESCE(SRP.VENDOR_PM, SRP.PARTNER_OBJID) AS VENDOR_PM,
|
||||
COALESCE(SRP.UNIT_PRICE, NULLIF(SRP.PARTNER_PRICE, '')::numeric, 0) AS UNIT_PRICE,
|
||||
COALESCE(SRP.TOTAL_PRICE, 0) AS TOTAL_PRICE,
|
||||
COALESCE(SRP.PROCESSING_UNIT_PRICE, 0) AS PROCESSING_UNIT_PRICE,
|
||||
COALESCE(SRP.PROCESSING_TOTAL_PRICE, 0) AS PROCESSING_TOTAL_PRICE,
|
||||
COALESCE(SRP.GRAND_TOTAL_PRICE, 0) AS GRAND_TOTAL_PRICE,
|
||||
SRP.PROPOSAL_DATE,
|
||||
SRP.PROCESSING_PROPOSAL_DATE,
|
||||
'SRP' AS DATA_SOURCE -- 데이터 소스 구분용
|
||||
FROM
|
||||
SALES_REQUEST_PART SRP
|
||||
@@ -3156,7 +3177,11 @@ WITH RECURSIVE VIEW_BOM(
|
||||
USE_YN,
|
||||
NET_QTY,
|
||||
PO_QTY,
|
||||
PROPOSAL_DATE
|
||||
PROPOSAL_DATE,
|
||||
PROCESSING_PROPOSAL_DATE,
|
||||
PROCESSING_UNIT_PRICE,
|
||||
PROCESSING_TOTAL_PRICE,
|
||||
GRAND_TOTAL_PRICE
|
||||
) AS (
|
||||
SELECT
|
||||
A.MBOM_HEADER_OBJID,
|
||||
@@ -3204,7 +3229,11 @@ WITH RECURSIVE VIEW_BOM(
|
||||
COALESCE(A.USE_YN, 'Y'),
|
||||
COALESCE(A.NET_QTY, 0),
|
||||
COALESCE(A.PO_QTY, 0),
|
||||
A.PROPOSAL_DATE
|
||||
A.PROPOSAL_DATE,
|
||||
A.PROCESSING_PROPOSAL_DATE,
|
||||
COALESCE(A.PROCESSING_UNIT_PRICE, 0),
|
||||
COALESCE(A.PROCESSING_TOTAL_PRICE, 0),
|
||||
COALESCE(A.GRAND_TOTAL_PRICE, 0)
|
||||
FROM
|
||||
MBOM_DETAIL A
|
||||
INNER JOIN MBOM_HEADER MH ON MH.OBJID = A.MBOM_HEADER_OBJID
|
||||
@@ -3264,7 +3293,11 @@ WITH RECURSIVE VIEW_BOM(
|
||||
COALESCE(B.USE_YN, 'Y'),
|
||||
COALESCE(B.NET_QTY, 0),
|
||||
COALESCE(B.PO_QTY, 0),
|
||||
B.PROPOSAL_DATE
|
||||
B.PROPOSAL_DATE,
|
||||
B.PROCESSING_PROPOSAL_DATE,
|
||||
COALESCE(B.PROCESSING_UNIT_PRICE, 0),
|
||||
COALESCE(B.PROCESSING_TOTAL_PRICE, 0),
|
||||
COALESCE(B.GRAND_TOTAL_PRICE, 0)
|
||||
FROM
|
||||
MBOM_DETAIL B
|
||||
JOIN
|
||||
@@ -3352,10 +3385,15 @@ SELECT
|
||||
V.NET_QTY,
|
||||
V.PO_QTY,
|
||||
V.PROPOSAL_DATE,
|
||||
V.PROCESSING_PROPOSAL_DATE,
|
||||
V.PROCESSING_UNIT_PRICE,
|
||||
V.PROCESSING_TOTAL_PRICE,
|
||||
V.GRAND_TOTAL_PRICE,
|
||||
'MBOM' AS DATA_SOURCE -- 데이터 소스 구분용
|
||||
FROM VIEW_BOM V
|
||||
LEFT JOIN PART_MNG P ON P.OBJID::VARCHAR = V.PART_OBJID::VARCHAR
|
||||
WHERE 1=1
|
||||
AND COALESCE(V.PRODUCTION_QTY, 0) > 0 -- 제작수량이 0인 항목 제외
|
||||
ORDER BY V.PATH2
|
||||
</select>
|
||||
|
||||
@@ -3382,6 +3420,9 @@ ORDER BY V.PATH2
|
||||
PROCESSING_VENDOR = #{PROCESSING_VENDOR},
|
||||
UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
PROCESSING_UNIT_PRICE = COALESCE(NULLIF(TRIM(#{PROCESSING_UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
PROCESSING_TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{PROCESSING_TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
GRAND_TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{GRAND_TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
EDITER = #{EDITER},
|
||||
EDIT_DATE = NOW()
|
||||
WHERE OBJID::VARCHAR = #{OBJID}
|
||||
@@ -3397,6 +3438,9 @@ ORDER BY V.PATH2
|
||||
PROCESSING_VENDOR = #{PROCESSING_VENDOR},
|
||||
UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
PROCESSING_UNIT_PRICE = COALESCE(NULLIF(TRIM(#{PROCESSING_UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
PROCESSING_TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{PROCESSING_TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
GRAND_TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{GRAND_TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
WRITER = #{EDITER}
|
||||
WHERE OBJID::VARCHAR = #{OBJID}
|
||||
</update>
|
||||
@@ -3418,9 +3462,9 @@ ORDER BY V.PATH2
|
||||
|
||||
<!-- 다음 요청번호 생성 (R + YYYYMMDD + - + 3자리 순번) - 구매요청서용 -->
|
||||
<select id="getNextRequestMngNo" resultType="string">
|
||||
SELECT 'R'||TO_CHAR(NOW(),'YYYYMMDD')||'-'||LPAD((COALESCE(MAX(SUBSTR(REQUEST_MNG_NO,11,13)),'0')::INTEGER+1)::TEXT,3,'0')
|
||||
SELECT 'R'||TO_CHAR(NOW(),'YYYYMMDD')||'-'||LPAD((COALESCE(MAX(SUBSTR(REQUEST_MNG_NO,11,13)),'0')::INTEGER+1)::TEXT,3,'0')
|
||||
FROM SALES_REQUEST_MASTER
|
||||
WHERE DOC_TYPE = 'PURCHASE_REQUEST' OR DOC_TYPE IS NULL
|
||||
WHERE DOC_TYPE IN ('PURCHASE_REQUEST', 'PURCHASE_REG') OR DOC_TYPE IS NULL
|
||||
</select>
|
||||
|
||||
<!-- 다음 품의서 번호 생성 (P + YYYYMMDD + - + 3자리 순번) - 품의서용 -->
|
||||
@@ -3459,7 +3503,7 @@ ORDER BY V.PATH2
|
||||
|
||||
<!-- ==================== 품의서 관리 ==================== -->
|
||||
|
||||
<!-- 품의서 대상 품목 조회 - M-BOM 기반 (MBOM_DETAIL에서 조회) -->
|
||||
<!-- 품의서 대상 품목 조회 - M-BOM 기반 (MBOM_DETAIL에서 조회) - 소재단가 기준 -->
|
||||
<select id="getProposalTargetPartsFromMBom" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
MD.OBJID,
|
||||
@@ -3470,27 +3514,62 @@ ORDER BY V.PATH2
|
||||
MD.UNIT_PRICE,
|
||||
MD.TOTAL_PRICE,
|
||||
MD.VENDOR AS VENDOR_PM,
|
||||
(SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE OBJID::VARCHAR = MD.VENDOR) AS VENDOR_NAME,
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = MD.VENDOR) AS VENDOR_NAME,
|
||||
MD.NET_QTY,
|
||||
MD.PO_QTY,
|
||||
'MBOM' AS DATA_SOURCE
|
||||
MD.PRODUCTION_QTY,
|
||||
'MBOM' AS DATA_SOURCE,
|
||||
'MATERIAL' AS PROPOSAL_TYPE
|
||||
FROM
|
||||
MBOM_DETAIL MD
|
||||
LEFT JOIN PART_MNG PM ON MD.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR
|
||||
WHERE
|
||||
MD.MBOM_HEADER_OBJID = #{MBOM_HEADER_OBJID}
|
||||
-- 단가가 입력되어 있고
|
||||
-- 소재단가가 입력되어 있고
|
||||
AND MD.UNIT_PRICE IS NOT NULL
|
||||
AND MD.UNIT_PRICE > 0
|
||||
-- 공급업체가 입력되어 있고
|
||||
AND MD.VENDOR IS NOT NULL
|
||||
AND MD.VENDOR != ''
|
||||
-- 품의서가 생성되지 않은 품목만
|
||||
-- 소재 품의서가 생성되지 않은 품목만
|
||||
AND MD.PROPOSAL_DATE IS NULL
|
||||
ORDER BY MD.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 대상 제외 품목 조회 - M-BOM 기반 (단가O, 공급업체X) -->
|
||||
<!-- 품의서 대상 품목 조회 - M-BOM 기반 (MBOM_DETAIL에서 조회) - 가공단가 기준 -->
|
||||
<select id="getProposalTargetPartsFromMBomProcessing" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
MD.OBJID,
|
||||
MD.PART_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
MD.QTY,
|
||||
MD.PROCESSING_UNIT_PRICE AS UNIT_PRICE,
|
||||
MD.PROCESSING_TOTAL_PRICE AS TOTAL_PRICE,
|
||||
MD.PROCESSING_VENDOR AS VENDOR_PM,
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = MD.PROCESSING_VENDOR) AS VENDOR_NAME,
|
||||
MD.NET_QTY,
|
||||
MD.PO_QTY,
|
||||
MD.PRODUCTION_QTY,
|
||||
'MBOM' AS DATA_SOURCE,
|
||||
'PROCESSING' AS PROPOSAL_TYPE
|
||||
FROM
|
||||
MBOM_DETAIL MD
|
||||
LEFT JOIN PART_MNG PM ON MD.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR
|
||||
WHERE
|
||||
MD.MBOM_HEADER_OBJID = #{MBOM_HEADER_OBJID}
|
||||
-- 가공단가가 입력되어 있고
|
||||
AND MD.PROCESSING_UNIT_PRICE IS NOT NULL
|
||||
AND MD.PROCESSING_UNIT_PRICE > 0
|
||||
-- 가공업체가 입력되어 있고
|
||||
AND MD.PROCESSING_VENDOR IS NOT NULL
|
||||
AND MD.PROCESSING_VENDOR != ''
|
||||
-- 가공 품의서가 생성되지 않은 품목만
|
||||
AND MD.PROCESSING_PROPOSAL_DATE IS NULL
|
||||
ORDER BY MD.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 대상 제외 품목 조회 - M-BOM 기반 (소재단가O, 공급업체X) -->
|
||||
<select id="getProposalExcludedPartsFromMBom" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
MD.OBJID,
|
||||
@@ -3500,23 +3579,51 @@ ORDER BY V.PATH2
|
||||
MD.QTY,
|
||||
MD.UNIT_PRICE,
|
||||
MD.TOTAL_PRICE,
|
||||
'MBOM' AS DATA_SOURCE
|
||||
'MBOM' AS DATA_SOURCE,
|
||||
'MATERIAL' AS PROPOSAL_TYPE
|
||||
FROM
|
||||
MBOM_DETAIL MD
|
||||
LEFT JOIN PART_MNG PM ON MD.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR
|
||||
WHERE
|
||||
MD.MBOM_HEADER_OBJID = #{MBOM_HEADER_OBJID}
|
||||
-- 단가가 입력되어 있고
|
||||
-- 소재단가가 입력되어 있고
|
||||
AND MD.UNIT_PRICE IS NOT NULL
|
||||
AND MD.UNIT_PRICE > 0
|
||||
-- 공급업체가 미입력
|
||||
AND (MD.VENDOR IS NULL OR MD.VENDOR = '')
|
||||
-- 품의서가 생성되지 않은 품목만
|
||||
-- 소재 품의서가 생성되지 않은 품목만
|
||||
AND MD.PROPOSAL_DATE IS NULL
|
||||
ORDER BY MD.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 대상 품목 조회 - 수동 작성 (SALES_REQUEST_PART에서 조회) -->
|
||||
<!-- 품의서 대상 제외 품목 조회 - M-BOM 기반 (가공단가O, 가공업체X) -->
|
||||
<select id="getProposalExcludedPartsFromMBomProcessing" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
MD.OBJID,
|
||||
MD.PART_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
MD.QTY,
|
||||
MD.PROCESSING_UNIT_PRICE AS UNIT_PRICE,
|
||||
MD.PROCESSING_TOTAL_PRICE AS TOTAL_PRICE,
|
||||
'MBOM' AS DATA_SOURCE,
|
||||
'PROCESSING' AS PROPOSAL_TYPE
|
||||
FROM
|
||||
MBOM_DETAIL MD
|
||||
LEFT JOIN PART_MNG PM ON MD.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR
|
||||
WHERE
|
||||
MD.MBOM_HEADER_OBJID = #{MBOM_HEADER_OBJID}
|
||||
-- 가공단가가 입력되어 있고
|
||||
AND MD.PROCESSING_UNIT_PRICE IS NOT NULL
|
||||
AND MD.PROCESSING_UNIT_PRICE > 0
|
||||
-- 가공업체가 미입력
|
||||
AND (MD.PROCESSING_VENDOR IS NULL OR MD.PROCESSING_VENDOR = '')
|
||||
-- 가공 품의서가 생성되지 않은 품목만
|
||||
AND MD.PROCESSING_PROPOSAL_DATE IS NULL
|
||||
ORDER BY MD.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 대상 품목 조회 - 수동 작성 (SALES_REQUEST_PART에서 조회) - 소재단가 기준 -->
|
||||
<select id="getProposalTargetPartsFromManual" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
SRP.OBJID,
|
||||
@@ -3527,27 +3634,62 @@ ORDER BY V.PATH2
|
||||
SRP.UNIT_PRICE,
|
||||
SRP.TOTAL_PRICE,
|
||||
SRP.VENDOR_PM,
|
||||
(SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE OBJID::VARCHAR = SRP.VENDOR_PM) AS VENDOR_NAME,
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = SRP.VENDOR_PM) AS VENDOR_NAME,
|
||||
SRP.NET_QTY,
|
||||
SRP.PO_QTY,
|
||||
'MANUAL' AS DATA_SOURCE
|
||||
SRP.PRODUCTION_QTY,
|
||||
'MANUAL' AS DATA_SOURCE,
|
||||
'MATERIAL' AS PROPOSAL_TYPE
|
||||
FROM
|
||||
SALES_REQUEST_PART SRP
|
||||
LEFT JOIN PART_MNG PM ON SRP.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR
|
||||
WHERE
|
||||
SRP.SALES_REQUEST_MASTER_OBJID = #{SALES_REQUEST_MASTER_OBJID}
|
||||
-- 단가가 입력되어 있고
|
||||
-- 소재단가가 입력되어 있고
|
||||
AND SRP.UNIT_PRICE IS NOT NULL
|
||||
AND SRP.UNIT_PRICE > 0
|
||||
-- 공급업체가 입력되어 있고
|
||||
AND SRP.VENDOR_PM IS NOT NULL
|
||||
AND SRP.VENDOR_PM != ''
|
||||
-- 품의서가 생성되지 않은 품목만
|
||||
-- 소재 품의서가 생성되지 않은 품목만
|
||||
AND SRP.PROPOSAL_DATE IS NULL
|
||||
ORDER BY SRP.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 대상 제외 품목 조회 - 수동 작성 (단가O, 공급업체X) -->
|
||||
<!-- 품의서 대상 품목 조회 - 수동 작성 (SALES_REQUEST_PART에서 조회) - 가공단가 기준 -->
|
||||
<select id="getProposalTargetPartsFromManualProcessing" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
SRP.OBJID,
|
||||
SRP.PART_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
SRP.QTY,
|
||||
SRP.PROCESSING_UNIT_PRICE AS UNIT_PRICE,
|
||||
SRP.PROCESSING_TOTAL_PRICE AS TOTAL_PRICE,
|
||||
SRP.PROCESSING_VENDOR AS VENDOR_PM,
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = SRP.PROCESSING_VENDOR) AS VENDOR_NAME,
|
||||
SRP.NET_QTY,
|
||||
SRP.PO_QTY,
|
||||
SRP.PRODUCTION_QTY,
|
||||
'MANUAL' AS DATA_SOURCE,
|
||||
'PROCESSING' AS PROPOSAL_TYPE
|
||||
FROM
|
||||
SALES_REQUEST_PART SRP
|
||||
LEFT JOIN PART_MNG PM ON SRP.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR
|
||||
WHERE
|
||||
SRP.SALES_REQUEST_MASTER_OBJID = #{SALES_REQUEST_MASTER_OBJID}
|
||||
-- 가공단가가 입력되어 있고
|
||||
AND SRP.PROCESSING_UNIT_PRICE IS NOT NULL
|
||||
AND SRP.PROCESSING_UNIT_PRICE > 0
|
||||
-- 가공업체가 입력되어 있고
|
||||
AND SRP.PROCESSING_VENDOR IS NOT NULL
|
||||
AND SRP.PROCESSING_VENDOR != ''
|
||||
-- 가공 품의서가 생성되지 않은 품목만
|
||||
AND SRP.PROCESSING_PROPOSAL_DATE IS NULL
|
||||
ORDER BY SRP.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 대상 제외 품목 조회 - 수동 작성 (소재단가O, 공급업체X) -->
|
||||
<select id="getProposalExcludedPartsFromManual" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
SRP.OBJID,
|
||||
@@ -3557,22 +3699,50 @@ ORDER BY V.PATH2
|
||||
SRP.QTY,
|
||||
SRP.UNIT_PRICE,
|
||||
SRP.TOTAL_PRICE,
|
||||
'MANUAL' AS DATA_SOURCE
|
||||
'MANUAL' AS DATA_SOURCE,
|
||||
'MATERIAL' AS PROPOSAL_TYPE
|
||||
FROM
|
||||
SALES_REQUEST_PART SRP
|
||||
LEFT JOIN PART_MNG PM ON SRP.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR
|
||||
WHERE
|
||||
SRP.SALES_REQUEST_MASTER_OBJID = #{SALES_REQUEST_MASTER_OBJID}
|
||||
-- 단가가 입력되어 있고
|
||||
-- 소재단가가 입력되어 있고
|
||||
AND SRP.UNIT_PRICE IS NOT NULL
|
||||
AND SRP.UNIT_PRICE > 0
|
||||
-- 공급업체가 미입력
|
||||
AND (SRP.VENDOR_PM IS NULL OR SRP.VENDOR_PM = '')
|
||||
-- 품의서가 생성되지 않은 품목만
|
||||
-- 소재 품의서가 생성되지 않은 품목만
|
||||
AND SRP.PROPOSAL_DATE IS NULL
|
||||
ORDER BY SRP.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 대상 제외 품목 조회 - 수동 작성 (가공단가O, 가공업체X) -->
|
||||
<select id="getProposalExcludedPartsFromManualProcessing" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
SRP.OBJID,
|
||||
SRP.PART_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
SRP.QTY,
|
||||
SRP.PROCESSING_UNIT_PRICE AS UNIT_PRICE,
|
||||
SRP.PROCESSING_TOTAL_PRICE AS TOTAL_PRICE,
|
||||
'MANUAL' AS DATA_SOURCE,
|
||||
'PROCESSING' AS PROPOSAL_TYPE
|
||||
FROM
|
||||
SALES_REQUEST_PART SRP
|
||||
LEFT JOIN PART_MNG PM ON SRP.PART_OBJID::VARCHAR = PM.OBJID::VARCHAR
|
||||
WHERE
|
||||
SRP.SALES_REQUEST_MASTER_OBJID = #{SALES_REQUEST_MASTER_OBJID}
|
||||
-- 가공단가가 입력되어 있고
|
||||
AND SRP.PROCESSING_UNIT_PRICE IS NOT NULL
|
||||
AND SRP.PROCESSING_UNIT_PRICE > 0
|
||||
-- 가공업체가 미입력
|
||||
AND (SRP.PROCESSING_VENDOR IS NULL OR SRP.PROCESSING_VENDOR = '')
|
||||
-- 가공 품의서가 생성되지 않은 품목만
|
||||
AND SRP.PROCESSING_PROPOSAL_DATE IS NULL
|
||||
ORDER BY SRP.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 생성 (SALES_REQUEST_MASTER에 INSERT) -->
|
||||
<insert id="insertProposal" parameterType="map">
|
||||
INSERT INTO SALES_REQUEST_MASTER (
|
||||
@@ -3610,7 +3780,7 @@ ORDER BY V.PATH2
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 품의서용 SALES_REQUEST_PART 생성 (M-BOM 기반 품목 복사) -->
|
||||
<!-- 품의서용 SALES_REQUEST_PART 생성 (M-BOM 기반 품목 복사) - 소재 -->
|
||||
<insert id="insertProposalPartFromMBom" parameterType="map">
|
||||
INSERT INTO SALES_REQUEST_PART (
|
||||
OBJID,
|
||||
@@ -3645,7 +3815,42 @@ ORDER BY V.PATH2
|
||||
WHERE OBJID = #{SOURCE_OBJID}
|
||||
</insert>
|
||||
|
||||
<!-- 품의서용 SALES_REQUEST_PART 생성 (수동 작성 품목 복사) -->
|
||||
<!-- 품의서용 SALES_REQUEST_PART 생성 (M-BOM 기반 품목 복사) - 가공 -->
|
||||
<insert id="insertProposalPartFromMBomProcessing" parameterType="map">
|
||||
INSERT INTO SALES_REQUEST_PART (
|
||||
OBJID,
|
||||
SALES_REQUEST_MASTER_OBJID,
|
||||
PART_OBJID,
|
||||
QTY,
|
||||
UNIT_PRICE,
|
||||
TOTAL_PRICE,
|
||||
VENDOR_PM,
|
||||
NET_QTY,
|
||||
PO_QTY,
|
||||
USE_YN,
|
||||
PROPOSAL_DATE,
|
||||
WRITER,
|
||||
REGDATE
|
||||
)
|
||||
SELECT
|
||||
#{NEW_OBJID},
|
||||
#{PROPOSAL_MASTER_OBJID},
|
||||
PART_OBJID,
|
||||
PRODUCTION_QTY AS QTY,
|
||||
PROCESSING_UNIT_PRICE AS UNIT_PRICE,
|
||||
PROCESSING_TOTAL_PRICE AS TOTAL_PRICE,
|
||||
PROCESSING_VENDOR AS VENDOR_PM,
|
||||
NET_QTY,
|
||||
PO_QTY,
|
||||
USE_YN,
|
||||
NOW() AS PROPOSAL_DATE,
|
||||
#{WRITER},
|
||||
NOW()
|
||||
FROM MBOM_DETAIL
|
||||
WHERE OBJID = #{SOURCE_OBJID}
|
||||
</insert>
|
||||
|
||||
<!-- 품의서용 SALES_REQUEST_PART 생성 (수동 작성 품목 복사) - 소재 -->
|
||||
<insert id="insertProposalPartFromManual" parameterType="map">
|
||||
INSERT INTO SALES_REQUEST_PART (
|
||||
OBJID,
|
||||
@@ -3680,7 +3885,42 @@ ORDER BY V.PATH2
|
||||
WHERE OBJID = #{SOURCE_OBJID}
|
||||
</insert>
|
||||
|
||||
<!-- 품의서 생성 후 PROPOSAL_DATE 업데이트 (수동 작성 - SALES_REQUEST_PART) -->
|
||||
<!-- 품의서용 SALES_REQUEST_PART 생성 (수동 작성 품목 복사) - 가공 -->
|
||||
<insert id="insertProposalPartFromManualProcessing" parameterType="map">
|
||||
INSERT INTO SALES_REQUEST_PART (
|
||||
OBJID,
|
||||
SALES_REQUEST_MASTER_OBJID,
|
||||
PART_OBJID,
|
||||
QTY,
|
||||
UNIT_PRICE,
|
||||
TOTAL_PRICE,
|
||||
VENDOR_PM,
|
||||
NET_QTY,
|
||||
PO_QTY,
|
||||
USE_YN,
|
||||
PROPOSAL_DATE,
|
||||
WRITER,
|
||||
REGDATE
|
||||
)
|
||||
SELECT
|
||||
#{NEW_OBJID},
|
||||
#{PROPOSAL_MASTER_OBJID},
|
||||
PART_OBJID,
|
||||
PRODUCTION_QTY AS QTY,
|
||||
PROCESSING_UNIT_PRICE AS UNIT_PRICE,
|
||||
PROCESSING_TOTAL_PRICE AS TOTAL_PRICE,
|
||||
PROCESSING_VENDOR AS VENDOR_PM,
|
||||
NET_QTY,
|
||||
PO_QTY,
|
||||
USE_YN,
|
||||
NOW() AS PROPOSAL_DATE,
|
||||
#{WRITER},
|
||||
NOW()
|
||||
FROM SALES_REQUEST_PART
|
||||
WHERE OBJID = #{SOURCE_OBJID}
|
||||
</insert>
|
||||
|
||||
<!-- 품의서 생성 후 PROPOSAL_DATE 업데이트 (수동 작성 - SALES_REQUEST_PART) - 소재 -->
|
||||
<update id="updateProposalDateForManualParts" parameterType="map">
|
||||
UPDATE SALES_REQUEST_PART
|
||||
SET PROPOSAL_DATE = NOW()
|
||||
@@ -3690,7 +3930,17 @@ ORDER BY V.PATH2
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!-- 품의서 생성 후 PROPOSAL_DATE 업데이트 (M-BOM - MBOM_DETAIL) -->
|
||||
<!-- 품의서 생성 후 PROCESSING_PROPOSAL_DATE 업데이트 (수동 작성 - SALES_REQUEST_PART) - 가공 -->
|
||||
<update id="updateProcessingProposalDateForManualParts" parameterType="map">
|
||||
UPDATE SALES_REQUEST_PART
|
||||
SET PROCESSING_PROPOSAL_DATE = NOW()
|
||||
WHERE OBJID IN
|
||||
<foreach collection="PART_OBJIDS" item="objid" open="(" separator="," close=")">
|
||||
#{objid}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!-- 품의서 생성 후 PROPOSAL_DATE 업데이트 (M-BOM - MBOM_DETAIL) - 소재 -->
|
||||
<update id="updateProposalDateForMBomParts" parameterType="map">
|
||||
UPDATE MBOM_DETAIL
|
||||
SET PROPOSAL_DATE = NOW()
|
||||
@@ -3700,6 +3950,16 @@ ORDER BY V.PATH2
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!-- 품의서 생성 후 PROCESSING_PROPOSAL_DATE 업데이트 (M-BOM - MBOM_DETAIL) - 가공 -->
|
||||
<update id="updateProcessingProposalDateForMBomParts" parameterType="map">
|
||||
UPDATE MBOM_DETAIL
|
||||
SET PROCESSING_PROPOSAL_DATE = NOW()
|
||||
WHERE OBJID IN
|
||||
<foreach collection="PART_OBJIDS" item="objid" open="(" separator="," close=")">
|
||||
#{objid}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!-- 품의서 목록 조회 -->
|
||||
<select id="getProposalMngGridList" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
|
||||
@@ -194,6 +194,56 @@ public class SalesMngController {
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 구매요청서 작성 페이지 (새로운 페이지)
|
||||
* - 구매요청서 작성 버튼 활성화
|
||||
* - SOURCE_TYPE = 'PURCHASE_REG'인 데이터만 조회
|
||||
*/
|
||||
@RequestMapping("/salesMng/purchaseRequestRegList.do")
|
||||
public String purchaseRequestRegList(HttpServletRequest request, @RequestParam Map paramMap){
|
||||
String actionType = CommonUtils.checkNull(paramMap.get("actionType"));
|
||||
String returnUrl = "/salesMng/purchaseRequestRegList";
|
||||
Map code_map = new HashMap();
|
||||
|
||||
try {
|
||||
if("excel".equals(actionType)){
|
||||
returnUrl = "/salesMng/purchaseRequestRegList";
|
||||
}
|
||||
|
||||
paramMap.put("SEARCH_STATUS", "create,reject,approvalRequest,release,reception");
|
||||
|
||||
// 프로젝트번호 project_no
|
||||
code_map.put("contract_objid",commonService.bizMakeOptionList("", (String)paramMap.get("contract_objid"),"common.getProjectNameList"));
|
||||
// 상태
|
||||
code_map.put("act_status",commonService.bizMakeOptionList("0001062", (String)paramMap.get("act_status"),"common.getCodeselect"));
|
||||
// 접수자
|
||||
code_map.put("receipt_writer", commonService.bizMakeOptionList("", (String)paramMap.get("writer"),"common.getUserselect"));
|
||||
// 구분
|
||||
code_map.put("request_cd",commonService.bizMakeOptionList("0000167", (String)paramMap.get("request_cd"),"common.getCodeselect"));
|
||||
|
||||
code_map.put("product_code",commonService.bizMakeOptionList("", (String)paramMap.get("product_code"),"common.getProductCodeselect"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
request.setAttribute("code_map", code_map);
|
||||
|
||||
return returnUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 구매요청서 작성 - 목록 페이징 (새로운 페이지용)
|
||||
* - DOC_TYPE = 'PURCHASE_REG'인 데이터만 조회
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/salesMng/purchaseRequestRegGridList.do")
|
||||
public Map getPurchaseRequestRegList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
// DOC_TYPE 필터 추가 (구매요청서 작성 페이지에서 생성된 데이터만)
|
||||
paramMap.put("DOC_TYPE_FILTER", "PURCHASE_REG");
|
||||
commonService.selectListPagingNew("salesMng.getSalesRequestMasterGridList", request, paramMap);
|
||||
return paramMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 구매의뢰서 조회
|
||||
*/
|
||||
@@ -419,6 +469,26 @@ public class SalesMngController {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 구매요청서 확정 처리
|
||||
* - STATUS를 'confirmed'로 변경하여 수정 불가능하게 함
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/salesMng/confirmSalesRequest.do")
|
||||
public Map<String,Object> confirmSalesRequest(HttpServletRequest request, @RequestParam Map paramMap){
|
||||
Map<String,Object> resultMap = new HashMap();
|
||||
|
||||
try{
|
||||
resultMap = salesMngService.confirmSalesRequest(request, paramMap);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("msg", "확정 처리 중 오류가 발생했습니다.");
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 구매의뢰 공급업체 내용을 저장한다.
|
||||
* @param request
|
||||
@@ -1358,25 +1428,37 @@ public class SalesMngController {
|
||||
|
||||
String salesRequestMasterObjid = CommonUtils.checkNull(paramMap.get("SALES_REQUEST_MASTER_OBJID"));
|
||||
|
||||
// Service의 공통 메서드 사용
|
||||
// Service의 공통 메서드 사용 (소재/가공 분리)
|
||||
Map partsInfo = salesMngService.getProposalTargetPartsWithInfo(sqlSession, salesRequestMasterObjid);
|
||||
List<Map> targetParts = (List<Map>)partsInfo.get("targetParts");
|
||||
List<Map> excludedParts = (List<Map>)partsInfo.get("excludedParts"); // 공급업체 미입력 품목
|
||||
|
||||
if(targetParts != null && !targetParts.isEmpty()) {
|
||||
// 소재/가공 각각 분리된 데이터
|
||||
List<Map> materialTargetParts = (List<Map>)partsInfo.get("materialTargetParts");
|
||||
List<Map> processingTargetParts = (List<Map>)partsInfo.get("processingTargetParts");
|
||||
List<Map> materialExcludedParts = (List<Map>)partsInfo.get("materialExcludedParts");
|
||||
List<Map> processingExcludedParts = (List<Map>)partsInfo.get("processingExcludedParts");
|
||||
|
||||
// 기존 호환성을 위한 통합 데이터
|
||||
List<Map> targetParts = (List<Map>)partsInfo.get("targetParts");
|
||||
List<Map> excludedParts = (List<Map>)partsInfo.get("excludedParts");
|
||||
|
||||
boolean hasMaterialParts = materialTargetParts != null && !materialTargetParts.isEmpty();
|
||||
boolean hasProcessingParts = processingTargetParts != null && !processingTargetParts.isEmpty();
|
||||
|
||||
if(hasMaterialParts || hasProcessingParts) {
|
||||
resultMap.put("resultFlag", "S");
|
||||
// 소재/가공 분리 데이터
|
||||
resultMap.put("materialTargetParts", materialTargetParts);
|
||||
resultMap.put("processingTargetParts", processingTargetParts);
|
||||
resultMap.put("materialExcludedParts", materialExcludedParts);
|
||||
resultMap.put("processingExcludedParts", processingExcludedParts);
|
||||
// 기존 호환성
|
||||
resultMap.put("data", targetParts);
|
||||
resultMap.put("excludedParts", excludedParts); // 공급업체 미입력 품목도 함께 반환
|
||||
resultMap.put("excludedParts", excludedParts);
|
||||
} else {
|
||||
// 대상 품목이 없는 경우, 공급업체 미입력 품목이 있는지 확인
|
||||
if(excludedParts != null && !excludedParts.isEmpty()) {
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품의서 생성 대상 품목이 없습니다.\n(단가와 공급업체가 모두 입력된 품목만 가능)");
|
||||
resultMap.put("excludedParts", excludedParts);
|
||||
} else {
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품의서 생성 대상 품목이 없습니다.\n(단가가 입력되고 품의서가 생성되지 않은 품목만 가능)");
|
||||
}
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품의서 생성 대상 품목이 없습니다.\n(소재단가+공급업체 또는 가공단가+가공업체가 입력되고 품의서가 생성되지 않은 품목만 가능)");
|
||||
resultMap.put("materialExcludedParts", materialExcludedParts);
|
||||
resultMap.put("processingExcludedParts", processingExcludedParts);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -409,6 +409,48 @@ public class SalesMngService {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 구매요청서 확정 처리
|
||||
* - STATUS를 'confirmed'로 변경하여 수정 불가능하게 함
|
||||
*/
|
||||
public Map confirmSalesRequest(HttpServletRequest request, Map paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try{
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
String masterObjId = CommonUtils.checkNull(paramMap.get("SALES_REQUEST_MASTER_OBJID"));
|
||||
|
||||
if("".equals(masterObjId)){
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("msg", "구매요청서 정보가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
Map updateParam = new HashMap();
|
||||
updateParam.put("OBJID", masterObjId);
|
||||
updateParam.put("STATUS", "confirmed");
|
||||
|
||||
sqlSession.update("salesMng.changeStatusSalesRequestMaster", updateParam);
|
||||
|
||||
sqlSession.commit();
|
||||
|
||||
resultMap.put("result", true);
|
||||
resultMap.put("msg", "확정되었습니다.");
|
||||
|
||||
}catch(Exception e){
|
||||
if(sqlSession != null) sqlSession.rollback();
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("msg", "확정 처리 중 오류가 발생했습니다.");
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 구매의뢰 내용을 저장한다.
|
||||
* @param request
|
||||
@@ -1907,10 +1949,10 @@ public class SalesMngService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 대상 품목 조회 (공통 메서드)
|
||||
* 품의서 대상 품목 조회 (소재/가공 각각 분리)
|
||||
* @param sqlSession
|
||||
* @param salesRequestMasterObjid
|
||||
* @return Map { targetParts: List<Map>, mbomHeaderObjid: String, purchaseRequestInfo: Map }
|
||||
* @return Map { materialTargetParts, processingTargetParts, materialExcludedParts, processingExcludedParts, mbomHeaderObjid, purchaseRequestInfo }
|
||||
* @throws Exception
|
||||
*/
|
||||
public Map getProposalTargetPartsWithInfo(SqlSession sqlSession, String salesRequestMasterObjid) throws Exception {
|
||||
@@ -1925,28 +1967,56 @@ public class SalesMngService {
|
||||
|
||||
String mbomHeaderObjid = CommonUtils.checkNull(purchaseRequestInfo.get("MBOM_HEADER_OBJID"));
|
||||
|
||||
// 2. 품의서 대상 품목 조회 (M-BOM 기반 여부에 따라 분기)
|
||||
List<Map> targetParts = null;
|
||||
List<Map> excludedParts = null; // 공급업체 미입력으로 제외된 품목
|
||||
// 2. 품의서 대상 품목 조회 (소재/가공 각각)
|
||||
List<Map> materialTargetParts = null; // 소재 품의서 대상
|
||||
List<Map> processingTargetParts = null; // 가공 품의서 대상
|
||||
List<Map> materialExcludedParts = null; // 소재 제외 (공급업체 미입력)
|
||||
List<Map> processingExcludedParts = null; // 가공 제외 (가공업체 미입력)
|
||||
|
||||
if(!mbomHeaderObjid.isEmpty()) {
|
||||
// M-BOM 기반 -> MBOM_DETAIL에서 조회
|
||||
Map mbomParam = new HashMap();
|
||||
mbomParam.put("MBOM_HEADER_OBJID", mbomHeaderObjid);
|
||||
targetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromMBom", mbomParam);
|
||||
excludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromMBom", mbomParam);
|
||||
|
||||
// 소재 품의서 대상
|
||||
materialTargetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromMBom", mbomParam);
|
||||
materialExcludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromMBom", mbomParam);
|
||||
|
||||
// 가공 품의서 대상
|
||||
processingTargetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromMBomProcessing", mbomParam);
|
||||
processingExcludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromMBomProcessing", mbomParam);
|
||||
} else {
|
||||
// 수동 작성 -> SALES_REQUEST_PART에서 조회
|
||||
targetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromManual", paramMap);
|
||||
excludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromManual", paramMap);
|
||||
// 소재 품의서 대상
|
||||
materialTargetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromManual", paramMap);
|
||||
materialExcludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromManual", paramMap);
|
||||
|
||||
// 가공 품의서 대상
|
||||
processingTargetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromManualProcessing", paramMap);
|
||||
processingExcludedParts = sqlSession.selectList("salesMng.getProposalExcludedPartsFromManualProcessing", paramMap);
|
||||
}
|
||||
|
||||
targetParts = CommonUtils.keyChangeUpperList(targetParts);
|
||||
excludedParts = CommonUtils.keyChangeUpperList(excludedParts);
|
||||
materialTargetParts = CommonUtils.keyChangeUpperList(materialTargetParts);
|
||||
processingTargetParts = CommonUtils.keyChangeUpperList(processingTargetParts);
|
||||
materialExcludedParts = CommonUtils.keyChangeUpperList(materialExcludedParts);
|
||||
processingExcludedParts = CommonUtils.keyChangeUpperList(processingExcludedParts);
|
||||
|
||||
// 3. 결과 반환
|
||||
// 3. 기존 호환성을 위해 targetParts, excludedParts도 유지 (소재+가공 합침)
|
||||
List<Map> targetParts = new ArrayList<Map>();
|
||||
targetParts.addAll(materialTargetParts);
|
||||
targetParts.addAll(processingTargetParts);
|
||||
|
||||
List<Map> excludedParts = new ArrayList<Map>();
|
||||
excludedParts.addAll(materialExcludedParts);
|
||||
excludedParts.addAll(processingExcludedParts);
|
||||
|
||||
// 4. 결과 반환
|
||||
result.put("targetParts", targetParts);
|
||||
result.put("excludedParts", excludedParts); // 공급업체 미입력 품목
|
||||
result.put("excludedParts", excludedParts);
|
||||
result.put("materialTargetParts", materialTargetParts);
|
||||
result.put("processingTargetParts", processingTargetParts);
|
||||
result.put("materialExcludedParts", materialExcludedParts);
|
||||
result.put("processingExcludedParts", processingExcludedParts);
|
||||
result.put("mbomHeaderObjid", mbomHeaderObjid);
|
||||
result.put("purchaseRequestInfo", purchaseRequestInfo);
|
||||
|
||||
@@ -1954,7 +2024,7 @@ public class SalesMngService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 생성
|
||||
* 품의서 생성 (소재/가공 각각 별도 품의서 생성)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
@@ -1979,78 +2049,49 @@ public class SalesMngService {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 1. 품의서 대상 품목 조회 (공통 메서드 사용)
|
||||
// 1. 품의서 대상 품목 조회 (소재/가공 분리)
|
||||
Map partsInfo = getProposalTargetPartsWithInfo(sqlSession, salesRequestMasterObjid);
|
||||
List<Map> targetParts = (List<Map>)partsInfo.get("targetParts");
|
||||
List<Map> materialTargetParts = (List<Map>)partsInfo.get("materialTargetParts");
|
||||
List<Map> processingTargetParts = (List<Map>)partsInfo.get("processingTargetParts");
|
||||
String mbomHeaderObjid = (String)partsInfo.get("mbomHeaderObjid");
|
||||
Map purchaseRequestInfo = (Map)partsInfo.get("purchaseRequestInfo");
|
||||
|
||||
if(targetParts == null || targetParts.isEmpty()) {
|
||||
boolean hasMaterialParts = materialTargetParts != null && !materialTargetParts.isEmpty();
|
||||
boolean hasProcessingParts = processingTargetParts != null && !processingTargetParts.isEmpty();
|
||||
|
||||
if(!hasMaterialParts && !hasProcessingParts) {
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품의서 생성 대상 품목이 없습니다. (단가가 입력되고 품의서가 생성되지 않은 품목만 가능)");
|
||||
resultMap.put("message", "품의서 생성 대상 품목이 없습니다.\n(소재단가+공급업체 또는 가공단가+가공업체가 입력되고 품의서가 생성되지 않은 품목만 가능)");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 2. 품의서 번호 생성
|
||||
String proposalNo = (String)sqlSession.selectOne("salesMng.getNextProposalNo");
|
||||
List<String> createdProposalNos = new ArrayList<String>();
|
||||
|
||||
// 3. 품의서 마스터 생성
|
||||
Map proposalMaster = new HashMap();
|
||||
proposalMaster.put("OBJID", CommonUtils.createObjId());
|
||||
proposalMaster.put("REQUEST_MNG_NO", proposalNo);
|
||||
proposalMaster.put("PROJECT_NO", purchaseRequestInfo.get("PROJECT_NO"));
|
||||
proposalMaster.put("MBOM_HEADER_OBJID", purchaseRequestInfo.get("MBOM_HEADER_OBJID"));
|
||||
proposalMaster.put("PURCHASE_TYPE", purchaseRequestInfo.get("PURCHASE_TYPE"));
|
||||
proposalMaster.put("ORDER_TYPE", purchaseRequestInfo.get("ORDER_TYPE"));
|
||||
proposalMaster.put("PRODUCT_NAME", purchaseRequestInfo.get("PRODUCT_NAME"));
|
||||
proposalMaster.put("AREA_CD", purchaseRequestInfo.get("AREA_CD"));
|
||||
proposalMaster.put("CUSTOMER_OBJID", purchaseRequestInfo.get("CUSTOMER_OBJID"));
|
||||
proposalMaster.put("PAID_TYPE", purchaseRequestInfo.get("PAID_TYPE"));
|
||||
proposalMaster.put("REQUEST_USER_ID", userId);
|
||||
proposalMaster.put("WRITER", userId);
|
||||
|
||||
sqlSession.insert("salesMng.insertProposal", proposalMaster);
|
||||
|
||||
// 4. 품의서용 SALES_REQUEST_PART 생성 (대상 품목 복사)
|
||||
String proposalMasterObjid = (String)proposalMaster.get("OBJID");
|
||||
List<String> sourceObjids = new ArrayList<String>();
|
||||
|
||||
for(Map part : targetParts) {
|
||||
String sourceObjid = CommonUtils.checkNull(part.get("OBJID"));
|
||||
sourceObjids.add(sourceObjid);
|
||||
|
||||
Map partParam = new HashMap();
|
||||
partParam.put("NEW_OBJID", CommonUtils.createObjId());
|
||||
partParam.put("PROPOSAL_MASTER_OBJID", proposalMasterObjid);
|
||||
partParam.put("SOURCE_OBJID", sourceObjid);
|
||||
partParam.put("WRITER", userId);
|
||||
|
||||
// M-BOM 기반 여부에 따라 INSERT 쿼리 분기
|
||||
if(!mbomHeaderObjid.isEmpty()) {
|
||||
// M-BOM 기반 -> MBOM_DETAIL에서 복사
|
||||
sqlSession.insert("salesMng.insertProposalPartFromMBom", partParam);
|
||||
} else {
|
||||
// 수동 작성 -> SALES_REQUEST_PART에서 복사
|
||||
sqlSession.insert("salesMng.insertProposalPartFromManual", partParam);
|
||||
}
|
||||
// 2. 소재 품의서 생성
|
||||
if(hasMaterialParts) {
|
||||
String materialProposalNo = createSingleProposal(sqlSession, userId, purchaseRequestInfo,
|
||||
materialTargetParts, mbomHeaderObjid, "MATERIAL");
|
||||
createdProposalNos.add("소재: " + materialProposalNo);
|
||||
}
|
||||
|
||||
// 5. 원본 데이터의 PROPOSAL_DATE 업데이트
|
||||
Map updateParam = new HashMap();
|
||||
updateParam.put("PART_OBJIDS", sourceObjids);
|
||||
// 3. 가공 품의서 생성
|
||||
if(hasProcessingParts) {
|
||||
String processingProposalNo = createSingleProposal(sqlSession, userId, purchaseRequestInfo,
|
||||
processingTargetParts, mbomHeaderObjid, "PROCESSING");
|
||||
createdProposalNos.add("가공: " + processingProposalNo);
|
||||
}
|
||||
|
||||
// M-BOM 기반 여부에 따라 업데이트 쿼리 분기
|
||||
String updateQuery = mbomHeaderObjid.isEmpty()
|
||||
? "salesMng.updateProposalDateForManualParts" // 수동 작성
|
||||
: "salesMng.updateProposalDateForMBomParts"; // M-BOM 기반
|
||||
|
||||
sqlSession.update(updateQuery, updateParam);
|
||||
sqlSession.commit();
|
||||
|
||||
// Java 7 호환: String.join 대신 StringBuilder 사용
|
||||
StringBuilder messageBuilder = new StringBuilder("품의서가 생성되었습니다.");
|
||||
for(String proposalNo : createdProposalNos) {
|
||||
messageBuilder.append("\n").append(proposalNo);
|
||||
}
|
||||
|
||||
resultMap.put("resultFlag", "S");
|
||||
resultMap.put("message", "품의서가 생성되었습니다. (품의서 번호: " + proposalNo + ")");
|
||||
resultMap.put("PROPOSAL_OBJID", proposalMaster.get("OBJID"));
|
||||
resultMap.put("PROPOSAL_NO", proposalNo);
|
||||
resultMap.put("message", messageBuilder.toString());
|
||||
resultMap.put("createdCount", createdProposalNos.size());
|
||||
|
||||
} catch(Exception e) {
|
||||
if(sqlSession != null) sqlSession.rollback();
|
||||
@@ -2063,4 +2104,94 @@ public class SalesMngService {
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 단일 품의서 생성 (소재 또는 가공)
|
||||
* @param sqlSession
|
||||
* @param userId
|
||||
* @param purchaseRequestInfo
|
||||
* @param targetParts
|
||||
* @param mbomHeaderObjid
|
||||
* @param proposalType MATERIAL(소재) 또는 PROCESSING(가공)
|
||||
* @return 생성된 품의서 번호
|
||||
*/
|
||||
private String createSingleProposal(SqlSession sqlSession, String userId, Map purchaseRequestInfo,
|
||||
List<Map> targetParts, String mbomHeaderObjid, String proposalType) throws Exception {
|
||||
|
||||
// 1. 품의서 번호 생성
|
||||
String proposalNo = (String)sqlSession.selectOne("salesMng.getNextProposalNo");
|
||||
|
||||
// 2. 품의서 마스터 생성
|
||||
Map proposalMaster = new HashMap();
|
||||
proposalMaster.put("OBJID", CommonUtils.createObjId());
|
||||
proposalMaster.put("REQUEST_MNG_NO", proposalNo);
|
||||
proposalMaster.put("PROJECT_NO", purchaseRequestInfo.get("PROJECT_NO"));
|
||||
proposalMaster.put("MBOM_HEADER_OBJID", purchaseRequestInfo.get("MBOM_HEADER_OBJID"));
|
||||
proposalMaster.put("PURCHASE_TYPE", purchaseRequestInfo.get("PURCHASE_TYPE"));
|
||||
proposalMaster.put("ORDER_TYPE", purchaseRequestInfo.get("ORDER_TYPE"));
|
||||
proposalMaster.put("PRODUCT_NAME", purchaseRequestInfo.get("PRODUCT_NAME"));
|
||||
proposalMaster.put("AREA_CD", purchaseRequestInfo.get("AREA_CD"));
|
||||
proposalMaster.put("CUSTOMER_OBJID", purchaseRequestInfo.get("CUSTOMER_OBJID"));
|
||||
proposalMaster.put("PAID_TYPE", purchaseRequestInfo.get("PAID_TYPE"));
|
||||
proposalMaster.put("REQUEST_USER_ID", userId);
|
||||
proposalMaster.put("WRITER", userId);
|
||||
proposalMaster.put("PROPOSAL_TYPE", proposalType); // 소재/가공 구분
|
||||
|
||||
sqlSession.insert("salesMng.insertProposal", proposalMaster);
|
||||
|
||||
// 3. 품의서용 SALES_REQUEST_PART 생성 (대상 품목 복사)
|
||||
String proposalMasterObjid = (String)proposalMaster.get("OBJID");
|
||||
List<String> sourceObjids = new ArrayList<String>();
|
||||
|
||||
for(Map part : targetParts) {
|
||||
String sourceObjid = CommonUtils.checkNull(part.get("OBJID"));
|
||||
sourceObjids.add(sourceObjid);
|
||||
|
||||
Map partParam = new HashMap();
|
||||
partParam.put("NEW_OBJID", CommonUtils.createObjId());
|
||||
partParam.put("PROPOSAL_MASTER_OBJID", proposalMasterObjid);
|
||||
partParam.put("SOURCE_OBJID", sourceObjid);
|
||||
partParam.put("WRITER", userId);
|
||||
partParam.put("PROPOSAL_TYPE", proposalType);
|
||||
|
||||
// M-BOM 기반 여부 + 소재/가공 구분에 따라 INSERT 쿼리 분기
|
||||
if(!mbomHeaderObjid.isEmpty()) {
|
||||
// M-BOM 기반
|
||||
if("PROCESSING".equals(proposalType)) {
|
||||
sqlSession.insert("salesMng.insertProposalPartFromMBomProcessing", partParam);
|
||||
} else {
|
||||
sqlSession.insert("salesMng.insertProposalPartFromMBom", partParam);
|
||||
}
|
||||
} else {
|
||||
// 수동 작성
|
||||
if("PROCESSING".equals(proposalType)) {
|
||||
sqlSession.insert("salesMng.insertProposalPartFromManualProcessing", partParam);
|
||||
} else {
|
||||
sqlSession.insert("salesMng.insertProposalPartFromManual", partParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 원본 데이터의 PROPOSAL_DATE 업데이트
|
||||
Map updateParam = new HashMap();
|
||||
updateParam.put("PART_OBJIDS", sourceObjids);
|
||||
|
||||
// M-BOM 기반 여부 + 소재/가공 구분에 따라 업데이트 쿼리 분기
|
||||
String updateQuery;
|
||||
if(mbomHeaderObjid.isEmpty()) {
|
||||
// 수동 작성
|
||||
updateQuery = "PROCESSING".equals(proposalType)
|
||||
? "salesMng.updateProcessingProposalDateForManualParts"
|
||||
: "salesMng.updateProposalDateForManualParts";
|
||||
} else {
|
||||
// M-BOM 기반
|
||||
updateQuery = "PROCESSING".equals(proposalType)
|
||||
? "salesMng.updateProcessingProposalDateForMBomParts"
|
||||
: "salesMng.updateProposalDateForMBomParts";
|
||||
}
|
||||
|
||||
sqlSession.update(updateQuery, updateParam);
|
||||
|
||||
return proposalNo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2961,6 +2961,8 @@ public class PurchaseOrderService {
|
||||
String contents = CommonUtils.checkNull(paramMap.get("contents"));
|
||||
String writerEmail = CommonUtils.checkNull(paramMap.get("WRITER_EMAIL"));
|
||||
String writer = CommonUtils.checkNull(paramMap.get("WRITER"));
|
||||
// 도면 파일 첨부 여부 (기본값: Y)
|
||||
String includeDrawingFiles = CommonUtils.checkNull(paramMap.get("includeDrawingFiles"), "Y");
|
||||
|
||||
// 발주서 정보 조회
|
||||
Map infoParam = new HashMap();
|
||||
@@ -3035,8 +3037,8 @@ public class PurchaseOrderService {
|
||||
attachFileList.add(excelFile);
|
||||
}
|
||||
|
||||
// 2. 도면 파일 압축 첨부
|
||||
if(partFileList != null && partFileList.size() > 0) {
|
||||
// 2. 도면 파일 압축 첨부 (includeDrawingFiles가 Y인 경우에만)
|
||||
if("Y".equals(includeDrawingFiles) && partFileList != null && partFileList.size() > 0) {
|
||||
File zf = MailUtil.zipFileListMail(zipName, partFileList);
|
||||
if(zf != null && zf.exists()) {
|
||||
HashMap hm = new HashMap();
|
||||
@@ -3177,4 +3179,126 @@ public class PurchaseOrderService {
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 발주 취소 전 입고 여부 확인
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return hasReceipt: 입고 여부, totalReceiptQty: 총 입고수량
|
||||
*/
|
||||
public Map checkReceiptForCancel(HttpServletRequest request, Map paramMap) throws Exception {
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
String purchaseOrderMasterObjid = CommonUtils.checkNull(paramMap.get("PURCHASE_ORDER_MASTER_OBJID"));
|
||||
|
||||
if(purchaseOrderMasterObjid.isEmpty()) {
|
||||
resultMap.put("hasReceipt", true);
|
||||
resultMap.put("message", "발주서 정보가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 입고 수량 조회 (ARRIVAL_PLAN 테이블에서 RECEIPT_QTY 합계)
|
||||
Map queryParam = new HashMap();
|
||||
queryParam.put("PURCHASE_ORDER_MASTER_OBJID", purchaseOrderMasterObjid);
|
||||
|
||||
Map receiptInfo = (Map)sqlSession.selectOne("purchaseOrder.getTotalReceiptQtyForCancel", queryParam);
|
||||
|
||||
int totalReceiptQty = 0;
|
||||
if(receiptInfo != null) {
|
||||
// 대소문자 구분 없이 키 찾기
|
||||
Object qtyValue = receiptInfo.get("TOTAL_RECEIPT_QTY");
|
||||
if(qtyValue == null) {
|
||||
qtyValue = receiptInfo.get("total_receipt_qty");
|
||||
}
|
||||
if(qtyValue != null) {
|
||||
totalReceiptQty = Integer.parseInt(qtyValue.toString());
|
||||
}
|
||||
System.out.println("=== 발주취소 입고확인(check) === OBJID: " + purchaseOrderMasterObjid + ", receiptInfo: " + receiptInfo + ", totalReceiptQty: " + totalReceiptQty);
|
||||
}
|
||||
|
||||
resultMap.put("hasReceipt", totalReceiptQty > 0);
|
||||
resultMap.put("totalReceiptQty", totalReceiptQty);
|
||||
|
||||
} finally {
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 발주 취소 실행 (입고가 없는 경우만)
|
||||
* STATUS를 'orderCancel'로 변경
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
public Map executeOrderCancel(HttpServletRequest request, Map paramMap) throws Exception {
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
String purchaseOrderMasterObjid = CommonUtils.checkNull(paramMap.get("PURCHASE_ORDER_MASTER_OBJID"));
|
||||
|
||||
if(purchaseOrderMasterObjid.isEmpty()) {
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("message", "발주서 정보가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 입고 여부 재확인
|
||||
Map queryParam = new HashMap();
|
||||
queryParam.put("PURCHASE_ORDER_MASTER_OBJID", purchaseOrderMasterObjid);
|
||||
|
||||
Map receiptInfo = (Map)sqlSession.selectOne("purchaseOrder.getTotalReceiptQtyForCancel", queryParam);
|
||||
|
||||
int totalReceiptQty = 0;
|
||||
if(receiptInfo != null) {
|
||||
// 대소문자 구분 없이 키 찾기
|
||||
Object qtyValue = receiptInfo.get("TOTAL_RECEIPT_QTY");
|
||||
if(qtyValue == null) {
|
||||
qtyValue = receiptInfo.get("total_receipt_qty");
|
||||
}
|
||||
if(qtyValue != null) {
|
||||
totalReceiptQty = Integer.parseInt(qtyValue.toString());
|
||||
}
|
||||
System.out.println("=== 발주취소 입고확인 === OBJID: " + purchaseOrderMasterObjid + ", receiptInfo: " + receiptInfo + ", totalReceiptQty: " + totalReceiptQty);
|
||||
}
|
||||
|
||||
if(totalReceiptQty > 0) {
|
||||
resultMap.put("result", false);
|
||||
resultMap.put("message", "입고된 항목이 있어 취소할 수 없습니다. (입고수량: " + totalReceiptQty + ")");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 발주 취소 처리 (STATUS = 'orderCancel')
|
||||
Map updateParam = new HashMap();
|
||||
updateParam.put("OBJID", purchaseOrderMasterObjid);
|
||||
updateParam.put("STATUS", "orderCancel");
|
||||
|
||||
sqlSession.update("purchaseOrder.updateOrderCancelStatus", updateParam);
|
||||
|
||||
// 동시발주 하위건도 함께 취소
|
||||
sqlSession.update("purchaseOrder.updateOrderCancelStatusMulti", updateParam);
|
||||
|
||||
sqlSession.commit();
|
||||
|
||||
resultMap.put("result", true);
|
||||
resultMap.put("message", "발주가 취소되었습니다.");
|
||||
|
||||
} catch(Exception e) {
|
||||
if(sqlSession != null) sqlSession.rollback();
|
||||
throw e;
|
||||
} finally {
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user