Files
wace_plm/WebContent/WEB-INF/view/partMng/structureBomCopyFormPopup.jsp
2025-11-17 17:29:04 +09:00

637 lines
16 KiB
Plaintext

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.pms.common.utils.*"%>
<%@ page import="java.util.*" %>
<%@include file= "/init.jsp" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><%=Constants.SYSTEM_NAME%></title>
<link href="/css/tabulator/tabulator.min.css" rel="stylesheet">
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
<style>
::-webkit-scrollbar {
width: 10px;
height: 15px;
}
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
/* 상단 입력 영역 */
.top-input-section {
padding: 15px 20px;
background: #f9f9f9;
border-bottom: 2px solid #ddd;
}
.input-table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
.input-table td {
padding: 5px 8px;
vertical-align: middle;
}
.input-table label {
font-weight: bold;
display: block;
white-space: nowrap;
}
.input-table input[type="text"] {
padding: 6px 8px;
border: 1px solid #ddd;
border-radius: 3px;
width: 100%;
box-sizing: border-box;
}
.bom-select-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
table-layout: fixed;
}
.bom-select-table td {
padding: 5px 8px;
vertical-align: middle;
}
.bom-select-table label {
font-weight: bold;
display: block;
white-space: nowrap;
}
.bom-select-table input[type="text"] {
padding: 6px 8px;
border: 1px solid #ddd;
border-radius: 3px;
width: 100%;
box-sizing: border-box;
}
/* 하단 버튼 영역 */
.bottom-button-section {
padding: 15px 20px;
background: #f9f9f9;
border-top: 2px solid #ddd;
text-align: center;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 100;
}
/* 그리드 영역 */
#structureTableWrap1 {
padding: 15px 20px;
height: calc(100vh - 260px);
overflow: auto;
padding-bottom: 80px;
}
#structureName {
margin-bottom: 10px;
font-weight: bold;
padding: 8px 0;
border-bottom: 1px solid #eee;
}
#structureName2 {
margin-bottom: 10px;
font-size: 12px;
color: #666;
}
/* Tabulator 커스텀 스타일 */
.tabulator-row.level-1 { background-color: #fde9d9 !important; }
.tabulator-row.level-2 { background-color: #daeef3 !important; }
.tabulator-row.level-3 { background-color: #e4dfec !important; }
.tabulator-row.level-4 { background-color: #ebf1de !important; }
.tabulator-row.level-5 { background-color: #f2f2f2 !important; }
.tabulator-row.level-6 { background-color: #f2dcdb !important; }
.tabulator-row.level-7 { background-color: #eeece1 !important; }
.tabulator-row.level-8 { background-color: #dce6f1 !important; }
.tabulator-row.level-9 { background-color: #FFFFEB !important; }
.tabulator-row.level-10 { background-color: #ffffff !important; }
</style>
<script>
var _tabulGrid;
var selectedRowData = null;
var selectedBomObjId = null; // 선택된 BOM의 OBJID
var selectedBomType = null; // 'EBOM' 또는 'MBOM'
var bomGridData = []; // BOM 그리드 데이터
$(function(){
// 페이지 로드 시 프로젝트 정보가 있으면 품번/품명 자동 입력
<c:if test="${not empty projectInfo}">
console.log("projectInfo가 있습니다. 품번/품명 설정 중...");
$("#COPY_PART_NO").val("${projectInfo.PART_NO}");
$("#COPY_PART_NAME").val("${projectInfo.PART_NAME}");
// E-BOM 품번은 사용자가 직접 입력하도록 비워둠 (M-BOM 품번과 다를 수 있음)
</c:if>
// 담기 버튼 - 선택한 BOM을 복사 대상으로 설정
$("#btnAddItem").click(function(){
var partNo = $("#COPY_PART_NO").val().trim();
var partName = $("#COPY_PART_NAME").val().trim();
if(!partNo || !partName) {
Swal.fire('품번과 품명을 입력해주세요.');
return;
}
// 선택된 BOM이 있는지 확인
if(!selectedBomObjId) {
Swal.fire('E-BOM 또는 M-BOM을 먼저 선택해주세요.');
return;
}
Swal.fire({
title: '담기 완료',
text: '선택한 BOM이 복사 대상으로 설정되었습니다.',
icon: 'success'
});
});
// 저장 버튼 - E-BOM을 M-BOM으로 복사
$("#btnSaveItem").click(function(){
fn_saveBomCopy();
});
// E-BOM 선택 버튼
$("#btnSelectEbom").click(function(){
var ebomPartNo = $("#EBOM_PART_NO").val().trim();
if(!ebomPartNo) {
Swal.fire('E-BOM 품번을 입력해주세요.');
return;
}
// E-BOM 조회 후 미리보기 로드
fn_loadBomPreview(ebomPartNo, 'EBOM');
});
// M-BOM 선택 버튼
$("#btnSelectMbom").click(function(){
var mbomPartNo = $("#MBOM_PART_NO").val().trim();
if(!mbomPartNo) {
Swal.fire('M-BOM 품번을 입력해주세요.');
return;
}
// M-BOM 조회 후 미리보기 로드
fn_loadBomPreview(mbomPartNo, 'MBOM');
});
// Excel 다운로드 버튼
$("#btnExcel").click(function() {
fn_excel();
});
// 도면 업로드 버튼 클릭
$("#btnDrawingUpload").click(function() {
$("#drawingFiles").click();
});
// 파일 선택 이벤트
$("#drawingFiles").change(function() {
fn_uploadDrawingFiles(this.files);
});
// 초기 그리드 생성 (빈 그리드)
fn_initGrid([], 3);
});
// BOM 미리보기 로드
function fn_loadBomPreview(partNo, bomType) {
console.log("fn_loadBomPreview 호출:", partNo, bomType);
// 먼저 품번으로 BOM OBJID 조회
$.ajax({
url: "/partMng/getBomObjIdByPartNo.do",
type: "POST",
data: { partNo: partNo },
dataType: "json",
success: function(response) {
console.log("getBomObjIdByPartNo 응답:", response);
if(response && response.OBJID) {
$("#bomPartName").text(partNo);
// 전역 변수에 저장
selectedBomObjId = response.OBJID;
selectedBomType = bomType;
// BOM 트리 데이터 로드
fn_loadBomTree(response.OBJID);
} else {
console.error("BOM OBJID를 찾을 수 없음:", response);
Swal.fire('해당 품번의 BOM을 찾을 수 없습니다.');
}
},
error: function(xhr, status, error) {
console.error("getBomObjIdByPartNo 에러:", xhr, status, error);
Swal.fire('BOM 조회 중 오류가 발생했습니다.');
}
});
}
// BOM 트리 데이터 로드
function fn_loadBomTree(bomObjId) {
console.log("fn_loadBomTree 호출:", bomObjId);
$.ajax({
url: "/partMng/getStructureTreeJson.do",
type: "POST",
data: {
objId: bomObjId,
bomReportObjid: bomObjId,
search_type: "working"
},
dataType: "json",
success: function(response) {
console.log("getStructureTreeJson 응답:", response);
if(response && response.length > 0) {
var maxLevel = response[0].MAX_LEVEL || 3;
// Level 필드 생성
var processedData = [];
response.forEach(function(item) {
for(var i = 1; i <= maxLevel; i++) {
item['LEVEL_' + i] = (item.LEVEL == i) ? '*' : '';
}
processedData.push(item);
});
// 전역 변수에 저장
bomGridData = processedData;
fn_initGrid(processedData, maxLevel);
} else {
console.warn("BOM 트리 데이터가 비어있음");
bomGridData = [];
fn_initGrid([], 3);
}
},
error: function(xhr, status, error) {
console.error("getStructureTreeJson 에러:", xhr, status, error);
Swal.fire('BOM 트리 조회 중 오류가 발생했습니다.');
}
});
}
// 도면 파일 업로드
function fn_uploadDrawingFiles(files) {
if(!files || files.length === 0) {
Swal.fire('파일을 선택해주세요.');
return;
}
Swal.fire('도면 다중 업로드 기능은 구현 예정입니다.');
}
// Tabulator 그리드 초기화
function fn_initGrid(data, maxLevel) {
maxLevel = maxLevel || 3; // 기본 3레벨
// 데이터에서 최대 레벨 계산
if(data && data.length > 0) {
data.forEach(function(row) {
if(row.LEVEL && row.LEVEL > maxLevel) {
maxLevel = row.LEVEL;
}
});
}
// 컬럼 정의
var columns = [
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '선택',
field: 'RADIO',
formatter: function(cell) {
var rowData = cell.getData();
return '<input type="radio" name="checkedPartNo" value="' + (rowData.CHILD_OBJID || '') + '">';
},
cellClick: function(e, cell) {
var radio = $(e.target);
if(radio.is(':radio')) {
selectedRowData = cell.getData();
$('input[name=checkedPartNo]').not(radio).prop('checked', false);
}
}
}
];
// 수준 컬럼 그룹
var levelColumns = [];
for(var i = 1; i <= maxLevel; i++) {
levelColumns.push({
headerHozAlign: 'center',
hozAlign: 'center',
width: 30,
title: i,
field: 'LEVEL_' + i,
formatter: function(cell) {
return cell.getValue() === '*' ? '*' : '';
}
});
}
columns.push({
title: '수준',
headerHozAlign: 'center',
columns: levelColumns
});
// 나머지 컬럼 추가
columns.push(
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 150,
title: '품번',
field: 'PART_NO'
},
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 200,
title: '품명',
field: 'PART_NAME'
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '수량',
field: 'QTY_TEMP'
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 100,
title: '항목 수량',
field: 'ITEM_QTY'
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '3D',
field: 'CU01_CNT',
formatter: function(cell) {
var rowData = cell.getData();
var iconClass = (rowData.CU01_CNT && rowData.CU01_CNT > 0) ? 'file_icon' : 'file_empty_icon';
return '<a href="#" class="File ' + iconClass + '"></a>';
}
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '2D',
field: 'CU02_CNT',
formatter: function(cell) {
var rowData = cell.getData();
var iconClass = (rowData.CU02_CNT && rowData.CU02_CNT > 0) ? 'file_icon' : 'file_empty_icon';
return '<a href="#" class="File ' + iconClass + '"></a>';
}
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: 'PDF',
field: 'CU03_CNT',
formatter: function(cell) {
var rowData = cell.getData();
var iconClass = (rowData.CU03_CNT && rowData.CU03_CNT > 0) ? 'file_icon' : 'file_empty_icon';
return '<a href="#" class="File ' + iconClass + '"></a>';
}
},
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 100,
title: '재료',
field: 'MATERIAL'
},
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 120,
title: '열처리경도',
field: 'HEAT_TREATMENT_HARDNESS'
}
);
// 기존 그리드 제거
if(_tabulGrid) {
_tabulGrid.destroy();
}
// Tabulator 생성
_tabulGrid = new Tabulator("#structureGrid", {
data: data,
layout: "fitColumns",
height: "calc(100vh - 360px)",
columns: columns,
rowFormatter: function(row) {
var data = row.getData();
if(data.LEVEL) {
$(row.getElement()).addClass('level-' + data.LEVEL);
}
},
placeholder: "BOM 데이터를 조회하려면 E-BOM 또는 M-BOM 품번을 입력하고 선택 버튼을 클릭하세요."
});
}
// BOM 복사 저장
function fn_saveBomCopy() {
var copyPartNo = $("#COPY_PART_NO").val().trim();
var copyPartName = $("#COPY_PART_NAME").val().trim();
var targetObjId = $("#TARGET_OBJID").val();
// 유효성 검사
if(!copyPartNo || !copyPartName) {
Swal.fire('품번과 품명을 입력해주세요.');
return;
}
if(!selectedBomObjId) {
Swal.fire('복사할 BOM을 선택해주세요.');
return;
}
if(bomGridData.length === 0) {
Swal.fire('복사할 BOM 데이터가 없습니다.');
return;
}
// 확인 메시지
var confirmMessage = targetObjId
? '선택한 ' + selectedBomType + '을(를) M-BOM으로 복사하시겠습니까?\n기존 M-BOM이 있다면 초기화됩니다.'
: '선택한 ' + selectedBomType + '을(를) 새로운 품번(' + copyPartNo + ')으로 복사하시겠습니까?';
Swal.fire({
title: 'BOM 복사',
text: confirmMessage,
icon: 'question',
showCancelButton: true,
confirmButtonText: '복사',
cancelButtonText: '취소'
}).then((result) => {
if(result.isConfirmed) {
// 저장 처리
Swal.fire({
title: '저장 중...',
text: 'BOM을 복사하고 있습니다.',
allowOutsideClick: false,
didOpen: () => {
Swal.showLoading();
}
});
$.ajax({
url: "/partMng/saveBomCopy.do",
type: "POST",
data: JSON.stringify({
targetObjId: targetObjId, // M-BOM 관리에서 선택한 프로젝트 OBJID
sourceBomObjId: selectedBomObjId,
sourceBomType: selectedBomType,
targetPartNo: copyPartNo,
targetPartName: copyPartName,
bomData: bomGridData
}),
contentType: "application/json",
dataType: "json",
success: function(response) {
Swal.close();
if(response && response.result === 'success') {
Swal.fire({
title: '저장 완료',
text: 'M-BOM이 성공적으로 생성되었습니다.',
icon: 'success'
}).then(() => {
// 부모 창(M-BOM 관리) 새로고침하여 아이콘 업데이트
if(window.opener && !window.opener.closed) {
window.opener.location.reload();
}
window.close();
});
} else {
Swal.fire({
title: '저장 실패',
text: response.message || 'BOM 복사 중 오류가 발생했습니다.',
icon: 'error'
});
}
},
error: function(xhr, status, error) {
Swal.close();
console.error('Save error:', error);
Swal.fire({
title: '저장 실패',
text: '서버 오류가 발생했습니다: ' + error,
icon: 'error'
});
}
});
}
});
}
// 닫기
function fn_close() {
window.close();
}
// Excel 다운로드
function fn_excel() {
if(_tabulGrid) {
_tabulGrid.download("xlsx", "BOM_Copy.xlsx", {sheetName: "BOM"});
}
}
</script>
</head>
<body class="backcolor">
<form name="form1" id="form1" action="" method="post">
<!-- Hidden fields -->
<input type="hidden" id="TARGET_OBJID" name="TARGET_OBJID" value="${param.objId}">
<!-- 상단: 품번/품명 입력 및 BOM 선택 영역 -->
<div class="top-input-section">
<table class="pmsPopuptable" style="margin-bottom: 10px;">
<colgroup>
<col width="10%">
<col width="25%">
<col width="10%">
<col width="25%">
<col width="30%">
</colgroup>
<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%;">
</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%;">
</td>
<td style="text-align: center;">
<input type="button" value="담기" class="plm_btns" id="btnAddItem">
<input type="button" value="저장" class="plm_btns" id="btnSaveItem">
</td>
</tr>
</table>
<table class="pmsPopuptable">
<colgroup>
<col width="15%">
<col width="85%">
</colgroup>
<tr>
<td class="input_title"><label for="EBOM_PART_NO">E-BOM 품번</label></td>
<td>
<input type="text" id="EBOM_PART_NO" name="EBOM_PART_NO" style="width: 400px; margin-right: 10px;">
<input type="button" value="E-BOM 선택" class="plm_btns" id="btnSelectEbom">
</td>
</tr>
<tr>
<td class="input_title"><label for="MBOM_PART_NO">M-BOM 품번</label></td>
<td>
<input type="text" id="MBOM_PART_NO" name="MBOM_PART_NO" style="width: 400px; margin-right: 10px;">
<input type="button" value="M-BOM 선택" class="plm_btns" id="btnSelectMbom">
</td>
</tr>
</table>
</div>
<!-- 중간: BOM 미리보기 그리드 -->
<div id="structureTableWrap1">
<div id="structureName">
<span id="bomPartName" style="font-weight: bold; color: #333;"></span>
<input type="button" value="Excel Download" class="plm_btns structure_btn" id="btnExcel" style="float:right;">
<input type="button" value="도면 다중 업로드" class="plm_btns structure_btn" id="btnDrawingUpload" style="float:right; margin-right:5px;">
<input type="file" id="drawingFiles" multiple style="display:none;" accept=".stp,.step,.dwg,.dxf,.pdf">
</div>
<div id="structureGrid"></div>
</div>
</form>
</body>
</html>