Files
wace_plm/WebContent/WEB-INF/view/salesMng/purchaseListFormPopUp.jsp

1015 lines
28 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<%@ 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"%>
<c:set var="resolvedProjectId"
value="${not empty param.PROJECT_MGMT_OBJID and param.PROJECT_MGMT_OBJID ne 'null'
? param.PROJECT_MGMT_OBJID
: (not empty resultMap.PROJECT_MGMT_OBJID
? resultMap.PROJECT_MGMT_OBJID
: (not empty resultMap.PROJECT_NO ? resultMap.PROJECT_NO : ''))}" />
<c:set var="resolvedBomReportObjid"
value="${not empty param.BOM_REPORT_OBJID and param.BOM_REPORT_OBJID ne 'null'
? param.BOM_REPORT_OBJID
: (not empty resultMap.BOM_REPORT_OBJID ? resultMap.BOM_REPORT_OBJID : '')}" />
<%-- MBOM_HEADER.OBJID를 직접 사용 (M-BOM 관리 화면에서 사용하는 것과 동일) --%>
<c:set var="resolvedMbomHeaderObjid"
value="${not empty param.MBOM_HEADER_OBJID and param.MBOM_HEADER_OBJID ne 'null'
? param.MBOM_HEADER_OBJID
: (not empty resultMap.MBOM_HEADER_OBJID ? resultMap.MBOM_HEADER_OBJID : '')}" />
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><%=Constants.SYSTEM_NAME%></title>
<script type="text/javascript" src="/js/tabulator/tabulator_custom.js"></script>
<style>
body, html {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.header {
padding: 15px 20px;
background: #f5f5f5;
border-bottom: 2px solid #ddd;
text-align: right;
}
.header h3 {
margin: 0 0 10px 0;
color: #333;
}
.info-table {
width: 100%;
border-collapse: collapse;
background: #fff;
border: 1px solid #ddd;
}
.info-table td {
padding: 8px 15px;
border: 1px solid #eee;
}
.info-table label {
font-weight: bold;
color: #555;
margin-right: 8px;
}
.info-table span {
color: #333;
}
.content {
flex: 1;
padding: 20px;
overflow: auto;
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h3 style="margin: 0 0 10px 0; float: left;">구매리스트</h3>
<div style="float: right;">
<input type="button" value="저장" class="plm_btns" onclick="fn_save();" style="margin-right: 5px;">
<input type="button" value="닫기" class="plm_btns" onclick="window.close();" style="margin-right: 5px;">
</div>
<div style="clear: both;"></div>
<!-- 프로젝트 정보 -->
<table class="info-table" style="margin-top: 10px;">
<tr>
<td>
<label>프로젝트번호:</label>
<span id="infoProjectNo">${resultMap.PROJECT_NUMBER}</span>
</td>
<td>
<label>고객사:</label>
<span id="infoCustomer">${resultMap.CUSTOMER_NAME}</span>
</td>
<td>
<label>품번:</label>
<span id="infoPartNo">${resultMap.PART_NO}</span>
</td>
<td>
<label>품명:</label>
<span id="infoPartName">${resultMap.PART_NAME}</span>
</td>
</tr>
<tr>
<td>
<label>구매유형:</label>
<span id="infoPurchaseType">${resultMap.PURCHASE_TYPE_NAME}</span>
</td>
<td>
<label>요청번호:</label>
<span id="infoRequestNo">${resultMap.REQUEST_MNG_NO}</span>
</td>
<td>
<label>요청인:</label>
<span id="infoRequestUser">${resultMap.REQUEST_USER_NAME}</span>
</td>
<td>
<label>입고요청일:</label>
<span id="infoDeliveryDate">${resultMap.DUE_DATE}</span>
</td>
</tr>
</table>
</div>
<div class="content">
<div id="purchaseListTable"></div>
</div>
</div>
<script>
var _tabulGrid;
var salesRequestMasterObjid = "${param.SALES_REQUEST_MASTER_OBJID}";
var projectMgmtObjid = "${resolvedProjectId}";
var bomReportObjid = "${resolvedBomReportObjid}";
var mbomHeaderObjid = "${resolvedMbomHeaderObjid}"; // MBOM_HEADER.OBJID (M-BOM 관리 화면에서 사용하는 ID)
var vendorList = []; // 공급업체 목록
var processingVendorList = []; // 가공업체 목록 (Select2용 배열)
// 디버그: resultMap 내용 확인 (주석처리)
// console.log("=== JSP resultMap 디버그 ===");
// console.log("resultMap.PROJECT_MGMT_OBJID:", "${resultMap.PROJECT_MGMT_OBJID}");
// console.log("resultMap.BOM_REPORT_OBJID:", "${resultMap.BOM_REPORT_OBJID}");
// console.log("resultMap.MBOM_HEADER_OBJID:", "${resultMap.MBOM_HEADER_OBJID}");
// console.log("resultMap.PROJECT_NO:", "${resultMap.PROJECT_NO}");
// console.log("resolvedProjectId:", projectMgmtObjid);
// console.log("resolvedBomReportObjid:", bomReportObjid);
// console.log("resolvedMbomHeaderObjid:", mbomHeaderObjid);
function logDebug(){
if(window.console && typeof window.console.log === "function"){
console.log.apply(console, arguments);
}
}
function logError(){
if(window.console && typeof window.console.error === "function"){
console.error.apply(console, arguments);
}
}
$(document).ready(function(){
// 공급업체 목록 로드 (가공업체도 동일 테이블 사용)
fn_loadVendorList(function(){
// vendorList에서 processingVendorList 변환 (Select2용 배열 형태)
processingVendorList = [];
for(var key in vendorList) {
if(key !== '') { // 빈 값 제외
processingVendorList.push({id: key, text: vendorList[key]});
}
}
console.log("가공업체 목록 변환 완료:", processingVendorList.length + "개");
fn_initGrid();
logDebug("purchaseListFormPopUp :: grid initialized");
fn_loadInitialData();
});
});
// 공급업체 목록 로드 (일반거래처관리 CLIENT_MNG)
function fn_loadVendorList(callback) {
vendorList = {}; // 객체 형태로 변경
vendorList[''] = '선택'; // 빈 값
$.ajax({
url: "/admin/clientMngListPagingGridList.do",
method: 'post',
data: {
countPerPage: 9999
},
dataType: 'json',
success: function(data) {
if(data && data.RESULTLIST) {
data.RESULTLIST.forEach(function(item) {
var name = item.CLIENT_NM || '';
var objid = item.OBJID || '';
if(objid && name) {
vendorList[objid] = name;
}
});
}
console.log("공급업체 로드 완료:", Object.keys(vendorList).length + "개", vendorList);
if(callback) callback();
},
error: function(xhr, status, error) {
logError("공급업체 목록 로드 실패:", error);
if(callback) callback();
}
});
}
function fn_loadInitialData(){
logDebug("purchaseListFormPopUp :: fn_loadInitialData start",
"projectMgmtObjid=", projectMgmtObjid,
"mbomHeaderObjid=", mbomHeaderObjid,
"salesRequestMasterObjid=", salesRequestMasterObjid);
var hasProject = projectMgmtObjid && projectMgmtObjid !== "" && projectMgmtObjid !== "null";
var hasMbomHeader = mbomHeaderObjid && mbomHeaderObjid !== "" && mbomHeaderObjid !== "null";
var hasMaster = salesRequestMasterObjid && salesRequestMasterObjid !== "" && salesRequestMasterObjid !== "null";
// M-BOM에서 생성된 경우만 M-BOM 데이터를 로드 (MBOM_HEADER_OBJID가 있어야 함)
if(hasMbomHeader){
logDebug("purchaseListFormPopUp :: M-BOM에서 생성된 구매리스트 - MBOM 로드");
fn_loadFromMBom(function(mbomList){
if(hasMaster){
// M-BOM 데이터가 있으면 merge, 없으면 SALES_REQUEST_PART만 로드
var hasMbomData = mbomList && mbomList.length > 0;
logDebug("purchaseListFormPopUp :: MBOM data count:", mbomList ? mbomList.length : 0);
fn_loadPurchaseList(hasMbomData); // M-BOM 있으면 merge, 없으면 단독 로드
}
});
} else if(hasMaster){
logDebug("purchaseListFormPopUp :: 수동 작성된 구매리스트 - SALES_REQUEST_PART만 로드");
fn_loadPurchaseList(false);
} else {
logDebug("purchaseListFormPopUp :: no data to load");
}
}
// 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') {
option.value = opt.id || opt.value || '';
option.text = opt.text || opt.label || '';
} else {
option.value = opt;
option.text = opt;
}
if(option.value == cellValue) {
option.selected = true;
}
select.appendChild(option);
});
container.appendChild(select);
onRendered(function() {
$(select).select2({
width: '100%',
dropdownAutoWidth: true,
allowClear: true,
placeholder: '선택'
});
$(select).select2('open');
});
$(select).on('select2:select select2:clear', function(e) {
success($(select).val());
});
$(select).on('select2:close', function() {
setTimeout(function() {
success($(select).val());
}, 100);
});
return container;
};
}
// Tabulator 그리드 초기화
function fn_initGrid() {
var columns = [
// 1. 체크박스
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 40,
frozen: true,
title: '<input type="checkbox" id="checkAll">',
field: 'CHK',
formatter: function(cell) {
return '<input type="checkbox" class="rowCheck">';
},
headerSort: false
},
// 2. No
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 50,
title: 'No',
field: 'ROW_NUM',
formatter: "rownum",
frozen: true
},
// 2-1. 구분 (M-BOM / 수동)
// {
// headerHozAlign: 'center',
// hozAlign: 'center',
// width: 70,
// title: '구분',
// frozen: true,
// field: 'DATA_SOURCE',
// formatter: function(cell) {
// var value = cell.getValue();
// if(value === 'MBOM') {
// return '<span style="color: #2196F3; font-weight: bold;">M-BOM</span>';
// } else if(value === 'SRP') {
// return '<span style="color: #4CAF50; font-weight: bold;">수동</span>';
// }
// return value || '';
// }
// },
// 3. 품번
{
headerHozAlign: 'center',
hozAlign: 'left',
widthGrow: 2,
title: '품번',
field: 'PART_NO',
frozen: true
},
// 4. 품명
{
headerHozAlign: 'center',
hozAlign: 'left',
widthGrow: 3,
title: '품명',
field: 'PART_NAME',
frozen: true
},
// 5. 수량
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '수량',
field: 'QTY'
},
// 6. 항목 수량
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 80,
title: '항목 수량',
field: 'ITEM_QTY'
},
// 7. 3D
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '3D',
field: 'CU01_CNT',
formatter: function(cell) {
var value = cell.getValue();
return value && value > 0 ? '<span class="file_icon"></span>' : '<span class="file_empty_icon"></span>';
}
},
// 8. 2D
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: '2D',
field: 'CU02_CNT',
formatter: function(cell) {
var value = cell.getValue();
return value && value > 0 ? '<span class="file_icon"></span>' : '<span class="file_empty_icon"></span>';
}
},
// 9. PDF
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 60,
title: 'PDF',
field: 'CU03_CNT',
formatter: function(cell) {
var value = cell.getValue();
return value && value > 0 ? '<span class="file_icon"></span>' : '<span class="file_empty_icon"></span>';
}
},
// 10. 재료
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 100,
title: '재료',
field: 'MATERIAL'
},
// 11. 열처리경도
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 120,
title: '열처리경도',
field: 'HEAT_TREATMENT_HARDNESS'
},
// 12. 열처리방법
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 120,
title: '열처리방법',
field: 'HEAT_TREATMENT_METHOD'
},
// 13. 표면처리
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 100,
title: '표면처리',
field: 'SURFACE_TREATMENT'
},
// 14. 메이커
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 150,
title: '메이커',
field: 'VENDOR'
},
// 15. 범주 이름
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 100,
title: '범주 이름',
field: 'PART_TYPE_TITLE'
},
// 16. 지급/사급
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 100,
title: '지급/사급',
field: 'SUPPLY_TYPE'
},
// 20. 소재소요량
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '소재소요량',
field: 'REQUIRED_QTY',
formatter: function(cell) {
var value = cell.getValue();
return value ? Number(value).toLocaleString() : '0';
}
},
// 21. 소재발주수량
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 120,
title: '소재발주수량',
field: 'ORDER_QTY',
formatter: function(cell) {
var value = cell.getValue();
return value ? Number(value).toLocaleString() : '0';
}
},
// 22. 항목수량
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 80,
title: '항목수량',
field: 'ITEM_QTY'
},
// 23. 제작수량
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '제작수량',
field: 'PRODUCTION_QTY',
formatter: function(cell) {
var value = cell.getValue();
return value ? Number(value).toLocaleString() : '0';
}
},
// 17. 소재 -> 소재재질
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 100,
title: '소재재질',
field: 'RAW_MATERIAL'
},
// 18. 사이즈 -> 규격
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 100,
title: '규격',
field: 'SIZE'
},
// 19. 소재품번
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 120,
title: '소재품번',
field: 'RAW_MATERIAL_NO'
},
// 30. 공급업체 (수정가능 - Select2 에디터)
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 150,
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">공급업체</span>',
field: 'VENDOR_PM',
editor: function(cell, onRendered, success, cancel, editorParams) {
// Select2 에디터 (가공업체와 동일한 목록 사용)
return createSelect2Editor(processingVendorList)(cell, onRendered, success, cancel, editorParams);
},
formatter: function(cell) {
var value = cell.getValue();
if(!value) return '';
// processingVendorList에서 해당 값의 이름 찾기
for(var i = 0; i < processingVendorList.length; i++) {
if(processingVendorList[i].id == value) {
return processingVendorList[i].text;
}
}
return value;
}
},
// 31. 단가 (수정가능) -> 소재단가
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">소재단가</span>',
field: 'UNIT_PRICE',
editor: 'number',
editable: true,
formatter: function(cell) {
var value = cell.getValue();
return value ? Number(value).toLocaleString() : '0';
}
},
// 32. 총단가 -> 소재총단가
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '소재총단가',
field: 'TOTAL_PRICE',
formatter: function(cell) {
var data = cell.getRow().getData();
var qty = parseFloat(data.PO_QTY) || 0;
var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
var totalPrice = qty * unitPrice;
return totalPrice > 0 ? totalPrice.toLocaleString() : '0';
}
},
// 27. 사용여부 (수정가능)
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 90,
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">사용여부</span>',
field: 'USE_YN',
editor: 'list',
editorParams: {
values: ['사용', '미사용']
},
mutator: function(value, data) {
// DB 값 변환: Y/N → 사용/미사용
if(value === 'Y' || value === '사용') return '사용';
if(value === 'N' || value === '미사용') return '미사용';
// 값이 없으면 기본값 '사용'
return '사용';
}
},
// 28. 정미수량 (편집 불가) - 소재소요량 × 제작수량
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '정미수량',
field: 'NET_QTY',
mutator: function(value, data) {
// 저장된 값이 있으면 우선 사용
if(value !== null && value !== undefined && value !== '' && parseFloat(value) > 0) {
return parseFloat(value);
}
// 계산: 소재소요량 × 제작수량 (올림 없음)
var requiredQty = parseFloat(data.REQUIRED_QTY) || 0;
var productionQty = parseFloat(data.PRODUCTION_QTY) || 0;
var calculated = requiredQty * productionQty;
return calculated > 0 ? calculated : 0;
},
formatter: function(cell) {
var value = cell.getValue();
return value ? Number(value).toLocaleString() : '0';
}
},
// 29. 발주수량 (수정가능) - 정미수량 올림
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">발주수량</span>',
field: 'PO_QTY',
editor: 'number',
mutator: function(value, data) {
// 저장된 값이 있으면 우선 사용
if(value !== null && value !== undefined && value !== '' && parseFloat(value) > 0) {
return parseFloat(value);
}
// 계산: 정미수량 올림
var netQty = parseFloat(data.NET_QTY) || 0;
return netQty > 0 ? Math.ceil(netQty) : 0;
},
formatter: function(cell) {
var value = cell.getValue();
return value ? Number(value).toLocaleString() : '0';
}
},
// 24. 가공업체 (수정가능 - Select2 에디터)
{
headerHozAlign: 'center',
hozAlign: 'left',
width: 150,
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">가공업체</span>',
field: 'PROCESSING_VENDOR',
editor: function(cell, onRendered, success, cancel, editorParams) {
// Select2 에디터
return createSelect2Editor(processingVendorList)(cell, onRendered, success, cancel, editorParams);
},
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 < processingVendorList.length; i++) {
if(processingVendorList[i].id == value) {
return processingVendorList[i].text;
}
}
return value;
}
},
// 가공단가 (수정가능)
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '<span style="background-color: #FFFF00; padding: 2px 5px;">가공단가</span>',
field: 'PROCESSING_UNIT_PRICE',
editor: 'number',
editable: true,
formatter: function(cell) {
var value = cell.getValue();
return value ? Number(value).toLocaleString() : '0';
}
},
// 가공총단가 (가공단가 × 제작수량)
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '가공총단가',
field: 'PROCESSING_TOTAL_PRICE',
formatter: function(cell) {
var data = cell.getRow().getData();
var productionQty = parseFloat(data.PRODUCTION_QTY) || 0;
var processingUnitPrice = parseFloat(data.PROCESSING_UNIT_PRICE) || 0;
var processingTotalPrice = productionQty * processingUnitPrice;
return processingTotalPrice > 0 ? processingTotalPrice.toLocaleString() : '0';
}
},
// 총합계 (소재총단가 + 가공총단가)
{
headerHozAlign: 'center',
hozAlign: 'right',
width: 100,
title: '총합계',
field: 'GRAND_TOTAL_PRICE',
formatter: function(cell) {
var data = cell.getRow().getData();
// 소재총단가: 발주수량 × 소재단가
var poQty = parseFloat(data.PO_QTY) || 0;
var unitPrice = parseFloat(data.UNIT_PRICE) || 0;
var materialTotalPrice = poQty * unitPrice;
// 가공총단가: 제작수량 × 가공단가
var productionQty = parseFloat(data.PRODUCTION_QTY) || 0;
var processingUnitPrice = parseFloat(data.PROCESSING_UNIT_PRICE) || 0;
var processingTotalPrice = productionQty * processingUnitPrice;
// 총합계
var grandTotal = materialTotalPrice + processingTotalPrice;
return grandTotal > 0 ? grandTotal.toLocaleString() : '0';
}
},
/* // 25. 가공납기 - 주석처리
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 100,
title: '가공납기',
field: 'PROCESSING_DEADLINE'
},
// 26. 연삭납기
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 100,
title: '연삭납기',
field: 'GRINDING_DEADLINE'
}, */
// 33. 소재 품의서작성일
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 110,
title: '소재품의서일',
field: 'PROPOSAL_DATE',
formatter: function(cell) {
var value = cell.getValue();
if(!value) return '';
// YYYY-MM-DD 형식으로 표시
if(value.length >= 10) {
return value.substring(0, 10);
}
return value;
}
},
// 34. 가공 품의서작성일
{
headerHozAlign: 'center',
hozAlign: 'center',
width: 110,
title: '가공품의서일',
field: 'PROCESSING_PROPOSAL_DATE',
formatter: function(cell) {
var value = cell.getValue();
if(!value) return '';
// YYYY-MM-DD 형식으로 표시
if(value.length >= 10) {
return value.substring(0, 10);
}
return value;
}
}
];
_tabulGrid = new Tabulator("#purchaseListTable", {
layout: "fitData",
height: "calc(100vh - 200px)",
columns: columns,
data: [],
placeholder: "데이터가 없습니다."
});
// 전체 체크박스 이벤트
$(document).on('click', '#checkAll', function() {
$('.rowCheck').prop('checked', $(this).prop('checked'));
});
// 셀 편집 이벤트
_tabulGrid.on("cellEdited", function(cell) {
var field = cell.getField();
var row = cell.getRow();
var data = row.getData();
// 발주수량, 소재단가, 가공단가 변경 시 총단가 자동 계산
if(field === 'PO_QTY' || field === 'UNIT_PRICE' || field === 'PROCESSING_UNIT_PRICE') {
row.reformat();
}
});
}
// 기존 구매리스트 조회
function fn_loadPurchaseList(mergeMode) {
logDebug("purchaseListFormPopUp :: fn_loadPurchaseList", "mergeMode=", mergeMode, "masterId=", salesRequestMasterObjid);
$.ajax({
url: "/salesMng/getPurchaseListDetail.do",
method: 'post',
data: {
SALES_REQUEST_MASTER_OBJID: salesRequestMasterObjid
},
dataType: 'json',
success: function(data) {
logDebug("purchaseListFormPopUp :: purchase list loaded", data);
if(data && data.list) {
if(mergeMode){
fn_mergeSavedData(data.list);
}else{
_tabulGrid.setData(data.list);
}
}
},
error: function(jqxhr, status, error){
logError("구매리스트 조회 오류:", error);
Swal.fire({
title: '오류',
text: '구매리스트 조회 중 오류가 발생했습니다.',
icon: 'error'
});
}
});
}
// M-BOM에서 구매리스트 생성
function fn_loadFromMBom(callback) {
logDebug("=== fn_loadFromMBom 호출 ===");
logDebug("MBOM_HEADER_OBJID:", mbomHeaderObjid);
// MBOM_HEADER_OBJID가 없으면 M-BOM 데이터를 로드하지 않음
if(!mbomHeaderObjid || mbomHeaderObjid === '' || mbomHeaderObjid === 'null') {
logDebug("MBOM_HEADER_OBJID가 없어서 M-BOM 로드 안 함");
if(callback) callback([]);
return;
}
$.ajax({
url: "/salesMng/getMBomForPurchaseList.do",
method: 'post',
data: {
PROJECT_MGMT_OBJID: mbomHeaderObjid, // MBOM_HEADER_OBJID를 직접 사용
bomReportObjId: bomReportObjid
},
dataType: 'json',
success: function(data) {
// console.log("=== M-BOM AJAX 응답 ===");
// console.log("전체 응답:", JSON.stringify(data));
// console.log("data.list:", data ? data.list : "data가 null");
// console.log("list 길이:", (data && data.list) ? data.list.length : 0);
// if(data && data.list && data.list.length > 0) {
// console.log("첫번째 항목 전체 키:", Object.keys(data.list[0]));
// console.log("첫번째 항목 PM_HEAT_RAW:", data.list[0].PM_HEAT_RAW);
// console.log("첫번째 항목 PM_METHOD_RAW:", data.list[0].PM_METHOD_RAW);
// console.log("첫번째 항목 PM_SURFACE_RAW:", data.list[0].PM_SURFACE_RAW);
// console.log("첫번째 항목 HEAT_TREATMENT_HARDNESS:", data.list[0].HEAT_TREATMENT_HARDNESS);
// }
var list = (data && data.list) ? data.list : [];
if(list.length > 0) {
// console.log("M-BOM 데이터 " + list.length + "건 로드됨");
_tabulGrid.setData(list);
} else {
// console.log("M-BOM 데이터 없음!");
// 알림 제거 - 머지 모드에서는 알림 안 띄움
}
if(typeof callback === "function"){
callback(list);
}
},
error: function(jqxhr, status, error){
console.error("=== M-BOM AJAX 오류 ===");
console.error("status:", status);
console.error("error:", error);
console.error("responseText:", jqxhr.responseText);
Swal.fire({
title: '오류',
text: 'M-BOM 조회 중 오류가 발생했습니다.',
icon: 'error'
});
if(typeof callback === "function"){
callback([]);
}
}
});
}
function fn_mergeSavedData(savedList){
logDebug("purchaseListFormPopUp :: merging saved data", savedList);
if(!savedList || savedList.length === 0) return;
var rowMap = {};
_tabulGrid.getRows().forEach(function(row){
var rowData = row.getData();
if(rowData && rowData.PART_OBJID){
rowMap[rowData.PART_OBJID] = row;
}
});
savedList.forEach(function(item){
var key = item.PART_OBJID;
var targetRow = rowMap[key];
if(targetRow){
targetRow.update(item);
}else{
_tabulGrid.addData([item], true);
}
});
}
// 저장
function fn_save() {
var gridData = _tabulGrid.getData();
if(!gridData || gridData.length === 0) {
Swal.fire({
title: '알림',
text: '저장할 데이터가 없습니다.',
icon: 'warning'
});
return;
}
// 저장 전 데이터 가공
gridData.forEach(function(item) {
// 소재총단가 계산 (PO_QTY * UNIT_PRICE)
var poQty = parseFloat(item.PO_QTY) || 0;
var unitPrice = parseFloat(item.UNIT_PRICE) || 0;
item.TOTAL_PRICE = poQty * unitPrice;
// 가공총단가 계산 (PRODUCTION_QTY * PROCESSING_UNIT_PRICE)
var productionQty = parseFloat(item.PRODUCTION_QTY) || 0;
var processingUnitPrice = parseFloat(item.PROCESSING_UNIT_PRICE) || 0;
item.PROCESSING_TOTAL_PRICE = productionQty * processingUnitPrice;
// 총합계 계산 (소재총단가 + 가공총단가)
item.GRAND_TOTAL_PRICE = item.TOTAL_PRICE + item.PROCESSING_TOTAL_PRICE;
// 사용여부 변환: 사용/미사용 → Y/N
if(item.USE_YN === '사용') {
item.USE_YN = 'Y';
} else if(item.USE_YN === '미사용') {
item.USE_YN = 'N';
}
});
Swal.fire({
title: '확인',
text: '저장하시겠습니까?',
icon: 'question',
showCancelButton: true,
confirmButtonText: '확인',
cancelButtonText: '취소'
}).then((result) => {
if (result.isConfirmed) {
$.ajax({
url: "/salesMng/savePurchaseList.do",
method: 'post',
data: {
SALES_REQUEST_MASTER_OBJID: salesRequestMasterObjid,
PROJECT_MGMT_OBJID: projectMgmtObjid,
purchaseListData: JSON.stringify(gridData)
},
dataType: 'json',
success: function(data) {
if(data && (data.resultFlag === 'S' || data.RESULTFLAG === 'S')) {
Swal.fire({
title: '성공',
text: '저장되었습니다.',
icon: 'success'
}).then(() => {
if(opener && opener.fn_search) {
opener.fn_search();
}
window.close();
});
} else {
Swal.fire({
title: '실패',
text: data.message || data.MESSAGE || '저장에 실패했습니다.',
icon: 'error'
});
}
},
error: function(jqxhr, status, error){
console.error("저장 오류:", error);
Swal.fire({
title: '오류',
text: '저장 중 오류가 발생했습니다.',
icon: 'error'
});
}
});
}
});
}
</script>
</body>
</html>