Merge pull request 'V2025111901' (#76) from V2025111901 into main
Reviewed-on: #76
This commit was merged in pull request #76.
This commit is contained in:
@@ -717,11 +717,11 @@ function fn_excel() {
|
||||
<tr>
|
||||
<td class="input_title"><label for="COPY_PART_NO">품번</label></td>
|
||||
<td>
|
||||
<input type="text" id="COPY_PART_NO" name="COPY_PART_NO" style="width: 100%;">
|
||||
<input type="text" id="COPY_PART_NO" name="COPY_PART_NO" style="width: 100%;" readonly>
|
||||
</td>
|
||||
<td class="input_title"><label for="COPY_PART_NAME">품명</label></td>
|
||||
<td>
|
||||
<input type="text" id="COPY_PART_NAME" name="COPY_PART_NAME" style="width: 100%;">
|
||||
<input type="text" id="COPY_PART_NAME" name="COPY_PART_NAME" style="width: 100%;" readonly>
|
||||
</td>
|
||||
<td></td>
|
||||
<td style="text-align: center;">
|
||||
|
||||
@@ -58,6 +58,7 @@ $(function(){
|
||||
|
||||
// 저장된 M-BOM 품번 조회 및 표시
|
||||
var projectObjId = "${info.OBJID}";
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/getLatestMbomByProjectId.do",
|
||||
type: "POST",
|
||||
@@ -68,7 +69,29 @@ $(function(){
|
||||
if(response && response.MBOM_NO) {
|
||||
console.log("저장된 M-BOM 발견:", response);
|
||||
$("#search_mbom_part_no").val(response.MBOM_NO);
|
||||
$("#search_save_date").val(response.REGDATE);
|
||||
|
||||
// 날짜 형식 변환 (타임스탬프 또는 문자열 -> YYYY-MM-DD)
|
||||
var regDate = response.REGDATE;
|
||||
if(regDate) {
|
||||
var dateStr = "";
|
||||
|
||||
// 타임스탬프(숫자)인 경우
|
||||
if(typeof regDate === 'number') {
|
||||
var date = new Date(regDate);
|
||||
var year = date.getFullYear();
|
||||
var month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
var day = String(date.getDate()).padStart(2, '0');
|
||||
dateStr = year + '-' + month + '-' + day;
|
||||
}
|
||||
// 문자열인 경우 (YYYY-MM-DD HH:mm:ss 형식)
|
||||
else if(typeof regDate === 'string') {
|
||||
dateStr = regDate.split(' ')[0];
|
||||
}
|
||||
|
||||
$("#search_save_date").val(dateStr);
|
||||
} else {
|
||||
$("#search_save_date").val("");
|
||||
}
|
||||
} else {
|
||||
console.log("저장된 M-BOM 없음");
|
||||
$("#search_mbom_part_no").val("");
|
||||
@@ -84,13 +107,23 @@ $(function(){
|
||||
var sourceBomType = "${info.SOURCE_BOM_TYPE}";
|
||||
var sourceEbomObjId = "${info.SOURCE_EBOM_OBJID}";
|
||||
var sourceMbomObjId = "${info.SOURCE_MBOM_OBJID}";
|
||||
var productCode = "${info.PRODUCT_CODE}";
|
||||
|
||||
console.log("할당된 BOM 정보:", {
|
||||
sourceBomType: sourceBomType,
|
||||
sourceEbomObjId: sourceEbomObjId,
|
||||
sourceMbomObjId: sourceMbomObjId
|
||||
sourceMbomObjId: sourceMbomObjId,
|
||||
productCode: productCode
|
||||
});
|
||||
|
||||
// Machine 이외 제품: M-BOM 템플릿 자동 로드
|
||||
<c:if test="${not empty mbomTemplateDetails}">
|
||||
console.log("M-BOM 템플릿 발견 - 자동 로드 시작");
|
||||
setTimeout(function() {
|
||||
fn_loadMbomTemplate();
|
||||
}, 500);
|
||||
</c:if>
|
||||
|
||||
// Controller에서 이미 데이터를 로드하여 JSP에 전달하므로 자동 조회 불필요
|
||||
// setTimeout(function() {
|
||||
// fn_searchMbom();
|
||||
@@ -126,7 +159,7 @@ $(function(){
|
||||
|
||||
// 닫기 버튼 클릭
|
||||
$("#btnClose").click(function(){
|
||||
window.close();
|
||||
fn_closeWindow();
|
||||
});
|
||||
|
||||
// 일괄 적용 버튼 클릭
|
||||
@@ -174,6 +207,59 @@ function fn_applyBulkDeadline() {
|
||||
}
|
||||
}
|
||||
|
||||
// M-BOM 템플릿 로드 (Machine 이외 제품)
|
||||
function fn_loadMbomTemplate() {
|
||||
console.log("fn_loadMbomTemplate 호출됨");
|
||||
|
||||
// 템플릿 데이터를 JSP에서 받아옴
|
||||
var templateDetails = [];
|
||||
<c:if test="${not empty mbomTemplateDetails}">
|
||||
<c:forEach items="${mbomTemplateDetails}" var="item">
|
||||
templateDetails.push({
|
||||
OBJID: '', // 새로 생성될 ID
|
||||
CHILD_OBJID: '${item.CHILD_OBJID}', // 템플릿의 CHILD_OBJID 유지 (트리 구조용)
|
||||
PARENT_OBJID: '${item.PARENT_OBJID}',
|
||||
SEQ: ${item.SEQ},
|
||||
LEVEL: ${item.LEVEL},
|
||||
PART_OBJID: '${item.PART_OBJID}',
|
||||
PART_NO: '${item.PART_NO}',
|
||||
PART_NAME: '${item.PART_NAME}',
|
||||
QTY: ${item.QTY},
|
||||
ITEM_QTY: ${item.QTY}, // 항목수량
|
||||
QTY_TEMP: ${item.QTY},
|
||||
UNIT: '${item.UNIT}',
|
||||
SUPPLY_TYPE: '${item.SUPPLY_TYPE}',
|
||||
MAKE_OR_BUY: '${item.MAKE_OR_BUY}',
|
||||
RAW_MATERIAL: '${item.RAW_MATERIAL}',
|
||||
RAW_MATERIAL_SPEC: '${item.RAW_MATERIAL_SPEC}',
|
||||
SIZE: '${item.RAW_MATERIAL_SIZE}',
|
||||
RAW_MATERIAL_NO: '${item.RAW_MATERIAL_PART_NO}',
|
||||
PROCESSING_VENDOR: '${item.PROCESSING_VENDOR}',
|
||||
PROCESSING_DEADLINE: '${item.PROCESSING_DEADLINE}',
|
||||
GRINDING_DEADLINE: '${item.GRINDING_DEADLINE}',
|
||||
REQUIRED_QTY: ${item.REQUIRED_QTY != null ? item.REQUIRED_QTY : 0},
|
||||
// ORDER_QTY, PRODUCTION_QTY는 명시적으로 설정하지 않음 (undefined)
|
||||
// 이렇게 하면 formatter에서 자동 계산됨
|
||||
REMARK: '${item.REMARK}',
|
||||
STATUS: 'ACTIVE'
|
||||
});
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
|
||||
console.log("템플릿 데이터 개수:", templateDetails.length);
|
||||
|
||||
// 왼쪽 프레임에 데이터 로드
|
||||
var bottomFrame = parent.frames[1];
|
||||
var leftFrame = bottomFrame ? bottomFrame.frames['leftFrame'] : null;
|
||||
|
||||
if(leftFrame && leftFrame._tabulGrid) {
|
||||
leftFrame._tabulGrid.setData(templateDetails);
|
||||
console.log("템플릿 데이터 로드 완료");
|
||||
} else {
|
||||
console.error("왼쪽 프레임 또는 그리드를 찾을 수 없습니다.");
|
||||
}
|
||||
}
|
||||
|
||||
// M-BOM 조회
|
||||
function fn_searchMbom() {
|
||||
var partNo = $("#search_part_no").val().trim();
|
||||
@@ -306,7 +392,7 @@ function fn_saveMbom() {
|
||||
}
|
||||
|
||||
// 현재 창 닫기
|
||||
window.close();
|
||||
fn_closeWindow();
|
||||
} else {
|
||||
alert("M-BOM 저장에 실패했습니다: " + (data.message || ""));
|
||||
}
|
||||
@@ -792,30 +878,30 @@ function compareItemFields(before, after) {
|
||||
<tr>
|
||||
<td><label for="search_part_no">품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_part_no" id="search_part_no" value="">
|
||||
<input type="text" name="search_part_no" id="search_part_no" style="width: 300px;" value="" readonly>
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="search_part_name">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_part_name" id="search_part_name" value="">
|
||||
<input type="text" name="search_part_name" id="search_part_name" style="width: 300px;" value="" readonly>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="search_mbom_part_no">M-BOM 품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_mbom_part_no" id="search_mbom_part_no" value="">
|
||||
<input type="text" name="search_mbom_part_no" id="search_mbom_part_no" style="width: 300px;" value="" readonly>
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="search_save_date">저장일</label></td>
|
||||
<td>
|
||||
<input type="date" name="search_save_date" id="search_save_date" value="">
|
||||
<input type="text" name="search_save_date" id="search_save_date" style="width: 300px;" value="" readonly>
|
||||
</td>
|
||||
<td style="width: 40px;"></td>
|
||||
<td >
|
||||
<input type="button" value="이력보기" class="plm_btns" id="btnHistory">
|
||||
<input type="button" value="저장" class="plm_btns" id="btnSave">
|
||||
<input type="button" value="닫기" class="plm_btns" id="btnClose">
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type="button" value="이력보기" class="plm_btns" id="btnHistory">
|
||||
<input type="button" value="저장" class="plm_btns" id="btnSave">
|
||||
<input type="button" value="닫기" class="plm_btns" id="btnClose">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="bulk_processing_deadline">가공납기 일괄</label></td>
|
||||
@@ -827,7 +913,7 @@ function compareItemFields(before, after) {
|
||||
<td>
|
||||
<input type="date" name="bulk_grinding_deadline" id="bulk_grinding_deadline" value="">
|
||||
</td>
|
||||
|
||||
<td style="width: 40px;"></td>
|
||||
<td>
|
||||
<input type="button" value="일괄 적용" class="plm_btns" id="btnApplyBulkDeadline">
|
||||
</td>
|
||||
@@ -1087,6 +1173,27 @@ function fn_mbomChangePart() {
|
||||
function generateTempId() {
|
||||
return -Math.floor(Math.random() * 1000000000);
|
||||
}
|
||||
|
||||
// 창 닫기 함수 (프레임 구조 고려)
|
||||
function fn_closeWindow() {
|
||||
try {
|
||||
// 최상위 창(frameset)을 닫기
|
||||
if(window.top && window.top.opener) {
|
||||
// 팝업으로 열린 경우
|
||||
window.top.close();
|
||||
} else if(window.parent && window.parent !== window) {
|
||||
// 프레임 내부인 경우 최상위 창 닫기 시도
|
||||
window.top.close();
|
||||
} else {
|
||||
// 일반 창인 경우
|
||||
window.close();
|
||||
}
|
||||
} catch(e) {
|
||||
console.error("창 닫기 오류:", e);
|
||||
// 오류 발생 시 강제로 닫기 시도
|
||||
window.top.close();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -389,13 +389,26 @@ function fn_checkAssignmentAndOpenMbom(projectObjId) {
|
||||
success: function(response) {
|
||||
console.log("BOM 할당 정보:", response);
|
||||
|
||||
// Machine(0000928) 이외 제품인지 확인
|
||||
var productCode = response ? response.PRODUCT_CODE : null;
|
||||
var partNo = response ? response.PART_NO : null;
|
||||
|
||||
if(!response || !response.SOURCE_BOM_TYPE) {
|
||||
// 할당 정보가 없는 경우
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
text: 'BOM 할당 정보가 없습니다.\nBOM 복사 버튼을 통해 먼저 BOM을 할당해주세요.',
|
||||
icon: 'info'
|
||||
});
|
||||
|
||||
// Machine 이외 제품이고 품번이 있으면 템플릿 확인
|
||||
if(productCode && productCode !== '0000928' && partNo) {
|
||||
console.log("Machine 이외 제품 - 템플릿 확인 후 팝업 열기");
|
||||
// 템플릿이 있을 수 있으므로 팝업 열기
|
||||
fn_openMBomFormPopup(projectObjId);
|
||||
} else {
|
||||
// Machine 제품이거나 품번이 없으면 할당 필요
|
||||
Swal.fire({
|
||||
title: '알림',
|
||||
text: 'BOM 할당 정보가 없습니다.\nBOM 복사 버튼을 통해 먼저 BOM을 할당해주세요.',
|
||||
icon: 'info'
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -373,12 +373,12 @@ function fn_changeRelatePartInfo(objId,rightObjId,leftObjId,leftPartNoQty,leftPa
|
||||
<form name="form1" id="form1" action="" method="post">
|
||||
<input type="hidden" name="objId" id="objId" value="${param.objId}" />
|
||||
|
||||
<div id="structurePopupBtnW" style="padding-top:20px;">
|
||||
<div id="structurePopupBtnW" style="padding-top:300px;">
|
||||
<input type="button" value="변경" class="plm_btns" id="moveChange">
|
||||
<br>
|
||||
<input type="button" value="<<" class="plm_btns" id="moveLeft" style="margin-left:0px;">
|
||||
<input type="button" value="<<" class="plm_btns" id="moveLeft" style="margin-left:4px;">
|
||||
<br>
|
||||
<input type="button" value=">>" class="plm_btns" id="moveRight" style="margin-left:0px;">
|
||||
<input type="button" value=">>" class="plm_btns" id="moveRight" style="margin-left:4px;">
|
||||
</div>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
@@ -397,6 +397,10 @@ function fn_initGrid() {
|
||||
var data = cell.getRow().getData();
|
||||
var itemQty = parseFloat(data.ITEM_QTY) || 0;
|
||||
var orderQty = itemQty * projectQuantity;
|
||||
|
||||
// 실제 데이터에도 저장 (getMbomTreeData에서 사용)
|
||||
cell.getRow().update({ORDER_QTY: orderQty}, false);
|
||||
|
||||
return orderQty.toLocaleString();
|
||||
}
|
||||
},
|
||||
@@ -421,12 +425,16 @@ function fn_initGrid() {
|
||||
step: 1
|
||||
},
|
||||
formatter: function(cell) {
|
||||
// 초기값은 소재발주수량 (항목수량 × 프로젝트 수주수량)
|
||||
// 초기값은 소재발주수량과 동일
|
||||
var value = cell.getValue();
|
||||
if(!value) {
|
||||
|
||||
if(value === undefined || value === null || value === '' || value === 0) {
|
||||
var data = cell.getRow().getData();
|
||||
var itemQty = parseFloat(data.ITEM_QTY) || 0;
|
||||
value = itemQty * projectQuantity;
|
||||
// ORDER_QTY 값을 그대로 사용
|
||||
value = data.ORDER_QTY || 0;
|
||||
|
||||
// 실제 데이터에도 저장 (getMbomTreeData에서 사용)
|
||||
cell.getRow().update({PRODUCTION_QTY: value}, false);
|
||||
}
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
@@ -613,7 +621,7 @@ function fn_initGrid() {
|
||||
// Tabulator 생성
|
||||
_tabulGrid = new Tabulator("#mBomTableWrap", {
|
||||
layout: "fitData",
|
||||
height: "calc(100vh - 150px)",
|
||||
height: "calc(100vh - 70px)",
|
||||
columns: columns,
|
||||
data: bomTreeData,
|
||||
rowFormatter: function(row) {
|
||||
@@ -704,7 +712,15 @@ function fn_searchMbom(searchParams) {
|
||||
console.log("M-BOM 조회 결과:", data);
|
||||
if(data && data.list) {
|
||||
console.log("데이터 개수:", data.list.length);
|
||||
_tabulGrid.setData(data.list);
|
||||
|
||||
// ORDER_QTY, PRODUCTION_QTY 제거하여 formatter에서 재계산되도록
|
||||
var processedData = data.list.map(function(item) {
|
||||
delete item.ORDER_QTY;
|
||||
delete item.PRODUCTION_QTY;
|
||||
return item;
|
||||
});
|
||||
|
||||
_tabulGrid.setData(processedData);
|
||||
} else {
|
||||
console.log("데이터 없음");
|
||||
_tabulGrid.setData([]);
|
||||
|
||||
@@ -10,26 +10,27 @@
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
/* padding: 10px; */
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#plmSearchZon {
|
||||
/* #plmSearchZon {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
} */
|
||||
#plmSearchZon table {
|
||||
width: 100%;
|
||||
table-layout: auto !important;
|
||||
}
|
||||
#plmSearchZon td {
|
||||
/* #plmSearchZon td {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
} */
|
||||
#plmSearchZon td.label,
|
||||
#plmSearchZon td:first-child {
|
||||
text-align: right;
|
||||
padding-right: 5px;
|
||||
}
|
||||
#ebomTable {
|
||||
height: 540px;
|
||||
height: 600px !important;
|
||||
}
|
||||
</style>
|
||||
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
|
||||
@@ -43,23 +44,23 @@ body, html {
|
||||
<tr>
|
||||
<td><label for="search_part_no">품번</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_part_no" id="search_part_no" value="">
|
||||
<input type="text" name="search_part_no" id="search_part_no" style="width: 100%;" value="">
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="search_part_name">품명</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_part_name" id="search_part_name" value="">
|
||||
<input type="text" name="search_part_name" id="search_part_name" style="width: 98%;"value="">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="search_material">재료</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_material" id="search_material" value="">
|
||||
<input type="text" name="search_material" id="search_material" style="width: 100%;" value="">
|
||||
</td>
|
||||
|
||||
<td class="label"><label for="search_supplier">공급업체</label></td>
|
||||
<td class="label"><label for="search_supplier">메이커</label></td>
|
||||
<td>
|
||||
<input type="text" name="search_supplier" id="search_supplier" value="">
|
||||
<input type="text" name="search_supplier" id="search_supplier" style="width: 98%;" value="">
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@@ -84,7 +85,7 @@ body, html {
|
||||
<option value="200">200</option>
|
||||
<option value="1000">1000</option>
|
||||
</select>
|
||||
<div class="table_Status" style="font-size: 12px;">
|
||||
<div class="table_Status" style="font-size: 12px; margin-right: 10px;">
|
||||
<b id="bTableStatus">0</b> 건
|
||||
</div>
|
||||
</div>
|
||||
@@ -126,7 +127,7 @@ function initEbomTable() {
|
||||
{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: "SUPPLIER", widthGrow: 1.5, vertAlign:"middle"}
|
||||
{title: "메이커", field: "MAKER", widthGrow: 1.5, vertAlign:"middle"}
|
||||
],
|
||||
placeholder: "검색 결과가 없습니다."
|
||||
});
|
||||
@@ -198,15 +199,32 @@ function updatePagination() {
|
||||
|
||||
$("#bTableStatus").text(allData.length);
|
||||
|
||||
// 페이지 버튼 생성
|
||||
// 페이지 버튼 생성 (10개씩만 표시)
|
||||
var pagingHtml = '';
|
||||
for(var i = 1; i <= totalPages; i++) {
|
||||
var pageGroupSize = 10; // 한 번에 표시할 페이지 수
|
||||
var currentGroup = Math.ceil(currentPage / pageGroupSize);
|
||||
var startPage = (currentGroup - 1) * pageGroupSize + 1;
|
||||
var endPage = Math.min(startPage + pageGroupSize - 1, totalPages);
|
||||
|
||||
// 이전 그룹 버튼
|
||||
if(startPage > 1) {
|
||||
pagingHtml += '<input type="button" name="mailPaging" class="paging" onclick="javascript:fnc_goPage(' + (startPage - 1) + ');" value="<">';
|
||||
}
|
||||
|
||||
// 페이지 번호 버튼
|
||||
for(var i = startPage; i <= endPage; i++) {
|
||||
if(i === currentPage) {
|
||||
pagingHtml += '<input type="button" name="mailPaging" class="paging selected" value="' + i + '">';
|
||||
} else {
|
||||
pagingHtml += '<input type="button" name="mailPaging" class="paging" onclick="javascript:fnc_goPage(' + i + ');" value="' + i + '">';
|
||||
}
|
||||
}
|
||||
|
||||
// 다음 그룹 버튼
|
||||
if(endPage < totalPages) {
|
||||
pagingHtml += '<input type="button" name="mailPaging" class="paging" onclick="javascript:fnc_goPage(' + (endPage + 1) + ');" value=">">';
|
||||
}
|
||||
|
||||
$("#pagingButtons").html(pagingHtml);
|
||||
}
|
||||
|
||||
|
||||
@@ -941,7 +941,7 @@ public class PartMngController {
|
||||
}
|
||||
|
||||
Map code_map = new HashMap();
|
||||
code_map.put("rev", commonService.bizMakeOptionList("", "", "common.getRevNoselect"));
|
||||
//code_map.put("rev", commonService.bizMakeOptionList("", "", "common.getRevNoselect"));
|
||||
code_map.put("product_code", commonService.bizMakeOptionList("", "", "common.getProductNoselect"));
|
||||
|
||||
// E-BOM 목록 (기존 getActiveBomList 사용)
|
||||
|
||||
@@ -967,6 +967,38 @@ public class ProductionPlanningController extends BaseService {
|
||||
|
||||
if(projectInfo != null && !projectInfo.isEmpty()) {
|
||||
request.setAttribute("info", projectInfo);
|
||||
|
||||
// Machine 이외 제품: 품번 기준 M-BOM 템플릿 조회
|
||||
String productCode = CommonUtils.checkNull(projectInfo.get("PRODUCT_CODE"));
|
||||
String partNo = CommonUtils.checkNull(projectInfo.get("PART_NO"));
|
||||
|
||||
System.out.println("제품구분 코드: " + productCode);
|
||||
System.out.println("품번: " + partNo);
|
||||
|
||||
// Machine(0000928) 이외 제품이고 품번이 있는 경우
|
||||
if(!"0000928".equals(productCode) && !"".equals(partNo)) {
|
||||
Map<String, Object> templateParam = new HashMap<>();
|
||||
templateParam.put("partNo", partNo);
|
||||
|
||||
// 품번 기준 최신 M-BOM 템플릿 조회
|
||||
Map<String, Object> template = commonService.selectOne("productionplanning.getLatestMbomTemplateByPartNo", request, templateParam);
|
||||
|
||||
if(template != null && !template.isEmpty()) {
|
||||
System.out.println("M-BOM 템플릿 발견: " + template.get("TEMPLATE_MBOM_NO"));
|
||||
|
||||
// 템플릿 상세 항목 조회
|
||||
Map<String, Object> detailParam = new HashMap<>();
|
||||
detailParam.put("mbomHeaderObjid", template.get("TEMPLATE_HEADER_OBJID"));
|
||||
List<Map<String, Object>> templateDetails = commonService.selectList("productionplanning.getMbomTemplateDetails", request, detailParam);
|
||||
|
||||
System.out.println("템플릿 상세 항목 수: " + (templateDetails != null ? templateDetails.size() : 0));
|
||||
|
||||
request.setAttribute("mbomTemplate", template);
|
||||
request.setAttribute("mbomTemplateDetails", templateDetails);
|
||||
} else {
|
||||
System.out.println("해당 품번의 M-BOM 템플릿 없음");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("projectInfo is null or empty!");
|
||||
}
|
||||
@@ -1115,8 +1147,29 @@ public class ProductionPlanningController extends BaseService {
|
||||
bomReportObjid = sourceMbomObjId;
|
||||
System.out.println("할당된 M-BOM 사용: " + bomReportObjid);
|
||||
} else {
|
||||
bomReportObjid = CommonUtils.checkNull(projectInfo.get("BOM_REPORT_OBJID"));
|
||||
System.out.println("기존 BOM_REPORT_OBJID 사용: " + bomReportObjid);
|
||||
// 할당된 BOM도 없으면 Machine 이외 제품은 템플릿 확인
|
||||
String productCode = CommonUtils.checkNull(projectInfo.get("PRODUCT_CODE"));
|
||||
String partNo = CommonUtils.checkNull(projectInfo.get("PART_NO"));
|
||||
|
||||
if(!"0000928".equals(productCode) && !"".equals(partNo)) {
|
||||
System.out.println("Machine 이외 제품 - 템플릿 조회 시도");
|
||||
Map<String, Object> templateParam = new HashMap<>();
|
||||
templateParam.put("partNo", partNo);
|
||||
|
||||
Map<String, Object> template = commonService.selectOne("productionplanning.getLatestMbomTemplateByPartNo", request, templateParam);
|
||||
|
||||
if(template != null && !template.isEmpty()) {
|
||||
bomReportObjid = CommonUtils.checkNull(template.get("TEMPLATE_HEADER_OBJID"));
|
||||
isSavedMbom = true; // 템플릿도 MBOM_DETAIL에서 조회
|
||||
System.out.println("템플릿 M-BOM 사용: " + bomReportObjid);
|
||||
} else {
|
||||
bomReportObjid = CommonUtils.checkNull(projectInfo.get("BOM_REPORT_OBJID"));
|
||||
System.out.println("기존 BOM_REPORT_OBJID 사용: " + bomReportObjid);
|
||||
}
|
||||
} else {
|
||||
bomReportObjid = CommonUtils.checkNull(projectInfo.get("BOM_REPORT_OBJID"));
|
||||
System.out.println("기존 BOM_REPORT_OBJID 사용: " + bomReportObjid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1470,13 +1523,15 @@ public class ProductionPlanningController extends BaseService {
|
||||
|
||||
if(assignment == null || assignment.isEmpty()) {
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", "M-BOM 기준 정보가 없습니다. BOM 복사 팝업에서 먼저 기준을 설정해주세요.");
|
||||
resultMap.put("message", "프로젝트 정보를 찾을 수 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
String sourceBomType = CommonUtils.checkNull(assignment.get("SOURCE_BOM_TYPE"));
|
||||
String sourceBomObjId = "";
|
||||
String baseBomPartNo = "";
|
||||
String productCode = CommonUtils.checkNull(assignment.get("PRODUCT_CODE"));
|
||||
String partNo = CommonUtils.checkNull(assignment.get("PART_NO"));
|
||||
|
||||
if("EBOM".equals(sourceBomType)) {
|
||||
sourceBomObjId = CommonUtils.checkNull(assignment.get("SOURCE_EBOM_OBJID"));
|
||||
@@ -1484,12 +1539,18 @@ public class ProductionPlanningController extends BaseService {
|
||||
} else if("MBOM".equals(sourceBomType)) {
|
||||
sourceBomObjId = CommonUtils.checkNull(assignment.get("SOURCE_MBOM_OBJID"));
|
||||
baseBomPartNo = CommonUtils.checkNull(assignment.get("MBOM_NO"));
|
||||
}
|
||||
|
||||
if(sourceBomObjId.isEmpty()) {
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", "기준 BOM 정보가 올바르지 않습니다.");
|
||||
return resultMap;
|
||||
} else {
|
||||
// 할당 정보가 없는 경우 - Machine 이외 제품은 템플릿 기반 저장 허용
|
||||
if(!"0000928".equals(productCode) && !"".equals(partNo)) {
|
||||
System.out.println("Machine 이외 제품 - 템플릿 기반 저장 허용");
|
||||
sourceBomType = "TEMPLATE"; // 템플릿 기반 저장 표시
|
||||
baseBomPartNo = partNo;
|
||||
} else {
|
||||
// Machine 제품이거나 품번이 없으면 할당 필요
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("message", "M-BOM 기준 정보가 없습니다. BOM 복사 팝업에서 먼저 기준을 설정해주세요.");
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
// M-BOM 품번 생성 또는 사용
|
||||
|
||||
@@ -2533,7 +2533,7 @@ SELECT option_objid::VARCHAR AS CODE
|
||||
<select id="getRevNoselect" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
T.OBJID::varchar AS CODE
|
||||
,COALESCE(T.REVISION, T.REV, '1.0') AS NAME
|
||||
,COALESCE(T.REVISION, '1.0') AS NAME
|
||||
,T1.PRODUCT_CODE AS CODE_CD
|
||||
,'' AS STATUS
|
||||
,T.spec_name AS ID
|
||||
@@ -2541,7 +2541,7 @@ SELECT option_objid::VARCHAR AS CODE
|
||||
FROM PART_BOM_REPORT T,PRODUCT_MGMT T1
|
||||
WHERE T.PRODUCT_MGMT_OBJID = T1.OBJID
|
||||
AND T1.OBJID = #{code}::numeric
|
||||
ORDER BY COALESCE(T.REVISION, T.REV, '1.0')
|
||||
ORDER BY COALESCE(T.REVISION, '1.0')
|
||||
|
||||
</select>
|
||||
|
||||
|
||||
@@ -3060,6 +3060,7 @@
|
||||
''
|
||||
) AS CATEGORY_NAME,
|
||||
CM.PRODUCT,
|
||||
CM.PRODUCT AS PRODUCT_CODE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
@@ -3442,6 +3443,59 @@
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 품번 기준 최신 M-BOM 템플릿 조회 (Machine 이외 제품용) -->
|
||||
<select id="getLatestMbomTemplateByPartNo" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
MH.OBJID AS TEMPLATE_HEADER_OBJID,
|
||||
MH.MBOM_NO AS TEMPLATE_MBOM_NO,
|
||||
MH.PART_NO,
|
||||
MH.PART_NAME,
|
||||
MH.SOURCE_BOM_TYPE,
|
||||
MH.SOURCE_EBOM_OBJID,
|
||||
MH.SOURCE_MBOM_OBJID,
|
||||
TO_CHAR(MH.REGDATE, 'YYYY-MM-DD HH24:MI:SS') AS REGDATE
|
||||
FROM MBOM_HEADER MH
|
||||
INNER JOIN PROJECT_MGMT PM ON MH.PROJECT_OBJID = PM.OBJID
|
||||
INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE MH.PART_NO = #{partNo}
|
||||
AND MH.STATUS = 'Y'
|
||||
AND CM.PRODUCT != '0000928' <!-- Machine 제외 -->
|
||||
ORDER BY MH.REGDATE DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 템플릿 M-BOM의 상세 항목 조회 -->
|
||||
<select id="getMbomTemplateDetails" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
MD.OBJID,
|
||||
MD.MBOM_HEADER_OBJID,
|
||||
MD.PARENT_OBJID,
|
||||
MD.CHILD_OBJID,
|
||||
MD.SEQ,
|
||||
MD.LEVEL,
|
||||
MD.PART_OBJID,
|
||||
MD.PART_NO,
|
||||
MD.PART_NAME,
|
||||
MD.QTY,
|
||||
MD.UNIT,
|
||||
MD.SUPPLY_TYPE,
|
||||
MD.MAKE_OR_BUY,
|
||||
MD.RAW_MATERIAL_PART_NO,
|
||||
MD.RAW_MATERIAL_SPEC,
|
||||
MD.RAW_MATERIAL,
|
||||
MD.RAW_MATERIAL_SIZE,
|
||||
MD.PROCESSING_VENDOR,
|
||||
MD.PROCESSING_DEADLINE,
|
||||
MD.GRINDING_DEADLINE,
|
||||
MD.REQUIRED_QTY,
|
||||
-- ORDER_QTY, PRODUCTION_QTY는 새 프로젝트에서 재계산되므로 제외
|
||||
MD.REMARK
|
||||
FROM MBOM_DETAIL MD
|
||||
WHERE MD.MBOM_HEADER_OBJID = #{mbomHeaderObjid}
|
||||
AND MD.STATUS = 'ACTIVE'
|
||||
ORDER BY MD.SEQ, MD.LEVEL
|
||||
</select>
|
||||
|
||||
<!-- M-BOM 할당 정보 조회 -->
|
||||
<select id="getMbomAssignment" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
@@ -3451,8 +3505,8 @@
|
||||
PM.SOURCE_MBOM_OBJID,
|
||||
PM.PART_NO,
|
||||
PM.PART_NAME,
|
||||
PM.PRODUCT,
|
||||
CODE_NAME(PM.PRODUCT) AS PRODUCT_NAME,
|
||||
CM.PRODUCT AS PRODUCT_CODE,
|
||||
CODE_NAME(CM.PRODUCT) AS PRODUCT_NAME,
|
||||
-- E-BOM 정보
|
||||
CASE WHEN PM.SOURCE_BOM_TYPE = 'EBOM' THEN
|
||||
(SELECT PART_NO FROM PART_BOM_REPORT WHERE OBJID = PM.SOURCE_EBOM_OBJID)
|
||||
@@ -3468,6 +3522,7 @@
|
||||
(SELECT PART_NAME FROM MBOM_HEADER WHERE OBJID = PM.SOURCE_MBOM_OBJID)
|
||||
END AS MBOM_PART_NAME
|
||||
FROM PROJECT_MGMT PM
|
||||
INNER JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
WHERE PM.OBJID::VARCHAR = #{projectObjId}
|
||||
</select>
|
||||
|
||||
@@ -3493,6 +3548,30 @@
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트의 활성 M-BOM 목록 조회 -->
|
||||
<select id="getActiveMbomsByProjectId" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT * FROM MBOM_HEADER
|
||||
WHERE PROJECT_OBJID = #{projectObjId}
|
||||
AND (STATUS = 'Y' OR STATUS = 'ACTIVE')
|
||||
ORDER BY REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- M-BOM HEADER 비활성화 -->
|
||||
<update id="inactivateMbomHeader" parameterType="map">
|
||||
UPDATE MBOM_HEADER
|
||||
SET STATUS = 'INACTIVE',
|
||||
EDIT_DATE = NOW()
|
||||
WHERE OBJID = #{mbomHeaderObjid}
|
||||
</update>
|
||||
|
||||
<!-- M-BOM DETAIL 비활성화 -->
|
||||
<update id="inactivateMbomDetail" parameterType="map">
|
||||
UPDATE MBOM_DETAIL
|
||||
SET STATUS = 'INACTIVE',
|
||||
EDIT_DATE = NOW()
|
||||
WHERE MBOM_HEADER_OBJID = #{mbomHeaderObjid}
|
||||
</update>
|
||||
|
||||
<!-- MBOM_HEADER 삽입 -->
|
||||
<insert id="insertMbomHeader" parameterType="map">
|
||||
INSERT INTO MBOM_HEADER (
|
||||
|
||||
@@ -1016,9 +1016,45 @@ public class ProductionPlanningService {
|
||||
boolean result = false;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession(false); // 수동 커밋
|
||||
|
||||
String projectObjId = CommonUtils.checkNull(paramMap.get("projectObjId"));
|
||||
|
||||
// 1. 기존 M-BOM 데이터 비활성화 (새로운 BOM 할당 시 초기화)
|
||||
if(!"".equals(projectObjId)) {
|
||||
// 해당 프로젝트의 기존 활성 M-BOM HEADER 조회
|
||||
Map<String, Object> queryParam = new HashMap<>();
|
||||
queryParam.put("projectObjId", projectObjId);
|
||||
List<Map<String, Object>> existingMboms = sqlSession.selectList("productionplanning.getActiveMbomsByProjectId", queryParam);
|
||||
|
||||
if(existingMboms != null && !existingMboms.isEmpty()) {
|
||||
System.out.println("========== 기존 M-BOM 비활성화 ==========");
|
||||
System.out.println("Project OBJID: " + projectObjId);
|
||||
System.out.println("비활성화할 M-BOM 개수: " + existingMboms.size());
|
||||
|
||||
for(Map<String, Object> mbom : existingMboms) {
|
||||
String mbomHeaderObjid = CommonUtils.checkNull(mbom.get("OBJID"));
|
||||
|
||||
if(!"".equals(mbomHeaderObjid)) {
|
||||
Map<String, Object> inactivateParam = new HashMap<>();
|
||||
inactivateParam.put("mbomHeaderObjid", mbomHeaderObjid);
|
||||
|
||||
// M-BOM DETAIL 비활성화
|
||||
sqlSession.update("productionplanning.inactivateMbomDetail", inactivateParam);
|
||||
|
||||
// M-BOM HEADER 비활성화
|
||||
sqlSession.update("productionplanning.inactivateMbomHeader", inactivateParam);
|
||||
|
||||
System.out.println("M-BOM 비활성화 완료: " + mbomHeaderObjid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. PROJECT_MGMT 업데이트 (새로운 BOM 할당 정보)
|
||||
int updateCount = sqlSession.update("productionplanning.saveBomAssignment", paramMap);
|
||||
result = (updateCount > 0);
|
||||
|
||||
sqlSession.commit();
|
||||
} catch(Exception e) {
|
||||
if(sqlSession != null) {
|
||||
@@ -1083,6 +1119,13 @@ public class ProductionPlanningService {
|
||||
cleanPartNo = cleanPartNo.substring(2); // "M-" 제거
|
||||
}
|
||||
mbomPrefix = "M-" + cleanPartNo + "-" + dateStr;
|
||||
} else if("TEMPLATE".equals(sourceBomType)) {
|
||||
// 템플릿 기준: M-{품번}-YYMMDD
|
||||
String cleanPartNo = baseBomPartNo.trim();
|
||||
if(cleanPartNo.startsWith("M-")) {
|
||||
cleanPartNo = cleanPartNo.substring(2); // "M-" 제거
|
||||
}
|
||||
mbomPrefix = "M-" + cleanPartNo + "-" + dateStr;
|
||||
} else if("MBOM".equals(sourceBomType)) {
|
||||
// M-BOM 기준: 기존 M-BOM 품번에서 날짜/순번 부분 제거 후 새 날짜 추가
|
||||
// 예: M-000AN014000-251124-01 → M-000AN014000 → M-000AN014000-251124
|
||||
@@ -1394,6 +1437,10 @@ public class ProductionPlanningService {
|
||||
} else if("MBOM".equals(sourceBomType)) {
|
||||
paramMap.put("sourceEbomObjid", null);
|
||||
paramMap.put("sourceMbomObjid", sourceBomObjId);
|
||||
} else if("TEMPLATE".equals(sourceBomType)) {
|
||||
// 템플릿 기반 저장: 할당 정보 없음
|
||||
paramMap.put("sourceEbomObjid", null);
|
||||
paramMap.put("sourceMbomObjid", null);
|
||||
}
|
||||
|
||||
// MBOM_HEADER 삽입
|
||||
|
||||
Reference in New Issue
Block a user