생산실적 등록 완료
This commit is contained in:
@@ -4500,9 +4500,9 @@
|
||||
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,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'ASSEMBLY' AND PR.STATUS = 'active'), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'INSPECTION' AND PR.STATUS = 'active'), 0) AS INSPECTION_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PM.OBJID::VARCHAR AND PR.RESULT_TYPE = 'SHIP_WAIT' AND PR.STATUS = 'active'), 0) AS SHIP_WAIT_QTY,
|
||||
'' AS EQUIPMENT_WBS,
|
||||
PP.OBJID AS PROD_PLAN_OBJID,
|
||||
PM.REGDATE AS SORT_DATE
|
||||
@@ -4550,9 +4550,9 @@
|
||||
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,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'ASSEMBLY' AND PR.STATUS = 'active'), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'INSPECTION' AND PR.STATUS = 'active'), 0) AS INSPECTION_QTY,
|
||||
COALESCE((SELECT SUM(RESULT_QTY) FROM PRODUCTION_RESULT PR WHERE PR.PROJECT_OBJID = PP.OBJID::VARCHAR AND PR.RESULT_TYPE = 'SHIP_WAIT' AND PR.STATUS = 'active'), 0) AS SHIP_WAIT_QTY,
|
||||
'' AS EQUIPMENT_WBS,
|
||||
PP.OBJID AS PROD_PLAN_OBJID,
|
||||
PP.REGDATE AS SORT_DATE
|
||||
@@ -4610,31 +4610,54 @@
|
||||
ORDER BY T.SORT_DATE DESC, T.PROJECT_NO DESC
|
||||
</select>
|
||||
|
||||
<!-- 프로젝트 정보 조회 (생산계획 폼용) -->
|
||||
<!-- 프로젝트 정보 조회 (생산계획 폼용) - PROJECT_MGMT 또는 PRODUCTION_PLAN에서 조회 -->
|
||||
<select id="getProdPlanProjectInfo" parameterType="map" resultType="map">
|
||||
SELECT
|
||||
PM.OBJID,
|
||||
PM.PROJECT_NO,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO) AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME) AS PART_NAME,
|
||||
COALESCE(CM.PRODUCT, PM.PRODUCT) AS PRODUCT_CODE,
|
||||
COALESCE(CM.CATEGORY_CD, '') AS CATEGORY_CODE,
|
||||
COALESCE(CM.CUSTOMER_OBJID, PM.CUSTOMER_OBJID) AS CUSTOMER_OBJID,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE) AS REQ_DEL_DATE,
|
||||
PM.QUANTITY AS ORDER_QTY,
|
||||
CM.CUSTOMER_REQUEST,
|
||||
(
|
||||
SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
) AS SERIAL_NO
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE PM.OBJID = #{projectObjid}
|
||||
SELECT * FROM (
|
||||
-- 1. PROJECT_MGMT 기반 조회
|
||||
SELECT
|
||||
PM.OBJID::VARCHAR AS OBJID,
|
||||
COALESCE(PM.PROJECT_NO, '') AS PROJECT_NO,
|
||||
COALESCE(CI.PART_NO, PM.PART_NO, '') AS PART_NO,
|
||||
COALESCE(CI.PART_NAME, PM.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(CM.PRODUCT, PM.PRODUCT, '') AS PRODUCT_CODE,
|
||||
COALESCE(CM.CATEGORY_CD, '') AS CATEGORY_CODE,
|
||||
COALESCE(CM.CUSTOMER_OBJID, PM.CUSTOMER_OBJID, '')::VARCHAR AS CUSTOMER_OBJID,
|
||||
COALESCE(CI.DUE_DATE, PM.DUE_DATE, CM.REQ_DEL_DATE, '') AS REQ_DEL_DATE,
|
||||
COALESCE(NULLIF(PM.QUANTITY, '')::numeric, 0) AS ORDER_QTY,
|
||||
COALESCE((SELECT NULLIF(PP.EXTRA_PROD_QTY, '')::numeric FROM PRODUCTION_PLAN PP WHERE PP.PROJECT_OBJID = PM.OBJID AND UPPER(PP.STATUS) = 'ACTIVE' LIMIT 1), 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(CM.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE((
|
||||
SELECT STRING_AGG(CIS.SERIAL_NO, ', ' ORDER BY CIS.SERIAL_NO)
|
||||
FROM CONTRACT_ITEM_SERIAL CIS
|
||||
WHERE CIS.ITEM_OBJID = CI.OBJID
|
||||
AND UPPER(CIS.STATUS) = 'ACTIVE'
|
||||
), '') AS SERIAL_NO
|
||||
FROM PROJECT_MGMT PM
|
||||
LEFT JOIN CONTRACT_MGMT CM ON PM.CONTRACT_OBJID = CM.OBJID
|
||||
LEFT JOIN CONTRACT_ITEM CI ON CI.CONTRACT_OBJID = PM.CONTRACT_OBJID
|
||||
AND CI.PART_OBJID = PM.PART_OBJID
|
||||
AND CI.STATUS = 'ACTIVE'
|
||||
WHERE PM.OBJID::VARCHAR = #{projectObjid}
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 2. PRODUCTION_PLAN 기반 조회 (OBJID로 직접 조회)
|
||||
SELECT
|
||||
PP.OBJID::VARCHAR AS OBJID,
|
||||
'' AS PROJECT_NO,
|
||||
COALESCE(PP.PART_NO, '') AS PART_NO,
|
||||
COALESCE(PP.PART_NAME, '') AS PART_NAME,
|
||||
COALESCE(PP.PRODUCT_CODE, '') AS PRODUCT_CODE,
|
||||
COALESCE(PP.CATEGORY_CODE, '') AS CATEGORY_CODE,
|
||||
COALESCE(PP.CUSTOMER_OBJID, '')::VARCHAR AS CUSTOMER_OBJID,
|
||||
COALESCE(PP.REQ_DEL_DATE, '') AS REQ_DEL_DATE,
|
||||
COALESCE(NULLIF(PP.ORDER_QTY, '')::numeric, 0) AS ORDER_QTY,
|
||||
COALESCE(NULLIF(PP.EXTRA_PROD_QTY, '')::numeric, 0) AS EXTRA_PROD_QTY,
|
||||
COALESCE(PP.CUSTOMER_REQUEST, '') AS CUSTOMER_REQUEST,
|
||||
COALESCE(PP.SERIAL_NO, '') AS SERIAL_NO
|
||||
FROM PRODUCTION_PLAN PP
|
||||
WHERE PP.OBJID::VARCHAR = #{projectObjid}
|
||||
) T
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
@@ -4754,6 +4777,7 @@
|
||||
RESULT_TYPE,
|
||||
RESULT_DATE,
|
||||
RESULT_QTY,
|
||||
ROW_SEQ,
|
||||
SERIAL_NO,
|
||||
WORKER_ID,
|
||||
WORKER_NAME,
|
||||
@@ -4767,6 +4791,7 @@
|
||||
#{RESULT_TYPE},
|
||||
#{RESULT_DATE},
|
||||
#{RESULT_QTY},
|
||||
#{ROW_SEQ},
|
||||
#{SERIAL_NO},
|
||||
#{userId},
|
||||
#{WORKER_NAME},
|
||||
@@ -4860,4 +4885,40 @@
|
||||
ORDER BY MD.RAW_MATERIAL_PART_NO
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 날짜별 조회 (피봇) -->
|
||||
<select id="getProdResultListByDate" parameterType="map" resultType="com.pms.common.UpperKeyMap">
|
||||
SELECT
|
||||
ROW_SEQ,
|
||||
RESULT_DATE,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'ASSEMBLY' THEN RESULT_QTY ELSE 0 END), 0) AS ASSEMBLY_QTY,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'INSPECTION' THEN RESULT_QTY ELSE 0 END), 0) AS INSPECTION_QTY,
|
||||
COALESCE(SUM(CASE WHEN RESULT_TYPE = 'SHIP_WAIT' THEN RESULT_QTY ELSE 0 END), 0) AS SHIP_WAIT_QTY,
|
||||
MAX(REMARK) AS REMARK
|
||||
FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND STATUS = 'active'
|
||||
GROUP BY ROW_SEQ, RESULT_DATE
|
||||
ORDER BY ROW_SEQ ASC
|
||||
</select>
|
||||
|
||||
<!-- 생산실적 행별 삭제 -->
|
||||
<delete id="deleteProdResultByRowSeq" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND ROW_SEQ = #{rowSeq}
|
||||
</delete>
|
||||
|
||||
<!-- 생산실적 날짜별 삭제 (기존 데이터 삭제 후 재입력용) -->
|
||||
<delete id="deleteProdResultByDate" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
AND RESULT_DATE = #{resultDate}
|
||||
</delete>
|
||||
|
||||
<!-- 생산실적 프로젝트 전체 삭제 -->
|
||||
<delete id="deleteProdResultByProject" parameterType="map">
|
||||
DELETE FROM PRODUCTION_RESULT
|
||||
WHERE PROJECT_OBJID = #{projectObjid}
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -13,40 +13,107 @@
|
||||
<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; }
|
||||
|
||||
/* 정보 테이블 스타일 */
|
||||
.info-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.info-table th {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px 15px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
width: 12%;
|
||||
}
|
||||
.info-table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px 15px;
|
||||
text-align: left;
|
||||
width: 21%;
|
||||
}
|
||||
.info-value {
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 실적등록 테이블 스타일 */
|
||||
.result-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.result-table th {
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #ccc;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.result-table td {
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
.result-table input[type="text"],
|
||||
.result-table input[type="number"] {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
border: 1px solid #ddd;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
}
|
||||
.result-table input[type="number"] {
|
||||
text-align: right;
|
||||
}
|
||||
.result-table .total-row {
|
||||
background-color: #f8f9fa;
|
||||
font-weight: bold;
|
||||
}
|
||||
.result-table .total-row td {
|
||||
padding: 10px 5px;
|
||||
}
|
||||
.result-table .total-label {
|
||||
background-color: #e9ecef;
|
||||
font-weight: bold;
|
||||
}
|
||||
.result-table .total-value {
|
||||
color: #0066cc;
|
||||
font-weight: bold;
|
||||
}
|
||||
.result-table .delete-btn {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 3px 8px;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.result-table .delete-btn:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<script type="text/javascript" src="/js/tabulator/tabulator_custom.js"></script>
|
||||
<script>
|
||||
var grid;
|
||||
<script type="text/javascript">
|
||||
var _projectObjid = "${param.projectObjid}";
|
||||
var _resultType = "${param.resultType}";
|
||||
|
||||
// 실적유형 목록
|
||||
var _RESULT_TYPE_LIST = [
|
||||
{"CODE": "ASSEMBLY", "NAME": "완조립"},
|
||||
{"CODE": "INSPECTION", "NAME": "검사"},
|
||||
{"CODE": "SHIP_WAIT", "NAME": "출하대기"}
|
||||
];
|
||||
var _rowIndex = 0;
|
||||
|
||||
$(function(){
|
||||
fnc_datepick();
|
||||
$(".select2").select2();
|
||||
|
||||
// 프로젝트 정보 로드
|
||||
if(_projectObjid) {
|
||||
fn_loadProjectInfo();
|
||||
}
|
||||
|
||||
// 그리드 초기화
|
||||
fn_initGrid();
|
||||
|
||||
// 실적 목록 조회
|
||||
fn_search();
|
||||
|
||||
@@ -55,11 +122,6 @@ $(function(){
|
||||
fn_addRow();
|
||||
});
|
||||
|
||||
// 행삭제 버튼
|
||||
$("#btnDelRow").click(function(){
|
||||
fn_delRow();
|
||||
});
|
||||
|
||||
// 저장 버튼
|
||||
$("#btnSave").click(function(){
|
||||
fn_save();
|
||||
@@ -68,14 +130,13 @@ $(function(){
|
||||
|
||||
// 날짜 선택기 초기화
|
||||
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
|
||||
$(document).on('focus', '.date-input', function(){
|
||||
$(this).datepicker({
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dateFormat: 'yy-mm-dd'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 프로젝트 정보 로드
|
||||
@@ -87,136 +148,152 @@ function fn_loadProjectInfo() {
|
||||
dataType: "json",
|
||||
async: false,
|
||||
success: function(data){
|
||||
console.log("프로젝트 정보 응답:", 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));
|
||||
console.log("info 데이터:", info);
|
||||
|
||||
// 대소문자 모두 체크
|
||||
var partNo = info.part_no || info.PART_NO || '-';
|
||||
var partName = info.part_name || info.PART_NAME || '-';
|
||||
var orderQty = info.order_qty || info.ORDER_QTY || 0;
|
||||
var extraProdQty = info.extra_prod_qty || info.EXTRA_PROD_QTY || 0;
|
||||
|
||||
$("#PART_NO").text(partNo);
|
||||
$("#PART_NAME").text(partName);
|
||||
$("#ORDER_QTY").text(fnc_formatNumber(orderQty));
|
||||
$("#EXTRA_PROD_QTY").text(fnc_formatNumber(extraProdQty));
|
||||
|
||||
// 총생산수량 = 수주수량 + 추가생산수량
|
||||
var orderQtyNum = parseInt(orderQty) || 0;
|
||||
var extraProdQtyNum = parseInt(extraProdQty) || 0;
|
||||
$("#TOTAL_PROD_QTY").text(fnc_formatNumber(orderQtyNum + extraProdQtyNum));
|
||||
}
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("프로젝트 정보 조회 실패:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 그리드 컬럼 정의
|
||||
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 fnc_formatNumber(num) {
|
||||
if(num == null || num == '') return '0';
|
||||
return parseInt(num).toLocaleString();
|
||||
}
|
||||
|
||||
// 실적 목록 조회
|
||||
function fn_search() {
|
||||
var params = {
|
||||
projectObjid: _projectObjid,
|
||||
resultType: _resultType
|
||||
projectObjid: _projectObjid
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/getProdResultList.do",
|
||||
url: "/productionplanning/getProdResultListByDate.do",
|
||||
type: "POST",
|
||||
data: params,
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if(data && data.list) {
|
||||
grid.setData(data.list);
|
||||
console.log("실적 데이터 응답:", data);
|
||||
if(data && data.list && data.list.length > 0) {
|
||||
// 기존 데이터 로드
|
||||
for(var i = 0; i < data.list.length; i++) {
|
||||
var row = data.list[i];
|
||||
// 대소문자 모두 체크
|
||||
var resultDate = row.result_date || row.RESULT_DATE || '';
|
||||
var assemblyQty = row.assembly_qty || row.ASSEMBLY_QTY || 0;
|
||||
var inspectionQty = row.inspection_qty || row.INSPECTION_QTY || 0;
|
||||
var shipWaitQty = row.ship_wait_qty || row.SHIP_WAIT_QTY || 0;
|
||||
fn_addRow(resultDate, assemblyQty, inspectionQty, shipWaitQty);
|
||||
}
|
||||
} else {
|
||||
// 데이터 없으면 빈 행 하나 추가
|
||||
fn_addRow();
|
||||
}
|
||||
fn_updateTotals();
|
||||
},
|
||||
error: function(jqxhr, status, error){
|
||||
console.error("실적 조회 실패:", error);
|
||||
fn_addRow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 행 추가
|
||||
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_addRow(resultDate, assemblyQty, inspectionQty, shipWaitQty) {
|
||||
_rowIndex++;
|
||||
var today = '${today}';
|
||||
|
||||
var html = '<tr id="row_' + _rowIndex + '" data-row-index="' + _rowIndex + '">';
|
||||
html += '<td><input type="text" class="date-input" name="RESULT_DATE_' + _rowIndex + '" value="' + (resultDate || today) + '" placeholder="YYYY-MM-DD"></td>';
|
||||
html += '<td><input type="number" class="qty-input assembly-qty" name="ASSEMBLY_QTY_' + _rowIndex + '" value="' + (assemblyQty || 0) + '" min="0" onchange="fn_updateTotals()"></td>';
|
||||
html += '<td><input type="number" class="qty-input inspection-qty" name="INSPECTION_QTY_' + _rowIndex + '" value="' + (inspectionQty || 0) + '" min="0" onchange="fn_updateTotals()"></td>';
|
||||
html += '<td><input type="number" class="qty-input ship-wait-qty" name="SHIP_WAIT_QTY_' + _rowIndex + '" value="' + (shipWaitQty || 0) + '" min="0" onchange="fn_updateTotals()"></td>';
|
||||
html += '<td><button type="button" class="delete-btn" onclick="fn_deleteRow(' + _rowIndex + ')">삭제</button></td>';
|
||||
html += '</tr>';
|
||||
|
||||
$("#resultTableBody").append(html);
|
||||
fn_updateTotals();
|
||||
}
|
||||
|
||||
// 행 삭제
|
||||
function fn_delRow() {
|
||||
var selectedRows = grid.getSelectedRows();
|
||||
if(selectedRows.length === 0) {
|
||||
Swal.fire('삭제할 행을 선택해주세요.');
|
||||
return;
|
||||
}
|
||||
function fn_deleteRow(rowIndex) {
|
||||
$("#row_" + rowIndex).remove();
|
||||
fn_updateTotals();
|
||||
}
|
||||
|
||||
// 총수량 업데이트
|
||||
function fn_updateTotals() {
|
||||
var totalAssembly = 0;
|
||||
var totalInspection = 0;
|
||||
var totalShipWait = 0;
|
||||
|
||||
selectedRows.forEach(function(row) {
|
||||
row.delete();
|
||||
$(".assembly-qty").each(function() {
|
||||
totalAssembly += parseInt($(this).val()) || 0;
|
||||
});
|
||||
$(".inspection-qty").each(function() {
|
||||
totalInspection += parseInt($(this).val()) || 0;
|
||||
});
|
||||
$(".ship-wait-qty").each(function() {
|
||||
totalShipWait += parseInt($(this).val()) || 0;
|
||||
});
|
||||
|
||||
$("#TOTAL_ASSEMBLY").text(totalAssembly.toLocaleString());
|
||||
$("#TOTAL_INSPECTION").text(totalInspection.toLocaleString());
|
||||
$("#TOTAL_SHIP_WAIT").text(totalShipWait.toLocaleString());
|
||||
}
|
||||
|
||||
// 저장
|
||||
function fn_save() {
|
||||
var allData = grid.getData();
|
||||
var resultList = [];
|
||||
|
||||
if(allData.length === 0) {
|
||||
$("#resultTableBody tr").each(function() {
|
||||
var rowIndex = $(this).data('row-index');
|
||||
var resultDate = $("input[name='RESULT_DATE_" + rowIndex + "']").val();
|
||||
var assemblyQty = parseInt($("input[name='ASSEMBLY_QTY_" + rowIndex + "']").val()) || 0;
|
||||
var inspectionQty = parseInt($("input[name='INSPECTION_QTY_" + rowIndex + "']").val()) || 0;
|
||||
var shipWaitQty = parseInt($("input[name='SHIP_WAIT_QTY_" + rowIndex + "']").val()) || 0;
|
||||
|
||||
if(resultDate) {
|
||||
resultList.push({
|
||||
RESULT_DATE: resultDate,
|
||||
ASSEMBLY_QTY: assemblyQty,
|
||||
INSPECTION_QTY: inspectionQty,
|
||||
SHIP_WAIT_QTY: shipWaitQty
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if(resultList.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;
|
||||
}
|
||||
for(var i = 0; i < resultList.length; i++) {
|
||||
var row = resultList[i];
|
||||
if(!row.RESULT_DATE) {
|
||||
Swal.fire('실적일자를 입력해주세요. (행 ' + (i+1) + ')');
|
||||
return;
|
||||
}
|
||||
if(!row.RESULT_QTY || row.RESULT_QTY <= 0) {
|
||||
Swal.fire('실적수량을 입력해주세요. (행 ' + (i+1) + ')');
|
||||
Swal.fire('날짜를 입력해주세요. (행 ' + (i+1) + ')');
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -224,12 +301,12 @@ function fn_save() {
|
||||
if(!confirm('저장하시겠습니까?')) return;
|
||||
|
||||
$.ajax({
|
||||
url: "/productionplanning/saveProdResultList.do",
|
||||
url: "/productionplanning/saveProdResultByDate.do",
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
projectObjid: _projectObjid,
|
||||
resultList: allData
|
||||
resultList: resultList
|
||||
}),
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
@@ -238,7 +315,7 @@ function fn_save() {
|
||||
if(opener && opener.fn_search) {
|
||||
opener.fn_search();
|
||||
}
|
||||
fn_search(); // 새로고침
|
||||
window.close(); // 저장 성공 시 자동 닫기
|
||||
} else {
|
||||
Swal.fire(data.msg || "저장에 실패했습니다.");
|
||||
}
|
||||
@@ -260,42 +337,77 @@ window.addEventListener('unload', function() {
|
||||
<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>
|
||||
<span style="font-size:20px;">생산실적 등록</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<!-- 프로젝트 정보 표시 -->
|
||||
<div style="padding:10px; background:#f5f5f5; border-bottom:1px solid #ddd;">
|
||||
<table style="width:100%;">
|
||||
<div style="padding:10px 10px 0 10px;">
|
||||
<table class="info-table">
|
||||
<colgroup>
|
||||
<col width="15%" />
|
||||
<col width="35%" />
|
||||
<col width="15%" />
|
||||
<col width="35%" />
|
||||
</colgroup>
|
||||
<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>
|
||||
<th>품번 <span style="color:red;">*</span></th>
|
||||
<td><span id="PART_NO" class="info-value">-</span></td>
|
||||
<th>품명 <span style="color:red;">*</span></th>
|
||||
<td><span id="PART_NAME" class="info-value">-</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>수주수량 <span style="color:red;">*</span></th>
|
||||
<td><span id="ORDER_QTY" class="info-value">0</span></td>
|
||||
<th>추가생산수량 <span style="color:red;">*</span></th>
|
||||
<td><span id="EXTRA_PROD_QTY" class="info-value">0</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>총생산수량 <span style="color:red;">*</span></th>
|
||||
<td colspan="3"><span id="TOTAL_PROD_QTY" class="info-value" style="color:#0066cc;">0</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="plm_menu_name_gdnsi">
|
||||
<h2><span>실적 목록</span></h2>
|
||||
<div class="btnArea">
|
||||
<div class="plm_menu_name_gdnsi" style="display:flex; justify-content:space-between; align-items:center; padding:0 10px; margin:10px 0;">
|
||||
<h2 style="margin:0;"><span>실적등록</span></h2>
|
||||
<div class="btnArea" style="margin:0;">
|
||||
<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>
|
||||
<!-- 실적등록 테이블 -->
|
||||
<div style="padding: 0 10px 10px 10px;">
|
||||
<table class="result-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:150px;">날짜</th>
|
||||
<th style="width:120px;">완조립</th>
|
||||
<th style="width:120px;">검사</th>
|
||||
<th style="width:120px;">출하대기</th>
|
||||
<th style="width:60px;">삭제</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="resultTableBody">
|
||||
<!-- 동적으로 행 추가 -->
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="total-row">
|
||||
<td class="total-label">총수량</td>
|
||||
<td class="total-value"><span id="TOTAL_ASSEMBLY">0</span></td>
|
||||
<td class="total-value"><span id="TOTAL_INSPECTION">0</span></td>
|
||||
<td class="total-value"><span id="TOTAL_SHIP_WAIT">0</span></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user