품의서 양식 개발, 입고관리 등...

This commit is contained in:
2025-12-02 15:10:41 +09:00
parent f97399d45b
commit 4c1967cd63
10 changed files with 1133 additions and 73 deletions

View File

@@ -39,6 +39,11 @@ body {
.tabulator-row.level-8 { background-color: #dce6f1 !important; }
.tabulator-row.level-9 { background-color: #FFFFEB !important; }
.tabulator-row.level-10 { background-color: #ffffff !important; }
/* 편집 가능한 컬럼 헤더 스타일 */
.editable-header {
background-color: #fff9c4 !important;
}
</style>
<script>
var _tabulGrid;
@@ -308,6 +313,7 @@ function fn_initGrid() {
width: 100,
title: '자급/사급',
field: 'SUPPLY_TYPE',
titleFormatter: function() { return '<span class="editable-header">자급/사급</span>'; },
editor: 'list',
editorParams: {
values: ['자급', '사급']
@@ -340,6 +346,7 @@ function fn_initGrid() {
width: 100,
title: '소재',
field: 'RAW_MATERIAL',
titleFormatter: function() { return '<span class="editable-header">소재</span>'; },
editor: 'list',
editorParams: {
values: materialList // 로드된 소재 목록 사용
@@ -367,6 +374,7 @@ function fn_initGrid() {
width: 100,
title: '사이즈',
field: 'SIZE',
titleFormatter: function() { return '<span class="editable-header">사이즈</span>'; },
editor: 'list',
editorParams: function(cell) {
// 선택된 소재에 따라 동적으로 사이즈 목록 로드
@@ -446,6 +454,7 @@ function fn_initGrid() {
width: 100,
title: '소재소요량',
field: 'REQUIRED_QTY',
titleFormatter: function() { return '<span class="editable-header">소재소요량</span>'; },
editor: 'number',
editorParams: {
min: 0,
@@ -495,6 +504,7 @@ function fn_initGrid() {
width: 100,
title: '제작수량',
field: 'PRODUCTION_QTY',
titleFormatter: function() { return '<span class="editable-header">제작수량</span>'; },
editor: 'number',
editorParams: {
min: 0,
@@ -521,6 +531,7 @@ function fn_initGrid() {
width: 150,
title: '가공업체',
field: 'PROCESSING_VENDOR',
titleFormatter: function() { return '<span class="editable-header">가공업체</span>'; },
editor: 'list',
editorParams: {
values: ['업체A', '업체B', '업체C'] // TODO: 실제 가공업체 목록으로 교체
@@ -532,6 +543,7 @@ function fn_initGrid() {
width: 100,
title: '가공납기',
field: 'PROCESSING_DEADLINE',
titleFormatter: function() { return '<span class="editable-header">가공납기</span>'; },
editor: 'date'
},
{
@@ -540,6 +552,7 @@ function fn_initGrid() {
width: 100,
title: '연삭납기',
field: 'GRINDING_DEADLINE',
titleFormatter: function() { return '<span class="editable-header">연삭납기</span>'; },
editor: 'date'
},
{

View File

@@ -6,6 +6,11 @@
<%@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>
@@ -75,44 +80,44 @@ $(document).ready(function(){
var columns = [
/* {headerHozAlign : 'center', hozAlign : 'center', width : '50', title : '년도', field : 'CM_YEAR' }, */
{headerHozAlign : 'center', hozAlign : 'left', width : '110', title : '고객사', field : 'CUSTOMER_NAME' },
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '프로젝트명', field : 'CUSTOMER_PROJECT_NAME' },
{headerHozAlign : 'center', hozAlign : 'left', width : '200', title : '유닛명', field : 'UNIT_NAME' },
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '프로젝트번호', field : 'PROJECT_NO',
{headerHozAlign : 'center', hozAlign : 'left', width : '120', title : '고객사', field : 'CUSTOMER_NAME' },
//{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '프로젝트명', field : 'CUSTOMER_PROJECT_NAME' },
//{headerHozAlign : 'center', hozAlign : 'left', width : '200', title : '유닛명', field : 'UNIT_NAME' },
{headerHozAlign : 'center', hozAlign : 'center', width : '130', title : '프로젝트번호', field : 'PROJECT_NO',
/* formatter:fnc_createGridAnchorTag,
cellClick:function(e, cell){
var objid = fnc_checkNull(cell.getData().CONTRACT_OBJID);
openProjectFormPopUp(objid);
} */
},
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주번호', field : 'PURCHASE_ORDER_NO',
{headerHozAlign : 'center', hozAlign : 'center', width : '130', title : '발주번호', field : 'PURCHASE_ORDER_NO',
formatter:fnc_createGridAnchorTag,
cellClick:function(e, cell){
var objId = fnc_checkNull(cell.getData().OBJID);
fn_formPopUp(objId);
}
},
{headerHozAlign : 'center', hozAlign : 'center', /*width : '73',*/ title : '동시', field : "MULTI_YN" },
{headerHozAlign : 'center', hozAlign : 'left', width : '150', title : '발주서_제목', field : 'TITLE' },
{headerHozAlign : 'center', hozAlign : 'center', width : '85', title : '입고요청일', field : 'DELIVERY_DATE' },
{headerHozAlign : 'center', hozAlign : 'left', width : '120', title : '구매/제작업체명', field : 'PARTNER_NAME' },
{headerHozAlign : 'center', hozAlign : 'center', width : '78', title : '구매담당', field : 'SALES_MNG_USER_NAME' },
{headerHozAlign : 'center', hozAlign : 'center', width : '78', title : '발주일', field : 'REGDATE' },
{headerHozAlign : 'center', hozAlign : 'right', width : '78', title : '발주수량', field : 'TOTAL_PO_QTY',
//{headerHozAlign : 'center', hozAlign : 'center', /*width : '73',*/ title : '동시', field : "MULTI_YN" },
{headerHozAlign : 'center', hozAlign : 'left', /* width : '180',*/ title : '발주서_제목', field : 'TITLE' },
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '입고요청일', field : 'DELIVERY_DATE' },
{headerHozAlign : 'center', hozAlign : 'left', width : '170', title : '구매/제작업체명', field : 'PARTNER_NAME' },
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '구매담당', field : 'SALES_MNG_USER_NAME' },
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '발주일', field : 'REGDATE' },
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '발주수량', field : 'TOTAL_PO_QTY',
formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false }
},
{headerHozAlign : 'center', hozAlign : 'center', width : '78', title : '입고일', field : 'CUR_DELIVERY_DATE' },
{headerHozAlign : 'center', hozAlign : 'center', width : '70', title : '입고자', field : 'CUR_RECEIVER_NAME' },
{headerHozAlign : 'center', hozAlign : 'right', width : '75', title : '입고수량', field : 'TOTAL_DELIVERY_QTY',
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '입고일', field : 'CUR_DELIVERY_DATE' },
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '입고자', field : 'CUR_RECEIVER_NAME' },
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '입고수량', field : 'TOTAL_DELIVERY_QTY',
formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false }
},
{headerHozAlign : 'center', hozAlign : 'right', width : '85', title : '미입고수량', field : 'NON_DELIVERY_QTY',
{headerHozAlign : 'center', hozAlign : 'right', width : '100', title : '미입고수량', field : 'NON_DELIVERY_QTY',
formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false }
},
/* {headerHozAlign : 'center', hozAlign : 'right', width : '90', title : '부적합수량', field : 'TOTAL_DEFECT_QTY',
formatter:"money", formatterParams:{thousand:",", symbolAfter:"p", precision:false }
}, */
{headerHozAlign : 'center', hozAlign : 'center', width : '75', title : '입고결과', field : 'DELIVERY_STATUS',
{headerHozAlign : 'center', hozAlign : 'center', width : '100', title : '입고결과', field : 'DELIVERY_STATUS',
formatter:fnc_createGridAnchorTag,
cellClick:function(e, cell){
var objId = fnc_checkNull(cell.getData().OBJID);
@@ -293,7 +298,7 @@ function fn_formPopUp(objId){
<div class="content-box-s">
<div class="plm_menu_name_gdnsi">
<h2>
<span>입고관리_입고결과등록</span>
<span><%=menuName%></span>
</h2>
<div class="btnArea">
<input type="button" class="plm_btns" value="조회" id="btnSearch">

View File

@@ -1806,8 +1806,8 @@ function fn_price_save(){
<div class="plm_btn_wrap" style="padding:0 8 0 8; text-align: right;">
<% if(isModify){ %>
<c:if test="${empty info || empty info.MULTI_YN || info.MULTI_YN eq 'Y' and info.MULTI_MASTER_YN eq 'Y'}">
<input type="button" value="행추가" class="plm_btns" id="btnAdd" name="btnAdd" style="background:#dfeffc">
<input type="button" value="행삭제" class="plm_btns" id="btnDel" name="btnDel" style="background:#dfeffc">
<!-- <input type="button" value="행추가" class="plm_btns" id="btnAdd" name="btnAdd" style="background:#dfeffc">
<input type="button" value="행삭제" class="plm_btns" id="btnDel" name="btnDel" style="background:#dfeffc"> -->
<input type="button" value="저장" class="plm_btns" id="btnSave" name="btnSave" style="background:#dfeffc">
<c:if test="${!empty info && !empty info.OBJID && !empty info.WRITER }">
<!-- 240305 막음(목록에서만 상신)

View File

@@ -0,0 +1,893 @@
<%@ 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"%>
<%
// 결재 정보 매핑
List approvalList = (List)request.getAttribute("approvalList");
Map<Integer, Map> approvalMap = new HashMap<Integer, Map>();
Map<Integer, Map> referenceMap = new HashMap<Integer, Map>();
if(approvalList != null) {
for(Object obj : approvalList) {
Map item = (Map)obj;
Integer seq = null;
Object seqObj = item.get("SEQ");
if(seqObj != null) {
if(seqObj instanceof Number) {
seq = ((Number)seqObj).intValue();
} else {
seq = Integer.parseInt(seqObj.toString());
}
}
if(seq != null) {
approvalMap.put(seq, item);
}
}
}
// 결재자 정보 (직급별)
String[] approvalNames = new String[10];
String[] approvalDates = new String[10];
String[] approvalStatus = new String[10];
for(int i = 1; i <= 9; i++) {
Map approver = approvalMap.get(i);
if(approver != null) {
approvalNames[i] = CommonUtils.checkNull(approver.get("TARGET_USER_NAME"));
approvalDates[i] = CommonUtils.checkNull(approver.get("PROC_DATE"));
approvalStatus[i] = CommonUtils.checkNull(approver.get("STATUS"));
} else {
approvalNames[i] = "";
approvalDates[i] = "";
approvalStatus[i] = "";
}
}
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><%=Constants.SYSTEM_NAME%> - 구매품의서</title>
<c:set var="now" value="<%=new java.util.Date() %>"/>
<c:set var="sysYear"><fmt:formatDate value="${now}" pattern="yyyy" /></c:set>
<style>
@page {
size: A4;
margin: 10mm;
}
@media print {
body {
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
.no-print {
display: none !important;
}
}
* {
box-sizing: border-box;
}
body {
font-family: 'Malgun Gothic', '맑은 고딕', sans-serif;
font-size: 12px;
margin: 0;
padding: 10px;
background: #fff;
overflow-x: hidden;
}
.proposal-container {
width: 100%;
max-width: 100%;
margin: 0 auto;
border: none;
padding: 0;
box-sizing: border-box;
}
.proposal-title {
text-align: center;
font-size: 28px;
font-weight: bold;
letter-spacing: 20px;
padding: 15px 0;
border-bottom: 2px solid #000;
}
.header-section {
display: flex;
border-bottom: 1px solid #000;
border-inline: 2px solid #000;
}
.header-left {
flex: 0 0 auto;
width: 35%;
min-width: 200px;
border-right: 1px solid #000;
}
.header-right {
flex: 1;
min-width: 0;
}
/* 하단 기본정보 섹션 (수신및참조 ~ 제목) */
.sub-info-section {
border-bottom: 1px solid #000;
border-inline: 2px solid #000;
}
.sub-info-section .info-table {
width: 100%;
}
.sub-info-section .info-table td.label {
width: 90px;
min-width: 90px;
}
.sub-info-section .info-table td.value {
width: auto;
}
.info-table {
width: 100%;
border-collapse: collapse;
}
.info-table td {
border: 1px solid #999;
padding: 2px 4px;
height: 26px;
vertical-align: middle;
}
.info-table .label {
background-color: #f5f5f5;
font-weight: bold;
width: 90px;
min-width: 90px;
text-align: center;
}
.info-table .value {
text-align: left;
}
/* 결재란 스타일 */
.approval-table {
width: 100%;
border-collapse: collapse;
}
.approval-table td, .approval-table th {
border: 1px solid #999;
text-align: center;
vertical-align: middle;
padding: 2px;
}
.approval-table .header-row td {
background-color: #f5f5f5;
font-weight: bold;
height: 22px;
font-size: 11px;
}
.approval-table .sign-cell {
height: 50px;
min-width: 45px;
position: relative;
}
.approval-table .sign-cell .sign-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
}
.approval-table .sign-cell .sign-number {
position: absolute;
top: 2px;
left: 4px;
font-size: 10px;
color: #ff0066;
font-weight: bold;
}
.approval-table .sign-cell .sign-name {
font-size: 11px;
}
.approval-table .sign-cell .sign-image {
width: 35px;
height: 35px;
border: 2px solid #ff0066;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin: 2px auto;
}
.approval-table .date-cell {
height: 40px;
font-size: 10px;
line-height: 1.2;
}
.approval-table .type-cell {
width: 25px;
min-width: 25px;
background-color: #f5f5f5;
font-weight: bold;
writing-mode: vertical-rl;
text-orientation: mixed;
}
.approval-table .position-cell {
width: 30px;
background-color: #f5f5f5;
font-weight: bold;
}
/* 중간 정보 섹션 */
.middle-section {
border-bottom: 1px solid #000;
border-inline: 2px solid #000;
}
.middle-table {
width: 100%;
border-collapse: collapse;
}
.middle-table td, .middle-table th {
border: 1px solid #999;
padding: 5px 8px;
text-align: center;
vertical-align: middle;
}
.middle-table .header-cell {
background-color: #ebf1de;
font-weight: bold;
}
.middle-table .date-header {
background-color: #ffff99;
}
.middle-table .total-header {
background-color: #dce6f1;
}
.middle-table .total-value {
background-color: #ffffcc;
font-weight: bold;
text-align: right;
font-size: 14px;
}
/* 품목 테이블 */
.item-section {
border-bottom: 1px solid #000;
border-inline: 2px solid #000;
}
.item-table {
width: 100%;
border-collapse: collapse;
}
.item-table th, .item-table td {
border: 1px solid #999;
padding: 1px 2px;
text-align: center;
vertical-align: middle;
}
.item-table th {
background-color: #f5f5f5;
font-weight: bold;
height: 30px;
}
.item-table td {
height: 35px;
}
.item-table .text-left {
text-align: left;
}
.item-table .text-right {
text-align: right;
}
.item-table .total-row td {
background-color: #fff;
font-weight: bold;
}
.reference-table {
width: 100%;
border-collapse: collapse;
}
.reference-table td {
border: 1px solid #999;
padding: 8px;
}
.reference-table .label {
background-color: #f5f5f5;
font-weight: bold;
width: 80px;
text-align: center;
}
/* 버튼 영역 */
.btn-area {
text-align: center;
padding: 15px;
background: #f5f5f5;
height: 50px;
display: flex;
align-items: center;
justify-content: right;
}
.btn-area .plm_btns {
margin: 0 5px;
}
/* 개정 정보 */
.revision-info {
text-align: right;
font-size: 11px;
color: #ff0000;
padding: 5px 10px;
border-bottom: 1px solid #000;
}
/* 수신및참조 버튼 */
.edit-btn {
background: #e0e0e0;
border: 1px solid #999;
padding: 2px 8px;
font-size: 11px;
cursor: pointer;
}
/* 입력 필드 스타일 */
.no-print-border {
border: 1px solid #ccc;
font-size: 12px;
}
@media print {
.no-print-border {
border: none !important;
background: transparent !important;
}
select.no-print-border {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
}
.text-center {
text-align: center;
}
</style>
<script>
$(document).ready(function(){
// 닫기 버튼
$("#btnClose").click(function(){
self.close();
});
// 인쇄 버튼
$("#btnPrint").click(function(){
window.print();
});
// 저장 버튼
$("#btnSave").click(function(){
fn_save();
});
// 날짜 피커 초기화
$(".date_icon").datepicker({
dateFormat: 'yy-mm-dd',
changeMonth: true,
changeYear: true
});
});
// 숫자 포맷팅
function formatNumber(num) {
if(num == null || num == '') return '0';
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
// 저장 함수
function fn_save(){
// 품목 정보 수집
var partList = [];
$(".part-row").each(function(){
// data-part-objid를 문자열로 가져옴 (attr 사용)
var partObjId = $(this).attr("data-part-objid");
var remark = $(this).find(".part-remark").val();
var deliveryDate = $(this).find(".part-delivery-date").val();
var unit = $(this).find(".part-unit").val();
partList.push({
PART_OBJID: String(partObjId),
REMARK: remark,
DELIVERY_REQUEST_DATE: deliveryDate,
UNIT: unit
});
});
$.ajax({
url: "/salesMng/saveProposal.do",
type: "POST",
data: {
PROPOSAL_OBJID: $("#OBJID").val(),
RECIPIENT_REF: $("#RECIPIENT_REF").val(),
EXECUTOR: $("#EXECUTOR").val(),
EXECUTION_DATE: $("#EXECUTION_DATE").val(),
TITLE: $("#TITLE").val(),
PART_LIST: JSON.stringify(partList)
},
dataType: "json",
success: function(data){
if(data.resultFlag == "S"){
Swal.fire({
icon: 'success',
title: '저장 완료',
text: data.message
});
} else {
Swal.fire({
icon: 'error',
title: '저장 실패',
text: data.message
});
}
},
error: function(jqxhr, status, error){
Swal.fire({
icon: 'error',
title: '오류',
text: '저장 중 오류가 발생했습니다.'
});
}
});
}
</script>
</head>
<body>
<form name="form1" id="form1" method="post">
<input type="hidden" name="OBJID" id="OBJID" value="${resultMap.OBJID}" />
<div class="proposal-container">
<!-- 제목 -->
<div class="proposal-title">구 매 품 의 서</div>
<!-- 상단 섹션: 기본정보 + 결재란 (품의번호~기안자까지만) -->
<div class="header-section">
<!-- 왼쪽: 기본 정보 (품의번호, 작성일자, 기안부서, 기안자) -->
<div class="header-left">
<table class="info-table" style="height:100%">
<tr>
<td class="label">품 의 번 호</td>
<td class="value" colspan="3">${resultMap.PROPOSAL_NO}</td>
</tr>
<tr>
<td class="label">작 성 일 자</td>
<td class="value" colspan="3">${resultMap.REGDATE_TITLE} <c:if test="${not empty resultMap.REGDATE}"><fmt:formatDate value="${resultMap.REGDATE}" pattern="HH:mm"/></c:if></td>
</tr>
<tr>
<td class="label">기 안 부 서</td>
<td class="value" colspan="3">
<c:choose>
<c:when test="${not empty resultMap.WRITER_NAME}">
<%
String writerDeptName = (String)((Map)request.getAttribute("resultMap")).get("WRITER_NAME");
if(writerDeptName != null && writerDeptName.contains(" ")) {
out.print(writerDeptName.substring(0, writerDeptName.indexOf(" ")));
} else {
out.print(writerDeptName != null ? writerDeptName : "-");
}
%>
</c:when>
<c:otherwise>-</c:otherwise>
</c:choose>
</td>
</tr>
<tr>
<td class="label">기 안 자</td>
<td class="value" colspan="3">
<c:choose>
<c:when test="${not empty resultMap.WRITER_NAME}">
<%
String writerName = (String)((Map)request.getAttribute("resultMap")).get("WRITER_NAME");
if(writerName != null && writerName.contains(" ")) {
out.print(writerName.substring(writerName.lastIndexOf(" ") + 1));
} else {
out.print(writerName != null ? writerName : "-");
}
%>
</c:when>
<c:otherwise>-</c:otherwise>
</c:choose>
</td>
</tr>
</table>
</div>
<!-- 오른쪽: 결재란 -->
<div class="header-right">
<table class="approval-table">
<!-- 결재 헤더 -->
<tr class="header-row">
<td rowspan="3" class="type-cell">결재</td>
<td>직장</td>
<td>대리</td>
<td>팀장</td>
<td>이사</td>
<td>상무이<br/>사</td>
<td>부사장</td>
<td>대표이<br/>사</td>
</tr>
<tr>
<td class="sign-cell">
<c:if test="${not empty approvalList[0]}">
<span class="sign-number">1</span>
<div class="sign-image">
<span class="sign-name">${approvalList[0].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
<td class="sign-cell">
<c:if test="${not empty approvalList[1]}">
<span class="sign-number">2</span>
<div class="sign-image">
<span class="sign-name">${approvalList[1].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
<td class="sign-cell">
<c:if test="${not empty approvalList[2]}">
<span class="sign-number">3</span>
<div class="sign-image">
<span class="sign-name">${approvalList[2].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
<td class="sign-cell">
<c:if test="${not empty approvalList[3]}">
<span class="sign-number">4</span>
<div class="sign-image">
<span class="sign-name">${approvalList[3].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
<td class="sign-cell">
<c:if test="${not empty approvalList[4]}">
<span class="sign-number">5</span>
<div class="sign-image">
<span class="sign-name">${approvalList[4].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
<td class="sign-cell">
<c:if test="${not empty approvalList[5]}">
<span class="sign-number">6</span>
<div class="sign-image">
<span class="sign-name">${approvalList[5].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
<td class="sign-cell">
<c:if test="${not empty approvalList[6]}">
<span class="sign-number">7</span>
<div class="sign-image">
<span class="sign-name">${approvalList[6].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
</tr>
<tr>
<td class="date-cell">
<c:if test="${not empty approvalList[0].PROC_DATE}">
${approvalList[0].PROC_DATE}
</c:if>
</td>
<td class="date-cell">
<c:if test="${not empty approvalList[1].PROC_DATE}">
${approvalList[1].PROC_DATE}
</c:if>
</td>
<td class="date-cell">
<c:if test="${not empty approvalList[2].PROC_DATE}">
${approvalList[2].PROC_DATE}
</c:if>
</td>
<td class="date-cell">
<c:if test="${not empty approvalList[3].PROC_DATE}">
${approvalList[3].PROC_DATE}
</c:if>
</td>
<td class="date-cell">
<c:if test="${not empty approvalList[4].PROC_DATE}">
${approvalList[4].PROC_DATE}
</c:if>
</td>
<td class="date-cell">
<c:if test="${not empty approvalList[5].PROC_DATE}">
${approvalList[5].PROC_DATE}
</c:if>
</td>
<td class="date-cell">
<c:if test="${not empty approvalList[6].PROC_DATE}">
${approvalList[6].PROC_DATE}
</c:if>
</td>
</tr>
<!-- 합의 헤더 -->
<tr class="header-row">
<td rowspan="3" class="type-cell">합의</td>
<td>주임</td>
<td>팀장</td>
<td colspan="5"></td>
</tr>
<tr>
<td class="sign-cell">
<c:if test="${fn:length(approvalList) > 7 and not empty approvalList[7]}">
<span class="sign-number">8</span>
<div class="sign-image">
<span class="sign-name">${approvalList[7].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
<td class="sign-cell">
<c:if test="${fn:length(approvalList) > 8 and not empty approvalList[8]}">
<span class="sign-number">9</span>
<div class="sign-image">
<span class="sign-name">${approvalList[8].TARGET_USER_NAME}</span>
</div>
</c:if>
</td>
<td colspan="5"></td>
</tr>
<tr>
<td class="date-cell">
<c:if test="${fn:length(approvalList) > 7 and not empty approvalList[7].PROC_DATE}">
${approvalList[7].PROC_DATE}
</c:if>
</td>
<td class="date-cell">
<c:if test="${fn:length(approvalList) > 8 and not empty approvalList[8].PROC_DATE}">
${approvalList[8].PROC_DATE}
</c:if>
</td>
<td colspan="5"></td>
</tr>
</table>
</div>
</div>
<!-- 하단 기본정보 (수신및참조, 시행자, 시행일자, 제목) - 입력 가능 -->
<div class="sub-info-section">
<table class="info-table" style="border-top: none;">
<tr>
<td class="label">수신및참조</td>
<td class="value" colspan="3">
<input type="text" name="RECIPIENT_REF" id="RECIPIENT_REF" value="${resultMap.RECIPIENT_REF}" style="width:100%; box-sizing:border-box;" placeholder="구매자재팀,제조관리팀" class="no-print-border"/>
</td>
</tr>
<tr>
<td class="label">시&nbsp;행&nbsp;자</td>
<td class="value" colspan="3">
<input type="text" name="EXECUTOR" id="EXECUTOR" value="${resultMap.EXECUTOR}" style="width:100%; box-sizing:border-box;" class="no-print-border"/>
</td>
</tr>
<tr>
<td class="label">시행일자</td>
<td class="value" colspan="3">
<input type="text" name="EXECUTION_DATE" id="EXECUTION_DATE" value="${resultMap.EXECUTION_DATE_TITLE}" style="width:120px;" class="date_icon no-print-border" autocomplete="off"/>
</td>
</tr>
<tr>
<td class="label">제&nbsp;&nbsp;&nbsp;&nbsp;목</td>
<td class="value" colspan="3">
<input type="text" name="TITLE" id="TITLE" value="${resultMap.TITLE}" style="width:100%; box-sizing:border-box;" placeholder="[일반] 구매품의서(${resultMap.WRITER_DEPT})" class="no-print-border"/>
</td>
</tr>
</table>
</div>
<!-- 개정 정보 -->
<div class="revision-info">[구매품의서 개정 : 22.05.17]</div>
<!-- 중간 정보 섹션 -->
<div class="middle-section">
<table class="middle-table">
<tr>
<th rowspan="2" class="header-cell" style="width:50px;">구<br/>분</th>
<th class="header-cell" style="width:100px;">부 서</th>
<th class="header-cell" style="width:100px;">소속팀</th>
<th class="header-cell" style="width:100px;">날 짜</th>
<th class="" style="width:150px;">${resultMap.REGDATE_TITLE}</th>
<th class="total-header" style="width:100px;">총 합 계</th>
</tr>
<tr style="height: 50px;">
<td>
<c:choose>
<c:when test="${not empty resultMap.WRITER_NAME}">
<%
String writerDept = (String)((Map)request.getAttribute("resultMap")).get("WRITER_NAME");
if(writerDept != null && writerDept.contains(" ")) {
out.print(writerDept.substring(0, writerDept.indexOf(" ")));
} else {
out.print("-");
}
%>
</c:when>
<c:otherwise>-</c:otherwise>
</c:choose>
</td>
<td>
<c:choose>
<c:when test="${not empty resultMap.WRITER_NAME}">
<%
String writerTeam = (String)((Map)request.getAttribute("resultMap")).get("WRITER_NAME");
if(writerTeam != null && writerTeam.contains(" ")) {
out.print(writerTeam.substring(0, writerTeam.indexOf(" ")));
} else {
out.print("-");
}
%>
</c:when>
<c:otherwise>-</c:otherwise>
</c:choose>
</td>
<td class="header-cell">기 안 자</td>
<td>
<c:choose>
<c:when test="${not empty resultMap.WRITER_NAME}">
<%
String writerOnly = (String)((Map)request.getAttribute("resultMap")).get("WRITER_NAME");
if(writerOnly != null && writerOnly.contains(" ")) {
out.print(writerOnly.substring(writerOnly.lastIndexOf(" ") + 1));
} else {
out.print(writerOnly != null ? writerOnly : "-");
}
%>
</c:when>
<c:otherwise>-</c:otherwise>
</c:choose>
</td>
<td class="total-value">
<c:set var="totalAmount" value="0"/>
<c:forEach var="item" items="${partList}">
<c:set var="totalAmount" value="${totalAmount + (empty item.TOTAL_PRICE ? 0 : item.TOTAL_PRICE)}"/>
</c:forEach>
<fmt:formatNumber value="${totalAmount}" pattern="#,###"/>
</td>
</tr>
</table>
</div>
<!-- 품목 테이블 -->
<div class="item-section">
<table class="item-table">
<thead>
<tr>
<th style="width:40px;">No.</th>
<th style="width:150px;">목 적</th>
<th style="width:250px;">품명 / 규격</th>
<th style="width:100px;">납 기 일</th>
<th style="width:100px;">업 체 명</th>
<th style="width:60px;">수량</th>
<th style="width:50px;">단위</th>
<th style="width:80px;">단가</th>
<th style="width:100px;">합 계</th>
</tr>
</thead>
<tbody>
<c:choose>
<c:when test="${not empty partList}">
<c:forEach var="item" items="${partList}" varStatus="status">
<tr class="part-row" data-part-objid="${item.OBJID}">
<td>${status.count}</td>
<td class="text-left">
<input type="text" name="REMARK_${item.OBJID}" class="part-remark no-print-border" value="${item.REMARK}" style="width:100%; box-sizing:border-box;"/>
</td>
<td class="text-left">
${item.PART_NAME}
<c:if test="${not empty item.SPEC}">
<br/>(${item.SPEC})
</c:if>
</td>
<td class="text-center">
<input type="text" name="DELIVERY_DATE_${item.OBJID}" class="part-delivery-date date_icon no-print-border" value="${item.DELIVERY_REQUEST_DATE_TITLE}" style="width:100%; box-sizing:border-box;" autocomplete="off"/>
</td>
<td class="text-left">${item.VENDOR_NAME}</td>
<td class="text-right"><fmt:formatNumber value="${item.QTY}" pattern="#,###"/></td>
<td>
<select name="UNIT_${item.OBJID}" class="part-unit no-print-border" style="width:100%; box-sizing:border-box;">
<option value="">선택</option>
${code_map.unit_list}
</select>
<script>
$(function(){ $("select[name='UNIT_${item.OBJID}']").val("${item.UNIT}"); });
</script>
</td>
<td class="text-right"><fmt:formatNumber value="${item.UNIT_PRICE}" pattern="#,###"/></td>
<td class="text-right"><fmt:formatNumber value="${item.TOTAL_PRICE}" pattern="#,###"/></td>
</tr>
</c:forEach>
</c:when>
<c:otherwise>
<tr>
<td colspan="9" style="height:100px;">등록된 품목이 없습니다.</td>
</tr>
</c:otherwise>
</c:choose>
<!-- 빈 행 추가 (최소 4행 유지) -->
<c:if test="${fn:length(partList) < 4}">
<c:forEach begin="${fn:length(partList) + 1}" end="4">
<tr>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</c:forEach>
</c:if>
</tbody>
</table>
</div>
<!-- 참조문서 섹션 -->
<div class="reference-section">
<table class="reference-table">
<tr style="height: 50px;">
<td class="label" style="vertical-align: middle; width: 150px;">참 조 문 서</td>
<td style="vertical-align: top; padding: 10px;">선택된 문서가 없습니다.</td>
</tr>
</table>
</div>
</div>
<!-- 버튼 영역 -->
<div class="btn-area no-print">
<input type="button" value="저장" class="plm_btns" id="btnSave" style="background:#28a745; color:white;">
<input type="button" value="인쇄" class="plm_btns" id="btnPrint" style="background:#17a2b8; color:white;">
<input type="button" value="닫기" class="plm_btns" id="btnClose">
</div>
</form>
</body>
</html>

View File

@@ -200,7 +200,7 @@ function fn_search(){
// 품의서 상세 팝업
function fn_openProposalFormPopUp(objId){
var url = "/salesMng/proposalFormPopUp.do?PROPOSAL_OBJID=" + fnc_checkNull(objId);
window.open(url, "proposalFormPopUp", "width=1200,height=700,scrollbars=yes,resizable=yes");
window.open(url, "proposalFormPopUp", "width=1200,height=900,scrollbars=yes,resizable=yes");
}
function _fnc_datepick(){