diff --git a/WebContent/WEB-INF/view/project/wbsTemplateMngList.jsp b/WebContent/WEB-INF/view/project/wbsTemplateMngList.jsp
index aa92765..d481235 100644
--- a/WebContent/WEB-INF/view/project/wbsTemplateMngList.jsp
+++ b/WebContent/WEB-INF/view/project/wbsTemplateMngList.jsp
@@ -92,14 +92,14 @@ $(document).ready(function(){
var columns = [
{headerHozAlign : 'center', hozAlign : 'left', width : '250', title : '제품구분', field : 'PRODUCT_NAME' },
- {headerHozAlign : 'center', hozAlign : 'left', width : '250', title : '기계형식', field : 'TITLE' },
- {headerHozAlign : 'center', hozAlign : 'left', /* width : '250', */ title : '고객사_장비목적', field : 'CUSTOMER_PRODUCT',
- formatter:fnc_createGridAnchorTag,
- cellClick:function(e, cell){
- var objid = fnc_checkNull(cell.getData().OBJID);
- fn_openTemplateMasterPopUp(objid);
- }
- },
+ {headerHozAlign : 'center', hozAlign : 'left', /* width : '250', */ title : '제목', field : 'TITLE' },
+ // {headerHozAlign : 'center', hozAlign : 'left', /* width : '250', */ title : '고객사_장비목적', field : 'CUSTOMER_PRODUCT',
+ // formatter:fnc_createGridAnchorTag,
+ // cellClick:function(e, cell){
+ // var objid = fnc_checkNull(cell.getData().OBJID);
+ // fn_openTemplateMasterPopUp(objid);
+ // }
+ // },
{headerHozAlign : 'center', hozAlign : 'center', width : '250', title : 'UNIT', field : 'WBS_TASK_CNT0',
formatter:fnc_getFolderIcon,
cellClick:function(e, cell){
@@ -130,18 +130,12 @@ function fn_openTemplateMasterPopUp(objId){
}
function fn_openWBSTaskListPopUp(objId){
- var hiddenForm = document.hiddenForm;
- var popup_width = 800;
- var popup_height = 700;
- var url = "/project/wbsTemplateTaskListDetailPopUp.do";
+ var popup_width = 1340;
+ var popup_height = 700;
+ var url = "/project/WBSExcelImportPopUp.do?templateObjId=" + objId;
var target = "openWBSTaskListPopUp";
-
+
fn_centerPopup(popup_width, popup_height, url, target);
-
- hiddenForm.action = url;
- hiddenForm.OBJID.value = objId;
- hiddenForm.target = target;
- hiddenForm.submit();
}
function _fnc_datepick(){
diff --git a/WebContent/WEB-INF/view/quality/incomingInspectionProgressPopUp.jsp b/WebContent/WEB-INF/view/quality/incomingInspectionProgressPopUp.jsp
index 50c2f81..8b73699 100644
--- a/WebContent/WEB-INF/view/quality/incomingInspectionProgressPopUp.jsp
+++ b/WebContent/WEB-INF/view/quality/incomingInspectionProgressPopUp.jsp
@@ -119,7 +119,8 @@ var _ACTION_RESULT_LIST = [
{"CODE": "", "NAME": "선택"},
{"CODE": "수정", "NAME": "수정완료"},
{"CODE": "폐기", "NAME": "폐기"},
- {"CODE": "특채", "NAME": "특채완료"}
+ {"CODE": "특채", "NAME": "특채완료"},
+ {"CODE": "검사완료", "NAME": "검사완료"}
];
// 검사자 목록
var _INSPECTOR_LIST = [];
diff --git a/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp b/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp
index ef0866e..129c0d1 100644
--- a/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp
+++ b/WebContent/WEB-INF/view/quality/processInspectionFormPopUp.jsp
@@ -181,6 +181,8 @@ function fn_select2Editor(cell, onRendered, success, cancel, editorParams) {
var select = document.createElement("select");
select.style.width = "100%";
+ select.style.opacity = "0";
+ select.style.position = "absolute";
// 옵션 생성
if(values && values.length > 0) {
@@ -203,21 +205,32 @@ function fn_select2Editor(cell, onRendered, success, cancel, editorParams) {
width: "100%"
});
$(select).select2("open");
-
- $(select).on("select2:select select2:clear", function(e) {
- var selectedVal = $(select).val() || "";
-
- // 콜백 호출 (프로젝트 변경 시 연동 처리 등)
- if(typeof editorParams.onSelect === "function") {
- editorParams.onSelect(cell, selectedVal);
- }
-
- success(selectedVal);
- });
-
- $(select).on("select2:close", function() {
- setTimeout(function() { success($(select).val() || ""); }, 100);
- });
+ });
+
+ var isCleared = false;
+
+ $(select).on("select2:select", function(e) {
+ var selectedVal = $(select).val() || "";
+ if(typeof editorParams.onSelect === "function") {
+ editorParams.onSelect(cell, selectedVal);
+ }
+ success(selectedVal);
+ });
+
+ $(select).on("select2:clear", function(e) {
+ isCleared = true;
+ if(typeof editorParams.onSelect === "function") {
+ editorParams.onSelect(cell, "");
+ }
+ setTimeout(function() {
+ $(select).select2("close");
+ success("");
+ }, 0);
+ });
+
+ $(select).on("select2:close", function() {
+ if(isCleared) return;
+ success($(select).val() || "");
});
return container;
diff --git a/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp b/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp
index e881b7d..969df00 100644
--- a/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp
+++ b/WebContent/WEB-INF/view/quality/semiProductInspectionFormPopUp.jsp
@@ -26,9 +26,10 @@ String loginUserId = CommonUtils.checkNull(person.getUserId());
<%=Constants.SYSTEM_NAME%>
-
+
-
+
+
@@ -137,6 +167,7 @@ var bomReportObjid = "${resolvedBomReportObjid}";
var mbomHeaderObjid = "${resolvedMbomHeaderObjid}"; // MBOM_HEADER.OBJID (M-BOM 관리 화면에서 사용하는 ID)
var vendorList = []; // 공급업체 목록
var processingVendorList = []; // 가공업체 목록 (Select2용 배열)
+var copiedVendorData = { field: null, value: null, displayName: '' }; // 복사된 업체 정보
// 디버그: resultMap 내용 확인 (주석처리)
// console.log("=== JSP resultMap 디버그 ===");
@@ -875,6 +906,149 @@ function fn_initGrid() {
row.reformat();
}
});
+
+ // 공급업체/가공업체 셀 우클릭 → 복사/붙여넣기 컨텍스트 메뉴
+ _tabulGrid.on("cellContext", function(e, cell) {
+ var field = cell.getField();
+ if(field !== 'VENDOR_PM' && field !== 'PROCESSING_VENDOR') return;
+ e.preventDefault();
+ fn_showVendorContextMenu(e, cell);
+ });
+
+ // 다른 곳 클릭 시 컨텍스트 메뉴 닫기
+ $(document).on('click', function() {
+ $('.vendor-context-menu').remove();
+ });
+}
+
+// 업체 복사/붙여넣기 컨텍스트 메뉴 표시
+function fn_showVendorContextMenu(e, cell) {
+ $('.vendor-context-menu').remove();
+
+ var field = cell.getField();
+ var cellValue = cell.getValue();
+ var fieldLabel = (field === 'VENDOR_PM') ? '공급업체' : '가공업체';
+ var displayName = fn_getVendorDisplayName(cellValue);
+
+ var menu = $('');
+
+ // 복사
+ var copyLabel = cellValue ? '
복사 : ' + displayName : '
복사 (값 없음)';
+ var $copyItem = $('
' + copyLabel + '
');
+ if(cellValue) {
+ $copyItem.on('click', function() {
+ copiedVendorData = { field: field, value: cellValue, displayName: displayName };
+ menu.remove();
+ Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: fieldLabel + ' 복사: ' + displayName, showConfirmButton: false, timer: 1200 });
+ });
+ } else {
+ $copyItem.addClass('disabled');
+ }
+ menu.append($copyItem);
+
+ menu.append('
');
+
+ // 선택행에 붙여넣기
+ var hasCopied = copiedVendorData.value && copiedVendorData.field === field;
+ var pasteLabel = hasCopied
+ ? '
선택행에 붙여넣기 : ' + copiedVendorData.displayName
+ : '
선택행에 붙여넣기 (복사된 ' + fieldLabel + ' 없음)';
+ var $pasteItem = $('
' + pasteLabel + '
');
+ if(hasCopied) {
+ $pasteItem.on('click', function() {
+ menu.remove();
+ fn_pasteVendorToCheckedRows(copiedVendorData.field, copiedVendorData.value);
+ });
+ } else {
+ $pasteItem.addClass('disabled');
+ }
+ menu.append($pasteItem);
+
+ menu.append('
');
+
+ // 전체행에 붙여넣기
+ var pasteAllLabel = hasCopied
+ ? '
전체행에 붙여넣기 : ' + copiedVendorData.displayName
+ : '
전체행에 붙여넣기 (복사된 ' + fieldLabel + ' 없음)';
+ var $pasteAllItem = $('
' + pasteAllLabel + '
');
+ if(hasCopied) {
+ $pasteAllItem.on('click', function() {
+ menu.remove();
+ fn_pasteVendorToAllRows(copiedVendorData.field, copiedVendorData.value);
+ });
+ } else {
+ $pasteAllItem.addClass('disabled');
+ }
+ menu.append($pasteAllItem);
+
+ // 화면 밖으로 나가지 않도록 위치 보정
+ var menuX = e.pageX;
+ var menuY = e.pageY;
+ $('body').append(menu);
+ var menuWidth = menu.outerWidth();
+ var menuHeight = menu.outerHeight();
+ if(menuX + menuWidth > $(window).width()) menuX = $(window).width() - menuWidth - 5;
+ if(menuY + menuHeight > $(window).height()) menuY = $(window).height() - menuHeight - 5;
+ menu.css({ left: menuX + 'px', top: menuY + 'px' });
+}
+
+// 업체 OBJID → 업체명 변환
+function fn_getVendorDisplayName(value) {
+ if(!value) return '';
+ for(var i = 0; i < processingVendorList.length; i++) {
+ if(processingVendorList[i].id == value) return processingVendorList[i].text;
+ }
+ return value;
+}
+
+// 체크된 행에 업체값 붙여넣기
+function fn_pasteVendorToCheckedRows(field, value) {
+ var count = 0;
+ $('.rowCheck:checked').each(function() {
+ var row = $(this).closest('.tabulator-row');
+ if(row.length > 0 && _tabulGrid) {
+ var rowComponent = _tabulGrid.getRow(row[0]);
+ if(rowComponent) {
+ var updateData = {};
+ updateData[field] = value;
+ rowComponent.update(updateData);
+ count++;
+ }
+ }
+ });
+ var fieldLabel = (field === 'VENDOR_PM') ? '공급업체' : '가공업체';
+ if(count > 0) {
+ Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: fieldLabel + ' ' + count + '건 적용 완료', showConfirmButton: false, timer: 1500 });
+ } else {
+ Swal.fire({ title: '알림', text: '체크된 행이 없습니다.\n먼저 적용할 행을 체크해주세요.', icon: 'info' });
+ }
+}
+
+// 전체 행에 업체값 붙여넣기
+function fn_pasteVendorToAllRows(field, value) {
+ var fieldLabel = (field === 'VENDOR_PM') ? '공급업체' : '가공업체';
+ var displayName = fn_getVendorDisplayName(value);
+
+ Swal.fire({
+ title: '전체 적용',
+ text: '모든 행의 ' + fieldLabel + '을(를) "' + displayName + '"(으)로 변경하시겠습니까?',
+ icon: 'question',
+ showCancelButton: true,
+ confirmButtonText: '적용',
+ cancelButtonText: '취소'
+ }).then(function(result) {
+ if(result.isConfirmed) {
+ var rows = _tabulGrid.getRows();
+ var count = 0;
+ rows.forEach(function(row) {
+ var updateData = {};
+ updateData[field] = value;
+ row.update(updateData);
+ count++;
+ });
+ Swal.fire({ toast: true, position: 'top-end', icon: 'success', title: fieldLabel + ' 전체 ' + count + '건 적용 완료', showConfirmButton: false, timer: 1500 });
+ }
+ });
}
// 기존 구매리스트 조회
@@ -944,11 +1118,7 @@ function fn_loadFromMBom(callback) {
var list = (data && data.list) ? data.list : [];
if(list.length > 0) {
- // console.log("M-BOM 데이터 " + list.length + "건 로드됨");
_tabulGrid.setData(list);
- } else {
- // console.log("M-BOM 데이터 없음!");
- // 알림 제거 - 머지 모드에서는 알림 안 띄움
}
if(typeof callback === "function"){
callback(list);
diff --git a/src/com/pms/controller/ProjectController.java b/src/com/pms/controller/ProjectController.java
index 8aedd0e..b237a43 100644
--- a/src/com/pms/controller/ProjectController.java
+++ b/src/com/pms/controller/ProjectController.java
@@ -2282,14 +2282,27 @@ public class ProjectController {
@RequestMapping("/project/WBSExcelImportPopUp.do")
public String partMngExcelImportPopUp(HttpServletRequest request, @RequestParam Map
paramMap){
String objid = CommonUtils.createObjId();
+ String templateObjId = CommonUtils.nullToEmpty((String)paramMap.get("templateObjId"));
Map code_map = new HashMap();
try{
- code_map.put("product_cd", commonService.bizMakeOptionList("0000001", CommonUtils.nullToEmpty((String)paramMap.get("product")),"common.getCodeselect")); //공장
-
+ code_map.put("product_cd", commonService.bizMakeOptionList("0000001", CommonUtils.nullToEmpty((String)paramMap.get("product")),"common.getCodeselect"));
+
+ if(!"".equals(templateObjId)){
+ Map templateParam = new HashMap();
+ templateParam.put("OBJID", templateObjId);
+ Map masterInfo = service.getWBSTemplateMasterInfo(request, templateParam);
+ List taskList = service.getWBSTemplateTaskList(request, templateParam);
+ request.setAttribute("masterInfo", masterInfo);
+ request.setAttribute("taskList", taskList);
+ request.setAttribute("templateObjId", templateObjId);
+
+ String productObjId = CommonUtils.nullToEmpty((String)masterInfo.get("PRODUCT_OBJID"));
+ code_map.put("product_cd", commonService.bizMakeOptionList("0000001", productObjId, "common.getCodeselect"));
+ }
}catch(Exception e){
e.printStackTrace();
}
-
+
request.setAttribute("OBJID",objid);
request.setAttribute("code_map",code_map);
return "/project/WBSExcelImportPopUp";
diff --git a/src/com/pms/mapper/project.xml b/src/com/pms/mapper/project.xml
index fce4c42..535257b 100644
--- a/src/com/pms/mapper/project.xml
+++ b/src/com/pms/mapper/project.xml
@@ -5611,29 +5611,38 @@
,PARENT_OBJID
,TASK_NAME
,TASK_SEQ
+ ,TASK_LEVEL
,USER_ID
,WRITER
,REG_DATE
,UNIT_NO
+ ,UPPER_TASK_OBJID
) VALUES (
#{objid}
,#{parent_objid}
,#{task_name}
,#{task_seq}
+ ,#{task_level}
,#{user_id}
,#{writer}
- ,now()
+ ,now()
,#{unit_no}
+ ,#{upper_task_objid}
) ON
CONFLICT (OBJID) DO
UPDATE SET
- TASK_NAME = #{task_name}
- ,TASK_SEQ = #{task_seq}
- ,USER_ID = #{user_id}
- ,UNIT_NO = #{unit_no}
+ TASK_NAME = #{task_name}
+ ,TASK_SEQ = #{task_seq}
+ ,TASK_LEVEL = #{task_level}
+ ,USER_ID = #{user_id}
+ ,UNIT_NO = #{unit_no}
+ ,UPPER_TASK_OBJID = #{upper_task_objid}
-
-
+
+
+ DELETE FROM PMS_WBS_TASK_STANDARD WHERE PARENT_OBJID = #{parent_objid}
+
+
diff --git a/src/com/pms/mapper/salesMng.xml b/src/com/pms/mapper/salesMng.xml
index 9980caf..45bf26c 100644
--- a/src/com/pms/mapper/salesMng.xml
+++ b/src/com/pms/mapper/salesMng.xml
@@ -3305,7 +3305,7 @@ WITH RECURSIVE VIEW_BOM(
A.PART_NO,
A.PART_NAME,
A.QTY,
- A.QTY,
+ A.ITEM_QTY,
A.QTY,
A.REGDATE,
A.SEQ,
@@ -3368,7 +3368,7 @@ WITH RECURSIVE VIEW_BOM(
B.PART_NO,
B.PART_NAME,
B.QTY,
- B.QTY,
+ B.ITEM_QTY,
B.QTY,
B.REGDATE,
B.SEQ,
@@ -3445,6 +3445,7 @@ GROUPED_BOM AS (
MIN(V.CHILD_OBJID) AS CHILD_OBJID,
MIN(V.PART_NAME) AS PART_NAME,
SUM(COALESCE(NULLIF(V.QTY::TEXT, '')::NUMERIC, 0)) AS QTY,
+ SUM(COALESCE(NULLIF(V.ITEM_QTY::TEXT, '')::NUMERIC, 0)) AS ITEM_QTY,
MIN(V.SEQ) AS SEQ,
MIN(V.STATUS) AS STATUS,
MIN(V.LEV) AS LEV,
@@ -3476,6 +3477,7 @@ GROUPED_BOM AS (
COUNT(*) AS GROUPED_COUNT
FROM VIEW_BOM V
WHERE COALESCE(V.PRODUCTION_QTY, 0) > 0
+ AND V.LEV > 1
GROUP BY V.PART_NO, V.PART_OBJID,
COALESCE(V.SUPPLY_TYPE, ''),
COALESCE(V.RAW_MATERIAL, ''),
@@ -3494,7 +3496,7 @@ SELECT
G.PART_NO,
G.PART_NAME,
G.QTY,
- G.QTY AS ITEM_QTY,
+ G.ITEM_QTY,
G.QTY AS QTY_TEMP,
G.LEV AS LEVEL,
0 AS SUB_PART_CNT,
@@ -3507,7 +3509,7 @@ SELECT
G.RAW_MATERIAL_SPEC,
G.RAW_MATERIAL,
G.RAW_MATERIAL_SIZE AS SIZE,
- CASE WHEN G.PROCESSING_VENDOR IS NULL THEN '0000008377' ELSE G.PROCESSING_VENDOR END AS PROCESSING_VENDOR,
+ G.PROCESSING_VENDOR,
G.PROCESSING_DEADLINE,
G.GRINDING_DEADLINE,
G.REQUIRED_QTY,
diff --git a/src/com/pms/service/ProjectService.java b/src/com/pms/service/ProjectService.java
index f8801a8..a5170ac 100644
--- a/src/com/pms/service/ProjectService.java
+++ b/src/com/pms/service/ProjectService.java
@@ -2940,51 +2940,54 @@ public class ProjectService {
try{
PersonBean person = (PersonBean)request.getSession().getAttribute(Constants.PERSON_BEAN);
String writer = CommonUtils.checkNull(person.getUserId());
-
+
String product = CommonUtils.checkNull(request.getParameter("product"));
String title = CommonUtils.checkNull(request.getParameter("title"));
String customer_product = CommonUtils.checkNull(request.getParameter("customer_product"));
-
- Map templateMapsterSqlParamMap = new HashMap();
-
- String wbsMasterObjId = CommonUtils.createObjId();
-
- templateMapsterSqlParamMap.put("objid" , wbsMasterObjId);
- templateMapsterSqlParamMap.put("product" , product);
- templateMapsterSqlParamMap.put("title" , title);
- templateMapsterSqlParamMap.put("writer" , writer);
- templateMapsterSqlParamMap.put("customer_product" , customer_product);
-
- //템플릿 마스터를 저장한다.
- sqlSession.insert("project.saveWBSTaskTemp",templateMapsterSqlParamMap);
-
+ String templateObjId = CommonUtils.checkNull(request.getParameter("templateObjId"));
+
+ String wbsMasterObjId;
+
+ if(!"".equals(templateObjId)){
+ wbsMasterObjId = templateObjId;
+ Map deleteParam = new HashMap();
+ deleteParam.put("parent_objid", wbsMasterObjId);
+ sqlSession.delete("project.deleteWBSTemplateTaskByMaster", deleteParam);
+ } else {
+ wbsMasterObjId = CommonUtils.createObjId();
+ Map templateMasterSqlParamMap = new HashMap();
+ templateMasterSqlParamMap.put("objid", wbsMasterObjId);
+ templateMasterSqlParamMap.put("product", product);
+ templateMasterSqlParamMap.put("title", title);
+ templateMasterSqlParamMap.put("writer", writer);
+ templateMasterSqlParamMap.put("customer_product", customer_product);
+ sqlSession.insert("project.saveWBSTaskTemp", templateMasterSqlParamMap);
+ }
+
String[] wbsObjIdList = request.getParameterValues("WBS_TASK_OBJID");
-
- if(null != wbsObjIdList || 0 < wbsObjIdList.length){
-
+
+ if(null != wbsObjIdList && 0 < wbsObjIdList.length){
+
for(int i = 0;i