feature/estimate-template-improvements #64

Merged
hjjeong merged 6 commits from feature/estimate-template-improvements into main 2025-11-13 08:51:47 +00:00
15 changed files with 767 additions and 192 deletions

View File

@@ -63,11 +63,26 @@ $(document).ready(function(){
//영업활동 등록 팝업
$(".btnRegist").click(function(){
var selectedData = _tabulGrid.getSelectedData();
var popup_width = 1400;
var popup_height = 560;
var params = "?actionType=regist"
var url = "/contractMgmt/estimateRegistFormPopup.do"+params;
//window.open("/ordermgmt/ordermgmtUpdateFormPopup.do"+params, "", "width=650, height=750","menubars=no, scrollbars=yes, resizable=yes");
var popup_height = 560;
var url = "";
// 선택된 행이 없으면 신규 등록
if(selectedData.length === 0){
url = "/contractMgmt/estimateRegistFormPopup.do?actionType=regist";
}
// 한 줄 선택된 경우 상세 팝업 (영업번호 클릭과 동일)
else if(selectedData.length === 1){
var objid = fnc_checkNull(selectedData[0].OBJID);
url = "/contractMgmt/estimateRegistFormPopup.do?objId=" + objid;
}
// 여러 줄 선택된 경우 경고
else {
Swal.fire("한 개의 행만 선택해주세요.");
return false;
}
fn_centerPopup(popup_width, popup_height, url);
});
@@ -502,11 +517,11 @@ function fn_FileRegist(objId, docType, docTypeName){
fn_centerPopup(popup_width, popup_height, url);
}
//영업활동등록 상세
//영업활동등록 상세 (뷰 전용 팝업)
function fn_projectConceptDetail(objId){
var popup_width = 1400;
var popup_height = 560;
var url = "/contractMgmt/estimateRegistFormPopup.do?objId="+objId;
var popup_width = 900;
var popup_height = 700;
var url = "/contractMgmt/estimateViewPopup.do?objId="+objId;
fn_centerPopup(popup_width, popup_height, url);
}

View File

@@ -15,34 +15,35 @@ String contractObjId = request.getParameter("contractObjId");
<title>견적서 메일 발송</title>
<style>
body {
font-family: 'Malgun Gothic', sans-serif;
margin: 20px;
margin: 10px;
background-color: #f5f5f5;
font-size: 13px;
}
.mail-form-container {
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
max-width: 900px;
padding: 15px 20px;
border-radius: 6px;
box-shadow: 0 1px 5px rgba(0,0,0,0.1);
max-width: 800px;
margin: 0 auto;
}
.form-title {
font-size: 24px;
font-size: 18px;
font-weight: bold;
margin-bottom: 30px;
margin-bottom: 15px;
color: #333;
border-bottom: 2px solid #3085d6;
padding-bottom: 10px;
padding-bottom: 8px;
}
.form-group {
margin-bottom: 20px;
margin-bottom: 12px;
}
.form-group label {
display: block;
font-weight: bold;
margin-bottom: 8px;
margin-bottom: 5px;
color: #555;
font-size: 13px;
}
.form-group label.required:after {
content: " *";
@@ -52,60 +53,63 @@ String contractObjId = request.getParameter("contractObjId");
.form-group input[type="email"],
.form-group textarea {
width: 100%;
padding: 10px;
padding: 6px 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
border-radius: 3px;
font-size: 13px;
box-sizing: border-box;
}
.form-group textarea {
min-height: 200px;
min-height: 120px;
resize: vertical;
}
.manager-list {
border: 1px solid #ddd;
border-radius: 4px;
padding: 15px;
border-radius: 3px;
padding: 8px;
background-color: #fafafa;
max-height: 200px;
max-height: 150px;
overflow-y: auto;
}
.manager-item {
padding: 8px;
margin-bottom: 5px;
padding: 5px;
margin-bottom: 3px;
background: white;
border-radius: 4px;
border-radius: 3px;
display: flex;
align-items: center;
font-size: 13px;
}
.manager-item input[type="checkbox"] {
margin-right: 10px;
width: 18px;
height: 18px;
margin-right: 8px;
width: 16px;
height: 16px;
cursor: pointer;
}
.manager-item label {
cursor: pointer;
margin: 0;
flex: 1;
font-size: 13px;
}
.no-managers {
color: #999;
text-align: center;
padding: 20px;
padding: 12px;
font-size: 13px;
}
.button-group {
text-align: center;
margin-top: 30px;
padding-top: 20px;
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #eee;
}
.btn {
padding: 12px 30px;
margin: 0 5px;
padding: 8px 20px;
margin: 0 4px;
border: none;
border-radius: 4px;
font-size: 16px;
border-radius: 3px;
font-size: 13px;
cursor: pointer;
transition: all 0.3s;
}
@@ -124,16 +128,17 @@ String contractObjId = request.getParameter("contractObjId");
background-color: #5a6268;
}
.info-text {
font-size: 12px;
font-size: 11px;
color: #666;
margin-top: 5px;
margin-top: 3px;
}
.pdf-status {
padding: 10px;
padding: 8px 10px;
background-color: #e7f3ff;
border-left: 4px solid #3085d6;
border-radius: 4px;
margin-bottom: 20px;
border-left: 3px solid #3085d6;
border-radius: 3px;
margin-bottom: 12px;
font-size: 13px;
}
.pdf-status i {
color: #3085d6;

View File

@@ -47,6 +47,9 @@
// 품번 데이터는 AJAX로 검색하므로 초기 데이터 없음
// 프로젝트 존재 여부 체크 변수
var hasProject = false;
$(function() {
// 반납사유 옵션을 템플릿에서 읽어옴
returnReasonOptions = $('#return_reason_template').html();
@@ -107,6 +110,9 @@
fn_addItemRow();
});
// 프로젝트 존재 여부 먼저 확인 (동기 방식)
fn_checkProjectExists();
// 기존 품목 데이터 로드
fn_loadExistingItems();
@@ -533,6 +539,17 @@
// 품번/품명 옵션 채우기 (저장된 품번/품명도 함께 전달)
fn_fillPartOptions(itemId, savedPartObjId, savedPartNo, savedPartName);
// 프로젝트가 있으면 품번/품명 셀렉트박스 비활성화 및 삭제 버튼 비활성화
if(hasProject) {
$("#PART_NO_" + itemId).prop("disabled", true).css("background-color", "#f5f5f5");
$("#PART_NAME_" + itemId).prop("disabled", true).css("background-color", "#f5f5f5");
$("#" + itemId + " button[onclick*='fn_deleteItemRow']").prop("disabled", true).css({
"background-color": "#ccc",
"cursor": "not-allowed",
"opacity": "0.6"
});
}
// datepicker 적용
$("#" + itemId + " .date_icon").datepicker({
changeMonth: true,
@@ -1176,8 +1193,66 @@
// ========== 품목 관리 함수 ==========
// 프로젝트 존재 여부 확인
function fn_checkProjectExists() {
var contractObjId = "${info.OBJID}";
console.log("=== fn_checkProjectExists 시작 ===");
console.log("contractObjId:", contractObjId);
if(!contractObjId || contractObjId === '') {
console.log("contractObjId 없음 - 체크 중단");
return;
}
$.ajax({
url: "/contractMgmt/checkProjectExists.do",
type: "POST",
data: { contractObjId: contractObjId },
dataType: "json",
async: false,
success: function(data) {
console.log("AJAX 응답 전체:", data);
console.log("data.exists 값:", data.exists);
console.log("data.exists 타입:", typeof data.exists);
console.log("JSON.stringify(data):", JSON.stringify(data));
if(data && data.exists === true) {
hasProject = true;
console.log("✅ 프로젝트 존재 확인 - hasProject = true");
console.log("프로젝트 정보:", data.projectInfo);
// 품목 추가 버튼 비활성화
$("#btnAddItem").prop("disabled", true).css({
"background-color": "#ccc",
"cursor": "not-allowed",
"opacity": "0.6"
});
} else {
console.log("❌ 프로젝트 없음 - hasProject = false");
}
},
error: function(xhr, status, error) {
console.error("프로젝트 존재 여부 확인 실패:", error);
console.error("Status:", status);
console.error("Response:", xhr.responseText);
}
});
console.log("=== fn_checkProjectExists 종료 - hasProject:", hasProject, "===");
}
// 품목 행 추가
function fn_addItemRow() {
// 프로젝트가 있으면 품목 추가 불가
if(hasProject) {
Swal.fire({
title: '품목 추가 불가',
text: '프로젝트가 이미 생성되어 품목을 추가할 수 없습니다.\n수량, 납기일 등만 수정 가능합니다.',
icon: 'warning'
});
return;
}
var itemId = 'item_' + itemCounter++;
// "품목 추가하세요" 메시지 행 제거
@@ -1520,6 +1595,16 @@
// 품목 행 삭제
function fn_deleteItemRow(itemId) {
// 프로젝트가 있으면 품목 삭제 불가
if(hasProject) {
Swal.fire({
title: '품목 삭제 불가',
text: '프로젝트가 이미 생성되어 품목을 삭제할 수 없습니다.',
icon: 'warning'
});
return;
}
if(confirm("해당 품목을 삭제하시겠습니까?")) {
$("#" + itemId).remove();

View File

@@ -523,7 +523,7 @@ function getCurrencySymbol() {
}
}
// 품명 셀렉트박스 초기화 함수
/* 품명 셀렉트박스 초기화 함수 - 주석처리 (텍스트 readonly로 변경)
function fn_initItemDescSelect(itemId) {
$("#" + itemId + " .item-desc-select").select2({
placeholder: "품명 입력하여 검색...",
@@ -594,6 +594,7 @@ function fn_initItemDescSelect(itemId) {
$("#" + itemId + " .item-part-objid").val(''); // part_objid 초기화
});
}
*/
// 행 추가 함수
function fn_addItemRow() {
@@ -606,8 +607,7 @@ function fn_addItemRow() {
var newRow = '<tr id="' + itemId + '">' +
'<td>' + nextNo + '</td>' +
'<td class="text-left editable">' +
'<select class="item-desc-select" style="width:100%;"></select>' +
'<input type="hidden" class="item-desc" value="">' +
'<input type="text" class="item-desc" value="" readonly style="background-color: #f5f5f5;">' +
'<input type="hidden" class="item-part-objid" value="">' +
'</td>' +
'<td class="text-left editable"><textarea class="item-spec"></textarea></td>' +
@@ -621,8 +621,8 @@ function fn_addItemRow() {
// 계 행 바로 위에 추가
$(".total-row").before(newRow);
// 품명 셀렉트박스 초기화
fn_initItemDescSelect(itemId);
// 품명 셀렉트박스 초기화 - 주석처리 (텍스트 readonly로 변경)
// fn_initItemDescSelect(itemId);
// 합계 재계산
fn_calculateTotal();
@@ -686,12 +686,7 @@ function fn_loadContractItems(contractObjId) {
itemsHtml += '<tr id="' + itemId + '">';
itemsHtml += '<td>' + (i + 1) + '</td>';
itemsHtml += '<td class="text-left editable">';
itemsHtml += '<select class="item-desc-select" style="width:100%;">';
if(partName) {
itemsHtml += '<option value="' + partObjId + '" selected>' + partName + '</option>';
}
itemsHtml += '</select>';
itemsHtml += '<input type="hidden" class="item-desc" value="' + partName + '">';
itemsHtml += '<input type="text" class="item-desc" value="' + partName + '" readonly style="background-color: #f5f5f5;">';
itemsHtml += '<input type="hidden" class="item-part-objid" value="' + partObjId + '">';
itemsHtml += '</td>';
itemsHtml += '<td class="text-left editable"><textarea class="item-spec"></textarea></td>';
@@ -746,11 +741,12 @@ function fn_loadContractItems(contractObjId) {
// HTML 삽입
$("#itemsTableBody").html(itemsHtml);
// 셀렉트박스 초기화
/* 셀렉트박스 초기화 - 주석처리 (텍스트 readonly로 변경)
for(var i = 0; i < data.items.length; i++) {
var itemId = 'contract_item_' + i;
fn_initItemDescSelect(itemId);
}
*/
// 합계 계산
fn_calculateTotal();
@@ -760,8 +756,10 @@ function fn_loadContractItems(contractObjId) {
fn_controlButtons();
} else {
// 품목이 없으면 기본 행 표시
/* 셀렉트박스 초기화 - 주석처리 (텍스트 readonly로 변경)
fn_initItemDescSelect('default_item_1');
fn_initItemDescSelect('default_item_2');
*/
fn_calculateTotal();
g_apprStatus = "작성중";
fn_controlButtons();
@@ -772,8 +770,10 @@ function fn_loadContractItems(contractObjId) {
Swal.fire("품목 데이터를 불러오는데 실패했습니다.");
// 오류 시 기본 행 표시
/* 셀렉트박스 초기화 - 주석처리 (텍스트 readonly로 변경)
fn_initItemDescSelect('default_item_1');
fn_initItemDescSelect('default_item_2');
*/
fn_calculateTotal();
g_apprStatus = "작성중";
fn_controlButtons();
@@ -935,9 +935,11 @@ function fn_loadData() {
}
*/ // 품목 데이터 로드 주석처리 끝
// 새로 작성 시 기본 행의 셀렉트박스 초기화
// 새로 작성 시 기본 행의 셀렉트박스 초기화 - 주석처리 (텍스트 readonly로 변경)
/*
fn_initItemDescSelect('default_item_1');
fn_initItemDescSelect('default_item_2');
*/
// 초기 로드 시 합계 계산
fn_calculateTotal();
@@ -1064,13 +1066,7 @@ function fn_loadTemplateData(templateObjId){
itemsHtml += '<tr id="' + itemId + '">';
itemsHtml += '<td>' + (i + 1) + '</td>';
itemsHtml += '<td class="text-left editable">';
itemsHtml += '<select class="item-desc-select" style="width:100%;">';
// PART_OBJID가 없으면 기존 텍스트를 옵션으로 표시
if(description) {
itemsHtml += '<option value="" selected>' + description + '</option>';
}
itemsHtml += '</select>';
itemsHtml += '<input type="hidden" class="item-desc" value="' + description + '">';
itemsHtml += '<input type="text" class="item-desc" value="' + description + '" readonly style="background-color: #f5f5f5;">';
itemsHtml += '<input type="hidden" class="item-part-objid" value="' + partObjId + '">';
itemsHtml += '</td>';
itemsHtml += '<td class="text-left editable"><textarea class="item-spec">' + specification + '</textarea></td>';
@@ -1125,7 +1121,7 @@ function fn_loadTemplateData(templateObjId){
// HTML 삽입
$("#itemsTableBody").html(itemsHtml);
// 셀렉트박스 초기화 및 데이터 설정
/* 셀렉트박스 초기화 및 데이터 설정 - 주석처리 (텍스트 readonly로 변경)
for(var i = 0; i < data.items.length; i++) {
var item = data.items[i];
var itemId = 'template_item_' + i;
@@ -1167,6 +1163,7 @@ function fn_loadTemplateData(templateObjId){
// 셀렉트박스 초기화 (옵션 추가 후)
fn_initItemDescSelect(itemId);
}
*/
// 테이블 내 비고 값 설정 (textarea 생성 직후)
$("#note_remarks").val(noteRemarks);
@@ -1436,8 +1433,7 @@ function fn_save() {
<tr id="default_item_1">
<td>1</td>
<td class="text-left editable">
<select class="item-desc-select" style="width:100%;"></select>
<input type="hidden" class="item-desc" value="">
<input type="text" class="item-desc" value="" readonly style="background-color: #f5f5f5;">
<input type="hidden" class="item-part-objid" value="">
</td>
<td class="text-left editable"><textarea class="item-spec"></textarea></td>
@@ -1450,8 +1446,7 @@ function fn_save() {
<tr id="default_item_2">
<td>2</td>
<td class="text-left editable">
<select class="item-desc-select" style="width:100%;"></select>
<input type="hidden" class="item-desc" value="">
<input type="text" class="item-desc" value="" readonly style="background-color: #f5f5f5;">
<input type="hidden" class="item-part-objid" value="">
</td>
<td class="text-left editable"><textarea class="item-spec"></textarea></td>
@@ -1502,7 +1497,7 @@ function fn_save() {
<!-- 버튼 영역 -->
<div class="btn-area no-print">
<button type="button" id="btnAddRow" class="estimate-btn">행 추가</button>
<!-- <button type="button" id="btnAddRow" class="estimate-btn">행 추가</button> -->
<button type="button" id="btnPrint" class="estimate-btn">인쇄</button>
<button type="button" id="btnDownloadPdf" class="estimate-btn">PDF 다운로드</button>
<button type="button" id="btnSave" class="estimate-btn">저장</button>

View File

@@ -0,0 +1,201 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.pms.common.utils.*"%>
<%@ page import="java.util.*"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@include file="/init_new.jsp"%>
<%
PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN);
String userId = CommonUtils.checkNull(person.getUserId());
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><%=Constants.SYSTEM_NAME%></title>
<style>
body {
font-family: 'Malgun Gothic', sans-serif;
font-size: 12px;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.popup-container {
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 20px;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
padding: 10px;
background-color: #f8f9fa;
border-left: 4px solid #007bff;
margin-bottom: 15px;
}
.info-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.info-table th {
background-color: #f8f9fa;
padding: 10px;
text-align: center;
border: 1px solid #dee2e6;
font-weight: bold;
width: 15%;
}
.info-table td {
padding: 10px;
border: 1px solid #dee2e6;
background-color: white;
}
.item-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.item-table thead th {
background-color: #f8f9fa;
padding: 10px;
text-align: center;
border: 1px solid #dee2e6;
font-weight: bold;
}
.item-table tbody td {
padding: 8px;
border: 1px solid #dee2e6;
text-align: center;
}
.item-table tbody td.text-left {
text-align: left;
}
.btn-area {
text-align: center;
margin-top: 20px;
}
.plm_btns {
padding: 8px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
margin: 0 5px;
}
.plm_btns:hover {
background-color: #0056b3;
}
</style>
<script type="text/javascript">
$(function() {
$("#btnClose").click(function() {
self.close();
});
});
</script>
</head>
<body>
<div class="popup-container">
<!-- 영업정보 섹션 -->
<div class="section-title">영업정보</div>
<table class="info-table">
<colgroup>
<col width="15%">
<col width="35%">
<col width="15%">
<col width="35%">
</colgroup>
<tr>
<th>주문유형</th>
<td>${info.CATEGORY_NAME}</td>
<th>제품구분</th>
<td>${info.PRODUCT_NAME}</td>
</tr>
<tr>
<th>유/무상</th>
<td>${info.PAID_TYPE_NAME}</td>
<th>접수일</th>
<td>${info.RECEIPT_DATE}</td>
</tr>
<tr>
<th>국내/해외</th>
<td>${info.AREA_NAME}</td>
<th>고객사</th>
<td>${info.CUSTOMER_NAME}</td>
</tr>
</table>
<!-- 품목정보 섹션 -->
<div class="section-title">품목정보</div>
<table class="item-table">
<colgroup>
<col width="5%">
<col width="15%">
<col width="25%">
<col width="15%">
<col width="10%">
<col width="15%">
<col width="15%">
</colgroup>
<thead>
<tr>
<th>No</th>
<th>품번</th>
<th>품명</th>
<th>S/N</th>
<th>요청납기</th>
<th>고객요청사항</th>
<th>반납사유</th>
</tr>
</thead>
<tbody>
<c:choose>
<c:when test="${empty itemList}">
<tr>
<td colspan="7" style="text-align:center; padding:30px; color:#999;">
등록된 품목이 없습니다.
</td>
</tr>
</c:when>
<c:otherwise>
<c:forEach items="${itemList}" var="item" varStatus="status">
<tr>
<td>${status.count}</td>
<td>${item.part_no}</td>
<td class="text-left">${item.part_name}</td>
<td>${item.serial_nos}</td>
<td>${item.due_date}</td>
<td class="text-left">${item.customer_request}</td>
<td>${item.return_reason}</td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
</tbody>
</table>
<!-- 버튼 영역 -->
<div class="btn-area">
<input type="button" value="닫기" class="plm_btns" id="btnClose">
</div>
</div>
</body>
</html>

View File

@@ -317,11 +317,11 @@ function fn_FileRegist(objId, docType, docTypeName){
fn_centerPopup(popup_width, popup_height, url);
}
//영업활동등록 상세
//영업활동등록 상세 (뷰 전용 팝업)
function fn_projectConceptDetail(objId){
var popup_width = 1400;
var popup_height = 560;
var url = "/contractMgmt/estimateRegistFormPopup.do?objId="+objId;
var popup_width = 900;
var popup_height = 700;
var url = "/contractMgmt/estimateViewPopup.do?objId="+objId;
fn_centerPopup(popup_width, popup_height, url);
}

View File

@@ -150,7 +150,7 @@ function fn_excel() {
}
function openOEMPopUp(objid){
var popup_width = 900;
var popup_height = 700;
var popup_height = 750;
var target = "openOEMPopUp";
fn_centerPopup(popup_width, popup_height, url, target);

View File

@@ -2,7 +2,7 @@
<%@ page import="com.pms.common.utils.*"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page import="java.util.*" %>
<%@include file= "/init.jsp" %>
<%@include file= "/init_new.jsp" %>
<%
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
String userId = CommonUtils.checkNull(person.getUserId());
@@ -412,7 +412,7 @@ function fn_edit(){
<input type="hidden" name="CONTRACT_OBJID" id="CONTRACT_OBJID" value="${resultMap.CONTRACT_OBJID}">
<section>
<div class="plm_menu_name" style="display:flex;">
<h2>
<h2 style="width: 100%;">
<span>품목 상세</span>
</h2>
</div>

View File

@@ -2,7 +2,7 @@
<%@ page import="com.pms.common.utils.*"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page import="java.util.*" %>
<%@include file= "/init.jsp" %>
<%@include file= "/init_new.jsp" %>
<%
PersonBean person = (PersonBean)session.getAttribute(Constants.PERSON_BEAN);
String userId = CommonUtils.checkNull(person.getUserId());
@@ -286,7 +286,7 @@ function fn_overlapPartMng(){
<input type="hidden" name="CONTRACT_OBJID" id="CONTRACT_OBJID" value="${resultMap.CONTRACT_OBJID}">
<section>
<div class="plm_menu_name" style="display:flex;">
<h2>
<h2 style="width: 100%;">
<span>
<c:if test="${ 'changeDesign' ne param.ACTION_TYPE}">
품목 등록

View File

@@ -26,6 +26,48 @@ $(document).ready(function(){
debug: false // 디버깅 모드 비활성화
});
// Select2 선택 시 텍스트 저장
$('#search_partNo').on('select2:select', function (e) {
var data = e.params.data;
$('#search_partNo_text').val(data.text);
});
$('#search_partName').on('select2:select', function (e) {
var data = e.params.data;
$('#search_partName_text').val(data.text);
});
// 이전 검색 조건 복원
setTimeout(function(){
var prevPartNoText = '${param.search_partNo_text}';
var prevPartNameText = '${param.search_partName_text}';
var prevPartNo = '${param.search_partNo}';
var prevPartName = '${param.search_partName}';
var prevPartObjId = '${param.search_partObjId}';
console.log("=== 검색 조건 복원 ===");
console.log("prevPartNoText:", prevPartNoText);
console.log("prevPartNameText:", prevPartNameText);
console.log("prevPartNo:", prevPartNo);
console.log("prevPartName:", prevPartName);
console.log("prevPartObjId:", prevPartObjId);
// 품번과 품명은 같은 OBJID를 사용하므로, 둘 중 하나만 복원
if(prevPartNoText && prevPartNo){
// 품번이 선택되어 있었던 경우
console.log("품번 복원:", prevPartNoText, prevPartNo);
var newOption = new Option(prevPartNoText, prevPartNo, true, true);
$('#search_partNo').append(newOption).trigger('change');
$('#search_partObjId').val(prevPartNo);
} else if(prevPartNameText && prevPartName){
// 품명이 선택되어 있었던 경우
console.log("품명 복원:", prevPartNameText, prevPartName);
var newOption = new Option(prevPartNameText, prevPartName, true, true);
$('#search_partName').append(newOption).trigger('change');
$('#search_partObjId').val(prevPartName);
}
}, 500);
$("#mainGrid").jqGrid({
height : 630,
colNames : headerNames,
@@ -82,12 +124,30 @@ $(document).ready(function(){
//정전개 조회
$("#btnSearchAscending").click(function(){
// 품번 또는 품명 필수 체크
var partNo = $.trim($("#search_partNo").val());
var partName = $.trim($("#search_partName").val());
if(!partNo && !partName){
Swal.fire('품번 또는 품명을 선택해 주세요');
return;
}
$("#searchType").val("ascending");
fn_search();
});
//역전개 조회
$("#btnSearchDescending").click(function(){
// 품번 또는 품명 필수 체크
var partNo = $.trim($("#search_partNo").val());
var partName = $.trim($("#search_partName").val());
if(!partNo && !partName){
Swal.fire('품번 또는 품명을 선택해 주세요');
return;
}
$("#searchType").val("descending");
fn_search();
});
@@ -100,18 +160,43 @@ $(document).ready(function(){
fn_excelExport($("#mainGrid"),"BOM_REPORT_정전개");
});
var search_level = '${param.search_level}';
$(".dataTr").each(function(i){
var lev = $(this).attr("data-LEVEL");
//if(lev == 1){ //1level만 활성화
if(!fnc_isEmpty(search_level)){ //검색조건 LEVEL까지만 활성화
if(Number(lev) <= Number(search_level)){ //검색조건 LEVEL까지만 활성화
$(this).show();
// 초기 로딩 시 레벨에 따라 표시 (검색 결과 기준)
setTimeout(function(){
var searchLevel = '${param.search_level}'; // 검색 조건의 레벨
// 최소 레벨 찾기
var minLevel = 999;
$(".dataTr").each(function(){
var lev = parseInt($(this).attr("data-LEVEL"));
if(lev < minLevel){
minLevel = lev;
}
}else{
$(this).show(); //전체 펼치기
});
// 표시할 최대 레벨 결정
var maxDisplayLevel = minLevel; // 기본값: 최소 레벨만
if(searchLevel && searchLevel != ''){
maxDisplayLevel = parseInt(searchLevel);
}
});
console.log("최소 레벨:", minLevel, "표시할 최대 레벨:", maxDisplayLevel);
// 지정된 레벨까지 표시
$(".dataTr").each(function(){
var lev = parseInt($(this).attr("data-LEVEL"));
if(lev <= maxDisplayLevel){
$(this).show();
// 표시된 항목 중 하위가 있고 아직 펼쳐지지 않은 항목은 Minus 아이콘으로 변경
if(lev < maxDisplayLevel){
var $img = $(this).find(".btnToggle");
if($img.length > 0 && $img.attr("src").indexOf("Plus") > -1){
$img.attr("src", "/images/btnMinus.png");
}
}
}
});
}, 100); // DOM 로딩 대기
/*
//클릭시 하위정보를 토글한다.
$(".dataTr").click(function(){
@@ -707,6 +792,8 @@ function fn_excelExport(pGridObj,pFileName){
<input type="hidden" name="search" id="search" value="Y">
<input type="hidden" name="actionType" id="actionType" value="" />
<input type="hidden" name="searchType" id="searchType" value="ascending" />
<input type="hidden" name="search_partNo_text" id="search_partNo_text" value="${param.search_partNo_text}" />
<input type="hidden" name="search_partName_text" id="search_partName_text" value="${param.search_partName_text}" />
<div class="min_part_enroll">
<div class="content-box">
<div class=""> <!-- content-box-s -->
@@ -766,16 +853,29 @@ function fn_excelExport(pGridObj,pFileName){
<select name="search_partNo" id="search_partNo" class="select2-part" style="width: 100%;">
<option value="">품번 선택</option>
</select>
<input type="hidden" name="search_partObjId" id="search_partObjId" value=""/>
<input type="hidden" name="search_partObjId" id="search_partObjId" value="${param.search_partObjId}"/>
</td>
<td class="align_r">
<label for="" class="">품명</label>
</td>
<td colspan="3">
<td>
<select name="search_partName" id="search_partName" class="select2-part" style="width: 100%;">
<option value="">품명 선택</option>
</select>
</td>
<td class="align_r">
<label for="" class="">표시 레벨</label>
</td>
<td>
<select name="search_level" id="search_level" class="select2" style="width: 100%;">
<option value="">선택</option>
<option value="1" ${param.search_level eq '1'?'selected':''}>1레벨</option>
<option value="2" ${param.search_level eq '2'?'selected':''}>2레벨</option>
<option value="3" ${param.search_level eq '3'?'selected':''}>3레벨</option>
<option value="4" ${param.search_level eq '4'?'selected':''}>4레벨</option>
<option value="5" ${param.search_level eq '5'?'selected':''}>5레벨</option>
</select>
</td>
<!-- <td class="align_r">
<label for="" class="">품번</label>
@@ -847,10 +947,10 @@ function fn_excelExport(pGridObj,pFileName){
<col width="90px" /> <!-- 표면처리 -->
<col width="90px" /> <!-- 공급업체 -->
<col width="80px" /> <!-- PART 타입 -->
<col width="60px" /> <!-- REVISION -->
<col width="70px" /> <!-- EO No -->
<col width="70px" /> <!-- EO Date -->
<col width="200px" /> <!-- REMARK -->
<!-- <col width="60px" /> REVISION
<col width="70px" /> EO No
<col width="70px" /> EO Date -->
<col width="200px" /> <!-- REMARK -->
</colgroup>
<thead>
<tr class="plm_thead">
@@ -877,11 +977,11 @@ function fn_excelExport(pGridObj,pFileName){
<td>열처리경도</td>
<td>열처리방법</td>
<td>표면처리</td>
<td>공급업체</td>
<td>메이커</td>
<td>범주 이름</td>
<td>Revision</td>
<!-- <td>Revision</td>
<td>EO No</td>
<td>EO Date</td>
<td>EO Date</td> -->
<td>비고</td>
</tr>
</thead>
@@ -915,9 +1015,9 @@ function fn_excelExport(pGridObj,pFileName){
<col width="90px" /> <!-- 표면처리 -->
<col width="90px" /> <!-- 공급업체 -->
<col width="80px" /> <!-- PART 타입 -->
<col width="60px" /> <!-- REVISION -->
<col width="70px" /> <!-- EO No -->
<col width="70px" /> <!-- EO Date -->
<!-- <col width="60px" /> REVISION
<col width="70px" /> EO No
<col width="70px" /> EO Date -->
<col width="200px" /> <!-- REMARK -->
</colgroup>
<c:choose>
@@ -931,22 +1031,17 @@ function fn_excelExport(pGridObj,pFileName){
<tr class="dataTr" data-LEVEL="${item.LEVEL}" data-REAL_LEVEL="${item.LEV}" data-BOM_REPORT_OBJID="${item.BOM_REPORT_OBJID}" data-TOP_OBJID="${item.ROOT_OBJID}"
data-SUB_TOP_OBJID="${item.SUB_ROOT_OBJID}" data-OBJID="${item.PART_OBJID}${status.index}" style="display:none;">
<td>
<c:if test="${item.LEAF eq '0'}">
<c:choose>
<c:when test="${empty param.search_level}">
<img src="/images/btnMinus.png" width="13px" height="13px" class="btnToggle" style="${item.LEVEL eq '1' and item.LEAF eq '0'?'cursor:pointer;':''}" data-BOM_REPORT_OBJID="${item.BOM_REPORT_OBJID}"
data-OBJID="${item.PART_OBJID}${status.index}" data-REAL_LEVEL="${item.LEV}" data-TOP_OBJID="${item.ROOT_OBJID}" data-SUB_TOP_OBJID="${item.SUB_ROOT_OBJID}">
<c:choose>
<c:when test="${item.LEAF eq '0'}">
<!-- 하위 항목이 있음: Plus 아이콘 표시 -->
<img src="/images/btnPlus.png" width="13px" height="13px" class="btnToggle" style="cursor:pointer;" data-BOM_REPORT_OBJID="${item.BOM_REPORT_OBJID}"
data-OBJID="${item.PART_OBJID}${status.index}" data-REAL_LEVEL="${item.LEV}" data-TOP_OBJID="${item.ROOT_OBJID}" data-SUB_TOP_OBJID="${item.SUB_ROOT_OBJID}">
</c:when>
<c:when test="${param.search_level > item.LEV}">
<img src="/images/btnMinus.png" width="13px" height="13px" class="btnToggle" style="${item.LEVEL eq '1' and item.LEAF eq '0'?'cursor:pointer;':''}" data-BOM_REPORT_OBJID="${item.BOM_REPORT_OBJID}"
data-OBJID="${item.PART_OBJID}${status.index}" data-REAL_LEVEL="${item.LEV}" data-TOP_OBJID="${item.ROOT_OBJID}" data-SUB_TOP_OBJID="${item.SUB_ROOT_OBJID}">
</c:when>
<c:when test="${param.search_level <= item.LEV}">
<img src="/images/btnPlus.png" width="13px" height="13px" class="btnToggle" style="${item.LEVEL eq '1' and item.LEAF eq '0'?'cursor:pointer;':''}" data-BOM_REPORT_OBJID="${item.BOM_REPORT_OBJID}"
data-OBJID="${item.PART_OBJID}${status.index}" data-REAL_LEVEL="${item.LEV}" data-TOP_OBJID="${item.ROOT_OBJID}" data-SUB_TOP_OBJID="${item.SUB_ROOT_OBJID}">
</c:when>
</c:choose>
</c:if>
<c:otherwise>
<!-- 하위 항목이 없음: - 표시 -->
<span style="display:inline-block; width:13px; text-align:center; color:#999;">-</span>
</c:otherwise>
</c:choose>
</td>
<c:forEach var="i" begin="1" end="${item.MAX_LEVEL}">
<c:if test="${item.LEVEL eq i}">
@@ -971,9 +1066,9 @@ function fn_excelExport(pGridObj,pFileName){
<td title="${item.SURFACE_TREATMENT}" class="align_l" style="text-align: left; padding-left: 5px;">${item.SURFACE_TREATMENT}</td><!-- 표면처리 -->
<td title="${item.MAKER}" class="align_l" style="text-align: left; padding-left: 5px;">${item.MAKER}</td><!-- 공급업체 -->
<td title="${item.PART_TYPE_TITLE}" class="align_c">${item.PART_TYPE_TITLE}</td><!-- PART_TYPE -->
<td title="${item.REVISION}" class="align_c" style="text-align: left; padding-left: 5px;">${item.REVISION}</td><!-- REVISION -->
<td title="${item.EO_NO}" class="align_c" style="text-align: left; padding-left: 5px;">${item.EO_NO}</td><!-- EO_NO -->
<td title="${item.EO_DATE}" class="align_c" style="text-align: left; padding-left: 5px;">${item.EO_DATE}</td><!-- EO_DATE -->
<!-- <td title="${item.REVISION}" class="align_c" style="text-align: left; padding-left: 5px;">${item.REVISION}</td> REVISION
<td title="${item.EO_NO}" class="align_c" style="text-align: left; padding-left: 5px;">${item.EO_NO}</td> EO_NO
<td title="${item.EO_DATE}" class="align_c" style="text-align: left; padding-left: 5px;">${item.EO_DATE}</td> EO_DATE -->
<td title="${item.REMARK}" class="align_l">${item.REMARK}</td><!-- REMARK -->
</tr>
</c:forEach>

View File

@@ -6038,7 +6038,7 @@ SELECT T1.LEV, T1.BOM_REPORT_OBJID, T1.ROOT_PART_NO, T1.PATH, T1.LEAF, T2.*
BT.ITEM_QTY,
BT.QTY AS QTY_TEMP,
BT.SEQ,
BT.LEAF,
-- BT.LEAF, -- 재귀 CTE의 LEAF는 항상 0이므로 제거 (아래에서 재계산)
-- PART 정보
PM.OBJID AS PART_OBJID,
PM.PART_NO,
@@ -6424,12 +6424,21 @@ SELECT T1.LEV, T1.BOM_REPORT_OBJID, T1.ROOT_PART_NO, T1.PATH, T1.LEAF, T2.*
)
SELECT
BT.BOM_REPORT_OBJID,
BT.LEV,
BT.LEV AS LEVEL,
-- 역전개는 레벨을 거꾸로 표시 (최상위가 1레벨)
(ML.MAX_LEVEL - BT.LEV + 1) AS LEV,
(ML.MAX_LEVEL - BT.LEV + 1) AS LEVEL,
BT.QTY,
BT.ITEM_QTY,
BT.QTY AS P_QTY,
BT.SEQ,
-- LEAF 계산 (역전개: 하위 항목이 있는지 체크 - 정전개와 동일)
(
SELECT CASE WHEN COUNT(*) > 0 THEN 0 ELSE 1 END
FROM BOM_PART_QTY BPQ2
WHERE BPQ2.PARENT_OBJID = BT.CHILD_OBJID
AND BPQ2.BOM_REPORT_OBJID = BT.BOM_REPORT_OBJID
AND COALESCE(BPQ2.STATUS, '') NOT IN ('deleting', 'deleted')
) AS LEAF,
-- PART 정보
PM.OBJID AS PART_OBJID,
PM.PART_NO,
@@ -6472,7 +6481,7 @@ SELECT T1.LEV, T1.BOM_REPORT_OBJID, T1.ROOT_PART_NO, T1.PATH, T1.LEAF, T2.*
ORDER BY
PBR.REGDATE DESC,
BT.LEV,
(ML.MAX_LEVEL - BT.LEV + 1), -- 역전개: 레벨 역순
BT.PATH
</select>

View File

@@ -7627,29 +7627,65 @@ SELECT
<!-- //영업정보 수정시 프로젝트 정보 업데이트 -->
<update id="ModifyProjectByContract" parameterType="map">
UPDATE PROJECT_MGMT
SET
DUE_DATE = #{due_date}
,CUSTOMER_PROJECT_NAME = #{customer_project_name}
,LOCATION = #{location}
,SETUP = #{setup}
,FACILITY = #{facility}
,FACILITY_TYPE = #{facility_type}
,FACILITY_DEPTH = #{facility_depth}
,CONTRACT_DATE = #{contract_date}
,PO_NO = #{po_no}
,PM_USER_ID = #{pm_user_id}
,CONTRACT_CURRENCY = #{contract_currency}
,CONTRACT_PRICE_CURRENCY = #{contract_price_currency}
,CONTRACT_PRICE = #{contract_price}
,PROJECT_NAME = #{project_name}
,CONTRACT_DEL_DATE = #{contract_del_date}
,REQ_DEL_DATE = #{req_del_date}
,CONTRACT_COMPANY = #{contract_company}
,MANUFACTURE_PLANT = #{manufacture_plant}
,PART_OBJID = #{part_objid}
,PART_NO = #{part_no}
,PART_NAME = #{part_name}
,QUANTITY = #{quantity}
<set>
<if test="due_date != null and due_date != ''">
DUE_DATE = #{due_date},
</if>
<if test="customer_project_name != null and customer_project_name != ''">
CUSTOMER_PROJECT_NAME = #{customer_project_name},
</if>
<if test="location != null and location != ''">
LOCATION = #{location},
</if>
<if test="setup != null and setup != ''">
SETUP = #{setup},
</if>
<if test="facility != null and facility != ''">
FACILITY = #{facility},
</if>
<if test="facility_type != null and facility_type != ''">
FACILITY_TYPE = #{facility_type},
</if>
<if test="facility_depth != null and facility_depth != ''">
FACILITY_DEPTH = #{facility_depth},
</if>
<if test="contract_date != null and contract_date != ''">
CONTRACT_DATE = #{contract_date},
</if>
<if test="po_no != null and po_no != ''">
PO_NO = #{po_no},
</if>
<if test="pm_user_id != null and pm_user_id != ''">
PM_USER_ID = #{pm_user_id},
</if>
<if test="contract_currency != null and contract_currency != ''">
CONTRACT_CURRENCY = #{contract_currency},
</if>
<if test="contract_price_currency != null and contract_price_currency != ''">
CONTRACT_PRICE_CURRENCY = #{contract_price_currency},
</if>
<if test="contract_price != null and contract_price != ''">
CONTRACT_PRICE = #{contract_price},
</if>
<if test="project_name != null and project_name != ''">
PROJECT_NAME = #{project_name},
</if>
<if test="contract_del_date != null and contract_del_date != ''">
CONTRACT_DEL_DATE = #{contract_del_date},
</if>
<if test="req_del_date != null and req_del_date != ''">
REQ_DEL_DATE = #{req_del_date},
</if>
<if test="contract_company != null and contract_company != ''">
CONTRACT_COMPANY = #{contract_company},
</if>
<if test="manufacture_plant != null and manufacture_plant != ''">
MANUFACTURE_PLANT = #{manufacture_plant},
</if>
<if test="quantity != null and quantity != ''">
QUANTITY = #{quantity}
</if>
</set>
WHERE CONTRACT_OBJID = #{objId}
AND PART_OBJID = #{part_objid}
</update>

View File

@@ -1813,6 +1813,40 @@ public class ContractMgmtController {
return "/contractMgmt/estimateRegistFormPopup";
}
/**
* 견적요청 조회 전용 팝업 (View Only)
* @param request
* @param paramMap
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@RequestMapping("/contractMgmt/estimateViewPopup.do")
public String estimateViewPopup(HttpSession session, HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
String objId = CommonUtils.checkNull(paramMap.get("objId"));
try{
Map info = null;
List<Map<String, Object>> itemList = new ArrayList<Map<String, Object>>();
if(paramMap.get("objId")!=null){
paramMap.put("objId",objId);
info = CommonUtils.keyChangeUpperMap(contractMgmtService.getContractMgmtInfo(paramMap));
// 품목 목록 조회
itemList = contractMgmtService.getContractItemList(objId);
}
request.setAttribute("info", info);
request.setAttribute("objId", objId);
request.setAttribute("itemList", itemList);
}catch(Exception e){
e.printStackTrace();
}
return "/contractMgmt/estimateViewPopup";
}
/**
* 품번 검색 (AJAX용)
*/
@@ -2571,4 +2605,43 @@ public class ContractMgmtController {
return resultMap;
}
/**
* 프로젝트 존재 여부 확인 (AJAX)
* @param request
* @param paramMap - contractObjId
* @return
*/
@ResponseBody
@RequestMapping(value="/contractMgmt/checkProjectExists.do", method=RequestMethod.POST)
public Map checkProjectExists(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
Map resultMap = new HashMap();
try {
String contractObjId = CommonUtils.checkNull(paramMap.get("contractObjId"));
if(StringUtils.isBlank(contractObjId)) {
System.out.println("contractObjId가 비어있음 - exists: false");
resultMap.put("exists", false);
return resultMap;
}
paramMap.put("objId", contractObjId);
Map projectInfo = contractMgmtService.checkProjectExists(paramMap);
if(projectInfo != null) {
resultMap.put("exists", true);
resultMap.put("projectInfo", projectInfo);
} else {
resultMap.put("exists", false);
}
} catch (Exception e) {
e.printStackTrace();
resultMap.put("exists", false);
resultMap.put("error", e.getMessage());
}
return resultMap;
}
}

View File

@@ -1411,8 +1411,11 @@
SELECT
A.OBJID
,A.CATEGORY_CD
,CODE_NAME(A.CATEGORY_CD) AS CATEGORY_NAME
,A.CUSTOMER_OBJID
,(SELECT SUPPLY_NAME FROM SUPPLY_MNG AS O WHERE O.OBJID = A.CUSTOMER_OBJID::NUMERIC) AS CUSTOMER_NAME
,A.PRODUCT
,CODE_NAME(A.PRODUCT) AS PRODUCT_NAME
,A.CUSTOMER_PROJECT_NAME
,A.STATUS_CD
,A.DUE_DATE
@@ -1455,12 +1458,14 @@
,A.EST_COMP_DATE
,A.EST_RESULT_CD
,A.AREA_CD
,CODE_NAME(A.AREA_CD) AS AREA_NAME
,A.TARGET_PROJECT_NO
,A.TARGET_PROJECT_NO_DIRECT
,A.CUSTOMER_PRODUCTION_NO
,A.MECHANICAL_TYPE
,A.OVERHAUL_ORDER
,A.PAID_TYPE
,(case when A.PAID_TYPE = 'paid' then '유상' when A.PAID_TYPE = 'free' then '무상' else A.PAID_TYPE end) AS PAID_TYPE_NAME
,A.RECEIPT_DATE
,A.PART_NO
,A.PART_NAME
@@ -3511,7 +3516,9 @@ ORDER BY ASM.SUPPLY_NAME
<select id="getProjectListBycontractObjid" parameterType="map" resultType="map">
SELECT
PROJECT_NAME
OBJID,
PROJECT_NAME,
PROJECT_NO
FROM
PROJECT_MGMT
WHERE CONTRACT_OBJID = #{objId}

View File

@@ -512,6 +512,35 @@ public class ContractMgmtService {
paramMap.put("writer", person.getUserId());
int cnt = sqlSession.update("contractMgmt.saveContractMgmtInfo", paramMap);
// 프로젝트가 존재하는 경우 프로젝트 정보도 업데이트 (수량 제외)
String contract_objid = CommonUtils.checkNull(paramMap.get("objId"));
if(!"".equals(contract_objid)) {
// CONTRACT_OBJID로 프로젝트 존재 여부 확인
resultList = sqlSession.selectOne("contractMgmt.getProjectListBycontractObjid", paramMap);
if(resultList != null) {
System.out.println("=== 견적요청 수정 시 프로젝트 업데이트 (수량 제외) ===");
System.out.println("CONTRACT_OBJID: " + contract_objid);
// 품목별로 프로젝트 업데이트 (수량은 제외)
List<Map> contractItems = getContractItems(paramMap);
if(contractItems != null && !contractItems.isEmpty()) {
for(Map item : contractItems) {
Map<String, Object> updateParam = new HashMap<String, Object>();
updateParam.putAll(paramMap);
updateParam.put("part_objid", item.get("PART_OBJID"));
updateParam.put("due_date", item.get("DUE_DATE"));
// quantity는 paramMap에서 제거하여 업데이트되지 않도록 함
updateParam.remove("quantity");
System.out.println("프로젝트 업데이트 - PART_OBJID: " + item.get("PART_OBJID") + ", 납기일: " + updateParam.get("due_date"));
sqlSession.update("project.ModifyProjectByContract", updateParam);
}
}
}
}
resultMap.put("result", true);
resultMap.put("msg", Message.SAVE_SUCCESS);
sqlSession.commit();
@@ -2591,39 +2620,36 @@ private String encodeImageToBase64(String imagePath) {
//paramMap.put("contract_price", contract_price/project_cnt + "");
if("0000964".equals(result_cd) || "0000968".equals(result_cd)){
// 품목별로 프로젝트 생성
// CONTRACT_OBJID로 프로젝트 존재 여부 확인 (한 번만 체크)
resultList = sqlSession.selectOne("contractMgmt.getProjectListBycontractObjid", paramMap);
boolean hasProject = (resultList != null);
// 품목별로 프로젝트 생성 또는 업데이트
List<Map> contractItems = getContractItems(paramMap);
if(contractItems != null && !contractItems.isEmpty()) {
System.out.println("품목 개수: " + contractItems.size() + "개 - 품목별 프로젝트 생성 시작");
System.out.println("품목 개수: " + contractItems.size() + "개 - 프로젝트 " + (hasProject ? "업데이트" : "생성") + " 시작");
for(Map item : contractItems) {
// 품목별 프로젝트 존재 여부 확인
Map<String, Object> projectCheckParam = new HashMap<String, Object>();
projectCheckParam.put("contractObjId", contract_objid);
projectCheckParam.put("part_objid", item.get("PART_OBJID"));
resultList = sqlSession.selectOne("contractMgmt.getProjectListByContractAndPartObjid", projectCheckParam);
if(null == resultList) {
// 새 프로젝트 생성
Map<String, Object> projectParam = new HashMap<String, Object>();
projectParam.putAll(paramMap); // 기본 정보 복사
// 품목별 정보 설정
projectParam.put("OBJID", CommonUtils.createObjId());
projectParam.put("is_temp", '1');
projectParam.put("part_objid", item.get("PART_OBJID"));
projectParam.put("part_no", item.get("PART_NO"));
projectParam.put("part_name", item.get("PART_NAME"));
projectParam.put("quantity", item.get("ORDER_QUANTITY") != null ? item.get("ORDER_QUANTITY") : item.get("QUANTITY"));
projectParam.put("due_date", item.get("DUE_DATE"));
if("0000170".equals(category_cd) || "0000171".equals(category_cd)){
projectParam.put("overhaul_project_no", target_project_no);
}
System.out.println("프로젝트 생성 - PART_OBJID: " + item.get("PART_OBJID") + ", 품번: " + item.get("PART_NO") + ", 품명: " + item.get("PART_NAME"));
for(Map item : contractItems) {
if(!hasProject) {
// 프로젝트가 없으면 모든 품목에 대해 생성
Map<String, Object> projectParam = new HashMap<String, Object>();
projectParam.putAll(paramMap); // 기본 정보 복사
// 품목별 정보 설정
projectParam.put("OBJID", CommonUtils.createObjId());
projectParam.put("is_temp", '1');
projectParam.put("part_objid", item.get("PART_OBJID"));
projectParam.put("part_no", item.get("PART_NO"));
projectParam.put("part_name", item.get("PART_NAME"));
projectParam.put("quantity", item.get("ORDER_QUANTITY") != null ? item.get("ORDER_QUANTITY") : item.get("QUANTITY"));
projectParam.put("due_date", item.get("DUE_DATE"));
if("0000170".equals(category_cd) || "0000171".equals(category_cd)){
projectParam.put("overhaul_project_no", target_project_no);
}
System.out.println("프로젝트 생성 - PART_OBJID: " + item.get("PART_OBJID") + ", 품번: " + item.get("PART_NO") + ", 품명: " + item.get("PART_NAME"));
// 프로젝트 등록
cnt = sqlSession.update("project.createProject", projectParam);
@@ -2648,25 +2674,22 @@ private String encodeImageToBase64(String imagePath) {
}
}
}
} else {
// 기존 프로젝트 업데이트
Map<String, Object> updateParam = new HashMap<String, Object>();
updateParam.putAll(paramMap);
updateParam.put("part_objid", item.get("PART_OBJID"));
updateParam.put("part_no", item.get("PART_NO"));
updateParam.put("part_name", item.get("PART_NAME"));
updateParam.put("quantity", item.get("ORDER_QUANTITY") != null ? item.get("ORDER_QUANTITY") : item.get("QUANTITY"));
updateParam.put("due_date", item.get("DUE_DATE"));
System.out.println("프로젝트 업데이트 - PART_OBJID: " + item.get("PART_OBJID") + ", 품번: " + item.get("PART_NO"));
sqlSession.update("project.ModifyProjectByContract", updateParam);
}
} else {
// 프로젝트가 있으면 모든 품목 업데이트 (수량, 금액 등만)
Map<String, Object> updateParam = new HashMap<String, Object>();
updateParam.putAll(paramMap);
updateParam.put("part_objid", item.get("PART_OBJID"));
updateParam.put("quantity", item.get("ORDER_QUANTITY") != null ? item.get("ORDER_QUANTITY") : item.get("QUANTITY"));
updateParam.put("due_date", item.get("DUE_DATE"));
System.out.println("프로젝트 업데이트 - PART_OBJID: " + item.get("PART_OBJID") + ", 수량: " + updateParam.get("quantity"));
sqlSession.update("project.ModifyProjectByContract", updateParam);
}
}
} else {
System.out.println("품목이 없습니다 - 기존 방식으로 프로젝트 생성");
// 품목이 없는 경우 기존 방식대로 처리
resultList = sqlSession.selectOne("contractMgmt.getProjectListBycontractObjid", paramMap);
if(null==resultList){
if(!hasProject){
paramMap.put("OBJID", CommonUtils.createObjId());
paramMap.put("is_temp", '1');
if("0000170".equals(category_cd) || "0000171".equals(category_cd)){
@@ -3235,4 +3258,35 @@ private String encodeImageToBase64(String imagePath) {
return resultMap;
}
/**
* 프로젝트 존재 여부 확인
* @param paramMap - objId (contractObjId)
* @return 프로젝트 정보 (없으면 null)
*/
@SuppressWarnings("rawtypes")
public Map checkProjectExists(Map paramMap) {
SqlSession sqlSession = null;
Map projectInfo = null;
try {
// autoCommit = true로 세션 생성
sqlSession = SqlMapConfig.getInstance().getSqlSession(true);
projectInfo = sqlSession.selectOne("contractMgmt.getProjectListBycontractObjid", paramMap);
if(projectInfo != null) {
projectInfo = CommonUtils.keyChangeUpperMap(projectInfo);
}
} catch(Exception e) {
System.out.println("❌ Service 오류: " + e.getMessage());
e.printStackTrace();
} finally {
if(sqlSession != null) sqlSession.close();
}
System.out.println("Service 최종 반환값: " + projectInfo);
return projectInfo;
}
}