Browse Source

【越加红】【WMS对接】【出库明细取消】

wuyx 6 months ago
parent
commit
d38c86ee75

+ 4 - 6
src/main/java/com/uas/eis/controller/ERPController.java

@@ -1,11 +1,9 @@
 package com.uas.eis.controller;
 
+import com.uas.eis.entity.vwms.req.ErpCancelIORequest;
 import com.uas.eis.service.ERPService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.Map;
 
@@ -44,8 +42,8 @@ public class ERPController {
      */
     @RequestMapping(value="/erp/cancelIO",method=RequestMethod.POST)
     @ResponseBody
-    public Map<String, Object> cancelIO(String master, String id,String emCode,String caller,String op){
-        return null;
+    public Map<String, Object> cancelIO(@RequestBody ErpCancelIORequest erpCancelIORequest){
+        return erpService.cancelIO(erpCancelIORequest);
     }
 
 }

+ 1 - 1
src/main/java/com/uas/eis/entity/vwms/entity/OrderLine.java

@@ -12,5 +12,5 @@ public class OrderLine {
     private String ownerCode; // 货主编码
     private String itemCode; // 商品编码
     private String itemName; // 商品名称
-    private Float planQty; // 应收商品数量
+    private Double planQty; // 应收商品数量
 }

+ 1 - 1
src/main/java/com/uas/eis/entity/vwms/entity/Prodiodetail.java

@@ -9,7 +9,7 @@ public class Prodiodetail {
     private Integer pdPdno;
     private String pdProdcode;
     private String pdProdname;
-    private Float pdQty;
+    private Double pdQty;
     private String pdWhcode;
     private String pdWhname;
     private String pdBrandName;

+ 42 - 0
src/main/java/com/uas/eis/entity/vwms/req/CancelIORequest.java

@@ -0,0 +1,42 @@
+package com.uas.eis.entity.vwms.req;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@JacksonXmlRootElement(localName = "request")
+public class CancelIORequest {
+    @JacksonXmlProperty(localName = "cancelItems")
+    CancelItems cancelItems;
+    @Data
+    public static class CancelItems{
+        @JacksonXmlElementWrapper(useWrapping = false)  // 去掉外层的包装
+        @JacksonXmlProperty(localName = "cancelItem")
+        List<CancelItem> cancelItem;
+    }
+
+    @Data
+    public static class CancelItem{
+        private String warehouseCode;//出库仓库编码(物理仓)
+        private String logicWarehouseCode;//逻辑仓
+        private String deliveryOrderCode;//出库单号
+        private String orderLineNo; // 行号
+        private String ownerCode; // 货主编码
+        private String itemCode; // 商品编码
+        private String itemName; // 商品名称
+        private Double cancelQty; // 应收商品数量
+
+        public CancelItem() {
+        }
+
+        public CancelItem(String warehouseCode, String ownerCode, String deliveryOrderCode) {
+            this.warehouseCode = warehouseCode;
+            this.deliveryOrderCode = deliveryOrderCode;
+            this.ownerCode = ownerCode;
+        }
+    }
+}

+ 12 - 0
src/main/java/com/uas/eis/entity/vwms/req/ErpCancelIORequest.java

@@ -0,0 +1,12 @@
+package com.uas.eis.entity.vwms.req;
+
+import lombok.Data;
+
+@Data
+public class ErpCancelIORequest{
+    String master;
+    String emCode;
+    String caller;
+    String formStore;
+    String gridStore;
+}

+ 2 - 1
src/main/java/com/uas/eis/service/DocCommonService.java

@@ -12,7 +12,8 @@ import java.util.Map;
  * @date 2025-03-04
  */
 public interface DocCommonService {
-    ProdInout getIO(String master,String id);
+    ProdInout getIO(String master,String id,String pdIds);
     String sendOutToWms(ProdInout prodInOut, String masterName);
     String sendInToWms(ProdInout prodInOut, String masterName);
+    String doPostToWms(String xml,String method);
 }

+ 3 - 0
src/main/java/com/uas/eis/service/ERPService.java

@@ -2,6 +2,8 @@ package com.uas.eis.service;
 
 
 
+import com.uas.eis.entity.vwms.req.ErpCancelIORequest;
+
 import java.util.Map;
 
 /**
@@ -14,4 +16,5 @@ public interface ERPService {
 
     Map<String, Object> sendIO(String master, String id, String emCode, String caller);
 
+    Map<String, Object> cancelIO(ErpCancelIORequest erpCancelIORequest);
 }

+ 20 - 13
src/main/java/com/uas/eis/service/Impl/DocCommonServiceImpl.java

@@ -45,12 +45,12 @@ public class DocCommonServiceImpl implements DocCommonService {
     private ObjectMapper objectMapper;  // 注入Jackson的ObjectMapper
 
     @Override
-    public ProdInout getIO(String master,String id){
+    public ProdInout getIO(String master,String id,String pdIds){
         // 查询主表信息
         ProdInout prodInOut = queryMainTable(master, id);
         prodInOut.setOutBizCode(prodInOut.getPiOrderType()+"-"+System.currentTimeMillis());// 外部业务代码 消息ID, 用于去重, 因为网络等原因导致重复传输, 请求不会被重复处理
         // 构建明细查询SQL
-        String detSql = buildDetailSql(master, prodInOut);
+        String detSql = buildDetailSql(master, prodInOut,pdIds);
         // 查询明细数据
         List<Prodiodetail> details = queryDetails(master, detSql);
         prodInOut.setDetails(details);
@@ -94,7 +94,7 @@ public class DocCommonServiceImpl implements DocCommonService {
                 new BeanPropertyRowMapper<>(ProdInout.class));
         return prodInOuts.get(0);
     }
-    private String buildDetailSql(String master, ProdInout prodInOut) {
+    private String buildDetailSql(String master, ProdInout prodInOut,String pdIds) {
         StringBuilder sqlBuilder = new StringBuilder();
         if ("in".equals(prodInOut.getPiWmsInType())) {
             sqlBuilder.append("select pd_piid pdPiid,(pd_id) pdId,(pd_pdno) pdPdno,pd_prodcode pdProdcode,pr_detail pdProdname,pr_brand pdBrandName" +
@@ -118,8 +118,11 @@ public class DocCommonServiceImpl implements DocCommonService {
                         .append(" left join ").append(master).append(".saledetail on sd_Code = pd_ordercode and sd_Detno = pd_orderdetno ")
                         .append(" left join ").append(master).append(".TRANSFERSTOCK ON PI_INOUTNO = TS_CODE ")
                         .append(" left join ").append(master).append(".TRANSFERSTOCKDETAIL ON TS_ID=TSD_TSID AND PD_PDNO = TSD_DETNO ")
-                        .append("where pd_piid = ").append(prodInOut.getPiId()).append(" and nvl(pr_sendwmsflag,0) = -1")
-                        .append(" order by pd_pdno ");
+                        .append("where pd_piid = ").append(prodInOut.getPiId()).append(" and nvl(pr_sendwmsflag,0) = -1");
+                if(StringUtil.hasText(pdIds)){
+                    sqlBuilder.append(" and pd_id in (").append(pdIds).append(")");
+                }
+                sqlBuilder.append(" order by pd_pdno ");
             }else {
                 sqlBuilder.append("select pd_piid pdPiid,(pd_id) pdId,(pd_pdno) pdPdno,pd_prodcode pdProdcode,")
                         .append("pr_detail pdProdname,pr_brand pdBrandName,(nvl(pd_inqty,0)+nvl(pd_outqty,0)) pdQty,")
@@ -131,8 +134,11 @@ public class DocCommonServiceImpl implements DocCommonService {
                         .append(" left join ").append(master).append(".product on pr_code = pd_prodcode ")
                         .append(" left join ").append(master).append(".warehouse on wh_Code = pd_whcode ")
                         .append(" left join ").append(master).append(".saledetail on sd_Code = pd_ordercode and sd_Detno = pd_orderdetno ")
-                        .append("where pd_piid = ").append(prodInOut.getPiId()).append(" and nvl(pr_sendwmsflag,0) = -1")
-                        .append(" order by pd_pdno ");
+                        .append("where pd_piid = ").append(prodInOut.getPiId()).append(" and nvl(pr_sendwmsflag,0) = -1");
+                if(StringUtil.hasText(pdIds)){
+                    sqlBuilder.append(" and pd_id in (").append(pdIds).append(")");
+                }
+                sqlBuilder.append(" order by pd_pdno ");
             }
         }
         return sqlBuilder.toString();
@@ -262,7 +268,7 @@ public class DocCommonServiceImpl implements DocCommonService {
             return "JSON转换失败";
         }
         //TODO 写入表:WMS_IO_RECORD_SEQ
-        return doSendOrderToWms(xml,method);
+        return doPostToWms(xml,method);
     }
 
     @Override
@@ -293,20 +299,21 @@ public class DocCommonServiceImpl implements DocCommonService {
             return "JSON转换失败";
         }
         //TODO 写入表:WMS_IO_RECORD_SEQ
-        return doSendOrderToWms(xml,method);
+        return doPostToWms(xml,method);
     }
-
-    private String doSendOrderToWms(String xml,String method){
+    @Override
+    public String doPostToWms(String xml,String method){
         String eMsg = null;
         try {
-            logger.info("doSendInOrderToWms method:{} XML: {}",method, xml);
+            logger.info("doPostToWms method:{} XML: {}",method, xml);
 //            HttpUtil.Response response = new HttpUtil.Response();
 //            response.setStatusCode(404);
+//            response.setResponseText("单据已分配。");
             HttpUtil.Response response = HttpUtil.postXmlToVWMS(method,xml, "UTF-8",vwmsConfig);
             if(!String.valueOf(response.getStatusCode()).startsWith("2")){
                 eMsg = "("+response.getStatusCode()+")"+StringUtil.nvl(response.getResponseText(),"未知").replaceAll("'","''");
             }else {
-                logger.info("doSendInOrderToWms method:{} response: {}",response.getResponseText());
+                logger.info("doPostToWms method:{} response: {}",response.getResponseText());
                 // 创建XmlMapper实例
                 XmlMapper xmlMapper = new XmlMapper();
                 IOResp ioResp = xmlMapper.readValue(response.getResponseText(), IOResp.class);

+ 130 - 4
src/main/java/com/uas/eis/service/Impl/ERPServiceImpl.java

@@ -15,12 +15,9 @@ import com.uas.eis.utils.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.stereotype.Service;
 
-import java.math.BigDecimal;
 import java.util.*;
-import java.util.stream.Collectors;
 
 /**
  * @author wuyx
@@ -187,7 +184,7 @@ public class ERPServiceImpl implements ERPService {
             retMap.put("message", "没有需要对接的明细。");
             return retMap;
         }
-        ProdInout prodInOut = docCommonService.getIO(master, id);
+        ProdInout prodInOut = docCommonService.getIO(master, id,null);
         if (CollectionUtil.isEmpty(prodInOut.getDetails())) {
             retMap.put("success", false);
             retMap.put("message", "没有需要同步的明细。");
@@ -236,4 +233,133 @@ public class ERPServiceImpl implements ERPService {
         return retMap;
     }
 
+    @Override
+    public Map<String, Object> cancelIO(ErpCancelIORequest erpCancelIORequest) {
+        String master = erpCancelIORequest.getMaster();
+        String emCode = erpCancelIORequest.getEmCode();
+        String caller = erpCancelIORequest.getCaller();
+        String formStore = erpCancelIORequest.getFormStore();
+        String gridStore = erpCancelIORequest.getGridStore();
+        Map<Object, Object> store = BaseUtil.parseFormStoreToMap(formStore);
+        List<Map<Object, Object>> gstore = BaseUtil.parseGridStoreToMaps(gridStore);
+        Object piId = store.get("pi_id");
+        Map<String, Object> retMap = new HashMap<>();
+        retMap.put("success", true);
+        logger.info("cancelIO-Begin:master {}  id {}", master, piId);
+        if(CollectionUtil.isEmpty(gstore)) {
+            logger.info("cancelIO-End:master {} id {} res {}", master, piId, "没有需要对接的明细。");
+            retMap.put("success", false);
+            retMap.put("message", "没有需要对接的明细。");
+            return retMap;
+        }
+        StringBuffer pdIds = new StringBuffer();
+        for (Map<Object, Object> map : gstore) {
+            if(pdIds.length()>0){
+                pdIds.append(",");
+            }
+            if(StringUtil.hasText(map.get("pd_id"))){
+                pdIds.append(map.get("pd_id"));
+            }
+            if(StringUtil.hasText(map.get("PD_ID"))){
+                pdIds.append(map.get("PD_ID"));
+            }
+        }
+        // 执行查询
+        if (!baseDao.checkIf(master + ".prodiodetail left join " + master + ".product on pr_code = pd_prodcode "
+                , "pd_id in (" + pdIds + ") and nvl(pr_sendwmsflag,0) = -1")) {
+            logger.info("cancelIO-End:master {} id {} res {}", master, piId, "明细不需要对接WMS。");
+            retMap.put("success", false);
+            retMap.put("message", "明细不需要对接WMS。");
+            return retMap;
+        }
+        ProdInout prodInOut = docCommonService.getIO(master, piId.toString(),pdIds.toString());
+        if (prodInOut.getPiWmsstatus().equals("已确认")) {
+            retMap.put("success", false);
+            retMap.put("message", "单据已确认采集,不允许重复同步。");
+            return retMap;
+        }
+        String ownerCode = master;
+        if("YUEJH_TEST".equals(master)){
+            ownerCode = "YUEJH";
+        }
+        if("YJH_T".equals(master)){
+            ownerCode = "AIFL";
+        }
+        if("YIT_T".equals(master)){
+            ownerCode = "YJH_HK";
+        }
+        String deliveryOrderCode = prodInOut.getPiInoutno();
+        String warehouseCode = vwmsConfig.getWarehouseCode();
+        List<Prodiodetail> prodiodetails = prodInOut.getDetails();
+        CancelIORequest cancelIORequest = new CancelIORequest();
+        CancelIORequest.CancelItems cancelItems = new CancelIORequest.CancelItems();
+        List<CancelIORequest.CancelItem> cancelItemList = new ArrayList<>();
+        for (Map<Object, Object> map : gstore) {
+            Long pdId = 0L;
+            Double qtyAfter = 0.0;
+            if(StringUtil.hasText(map.get("pd_id"))){
+                pdId = Long.valueOf(map.get("pd_id").toString());
+            }
+            if(StringUtil.hasText(map.get("PD_ID"))){
+                pdId = Long.valueOf(map.get("PD_ID").toString());
+            }
+            if(StringUtil.hasText(map.get("pd_outqty"))){
+                qtyAfter = Double.valueOf(map.get("pd_outqty").toString());
+            }
+            if(StringUtil.hasText(map.get("PD_OUTQTY"))){
+                qtyAfter = Double.valueOf(map.get("PD_OUTQTY").toString());
+            }
+            if(pdId > 0){
+                Long finalPdId = pdId;
+                Prodiodetail detail = prodiodetails.stream()
+                        .filter(p -> finalPdId.equals(p.getPdId()))
+                        .findFirst()
+                        .orElse(null);
+                if(detail != null) {
+                    Double qtyBefor = detail.getPdQty();
+                    Double cancelQty = NumberUtil.sub(qtyBefor,qtyAfter);
+                    if(cancelQty>0){
+                        CancelIORequest.CancelItem cancelItem = new CancelIORequest.CancelItem(warehouseCode,ownerCode,deliveryOrderCode);
+                        cancelItem.setOrderLineNo(String.valueOf(detail.getPdPdno()));
+                        cancelItem.setLogicWarehouseCode(detail.getPdWhcode());
+                        cancelItem.setItemCode(detail.getPdProdcode());
+                        cancelItem.setItemName(detail.getPdProdname());
+                        cancelItem.setCancelQty(cancelQty);
+                        cancelItemList.add(cancelItem);
+                    }
+                }
+            }
+        }
+        if(CollectionUtil.isEmpty(cancelItemList)){
+            retMap.put("success", false);
+            retMap.put("message", "无需要取消的明细。");
+            return retMap;
+        }
+        cancelItems.setCancelItem(cancelItemList);
+        cancelIORequest.setCancelItems(cancelItems);
+        String xml = null;
+        String method = "stockout.detailCancel";
+        try {
+            XmlMapper xmlMapper = new XmlMapper();
+            xml = xmlMapper.writeValueAsString(cancelIORequest);
+//            System.out.println("xml:"+xml);
+            String errMsg = docCommonService.doPostToWms(xml,method);
+            if (errMsg != null) {
+                    errMsg = errMsg.replaceAll("'", "''");
+                    logger.info("cancelIO-End-failure master {} pdIds {} errorTip {}", master, pdIds.toString(), errMsg);
+                    retMap.put("success", false);
+                    retMap.put("message", errMsg);
+                    return retMap;
+            } else {
+                logger.info("cancelIO-End-success master {} pdIds {} ", master, pdIds.toString());
+            }
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+            retMap.put("success", false);
+            retMap.put("message", "JSON转换失败。");
+            return retMap;
+        }
+        retMap.put("message", "取消成功。");
+        return retMap;
+    }
 }

+ 22 - 0
src/test/java/com/uas/eis/UasEisApplicationTests.java

@@ -10,6 +10,7 @@ import com.uas.eis.config.VwmsConfig;
 import com.uas.eis.dao.*;
 import com.uas.eis.entity.vwms.req.BaseItemsReq;
 import com.uas.eis.entity.vwms.req.BaseReq;
+import com.uas.eis.entity.vwms.req.ErpCancelIORequest;
 import com.uas.eis.entity.vwms.req.ProductReq;
 import com.uas.eis.entity.vwms.resp.BaseVastResp;
 import com.uas.eis.service.ERPService;
@@ -40,6 +41,27 @@ public class UasEisApplicationTests {
 	private ERPService erpService;
 	@Autowired
 	private VwmsConfig vwmsConfig;
+
+	@Test
+	public void testCancelIO(){
+		// 设置测试数据
+		String master = "YUEJH_TEST";
+		String emCode = "TEST";
+		String caller="ProdInOut!Sale";
+		String formStore = "{\"pi_id\":\"50744191\"}";
+		String gridStore = "[{\"pd_id\":47029492,\"pd_outqty\":0}]";
+		// 调用待测方法
+		ErpCancelIORequest erpCancelIORequest = new ErpCancelIORequest();
+		erpCancelIORequest.setMaster(master);
+		erpCancelIORequest.setEmCode(emCode);
+		erpCancelIORequest.setCaller(caller);
+		erpCancelIORequest.setFormStore(formStore);
+		erpCancelIORequest.setGridStore(gridStore);
+		Map<String, Object> result = erpService.cancelIO(erpCancelIORequest);
+		System.out.println("result:"+result.toString());
+	}
+
+
 	@Test
 	public void testSendJSTH(){
 		// 设置测试数据