주문서관리 수주취소 기능 추가(부분 취소만 가능)
This commit is contained in:
@@ -151,6 +151,28 @@ $(document).ready(function(){
|
||||
document.form1.submit();
|
||||
});
|
||||
|
||||
// 수주취소
|
||||
$("#btnOrderCancel").click(function(){
|
||||
var selectedData = _tabulGrid.getSelectedData();
|
||||
if(selectedData.length < 1){
|
||||
Swal.fire("수주취소할 행을 선택해주십시오.");
|
||||
return false;
|
||||
} else if(selectedData.length > 1){
|
||||
Swal.fire("한번에 한개의 수주만 취소 가능합니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var contractObjId = fnc_checkNull(selectedData[0].OBJID);
|
||||
var orderQty = parseInt(selectedData[0].ORDER_QUANTITY) || 0;
|
||||
|
||||
if(orderQty === 0){
|
||||
Swal.fire("수주 수량이 없는 건은 취소할 수 없습니다.");
|
||||
return false;
|
||||
}
|
||||
|
||||
fn_openOrderCancelPopup(contractObjId);
|
||||
});
|
||||
|
||||
fn_search();
|
||||
});
|
||||
|
||||
@@ -203,6 +225,14 @@ var columns = [
|
||||
return Number(value).toLocaleString();
|
||||
}
|
||||
},
|
||||
// 8-1. 수주취소
|
||||
{headerHozAlign : 'center', hozAlign : 'right', minWidth : 60, widthGrow: 0.7, title : '수주취소', field : 'CANCEL_QTY_SUM',
|
||||
formatter: function(cell) {
|
||||
var value = cell.getValue();
|
||||
if(!value || value === '' || value === 0 || value === '0') return '';
|
||||
return "<span style='color:#e74c3c; font-weight:bold;'>" + Number(value).toLocaleString() + "</span>";
|
||||
}
|
||||
},
|
||||
// 9. 유/무상
|
||||
{headerHozAlign : 'center', hozAlign : 'center', minWidth : 45, widthGrow: 0.5, title : '유/무상', field : 'PAID_TYPE' },
|
||||
// 10. 수주상태
|
||||
@@ -656,6 +686,131 @@ function fn_showSerialNoPopup(serialNoString){
|
||||
});
|
||||
}
|
||||
|
||||
// 수주취소 팝업 - 품목별 취소 수량 입력
|
||||
function fn_openOrderCancelPopup(contractObjId){
|
||||
$.ajax({
|
||||
url: "/contractMgmt/getContractItems.do",
|
||||
type: "POST",
|
||||
data: { contractObjId: contractObjId },
|
||||
dataType: "json",
|
||||
success: function(data){
|
||||
if(data.result !== "success" || !data.items || data.items.length === 0){
|
||||
Swal.fire("수주 품목 정보가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
var items = data.items;
|
||||
var html = '<div style="max-height: 400px; overflow-y: auto;">';
|
||||
html += '<table style="width: 100%; border-collapse: collapse;">';
|
||||
html += '<thead><tr style="background-color: #f0f0f0;">';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">품번</th>';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">품명</th>';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">수주수량</th>';
|
||||
html += '<th style="border: 1px solid #ddd; padding: 8px;">취소수량</th>';
|
||||
html += '</tr></thead><tbody>';
|
||||
|
||||
items.forEach(function(item, idx){
|
||||
var objid = item.OBJID || item.objid || '';
|
||||
var partNo = item.PART_NO || item.part_no || '';
|
||||
var partName = item.PART_NAME || item.part_name || '';
|
||||
var orderQty = item.ORDER_QUANTITY || item.order_quantity || '0';
|
||||
var cancelQty = item.CANCEL_QTY || item.cancel_qty || '';
|
||||
var orderQtyNum = parseInt(orderQty) || 0;
|
||||
var maxCancel = orderQtyNum > 0 ? orderQtyNum - 1 : 0;
|
||||
|
||||
html += '<tr>';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">' + partNo + '</td>';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: left;">' + partName + '</td>';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: right;">' + (orderQtyNum > 0 ? Number(orderQtyNum).toLocaleString() : '-') + '</td>';
|
||||
html += '<td style="border: 1px solid #ddd; padding: 8px; text-align: center;">';
|
||||
if(orderQtyNum > 0){
|
||||
html += '<input type="number" class="cancel-qty-input" data-objid="' + objid + '" data-order-qty="' + orderQtyNum + '" ';
|
||||
html += 'value="' + (cancelQty || '') + '" min="0" max="' + maxCancel + '" ';
|
||||
html += 'style="width: 80px; text-align: right; padding: 4px;" placeholder="0">';
|
||||
} else {
|
||||
html += '-';
|
||||
}
|
||||
html += '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
html += '</tbody></table>';
|
||||
html += '<p style="margin-top: 10px; color: #888; font-size: 12px;">※ 전체 수량 취소는 불가하며, 부분 수량만 취소 가능합니다.</p>';
|
||||
html += '</div>';
|
||||
|
||||
Swal.fire({
|
||||
title: '수주취소 수량 입력',
|
||||
html: html,
|
||||
width: '700px',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: '저장',
|
||||
cancelButtonText: '닫기',
|
||||
confirmButtonColor: '#e74c3c',
|
||||
preConfirm: function(){
|
||||
var inputs = document.querySelectorAll('.cancel-qty-input');
|
||||
var itemObjIds = [];
|
||||
var cancelQtys = [];
|
||||
var orderQtys = [];
|
||||
var hasError = false;
|
||||
|
||||
inputs.forEach(function(input){
|
||||
var val = input.value.trim();
|
||||
var orderQty = parseInt(input.getAttribute('data-order-qty'));
|
||||
var cancelVal = val === '' ? 0 : parseInt(val);
|
||||
|
||||
if(cancelVal < 0){
|
||||
Swal.showValidationMessage('취소 수량은 0 이상이어야 합니다.');
|
||||
hasError = true;
|
||||
return;
|
||||
}
|
||||
if(cancelVal >= orderQty){
|
||||
Swal.showValidationMessage('취소 수량(' + cancelVal + ')은 수주수량(' + orderQty + ')보다 적어야 합니다.');
|
||||
hasError = true;
|
||||
return;
|
||||
}
|
||||
|
||||
itemObjIds.push(input.getAttribute('data-objid'));
|
||||
cancelQtys.push(cancelVal);
|
||||
orderQtys.push(orderQty);
|
||||
});
|
||||
|
||||
if(hasError) return false;
|
||||
|
||||
return { itemObjIds: itemObjIds, cancelQtys: cancelQtys, orderQtys: orderQtys };
|
||||
}
|
||||
}).then(function(result){
|
||||
if(result.isConfirmed && result.value){
|
||||
var val = result.value;
|
||||
$.ajax({
|
||||
url: "/contractMgmt/saveOrderCancelQty.do",
|
||||
type: "POST",
|
||||
data: {
|
||||
itemObjIds: val.itemObjIds.join(","),
|
||||
cancelQtys: val.cancelQtys.join(","),
|
||||
orderQtys: val.orderQtys.join(",")
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(res){
|
||||
if(res.result === "true"){
|
||||
Swal.fire({ title: '저장 완료', text: res.msg, icon: 'success' });
|
||||
fn_search();
|
||||
} else {
|
||||
Swal.fire({ title: '저장 실패', text: res.msg, icon: 'error' });
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
Swal.fire("수주취소 저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function(){
|
||||
Swal.fire("품목 정보 조회 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//코드값을 받아와서 동적으로 selectbox 생성
|
||||
function optionJobGroup(code){
|
||||
var val=code;
|
||||
@@ -790,11 +945,12 @@ function openProjectFormPopUp(objId){
|
||||
<h2>
|
||||
<span>영업관리_주문서관리</span>
|
||||
</h2>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch" name="btnSearch">
|
||||
<input type="button" value="수주등록" class="plm_btns btnRegist">
|
||||
<input type="button" value="결재상신" class="plm_btns" id="btnApproval">
|
||||
</div>
|
||||
<div class="btnArea">
|
||||
<input type="button" value="조회" class="plm_btns" id="btnSearch" name="btnSearch">
|
||||
<input type="button" value="수주등록" class="plm_btns btnRegist">
|
||||
<input type="button" value="수주취소" class="plm_btns" id="btnOrderCancel" style="background-color:#e74c3c; color:#fff;">
|
||||
<input type="button" value="결재상신" class="plm_btns" id="btnApproval">
|
||||
</div>
|
||||
</div>
|
||||
<div id="plmSearchZon">
|
||||
<!-- 검색필터: 주문유형, 발주번호, 고객사, 품번, 품명, S/N, 수주상태, 발주일(기간), 요청납기(기간) -->
|
||||
|
||||
@@ -2853,6 +2853,25 @@ public class ContractMgmtController {
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 수주취소 수량 저장
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value="/contractMgmt/saveOrderCancelQty.do", method=RequestMethod.POST)
|
||||
public Map saveOrderCancelQty(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
Map resultMap = new HashMap();
|
||||
|
||||
try {
|
||||
resultMap = contractMgmtService.saveOrderCancelQty(request, paramMap);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
resultMap.put("result", "false");
|
||||
resultMap.put("msg", "수주취소 저장 중 오류가 발생했습니다.");
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@RequestMapping("/contractMgmt/FileRegistPopup.do")
|
||||
public String FileRegistPopup(HttpServletRequest request, @RequestParam Map<String, Object> paramMap){
|
||||
request.setAttribute("docType", CommonUtils.checkNull(paramMap.get("docType")));
|
||||
|
||||
@@ -717,6 +717,16 @@
|
||||
AND ORDER_QUANTITY != ''
|
||||
AND ORDER_QUANTITY != '0'
|
||||
) AS HAS_ORDER_DATA
|
||||
-- 수주취소 수량 합계
|
||||
,(
|
||||
SELECT COALESCE(SUM(CAST(NULLIF(CANCEL_QTY, '') AS NUMERIC)), 0)
|
||||
FROM CONTRACT_ITEM
|
||||
WHERE CONTRACT_OBJID = T.OBJID
|
||||
AND STATUS = 'ACTIVE'
|
||||
AND CANCEL_QTY IS NOT NULL
|
||||
AND CANCEL_QTY != ''
|
||||
AND CANCEL_QTY != '0'
|
||||
) AS CANCEL_QTY_SUM
|
||||
FROM
|
||||
CONTRACT_MGMT AS T
|
||||
LEFT OUTER JOIN
|
||||
@@ -5092,7 +5102,8 @@ WHERE
|
||||
CI.ORDER_UNIT_PRICE,
|
||||
CI.ORDER_SUPPLY_PRICE,
|
||||
CI.ORDER_VAT,
|
||||
CI.ORDER_TOTAL_AMOUNT
|
||||
CI.ORDER_TOTAL_AMOUNT,
|
||||
CI.CANCEL_QTY
|
||||
FROM
|
||||
CONTRACT_ITEM CI
|
||||
LEFT JOIN PART_MNG PM ON CI.PART_OBJID = PM.OBJID
|
||||
@@ -5117,7 +5128,8 @@ WHERE
|
||||
CI.ORDER_UNIT_PRICE,
|
||||
CI.ORDER_SUPPLY_PRICE,
|
||||
CI.ORDER_VAT,
|
||||
CI.ORDER_TOTAL_AMOUNT
|
||||
CI.ORDER_TOTAL_AMOUNT,
|
||||
CI.CANCEL_QTY
|
||||
ORDER BY CI.SEQ
|
||||
</select>
|
||||
|
||||
@@ -5133,6 +5145,16 @@ WHERE
|
||||
WHERE OBJID = #{contractItemObjId}
|
||||
</update>
|
||||
|
||||
<!-- 수주취소 수량 업데이트 -->
|
||||
<update id="updateContractItemCancelQty" parameterType="map">
|
||||
UPDATE CONTRACT_ITEM
|
||||
SET
|
||||
CANCEL_QTY = #{cancelQty},
|
||||
CHGDATE = NOW(),
|
||||
CHG_USER_ID = #{userId}
|
||||
WHERE OBJID = #{itemObjId}
|
||||
</update>
|
||||
|
||||
<!-- ====================================
|
||||
품목 관리 쿼리
|
||||
==================================== -->
|
||||
|
||||
@@ -3865,4 +3865,89 @@ private String encodeImageToBase64(String imagePath) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 수주취소 수량 저장
|
||||
* 품목별로 부분 취소 수량을 업데이트한다. (전체 취소 불가, 부분만 가능)
|
||||
*/
|
||||
public Map<String, Object> saveOrderCancelQty(HttpServletRequest request, Map<String, Object> paramMap) {
|
||||
Map<String, Object> resultMap = new HashMap<String, Object>();
|
||||
SqlSession sqlSession = null;
|
||||
|
||||
try {
|
||||
sqlSession = SqlMapConfig.getInstance().getSqlSession();
|
||||
|
||||
HttpSession session = request.getSession();
|
||||
PersonBean person = (PersonBean) session.getAttribute(Constants.PERSON_BEAN);
|
||||
String userId = person.getUserId();
|
||||
|
||||
String itemObjIdsStr = CommonUtils.checkNull(paramMap.get("itemObjIds"));
|
||||
String cancelQtysStr = CommonUtils.checkNull(paramMap.get("cancelQtys"));
|
||||
String orderQtysStr = CommonUtils.checkNull(paramMap.get("orderQtys"));
|
||||
|
||||
if ("".equals(itemObjIdsStr) || "".equals(cancelQtysStr)) {
|
||||
resultMap.put("result", "false");
|
||||
resultMap.put("msg", "취소 수량 정보가 없습니다.");
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
String[] itemObjIds = itemObjIdsStr.split(",");
|
||||
String[] cancelQtys = cancelQtysStr.split(",");
|
||||
String[] orderQtys = orderQtysStr.split(",");
|
||||
|
||||
for (int i = 0; i < itemObjIds.length; i++) {
|
||||
String cancelQty = cancelQtys[i].trim();
|
||||
String orderQty = orderQtys[i].trim();
|
||||
|
||||
// 빈 값이면 스킵
|
||||
if ("".equals(cancelQty) || "0".equals(cancelQty)) {
|
||||
// 취소수량 0이면 초기화
|
||||
Map<String, Object> updateParam = new HashMap<String, Object>();
|
||||
updateParam.put("itemObjId", itemObjIds[i].trim());
|
||||
updateParam.put("cancelQty", "");
|
||||
updateParam.put("userId", userId);
|
||||
sqlSession.update("contractMgmt.updateContractItemCancelQty", updateParam);
|
||||
continue;
|
||||
}
|
||||
|
||||
int cancelQtyInt = Integer.parseInt(cancelQty);
|
||||
int orderQtyInt = Integer.parseInt(orderQty);
|
||||
|
||||
// 전체 수량 취소 불가 (부분만 가능)
|
||||
if (cancelQtyInt >= orderQtyInt) {
|
||||
resultMap.put("result", "false");
|
||||
resultMap.put("msg", "수주취소 수량은 수주수량(" + orderQtyInt + ")보다 적어야 합니다.");
|
||||
sqlSession.rollback();
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
if (cancelQtyInt < 0) {
|
||||
resultMap.put("result", "false");
|
||||
resultMap.put("msg", "수주취소 수량은 0 이상이어야 합니다.");
|
||||
sqlSession.rollback();
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
Map<String, Object> updateParam = new HashMap<String, Object>();
|
||||
updateParam.put("itemObjId", itemObjIds[i].trim());
|
||||
updateParam.put("cancelQty", cancelQty);
|
||||
updateParam.put("userId", userId);
|
||||
sqlSession.update("contractMgmt.updateContractItemCancelQty", updateParam);
|
||||
}
|
||||
|
||||
sqlSession.commit();
|
||||
resultMap.put("result", "true");
|
||||
resultMap.put("msg", "수주취소 수량이 저장되었습니다.");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (sqlSession != null) sqlSession.rollback();
|
||||
resultMap.put("result", "false");
|
||||
resultMap.put("msg", "수주취소 저장 중 오류가 발생했습니다.");
|
||||
} finally {
|
||||
if (sqlSession != null) sqlSession.close();
|
||||
}
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user