구매요청_품의서관리 결재완료시 -> 구매관리_품의서관리에,, 그 후 프로세스 통합

This commit is contained in:
2026-01-19 16:41:44 +09:00
parent 8d14504861
commit f3823dae40
7 changed files with 796 additions and 61 deletions

View File

@@ -0,0 +1,227 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page import="com.pms.common.utils.*"%>
<%@ page import="java.util.*" %>
<%@include file= "/init.jsp" %>
<c:set var="now" value="<%=new java.util.Date() %>"/>
<c:set var="sysYear"><fmt:formatDate value="${now}" pattern="yyyy" /></c:set>
<%
// DB에서 메뉴명 조회 (공통 유틸 사용)
String menuObjId = request.getParameter("menuObjId");
String menuName = CommonUtils.getMenuName(menuObjId, "구매요청_품의서관리");
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><%=Constants.SYSTEM_NAME%></title>
<style>
body, html {
overflow-x: hidden;
width: 100%;
margin: 0;
padding: 0;
}
.pmsPopupForm tr:last-child td {
border-bottom: none;
}
.select2-selection__choice {
font-size: 11px;
background-color: #fff !important;
border: none !important;
margin-right: 0px !important;
}
.select2-selection__choice__remove {
display: contents !important;
}
.select2-container .select2-selection--multiple {
min-height: 20px !important;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
margin-top: 3.5px !important;
}
.select2-selection__rendered {
height: 18px !important;
}
/* frozen 컬럼 오른쪽 굵은 선 제거 (헤더) */
.tabulator .tabulator-header .tabulator-frozen-left {
border-right: none !important;
}
/* frozen 컬럼 기본 두꺼운 테두리 제거 */
.tabulator .tabulator-frozen-left {
border-right: none !important;
}
/* 체크박스 컬럼 오른쪽에 얇은 구분선 추가 (데이터 행만) */
.tabulator .tabulator-tableholder .tabulator-table .tabulator-row .tabulator-cell.tabulator-frozen-left {
border-right: 1px solid #ddd !important;
}
</style>
<script>
var _tabulGrid;
$(document).ready(function(){
// DOM 렌더링 완료 후 그리드 높이 계산
setTimeout(function() {
fnc_calculateContentHeight("gridDiv", 10);
}, 100);
$(window).resize(function() {
fnc_calculateContentHeight("gridDiv", 10);
});
$('.select2').select2();
$("input[type=text]").keyup(function(e){
if(e.keyCode == 13){
$("#btnSearch").trigger("click");
}
});
// 조회
$("#btnSearch").click(function(){
fn_search();
});
// 결재상신
$("#btnApproval").click(function(){
var selectedData = _tabulGrid.getSelectedData();
if(selectedData.length<1){
Swal.fire("결재상신할 행을 선택해주십시오.");
return false;
}else if(selectedData.length>1){
Swal.fire("한번에 한개의 결재만 가능합니다.");
return false;
}else{
var targetStatus = fnc_checkNull(selectedData[0].STATUS_TITLE);
var status = fnc_checkNull(selectedData[0].STATUS);
if(targetStatus == "결재완료" || targetStatus == "결재중" || status == "cancel"){
Swal.fire("작성중/결재반려인 상태만 결재상신 가능합니다.");
return false;
}else{
if(confirm("결재상신 하시겠습니까?")){
var objId = fnc_checkNull(selectedData[0].OBJID);
var title = encodeURIComponent("품의서 결재");
window.open("/approval/registApproval.do?targetType=PROPOSAL&targetObjId="+objId+"&approvalTitle="+title,"registApproval","width=700,height=700");
}
}
}
});
fn_search();
_fnc_datepick();
});
// 그리드 컬럼 정의
var columns = [
{title:'OBJID', field:'OBJID', visible: false},
{title:'STATUS', field:'STATUS', visible: false},
{headerHozAlign:'center', hozAlign:'center', title:"품의서 No", field:"PROPOSAL_NO", widthGrow:1.2, frozen:true,
formatter: fnc_createGridAnchorTag,
cellClick : function(e, cell) {
fn_openProposalFormPopUp(cell.getData().OBJID);
}
},
{headerHozAlign:'center', hozAlign:'left', title:"프로젝트번호", field:"PROJECT_NUMBER", widthGrow:1.3},
{headerHozAlign:'center', hozAlign:'center', title:"구매유형", field:"PURCHASE_TYPE_NAME", widthGrow:1.0},
{headerHozAlign:'center', hozAlign:'center', title:"주문유형", field:"ORDER_TYPE_NAME", widthGrow:1.0},
{headerHozAlign:'center', hozAlign:'center', title:"제품구분", field:"PRODUCT_NAME_TITLE", widthGrow:1.0},
{headerHozAlign:'center', hozAlign:'left', title:"품번", field:"PART_NO", widthGrow:1.5},
{headerHozAlign:'center', hozAlign:'left', title:"품명", field:"PART_NAME", widthGrow:1.8},
{headerHozAlign:'center', hozAlign:'center', title:"결재상태", field:"STATUS_TITLE", widthGrow:1.0,
formatter:fnc_createGridAnchorTag,
cellClick:function(e, cell){
var statusTitle = fnc_checkNull(cell.getData().STATUS_TITLE);
if(statusTitle == "결재중" || statusTitle == "결재완료" || statusTitle == "반려"){
fnc_approvalDetail(cell.getData().APPROVAL_OBJID, cell.getData().ROUTE_OBJID);
}
}
},
{headerHozAlign:'center', hozAlign:'center', title:"작성일", field:"REGDATE_TITLE", widthGrow:1.0}
];
// 검색 - 구매요청_품의서 전용 API 호출
function fn_search(){
_tabulGrid = fnc_tabul_search(_tabul_layout_fitColumns, _tabulGrid, "/salesMng/purchaseRegProposalMngGridList.do", columns, true);
}
// 품의서 상세 팝업
function fn_openProposalFormPopUp(objId){
var url = "/salesMng/proposalFormPopUp.do?PROPOSAL_OBJID=" + fnc_checkNull(objId);
window.open(url, "proposalFormPopUp", "width=1200,height=900,scrollbars=yes,resizable=yes");
}
function _fnc_datepick(){
var $dateinput = $("input.date_icon");
for(var i=0; i<$dateinput.length; i++){
$dateinput.eq(i).attr("size","10");
$dateinput.eq(i).datepicker({
changeMonth:true,
changeYear:true
});
}
}
</script>
</head>
<body>
<form name="form1" id="form1" action="" method="post">
<input type="hidden" name="actionType" id="actionType" value="" />
<div class="min_part_enroll">
<div class="content-box">
<div class="content-box-s">
<div class="plm_menu_name_gdnsi">
<h2>
<span><%=menuName%></span>
</h2>
<div class="btnArea">
<input type="button" value="조회" class="plm_btns" id="btnSearch">
<input type="button" value="결재상신" class="plm_btns" id="btnApproval" style="background:#17a2b8; color:white;">
</div>
</div>
<div id="plmSearchZon">
<table>
<tbody>
<tr>
<td class="align_r"><label>품의서 No</label></td>
<td>
<input type="text" name="SEARCH_PROPOSAL_NO" id="SEARCH_PROPOSAL_NO" style="width:150px;" value="${param.SEARCH_PROPOSAL_NO}"/>
</td>
<td class="align_r"><label>프로젝트번호</label></td>
<td>
<input type="text" name="SEARCH_PROJECT_NO" id="SEARCH_PROJECT_NO" style="width:150px;" value="${param.SEARCH_PROJECT_NO}"/>
</td>
<td class="align_r"><label>결재상태</label></td>
<td>
<select name="SEARCH_STATUS" id="SEARCH_STATUS" class="select2" style="width:130px;">
<option value="">전체</option>
<option value="create">작성중</option>
<option value="inProcess">결재중</option>
<option value="approvalComplete">결재완료</option>
<option value="reject">반려</option>
</select>
</td>
<td class="align_r"><label>작성일</label></td>
<td>
<input type="text" name="regdate_start" id="regdate_start" style="width:110px;" autocomplete="off" value="${param.regdate_start}" class="date_icon">~
<input type="text" name="regdate_end" id="regdate_end" style="width:110px;" autocomplete="off" value="${param.regdate_end}" class="date_icon">
</td>
</tr>
</tbody>
</table>
</div>
<%@include file= "/WEB-INF/view/common/common_gridArea.jsp" %>
</div>
</div>
</div>
</form>
</body>
<style>
.container::-webkit-scrollbar-thumb {background: linear-gradient(to bottom, #f5d78e, #f5d78e) !important;}
.container::-webkit-scrollbar-track {background-color: white !important;}
.container::-webkit-scrollbar-button { display: none !important;}
</style>
</html>

View File

@@ -203,28 +203,8 @@ var columns = [
fn_openSalesRequestFormPopUp(data.OBJID);
}
}
,{headerHozAlign : 'center', hozAlign : 'center', title : "요청인", field :"REQUEST_USER_NAME" , widthGrow:1.1,
// 요청인: 구매요청서 작성 시에만 표시
formatter: function(cell, formatterParams, onRendered){
var data = cell.getData();
var hasPurchaseRequest = fnc_checkNull(data.HAS_PURCHASE_REQUEST);
if(hasPurchaseRequest == 'Y') {
return fnc_checkNull(data.REQUEST_USER_NAME);
}
return '-';
}
}
,{headerHozAlign : 'center', hozAlign : 'center', title : "입고요청일", field :"DELIVERY_REQUEST_DATE" , widthGrow:1.1,
// 입고요청일: 구매요청서 작성 시에만 표시
formatter: function(cell, formatterParams, onRendered){
var data = cell.getData();
var hasPurchaseRequest = fnc_checkNull(data.HAS_PURCHASE_REQUEST);
if(hasPurchaseRequest == 'Y') {
return fnc_checkNull(data.DELIVERY_REQUEST_DATE);
}
return '-';
}
}
,{headerHozAlign : 'center', hozAlign : 'center', title : "요청인", field :"REQUEST_USER_NAME" , widthGrow:1.1 }
,{headerHozAlign : 'center', hozAlign : 'center', title : "입고요청일", field :"DELIVERY_REQUEST_DATE" , widthGrow:1.1 }
,{headerHozAlign : 'center', hozAlign : 'center', title : "작성일", field :"REGDATE_TITLE" , widthGrow:1.1 }
,{headerHozAlign : 'center', hozAlign : 'center', title : "상태", field :"STATUS_TITLE" , widthGrow:1.1 }
];
@@ -480,10 +460,9 @@ function fn_formPopUp(objId,sales_request_objid){
}
/**
* 품의서 생성 함수
* - 선택된 구매요청서에서 단가 입력된 품목만 필터링
* 품의서 생성 함수 (구매요청서 전용)
* - 선택된 구매요청서에서 단가+공급업체 입력된 품목만 필터링
* - 이미 품의서가 생성된 품목은 제외
* - 하나의 품의서로 생성
*/
function fn_createProposal() {
// 1. 선택된 행 확인
@@ -510,9 +489,9 @@ function fn_createProposal() {
var selectedRow = selectedRows[0];
var salesRequestObjid = fnc_checkNull(selectedRow.OBJID);
// 2. 구매요청서의 품목 중 단가가 입력되고 품의서 미생성된 품목 조회
// 2. 구매요청서 품의서 대상 품목 조회 (전용 API)
$.ajax({
url: "/salesMng/getProposalTargetParts.do",
url: "/salesMng/getProposalTargetPartsFromPurchaseReg.do",
type: "POST",
data: {
SALES_REQUEST_MASTER_OBJID: salesRequestObjid
@@ -521,13 +500,13 @@ function fn_createProposal() {
success: function(response) {
if(response.resultFlag === "S") {
var targetParts = response.data;
var excludedParts = response.excludedParts || []; // 공급업체 미입력 품목
var excludedParts = response.excludedParts || [];
// 3. 대상 품목 확인
if(!targetParts || targetParts.length == 0) {
Swal.fire({
title: '알림',
text: '품의서를 생성할 품목이 없습니다.\n(단가공급업체가 모두 입력되고 품의서가 생성되지 않은 품목만 대상)',
text: '품의서를 생성할 품목이 없습니다.\n(단가+공급업체 입력, 품의서 미생성 품목만 대상)',
icon: 'info'
});
return;
@@ -536,14 +515,14 @@ function fn_createProposal() {
// 4. 품의서 생성 확인
var partCount = targetParts.length;
var partListHtml = targetParts.map(function(part) {
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
return '- ' + fnc_checkNull(part.PART_NO || part.part_no) + ' / ' + fnc_checkNull(part.PART_NAME || part.part_name);
}).join('<br/>');
// 공급업체 미입력으로 제외된 품목이 있는 경우 알림 추가
var excludedHtml = '';
if(excludedParts && excludedParts.length > 0) {
var excludedListHtml = excludedParts.map(function(part) {
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
return '- ' + fnc_checkNull(part.PART_NO || part.part_no) + ' / ' + fnc_checkNull(part.PART_NAME || part.part_name);
}).join('<br/>');
excludedHtml = '<div style="margin-top:15px; padding:10px; background-color:#fff3cd; border:1px solid #ffc107; border-radius:4px;">' +
@@ -569,7 +548,7 @@ function fn_createProposal() {
cancelButtonText: '취소'
}).then((result) => {
if (result.isConfirmed) {
fn_executeCreateProposal(salesRequestObjid, targetParts);
fn_executeCreateProposal(salesRequestObjid);
}
});
} else {
@@ -579,7 +558,7 @@ function fn_createProposal() {
if(excludedParts && excludedParts.length > 0) {
var excludedListHtml = excludedParts.map(function(part) {
return '- ' + fnc_checkNull(part.PART_NO) + ' / ' + fnc_checkNull(part.PART_NAME);
return '- ' + fnc_checkNull(part.PART_NO || part.part_no) + ' / ' + fnc_checkNull(part.PART_NAME || part.part_name);
}).join('<br/>');
excludedHtml = '<br/><br/><div style="text-align:left; padding:10px; background-color:#fff3cd; border:1px solid #ffc107; border-radius:4px;">' +
@@ -600,7 +579,7 @@ function fn_createProposal() {
error: function(xhr, status, error) {
Swal.fire({
title: '오류',
text: '서버 통신 중 오류가 발생했습니다.22',
text: '서버 통신 중 오류가 발생했습니다.',
icon: 'error'
});
}
@@ -608,22 +587,21 @@ function fn_createProposal() {
}
/**
* 품의서 생성 실행
* 품의서 생성 실행 (구매요청서 전용)
*/
function fn_executeCreateProposal(salesRequestObjid, targetParts) {
function fn_executeCreateProposal(salesRequestObjid) {
$.ajax({
url: "/salesMng/createProposalFromPurchaseList.do",
url: "/salesMng/createProposalFromPurchaseReg.do",
type: "POST",
data: {
SALES_REQUEST_MASTER_OBJID: salesRequestObjid,
TARGET_PARTS: JSON.stringify(targetParts)
SALES_REQUEST_MASTER_OBJID: salesRequestObjid
},
dataType: "json",
success: function(response) {
if(response.resultFlag === "S") {
Swal.fire({
title: '생성 완료',
text: '품의서가 생성되었습니다.\n품의서 관리에서 확인하세요.',
html: response.message || '품의서가 생성되었습니다.',
icon: 'success'
}).then(() => {
fn_search(); // 목록 새로고침