Merge pull request 'V20260210' (#160) from V20260210 into main

Reviewed-on: #160
This commit was merged in pull request #160.
This commit is contained in:
2026-03-04 07:09:37 +00:00
12 changed files with 109 additions and 27 deletions

View File

@@ -199,8 +199,9 @@ var columns = [
formatter: fnc_subInfoValueFormatter,
cellClick:function(e, cell){
var objId = fnc_checkNull(cell.getData().OBJID);
// 바로 팝업 열기 (팝업창 내부에서 경고 처리)
fn_openSetStructure(objId);
var STATUS = fnc_checkNull(cell.getData().STATUS);
var viewMode = (STATUS != 'N') ? 'Y' : 'N';
fn_openSetStructure(objId, viewMode);
}
},
@@ -496,8 +497,10 @@ function fn_openSetBomCopy(product_code){
/**
* 구조등록 팝업
*/
function fn_openSetStructure(objId){
window.open("/partMng/setStructurePopupMainFS.do?objId="+objId, "", "width=1880, height=900, resizable=yes");
function fn_openSetStructure(objId, viewMode){
var url = "/partMng/setStructurePopupMainFS.do?objId="+objId;
if(viewMode == 'Y') url += "&viewMode=Y";
window.open(url, "", "width=1880, height=900, resizable=yes");
}
/**
* 배포사유 입력 팝업

View File

@@ -323,7 +323,7 @@ $(function(){
<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:20px; ${param.viewMode == 'Y' ? 'display:none;' : ''}">
<input type="button" value="변경" class="plm_btns" id="moveChange">
<br>
<input type="button" value="<<" class="plm_btns" id="moveLeft" style="margin-left:0px;">

View File

@@ -1,6 +1,10 @@
<%String objId = com.pms.common.utils.CommonUtils.checkNull(request.getParameter("objId"));%>
<%
String objId = com.pms.common.utils.CommonUtils.checkNull(request.getParameter("objId"));
String viewMode = com.pms.common.utils.CommonUtils.checkNull(request.getParameter("viewMode"));
String viewModeParam = "Y".equals(viewMode) ? "&viewMode=Y" : "";
%>
<frameset cols="65%,6%,*" border="0" noresize>
<frame src="/partMng/structurePopupLeft.do?objId=<%=objId%>&actionType=working" name="leftFrame" scrolling ="no" >
<frame src="/partMng/structurePopupCenter.do?objId=<%=objId%>" name="centerFrame" style="width:">
<frame src="/partMng/structurePopupRight.do?objId=<%=objId%>" name="rightFrame" scrolling ="no">
<frame src="/partMng/structurePopupLeft.do?objId=<%=objId%>&actionType=working<%=viewModeParam%>" name="leftFrame" scrolling ="no" >
<frame src="/partMng/structurePopupCenter.do?objId=<%=objId%><%=viewModeParam%>" name="centerFrame" style="width:">
<frame src="/partMng/structurePopupRight.do?objId=<%=objId%><%=viewModeParam%>" name="rightFrame" scrolling ="no">
</frameset><noframes></noframes>

View File

@@ -1,8 +1,10 @@
<%
java.util.Map map = (java.util.HashMap)request.getAttribute("info");
String viewMode = com.pms.common.utils.CommonUtils.checkNull(request.getParameter("viewMode"));
String viewModeParam = "Y".equals(viewMode) ? "&viewMode=Y" : "";
%>
<frameset rows="100px, *, 50px" border="0" noresize>
<frame src="/partMng/structureHeaderPopup.do?objId=<%=com.pms.common.utils.CommonUtils.checkNull(map.get("OBJID"))%>">
<frame src="/partMng/structureBottomPopupFS.do?objId=<%=com.pms.common.utils.CommonUtils.checkNull(map.get("OBJID"))%>">
<frame src="/partMng/structureHeaderPopup.do?objId=<%=com.pms.common.utils.CommonUtils.checkNull(map.get("OBJID"))%><%=viewModeParam%>">
<frame src="/partMng/structureBottomPopupFS.do?objId=<%=com.pms.common.utils.CommonUtils.checkNull(map.get("OBJID"))%><%=viewModeParam%>">
<frame src="/partMng/structureBtnAreaPopup.do">
</frameset><noframes></noframes>

View File

@@ -58,10 +58,15 @@
var _tabulGrid;
var selectedRowData = null;
var isViewMode = ('${param.viewMode}' == 'Y');
$(function(){
if('${param.readonly}' == 'readonly'){
if('${param.readonly}' == 'readonly' || isViewMode){
$("#structureName2").hide();
}
if(isViewMode){
$("#btnDrawingUpload").hide();
}
$("#btnExcel").click(function() {
fn_excel();

View File

@@ -162,7 +162,7 @@ function fn_closeEbom() {
<form name="form1" id="form1" action="" method="post">
<div class="plm_menu_name">
<h2>
<span>E-BOM 확인/수정</span>
<span>E-BOM ${param.viewMode == 'Y' ? '조회' : '확인/수정'}</span>
<c:if test="${not empty partNo}">
<span style="font-size: 14px; font-weight: normal; color: #666; margin-left: 20px;">
품번: <strong style="color: #333;">${partNo}</strong>
@@ -191,7 +191,9 @@ function fn_closeEbom() {
<td>
<button type="button" class="plm_btns" onclick="fn_applyFilter()">검색</button>
<button type="button" class="plm_btns" onclick="fn_resetFilter()">초기화</button>
<c:if test="${param.viewMode != 'Y'}">
<button type="button" class="plm_btns" onclick="fn_saveEbom()" style="background-color:#4CAF50; color:white; margin-left:20px;">저장</button>
</c:if>
<button type="button" class="plm_btns" onclick="fn_closeEbom()">닫기</button>
</td>
</tr>

View File

@@ -292,6 +292,7 @@ function fn_loadMbomTemplate() {
if(leftFrame && leftFrame._tabulGrid) {
leftFrame._tabulGrid.setData(templateDetails);
if(leftFrame.fn_syncLastValidData) leftFrame.fn_syncLastValidData();
console.log("템플릿 데이터 로드 완료");
} else {
console.error("왼쪽 프레임 또는 그리드를 찾을 수 없습니다.");
@@ -1031,6 +1032,7 @@ function buildSubTreeFlatList(subTree, parentObjid, baseLevel) {
REVISION: item.REVISION || item.revision || '',
SUPPLY_TYPE: '사급',
STATUS: 'ACTIVE',
_IS_ADDED: true,
_IS_SUB_PART: true
});
}
@@ -1140,7 +1142,8 @@ function fn_mbomAddPart() {
SPEC: rowData.SPEC,
REVISION: rowData.REVISION,
SUPPLY_TYPE: '사급',
STATUS: 'ACTIVE'
STATUS: 'ACTIVE',
_IS_ADDED: true
};
newParts.push(newPart);
@@ -1158,6 +1161,13 @@ function fn_mbomAddPart() {
}
}
// 수준(LEVEL_X) 필드 설정
for(var i = 0; i < newParts.length; i++) {
if(leftFrame && leftFrame.fn_setLevelFields) {
leftFrame.fn_setLevelFields(newParts[i]);
}
}
// 왼쪽 프레임의 Tabulator에 추가
if(leftFrame && leftFrame._tabulGrid) {
if(parentObjid) {
@@ -1180,6 +1190,11 @@ function fn_mbomAddPart() {
}
}
// 드래그 이동용 데이터 동기화
if(leftFrame && leftFrame.fn_syncLastValidData) {
leftFrame.fn_syncLastValidData();
}
var message = rightSelectedRows.length + '개 파트가 추가되었습니다.';
if(subPartCount > 0) {
message += '\n(반제품 하위 ' + subPartCount + '개 품목 포함)';
@@ -1253,6 +1268,7 @@ function fn_mbomDeletePart() {
// 선택한 행 + 하위 품목 일괄 삭제
allData.splice(foundIndex, deleteCount);
leftFrame._tabulGrid.setData(allData);
if(leftFrame.fn_syncLastValidData) leftFrame.fn_syncLastValidData();
var message = '파트가 삭제되었습니다.';
if(deleteCount > 1) {
@@ -1463,6 +1479,7 @@ function fn_changeTopProduct() {
// 왼쪽 트리에 새 데이터 설정
if(leftFrame && leftFrame._tabulGrid) {
leftFrame._tabulGrid.setData(newTreeData);
if(leftFrame.fn_syncLastValidData) leftFrame.fn_syncLastValidData();
}
// M-BOM 품번을 변경된 최상위 제품의 품번으로 설정

View File

@@ -78,6 +78,7 @@ body {
</style>
<script>
var _tabulGrid;
var _lastValidData = [];
var selectedRowData = null; // 선택된 행 데이터
// 프로젝트 수주수량 (최상위 프레임에서 가져오기)
var projectQuantity = 1; // 기본값
@@ -247,9 +248,19 @@ function createSelect2Editor(options) {
};
}
// 수준(LEVEL_X) 필드 생성 (파트 추가 시 사용)
var _maxLevel = ${empty MAXLEV ? 1 : MAXLEV};
function fn_setLevelFields(item) {
var level = parseInt(item.LEVEL) || 1;
for(var i = 1; i <= _maxLevel; i++) {
item['LEVEL_' + i] = (i === level) ? '*' : '';
}
return item;
}
// Tabulator 그리드 초기화
function fn_initGrid() {
var maxLevel = ${empty MAXLEV ? 1 : MAXLEV};
var maxLevel = _maxLevel;
// 컬럼 정의
var columns = [];
@@ -328,6 +339,17 @@ function fn_initGrid() {
width: 50,
title: '수량',
field: 'QTY_TEMP',
editor: 'number',
editorParams: { min: 0, step: 1, selectContents: true },
editable: function(cell) { var d = cell.getRow().getData(); return d._IS_ADDED === true && d._IS_SUB_PART !== true; },
formatter: function(cell) {
var d = cell.getRow().getData();
if(d._IS_ADDED === true && d._IS_SUB_PART !== true) {
cell.getElement().style.backgroundColor = '#FFF9C4';
cell.getElement().style.border = '1px solid #F9A825';
}
return cell.getValue();
},
visible: true
},
{
@@ -336,6 +358,17 @@ function fn_initGrid() {
width: 80,
title: '항목 수량',
field: 'ITEM_QTY',
editor: 'number',
editorParams: { min: 0, step: 1, selectContents: true },
editable: function(cell) { var d = cell.getRow().getData(); return d._IS_ADDED === true && d._IS_SUB_PART !== true; },
formatter: function(cell) {
var d = cell.getRow().getData();
if(d._IS_ADDED === true && d._IS_SUB_PART !== true) {
cell.getElement().style.backgroundColor = '#FFF9C4';
cell.getElement().style.border = '1px solid #F9A825';
}
return cell.getValue();
},
visible: true
},
/* 주석처리: Rev, 규격, 제품구분, 상태 컬럼
@@ -1036,7 +1069,7 @@ function fn_initGrid() {
});
// 초기 유효 데이터 저장
var _lastValidData = bomTreeData.slice();
_lastValidData = bomTreeData.slice();
// 드래그 이동 후 같은 부모 내 이동만 허용, 하위 품목도 함께 이동
_tabulGrid.on("rowMoved", function(row) {
@@ -1167,6 +1200,13 @@ function fn_initGrid() {
});
}
// 외부(mBomHeaderPopup)에서 파트 추가/삭제 후 호출하여 드래그 이동용 데이터 동기화
function fn_syncLastValidData() {
if(_tabulGrid) {
_lastValidData = _tabulGrid.getData().slice();
}
}
// 필터 적용 함수
function fn_applyFilter() {
var partNo = $("#filterPartNo").val().trim();
@@ -1297,7 +1337,8 @@ function getMbomTreeData() {
partName: row.PART_NAME,
// 수량 정보
qty: toNumber(row.QTY_TEMP || row.QTY || row.ITEM_QTY),
qty: toNumber(row.QTY_TEMP || row.QTY),
itemQty: toNumber(row.ITEM_QTY),
unit: row.UNIT,
// 생산 정보

View File

@@ -187,6 +187,12 @@ function fn_registResultPopUp(){
return;
}
var amaranthStatus = fnc_checkNull(selected[0].AMARANTH_STATUS);
if(amaranthStatus != "complete"){
Swal.fire("결재완료된 건만 결과등록이 가능합니다.");
return;
}
var popup_width = 1200;
var popup_height = 600;
var hiddenForm = document.hiddenForm;

View File

@@ -19,11 +19,11 @@ String objId = CommonUtils.checkNull(info.get("objid"));
// 오늘 날짜
String today = new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date());
String completeDate = CommonUtils.checkNull(info.get("complete_date"));
if(completeDate.isEmpty()) completeDate = today;
if(completeDate.isEmpty() && !isViewMode) completeDate = today;
// 조치자 - 기본값 로그인 사용자
// 조치자 - 기본값 로그인 사용자 (뷰 모드에서는 저장된 값만 표시)
String actionUserId = CommonUtils.checkNull(info.get("action_user_id"));
if(actionUserId.isEmpty()) actionUserId = connectUserId;
if(actionUserId.isEmpty() && !isViewMode) actionUserId = connectUserId;
%>
<!DOCTYPE html>
<html>

View File

@@ -3870,8 +3870,8 @@
<insert id="insertMbomDetail" parameterType="map">
INSERT INTO MBOM_DETAIL (
OBJID, MBOM_HEADER_OBJID, PARENT_OBJID, CHILD_OBJID, SEQ, LEVEL,
PART_OBJID, PART_NO, PART_NAME, QTY, UNIT,
SUPPLY_TYPE, MAKE_OR_BUY,
PART_OBJID, PART_NO, PART_NAME, QTY, ITEM_QTY, UNIT,
SUPPLY_TYPE, MAKE_OR_BUY,
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,
@@ -3883,8 +3883,8 @@
STATUS, WRITER, REGDATE, EDITER, EDIT_DATE, REMARK
) VALUES (
#{objid}, #{mbomHeaderObjid}, #{parentObjid}, #{childObjid}, #{seq}, #{level},
#{partObjid}, #{partNo}, #{partName}, #{qty}, #{unit},
#{supplyType}, #{makeOrBuy},
#{partObjid}, #{partNo}, #{partName}, #{qty}, #{itemQty}, #{unit},
#{supplyType}, #{makeOrBuy},
#{rawMaterialPartNo}, #{rawMaterialSpec}, #{rawMaterial}, #{rawMaterialSize},
#{processingVendor}, #{processingDeadline}, #{grindingDeadline},
#{requiredQty}, #{orderQty}, #{productionQty}, #{stockQty}, #{shortageQty},
@@ -3931,6 +3931,7 @@
PART_NO = NULLIF(#{partNo}, ''),
PART_NAME = NULLIF(#{partName}, ''),
QTY = NULLIF(#{qty}::TEXT, '')::NUMERIC,
ITEM_QTY = NULLIF(#{itemQty}::TEXT, '')::NUMERIC,
UNIT = NULLIF(#{unit}, ''),
SUPPLY_TYPE = NULLIF(#{supplyType}, ''),
MAKE_OR_BUY = NULLIF(#{makeOrBuy}, ''),
@@ -4055,6 +4056,7 @@
MD.PART_NO,
MD.PART_NAME,
MD.QTY,
MD.ITEM_QTY,
MD.UNIT,
MD.SUPPLY_TYPE,
MD.MAKE_OR_BUY,
@@ -4148,7 +4150,7 @@
A.PART_NO,
A.PART_NAME,
A.QTY,
A.QTY,
A.ITEM_QTY,
A.QTY,
A.REGDATE,
A.SEQ,
@@ -4201,7 +4203,7 @@
B.PART_NO,
B.PART_NAME,
B.QTY,
B.QTY,
B.ITEM_QTY,
B.QTY,
B.REGDATE,
B.SEQ,

View File

@@ -1482,7 +1482,7 @@ VALUES
WHERE 1=1
AND PM.IS_LAST = '1'
ORDER BY PM.PART_NO
LIMIT 500
-- LIMIT 500
</select>
<select id="SalesBomPartListByProjectUnit" parameterType="map" resultType="map">