2025-11-17 17:29:04 +09:00
|
|
|
|
<%@ 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">
|
2025-12-11 15:18:47 +09:00
|
|
|
|
<link href="/css/select2/select2.min.css" rel="stylesheet">
|
2025-11-17 17:29:04 +09:00
|
|
|
|
<script type="text/javascript" src="/js/tabulator/tabulator.min.js"></script>
|
2025-12-11 15:18:47 +09:00
|
|
|
|
<script type="text/javascript" src="/js/select2/select2.min.js"></script>
|
2025-11-17 17:29:04 +09:00
|
|
|
|
<style>
|
|
|
|
|
|
::-webkit-scrollbar {
|
|
|
|
|
|
width: 10px;
|
|
|
|
|
|
height: 15px;
|
|
|
|
|
|
}
|
|
|
|
|
|
#mBomTableWrap {
|
|
|
|
|
|
width: 99%;
|
|
|
|
|
|
margin: 10px auto;
|
2025-11-18 14:37:36 +09:00
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
overflow-y: hidden;
|
2025-11-17 17:29:04 +09:00
|
|
|
|
}
|
|
|
|
|
|
#mBomName {
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
}
|
2025-11-18 14:37:36 +09:00
|
|
|
|
body {
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
2025-11-17 17:29:04 +09:00
|
|
|
|
/* 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; }
|
2025-12-02 15:10:41 +09:00
|
|
|
|
|
|
|
|
|
|
/* 편집 가능한 컬럼 헤더 스타일 */
|
|
|
|
|
|
.editable-header {
|
|
|
|
|
|
background-color: #fff9c4 !important;
|
|
|
|
|
|
}
|
2025-12-11 15:18:47 +09:00
|
|
|
|
|
2026-01-15 14:40:26 +09:00
|
|
|
|
/* 선택된 행 하이라이트 스타일 */
|
|
|
|
|
|
.tabulator-row.row-selected {
|
|
|
|
|
|
background-color: #b8daff !important;
|
|
|
|
|
|
border: 1px solid #007bff !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-11 15:18:47 +09:00
|
|
|
|
/* Select2 in Tabulator 스타일 */
|
|
|
|
|
|
.tabulator-cell .select2-container {
|
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tabulator-cell .select2-container--default .select2-selection--single {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tabulator-cell .select2-container--default .select2-selection--single .select2-selection__rendered {
|
|
|
|
|
|
line-height: normal;
|
|
|
|
|
|
padding-left: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.tabulator-cell .select2-container--default .select2-selection--single .select2-selection__arrow {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
}
|
|
|
|
|
|
.select2-container--open {
|
|
|
|
|
|
z-index: 9999 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.select2-results__option {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
}
|
2025-11-17 17:29:04 +09:00
|
|
|
|
</style>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
var _tabulGrid;
|
2026-01-15 14:40:26 +09:00
|
|
|
|
var selectedRowData = null; // 선택된 행 데이터
|
2025-11-24 18:47:21 +09:00
|
|
|
|
// 프로젝트 수주수량 (최상위 프레임에서 가져오기)
|
|
|
|
|
|
var projectQuantity = 1; // 기본값
|
2025-11-17 17:29:04 +09:00
|
|
|
|
|
2025-11-26 17:18:31 +09:00
|
|
|
|
// 소재 목록 전역 변수
|
|
|
|
|
|
var materialList = [];
|
|
|
|
|
|
|
2025-12-11 15:18:47 +09:00
|
|
|
|
// 공급업체(가공업체) 목록 전역 변수
|
|
|
|
|
|
var supplyVendorList = [];
|
|
|
|
|
|
|
2025-11-17 17:29:04 +09:00
|
|
|
|
$(function(){
|
2025-11-24 18:47:21 +09:00
|
|
|
|
// 최상위 프레임(mBomPopupHeaderFs.jsp)에서 프로젝트 수주수량 가져오기
|
|
|
|
|
|
try {
|
|
|
|
|
|
if(parent && parent.parent && parent.parent.PROJECT_QUANTITY) {
|
|
|
|
|
|
projectQuantity = parseFloat(parent.parent.PROJECT_QUANTITY) || 1;
|
|
|
|
|
|
console.log("프로젝트 수주수량:", projectQuantity);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log("PROJECT_QUANTITY를 찾을 수 없습니다. 기본값 1 사용");
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch(e) {
|
|
|
|
|
|
console.log("프로젝트 수주수량 가져오기 실패:", e);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 17:18:31 +09:00
|
|
|
|
// 소재 목록 로드
|
|
|
|
|
|
fn_loadMaterialList();
|
|
|
|
|
|
|
2025-12-11 15:18:47 +09:00
|
|
|
|
// 공급업체(가공업체) 목록 로드
|
|
|
|
|
|
fn_loadSupplyVendorList();
|
|
|
|
|
|
|
2025-11-17 17:29:04 +09:00
|
|
|
|
// Tabulator 초기화
|
|
|
|
|
|
fn_initGrid();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-26 17:18:31 +09:00
|
|
|
|
// 소재 목록 로드
|
|
|
|
|
|
function fn_loadMaterialList() {
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: '/admin/getMaterialList.do',
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
async: false,
|
|
|
|
|
|
success: function(response) {
|
|
|
|
|
|
if(response && response.list) {
|
|
|
|
|
|
// 중복 제거하여 소재 코드만 추출
|
|
|
|
|
|
var uniqueMaterials = {};
|
|
|
|
|
|
response.list.forEach(function(item) {
|
|
|
|
|
|
uniqueMaterials[item.MATERIAL_CODE] = true;
|
|
|
|
|
|
});
|
|
|
|
|
|
materialList = Object.keys(uniqueMaterials);
|
|
|
|
|
|
console.log("소재 목록 로드 완료:", materialList);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
error: function() {
|
|
|
|
|
|
console.error("소재 목록 로드 실패");
|
|
|
|
|
|
materialList = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-11 15:18:47 +09:00
|
|
|
|
// 가공업체 목록 로드 (CLIENT_MNG 테이블)
|
|
|
|
|
|
function fn_loadSupplyVendorList() {
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: '/common/getClientMngList.do',
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
async: false,
|
|
|
|
|
|
dataType: 'json',
|
|
|
|
|
|
success: function(data) {
|
|
|
|
|
|
if(data && data.length > 0) {
|
2025-12-12 15:09:58 +09:00
|
|
|
|
// {id: CODE_ID(OBJID), text: NAME(CLIENT_NM)} 형태로 변환
|
2025-12-11 15:18:47 +09:00
|
|
|
|
supplyVendorList = data.map(function(item) {
|
|
|
|
|
|
return {
|
2025-12-12 15:09:58 +09:00
|
|
|
|
id: item.CODE_ID,
|
|
|
|
|
|
text: item.NAME
|
2025-12-11 15:18:47 +09:00
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log("가공업체 목록 로드 완료:", supplyVendorList.length + "개");
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
error: function() {
|
|
|
|
|
|
console.error("가공업체 목록 로드 실패");
|
|
|
|
|
|
supplyVendorList = [];
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Select2 커스텀 에디터 생성 함수
|
|
|
|
|
|
function createSelect2Editor(options) {
|
|
|
|
|
|
return function(cell, onRendered, success, cancel, editorParams) {
|
|
|
|
|
|
var cellValue = cell.getValue();
|
|
|
|
|
|
var container = document.createElement("span");
|
|
|
|
|
|
var select = document.createElement("select");
|
|
|
|
|
|
select.style.width = "100%";
|
|
|
|
|
|
|
|
|
|
|
|
// 빈 옵션 추가
|
|
|
|
|
|
var emptyOption = document.createElement("option");
|
|
|
|
|
|
emptyOption.value = "";
|
|
|
|
|
|
emptyOption.text = "선택";
|
|
|
|
|
|
select.appendChild(emptyOption);
|
|
|
|
|
|
|
|
|
|
|
|
// 옵션 추가
|
|
|
|
|
|
options.forEach(function(opt) {
|
|
|
|
|
|
var option = document.createElement("option");
|
|
|
|
|
|
if(typeof opt === 'object') {
|
2025-12-12 15:09:58 +09:00
|
|
|
|
option.value = opt.id || opt.value || '';
|
|
|
|
|
|
option.text = opt.text || opt.label || '';
|
2025-12-11 15:18:47 +09:00
|
|
|
|
} else {
|
|
|
|
|
|
option.value = opt;
|
|
|
|
|
|
option.text = opt;
|
|
|
|
|
|
}
|
2025-12-12 15:09:58 +09:00
|
|
|
|
if(option.value == cellValue) {
|
2025-12-11 15:18:47 +09:00
|
|
|
|
option.selected = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
select.appendChild(option);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
container.appendChild(select);
|
|
|
|
|
|
|
|
|
|
|
|
onRendered(function() {
|
|
|
|
|
|
$(select).select2({
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
dropdownAutoWidth: true,
|
|
|
|
|
|
placeholder: '선택',
|
|
|
|
|
|
allowClear: true,
|
2025-12-12 15:09:58 +09:00
|
|
|
|
dropdownParent: $('body'), // 드롭다운이 셀 밖으로 나오도록
|
|
|
|
|
|
templateResult: function(data) {
|
|
|
|
|
|
return data.text;
|
|
|
|
|
|
},
|
|
|
|
|
|
templateSelection: function(data) {
|
|
|
|
|
|
return data.text;
|
|
|
|
|
|
}
|
2025-12-11 15:18:47 +09:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$(select).on('select2:select select2:clear', function(e) {
|
|
|
|
|
|
success($(select).val() || null);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
$(select).on('select2:close', function(e) {
|
|
|
|
|
|
// 포커스 잃었을 때 처리
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Select2 열기
|
|
|
|
|
|
$(select).select2('open');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return container;
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-17 17:29:04 +09:00
|
|
|
|
// Tabulator 그리드 초기화
|
|
|
|
|
|
function fn_initGrid() {
|
|
|
|
|
|
var maxLevel = ${empty MAXLEV ? 1 : MAXLEV};
|
|
|
|
|
|
|
|
|
|
|
|
// 컬럼 정의
|
|
|
|
|
|
var columns = [];
|
|
|
|
|
|
|
2025-11-18 14:37:36 +09:00
|
|
|
|
// 라디오 버튼 컬럼 (E-BOM과 동일)
|
|
|
|
|
|
columns.push({
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
width: 40,
|
2025-11-18 14:37:36 +09:00
|
|
|
|
title: '선택',
|
|
|
|
|
|
field: 'RADIO',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
frozen: true,
|
2025-11-18 14:37:36 +09:00
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var rowData = cell.getData();
|
|
|
|
|
|
return '<input type="radio" name="checkedPartNo" value="' + (rowData.CHILD_OBJID || '') + '" ' +
|
|
|
|
|
|
'data-OBJID="' + (rowData.OBJID || '') + '" ' +
|
|
|
|
|
|
'data-PART_NO="' + (rowData.PART_NO || '') + '" ' +
|
|
|
|
|
|
'data-PARENT_PART_NO="' + (rowData.PARENT_PART_NO || '') + '" ' +
|
|
|
|
|
|
'data-PART_NO_QTY="' + (rowData.LAST_PART_OBJID || '') + '" ' +
|
|
|
|
|
|
'data-PARENT_PARTS="' + (rowData.PARENT_PARTS || '') + '" ' +
|
|
|
|
|
|
'data-LAST_PART_OBJID="' + (rowData.LAST_PART_OBJID || rowData.BOM_LAST_PART_OBJID || '') + '" ' +
|
|
|
|
|
|
'data-PARENT_OBJID="' + (rowData.PARENT_OBJID || '') + '" ' +
|
|
|
|
|
|
'data-PART_OBJID="' + (rowData.PART_OBJID || '') + '" ' +
|
|
|
|
|
|
'data-BOM_LAST_PART_OBJID="' + (rowData.BOM_LAST_PART_OBJID || rowData.LAST_PART_OBJID || '') + '" ' +
|
2025-11-25 13:10:30 +09:00
|
|
|
|
'data-CHILD_OBJID="' + (rowData.CHILD_OBJID || '') + '" ' +
|
|
|
|
|
|
'data-LEVEL="' + (rowData.LEVEL || 1) + '" ' +
|
|
|
|
|
|
'data-PART_NO="' + (rowData.PART_NO || '') + '">';
|
2025-11-18 14:37:36 +09:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-17 17:29:04 +09:00
|
|
|
|
// 수준 컬럼 그룹
|
|
|
|
|
|
var levelColumns = [];
|
|
|
|
|
|
for(var i = 1; i <= maxLevel; i++) {
|
|
|
|
|
|
levelColumns.push({
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
2026-01-15 14:40:26 +09:00
|
|
|
|
width: 25,
|
|
|
|
|
|
minWidth: 25,
|
|
|
|
|
|
maxWidth: 25,
|
2025-11-17 17:29:04 +09:00
|
|
|
|
title: i,
|
|
|
|
|
|
field: 'LEVEL_' + i,
|
|
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
return cell.getValue() === '*' ? '*' : '';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
columns.push({
|
|
|
|
|
|
title: '수준',
|
|
|
|
|
|
headerHozAlign: 'center',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
frozen: true,
|
2025-11-17 17:29:04 +09:00
|
|
|
|
columns: levelColumns
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-18 14:37:36 +09:00
|
|
|
|
// 기본 정보 컬럼들 (E-BOM 정보)
|
2025-11-17 17:29:04 +09:00
|
|
|
|
columns.push(
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
widthGrow: 2,
|
2025-11-17 17:29:04 +09:00
|
|
|
|
title: '품번',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
field: 'PART_NO',
|
|
|
|
|
|
frozen: true
|
2025-11-17 17:29:04 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
widthGrow: 3,
|
2025-11-17 17:29:04 +09:00
|
|
|
|
title: '품명',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
field: 'PART_NAME',
|
|
|
|
|
|
frozen: true
|
2025-11-17 17:29:04 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
2026-01-15 14:40:26 +09:00
|
|
|
|
width: 50,
|
2025-11-17 17:29:04 +09:00
|
|
|
|
title: '수량',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
field: 'QTY_TEMP',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true
|
2025-11-17 17:29:04 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
width: 80,
|
2025-11-17 17:29:04 +09:00
|
|
|
|
title: '항목 수량',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
field: 'ITEM_QTY',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true
|
2025-11-17 17:29:04 +09:00
|
|
|
|
},
|
2025-11-18 14:37:36 +09:00
|
|
|
|
/* 주석처리: Rev, 규격, 제품구분, 상태 컬럼
|
2025-11-17 17:29:04 +09:00
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
|
|
|
|
|
width: 80,
|
|
|
|
|
|
title: 'Rev',
|
|
|
|
|
|
field: 'REVISION'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 150,
|
|
|
|
|
|
title: '규격',
|
|
|
|
|
|
field: 'SPEC'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '제품구분',
|
|
|
|
|
|
field: 'PRODUCT_NAME'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '상태',
|
|
|
|
|
|
field: 'STATUS_NAME'
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
|
|
|
|
|
*/
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
2026-01-15 14:40:26 +09:00
|
|
|
|
width: 50,
|
2025-11-18 14:37:36 +09:00
|
|
|
|
title: '3D',
|
|
|
|
|
|
field: 'CU01_CNT',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true,
|
2025-11-18 14:37:36 +09:00
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var value = cell.getValue();
|
|
|
|
|
|
return value && value > 0 ? '<span class="file_icon"></span>' : '<span class="file_empty_icon"></span>';
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
2026-01-15 14:40:26 +09:00
|
|
|
|
width: 50,
|
2025-11-18 14:37:36 +09:00
|
|
|
|
title: '2D',
|
|
|
|
|
|
field: 'CU02_CNT',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true,
|
2025-11-18 14:37:36 +09:00
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var value = cell.getValue();
|
|
|
|
|
|
return value && value > 0 ? '<span class="file_icon"></span>' : '<span class="file_empty_icon"></span>';
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
|
|
|
|
|
width: 60,
|
|
|
|
|
|
title: 'PDF',
|
|
|
|
|
|
field: 'CU03_CNT',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true,
|
2025-11-18 14:37:36 +09:00
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var value = cell.getValue();
|
|
|
|
|
|
return value && value > 0 ? '<span class="file_icon"></span>' : '<span class="file_empty_icon"></span>';
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '재료',
|
|
|
|
|
|
field: 'MATERIAL',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 120,
|
|
|
|
|
|
title: '열처리경도',
|
|
|
|
|
|
field: 'HEAT_TREATMENT_HARDNESS',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 120,
|
|
|
|
|
|
title: '열처리방법',
|
|
|
|
|
|
field: 'HEAT_TREATMENT_METHOD',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '표면처리',
|
|
|
|
|
|
field: 'SURFACE_TREATMENT',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
visible: true
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 150,
|
2025-11-24 18:47:21 +09:00
|
|
|
|
title: '메이커',
|
|
|
|
|
|
field: 'MAKER',
|
|
|
|
|
|
visible: true
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '범주이름',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
field: 'PART_TYPE_TITLE',
|
|
|
|
|
|
visible: true
|
2025-11-17 17:29:04 +09:00
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2025-11-18 14:37:36 +09:00
|
|
|
|
// 생산관리 컬럼 그룹
|
|
|
|
|
|
columns.push({
|
|
|
|
|
|
title: '생산관리',
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
columns: [
|
2025-12-11 15:18:47 +09:00
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
2026-01-15 14:40:26 +09:00
|
|
|
|
width: 70,
|
2025-12-11 15:18:47 +09:00
|
|
|
|
title: '자급/사급',
|
|
|
|
|
|
field: 'SUPPLY_TYPE',
|
|
|
|
|
|
titleFormatter: function() { return '<span class="editable-header">자급/사급</span>'; },
|
|
|
|
|
|
editor: createSelect2Editor([{id: '자급', text: '자급'}, {id: '사급', text: '사급'}]),
|
|
|
|
|
|
cellEdited: function(cell) {
|
|
|
|
|
|
var row = cell.getRow();
|
|
|
|
|
|
var data = row.getData();
|
|
|
|
|
|
// 자급 선택 시 소재 관련 필드 초기화 (null로 설정하여 DB에서 NULL 처리)
|
|
|
|
|
|
if(data.SUPPLY_TYPE === '자급') {
|
|
|
|
|
|
row.update({
|
|
|
|
|
|
RAW_MATERIAL: null,
|
|
|
|
|
|
SIZE: null,
|
|
|
|
|
|
RAW_MATERIAL_NO: null,
|
|
|
|
|
|
REQUIRED_QTY: null
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 사급 선택 시 초기화
|
2025-11-26 17:18:31 +09:00
|
|
|
|
row.update({
|
2025-12-11 15:18:47 +09:00
|
|
|
|
RAW_MATERIAL: null,
|
|
|
|
|
|
SIZE: null,
|
|
|
|
|
|
RAW_MATERIAL_NO: null,
|
|
|
|
|
|
REQUIRED_QTY: null
|
2025-11-26 17:18:31 +09:00
|
|
|
|
});
|
2025-11-18 14:37:36 +09:00
|
|
|
|
}
|
2025-12-11 15:18:47 +09:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '소재',
|
|
|
|
|
|
field: 'RAW_MATERIAL',
|
|
|
|
|
|
titleFormatter: function() { return '<span class="editable-header">소재</span>'; },
|
|
|
|
|
|
editor: function(cell, onRendered, success, cancel, editorParams) {
|
|
|
|
|
|
// 소재 목록을 Select2용 형태로 변환
|
|
|
|
|
|
var options = materialList.map(function(m) { return {id: m, text: m}; });
|
|
|
|
|
|
return createSelect2Editor(options)(cell, onRendered, success, cancel, editorParams);
|
|
|
|
|
|
},
|
|
|
|
|
|
editable: function(cell) {
|
|
|
|
|
|
return cell.getRow().getData().SUPPLY_TYPE === '사급';
|
|
|
|
|
|
},
|
|
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var data = cell.getRow().getData();
|
|
|
|
|
|
if(data.SUPPLY_TYPE === '자급') return '-';
|
|
|
|
|
|
return cell.getValue() || '';
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
2025-12-11 15:18:47 +09:00
|
|
|
|
cellEdited: function(cell) {
|
|
|
|
|
|
// 소재 선택 시 사이즈 초기화
|
|
|
|
|
|
var row = cell.getRow();
|
|
|
|
|
|
row.update({
|
|
|
|
|
|
SIZE: '',
|
|
|
|
|
|
RAW_MATERIAL_NO: ''
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-11-18 14:37:36 +09:00
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '사이즈',
|
|
|
|
|
|
field: 'SIZE',
|
2025-12-02 15:10:41 +09:00
|
|
|
|
titleFormatter: function() { return '<span class="editable-header">사이즈</span>'; },
|
2025-12-11 15:18:47 +09:00
|
|
|
|
editor: function(cell, onRendered, success, cancel, editorParams) {
|
2025-11-26 17:18:31 +09:00
|
|
|
|
// 선택된 소재에 따라 동적으로 사이즈 목록 로드
|
|
|
|
|
|
var data = cell.getRow().getData();
|
|
|
|
|
|
var materialCode = data.RAW_MATERIAL;
|
|
|
|
|
|
|
|
|
|
|
|
if(!materialCode) {
|
2025-12-11 15:18:47 +09:00
|
|
|
|
cancel();
|
|
|
|
|
|
return;
|
2025-11-26 17:18:31 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 서버에서 해당 소재의 사이즈 목록 가져오기
|
|
|
|
|
|
var sizes = [];
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: '/admin/getMaterialSizes.do',
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
data: {materialCode: materialCode},
|
|
|
|
|
|
async: false,
|
|
|
|
|
|
success: function(response) {
|
|
|
|
|
|
if(response && response.list) {
|
|
|
|
|
|
sizes = response.list.map(function(item) {
|
2025-12-11 15:18:47 +09:00
|
|
|
|
return {id: item.SIZE_SPEC, text: item.SIZE_SPEC};
|
2025-11-26 17:18:31 +09:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-12-11 15:18:47 +09:00
|
|
|
|
return createSelect2Editor(sizes)(cell, onRendered, success, cancel, editorParams);
|
2025-11-24 18:47:21 +09:00
|
|
|
|
},
|
|
|
|
|
|
editable: function(cell) {
|
2025-11-26 17:18:31 +09:00
|
|
|
|
var data = cell.getRow().getData();
|
|
|
|
|
|
return data.SUPPLY_TYPE === '사급' && data.RAW_MATERIAL;
|
2025-11-24 18:47:21 +09:00
|
|
|
|
},
|
2025-11-18 14:37:36 +09:00
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var data = cell.getRow().getData();
|
2025-11-24 18:47:21 +09:00
|
|
|
|
if(data.SUPPLY_TYPE === '자급') return '-';
|
|
|
|
|
|
return cell.getValue() || '';
|
|
|
|
|
|
},
|
|
|
|
|
|
cellEdited: function(cell) {
|
2025-11-26 17:18:31 +09:00
|
|
|
|
// 사이즈 선택 시 소재품번 자동 조회
|
2025-11-24 18:47:21 +09:00
|
|
|
|
var row = cell.getRow();
|
|
|
|
|
|
var data = row.getData();
|
2025-11-26 17:18:31 +09:00
|
|
|
|
|
2025-11-24 18:47:21 +09:00
|
|
|
|
if(data.RAW_MATERIAL && data.SIZE) {
|
2025-11-26 17:18:31 +09:00
|
|
|
|
// 서버에서 소재품번 조회
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: '/admin/getMaterialPartNo.do',
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
data: {
|
|
|
|
|
|
materialCode: data.RAW_MATERIAL,
|
|
|
|
|
|
sizeSpec: data.SIZE
|
|
|
|
|
|
},
|
|
|
|
|
|
success: function(response) {
|
|
|
|
|
|
if(response && response.MATERIAL_PART_NO) {
|
|
|
|
|
|
row.update({RAW_MATERIAL_NO: response.MATERIAL_PART_NO});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-11-24 18:47:21 +09:00
|
|
|
|
}
|
2025-11-18 14:37:36 +09:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
width: 120,
|
|
|
|
|
|
title: '소재품번',
|
|
|
|
|
|
field: 'RAW_MATERIAL_NO',
|
|
|
|
|
|
editor: false,
|
|
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var data = cell.getRow().getData();
|
|
|
|
|
|
if(data.SUPPLY_TYPE === '자급') return '-';
|
|
|
|
|
|
return cell.getValue() || '';
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'right',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
width: 100,
|
2025-11-24 18:47:21 +09:00
|
|
|
|
title: '소재소요량',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
field: 'REQUIRED_QTY',
|
2025-12-02 15:10:41 +09:00
|
|
|
|
titleFormatter: function() { return '<span class="editable-header">소재소요량</span>'; },
|
2025-11-24 18:47:21 +09:00
|
|
|
|
editor: 'number',
|
|
|
|
|
|
editorParams: {
|
|
|
|
|
|
min: 0,
|
|
|
|
|
|
step: 0.01 // 소수 가능
|
|
|
|
|
|
},
|
|
|
|
|
|
editable: function(cell) {
|
|
|
|
|
|
return cell.getRow().getData().SUPPLY_TYPE === '사급';
|
|
|
|
|
|
},
|
|
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var data = cell.getRow().getData();
|
|
|
|
|
|
if(data.SUPPLY_TYPE === '자급') return '-';
|
|
|
|
|
|
var value = cell.getValue();
|
|
|
|
|
|
return value ? Number(value).toLocaleString() : '0';
|
|
|
|
|
|
}
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
hozAlign: 'right',
|
|
|
|
|
|
width: 120,
|
|
|
|
|
|
title: '소재발주수량',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
field: 'ORDER_QTY',
|
|
|
|
|
|
editor: false,
|
|
|
|
|
|
formatter: function(cell) {
|
2025-11-24 18:47:21 +09:00
|
|
|
|
// 항목수량 × 프로젝트 수주수량 (수정 불가)
|
|
|
|
|
|
var data = cell.getRow().getData();
|
|
|
|
|
|
var itemQty = parseFloat(data.ITEM_QTY) || 0;
|
|
|
|
|
|
var orderQty = itemQty * projectQuantity;
|
2025-11-25 18:30:44 +09:00
|
|
|
|
|
|
|
|
|
|
// 실제 데이터에도 저장 (getMbomTreeData에서 사용)
|
|
|
|
|
|
cell.getRow().update({ORDER_QTY: orderQty}, false);
|
|
|
|
|
|
|
2025-11-24 18:47:21 +09:00
|
|
|
|
return orderQty.toLocaleString();
|
2025-11-18 14:37:36 +09:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
hozAlign: 'right',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
width: 80,
|
2025-11-24 18:47:21 +09:00
|
|
|
|
title: '항목수량',
|
|
|
|
|
|
field: 'ITEM_QTY',
|
|
|
|
|
|
editor: false,
|
|
|
|
|
|
visible: true
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
hozAlign: 'right',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '제작수량',
|
|
|
|
|
|
field: 'PRODUCTION_QTY',
|
2025-12-02 15:10:41 +09:00
|
|
|
|
titleFormatter: function() { return '<span class="editable-header">제작수량</span>'; },
|
2025-11-18 14:37:36 +09:00
|
|
|
|
editor: 'number',
|
|
|
|
|
|
editorParams: {
|
|
|
|
|
|
min: 0,
|
|
|
|
|
|
step: 1
|
2025-11-24 18:47:21 +09:00
|
|
|
|
},
|
|
|
|
|
|
formatter: function(cell) {
|
2025-11-26 11:58:52 +09:00
|
|
|
|
// 저장된 값이 있으면 그대로 사용, 없으면 항목수량 × 수주수량으로 계산
|
2025-11-24 18:47:21 +09:00
|
|
|
|
var value = cell.getValue();
|
2025-11-25 18:30:44 +09:00
|
|
|
|
|
|
|
|
|
|
if(value === undefined || value === null || value === '' || value === 0) {
|
2025-11-24 18:47:21 +09:00
|
|
|
|
var data = cell.getRow().getData();
|
2025-11-26 11:58:52 +09:00
|
|
|
|
var itemQty = parseFloat(data.ITEM_QTY) || 0;
|
|
|
|
|
|
value = itemQty * projectQuantity;
|
2025-11-25 18:30:44 +09:00
|
|
|
|
|
|
|
|
|
|
// 실제 데이터에도 저장 (getMbomTreeData에서 사용)
|
|
|
|
|
|
cell.getRow().update({PRODUCTION_QTY: value}, false);
|
2025-11-24 18:47:21 +09:00
|
|
|
|
}
|
|
|
|
|
|
return Number(value).toLocaleString();
|
2025-11-18 14:37:36 +09:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-12-11 15:18:47 +09:00
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 150,
|
|
|
|
|
|
title: '가공업체',
|
|
|
|
|
|
field: 'PROCESSING_VENDOR',
|
|
|
|
|
|
titleFormatter: function() { return '<span class="editable-header">가공업체</span>'; },
|
|
|
|
|
|
editor: function(cell, onRendered, success, cancel, editorParams) {
|
|
|
|
|
|
// 가공업체 목록 Select2 에디터
|
|
|
|
|
|
return createSelect2Editor(supplyVendorList)(cell, onRendered, success, cancel, editorParams);
|
2025-12-12 15:09:58 +09:00
|
|
|
|
},
|
|
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var value = cell.getValue();
|
|
|
|
|
|
|
|
|
|
|
|
// 저장된 값이 없으면 기본값 '5001'(RPS) 설정
|
|
|
|
|
|
if(value === undefined || value === null || value === '') {
|
|
|
|
|
|
value = '5001';
|
|
|
|
|
|
cell.getRow().update({PROCESSING_VENDOR: value}, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// OBJID로 업체명 조회하여 표시
|
|
|
|
|
|
for(var i = 0; i < supplyVendorList.length; i++) {
|
|
|
|
|
|
if(supplyVendorList[i].id == value) {
|
|
|
|
|
|
return supplyVendorList[i].text;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return value;
|
2025-12-11 15:18:47 +09:00
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-12-09 15:15:19 +09:00
|
|
|
|
/* 주석처리: 가공납기, 연삭납기 컬럼
|
2025-11-18 14:37:36 +09:00
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '가공납기',
|
|
|
|
|
|
field: 'PROCESSING_DEADLINE',
|
2025-12-02 15:10:41 +09:00
|
|
|
|
titleFormatter: function() { return '<span class="editable-header">가공납기</span>'; },
|
2025-11-18 14:37:36 +09:00
|
|
|
|
editor: 'date'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'center',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '연삭납기',
|
|
|
|
|
|
field: 'GRINDING_DEADLINE',
|
2025-12-02 15:10:41 +09:00
|
|
|
|
titleFormatter: function() { return '<span class="editable-header">연삭납기</span>'; },
|
2025-11-18 14:37:36 +09:00
|
|
|
|
editor: 'date'
|
|
|
|
|
|
},
|
2025-12-09 15:15:19 +09:00
|
|
|
|
*/
|
2025-11-18 14:37:36 +09:00
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'left',
|
|
|
|
|
|
width: 150,
|
|
|
|
|
|
title: '공급업체',
|
2025-11-27 14:52:51 +09:00
|
|
|
|
field: 'VENDOR_NAME',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
editor: false, // 구매쪽에서 입력
|
|
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
return cell.getValue() || '-';
|
|
|
|
|
|
}
|
2025-11-18 14:37:36 +09:00
|
|
|
|
},
|
2025-11-27 18:39:18 +09:00
|
|
|
|
// 숨김 컬럼: 공급업체 코드 (저장 시 필요)
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'VENDOR',
|
|
|
|
|
|
visible: false
|
|
|
|
|
|
},
|
|
|
|
|
|
// 숨김 컬럼: 품의서 작성일 (저장 시 기존 값 유지)
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'PROPOSAL_DATE',
|
|
|
|
|
|
visible: false
|
|
|
|
|
|
},
|
|
|
|
|
|
// 숨김 컬럼: 순수량 (저장 시 기존 값 유지)
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'NET_QTY',
|
|
|
|
|
|
visible: false
|
|
|
|
|
|
},
|
|
|
|
|
|
// 숨김 컬럼: 발주수량 (저장 시 기존 값 유지)
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'PO_QTY',
|
|
|
|
|
|
visible: false
|
|
|
|
|
|
},
|
2025-11-18 14:37:36 +09:00
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'right',
|
|
|
|
|
|
width: 100,
|
|
|
|
|
|
title: '단가',
|
|
|
|
|
|
field: 'UNIT_PRICE',
|
2025-11-24 18:47:21 +09:00
|
|
|
|
editor: false, // 구매쪽에서 입력
|
2025-11-18 14:37:36 +09:00
|
|
|
|
formatter: function(cell) {
|
|
|
|
|
|
var value = cell.getValue();
|
2025-11-24 18:47:21 +09:00
|
|
|
|
return value ? Number(value).toLocaleString() : '-';
|
2025-11-18 14:37:36 +09:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
headerHozAlign: 'center',
|
|
|
|
|
|
hozAlign: 'right',
|
|
|
|
|
|
width: 100,
|
2025-11-24 18:47:21 +09:00
|
|
|
|
title: '금액',
|
2025-11-18 14:37:36 +09:00
|
|
|
|
field: 'TOTAL_PRICE',
|
|
|
|
|
|
editor: false,
|
|
|
|
|
|
formatter: function(cell) {
|
2025-11-24 18:47:21 +09:00
|
|
|
|
// 항목수량 × 단가
|
2025-11-18 14:37:36 +09:00
|
|
|
|
var data = cell.getRow().getData();
|
2025-11-24 18:47:21 +09:00
|
|
|
|
var itemQty = parseFloat(data.ITEM_QTY) || 0;
|
2025-11-18 14:37:36 +09:00
|
|
|
|
var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
|
2025-11-24 18:47:21 +09:00
|
|
|
|
var totalPrice = itemQty * unitPrice;
|
|
|
|
|
|
return totalPrice > 0 ? totalPrice.toLocaleString() : '-';
|
2025-11-18 14:37:36 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-24 18:47:21 +09:00
|
|
|
|
// 구매 컬럼 그룹 (제작수량 기준)
|
|
|
|
|
|
// columns.push({
|
|
|
|
|
|
// title: '구매',
|
|
|
|
|
|
// headerHozAlign: 'center',
|
|
|
|
|
|
// columns: [
|
|
|
|
|
|
// {
|
|
|
|
|
|
// headerHozAlign: 'center',
|
|
|
|
|
|
// hozAlign: 'left',
|
|
|
|
|
|
// width: 150,
|
|
|
|
|
|
// title: '소재품번',
|
|
|
|
|
|
// field: 'MATERIAL_PART_NO',
|
|
|
|
|
|
// editor: 'input'
|
|
|
|
|
|
// },
|
|
|
|
|
|
// {
|
|
|
|
|
|
// headerHozAlign: 'center',
|
|
|
|
|
|
// hozAlign: 'center',
|
|
|
|
|
|
// width: 100,
|
|
|
|
|
|
// title: '정미수량',
|
|
|
|
|
|
// field: 'NET_QTY',
|
|
|
|
|
|
// editor: false,
|
|
|
|
|
|
// formatter: function(cell) {
|
|
|
|
|
|
// // 소요량 × 제작수량 (소수점 무조건 올림)
|
|
|
|
|
|
// var data = cell.getRow().getData();
|
|
|
|
|
|
// var requiredQty = parseFloat(data.REQUIRED_QTY) || 0;
|
|
|
|
|
|
// var productionQty = parseFloat(data.PRODUCTION_QTY) || 0;
|
|
|
|
|
|
// var netQty = requiredQty * productionQty;
|
|
|
|
|
|
// return Math.ceil(netQty); // 무조건 올림
|
|
|
|
|
|
// }
|
|
|
|
|
|
// },
|
|
|
|
|
|
// {
|
|
|
|
|
|
// headerHozAlign: 'center',
|
|
|
|
|
|
// hozAlign: 'center',
|
|
|
|
|
|
// width: 100,
|
|
|
|
|
|
// title: '발주수량',
|
|
|
|
|
|
// field: 'PO_QTY',
|
|
|
|
|
|
// editor: 'number',
|
|
|
|
|
|
// editorParams: {
|
|
|
|
|
|
// min: 0,
|
|
|
|
|
|
// step: 1
|
|
|
|
|
|
// }
|
|
|
|
|
|
// },
|
|
|
|
|
|
// {
|
|
|
|
|
|
// headerHozAlign: 'center',
|
|
|
|
|
|
// hozAlign: 'left',
|
|
|
|
|
|
// width: 150,
|
|
|
|
|
|
// title: '공급업체',
|
|
|
|
|
|
// field: 'VENDOR',
|
|
|
|
|
|
// editor: 'input'
|
|
|
|
|
|
// },
|
|
|
|
|
|
// {
|
|
|
|
|
|
// headerHozAlign: 'center',
|
|
|
|
|
|
// hozAlign: 'right',
|
|
|
|
|
|
// width: 100,
|
|
|
|
|
|
// title: '단가',
|
|
|
|
|
|
// field: 'UNIT_PRICE',
|
|
|
|
|
|
// editor: 'number',
|
|
|
|
|
|
// editorParams: {
|
|
|
|
|
|
// min: 0,
|
|
|
|
|
|
// step: 0.01
|
|
|
|
|
|
// },
|
|
|
|
|
|
// formatter: function(cell) {
|
|
|
|
|
|
// var value = cell.getValue();
|
|
|
|
|
|
// return value ? Number(value).toLocaleString() : '0';
|
|
|
|
|
|
// }
|
|
|
|
|
|
// },
|
|
|
|
|
|
// {
|
|
|
|
|
|
// headerHozAlign: 'center',
|
|
|
|
|
|
// hozAlign: 'right',
|
|
|
|
|
|
// width: 100,
|
|
|
|
|
|
// title: '총단가',
|
|
|
|
|
|
// field: 'TOTAL_PRICE',
|
|
|
|
|
|
// editor: false,
|
|
|
|
|
|
// formatter: function(cell) {
|
|
|
|
|
|
// // 발주수량 × 단가
|
|
|
|
|
|
// var data = cell.getRow().getData();
|
|
|
|
|
|
// var poQty = parseFloat(data.PO_QTY) || 0;
|
|
|
|
|
|
// var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
|
|
|
|
|
|
// var totalPrice = poQty * unitPrice;
|
|
|
|
|
|
// return totalPrice.toLocaleString();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// ]
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
2025-11-18 14:37:36 +09:00
|
|
|
|
// 서버에서 전달받은 데이터 확인
|
|
|
|
|
|
var bomTreeData = ${bomTreeListJson};
|
|
|
|
|
|
console.log("bomTreeData:", bomTreeData);
|
|
|
|
|
|
console.log("bomTreeData length:", bomTreeData ? bomTreeData.length : 0);
|
|
|
|
|
|
|
2025-11-24 18:47:21 +09:00
|
|
|
|
// 데이터 전처리: SUPPLY_TYPE 기본값 설정
|
|
|
|
|
|
if(bomTreeData && bomTreeData.length > 0) {
|
|
|
|
|
|
bomTreeData.forEach(function(row) {
|
|
|
|
|
|
// SUPPLY_TYPE이 없으면 '사급'으로 설정
|
|
|
|
|
|
if(!row.SUPPLY_TYPE) {
|
|
|
|
|
|
row.SUPPLY_TYPE = '사급';
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 모든 컬럼에 headerSort: false 일괄 적용
|
|
|
|
|
|
columns.forEach(function(col) {
|
|
|
|
|
|
col.headerSort = false;
|
|
|
|
|
|
// 중첩된 컬럼이 있는 경우 (수준 컬럼 등)
|
|
|
|
|
|
if(col.columns) {
|
|
|
|
|
|
col.columns.forEach(function(subCol) {
|
|
|
|
|
|
subCol.headerSort = false;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-17 17:29:04 +09:00
|
|
|
|
// Tabulator 생성
|
|
|
|
|
|
_tabulGrid = new Tabulator("#mBomTableWrap", {
|
2025-11-18 14:37:36 +09:00
|
|
|
|
layout: "fitData",
|
2025-11-25 15:15:20 +09:00
|
|
|
|
height: "calc(100vh - 70px)",
|
2025-11-17 17:29:04 +09:00
|
|
|
|
columns: columns,
|
2025-11-18 14:37:36 +09:00
|
|
|
|
data: bomTreeData,
|
2025-11-17 17:29:04 +09:00
|
|
|
|
rowFormatter: function(row) {
|
|
|
|
|
|
var data = row.getData();
|
|
|
|
|
|
var level = data.LEVEL || 1;
|
|
|
|
|
|
row.getElement().classList.add('level-' + level);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-11-18 14:37:36 +09:00
|
|
|
|
|
2026-01-15 14:40:26 +09:00
|
|
|
|
// 행 클릭 시 선택 처리 이벤트
|
|
|
|
|
|
_tabulGrid.on("rowClick", function(e, row) {
|
|
|
|
|
|
// 링크 클릭 시에는 기본 동작 유지
|
|
|
|
|
|
if($(e.target).is('a')) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 기존 선택 해제
|
|
|
|
|
|
$('.tabulator-row.row-selected').removeClass('row-selected');
|
|
|
|
|
|
$('input[name=checkedPartNo]').prop('checked', false);
|
|
|
|
|
|
|
|
|
|
|
|
// 현재 행 선택
|
|
|
|
|
|
$(row.getElement()).addClass('row-selected');
|
|
|
|
|
|
var rowData = row.getData();
|
|
|
|
|
|
selectedRowData = rowData;
|
|
|
|
|
|
|
|
|
|
|
|
// 해당 행의 라디오 버튼 선택
|
|
|
|
|
|
$(row.getElement()).find('input[name=checkedPartNo]').prop('checked', true);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-18 14:37:36 +09:00
|
|
|
|
// 셀 편집 이벤트 등록
|
|
|
|
|
|
_tabulGrid.on("cellEdited", function(cell) {
|
|
|
|
|
|
var field = cell.getField();
|
|
|
|
|
|
var row = cell.getRow();
|
|
|
|
|
|
var data = row.getData();
|
|
|
|
|
|
|
|
|
|
|
|
// 지급/사급 변경 시 소재, 사이즈, 소요량 필드 재계산
|
|
|
|
|
|
if(field === 'SUPPLY_TYPE') {
|
|
|
|
|
|
if(data.SUPPLY_TYPE === '자급') {
|
2025-12-11 15:18:47 +09:00
|
|
|
|
// 자급인 경우 소재, 사이즈, 소요량 초기화 (null로 설정)
|
2025-11-18 14:37:36 +09:00
|
|
|
|
row.update({
|
2025-12-11 15:18:47 +09:00
|
|
|
|
RAW_MATERIAL: null,
|
|
|
|
|
|
SIZE: null,
|
|
|
|
|
|
REQUIRED_QTY: null
|
2025-11-18 14:37:36 +09:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
// 행 전체 재렌더링
|
|
|
|
|
|
row.reformat();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 제작수량 변경 시 정미수량 자동 계산
|
|
|
|
|
|
if(field === 'PRODUCTION_QTY' || field === 'REQUIRED_QTY') {
|
|
|
|
|
|
var requiredQty = parseFloat(data.REQUIRED_QTY) || 0;
|
|
|
|
|
|
var productionQty = parseFloat(data.PRODUCTION_QTY) || 0;
|
|
|
|
|
|
var netQty = Math.ceil(requiredQty * productionQty);
|
|
|
|
|
|
row.update({NET_QTY: netQty});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 발주수량 또는 단가 변경 시 총단가 자동 계산
|
|
|
|
|
|
if(field === 'PO_QTY' || field === 'UNIT_PRICE') {
|
|
|
|
|
|
var poQty = parseFloat(data.PO_QTY) || 0;
|
|
|
|
|
|
var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
|
|
|
|
|
|
var totalPrice = poQty * unitPrice;
|
|
|
|
|
|
row.update({TOTAL_PRICE: totalPrice});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Q'ty 초기값 설정 (발주수량에서 가져오기)
|
|
|
|
|
|
if(field === 'ORDER_QTY' && !data.QTY) {
|
|
|
|
|
|
row.update({QTY: data.ORDER_QTY});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2025-11-17 17:29:04 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 필터 적용 함수
|
|
|
|
|
|
function fn_applyFilter() {
|
|
|
|
|
|
var partNo = $("#filterPartNo").val().trim();
|
|
|
|
|
|
var partName = $("#filterPartName").val().trim();
|
|
|
|
|
|
|
|
|
|
|
|
if(!partNo && !partName) {
|
|
|
|
|
|
_tabulGrid.clearFilter();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_tabulGrid.setFilter([
|
|
|
|
|
|
[
|
|
|
|
|
|
{field: "PART_NO", type: "like", value: partNo},
|
|
|
|
|
|
{field: "PART_NAME", type: "like", value: partName}
|
|
|
|
|
|
]
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 필터 초기화 함수
|
|
|
|
|
|
function fn_resetFilter() {
|
|
|
|
|
|
$("#filterPartNo").val("");
|
|
|
|
|
|
$("#filterPartName").val("");
|
|
|
|
|
|
_tabulGrid.clearFilter();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// M-BOM 조회 (헤더 프레임에서 호출)
|
|
|
|
|
|
function fn_searchMbom(searchParams) {
|
2025-11-18 14:37:36 +09:00
|
|
|
|
console.log("fn_searchMbom (left) 호출됨:", searchParams);
|
|
|
|
|
|
|
2025-11-17 17:29:04 +09:00
|
|
|
|
$.ajax({
|
|
|
|
|
|
url: "/productionplanning/getMbomList.do",
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data: searchParams,
|
|
|
|
|
|
dataType: 'json',
|
|
|
|
|
|
success: function(data) {
|
2025-11-18 14:37:36 +09:00
|
|
|
|
console.log("M-BOM 조회 결과:", data);
|
2025-11-17 17:29:04 +09:00
|
|
|
|
if(data && data.list) {
|
2025-11-18 14:37:36 +09:00
|
|
|
|
console.log("데이터 개수:", data.list.length);
|
2025-11-25 18:30:44 +09:00
|
|
|
|
|
|
|
|
|
|
// 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);
|
2025-11-17 17:29:04 +09:00
|
|
|
|
} else {
|
2025-11-18 14:37:36 +09:00
|
|
|
|
console.log("데이터 없음");
|
2025-11-17 17:29:04 +09:00
|
|
|
|
_tabulGrid.setData([]);
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
error: function(jqxhr, status, error){
|
|
|
|
|
|
console.error("M-BOM 조회 오류:", error);
|
2025-11-18 14:37:36 +09:00
|
|
|
|
console.error("응답:", jqxhr.responseText);
|
2025-11-17 17:29:04 +09:00
|
|
|
|
_tabulGrid.setData([]);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-09 15:15:19 +09:00
|
|
|
|
/* 주석처리: 가공납기/연삭납기 일괄 적용
|
2025-11-24 18:47:21 +09:00
|
|
|
|
function applyBulkDeadline(processingDeadline, grindingDeadline) {
|
|
|
|
|
|
if(!_tabulGrid) {
|
|
|
|
|
|
console.error("그리드가 초기화되지 않았습니다.");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log("일괄 적용 시작");
|
|
|
|
|
|
console.log("가공납기:", processingDeadline);
|
|
|
|
|
|
console.log("연삭납기:", grindingDeadline);
|
|
|
|
|
|
|
|
|
|
|
|
var allRows = _tabulGrid.getRows();
|
|
|
|
|
|
console.log("전체 행 수:", allRows.length);
|
|
|
|
|
|
|
|
|
|
|
|
var updatedCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
allRows.forEach(function(row) {
|
|
|
|
|
|
var updateData = {};
|
|
|
|
|
|
|
|
|
|
|
|
if(processingDeadline) {
|
|
|
|
|
|
updateData.PROCESSING_DEADLINE = processingDeadline;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(grindingDeadline) {
|
|
|
|
|
|
updateData.GRINDING_DEADLINE = grindingDeadline;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 행 직접 업데이트
|
|
|
|
|
|
row.update(updateData);
|
|
|
|
|
|
updatedCount++;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
console.log("업데이트 완료 - 업데이트된 행:", updatedCount);
|
|
|
|
|
|
return updatedCount;
|
|
|
|
|
|
}
|
2025-12-09 15:15:19 +09:00
|
|
|
|
*/
|
2025-11-24 18:47:21 +09:00
|
|
|
|
|
2026-01-15 14:40:26 +09:00
|
|
|
|
// 선택된 행 데이터 가져오기 (Center 프레임에서 사용)
|
|
|
|
|
|
function getSelectedRowData() {
|
|
|
|
|
|
return selectedRowData;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-17 17:29:04 +09:00
|
|
|
|
// M-BOM 트리 데이터 수집 (저장용)
|
|
|
|
|
|
function getMbomTreeData() {
|
|
|
|
|
|
var allData = _tabulGrid.getData();
|
|
|
|
|
|
|
2025-12-11 15:18:47 +09:00
|
|
|
|
// 숫자 변환 헬퍼 함수 (빈 문자열, '-', 숫자가 아닌 값 → null)
|
2025-11-24 18:47:21 +09:00
|
|
|
|
function toNumber(value) {
|
2025-12-11 15:18:47 +09:00
|
|
|
|
if (value === null || value === undefined || value === '' || value === '-') return null;
|
2025-11-24 18:47:21 +09:00
|
|
|
|
var num = parseFloat(value);
|
|
|
|
|
|
return isNaN(num) ? null : num;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-11 15:18:47 +09:00
|
|
|
|
// 문자열 변환 헬퍼 함수 ('-' → null)
|
|
|
|
|
|
function toString(value) {
|
|
|
|
|
|
if (value === null || value === undefined || value === '-') return null;
|
|
|
|
|
|
return value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 18:47:21 +09:00
|
|
|
|
// 데이터 구조 변환 (MBOM_DETAIL 테이블에 필요한 모든 필드 포함)
|
2025-11-17 17:29:04 +09:00
|
|
|
|
var mbomData = allData.map(function(row) {
|
|
|
|
|
|
return {
|
2025-11-24 18:47:21 +09:00
|
|
|
|
// BOM 구조 정보
|
|
|
|
|
|
parentObjid: row.PARENT_OBJID,
|
|
|
|
|
|
childObjid: row.CHILD_OBJID,
|
|
|
|
|
|
seq: row.SEQ,
|
|
|
|
|
|
level: row.LEVEL,
|
|
|
|
|
|
|
|
|
|
|
|
// 품목 정보
|
|
|
|
|
|
partObjid: row.PART_OBJID || row.LAST_PART_OBJID,
|
|
|
|
|
|
partNo: row.PART_NO,
|
|
|
|
|
|
partName: row.PART_NAME,
|
|
|
|
|
|
|
2025-12-11 15:18:47 +09:00
|
|
|
|
// 수량 정보
|
2025-11-24 18:47:21 +09:00
|
|
|
|
qty: toNumber(row.QTY_TEMP || row.QTY || row.ITEM_QTY),
|
|
|
|
|
|
unit: row.UNIT,
|
|
|
|
|
|
|
|
|
|
|
|
// 생산 정보
|
|
|
|
|
|
supplyType: row.SUPPLY_TYPE,
|
|
|
|
|
|
makeOrBuy: row.MAKE_OR_BUY,
|
2025-12-11 15:18:47 +09:00
|
|
|
|
rawMaterial: toString(row.RAW_MATERIAL), // 자급 시 '-' → null
|
|
|
|
|
|
rawMaterialSpec: toString(row.RAW_MATERIAL_SPEC),
|
|
|
|
|
|
rawMaterialSize: toString(row.SIZE), // 자급 시 '-' → null
|
|
|
|
|
|
rawMaterialPartNo: toString(row.RAW_MATERIAL_NO), // 자급 시 '-' → null
|
2025-11-24 18:47:21 +09:00
|
|
|
|
processingVendor: row.PROCESSING_VENDOR,
|
|
|
|
|
|
processingDeadline: row.PROCESSING_DEADLINE,
|
|
|
|
|
|
grindingDeadline: row.GRINDING_DEADLINE,
|
2025-12-11 15:18:47 +09:00
|
|
|
|
requiredQty: toNumber(row.REQUIRED_QTY), // 자급 시 '-' → null
|
|
|
|
|
|
orderQty: toNumber(row.ORDER_QTY),
|
|
|
|
|
|
productionQty: toNumber(row.PRODUCTION_QTY),
|
|
|
|
|
|
stockQty: toNumber(row.STOCK_QTY),
|
|
|
|
|
|
shortageQty: toNumber(row.SHORTAGE_QTY),
|
2025-11-24 18:47:21 +09:00
|
|
|
|
|
|
|
|
|
|
// 구매 정보
|
2025-11-27 18:39:18 +09:00
|
|
|
|
vendor: row.VENDOR || row.VENDOR_PM, // 공급업체 코드/OBJID (기존 값 유지)
|
2025-12-11 15:18:47 +09:00
|
|
|
|
unitPrice: toNumber(row.UNIT_PRICE),
|
2025-11-28 18:38:23 +09:00
|
|
|
|
// totalPrice 계산: 항목수량 × 단가
|
|
|
|
|
|
totalPrice: (function() {
|
|
|
|
|
|
var itemQty = parseFloat(row.ITEM_QTY) || 0;
|
|
|
|
|
|
var unitPrice = parseFloat(row.UNIT_PRICE) || 0;
|
|
|
|
|
|
return itemQty * unitPrice;
|
|
|
|
|
|
})(),
|
2025-11-24 18:47:21 +09:00
|
|
|
|
currency: row.CURRENCY,
|
2025-12-11 15:18:47 +09:00
|
|
|
|
leadTime: toNumber(row.LEAD_TIME),
|
|
|
|
|
|
minOrderQty: toNumber(row.MIN_ORDER_QTY),
|
|
|
|
|
|
netQty: toNumber(row.NET_QTY), // 순수량
|
|
|
|
|
|
poQty: toNumber(row.PO_QTY), // 발주수량
|
2025-11-27 18:39:18 +09:00
|
|
|
|
proposalDate: row.PROPOSAL_DATE, // 품의서 작성일 (기존 값 유지)
|
2025-11-24 18:47:21 +09:00
|
|
|
|
|
|
|
|
|
|
// 기타
|
|
|
|
|
|
status: row.STATUS,
|
|
|
|
|
|
remark: row.REMARK,
|
|
|
|
|
|
revision: row.REVISION,
|
|
|
|
|
|
spec: row.SPEC,
|
|
|
|
|
|
writer: row.WRITER,
|
|
|
|
|
|
editer: row.EDITER,
|
|
|
|
|
|
objid: row.OBJID
|
2025-11-17 17:29:04 +09:00
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return mbomData;
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
2025-11-18 14:37:36 +09:00
|
|
|
|
<!-- <div id="mBomName">
|
2025-11-17 17:29:04 +09:00
|
|
|
|
<c:choose>
|
|
|
|
|
|
<c:when test="${not empty ebomInfo}">
|
|
|
|
|
|
E-BOM: ${ebomInfo.PART_NO} - ${ebomInfo.PART_NAME}
|
|
|
|
|
|
</c:when>
|
|
|
|
|
|
<c:otherwise>
|
|
|
|
|
|
할당된 E-BOM이 없습니다.
|
|
|
|
|
|
</c:otherwise>
|
|
|
|
|
|
</c:choose>
|
2025-11-18 14:37:36 +09:00
|
|
|
|
</div> -->
|
2025-11-17 17:29:04 +09:00
|
|
|
|
<div id="mBomTableWrap"></div>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|
|
|
|
|
|
|