분할출하 S/N 선택 기능 추가

This commit is contained in:
2026-03-24 12:08:26 +09:00
parent 6d7019c1bc
commit d80a3f5341
7 changed files with 370 additions and 15 deletions

View File

@@ -441,7 +441,28 @@ public class SalesNcollectMgmtController {
// orderInfo로 견적 정보 전달 (saleInfo가 이미 모든 필요한 정보를 포함)
request.setAttribute("orderInfo", saleInfo);
}
// 이미 사용된 분할S/N 조회 (현재 수정 중인 logId 제외)
if(paramMap.get("orderNo") != null && !paramMap.get("orderNo").equals("")) {
Map<String, Object> usedSnParam = new HashMap<String, Object>();
usedSnParam.put("projectNo", paramMap.get("orderNo"));
if(paramMap.get("logId") != null && !paramMap.get("logId").equals("")) {
usedSnParam.put("excludeLogId", paramMap.get("logId"));
}
List<Map<String, Object>> usedSnList = salesNcollectMgmtService.getUsedSplitSerialNos(usedSnParam);
// 이미 사용된 S/N들을 하나의 콤마 구분 문자열로 합침
StringBuilder usedSnBuilder = new StringBuilder();
for(Map<String, Object> usedSn : usedSnList) {
String splitSn = (String) usedSn.get("split_serial_no");
if(splitSn != null && !splitSn.isEmpty()) {
if(usedSnBuilder.length() > 0) usedSnBuilder.append(",");
usedSnBuilder.append(splitSn);
}
}
request.setAttribute("usedSplitSerialNos", usedSnBuilder.toString());
}
// 수정 모드: saleInfo에서 담당자 선택값 반영
if(saleInfo != null && saleInfo.get("MANAGER") != null) {
String selectedManager = saleInfo.get("MANAGER").toString();

View File

@@ -844,14 +844,9 @@
FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID) AS PAYMENT_TYPE,
T.PART_NO AS PRODUCT_NO,
T.PART_NAME AS PRODUCT_NAME,
-- S/N: CONTRACT_ITEM_SERIAL(마스터) 우선, 없으면 판매등록 텍스트 fallback (그리드 요약용)
-- S/N: CONTRACT_ITEM_SERIAL(마스터) 우선, 없으면 판매등록 텍스트 fallback (콤마 구분 전체 목록)
COALESCE(
(SELECT
CASE
WHEN COUNT(*) = 0 THEN NULL
WHEN COUNT(*) = 1 THEN MIN(CIS.SERIAL_NO)
ELSE MIN(CIS.SERIAL_NO) || ' 외 ' || (COUNT(*) - 1)::TEXT || '건'
END
(SELECT STRING_AGG(CIS.SERIAL_NO, ',' ORDER BY CIS.SEQ)
FROM CONTRACT_ITEM CI
LEFT JOIN CONTRACT_ITEM_SERIAL CIS ON CI.OBJID = CIS.ITEM_OBJID AND UPPER(CIS.STATUS) = 'ACTIVE'
WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID
@@ -860,6 +855,15 @@
AND CIS.SERIAL_NO IS NOT NULL),
SR.serial_no
) AS SERIAL_NO,
-- 분할S/N: shipment_log에서 해당 프로젝트의 모든 분할S/N 집계
COALESCE(
(SELECT STRING_AGG(SL_SN.split_serial_no, ',' ORDER BY SL_SN.log_id)
FROM shipment_log SL_SN
WHERE SL_SN.target_objid = T.PROJECT_NO
AND SL_SN.split_serial_no IS NOT NULL
AND SL_SN.split_serial_no != ''),
''
) AS SPLIT_SERIAL_NO,
COALESCE(NULLIF(REPLACE(T.QUANTITY, ',', ''), '')::numeric, 0) AS ORDER_QUANTITY,
-- 요청납기: CONTRACT_ITEM 우선, 없으면 PROJECT_MGMT, 없으면 CONTRACT_MGMT
COALESCE(
@@ -1902,7 +1906,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
remaining_quantity, shipping_status, shipping_date, shipping_method,
sales_unit_price, sales_supply_price, sales_vat, sales_total_amount,
sales_currency, sales_exchange_rate, manager_user_id, incoterms,
serial_no, parent_sale_no, reg_user_id
serial_no, parent_sale_no, reg_user_id, split_serial_no
) VALUES (
#{targetObjid}, 'SPLIT_SHIPMENT', '분할 출하',
#{salesQuantity}::integer, #{originalQuantity}::integer, #{remainingQuantity}::integer,
@@ -1916,7 +1920,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
#{shippingMethod}, #{salesUnitPrice}::numeric, #{salesSupplyPrice}::numeric,
#{salesVat}::numeric, #{salesTotalAmount}::numeric, #{salesCurrency},
#{salesExchangeRate}::numeric, #{managerUserId}, #{incoterms}, #{serialNo},
#{parentSaleNo}::integer, #{cretEmpNo}
#{parentSaleNo}::integer, #{cretEmpNo}, #{splitSerialNo}
)
</insert>
@@ -1994,6 +1998,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
WHERE PM.PROJECT_NO = SL.target_objid AND CI.STATUS = 'ACTIVE'
), '-') AS serial_no,
SL.target_objid AS project_no,
COALESCE(SL.split_serial_no, '-') AS split_serial_no,
TO_CHAR(SL.reg_date, 'YYYY-MM-DD HH24:MI:SS') AS reg_date
FROM shipment_log SL
WHERE SL.target_objid = #{projectNo}
@@ -2025,6 +2030,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
COALESCE(SL.sales_exchange_rate, 0) AS SALES_EXCHANGE_RATE,
COALESCE(SL.manager_user_id, '') AS MANAGER,
COALESCE(SL.incoterms, '') AS INCOTERMS,
COALESCE(SL.split_serial_no, '') AS SPLIT_SERIAL_NO,
COALESCE(SL.original_quantity, 0) AS ORDER_QUANTITY,
COALESCE(SL.remaining_quantity, 0) AS REMAINING_QUANTITY
FROM shipment_log SL
@@ -2070,6 +2076,9 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
<if test="incoterms != null and incoterms != ''">
, incoterms = #{incoterms}
</if>
<if test="splitSerialNo != null and splitSerialNo != ''">
, split_serial_no = #{splitSerialNo}
</if>
WHERE log_id = #{logId}::integer
</update>
@@ -2406,6 +2415,7 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
WHERE CI.CONTRACT_OBJID = T.CONTRACT_OBJID
AND CI.PART_OBJID = T.PART_OBJID AND CI.STATUS = 'ACTIVE'
), '') AS SERIAL_NO,
COALESCE(SL.split_serial_no, '') AS SPLIT_SERIAL_NO,
COALESCE(NULLIF(REPLACE(T.QUANTITY, ',', ''), '')::numeric, 0) AS ORDER_QUANTITY,
(SELECT CM.PO_NO FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID) AS PO_NO,
COALESCE(T.CONTRACT_DATE, (SELECT CM.order_date FROM CONTRACT_MGMT CM WHERE CM.OBJID = T.CONTRACT_OBJID)) AS ORDER_DATE,
@@ -2742,6 +2752,22 @@ ORDER BY T.REGDATE DESC, T.PROJECT_NO DESC
WHERE PROJECT_NO = #{projectNo}
</update>
<!-- 프로젝트의 이미 사용된 분할S/N 목록 조회 -->
<select id="getUsedSplitSerialNos" parameterType="map" resultType="map">
/* salesNcollectMgmt.getUsedSplitSerialNos - 이미 사용된 분할S/N 조회 */
SELECT
SL.log_id,
COALESCE(SL.split_serial_no, '') AS split_serial_no
FROM shipment_log SL
WHERE SL.target_objid = #{projectNo}
<if test="excludeLogId != null and excludeLogId != ''">
AND SL.log_id != #{excludeLogId}::integer
</if>
AND SL.split_serial_no IS NOT NULL
AND SL.split_serial_no != ''
ORDER BY SL.log_id
</select>
</mapper>

View File

@@ -401,6 +401,10 @@ public Map<String, Object> saveSaleRegistration(HttpServletRequest request, Map<
if(logId != null && !"".equals(logId)) {
System.out.println("=== shipment_log 수정 모드 (logId: " + logId + ") ===");
paramMap.put("shippingOrderStatus", "출하지시");
// splitSerialNo가 있으면 전달
if(paramMap.get("splitSerialNo") != null) {
paramMap.put("splitSerialNo", paramMap.get("splitSerialNo"));
}
sqlSession.update("salesNcollectMgmt.updateShipmentLog", paramMap);
} else {
// 신규 등록 → shipment_log에 INSERT
@@ -424,6 +428,7 @@ public Map<String, Object> saveSaleRegistration(HttpServletRequest request, Map<
logParam.put("managerUserId", paramMap.get("managerUserId"));
logParam.put("incoterms", paramMap.get("incoterms"));
logParam.put("serialNo", paramMap.get("serialNo"));
logParam.put("splitSerialNo", paramMap.get("splitSerialNo"));
logParam.put("parentSaleNo", null);
logParam.put("cretEmpNo", paramMap.get("cretEmpNo"));
@@ -518,6 +523,23 @@ public Map<String, Object> saveSaleRegistration(HttpServletRequest request, Map<
return resultMap;
}
/**
* 프로젝트의 이미 사용된 분할S/N 목록 조회
*/
public List<Map<String, Object>> getUsedSplitSerialNos(Map<String, Object> paramMap) {
SqlSession sqlSession = null;
List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
try {
sqlSession = SqlMapConfig.getInstance().getSqlSession(true);
resultList = sqlSession.selectList("salesNcollectMgmt.getUsedSplitSerialNos", paramMap);
} catch(Exception e) {
e.printStackTrace();
} finally {
if(sqlSession != null) sqlSession.close();
}
return resultList;
}
/**
* <pre>
* 분할출하 처리 (로그 기반)