Merge pull request 'V2025111901' (#81) from V2025111901 into main
Reviewed-on: #81
This commit was merged in pull request #81.
This commit is contained in:
@@ -23,32 +23,9 @@ try {
|
||||
sqlSession.close();
|
||||
}
|
||||
|
||||
// 메뉴 이름 조회
|
||||
// 메뉴 이름 조회 (공통 유틸 사용)
|
||||
String menuObjId = request.getParameter("menuObjId");
|
||||
if(menuObjId != null && !menuObjId.isEmpty()) {
|
||||
org.apache.ibatis.session.SqlSession sqlSession = com.pms.common.SqlMapConfig.getInstance().getSqlSession();
|
||||
java.util.Map<String, Object> menuParam = new java.util.HashMap<String, Object>();
|
||||
menuParam.put("OBJID", menuObjId);
|
||||
|
||||
java.util.Map menuInfo = (java.util.Map)sqlSession.selectOne("admin.selectMenuInfo", menuParam);
|
||||
if(menuInfo != null && menuInfo.get("MENU_NAME_KOR") != null) {
|
||||
// 상위 메뉴 이름 조회
|
||||
String parentObjId = CommonUtils.checkNull(menuInfo.get("PARENT_OBJ_ID"));
|
||||
if(!parentObjId.isEmpty() && !"0".equals(parentObjId)) {
|
||||
menuParam.put("OBJID", parentObjId);
|
||||
java.util.Map parentMenuInfo = (java.util.Map)sqlSession.selectOne("admin.selectMenuInfo", menuParam);
|
||||
if(parentMenuInfo != null && parentMenuInfo.get("MENU_NAME_KOR") != null) {
|
||||
menuName = CommonUtils.checkNull(parentMenuInfo.get("MENU_NAME_KOR")) + "_" + CommonUtils.checkNull(menuInfo.get("MENU_NAME_KOR"));
|
||||
} else {
|
||||
menuName = CommonUtils.checkNull(menuInfo.get("MENU_NAME_KOR"));
|
||||
}
|
||||
} else {
|
||||
menuName = CommonUtils.checkNull(menuInfo.get("MENU_NAME_KOR"));
|
||||
}
|
||||
}
|
||||
|
||||
sqlSession.close();
|
||||
}
|
||||
menuName = CommonUtils.getMenuName(menuObjId, menuName);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -4,12 +4,25 @@
|
||||
<%@ 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>
|
||||
<c:set var="sysYear"><fmt:formatDate value="${now}" pattern="yyyy" /></c:set>
|
||||
<%
|
||||
// DB에서 메뉴명 조회 (공통 유틸 사용)
|
||||
String menuObjId = request.getParameter("menuObjId");
|
||||
String menuName = CommonUtils.getMenuName(menuObjId, "생산관리_M-BOM관리");
|
||||
%>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
body, html {
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript" src="/js/tabulator/tabulator_custom.js"></script>
|
||||
<style>
|
||||
/* 체크박스 컬럼 오른쪽에 얇은 구분선 추가 (데이터 행만) */
|
||||
@@ -611,7 +624,7 @@ function fn_openPurchaseListPopup() {
|
||||
<div class="content-box-s">
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2>
|
||||
<span>생산관리_M-BOM관리</span>
|
||||
<span><%=menuName%></span>
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" class="plm_btns" value="조회" id="btnSearch">
|
||||
|
||||
@@ -553,6 +553,26 @@ function fn_initGrid() {
|
||||
return cell.getValue() || '-';
|
||||
}
|
||||
},
|
||||
// 숨김 컬럼: 공급업체 코드 (저장 시 필요)
|
||||
{
|
||||
field: 'VENDOR',
|
||||
visible: false
|
||||
},
|
||||
// 숨김 컬럼: 품의서 작성일 (저장 시 기존 값 유지)
|
||||
{
|
||||
field: 'PROPOSAL_DATE',
|
||||
visible: false
|
||||
},
|
||||
// 숨김 컬럼: 순수량 (저장 시 기존 값 유지)
|
||||
{
|
||||
field: 'NET_QTY',
|
||||
visible: false
|
||||
},
|
||||
// 숨김 컬럼: 발주수량 (저장 시 기존 값 유지)
|
||||
{
|
||||
field: 'PO_QTY',
|
||||
visible: false
|
||||
},
|
||||
{
|
||||
headerHozAlign: 'center',
|
||||
hozAlign: 'right',
|
||||
@@ -870,7 +890,7 @@ function getMbomTreeData() {
|
||||
partNo: row.PART_NO,
|
||||
partName: row.PART_NAME,
|
||||
|
||||
// 수량 정보 (숫자로 변환)
|
||||
// 수량 정보 (원본 값 유지 - null/undefined만 변환)
|
||||
qty: toNumber(row.QTY_TEMP || row.QTY || row.ITEM_QTY),
|
||||
unit: row.UNIT,
|
||||
|
||||
@@ -884,19 +904,22 @@ function getMbomTreeData() {
|
||||
processingVendor: row.PROCESSING_VENDOR,
|
||||
processingDeadline: row.PROCESSING_DEADLINE,
|
||||
grindingDeadline: row.GRINDING_DEADLINE,
|
||||
requiredQty: toNumber(row.REQUIRED_QTY),
|
||||
orderQty: toNumber(row.ORDER_QTY),
|
||||
productionQty: toNumber(row.PRODUCTION_QTY),
|
||||
stockQty: toNumber(row.STOCK_QTY),
|
||||
shortageQty: toNumber(row.SHORTAGE_QTY),
|
||||
requiredQty: row.REQUIRED_QTY, // 원본 값 그대로
|
||||
orderQty: row.ORDER_QTY, // 원본 값 그대로
|
||||
productionQty: row.PRODUCTION_QTY, // 원본 값 그대로
|
||||
stockQty: row.STOCK_QTY, // 원본 값 그대로
|
||||
shortageQty: row.SHORTAGE_QTY, // 원본 값 그대로
|
||||
|
||||
// 구매 정보
|
||||
vendor: row.VENDOR_NAME,
|
||||
unitPrice: toNumber(row.UNIT_PRICE),
|
||||
totalPrice: toNumber(row.TOTAL_PRICE),
|
||||
vendor: row.VENDOR || row.VENDOR_PM, // 공급업체 코드/OBJID (기존 값 유지)
|
||||
unitPrice: row.UNIT_PRICE, // 원본 값 그대로
|
||||
totalPrice: row.TOTAL_PRICE, // 원본 값 그대로
|
||||
currency: row.CURRENCY,
|
||||
leadTime: toNumber(row.LEAD_TIME),
|
||||
minOrderQty: toNumber(row.MIN_ORDER_QTY),
|
||||
leadTime: row.LEAD_TIME, // 원본 값 그대로
|
||||
minOrderQty: row.MIN_ORDER_QTY, // 원본 값 그대로
|
||||
netQty: row.NET_QTY, // 순수량 추가
|
||||
poQty: row.PO_QTY, // 발주수량 추가
|
||||
proposalDate: row.PROPOSAL_DATE, // 품의서 작성일 (기존 값 유지)
|
||||
|
||||
// 기타
|
||||
status: row.STATUS,
|
||||
|
||||
@@ -6,12 +6,23 @@
|
||||
<%@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>
|
||||
body, html {
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.pmsPopupForm tr:last-child td {
|
||||
border-bottom: none;
|
||||
}
|
||||
@@ -50,6 +61,15 @@
|
||||
var _tabulGrid;
|
||||
|
||||
$(document).ready(function(){
|
||||
// DOM 렌더링 완료 후 그리드 높이 계산
|
||||
setTimeout(function() {
|
||||
fnc_calculateContentHeight("gridDiv", 10);
|
||||
}, 100);
|
||||
|
||||
$(window).resize(function() {
|
||||
fnc_calculateContentHeight("gridDiv", 10);
|
||||
});
|
||||
|
||||
$('.select2').select2();
|
||||
|
||||
$("input[type=text]").keyup(function(e){
|
||||
@@ -125,14 +145,11 @@ $(document).ready(function(){
|
||||
var columns = [
|
||||
{title:'OBJID', field:'OBJID', visible: false},
|
||||
{title:'STATUS', field:'STATUS', visible: false},
|
||||
{headerHozAlign:'center', hozAlign:'left', title:"품의서 No", field:"PROPOSAL_NO", widthGrow:1.2, frozen:true,
|
||||
cellClick: function(e, cell){
|
||||
var objId = cell.getData().OBJID;
|
||||
fn_openProposalFormPopUp(objId);
|
||||
},
|
||||
formatter: function(cell){
|
||||
return '<a href="#" style="color:#0066cc; text-decoration:underline;">' + fnc_checkNull(cell.getValue()) + '</a>';
|
||||
}
|
||||
{headerHozAlign:'center', hozAlign:'center', title:"품의서 No", field:"PROPOSAL_NO", widthGrow:1.2, frozen:true,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick : function(e, cell) {
|
||||
fn_openProposalFormPopUp(cell.getData().OBJID);
|
||||
}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'left', title:"프로젝트번호", field:"PROJECT_NUMBER", widthGrow:1.3},
|
||||
{headerHozAlign:'center', hozAlign:'center', title:"구매유형", field:"PURCHASE_TYPE_NAME", widthGrow:1.0},
|
||||
@@ -175,15 +192,15 @@ function fn_openProposalFormPopUp(objId){
|
||||
<div class="content-box-s">
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2>
|
||||
<span>구매관리_품의서관리</span>
|
||||
<span><%=menuName%></span>
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
<input type="button" value="결재상신" class="plm_btns" id="btnApproval" style="background:#17a2b8; color:white;">
|
||||
<input type="button" value="발주서생성" class="plm_btns" id="btnCreatePO" style="background:#28a745; color:white;">
|
||||
<%-- <input type="button" value="초기화" class="plm_btns" id="btnReset">
|
||||
<input type="button" value="엑셀 다운로드" class="plm_btns" id="btnExcel"> --%>
|
||||
</div>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
<input type="button" value="결재상신" class="plm_btns" id="btnApproval" style="background:#17a2b8; color:white;">
|
||||
<input type="button" value="발주서생성" class="plm_btns" id="btnCreatePO" style="background:#28a745; color:white;">
|
||||
<%-- <input type="button" value="초기화" class="plm_btns" id="btnReset">
|
||||
<input type="button" value="엑셀 다운로드" class="plm_btns" id="btnExcel"> --%>
|
||||
</div>
|
||||
</div>
|
||||
<div id="plmSearchZon">
|
||||
<table>
|
||||
|
||||
@@ -722,15 +722,10 @@ function fn_save() {
|
||||
}
|
||||
|
||||
// 품의서작성일 자동 설정 (현재 날짜)
|
||||
var today = new Date();
|
||||
var proposalDate = today.getFullYear() + '-' +
|
||||
String(today.getMonth() + 1).padStart(2, '0') + '-' +
|
||||
String(today.getDate()).padStart(2, '0');
|
||||
|
||||
gridData.forEach(function(item) {
|
||||
if(!item.PROPOSAL_DATE) {
|
||||
item.PROPOSAL_DATE = proposalDate;
|
||||
}
|
||||
// PROPOSAL_DATE는 품의서 생성 시에만 자동 설정되므로 여기서는 제거
|
||||
// (기존에 저장된 값이 있으면 유지, 없으면 NULL로 유지)
|
||||
|
||||
// 사용여부 변환: 사용/미사용 → Y/N
|
||||
if(item.USE_YN === '사용') {
|
||||
item.USE_YN = 'Y';
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
<%@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>
|
||||
@@ -103,57 +108,10 @@ $(document).ready(function(){
|
||||
fn_openSalesRequestFormPopUp("");
|
||||
});
|
||||
|
||||
//품의서 생성 (TODO: 품의서 생성 기능 구현 필요 - 기존 발주서 작성 기능과 다름)
|
||||
/*
|
||||
// 품의서 생성
|
||||
$("#btnReg").click(function(){
|
||||
var selectedRowIds = _tabulGrid.getSelectedData();
|
||||
console.log(selectedRowIds);
|
||||
if(selectedRowIds.length==0){
|
||||
Swal.fire("품의서 생성할 행을 선택해주십시오.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var targetStatus = fnc_checkNull(selectedRowIds[0].STATUS_TITLE);
|
||||
if(targetStatus != "접수"){
|
||||
Swal.fire("접수 상태일 경우 품의서 생성이 가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//var sales_request_objId = fnc_checkNull(selectedRowIds[0].OBJID);
|
||||
//fn_formPopUp("",sales_request_objId);
|
||||
Swal.fire({
|
||||
title: '품의서를 생성 하시겠습니까?',
|
||||
text: '',
|
||||
icon: 'warning',
|
||||
|
||||
showCancelButton: true, // cancel버튼 보이기. 기본은 원래 없음
|
||||
confirmButtonColor: '#3085d6', // confrim 버튼 색깔 지정
|
||||
cancelButtonColor: '#d33', // cancel 버튼 색깔 지정
|
||||
confirmButtonText: '확인', // confirm 버튼 텍스트 지정
|
||||
cancelButtonText: '취소', // cancel 버튼 텍스트 지정
|
||||
reverseButtons: false, // 버튼 순서 거꾸로
|
||||
|
||||
}).then(result => {
|
||||
// 만약 Promise리턴을 받으면,
|
||||
if (result.isConfirmed) { // 만약 모달창에서 confirm 버튼을 눌렀다면
|
||||
$.ajax({
|
||||
url:"/purchaseOrder/purchaseOrder_salesRequest_Save.do"
|
||||
,type:"POST"
|
||||
,data: $("#form1").serialize() + "&jqGrid="+ encodeURIComponent(JSON.stringify(selectedRowIds))
|
||||
,dataType:"json"
|
||||
,success:function(data){
|
||||
if(data =="SUCCESS"){
|
||||
alert("저장되었습니다.");
|
||||
};
|
||||
fn_search();
|
||||
}
|
||||
,error: function(jqxhr, status, error){
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
fn_createProposal();
|
||||
});
|
||||
*/
|
||||
|
||||
$("#btnOrderBOMReg").click(function(){
|
||||
fn_salesRequestTargetBOMListPopUp();
|
||||
@@ -222,18 +180,24 @@ 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 :"REQUEST_MNG_NO" , widthGrow:1.1,
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
// 구매요청서 작성 여부: PART_NO가 있으면 품목이 저장된 것 (구매요청서 작성됨)
|
||||
var data = cell.getData();
|
||||
var partNo = fnc_checkNull(data.PART_NO);
|
||||
var iconClass = (partNo != '' && partNo != null) ? 'file_icon' : 'file_empty_icon';
|
||||
return '<a href="#" class="File ' + iconClass + '" style="width:20px; height:20px; display:inline-block;"></a>';
|
||||
},
|
||||
cellClick : function(e, cell) {
|
||||
fn_openSalesRequestFormPopUp(cell.getData().OBJID);
|
||||
}
|
||||
}
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "구매요청서", field :"REQUEST_MNG_NO" , widthGrow:1.1,
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
// 구매요청서 작성 여부: PART_NO가 있으면 품목이 저장된 것 (구매요청서 작성됨)
|
||||
var data = cell.getData();
|
||||
var partNo = fnc_checkNull(data.PART_NO);
|
||||
var iconClass = (partNo != '' && partNo != null) ? '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 partNo = fnc_checkNull(data.PART_NO);
|
||||
|
||||
// 구매요청서가 작성된 경우(파란색 아이콘)만 팝업 열기
|
||||
if(partNo != '' && partNo != null) {
|
||||
fn_openSalesRequestFormPopUp(data.OBJID);
|
||||
}
|
||||
}
|
||||
}
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "요청인", field :"REQUEST_USER_NAME" , widthGrow:1.1 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "입고요청일", field :"DELIVERY_REQUEST_DATE" , widthGrow:1.1 }
|
||||
,{headerHozAlign : 'center', hozAlign : 'center', title : "작성일", field :"REGDATE_TITLE" , widthGrow:1.1 }
|
||||
@@ -478,6 +442,139 @@ function fn_formPopUp(objId,sales_request_objid){
|
||||
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;
|
||||
|
||||
// 3. 대상 품목 확인
|
||||
if(!targetParts || targetParts.length == 0) {
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
text: '품의서를 생성할 품목이 없습니다.\n(단가가 입력되고 품의서가 생성되지 않은 품목만 대상)',
|
||||
icon: 'info'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 품의서 생성 확인
|
||||
var partCount = targetParts.length;
|
||||
var partList = targetParts.map(function(part) {
|
||||
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
|
||||
}).join('\n');
|
||||
|
||||
Swal.fire({
|
||||
title: '품의서 생성',
|
||||
html: '<div style="text-align:left;">' +
|
||||
'<p>총 <strong>' + partCount + '건</strong>의 품목으로 품의서를 생성합니다.</p>' +
|
||||
'<div style="max-height:200px; overflow-y:auto; border:1px solid #ddd; padding:10px; margin-top:10px; font-size:12px;">' +
|
||||
partList +
|
||||
'</div>' +
|
||||
'</div>',
|
||||
icon: 'question',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '생성',
|
||||
cancelButtonText: '취소'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
fn_executeCreateProposal(salesRequestObjid, targetParts);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: '오류',
|
||||
text: response.message || '품목 조회 중 오류가 발생했습니다.',
|
||||
icon: 'error'
|
||||
});
|
||||
}
|
||||
},
|
||||
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">
|
||||
@@ -491,7 +588,7 @@ function fn_formPopUp(objId,sales_request_objid){
|
||||
<div class="content-box-s">
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2>
|
||||
<span>구매관리_구매리스트관리</span>
|
||||
<span><%=menuName%></span>
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch">
|
||||
|
||||
@@ -1917,6 +1917,76 @@ public class CommonUtils {
|
||||
|
||||
return concatenatedValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* menuObjId로 메뉴명을 조회한다 (상위메뉴_하위메뉴 형식)
|
||||
*
|
||||
* @param menuObjId 메뉴 OBJID
|
||||
* @param defaultMenuName 기본 메뉴명 (조회 실패 시 반환)
|
||||
* @return 메뉴명 (상위메뉴_하위메뉴 형식)
|
||||
*/
|
||||
public static String getMenuName(String menuObjId, String defaultMenuName) {
|
||||
String menuName = defaultMenuName;
|
||||
org.apache.ibatis.session.SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
if(menuObjId == null || menuObjId.isEmpty()) {
|
||||
logger.debug("menuObjId가 null 또는 빈 문자열입니다. 기본값 반환: " + defaultMenuName);
|
||||
return menuName;
|
||||
}
|
||||
|
||||
sqlSession = com.pms.common.SqlMapConfig.getInstance().getSqlSession();
|
||||
Map<String, Object> menuParam = new HashMap<String, Object>();
|
||||
menuParam.put("OBJID", menuObjId);
|
||||
|
||||
// MyBatis resultType="map"은 컬럼명을 소문자로 반환하므로 대문자로 변환 필요
|
||||
Map menuInfo = (Map)sqlSession.selectOne("admin.selectMenuInfo", menuParam);
|
||||
if(menuInfo != null) {
|
||||
// Map의 key를 대문자로 변환
|
||||
menuInfo = toUpperCaseMapKey(menuInfo);
|
||||
logger.debug("메뉴 정보 조회 성공: " + menuInfo);
|
||||
|
||||
if(menuInfo.get("MENU_NAME_KOR") != null) {
|
||||
// 상위 메뉴 이름 조회
|
||||
String parentObjId = checkNull(menuInfo.get("PARENT_OBJ_ID"));
|
||||
if(!parentObjId.isEmpty() && !"0".equals(parentObjId)) {
|
||||
menuParam.put("OBJID", parentObjId);
|
||||
Map parentMenuInfo = (Map)sqlSession.selectOne("admin.selectMenuInfo", menuParam);
|
||||
if(parentMenuInfo != null) {
|
||||
// 상위 메뉴도 대문자로 변환
|
||||
parentMenuInfo = toUpperCaseMapKey(parentMenuInfo);
|
||||
if(parentMenuInfo.get("MENU_NAME_KOR") != null) {
|
||||
menuName = checkNull(parentMenuInfo.get("MENU_NAME_KOR")) + "_" + checkNull(menuInfo.get("MENU_NAME_KOR"));
|
||||
} else {
|
||||
menuName = checkNull(menuInfo.get("MENU_NAME_KOR"));
|
||||
}
|
||||
} else {
|
||||
menuName = checkNull(menuInfo.get("MENU_NAME_KOR"));
|
||||
}
|
||||
} else {
|
||||
menuName = checkNull(menuInfo.get("MENU_NAME_KOR"));
|
||||
}
|
||||
logger.debug("최종 메뉴명: " + menuName);
|
||||
} else {
|
||||
logger.warn("MENU_NAME_KOR이 null입니다. menuObjId: " + menuObjId);
|
||||
}
|
||||
} else {
|
||||
logger.warn("메뉴 정보를 찾을 수 없습니다. menuObjId: " + menuObjId);
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.error("메뉴명 조회 중 오류 발생 (menuObjId: " + menuObjId + "): " + e.getMessage(), e);
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
try {
|
||||
sqlSession.close();
|
||||
} catch(Exception e) {
|
||||
logger.error("SqlSession 종료 중 오류 발생: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return menuName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3766,7 +3766,11 @@
|
||||
RAW_MATERIAL_PART_NO, RAW_MATERIAL_SPEC, RAW_MATERIAL, RAW_MATERIAL_SIZE,
|
||||
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,
|
||||
<if test="proposalDate != null">
|
||||
PROPOSAL_DATE,
|
||||
</if>
|
||||
STATUS, WRITER, REGDATE, REMARK
|
||||
) VALUES (
|
||||
#{objid}, #{mbomHeaderObjid}, #{parentObjid}, #{childObjid}, #{seq}, #{level},
|
||||
@@ -3775,7 +3779,11 @@
|
||||
#{rawMaterialPartNo}, #{rawMaterialSpec}, #{rawMaterial}, #{rawMaterialSize},
|
||||
#{processingVendor}, #{processingDeadline}, #{grindingDeadline},
|
||||
#{requiredQty}, #{orderQty}, #{productionQty}, #{stockQty}, #{shortageQty},
|
||||
#{netQty}, #{poQty},
|
||||
#{vendor}, #{unitPrice}, #{totalPrice}, #{currency}, #{leadTime}, #{minOrderQty},
|
||||
<if test="proposalDate != null">
|
||||
#{proposalDate},
|
||||
</if>
|
||||
'ACTIVE', #{sessionUserId}, NOW(), #{remark}
|
||||
)
|
||||
</insert>
|
||||
@@ -3870,12 +3878,15 @@
|
||||
PRODUCTION_QTY,
|
||||
STOCK_QTY,
|
||||
SHORTAGE_QTY,
|
||||
NET_QTY,
|
||||
PO_QTY,
|
||||
VENDOR,
|
||||
UNIT_PRICE,
|
||||
TOTAL_PRICE,
|
||||
CURRENCY,
|
||||
LEAD_TIME,
|
||||
MIN_ORDER_QTY,
|
||||
PROPOSAL_DATE,
|
||||
STATUS,
|
||||
REMARK
|
||||
FROM
|
||||
|
||||
@@ -607,12 +607,13 @@
|
||||
PRODUCT_NAME,
|
||||
AREA_CD,
|
||||
CUSTOMER_OBJID,
|
||||
PAID_TYPE
|
||||
PAID_TYPE,
|
||||
DOC_TYPE
|
||||
)
|
||||
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),
|
||||
(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),
|
||||
#{REQUEST_CD },
|
||||
#{PROJECT_NO },
|
||||
#{RELEASE },
|
||||
@@ -631,7 +632,8 @@ VALUES
|
||||
#{PRODUCT_NAME },
|
||||
#{AREA_CD },
|
||||
#{CUSTOMER_OBJID },
|
||||
#{PAID_TYPE }
|
||||
#{PAID_TYPE },
|
||||
'PURCHASE_REQUEST'
|
||||
) ON CONFLICT (OBJID) DO
|
||||
UPDATE
|
||||
SET
|
||||
@@ -1150,6 +1152,8 @@ VALUES
|
||||
) SRP ON SRP.SALES_REQUEST_MASTER_OBJID::VARCHAR = SRM.OBJID::VARCHAR
|
||||
AND SRP.SUB_RNUM = 1 -->
|
||||
WHERE 1=1
|
||||
-- 구매요청서만 조회 (품의서 제외)
|
||||
AND (SRM.DOC_TYPE = 'PURCHASE_REQUEST' OR SRM.DOC_TYPE IS NULL)
|
||||
<if test="Year !=null and Year != '' ">
|
||||
AND TO_CHAR(REGDATE,'YYYY') = #{Year}
|
||||
</if>
|
||||
@@ -3292,7 +3296,7 @@ ORDER BY V.PATH2
|
||||
VENDOR = #{VENDOR_PM},
|
||||
UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
PROPOSAL_DATE = CASE WHEN NULLIF(TRIM(#{PROPOSAL_DATE}::TEXT), '') IS NOT NULL THEN #{PROPOSAL_DATE}::DATE ELSE NULL END,
|
||||
-- PROPOSAL_DATE는 품의서 생성 시에만 자동 설정 (여기서는 업데이트하지 않음)
|
||||
EDITER = #{EDITER},
|
||||
EDIT_DATE = NOW()
|
||||
WHERE OBJID::VARCHAR = #{OBJID}
|
||||
@@ -3307,7 +3311,7 @@ ORDER BY V.PATH2
|
||||
VENDOR_PM = #{VENDOR_PM},
|
||||
UNIT_PRICE = COALESCE(NULLIF(TRIM(#{UNIT_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
TOTAL_PRICE = COALESCE(NULLIF(TRIM(#{TOTAL_PRICE}::TEXT), '')::NUMERIC, 0),
|
||||
PROPOSAL_DATE = CASE WHEN NULLIF(TRIM(#{PROPOSAL_DATE}::TEXT), '') IS NOT NULL THEN #{PROPOSAL_DATE}::DATE ELSE NULL END,
|
||||
-- PROPOSAL_DATE는 품의서 생성 시에만 자동 설정 (여기서는 업데이트하지 않음)
|
||||
WRITER = #{EDITER}
|
||||
WHERE OBJID::VARCHAR = #{OBJID}
|
||||
</update>
|
||||
@@ -3327,10 +3331,18 @@ ORDER BY V.PATH2
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 다음 요청번호 생성 (R + YYYYMMDD + - + 3자리 순번) -->
|
||||
<!-- 다음 요청번호 생성 (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')
|
||||
FROM SALES_REQUEST_MASTER
|
||||
WHERE DOC_TYPE = 'PURCHASE_REQUEST' OR DOC_TYPE IS NULL
|
||||
</select>
|
||||
|
||||
<!-- 다음 품의서 번호 생성 (P + YYYYMMDD + - + 3자리 순번) - 품의서용 -->
|
||||
<select id="getNextProposalNo" resultType="string">
|
||||
SELECT 'P'||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 = 'PROPOSAL'
|
||||
</select>
|
||||
|
||||
<!-- M-BOM에서 구매리스트 생성 - SALES_REQUEST_MASTER만 생성 (SALES_REQUEST_PART는 생성 안 함) -->
|
||||
@@ -3343,7 +3355,8 @@ ORDER BY V.PATH2
|
||||
REQUEST_USER_ID,
|
||||
STATUS,
|
||||
WRITER,
|
||||
REGDATE
|
||||
REGDATE,
|
||||
DOC_TYPE
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
#{REQUEST_MNG_NO},
|
||||
@@ -3352,13 +3365,197 @@ ORDER BY V.PATH2
|
||||
#{REQUEST_USER_ID},
|
||||
#{STATUS},
|
||||
#{WRITER},
|
||||
NOW()
|
||||
NOW(),
|
||||
'PURCHASE_REQUEST'
|
||||
)
|
||||
</insert>
|
||||
|
||||
|
||||
<!-- ==================== 품의서 관리 ==================== -->
|
||||
|
||||
<!-- 품의서 대상 품목 조회 - M-BOM 기반 (MBOM_DETAIL에서 조회) -->
|
||||
<select id="getProposalTargetPartsFromMBom" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
MD.OBJID,
|
||||
MD.PART_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
MD.QTY,
|
||||
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,
|
||||
MD.NET_QTY,
|
||||
MD.PO_QTY,
|
||||
'MBOM' AS DATA_SOURCE
|
||||
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.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,
|
||||
SRP.PART_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
SRP.QTY,
|
||||
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,
|
||||
SRP.NET_QTY,
|
||||
SRP.PO_QTY,
|
||||
'MANUAL' AS DATA_SOURCE
|
||||
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.PROPOSAL_DATE IS NULL
|
||||
ORDER BY SRP.REGDATE
|
||||
</select>
|
||||
|
||||
<!-- 품의서 생성 (SALES_REQUEST_MASTER에 INSERT) -->
|
||||
<insert id="insertProposal" parameterType="map">
|
||||
INSERT INTO SALES_REQUEST_MASTER (
|
||||
OBJID,
|
||||
REQUEST_MNG_NO,
|
||||
PROJECT_NO,
|
||||
MBOM_HEADER_OBJID,
|
||||
PURCHASE_TYPE,
|
||||
ORDER_TYPE,
|
||||
PRODUCT_NAME,
|
||||
AREA_CD,
|
||||
CUSTOMER_OBJID,
|
||||
PAID_TYPE,
|
||||
REQUEST_USER_ID,
|
||||
STATUS,
|
||||
WRITER,
|
||||
REGDATE,
|
||||
DOC_TYPE
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
#{REQUEST_MNG_NO},
|
||||
#{PROJECT_NO},
|
||||
#{MBOM_HEADER_OBJID},
|
||||
#{PURCHASE_TYPE},
|
||||
#{ORDER_TYPE},
|
||||
#{PRODUCT_NAME},
|
||||
#{AREA_CD},
|
||||
#{CUSTOMER_OBJID},
|
||||
#{PAID_TYPE},
|
||||
#{REQUEST_USER_ID},
|
||||
'create',
|
||||
#{WRITER},
|
||||
NOW(),
|
||||
'PROPOSAL'
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 품의서용 SALES_REQUEST_PART 생성 (M-BOM 기반 품목 복사) -->
|
||||
<insert id="insertProposalPartFromMBom" 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,
|
||||
QTY,
|
||||
UNIT_PRICE,
|
||||
TOTAL_PRICE,
|
||||
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,
|
||||
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,
|
||||
QTY,
|
||||
UNIT_PRICE,
|
||||
TOTAL_PRICE,
|
||||
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()
|
||||
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()
|
||||
WHERE OBJID IN
|
||||
<foreach collection="PART_OBJIDS" item="objid" open="(" separator="," close=")">
|
||||
#{objid}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<!-- 품의서 목록 조회 -->
|
||||
<select id="getProposalMngGridList" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
@@ -3374,14 +3571,14 @@ ORDER BY V.PATH2
|
||||
(SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = SRM.ORDER_TYPE) AS ORDER_TYPE_NAME,
|
||||
SRM.PRODUCT_NAME,
|
||||
(SELECT CODE_NAME FROM COMM_CODE CC WHERE CC.CODE_ID = SRM.PRODUCT_NAME) AS PRODUCT_NAME_TITLE,
|
||||
-- 품번/품명 ("외 N건" 형태로 표시)
|
||||
-- 품번/품명 ("외 N건" 형태로 표시) - 품의서는 항상 SALES_REQUEST_PART에 데이터가 있음
|
||||
(
|
||||
SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) > 1 THEN
|
||||
(SELECT PM.PART_NO FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)) || ' 외 ' || (COUNT(*) - 1) || '건'
|
||||
COALESCE((SELECT PM.PART_NO FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)), '') || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
ELSE
|
||||
(SELECT PM.PART_NO FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1))
|
||||
COALESCE((SELECT PM.PART_NO FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)), '')
|
||||
END
|
||||
FROM SALES_REQUEST_PART
|
||||
WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID
|
||||
@@ -3390,9 +3587,9 @@ ORDER BY V.PATH2
|
||||
SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) > 1 THEN
|
||||
(SELECT PM.PART_NAME FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)) || ' 외 ' || (COUNT(*) - 1) || '건'
|
||||
COALESCE((SELECT PM.PART_NAME FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)), '') || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
ELSE
|
||||
(SELECT PM.PART_NAME FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1))
|
||||
COALESCE((SELECT PM.PART_NAME FROM PART_MNG PM WHERE PM.OBJID::VARCHAR = (SELECT PART_OBJID FROM SALES_REQUEST_PART WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)), '')
|
||||
END
|
||||
FROM SALES_REQUEST_PART
|
||||
WHERE SALES_REQUEST_MASTER_OBJID = SRM.OBJID
|
||||
@@ -3402,19 +3599,19 @@ ORDER BY V.PATH2
|
||||
SELECT
|
||||
CASE
|
||||
WHEN COUNT(DISTINCT POM.PARTNER_OBJID) > 1 THEN
|
||||
(SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE OBJID = (SELECT PARTNER_OBJID FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)::NUMERIC) || ' 외 ' || (COUNT(DISTINCT POM.PARTNER_OBJID) - 1) || '건'
|
||||
COALESCE((SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE OBJID = (SELECT PARTNER_OBJID FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)::NUMERIC), '') || ' 외 ' || (COUNT(DISTINCT POM.PARTNER_OBJID) - 1)::TEXT || '건'
|
||||
ELSE
|
||||
(SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE OBJID = (SELECT PARTNER_OBJID FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)::NUMERIC)
|
||||
COALESCE((SELECT SUPPLY_NAME FROM ADMIN_SUPPLY_MNG WHERE OBJID = (SELECT PARTNER_OBJID FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID ORDER BY REGDATE LIMIT 1)::NUMERIC), '')
|
||||
END
|
||||
FROM PURCHASE_ORDER_MASTER POM
|
||||
WHERE POM.SALES_REQUEST_OBJID = SRM.OBJID
|
||||
) AS SUPPLIER_NAME,
|
||||
-- 총액
|
||||
(SELECT SUM(COALESCE(TOTAL_PRICE, 0)) FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID) AS TOTAL_AMOUNT,
|
||||
(SELECT SUM(COALESCE(TOTAL_PRICE::numeric, 0)) FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID) AS TOTAL_AMOUNT,
|
||||
-- 메일발송 여부
|
||||
(SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID AND MAIL_SENT = 'Y') AS MAIL_SENT,
|
||||
-- 발주일
|
||||
(SELECT TO_CHAR(MAX(ORDER_DATE), 'YYYY-MM-DD') FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID) AS ORDER_DATE,
|
||||
-- (SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID AND MAIL_SENT = 'Y') AS MAIL_SENT,
|
||||
-- 발주일 (일단 주석처리)
|
||||
-- (SELECT TO_CHAR(MAX(ORDER_DATE), 'YYYY-MM-DD') FROM PURCHASE_ORDER_MASTER WHERE SALES_REQUEST_OBJID = SRM.OBJID) AS ORDER_DATE,
|
||||
SRM.STATUS,
|
||||
CASE
|
||||
WHEN A.APPR_STATUS IS NOT NULL THEN A.APPR_STATUS
|
||||
@@ -3468,7 +3665,7 @@ ORDER BY V.PATH2
|
||||
) A ON SRM.OBJID::VARCHAR = A.TARGET_OBJID::VARCHAR
|
||||
WHERE 1=1
|
||||
AND SRM.STATUS IN ('create', 'approvalRequest', 'approvalComplete', 'reject')
|
||||
|
||||
AND SRM.DOC_TYPE = 'PROPOSAL'
|
||||
<if test="SEARCH_PROPOSAL_NO != null and !''.equals(SEARCH_PROPOSAL_NO)">
|
||||
AND SRM.REQUEST_MNG_NO LIKE '%${SEARCH_PROPOSAL_NO}%'
|
||||
</if>
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -24,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.pms.common.JsonUtil;
|
||||
import com.pms.common.SqlMapConfig;
|
||||
import com.pms.common.bean.PersonBean;
|
||||
import com.pms.common.utils.CommonUtils;
|
||||
import com.pms.common.utils.Constants;
|
||||
@@ -1300,4 +1302,90 @@ public class SalesMngController {
|
||||
request.setAttribute("code_map", code_map);
|
||||
return "/salesMng/proposalFormPopUp";
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 생성 (JSP에서 호출)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/salesMng/createProposal.do")
|
||||
public Map createProposal(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
resultMap = salesMngService.createProposal(request, paramMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품의서 생성 중 오류가 발생했습니다: " + e.getMessage());
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 대상 품목 조회 (JSP에서 호출)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/salesMng/getProposalTargetParts.do")
|
||||
public Map getProposalTargetParts(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
String salesRequestMasterObjid = CommonUtils.checkNull(paramMap.get("SALES_REQUEST_MASTER_OBJID"));
|
||||
|
||||
// Service의 공통 메서드 사용
|
||||
Map partsInfo = salesMngService.getProposalTargetPartsWithInfo(sqlSession, salesRequestMasterObjid);
|
||||
List<Map> targetParts = (List<Map>)partsInfo.get("targetParts");
|
||||
|
||||
if(targetParts != null && !targetParts.isEmpty()) {
|
||||
resultMap.put("resultFlag", "S");
|
||||
resultMap.put("data", targetParts);
|
||||
} else {
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품의서 생성 대상 품목이 없습니다.\n(단가가 입력되고 품의서가 생성되지 않은 품목만 가능)");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품목 조회 중 오류가 발생했습니다: " + e.getMessage());
|
||||
} finally {
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 대상 품목 미리보기 (JSP에서 호출 - 별칭)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/salesMng/getProposalTargetPartsForPreview.do")
|
||||
public Map getProposalTargetPartsForPreview(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
return getProposalTargetParts(request, paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 생성 실행 (JSP에서 호출)
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/salesMng/createProposalFromPurchaseList.do")
|
||||
public Map createProposalFromPurchaseList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
return createProposal(request, paramMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1905,4 +1905,157 @@ public class SalesMngService {
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 대상 품목 조회 (공통 메서드)
|
||||
* @param sqlSession
|
||||
* @param salesRequestMasterObjid
|
||||
* @return Map { targetParts: List<Map>, mbomHeaderObjid: String, purchaseRequestInfo: Map }
|
||||
* @throws Exception
|
||||
*/
|
||||
public Map getProposalTargetPartsWithInfo(SqlSession sqlSession, String salesRequestMasterObjid) throws Exception {
|
||||
Map result = new HashMap();
|
||||
|
||||
// 1. 구매요청서 정보 조회
|
||||
Map paramMap = new HashMap();
|
||||
paramMap.put("SALES_REQUEST_MASTER_OBJID", salesRequestMasterObjid);
|
||||
|
||||
Map purchaseRequestInfo = (Map)sqlSession.selectOne("salesMng.getSalesRequestMasterInfo", paramMap);
|
||||
purchaseRequestInfo = CommonUtils.toUpperCaseMapKey(purchaseRequestInfo);
|
||||
|
||||
String mbomHeaderObjid = CommonUtils.checkNull(purchaseRequestInfo.get("MBOM_HEADER_OBJID"));
|
||||
|
||||
// 2. 품의서 대상 품목 조회 (M-BOM 기반 여부에 따라 분기)
|
||||
List<Map> targetParts = null;
|
||||
|
||||
if(!mbomHeaderObjid.isEmpty()) {
|
||||
// M-BOM 기반 -> MBOM_DETAIL에서 조회
|
||||
Map mbomParam = new HashMap();
|
||||
mbomParam.put("MBOM_HEADER_OBJID", mbomHeaderObjid);
|
||||
targetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromMBom", mbomParam);
|
||||
} else {
|
||||
// 수동 작성 -> SALES_REQUEST_PART에서 조회
|
||||
targetParts = sqlSession.selectList("salesMng.getProposalTargetPartsFromManual", paramMap);
|
||||
}
|
||||
|
||||
targetParts = CommonUtils.keyChangeUpperList(targetParts);
|
||||
|
||||
// 3. 결과 반환
|
||||
result.put("targetParts", targetParts);
|
||||
result.put("mbomHeaderObjid", mbomHeaderObjid);
|
||||
result.put("purchaseRequestInfo", purchaseRequestInfo);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 품의서 생성
|
||||
* @param request
|
||||
* @param paramMap
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public Map createProposal(HttpServletRequest request, Map<String, Object> paramMap) throws Exception {
|
||||
Map resultMap = new HashMap();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false);
|
||||
|
||||
HttpSession session = request.getSession();
|
||||
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = CommonUtils.checkNull(person.getUserId());
|
||||
|
||||
String salesRequestMasterObjid = CommonUtils.checkNull(paramMap.get("SALES_REQUEST_MASTER_OBJID"));
|
||||
|
||||
if(salesRequestMasterObjid.isEmpty()) {
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "구매요청서 정보가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 1. 품의서 대상 품목 조회 (공통 메서드 사용)
|
||||
Map partsInfo = getProposalTargetPartsWithInfo(sqlSession, salesRequestMasterObjid);
|
||||
List<Map> targetParts = (List<Map>)partsInfo.get("targetParts");
|
||||
String mbomHeaderObjid = (String)partsInfo.get("mbomHeaderObjid");
|
||||
Map purchaseRequestInfo = (Map)partsInfo.get("purchaseRequestInfo");
|
||||
|
||||
if(targetParts == null || targetParts.isEmpty()) {
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품의서 생성 대상 품목이 없습니다. (단가가 입력되고 품의서가 생성되지 않은 품목만 가능)");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
// 2. 품의서 번호 생성
|
||||
String proposalNo = (String)sqlSession.selectOne("salesMng.getNextProposalNo");
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 원본 데이터의 PROPOSAL_DATE 업데이트
|
||||
Map updateParam = new HashMap();
|
||||
updateParam.put("PART_OBJIDS", sourceObjids);
|
||||
|
||||
// M-BOM 기반 여부에 따라 업데이트 쿼리 분기
|
||||
String updateQuery = mbomHeaderObjid.isEmpty()
|
||||
? "salesMng.updateProposalDateForManualParts" // 수동 작성
|
||||
: "salesMng.updateProposalDateForMBomParts"; // M-BOM 기반
|
||||
|
||||
sqlSession.update(updateQuery, updateParam);
|
||||
sqlSession.commit();
|
||||
|
||||
resultMap.put("resultFlag", "S");
|
||||
resultMap.put("message", "품의서가 생성되었습니다. (품의서 번호: " + proposalNo + ")");
|
||||
resultMap.put("PROPOSAL_OBJID", proposalMaster.get("OBJID"));
|
||||
resultMap.put("PROPOSAL_NO", proposalNo);
|
||||
|
||||
} catch(Exception e) {
|
||||
if(sqlSession != null) sqlSession.rollback();
|
||||
e.printStackTrace();
|
||||
resultMap.put("resultFlag", "F");
|
||||
resultMap.put("message", "품의서 생성 중 오류가 발생했습니다: " + e.getMessage());
|
||||
} finally {
|
||||
if(sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1361,52 +1361,109 @@ public class ProductionPlanningService {
|
||||
}
|
||||
}
|
||||
|
||||
// M-BOM 업데이트
|
||||
paramMap.put("mbomHeaderObjid", existingMbom.get("OBJID"));
|
||||
sqlSession.update("productionplanning.updateMbomHeader", paramMap);
|
||||
sqlSession.delete("productionplanning.deleteMbomDetail", paramMap);
|
||||
|
||||
// 새 상세 데이터 삽입
|
||||
if(mbomData != null && !mbomData.isEmpty()) {
|
||||
for(Map<String, Object> item : mbomData) {
|
||||
item.put("mbomHeaderObjid", existingMbom.get("OBJID"));
|
||||
item.put("sessionUserId", userId);
|
||||
|
||||
// SEQ가 없으면 기존 SEQ 유지 (JSP에서 전송된 seq 사용)
|
||||
// 없는 경우에만 새로 부여
|
||||
if(item.get("seq") == null || "".equals(item.get("seq"))) {
|
||||
item.put("seq", 999); // 임시값 (나중에 정렬 필요)
|
||||
}
|
||||
|
||||
// 기존 항목인 경우 objid와 childObjid 유지
|
||||
// 새 항목인 경우에만 생성
|
||||
String objid = CommonUtils.checkNull(item.get("objid"));
|
||||
String childObjid = CommonUtils.checkNull(item.get("childObjid"));
|
||||
|
||||
if("".equals(objid)) {
|
||||
objid = CommonUtils.createObjId();
|
||||
item.put("objid", objid);
|
||||
}
|
||||
|
||||
if("".equals(childObjid)) {
|
||||
childObjid = objid; // 새 항목은 objid와 동일
|
||||
item.put("childObjid", childObjid);
|
||||
}
|
||||
|
||||
// LEVEL이 없으면 기본값 1 설정
|
||||
if(item.get("level") == null || "".equals(item.get("level"))) {
|
||||
item.put("level", 1);
|
||||
}
|
||||
|
||||
System.out.println("UPDATE M-BOM DETAIL: seq=" + item.get("seq") +
|
||||
", level=" + item.get("level") +
|
||||
", partNo=" + item.get("partNo") +
|
||||
", parentObjid=" + item.get("parentObjid") +
|
||||
", childObjid=" + childObjid);
|
||||
|
||||
sqlSession.insert("productionplanning.insertMbomDetail", item);
|
||||
// M-BOM 업데이트
|
||||
paramMap.put("mbomHeaderObjid", existingMbom.get("OBJID"));
|
||||
sqlSession.update("productionplanning.updateMbomHeader", paramMap);
|
||||
|
||||
// 삭제 전에 기존 데이터 백업 (PROPOSAL_DATE, VENDOR, NET_QTY, PO_QTY 등 보존)
|
||||
Map<String, Object> queryParam = new HashMap<>();
|
||||
queryParam.put("mbomHeaderObjid", existingMbom.get("OBJID")); // camelCase로 수정
|
||||
List<Map> oldMbomDetails = sqlSession.selectList("productionplanning.getMbomDetailList", queryParam);
|
||||
|
||||
// OBJID를 키로 하는 맵 생성 (빠른 조회)
|
||||
Map<String, Map> existingDataMap = new HashMap<>();
|
||||
if(oldMbomDetails != null) {
|
||||
for(Map detail : oldMbomDetails) {
|
||||
detail = CommonUtils.toUpperCaseMapKey(detail);
|
||||
String objid = CommonUtils.checkNull(detail.get("OBJID"));
|
||||
if(!objid.isEmpty()) {
|
||||
existingDataMap.put(objid, detail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlSession.delete("productionplanning.deleteMbomDetail", paramMap);
|
||||
|
||||
|
||||
// 새 상세 데이터 삽입
|
||||
if(mbomData != null && !mbomData.isEmpty()) {
|
||||
for(Map<String, Object> item : mbomData) {
|
||||
item.put("mbomHeaderObjid", existingMbom.get("OBJID"));
|
||||
item.put("sessionUserId", userId);
|
||||
|
||||
// SEQ가 없으면 기존 SEQ 유지 (JSP에서 전송된 seq 사용)
|
||||
// 없는 경우에만 새로 부여
|
||||
if(item.get("seq") == null || "".equals(item.get("seq"))) {
|
||||
item.put("seq", 999); // 임시값 (나중에 정렬 필요)
|
||||
}
|
||||
|
||||
// 기존 항목인 경우 objid와 childObjid 유지
|
||||
// 새 항목인 경우에만 생성
|
||||
String objid = CommonUtils.checkNull(item.get("objid"));
|
||||
String childObjid = CommonUtils.checkNull(item.get("childObjid"));
|
||||
|
||||
if("".equals(objid)) {
|
||||
objid = CommonUtils.createObjId();
|
||||
item.put("objid", objid);
|
||||
}
|
||||
|
||||
if("".equals(childObjid)) {
|
||||
childObjid = objid; // 새 항목은 objid와 동일
|
||||
item.put("childObjid", childObjid);
|
||||
}
|
||||
|
||||
// 기존 데이터에서 보존해야 할 값들 복원
|
||||
Map existingData = existingDataMap.get(objid);
|
||||
if(existingData != null) {
|
||||
// PROPOSAL_DATE가 JSP에서 안 넘어왔으면 기존 값 사용
|
||||
if(item.get("proposalDate") == null || "".equals(item.get("proposalDate"))) {
|
||||
Object proposalDate = existingData.get("PROPOSAL_DATE");
|
||||
if(proposalDate != null) {
|
||||
item.put("proposalDate", proposalDate);
|
||||
System.out.println("PROPOSAL_DATE 복원: " + objid + " -> " + proposalDate);
|
||||
}
|
||||
}
|
||||
|
||||
// VENDOR가 JSP에서 안 넘어왔으면 기존 값 사용
|
||||
if(item.get("vendor") == null || "".equals(item.get("vendor"))) {
|
||||
Object vendor = existingData.get("VENDOR");
|
||||
if(vendor != null) {
|
||||
item.put("vendor", vendor);
|
||||
System.out.println("VENDOR 복원: " + objid + " -> " + vendor);
|
||||
}
|
||||
}
|
||||
|
||||
// NET_QTY가 JSP에서 안 넘어왔으면 기존 값 사용
|
||||
if(item.get("netQty") == null || "".equals(item.get("netQty"))) {
|
||||
Object netQty = existingData.get("NET_QTY");
|
||||
if(netQty != null) {
|
||||
item.put("netQty", netQty);
|
||||
}
|
||||
}
|
||||
|
||||
// PO_QTY가 JSP에서 안 넘어왔으면 기존 값 사용
|
||||
if(item.get("poQty") == null || "".equals(item.get("poQty"))) {
|
||||
Object poQty = existingData.get("PO_QTY");
|
||||
if(poQty != null) {
|
||||
item.put("poQty", poQty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LEVEL이 없으면 기본값 1 설정
|
||||
if(item.get("level") == null || "".equals(item.get("level"))) {
|
||||
item.put("level", 1);
|
||||
}
|
||||
|
||||
System.out.println("UPDATE M-BOM DETAIL: seq=" + item.get("seq") +
|
||||
", level=" + item.get("level") +
|
||||
", partNo=" + item.get("partNo") +
|
||||
", parentObjid=" + item.get("parentObjid") +
|
||||
", childObjid=" + childObjid);
|
||||
|
||||
sqlSession.insert("productionplanning.insertMbomDetail", item);
|
||||
}
|
||||
}
|
||||
|
||||
// 변경 사항이 있을 때만 이력 저장
|
||||
if(!changedItems.isEmpty()) {
|
||||
|
||||
Reference in New Issue
Block a user