Merge branch 'main' of https://g.wace.me/chpark/wace_plm into V2025121808
This commit is contained in:
@@ -44,6 +44,8 @@ $(function(){
|
||||
$("#PROJECT_NO").on("change select2:select", function(){
|
||||
var projectObjid = $(this).val();
|
||||
console.log("프로젝트번호 변경됨:", projectObjid);
|
||||
// PROJECT_OBJID hidden 필드에도 값 설정
|
||||
$("#PROJECT_OBJID").val(projectObjid);
|
||||
if(fnc_checkNull(projectObjid) != ""){
|
||||
fn_loadProjectInfo(projectObjid);
|
||||
} else {
|
||||
@@ -113,11 +115,25 @@ function fn_loadProjectInfo(projectObjid){
|
||||
$("#CATEGORY_CODE").val(info.category_code).trigger("change.select2");
|
||||
}
|
||||
|
||||
// 고객사 (C_ 접두어 제거)
|
||||
// 고객사 설정 (C_ 접두어 유무 모두 시도)
|
||||
if(fnc_checkNull(info.customer_objid) != ""){
|
||||
var customerObjid = info.customer_objid.replace("C_", "");
|
||||
console.log("고객사 설정:", customerObjid);
|
||||
$("#CUSTOMER_OBJID").val(customerObjid).trigger("change.select2");
|
||||
var customerObjid = info.customer_objid;
|
||||
console.log("고객사 원본값:", customerObjid);
|
||||
|
||||
// 먼저 원본값으로 시도
|
||||
$("#CUSTOMER_OBJID").val(customerObjid);
|
||||
if($("#CUSTOMER_OBJID").val() != customerObjid) {
|
||||
// C_ 제거 후 시도
|
||||
customerObjid = info.customer_objid.replace("C_", "");
|
||||
$("#CUSTOMER_OBJID").val(customerObjid);
|
||||
}
|
||||
if($("#CUSTOMER_OBJID").val() != customerObjid) {
|
||||
// C_ 추가 후 시도
|
||||
customerObjid = "C_" + info.customer_objid.replace("C_", "");
|
||||
$("#CUSTOMER_OBJID").val(customerObjid);
|
||||
}
|
||||
console.log("고객사 최종설정:", $("#CUSTOMER_OBJID").val());
|
||||
$("#CUSTOMER_OBJID").trigger("change.select2");
|
||||
}
|
||||
|
||||
// 품번
|
||||
@@ -166,11 +182,21 @@ function fn_clearProjectInfo(){
|
||||
|
||||
// 기존 데이터 로드 (수정 모드)
|
||||
function fn_loadExistingData(){
|
||||
// JSP EL로 기존 데이터 설정
|
||||
// JSP EL로 기존 데이터 설정 (resultMap 키는 소문자)
|
||||
<% if(info != null) { %>
|
||||
$("#PRODUCT_CODE").val("${resultMap.PRODUCT_CODE}").trigger("change");
|
||||
$("#CATEGORY_CODE").val("${resultMap.CATEGORY_CODE}").trigger("change");
|
||||
$("#CUSTOMER_OBJID").val("${resultMap.CUSTOMER_OBJID}").trigger("change");
|
||||
// 프로젝트번호 설정
|
||||
var projectObjid = "${resultMap.project_objid}";
|
||||
if(projectObjid) {
|
||||
$("#PROJECT_NO").val(projectObjid).trigger("change.select2");
|
||||
}
|
||||
// 제품구분
|
||||
$("#PRODUCT_CODE").val("${resultMap.product_code}").trigger("change.select2");
|
||||
// 주문유형
|
||||
$("#CATEGORY_CODE").val("${resultMap.category_code}").trigger("change.select2");
|
||||
// 생산유형
|
||||
$("#PRODUCTION_TYPE").val("${resultMap.production_type}").trigger("change.select2");
|
||||
// 고객사
|
||||
$("#CUSTOMER_OBJID").val("${resultMap.customer_objid}").trigger("change.select2");
|
||||
fn_calcTotalQty();
|
||||
<% } %>
|
||||
}
|
||||
@@ -254,8 +280,8 @@ function fn_save(){
|
||||
</script>
|
||||
<body>
|
||||
<form name="form1" id="form1" method="post">
|
||||
<input type="hidden" name="OBJID" id="OBJID" value="${resultMap.OBJID}">
|
||||
<input type="hidden" name="PROJECT_OBJID" id="PROJECT_OBJID" value="${resultMap.PROJECT_OBJID}">
|
||||
<input type="hidden" name="OBJID" id="OBJID" value="${resultMap.objid}">
|
||||
<input type="hidden" name="PROJECT_OBJID" id="PROJECT_OBJID" value="${resultMap.project_objid}">
|
||||
<input type="hidden" name="actionType" id="actionType" value="${actionType}">
|
||||
|
||||
<section>
|
||||
@@ -319,7 +345,7 @@ function fn_save(){
|
||||
</td>
|
||||
<td class="input_title"><label>요청납기<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="REQ_DEL_DATE" id="REQ_DEL_DATE" class="date_icon" value="${resultMap.REQ_DEL_DATE}">
|
||||
<input type="text" name="REQ_DEL_DATE" id="REQ_DEL_DATE" class="date_icon" value="${resultMap.req_del_date}">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -327,15 +353,15 @@ function fn_save(){
|
||||
<tr>
|
||||
<td class="input_title"><label>품번<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="PART_NO" id="PART_NO" value="${resultMap.PART_NO}">
|
||||
<input type="text" name="PART_NO" id="PART_NO" value="${resultMap.part_no}">
|
||||
</td>
|
||||
<td class="input_title"><label>품명<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<input type="text" name="PART_NAME" id="PART_NAME" value="${resultMap.PART_NAME}">
|
||||
<input type="text" name="PART_NAME" id="PART_NAME" value="${resultMap.part_name}">
|
||||
</td>
|
||||
<td class="input_title"><label>S/N</label></td>
|
||||
<td>
|
||||
<input type="text" name="SERIAL_NO" id="SERIAL_NO" value="${resultMap.SERIAL_NO}">
|
||||
<input type="text" name="SERIAL_NO" id="SERIAL_NO" value="${resultMap.serial_no}">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -343,15 +369,15 @@ function fn_save(){
|
||||
<tr>
|
||||
<td class="input_title"><label>수주수량<span class="required-mark">*</span></label></td>
|
||||
<td>
|
||||
<input type="number" name="ORDER_QTY" id="ORDER_QTY" min="0" value="${resultMap.ORDER_QTY}">
|
||||
<input type="number" name="ORDER_QTY" id="ORDER_QTY" min="0" value="${resultMap.order_qty}">
|
||||
</td>
|
||||
<td class="input_title"><label>추가생산수량</label></td>
|
||||
<td>
|
||||
<input type="number" name="EXTRA_PROD_QTY" id="EXTRA_PROD_QTY" min="0" value="${resultMap.EXTRA_PROD_QTY}" placeholder="0">
|
||||
<input type="number" name="EXTRA_PROD_QTY" id="EXTRA_PROD_QTY" min="0" value="${resultMap.extra_prod_qty}" placeholder="0">
|
||||
</td>
|
||||
<td class="input_title"><label>총생산수량</label></td>
|
||||
<td>
|
||||
<input type="text" name="TOTAL_PROD_QTY" id="TOTAL_PROD_QTY" class="readonly-field" readonly value="${resultMap.TOTAL_PROD_QTY}">
|
||||
<input type="text" name="TOTAL_PROD_QTY" id="TOTAL_PROD_QTY" class="readonly-field" readonly value="${resultMap.total_prod_qty}">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -359,7 +385,7 @@ function fn_save(){
|
||||
<tr>
|
||||
<td class="input_title"><label>고객사 요청사항</label></td>
|
||||
<td colspan="5">
|
||||
<input type="text" name="CUSTOMER_REQUEST" id="CUSTOMER_REQUEST" value="${resultMap.CUSTOMER_REQUEST}" style="width:100%;">
|
||||
<input type="text" name="CUSTOMER_REQUEST" id="CUSTOMER_REQUEST" value="${resultMap.customer_request}" style="width:100%;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -244,11 +244,9 @@ var columns = [
|
||||
width: 80,
|
||||
title: '완조립',
|
||||
field: 'ASSEMBLY_QTY',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell) {
|
||||
if(cell.getValue() > 0) {
|
||||
fn_openQtyDetailPopup(cell.getData().OBJID, 'ASSEMBLY');
|
||||
}
|
||||
fn_openProdResultPopup(cell.getData().OBJID, 'ASSEMBLY');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -259,11 +257,9 @@ var columns = [
|
||||
width: 70,
|
||||
title: '검사',
|
||||
field: 'INSPECTION_QTY',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell) {
|
||||
if(cell.getValue() > 0) {
|
||||
fn_openQtyDetailPopup(cell.getData().OBJID, 'INSPECTION');
|
||||
}
|
||||
fn_openProdResultPopup(cell.getData().OBJID, 'INSPECTION');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -274,11 +270,9 @@ var columns = [
|
||||
width: 90,
|
||||
title: '출하대기',
|
||||
field: 'SHIP_WAIT_QTY',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell) {
|
||||
if(cell.getValue() > 0) {
|
||||
fn_openQtyDetailPopup(cell.getData().OBJID, 'SHIP_WAIT');
|
||||
}
|
||||
fn_openProdResultPopup(cell.getData().OBJID, 'SHIP_WAIT');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -332,7 +326,7 @@ function fn_createProdPlan() {
|
||||
var checkedRows = getCheckedRows();
|
||||
|
||||
var popup_width = 900;
|
||||
var popup_height = 500;
|
||||
var popup_height = 400;
|
||||
var url = "/productionplanning/prodPlanFormPopup.do";
|
||||
|
||||
if(checkedRows.length === 1) {
|
||||
@@ -399,18 +393,16 @@ function fn_registProdResult() {
|
||||
}
|
||||
|
||||
var rowData = checkedRows[0];
|
||||
var popup_width = 1000;
|
||||
var popup_height = 700;
|
||||
var url = "/productionplanning/prodResultFormPopup.do?projectObjid=" + rowData.OBJID;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'prodResultPopup');
|
||||
// 실적유형 선택 없이 팝업 열기 (팝업에서 선택 가능)
|
||||
fn_openProdResultPopup(rowData.OBJID, '');
|
||||
}
|
||||
|
||||
// 수량 상세 팝업 (완조립, 검사, 출하대기 클릭 시)
|
||||
function fn_openQtyDetailPopup(projectObjid, qtyType) {
|
||||
var popup_width = 800;
|
||||
var popup_height = 500;
|
||||
var url = "/productionplanning/prodQtyDetailPopup.do?projectObjid=" + projectObjid + "&qtyType=" + qtyType;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'qtyDetailPopup');
|
||||
// 생산실적 등록/수정 팝업 (완조립, 검사, 출하대기 클릭 시)
|
||||
function fn_openProdResultPopup(projectObjid, resultType) {
|
||||
var popup_width = 1000;
|
||||
var popup_height = 700;
|
||||
var url = "/productionplanning/prodResultFormPopup.do?projectObjid=" + projectObjid + "&resultType=" + resultType;
|
||||
fn_centerPopup(popup_width, popup_height, url, 'prodResultPopup');
|
||||
}
|
||||
|
||||
// 선택된 행 가져오기 (Tabulator 선택 기능 사용)
|
||||
@@ -440,7 +432,7 @@ function getCheckedRows() {
|
||||
<div class="btnArea">
|
||||
<input type="button" class="plm_btns" value="조회" id="btnSearch">
|
||||
<input type="button" class="plm_btns" value="생산계획 생성" id="btnCreateProdPlan">
|
||||
<input type="button" class="plm_btns" value="작업지시 생성" id="btnCreateWorkOrder">
|
||||
<!-- <input type="button" class="plm_btns" value="작업지시 생성" id="btnCreateWorkOrder"> -->
|
||||
<input type="button" class="plm_btns" value="생산실적 등록" id="btnRegistProdResult">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,302 @@
|
||||
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
<%@ page import="com.pms.common.utils.*"%>
|
||||
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@include file= "/init_new.jsp" %>
|
||||
<c:set var="now" value="<%=new java.util.Date()%>" />
|
||||
<c:set var="today"><fmt:formatDate value="${now}" pattern="yyyy-MM-dd" /></c:set>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title><%=Constants.SYSTEM_NAME%></title>
|
||||
<style>
|
||||
.input_title {border-left:1px solid #ccc; background-color:#f5f5f5; font-weight:bold;}
|
||||
.pmsPopupForm tr:last-child td{border-bottom:1px solid #ccc;}
|
||||
.pmsPopupForm td { padding: 5px 8px; }
|
||||
.required-mark { color: red; font-weight: bold; margin-left: 2px; }
|
||||
.readonly-field { background-color: #eee !important; }
|
||||
/* 공통 버튼 숨기기 */
|
||||
.resetBtn, .excelBtn { display: none !important; }
|
||||
body { min-height: auto !important; }
|
||||
</style>
|
||||
</head>
|
||||
<script type="text/javascript" src="/js/tabulator/tabulator_custom.js"></script>
|
||||
<script>
|
||||
var grid;
|
||||
var _projectObjid = "${param.projectObjid}";
|
||||
var _resultType = "${param.resultType}";
|
||||
|
||||
// 실적유형 목록
|
||||
var _RESULT_TYPE_LIST = [
|
||||
{"CODE": "ASSEMBLY", "NAME": "완조립"},
|
||||
{"CODE": "INSPECTION", "NAME": "검사"},
|
||||
{"CODE": "SHIP_WAIT", "NAME": "출하대기"}
|
||||
];
|
||||
|
||||
$(function(){
|
||||
fnc_datepick();
|
||||
$(".select2").select2();
|
||||
|
||||
// 프로젝트 정보 로드
|
||||
if(_projectObjid) {
|
||||
fn_loadProjectInfo();
|
||||
}
|
||||
|
||||
// 그리드 초기화
|
||||
fn_initGrid();
|
||||
|
||||
// 실적 목록 조회
|
||||
fn_search();
|
||||
|
||||
// 행추가 버튼
|
||||
$("#btnAddRow").click(function(){
|
||||
fn_addRow();
|
||||
});
|
||||
|
||||
// 행삭제 버튼
|
||||
$("#btnDelRow").click(function(){
|
||||
fn_delRow();
|
||||
});
|
||||
|
||||
// 저장 버튼
|
||||
$("#btnSave").click(function(){
|
||||
fn_save();
|
||||
});
|
||||
});
|
||||
|
||||
// 날짜 선택기 초기화
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 프로젝트 정보 로드
|
||||
function fn_loadProjectInfo() {
|
||||
$.ajax({
|
||||
url: "/productionplanning/getProdPlanProjectInfo.do",
|
||||
type: "POST",
|
||||
data: { "projectObjid": _projectObjid },
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(data){
|
||||
if(data && data.result == "success" && data.info){
|
||||
var info = data.info;
|
||||
$("#PROJECT_NO").text(fnc_checkNull(info.project_no));
|
||||
$("#PART_NO").text(fnc_checkNull(info.part_no));
|
||||
$("#PART_NAME").text(fnc_checkNull(info.part_name));
|
||||
$("#ORDER_QTY").text(fnc_checkNull(info.order_qty));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 그리드 컬럼 정의
|
||||
var columns = [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", headerHozAlign:'center', hozAlign:"center", headerSort:false, width:30},
|
||||
{title:'OBJID', field:'OBJID', visible: false},
|
||||
{title:'실적유형', field:'RESULT_TYPE', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: "list",
|
||||
editorParams: {
|
||||
values: {"ASSEMBLY":"완조립", "INSPECTION":"검사", "SHIP_WAIT":"출하대기"}
|
||||
},
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val == 'ASSEMBLY') return '완조립';
|
||||
if(val == 'INSPECTION') return '검사';
|
||||
if(val == 'SHIP_WAIT') return '출하대기';
|
||||
return val;
|
||||
}
|
||||
},
|
||||
{title:'실적일자', field:'RESULT_DATE', headerHozAlign:'center', hozAlign:'center', width:110,
|
||||
editor: "input"
|
||||
},
|
||||
{title:'실적수량', field:'RESULT_QTY', headerHozAlign:'center', hozAlign:'right', width:90,
|
||||
editor: "number",
|
||||
formatter: "money", formatterParams: {thousand:",", precision:false}
|
||||
},
|
||||
{title:'S/N', field:'SERIAL_NO', headerHozAlign:'center', hozAlign:'left', width:120,
|
||||
editor: "input"
|
||||
},
|
||||
{title:'작업자', field:'WORKER_NAME', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: "input"
|
||||
},
|
||||
{title:'비고', field:'REMARK', headerHozAlign:'center', hozAlign:'left', minWidth:150,
|
||||
editor: "input"
|
||||
}
|
||||
];
|
||||
|
||||
// 그리드 초기화
|
||||
function fn_initGrid() {
|
||||
grid = new Tabulator("#grid", {
|
||||
layout: "fitColumns",
|
||||
height: "calc(100vh - 200px)",
|
||||
columns: columns,
|
||||
data: [],
|
||||
selectableRows: true,
|
||||
placeholder: "데이터가 없습니다."
|
||||
});
|
||||
}
|
||||
|
||||
// 실적 목록 조회
|
||||
function fn_search() {
|
||||
var params = {
|
||||
projectObjid: _projectObjid,
|
||||
resultType: _resultType
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/getProdResultList.do",
|
||||
type: "POST",
|
||||
data: params,
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if(data && data.list) {
|
||||
grid.setData(data.list);
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("실적 조회 실패:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 행 추가
|
||||
function fn_addRow() {
|
||||
var newRow = {
|
||||
OBJID: '',
|
||||
RESULT_TYPE: _resultType || 'ASSEMBLY',
|
||||
RESULT_DATE: '${today}',
|
||||
RESULT_QTY: '',
|
||||
SERIAL_NO: '',
|
||||
WORKER_NAME: '${connectUserName}',
|
||||
REMARK: ''
|
||||
};
|
||||
grid.addRow(newRow);
|
||||
}
|
||||
|
||||
// 행 삭제
|
||||
function fn_delRow() {
|
||||
var selectedRows = grid.getSelectedRows();
|
||||
if(selectedRows.length === 0) {
|
||||
Swal.fire('삭제할 행을 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
selectedRows.forEach(function(row) {
|
||||
row.delete();
|
||||
});
|
||||
}
|
||||
|
||||
// 저장
|
||||
function fn_save() {
|
||||
var allData = grid.getData();
|
||||
|
||||
if(allData.length === 0) {
|
||||
Swal.fire('저장할 데이터가 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
// 유효성 검사
|
||||
for(var i = 0; i < allData.length; i++) {
|
||||
var row = allData[i];
|
||||
if(!row.RESULT_TYPE) {
|
||||
Swal.fire('실적유형을 선택해주세요. (행 ' + (i+1) + ')');
|
||||
return;
|
||||
}
|
||||
if(!row.RESULT_DATE) {
|
||||
Swal.fire('실적일자를 입력해주세요. (행 ' + (i+1) + ')');
|
||||
return;
|
||||
}
|
||||
if(!row.RESULT_QTY || row.RESULT_QTY <= 0) {
|
||||
Swal.fire('실적수량을 입력해주세요. (행 ' + (i+1) + ')');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!confirm('저장하시겠습니까?')) return;
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/saveProdResultList.do",
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
projectObjid: _projectObjid,
|
||||
resultList: allData
|
||||
}),
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if(data.result == "success") {
|
||||
alert(data.msg || "저장되었습니다.");
|
||||
if(opener && opener.fn_search) {
|
||||
opener.fn_search();
|
||||
}
|
||||
fn_search(); // 새로고침
|
||||
} else {
|
||||
Swal.fire(data.msg || "저장에 실패했습니다.");
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
Swal.fire("저장 중 오류가 발생했습니다.");
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 팝업 닫힐 때 부모 새로고침
|
||||
window.addEventListener('unload', function() {
|
||||
if(window.opener && window.opener.fn_search) {
|
||||
window.opener.fn_search();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<body style="overflow-x: hidden;">
|
||||
<form name="form1" id="form1" method="post">
|
||||
<input type="hidden" name="PROJECT_OBJID" id="PROJECT_OBJID" value="${param.projectObjid}">
|
||||
<input type="hidden" name="RESULT_TYPE" id="RESULT_TYPE_HIDDEN" value="${param.resultType}">
|
||||
|
||||
<section>
|
||||
<div class="plm_menu_name" style="display:flex;">
|
||||
<h2 style="width:100%;height:50px;text-align:center;margin-top:10px;">
|
||||
<span style="font-size:20px;">생산실적 등록/수정</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<!-- 프로젝트 정보 표시 -->
|
||||
<div style="padding:10px; background:#f5f5f5; border-bottom:1px solid #ddd;">
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<td style="width:70px; font-weight:bold;">프로젝트:</td>
|
||||
<td style="width:150px;"><span id="PROJECT_NO">-</span></td>
|
||||
<td style="width:50px; font-weight:bold;">품번:</td>
|
||||
<td style="width:150px;"><span id="PART_NO">-</span></td>
|
||||
<td style="width:50px; font-weight:bold;">품명:</td>
|
||||
<td><span id="PART_NAME">-</span></td>
|
||||
<td style="width:70px; font-weight:bold;">수주수량:</td>
|
||||
<td style="width:70px;"><span id="ORDER_QTY">-</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2><span>실적 목록</span></h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="행추가" class="plm_btns" id="btnAddRow">
|
||||
<input type="button" value="행삭제" class="plm_btns" id="btnDelRow">
|
||||
<input type="button" value="저장" class="plm_btns" id="btnSave">
|
||||
<input type="button" value="닫기" class="plm_btns" onclick="window.close();">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="grid" style="margin: 10px;"></div>
|
||||
</section>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
@@ -86,6 +86,8 @@ $(document).ready(function(){
|
||||
|
||||
// 컬럼: 품의서 No, 발주서 No, 프로젝트번호, 품번, 품명, 공급업체, 입고결과, 요청일, 요청자, 검사자, 검사일, 검사결과
|
||||
var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사일', field:'INSPECTION_DATE'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'품의서 No', field:'PROPOSAL_NO'
|
||||
// formatter:fnc_createGridAnchorTag,
|
||||
// cellClick:function(e, cell){
|
||||
@@ -103,7 +105,7 @@ var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:130, widthGrow:1, title:'프로젝트번호', field:'PROJECT_NO'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'제품구분', field:'PRODUCT_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:120, widthGrow:2, title:'품번', field:'PART_NO'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:150, widthGrow:3, title:'품명', field:'PART_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:130, widthGrow:3, title:'품명', field:'PART_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:130, widthGrow:2, title:'공급업체', field:'PARTNER_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'입고결과', field:'DELIVERY_STATUS',
|
||||
formatter:fnc_createGridAnchorTag,
|
||||
@@ -115,28 +117,26 @@ var columns = [
|
||||
},
|
||||
// {headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'요청일', field:'REQUEST_DATE'},
|
||||
// {headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'요청자', field:'REQUEST_USER_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사일', field:'INSPECTION_DATE'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 100, widthGrow : 1, title : '업체성적서', field : 'INSPECTION_FILE_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_FileRegist(objid,"INSPECTION_FILE","검사성적서");
|
||||
}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'검사결과', field:'INSPECTION_RESULT',
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:80, widthGrow:1, title:'검사현황', field:'INSPECTION_RESULT',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var val = fnc_checkNull(cell.getValue());
|
||||
if(val === 'NG') return '<span class="inspection-ng">NG</span>';
|
||||
if(val === 'OK') return '<span class="inspection-ok">OK</span>';
|
||||
if(val === '검사중') return '<span style="color:#ffc107;font-weight:bold;">검사중</span>';
|
||||
// 처리결과 기준: 전부 입력 = 완료, 일부만 입력 = 진행중, 없으면 미검사
|
||||
if(val === '완료') return '<span class="inspection-ok">완료</span>';
|
||||
if(val === '진행중') return '<span style="color:#ffc107;font-weight:bold;">진행중</span>';
|
||||
return '<span style="color:#999;cursor:pointer;">미검사</span>';
|
||||
},
|
||||
cellClick:function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_inspectionPopUp(objId);
|
||||
}
|
||||
}
|
||||
},
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 100, widthGrow : 1, title : '업체성적서', field : 'INSPECTION_FILE_CNT',
|
||||
formatter:fnc_subInfoValueFormatter,
|
||||
cellClick:function(e, cell){
|
||||
var objid = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_FileRegist(objid,"INSPECTION_FILE","검사성적서");
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// 조회
|
||||
|
||||
@@ -136,15 +136,15 @@ var _DEFECT_TYPE_LIST = [];
|
||||
// 처리현황 목록
|
||||
var _ACTION_STATUS_LIST = [
|
||||
{"CODE": "", "NAME": "선택"},
|
||||
{"CODE": "Rework", "NAME": "Rework"},
|
||||
{"CODE": "Scrap", "NAME": "Scrap"}
|
||||
{"CODE": "Rework", "NAME": "수정"},
|
||||
{"CODE": "Scrap", "NAME": "폐기"}
|
||||
];
|
||||
// 처리결과 목록
|
||||
var _ACTION_RESULT_LIST = [
|
||||
{"CODE": "", "NAME": "선택"},
|
||||
{"CODE": "수정", "NAME": "수정"},
|
||||
{"CODE": "수정", "NAME": "수정완료"},
|
||||
{"CODE": "폐기", "NAME": "폐기"},
|
||||
{"CODE": "특채", "NAME": "특채"}
|
||||
{"CODE": "특채", "NAME": "특채완료"}
|
||||
];
|
||||
// 검사자 목록
|
||||
var _INSPECTOR_LIST = [];
|
||||
@@ -208,8 +208,8 @@ $(document).ready(function(){
|
||||
// =====================================================
|
||||
function fn_initLeftGrid() {
|
||||
var columns = [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", headerHozAlign:"center", hozAlign:"center", headerSort:false, width:30},
|
||||
{title:'품번', field:'PART_NO', headerHozAlign:'center', hozAlign:'left', width:150,
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", headerHozAlign:"center", hozAlign:"center", headerSort:false, width:30, frozen: true},
|
||||
{title:'품번', field:'PART_NO', headerHozAlign:'center', hozAlign:'left', width:150, frozen: true,
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell) {
|
||||
// 품번 클릭 시 품목상세 팝업
|
||||
@@ -218,18 +218,52 @@ function fn_initLeftGrid() {
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:'품명', field:'PART_NAME', headerHozAlign:'center', hozAlign:'left', width:150},
|
||||
{title:'품명', field:'PART_NAME', headerHozAlign:'center', hozAlign:'left', width:150, frozen: true},
|
||||
{title:'입고일', field:'DELIVERY_DATE', headerHozAlign:'center', hozAlign:'center', width:90},
|
||||
{title:'입고수량', field:'DELIVERY_QTY', headerHozAlign:'center', hozAlign:'right', width:90,
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
{title:'검사여부', field:'INSPECTION_YN', headerHozAlign:'center', hozAlign:'center', width:70,
|
||||
{title:'검사여부', field:'INSPECTION_YN', headerHozAlign:'center', hozAlign:'center', width:80,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === '검사') return '<span style="color:#007bff;font-weight:bold;">검사</span>';
|
||||
if(val === '스킵') return '<span style="color:#999;">스킵</span>';
|
||||
return val;
|
||||
}
|
||||
},
|
||||
{title:'검사수량', field:'INSPECTION_QTY', headerHozAlign:'center', hozAlign:'right', width:85,
|
||||
editor:"number",
|
||||
editorParams: {min:0, step:1},
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '';
|
||||
return parseInt(val).toLocaleString();
|
||||
}
|
||||
},
|
||||
{title:'불량수량', field:'DEFECT_QTY_SUM', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '0';
|
||||
return parseInt(val).toLocaleString();
|
||||
}
|
||||
},
|
||||
{title:'불량율', field:'LEFT_DEFECT_RATE', headerHozAlign:'center', hozAlign:'right', width:70,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '';
|
||||
return val + '%';
|
||||
}
|
||||
},
|
||||
{title:'검사성적서', field:'INSPECTION_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell) {
|
||||
var objId = fnc_checkNull(cell.getData().INSPECTION_DETAIL_OBJID);
|
||||
if(objId) {
|
||||
fn_openInspectionFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire("먼저 저장 후 파일을 등록할 수 있습니다.");
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -272,7 +306,75 @@ function fn_initLeftGrid() {
|
||||
|
||||
// 셀 편집 이벤트
|
||||
leftGrid.on("cellEdited", function(cell) {
|
||||
cell.getData().GRID_STATUS = 'U';
|
||||
var row = cell.getRow();
|
||||
var data = row.getData();
|
||||
var field = cell.getField();
|
||||
|
||||
// 검사수량 변경 시 불량율 재계산
|
||||
if (field === 'INSPECTION_QTY') {
|
||||
fn_calcLeftGridDefectRate(row);
|
||||
}
|
||||
|
||||
data.GRID_STATUS = 'U';
|
||||
});
|
||||
}
|
||||
|
||||
// 좌측 그리드 불량율 계산 (불량수량합계 / 입고수량 * 100)
|
||||
function fn_calcLeftGridDefectRate(row) {
|
||||
var data = row.getData();
|
||||
var deliveryQty = parseInt(data.DELIVERY_QTY) || 0;
|
||||
var defectQtySum = parseInt(data.DEFECT_QTY_SUM) || 0;
|
||||
|
||||
if (deliveryQty > 0) {
|
||||
var rate = (defectQtySum / deliveryQty * 100).toFixed(2);
|
||||
row.update({"LEFT_DEFECT_RATE": rate});
|
||||
} else {
|
||||
row.update({"LEFT_DEFECT_RATE": ""});
|
||||
}
|
||||
}
|
||||
|
||||
// 검사성적서 파일 팝업
|
||||
function fn_openInspectionFilePopUp(objId) {
|
||||
var popup_width = 800;
|
||||
var popup_height = 300;
|
||||
var params = "?targetObjId=" + objId + "&docType=INSPECTION_REPORT&docTypeName=검사성적서";
|
||||
var url = "/common/FileRegistPopup.do" + params;
|
||||
window.open(url, "inspectionFilePopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
// 좌측 그리드 불량수량 합계/불량율 실시간 업데이트 (우측 그리드 변경 시)
|
||||
function fn_updateLeftGridDefectSum() {
|
||||
if(!selectedRowData) return;
|
||||
|
||||
// 우측 그리드의 불량수량 합계 계산
|
||||
var rightGridData = rightGrid.getData();
|
||||
var defectQtySum = 0;
|
||||
rightGridData.forEach(function(row) {
|
||||
if(row.GRID_STATUS !== 'D') { // 삭제 표시된 행 제외
|
||||
defectQtySum += parseInt(row.DEFECT_QTY) || 0;
|
||||
}
|
||||
});
|
||||
|
||||
// 좌측 그리드에서 현재 선택된 행 찾기
|
||||
var leftRows = leftGrid.getRows();
|
||||
leftRows.forEach(function(row) {
|
||||
var data = row.getData();
|
||||
if(data.INSPECTION_DETAIL_OBJID === selectedDetailObjid) {
|
||||
// 불량수량 합계 업데이트
|
||||
row.update({"DEFECT_QTY_SUM": defectQtySum});
|
||||
|
||||
// 불량율 재계산 (불량수량합계 / 입고수량 * 100)
|
||||
var deliveryQty = parseInt(data.DELIVERY_QTY) || 0;
|
||||
if(deliveryQty > 0) {
|
||||
var rate = (defectQtySum / deliveryQty * 100).toFixed(2);
|
||||
row.update({"LEFT_DEFECT_RATE": rate});
|
||||
} else {
|
||||
row.update({"LEFT_DEFECT_RATE": ""});
|
||||
}
|
||||
|
||||
// 변경 표시
|
||||
data.GRID_STATUS = 'U';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -334,29 +436,30 @@ function fn_initRightGrid() {
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_ACTION_STATUS_LIST}
|
||||
},
|
||||
{title:'검사수량', field:'INSPECTION_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
editor:"input",
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '';
|
||||
return parseInt(val);
|
||||
}
|
||||
},
|
||||
// {title:'검사수량', field:'INSPECTION_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
// editor:"input",
|
||||
// formatter: function(cell) {
|
||||
// var val = cell.getValue();
|
||||
// if(val === null || val === '' || val === undefined) return '';
|
||||
// return parseInt(val);
|
||||
// }
|
||||
// },
|
||||
{title:'불량수량', field:'DEFECT_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
editor:"input",
|
||||
editor:"number",
|
||||
editorParams: {min:0, step:1},
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === null || val === '' || val === undefined) return '';
|
||||
return parseInt(val);
|
||||
}
|
||||
},
|
||||
{title:'불량율', field:'DEFECT_RATE', headerHozAlign:'center', hozAlign:'right', width:70, editor:false,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if (val) return val + '%';
|
||||
return '';
|
||||
}
|
||||
},
|
||||
// {title:'불량율', field:'DEFECT_RATE', headerHozAlign:'center', hozAlign:'right', width:70, editor:false,
|
||||
// formatter: function(cell) {
|
||||
// var val = cell.getValue();
|
||||
// if (val) return val + '%';
|
||||
// return '';
|
||||
// }
|
||||
// },
|
||||
{title:'검사일', field:'INSPECTION_DATE', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor:"date"
|
||||
},
|
||||
@@ -427,25 +530,33 @@ function fn_initRightGrid() {
|
||||
rightGrid.on("cellEdited", function(cell) {
|
||||
var row = cell.getRow();
|
||||
var data = row.getData();
|
||||
var field = cell.getField();
|
||||
|
||||
// 불량유형 변경 시 불량원인 초기화
|
||||
if (cell.getField() === 'DEFECT_TYPE') {
|
||||
if (field === 'DEFECT_TYPE') {
|
||||
row.update({"DEFECT_REASON": ""});
|
||||
}
|
||||
|
||||
// 검사수량, 불량수량 변경 시 불량율 자동 계산
|
||||
if (cell.getField() === 'INSPECTION_QTY' || cell.getField() === 'DEFECT_QTY') {
|
||||
// 불량수량 변경 시 정수로 변환
|
||||
if (field === 'DEFECT_QTY') {
|
||||
var defectQty = parseInt(data.DEFECT_QTY) || 0;
|
||||
row.update({"DEFECT_QTY": defectQty});
|
||||
// 불량율 계산
|
||||
fn_calcDefectRate(row);
|
||||
// 검사결과 자동 설정
|
||||
fn_updateInspectionResult(row);
|
||||
// 좌측 그리드 불량수량 합계/불량율 업데이트
|
||||
fn_updateLeftGridDefectSum();
|
||||
}
|
||||
|
||||
// 검사수량 변경 시 불량율 자동 계산
|
||||
if (field === 'INSPECTION_QTY') {
|
||||
fn_calcDefectRate(row);
|
||||
}
|
||||
|
||||
// 불량수량 변경 시 검사결과 자동 설정
|
||||
if (cell.getField() === 'DEFECT_QTY') {
|
||||
var defectQty = parseInt(data.DEFECT_QTY) || 0;
|
||||
if (defectQty > 0) {
|
||||
row.update({"INSPECTION_RESULT": "NG"});
|
||||
} else {
|
||||
row.update({"INSPECTION_RESULT": "OK"});
|
||||
}
|
||||
// 처리결과 변경 시 검사결과 자동 설정
|
||||
if (field === 'ACTION_RESULT') {
|
||||
fn_updateInspectionResult(row);
|
||||
}
|
||||
|
||||
data.GRID_STATUS = data.GRID_STATUS === 'I' ? 'I' : 'U';
|
||||
@@ -466,6 +577,28 @@ function fn_calcDefectRate(row) {
|
||||
}
|
||||
}
|
||||
|
||||
// 검사결과 자동 설정
|
||||
// 처리결과가 '수정' 또는 '특채'이면 OK, 불량수량 > 0 이면 NG, 그 외 OK
|
||||
function fn_updateInspectionResult(row) {
|
||||
var data = row.getData();
|
||||
var defectQty = parseInt(data.DEFECT_QTY) || 0;
|
||||
var actionResult = fnc_checkNull(data.ACTION_RESULT);
|
||||
|
||||
console.log("[검사결과 자동설정] 불량수량:", defectQty, ", 처리결과:", actionResult);
|
||||
|
||||
var newResult = "OK";
|
||||
// 처리결과가 '수정' 또는 '특채'이면 불량수량 있어도 OK
|
||||
if (actionResult === '수정' || actionResult === '특채') {
|
||||
newResult = "OK";
|
||||
} else if (defectQty > 0) {
|
||||
// 불량수량 있으면 NG
|
||||
newResult = "NG";
|
||||
}
|
||||
|
||||
console.log("[검사결과 자동설정] 결과:", newResult);
|
||||
row.update({"INSPECTION_RESULT": newResult});
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 좌측 그리드 조회
|
||||
// =====================================================
|
||||
@@ -609,6 +742,8 @@ function fn_deleteDefectRow() {
|
||||
row.getElement().style.display = 'none';
|
||||
}
|
||||
});
|
||||
// 좌측 그리드 불량수량 합계/불량율 업데이트
|
||||
fn_updateLeftGridDefectSum();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ String connector = person.getUserId();
|
||||
/* 검사결과 스타일 */
|
||||
.inspection-ng { color: #dc3545; font-weight: bold; }
|
||||
.inspection-ok { color: #28a745; font-weight: bold; }
|
||||
/* 공통에서 추가되는 초기화, Excel Download 버튼 숨기기 */
|
||||
.resetBtn, .excelBtn { display: none !important; }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -170,6 +172,16 @@ function fn_search(){
|
||||
|
||||
var columns = [
|
||||
{formatter:"rowSelection", titleFormatter:"rowSelection", hozAlign:"center", headerSort:false, width:30},
|
||||
{title:'검사일', field:'INSPECTION_DATE', headerHozAlign:'center', hozAlign:'center', width:110,
|
||||
editor:"date"
|
||||
},
|
||||
{title:'검사자', field:'INSPECTOR_ID', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST});
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST}
|
||||
},
|
||||
{title:'진행공정', field:'PROCESS_CD', headerHozAlign:'center', hozAlign:'center', width:130,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
@@ -259,10 +271,10 @@ function fn_search(){
|
||||
editor:"input",
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
{title:'불량수량', field:'DEFECT_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
editor:"input",
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
// {title:'불량수량', field:'DEFECT_QTY', headerHozAlign:'center', hozAlign:'right', width:80,
|
||||
// editor:"input",
|
||||
// formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
// },
|
||||
{title:'작업환경상태', field:'WORK_ENV_STATUS', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
@@ -277,6 +289,16 @@ function fn_search(){
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_MEASURING_DEVICE_LIST}
|
||||
},
|
||||
{title:'검사결과', field:'INSPECTION_RESULT', headerHozAlign:'center', hozAlign:'center', width:80,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === 'NG') return '<span class="inspection-ng">NG</span>';
|
||||
if(val === 'OK') return '<span class="inspection-ok">OK</span>';
|
||||
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST});
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST}
|
||||
},
|
||||
{title:'담당팀', field:'DEPT_CD', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
@@ -291,32 +313,14 @@ function fn_search(){
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_USER_LIST}
|
||||
},
|
||||
{title:'검사일', field:'INSPECTION_DATE', headerHozAlign:'center', hozAlign:'center', width:110,
|
||||
editor:"date"
|
||||
},
|
||||
{title:'검사자', field:'INSPECTOR_ID', headerHozAlign:'center', hozAlign:'center', width:100,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST});
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTOR_LIST}
|
||||
},
|
||||
|
||||
{title:'특이사항', field:'REMARK', headerHozAlign:'center', hozAlign:'left', width:150,
|
||||
editor:"input"
|
||||
},
|
||||
{title:'조치현황', field:'ACTION_STATUS', headerHozAlign:'center', hozAlign:'left', width:150,
|
||||
editor:"input"
|
||||
},
|
||||
{title:'검사결과', field:'INSPECTION_RESULT', headerHozAlign:'center', hozAlign:'center', width:80,
|
||||
editor: fnc_customSelectEditor,
|
||||
formatter: function(cell) {
|
||||
var val = cell.getValue();
|
||||
if(val === 'NG') return '<span class="inspection-ng">NG</span>';
|
||||
if(val === 'OK') return '<span class="inspection-ok">OK</span>';
|
||||
return fnc_customSelectFormatter(cell, {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST});
|
||||
},
|
||||
editorParams: {valueId:"CODE", labelId:"NAME", values:_INSPECTION_RESULT_LIST}
|
||||
},
|
||||
|
||||
{title:'이미지파일', field:'IMAGE_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell) {
|
||||
@@ -327,18 +331,18 @@ function fn_search(){
|
||||
Swal.fire("먼저 저장 후 이미지를 등록할 수 있습니다.");
|
||||
}
|
||||
}
|
||||
},
|
||||
{title:'첨부파일', field:'ATTACH_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell) {
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
if(objId) {
|
||||
fn_openAttachFilePopUp(objId);
|
||||
} else {
|
||||
Swal.fire("먼저 저장 후 파일을 등록할 수 있습니다.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// {title:'첨부파일', field:'ATTACH_FILE_CNT', headerHozAlign:'center', hozAlign:'center', width:90,
|
||||
// formatter: fnc_subInfoValueFormatter,
|
||||
// cellClick: function(e, cell) {
|
||||
// var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
// if(objId) {
|
||||
// fn_openAttachFilePopUp(objId);
|
||||
// } else {
|
||||
// Swal.fire("먼저 저장 후 파일을 등록할 수 있습니다.");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
];
|
||||
|
||||
// 그리드가 없으면 생성
|
||||
|
||||
@@ -88,7 +88,8 @@ $(document).ready(function(){
|
||||
|
||||
// 컬럼: 검사일, 프로젝트번호, 품번, 품명, 불량수량, 작업환경상태, 측정기, 검사자, 검사결과
|
||||
var columns = [
|
||||
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'검사일', field:'INSPECTION_DATE' },
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:150, widthGrow:2, title:'프로젝트번호', field:'PROJECT_NO'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'제품구분', field:'PRODUCT_NAME'},
|
||||
{headerHozAlign:'center', hozAlign:'left', minWidth:180, widthGrow:2, title:'품번', field:'PART_NO'},
|
||||
@@ -96,24 +97,28 @@ var columns = [
|
||||
{headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'검사수량 합계', field:'INSPECTION_QTY',
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'불량수량 합계', field:'DEFECT_QTY',
|
||||
formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'작업환경상태', field:'WORK_ENV_STATUS'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'측정기', field:'MEASURING_DEVICE'},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:110, widthGrow:1, title:'검사일', field:'INSPECTION_DATE',
|
||||
formatter: fnc_createGridAnchorTag,
|
||||
cellClick: function(e, cell){
|
||||
fn_openFormPopUp(cell.getData().OBJID);
|
||||
}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사자', field:'INSPECTOR_NAME'},
|
||||
// {headerHozAlign:'center', hozAlign:'right', minWidth:100, widthGrow:1, title:'불량수량 합계', field:'DEFECT_QTY',
|
||||
// formatter:"money", formatterParams:{thousand:",", precision:false}
|
||||
// },
|
||||
// {headerHozAlign:'center', hozAlign:'center', minWidth:120, widthGrow:1, title:'작업환경상태', field:'WORK_ENV_STATUS'},
|
||||
// {headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'측정기', field:'MEASURING_DEVICE'},
|
||||
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'검사결과', field:'INSPECTION_RESULT',
|
||||
formatter: function(cell, formatterParams, onRendered){
|
||||
var val = fnc_checkNull(cell.getValue());
|
||||
if(val === 'NG') return '<span class="inspection-ng">NG</span>';
|
||||
if(val === 'OK') return '<span class="inspection-ok">OK</span>';
|
||||
return val;
|
||||
},
|
||||
cellClick: function(e, cell){
|
||||
fn_openFormPopUp(cell.getData().OBJID);
|
||||
}
|
||||
},
|
||||
{headerHozAlign:'center', hozAlign:'center', minWidth:100, widthGrow:1, title:'첨부파일', field:'PROCESS_INSPECTION_FILE_CNT',
|
||||
formatter: fnc_subInfoValueFormatter,
|
||||
cellClick: function(e, cell){
|
||||
var objId = fnc_checkNull(cell.getData().OBJID);
|
||||
fn_openAttachFilePopUp(objId);
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -151,6 +156,19 @@ function fn_registPopUp(){
|
||||
window.open(url, "processInspectionPopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
|
||||
}
|
||||
|
||||
function fn_openAttachFilePopUp(objId) {
|
||||
_filePopupOpen = true; // 파일 팝업 열림 플래그 설정
|
||||
|
||||
var popup_width = 800;
|
||||
var popup_height = 300;
|
||||
var params = "?targetObjId=" + objId + "&docType=PROCESS_INSPECTION_FILE&docTypeName=공정검사첨부";
|
||||
var url = "/common/FileRegistPopup.do" + params;
|
||||
var popup = window.open(url, "attachFilePopUp", "width=" + popup_width + ",height=" + popup_height + ",scrollbars=yes,resizable=yes");
|
||||
|
||||
// 팝업 닫힘 감지하여 해당 행의 파일 카운트만 업데이트
|
||||
fn_watchPopupClose(popup, objId, 'ATTACH_FILE_CNT', 'PROCESS_INSPECTION_FILE');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
/* 기본 바디 스타일 - 깔끔한 배경 */
|
||||
body {
|
||||
background: var(--background);
|
||||
min-height: 100vh;
|
||||
/* min-height: 100vh; */
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.6;
|
||||
|
||||
@@ -1788,4 +1788,60 @@ public class ProductionPlanningController extends BaseService {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 등록/수정 팝업
|
||||
*/
|
||||
@RequestMapping("/productionplanning/prodResultFormPopup.do")
|
||||
public String prodResultFormPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
return "/productionplanning/prodResultFormPopup";
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 목록 조회
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping("/productionplanning/getProdResultList.do")
|
||||
public Map getProdResultList(HttpServletRequest request, @RequestParam Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try {
|
||||
List list = productionPlanningService.getProdResultList(paramMap);
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("list", list);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "조회 실패");
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 저장 (JSON)
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/productionplanning/saveProdResultList.do", produces="application/json;charset=UTF-8")
|
||||
public Map saveProdResultList(HttpServletRequest request, @RequestBody Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
try {
|
||||
HttpSession session = request.getSession();
|
||||
PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN);
|
||||
paramMap.put("userId", person.getUserId());
|
||||
paramMap.put("userName", person.getUserName());
|
||||
|
||||
boolean success = productionPlanningService.saveProdResultList(paramMap);
|
||||
if(success) {
|
||||
resultMap.put("result", "success");
|
||||
resultMap.put("msg", "저장되었습니다.");
|
||||
} else {
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "저장에 실패했습니다.");
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "fail");
|
||||
resultMap.put("msg", "저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4406,134 +4406,161 @@
|
||||
|
||||
<!-- 생산계획&실적관리 그리드 목록 조회 -->
|
||||
<select id="prodPlanResultMgmtGridList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
CM.PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
CM.CATEGORY_CD AS CATEGORY_CODE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.CATEGORY_CD LIMIT 1),
|
||||
CM.CATEGORY_CD
|
||||
) AS CATEGORY_CODE_NAME,
|
||||
-- 생산유형 (TODO: 실제 컬럼명 확인 필요)
|
||||
'' AS PRODUCTION_TYPE,
|
||||
'' AS PRODUCTION_TYPE_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
CASE
|
||||
WHEN CM.CUSTOMER_OBJID LIKE 'C_%' THEN
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG AS C WHERE 'C_' || C.OBJID::VARCHAR = CM.CUSTOMER_OBJID LIMIT 1)
|
||||
ELSE
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID::VARCHAR = CM.CUSTOMER_OBJID::VARCHAR LIMIT 1)
|
||||
END,
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
-- 요청납기
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
-- 고객사요청사항
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
-- 품번/품명
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
-- S/N
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO,
|
||||
-- 수주수량
|
||||
COALESCE(PM.QUANTITY::numeric, CI.ORDER_QUANTITY::numeric, 0) AS QUANTITY,
|
||||
-- 추가생산수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS EXTRA_PROD_QTY,
|
||||
-- 총생산수량 (수주수량 + 추가생산수량)
|
||||
COALESCE(PM.QUANTITY::numeric, CI.ORDER_QUANTITY::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
-- 완조립 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS ASSEMBLY_QTY,
|
||||
-- 검사 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS INSPECTION_QTY,
|
||||
-- 출하대기 수량 (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
0 AS SHIP_WAIT_QTY,
|
||||
-- 장비조립WBS (TODO: 실제 테이블/컬럼 확인 필요)
|
||||
'' AS EQUIPMENT_WBS,
|
||||
-- 생산계획 OBJID (있으면 수정, 없으면 신규)
|
||||
NULL AS PROD_PLAN_OBJID
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT OUTER JOIN CONTRACT_ITEM CI ON PM.CONTRACT_OBJID = CI.CONTRACT_OBJID
|
||||
AND PM.PART_OBJID = CI.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
SELECT * FROM (
|
||||
-- 1. 프로젝트 기반 데이터 (기존)
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
CM.PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.PRODUCT LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
CM.CATEGORY_CD AS CATEGORY_CODE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = CM.CATEGORY_CD LIMIT 1),
|
||||
CM.CATEGORY_CD
|
||||
) AS CATEGORY_CODE_NAME,
|
||||
COALESCE(PP.PRODUCTION_TYPE, '') AS PRODUCTION_TYPE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCTION_TYPE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCTION_TYPE_NAME,
|
||||
CM.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
CASE
|
||||
WHEN CM.CUSTOMER_OBJID LIKE 'C_%' THEN
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG AS C WHERE 'C_' || C.OBJID::VARCHAR = CM.CUSTOMER_OBJID LIMIT 1)
|
||||
ELSE
|
||||
(SELECT SUPPLY_NAME FROM SUPPLY_MNG WHERE OBJID::VARCHAR = CM.CUSTOMER_OBJID::VARCHAR LIMIT 1)
|
||||
END,
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
COALESCE(CI.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
(SELECT
|
||||
CASE
|
||||
WHEN COUNT(*) = 0 THEN ''
|
||||
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
|
||||
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
|
||||
END
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND CIS.SERIAL_NO IS NOT NULL) AS SERIAL_NO,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, NULLIF(CI.ORDER_QUANTITY, '')::numeric, 0) AS QUANTITY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, NULLIF(CI.ORDER_QUANTITY, '')::numeric, 0) + COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
0 AS ASSEMBLY_QTY,
|
||||
0 AS INSPECTION_QTY,
|
||||
0 AS SHIP_WAIT_QTY,
|
||||
'' AS EQUIPMENT_WBS,
|
||||
PP.OBJID AS PROD_PLAN_OBJID,
|
||||
PM.REGDATE AS SORT_DATE
|
||||
FROM
|
||||
PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT OUTER JOIN CONTRACT_ITEM CI ON PM.CONTRACT_OBJID = CI.CONTRACT_OBJID
|
||||
AND PM.PART_OBJID = CI.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
LEFT OUTER JOIN PRODUCTION_PLAN PP ON PP.PROJECT_OBJID = PM.OBJID
|
||||
AND PP.STATUS = 'active'
|
||||
WHERE PM.PROJECT_NO IS NOT NULL AND PM.PROJECT_NO != ''
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 2. 프로젝트 없이 등록한 생산계획
|
||||
SELECT
|
||||
PP.OBJID AS OBJID,
|
||||
'' AS PROJECT_NO,
|
||||
PP.PRODUCT_CODE AS PRODUCT,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCT_CODE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCT_NAME,
|
||||
PP.CATEGORY_CODE AS CATEGORY_CODE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.CATEGORY_CODE LIMIT 1),
|
||||
''
|
||||
) AS CATEGORY_CODE_NAME,
|
||||
COALESCE(PP.PRODUCTION_TYPE, '') AS PRODUCTION_TYPE,
|
||||
COALESCE(
|
||||
(SELECT CODE_NAME FROM COMM_CODE WHERE CODE_ID = PP.PRODUCTION_TYPE LIMIT 1),
|
||||
''
|
||||
) AS PRODUCTION_TYPE_NAME,
|
||||
PP.CUSTOMER_OBJID,
|
||||
COALESCE(
|
||||
(SELECT CLIENT_NM FROM CLIENT_MNG WHERE OBJID::VARCHAR = PP.CUSTOMER_OBJID LIMIT 1),
|
||||
''
|
||||
) AS CUSTOMER_NAME,
|
||||
PP.REQ_DEL_DATE,
|
||||
COALESCE(PP.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(PP.PART_NO, '') AS PART_NO,
|
||||
COALESCE(PP.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(PP.SERIAL_NO, '') AS SERIAL_NO,
|
||||
COALESCE(NULLIF(PP.ORDER_QTY, '')::numeric, 0) AS QUANTITY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(NULLIF(PP.TOTAL_PROD_QTY, '')::numeric, 0) AS TOTAL_PROD_QTY,
|
||||
0 AS ASSEMBLY_QTY,
|
||||
0 AS INSPECTION_QTY,
|
||||
0 AS SHIP_WAIT_QTY,
|
||||
'' AS EQUIPMENT_WBS,
|
||||
PP.OBJID AS PROD_PLAN_OBJID,
|
||||
PP.REGDATE AS SORT_DATE
|
||||
FROM PRODUCTION_PLAN PP
|
||||
WHERE PP.STATUS = 'active'
|
||||
AND (PP.PROJECT_OBJID IS NULL OR PP.PROJECT_OBJID = '')
|
||||
) T
|
||||
WHERE 1=1
|
||||
AND PM.PROJECT_NO IS NOT NULL
|
||||
AND PM.PROJECT_NO != ''
|
||||
<!-- 프로젝트번호 검색 (multiple select) -->
|
||||
<if test="search_project_nos != null and search_project_nos != ''">
|
||||
AND PM.OBJID::VARCHAR IN
|
||||
AND T.OBJID::VARCHAR IN
|
||||
<foreach item="projNo" collection="search_project_nos.split(',')" open="(" separator="," close=")">
|
||||
#{projNo}
|
||||
</foreach>
|
||||
</if>
|
||||
<!-- 제품구분 검색 -->
|
||||
<if test="search_product_code != null and search_product_code != ''">
|
||||
AND CM.PRODUCT = #{search_product_code}
|
||||
AND T.PRODUCT = #{search_product_code}
|
||||
</if>
|
||||
<!-- 주문유형 검색 -->
|
||||
<if test="search_category_code != null and search_category_code != ''">
|
||||
AND CM.CATEGORY_CD = #{search_category_code}
|
||||
AND T.CATEGORY_CODE = #{search_category_code}
|
||||
</if>
|
||||
<!-- 생산유형 검색 -->
|
||||
<if test="search_production_type != null and search_production_type != ''">
|
||||
AND 1=1 <!-- TODO: 생산유형 컬럼 확인 후 조건 추가 -->
|
||||
AND T.PRODUCTION_TYPE = #{search_production_type}
|
||||
</if>
|
||||
<!-- 고객사 검색 (C_ 접두사 처리) -->
|
||||
<!-- 고객사 검색 -->
|
||||
<if test="search_customer_objid != null and search_customer_objid != ''">
|
||||
AND (
|
||||
CM.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
OR CM.CUSTOMER_OBJID = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
OR REPLACE(CM.CUSTOMER_OBJID, 'C_', '') = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
T.CUSTOMER_OBJID = #{search_customer_objid}
|
||||
OR T.CUSTOMER_OBJID = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
OR REPLACE(T.CUSTOMER_OBJID, 'C_', '') = REPLACE(#{search_customer_objid}, 'C_', '')
|
||||
)
|
||||
</if>
|
||||
<!-- 요청납기 검색 -->
|
||||
<if test="search_req_del_date_from != null and search_req_del_date_from != ''">
|
||||
AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) >= #{search_req_del_date_from}
|
||||
AND T.REQ_DEL_DATE >= #{search_req_del_date_from}
|
||||
</if>
|
||||
<if test="search_req_del_date_to != null and search_req_del_date_to != ''">
|
||||
AND COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) <= #{search_req_del_date_to}
|
||||
AND T.REQ_DEL_DATE <= #{search_req_del_date_to}
|
||||
</if>
|
||||
<!-- 품번 검색 -->
|
||||
<if test="search_part_no != null and search_part_no != ''">
|
||||
AND (
|
||||
UPPER(PM.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
OR UPPER(CI.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
)
|
||||
AND UPPER(T.PART_NO) LIKE '%' || UPPER(#{search_part_no}) || '%'
|
||||
</if>
|
||||
<!-- 품명 검색 -->
|
||||
<if test="search_part_name != null and search_part_name != ''">
|
||||
AND (
|
||||
UPPER(PM.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
OR UPPER(CI.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
)
|
||||
AND UPPER(T.PART_NAME) LIKE '%' || UPPER(#{search_part_name}) || '%'
|
||||
</if>
|
||||
<!-- S/N 검색 -->
|
||||
<if test="search_serial_no != null and search_serial_no != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
AND UPPER(CIS.SERIAL_NO) LIKE '%' || UPPER(#{search_serial_no}) || '%'
|
||||
)
|
||||
AND UPPER(T.SERIAL_NO) LIKE '%' || UPPER(#{search_serial_no}) || '%'
|
||||
</if>
|
||||
ORDER BY PM.REGDATE DESC, PM.PROJECT_NO DESC
|
||||
ORDER BY T.SORT_DATE DESC, T.PROJECT_NO DESC
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트 정보 조회 (생산계획 폼용) -->
|
||||
@@ -4650,4 +4677,71 @@
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
<!-- 생산실적 목록 조회 -->
|
||||
<select id="getProdResultList" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
OBJID,
|
||||
PROJECT_OBJID,
|
||||
RESULT_TYPE,
|
||||
TO_CHAR(RESULT_DATE::DATE, 'YYYY-MM-DD') AS RESULT_DATE,
|
||||
RESULT_QTY,
|
||||
SERIAL_NO,
|
||||
WORKER_ID,
|
||||
WORKER_NAME,
|
||||
REMARK,
|
||||
STATUS
|
||||
FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND STATUS = 'active'
|
||||
<if test="resultType != null and resultType != ''">
|
||||
AND RESULT_TYPE = #{resultType}
|
||||
</if>
|
||||
ORDER BY RESULT_DATE DESC, REGDATE DESC
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 등록 -->
|
||||
<insert id="insertProdResult" parameterType="map">
|
||||
INSERT INTO PRODUCTION_RESULT (
|
||||
OBJID,
|
||||
PROJECT_OBJID,
|
||||
RESULT_TYPE,
|
||||
RESULT_DATE,
|
||||
RESULT_QTY,
|
||||
SERIAL_NO,
|
||||
WORKER_ID,
|
||||
WORKER_NAME,
|
||||
REMARK,
|
||||
STATUS,
|
||||
REGDATE,
|
||||
WRITER
|
||||
) VALUES (
|
||||
#{OBJID},
|
||||
#{PROJECT_OBJID},
|
||||
#{RESULT_TYPE},
|
||||
#{RESULT_DATE},
|
||||
#{RESULT_QTY},
|
||||
#{SERIAL_NO},
|
||||
#{userId},
|
||||
#{WORKER_NAME},
|
||||
#{REMARK},
|
||||
'active',
|
||||
NOW(),
|
||||
#{userId}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 생산실적 수정 -->
|
||||
<update id="updateProdResult" parameterType="map">
|
||||
UPDATE PRODUCTION_RESULT SET
|
||||
RESULT_TYPE = #{RESULT_TYPE},
|
||||
RESULT_DATE = #{RESULT_DATE},
|
||||
RESULT_QTY = #{RESULT_QTY},
|
||||
SERIAL_NO = #{SERIAL_NO},
|
||||
WORKER_NAME = #{WORKER_NAME},
|
||||
REMARK = #{REMARK},
|
||||
MODDATE = NOW(),
|
||||
MODIFIER = #{userId}
|
||||
WHERE OBJID = #{OBJID}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -711,10 +711,9 @@
|
||||
,DEFECT.INSPECTOR_NAME_DISPLAY AS INSPECTOR_NAME
|
||||
/* 검사일: YYYY-MM-DD 외 N건 형태 */
|
||||
,DEFECT.INSPECTION_DATE_DISPLAY AS INSPECTION_DATE
|
||||
/* 검사결과: 하나라도 NG면 NG, 검사 대상(스킵 제외) 모두 검사완료면 OK, 일부만 검사면 검사중 */
|
||||
,(CASE WHEN DEFECT.NG_COUNT > 0 THEN 'NG'
|
||||
WHEN DEFECT.INSPECTION_TARGET_COUNT > 0 AND DEFECT.INSPECTION_TARGET_COUNT = DEFECT.INSPECTED_COUNT THEN 'OK'
|
||||
WHEN DEFECT.INSPECTED_COUNT > 0 THEN '검사중'
|
||||
/* 검사현황: 불량상세 처리결과(ACTION_RESULT)가 전부 있으면 완료, 일부만 있으면 진행중 */
|
||||
,(CASE WHEN DEFECT.DEFECT_TOTAL_COUNT > 0 AND DEFECT.DEFECT_TOTAL_COUNT = DEFECT.ACTION_RESULT_COUNT THEN '완료'
|
||||
WHEN DEFECT.ACTION_RESULT_COUNT > 0 THEN '진행중'
|
||||
ELSE '' END) AS INSPECTION_RESULT
|
||||
|
||||
/* 검사여부: 검사가 하나라도 있으면 '검사', 모두 스킵이면 '스킵', 아무것도 없으면 빈값 */
|
||||
@@ -764,6 +763,10 @@
|
||||
END AS INSPECTION_DATE_DISPLAY
|
||||
/* 검사 대상 건수 (스킵 제외, 검사인 항목만) */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' THEN 1 END) AS INSPECTION_TARGET_COUNT
|
||||
/* 불량상세 테이블 전체 건수 (검사인 항목 기준) */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' THEN IDF.OBJID END) AS DEFECT_TOTAL_COUNT
|
||||
/* 처리결과(ACTION_RESULT) 입력된 건수 */
|
||||
,COUNT(CASE WHEN IID2.INSPECTION_YN = '검사' AND IDF.ACTION_RESULT IS NOT NULL AND IDF.ACTION_RESULT != '' THEN 1 END) AS ACTION_RESULT_COUNT
|
||||
/* 검사결과 입력된 건수 */
|
||||
,COUNT(CASE WHEN IDF.INSPECTION_RESULT IS NOT NULL AND IDF.INSPECTION_RESULT != '' THEN 1 END) AS INSPECTED_COUNT
|
||||
,COUNT(CASE WHEN IDF.INSPECTION_RESULT = 'NG' THEN 1 END) AS NG_COUNT
|
||||
@@ -1108,6 +1111,7 @@
|
||||
FROM PROCESS_INSPECTION_DETAIL PID WHERE PID.MASTER_OBJID = PIM.OBJID
|
||||
) AS INSPECTION_RESULT
|
||||
, PIM.REMARK
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO F WHERE F.TARGET_OBJID = PIM.OBJID AND F.DOC_TYPE = 'PROCESS_INSPECTION_FILE' AND UPPER(F.STATUS) = 'ACTIVE') AS PROCESS_INSPECTION_FILE_CNT
|
||||
FROM PROCESS_INSPECTION_MASTER PIM
|
||||
WHERE 1=1
|
||||
/* 프로젝트번호 */
|
||||
@@ -2317,6 +2321,14 @@
|
||||
, IID.REMARK
|
||||
, IMI.PURCHASE_ORDER_MASTER_OBJID
|
||||
, POM.PURCHASE_ORDER_NO
|
||||
/* 불량수량 합계 (INCOMING_INSPECTION_DETAIL.DEFECT_QTY에 저장된 값 사용) */
|
||||
, COALESCE(NULLIF(IID.DEFECT_QTY, '')::NUMERIC, 0) AS DEFECT_QTY_SUM
|
||||
/* 불량율 (불량수량합계 / 입고수량 * 100) */
|
||||
, CASE WHEN IMI.RECEIPT_QTY::NUMERIC > 0
|
||||
THEN ROUND(COALESCE(NULLIF(IID.DEFECT_QTY, '')::NUMERIC, 0) / IMI.RECEIPT_QTY::NUMERIC * 100, 2)
|
||||
ELSE NULL END AS LEFT_DEFECT_RATE
|
||||
/* 검사성적서 파일 수 */
|
||||
, (SELECT COUNT(*) FROM ATTACH_FILE_INFO AFI WHERE AFI.TARGET_OBJID = IID.OBJID AND AFI.DOC_TYPE = 'INSPECTION_REPORT' AND UPPER(AFI.STATUS) = 'ACTIVE') AS INSPECTION_FILE_CNT
|
||||
FROM INVENTORY_MGMT_IN IMI
|
||||
INNER JOIN INVENTORY_MGMT IM ON IM.OBJID = IMI.PARENT_OBJID
|
||||
INNER JOIN PART_MNG PM ON PM.OBJID::VARCHAR = IM.PART_OBJID
|
||||
|
||||
@@ -1758,4 +1758,73 @@ public class ProductionPlanningService {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 목록 조회
|
||||
*/
|
||||
public List getProdResultList(Map<String, Object> paramMap) {
|
||||
List resultList = new ArrayList();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
resultList = sqlSession.selectList("productionplanning.getProdResultList", paramMap);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 생산실적 저장 (리스트)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean saveProdResultList(Map<String, Object> paramMap) {
|
||||
boolean result = false;
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
String projectObjid = CommonUtils.nullToEmpty((String)paramMap.get("projectObjid"));
|
||||
String userId = CommonUtils.nullToEmpty((String)paramMap.get("userId"));
|
||||
List<Map<String, Object>> resultList = (List<Map<String, Object>>)paramMap.get("resultList");
|
||||
|
||||
if(resultList != null && resultList.size() > 0) {
|
||||
for(Map<String, Object> row : resultList) {
|
||||
row.put("PROJECT_OBJID", projectObjid);
|
||||
row.put("userId", userId);
|
||||
|
||||
String objid = CommonUtils.nullToEmpty((String)row.get("OBJID"));
|
||||
if("".equals(objid)) {
|
||||
// 신규 등록
|
||||
row.put("OBJID", CommonUtils.createObjId());
|
||||
sqlSession.insert("productionplanning.insertProdResult", row);
|
||||
} else {
|
||||
// 수정
|
||||
sqlSession.update("productionplanning.updateProdResult", row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
result = true;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
if(sqlSession != null) {
|
||||
sqlSession.rollback();
|
||||
}
|
||||
} finally {
|
||||
if(sqlSession != null) {
|
||||
sqlSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1806,6 +1806,8 @@ public class QualityService extends BaseService{
|
||||
sqlParamMap.put("INSPECTION_TYPE", CommonUtils.checkNull(data.get("INSPECTION_TYPE")));
|
||||
sqlParamMap.put("INSPECTION_DATE", inspectionDate);
|
||||
sqlParamMap.put("INSPECTOR_ID", inspectorId);
|
||||
sqlParamMap.put("INSPECTION_QTY", CommonUtils.checkNull(data.get("INSPECTION_QTY"))); // 검사수량
|
||||
sqlParamMap.put("DEFECT_QTY", CommonUtils.checkNull(data.get("DEFECT_QTY_SUM"))); // 불량수량 합계
|
||||
sqlParamMap.put("WRITER", writer);
|
||||
|
||||
sqlSession.update("quality.saveIncomingInspectionDetail", sqlParamMap);
|
||||
@@ -1821,7 +1823,7 @@ public class QualityService extends BaseService{
|
||||
|
||||
for(Map defect : defectList) {
|
||||
String gridStatus = CommonUtils.checkNull(defect.get("GRID_STATUS"));
|
||||
|
||||
|
||||
Map sqlParamMap = new HashMap();
|
||||
sqlParamMap.put("OBJID", CommonUtils.checkNull(defect.get("OBJID")));
|
||||
sqlParamMap.put("INSPECTION_DETAIL_OBJID", selectedDetailObjid);
|
||||
@@ -1837,7 +1839,7 @@ public class QualityService extends BaseService{
|
||||
sqlParamMap.put("INSPECTION_RESULT", CommonUtils.checkNull(defect.get("INSPECTION_RESULT")));
|
||||
sqlParamMap.put("REMARK", CommonUtils.checkNull(defect.get("REMARK")));
|
||||
sqlParamMap.put("WRITER", writer);
|
||||
|
||||
|
||||
if("D".equals(gridStatus)) {
|
||||
// 삭제
|
||||
sqlSession.delete("quality.deleteIncomingInspectionDefect", sqlParamMap);
|
||||
|
||||
Reference in New Issue
Block a user