Sfoglia il codice sorgente

feat: 批量订单导入;

hanchaolong 2 settimane fa
parent
commit
dda0e146ff

+ 5 - 2
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/controller/BizWaybillOrderController.java

@@ -193,14 +193,17 @@ public class BizWaybillOrderController extends BaseController
 
             // 使用 ExcelUtil 读取 Excel 数据
             if (1 == orderType) {
-                ExcelUtil<JDOrderDTO> util = new ExcelUtil<>(JDOrderDTO.class);
-                List<JDOrderDTO> orderList = util.importExcel(file.getInputStream());
+                List<JDOrderDTO> orderList = EasyExcel.read(file.getInputStream())
+                        .head(JDOrderDTO.class)
+                        .sheet()
+                        .doReadSync();
 
                 // 校验数据
                 if (orderList == null || orderList.isEmpty()) {
                     return AjaxResult.error("Excel 文件中没有有效的订单数据");
                 }
 
+                total = orderList.size();
                 // 调用批量下单方法
                 bizWaybillOrderService.batchInsertJDBizWaybillOrder(orderList, orderType);
             }

+ 2 - 215
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/domain/dto/JDOrderDTO.java

@@ -7,6 +7,7 @@ import com.alibaba.excel.annotation.write.style.ColumnWidth;
 import com.alibaba.excel.annotation.write.style.HeadRowHeight;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.ruoyi.common.core.annotation.Excel;
+import lombok.Data;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
@@ -17,6 +18,7 @@ import java.util.Date;
  */
 @HeadRowHeight(20)
 @ExcelIgnoreUnannotated
+@Data
 public class JDOrderDTO implements Serializable {
     private static final long serialVersionUID = 1L;
 
@@ -133,219 +135,4 @@ public class JDOrderDTO implements Serializable {
     @ColumnWidth(15)
     private String isReceiptCollect;
 
-    public String getSenderName() {
-        return senderName;
-    }
-
-    public void setSenderName(String senderName) {
-        this.senderName = senderName;
-    }
-
-    public String getSenderPhone() {
-        return senderPhone;
-    }
-
-    public void setSenderPhone(String senderPhone) {
-        this.senderPhone = senderPhone;
-    }
-
-    public String getSenderProvince() {
-        return senderProvince;
-    }
-
-    public void setSenderProvince(String senderProvince) {
-        this.senderProvince = senderProvince;
-    }
-
-    public String getSenderCity() {
-        return senderCity;
-    }
-
-    public void setSenderCity(String senderCity) {
-        this.senderCity = senderCity;
-    }
-
-    public String getSenderCounty() {
-        return senderCounty;
-    }
-
-    public void setSenderCounty(String senderCounty) {
-        this.senderCounty = senderCounty;
-    }
-
-    public String getSenderAddress() {
-        return senderAddress;
-    }
-
-    public void setSenderAddress(String senderAddress) {
-        this.senderAddress = senderAddress;
-    }
-
-    public String getReceiverName() {
-        return receiverName;
-    }
-
-    public void setReceiverName(String receiverName) {
-        this.receiverName = receiverName;
-    }
-
-    public String getReceiverPhone() {
-        return receiverPhone;
-    }
-
-    public void setReceiverPhone(String receiverPhone) {
-        this.receiverPhone = receiverPhone;
-    }
-
-    public String getReceiverProvince() {
-        return receiverProvince;
-    }
-
-    public void setReceiverProvince(String receiverProvince) {
-        this.receiverProvince = receiverProvince;
-    }
-
-    public String getReceiverCity() {
-        return receiverCity;
-    }
-
-    public void setReceiverCity(String receiverCity) {
-        this.receiverCity = receiverCity;
-    }
-
-    public String getReceiverCounty() {
-        return receiverCounty;
-    }
-
-    public void setReceiverCounty(String receiverCounty) {
-        this.receiverCounty = receiverCounty;
-    }
-
-    public String getReceiverAddress() {
-        return receiverAddress;
-    }
-
-    public void setReceiverAddress(String receiverAddress) {
-        this.receiverAddress = receiverAddress;
-    }
-
-    public String getGoodsName() {
-        return goodsName;
-    }
-
-    public void setGoodsName(String goodsName) {
-        this.goodsName = goodsName;
-    }
-
-    public BigDecimal getGoodsWeight() {
-        return goodsWeight;
-    }
-
-    public void setGoodsWeight(BigDecimal goodsWeight) {
-        this.goodsWeight = goodsWeight;
-    }
-
-    public BigDecimal getGoodsVolume() {
-        return goodsVolume;
-    }
-
-    public void setGoodsVolume(BigDecimal goodsVolume) {
-        this.goodsVolume = goodsVolume;
-    }
-
-    public Long getGoodsQty() {
-        return goodsQty;
-    }
-
-    public void setGoodsQty(Long goodsQty) {
-        this.goodsQty = goodsQty;
-    }
-
-    public Integer getPickupType() {
-        return pickupType;
-    }
-
-    public void setPickupType(Integer pickupType) {
-        this.pickupType = pickupType;
-    }
-
-    public String getSendStartTime() {
-        return sendStartTime;
-    }
-
-    public void setSendStartTime(String sendStartTime) {
-        this.sendStartTime = sendStartTime;
-    }
-
-    public String getSendEndTime() {
-        return sendEndTime;
-    }
-
-    public void setSendEndTime(String sendEndTime) {
-        this.sendEndTime = sendEndTime;
-    }
-
-    public String getProductCode() {
-        return productCode;
-    }
-
-    public void setProductCode(String productCode) {
-        this.productCode = productCode;
-    }
-
-    public String getAddedService() {
-        return addedService;
-    }
-
-    public void setAddedService(String addedService) {
-        this.addedService = addedService;
-    }
-
-    public String getRemark() {
-        return remark;
-    }
-
-    public void setRemark(String remark) {
-        this.remark = remark;
-    }
-
-    public String getIsPack() {
-        return isPack;
-    }
-
-    public void setIsPack(String isPack) {
-        this.isPack = isPack;
-    }
-
-    public BigDecimal getGuaranteeMoney() {
-        return guaranteeMoney;
-    }
-
-    public void setGuaranteeMoney(BigDecimal guaranteeMoney) {
-        this.guaranteeMoney = guaranteeMoney;
-    }
-
-    public String getIsReceiptCollect() {
-        return isReceiptCollect;
-    }
-
-    public void setIsReceiptCollect(String isReceiptCollect) {
-        this.isReceiptCollect = isReceiptCollect;
-    }
-
-    public Date getPickupStartTime() {
-        return pickupStartTime;
-    }
-
-    public void setPickupStartTime(Date pickupStartTime) {
-        this.pickupStartTime = pickupStartTime;
-    }
-
-    public Date getPickupEndTime() {
-        return pickupEndTime;
-    }
-
-    public void setPickupEndTime(Date pickupEndTime) {
-        this.pickupEndTime = pickupEndTime;
-    }
 }

+ 108 - 44
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/BizWaybillOrderServiceImpl.java

@@ -2,6 +2,7 @@ package com.ruoyi.logistics.service.impl;
 
 import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
+import java.text.ParseException;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
@@ -380,7 +381,6 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
      */
     @Override
     public int batchInsertJDBizWaybillOrder(List<JDOrderDTO> orderList, Integer orderType) {
-        int successCount = 0;
         int failCount = 0;
         List<String> errorMessages = new ArrayList<>();
 
@@ -392,34 +392,46 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
         Set<String> collect = sysDeptRates.stream().map(SysDeptRate::getProductType).collect(Collectors.toSet());
 
         List<BizWaybillOrder> bizWaybillOrders = new ArrayList<>();
-        for (JDOrderDTO dto : orderList) {
+        for (int i = 0; i < orderList.size(); i++) {
+            JDOrderDTO dto = orderList.get(i);
+            int row = i + 2; // 行号从1开始
             try {
                 preDataVerify(dto, collect);
 
                 // 将 JDOrderDTO 转换为 BizWaybillOrder
                 BizWaybillOrder bizWaybillOrder = convertToBizWaybillOrder(dto, loginUser);
+                String orderId = redisIdGenerator.generateUniqueId("RJSD");
+                bizWaybillOrder.setWaybillNo(orderId);
+                bizWaybillOrder.setOrderStatus(OrderStatusEnum.ORDER_STATUS_1.getCode());
 
                 // 前置校验
+                String senderProvince = bizWaybillOrder.getSenderProvince();
+                String senderCity = bizWaybillOrder.getSenderCity();
+                String senderCounty = bizWaybillOrder.getSenderCounty();
+                String receiverProvince = bizWaybillOrder.getReceiverProvince();
+                String receiverCity = bizWaybillOrder.getReceiverCity();
+                String receiverCounty = bizWaybillOrder.getReceiverCounty();
+
+                bizWaybillOrder.setSenderProvince("");
+                bizWaybillOrder.setSenderCity("");
+                bizWaybillOrder.setSenderCounty("");
+                bizWaybillOrder.setReceiverProvince("");
+                bizWaybillOrder.setReceiverCity("");
+                bizWaybillOrder.setReceiverCounty("");
+
                 JSONObject jsonObject = logisticsOrderService.precheckOrder(bizWaybillOrder);
                 if (!jsonObject.getBooleanValue("success")) {
                     log.warn("订单前置校验未通过!发件人:{}, 收件人:{}, 原因:{}",
                             dto.getSenderName(), dto.getReceiverName(), jsonObject.getString("msg"));
-                    failCount++;
-                    errorMessages.add(String.format("订单 %s-%s 校验失败:%s",
-                            dto.getSenderName(), dto.getReceiverName(), jsonObject.getString("msg")));
-                    continue;
+                    throw new ServiceException(jsonObject.getString("msg"));
                 }
 
-                // 调用下单接口
-                JSONObject orderObject = logisticsOrderService.createOrder(bizWaybillOrder);
-                if (!orderObject.getBooleanValue("success")) {
-                    log.warn("下单失败!发件人:{}, 收件人:{}, 原因:{}",
-                            dto.getSenderName(), dto.getReceiverName(), orderObject.getString("msg"));
-                    failCount++;
-                    errorMessages.add(String.format("订单 %s-%s 下单失败:%s",
-                            dto.getSenderName(), dto.getReceiverName(), orderObject.getString("msg")));
-                    continue;
-                }
+                bizWaybillOrder.setSenderProvince(senderProvince);
+                bizWaybillOrder.setSenderCity(senderCity);
+                bizWaybillOrder.setSenderCounty(senderCounty);
+                bizWaybillOrder.setReceiverProvince(receiverProvince);
+                bizWaybillOrder.setReceiverCity(receiverCity);
+                bizWaybillOrder.setReceiverCounty(receiverCounty);
 
                 // 设置默认值
                 bizWaybillOrder.setPickupType(1);
@@ -427,14 +439,13 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
                 bizWaybillOrder.setUserId(loginUser.getUserid());
                 bizWaybillOrder.setDeptId(loginUser.getSysUser().getDeptId());
 
-
                 bizWaybillOrders.add(bizWaybillOrder);
             } catch (Exception e) {
                 log.error("批量下单异常!发件人:{}, 收件人:{}", 
                     dto.getSenderName(), dto.getReceiverName(), e);
                 failCount++;
-                errorMessages.add(String.format("订单 %s-%s 异常:%s", 
-                    dto.getSenderName(), dto.getReceiverName(), e.getMessage()));
+                errorMessages.add(String.format("第 %s 行订单 %s-%s 异常:%s",
+                    row, dto.getSenderName(), dto.getReceiverName(), e.getMessage()));
             }
         }
 
@@ -442,27 +453,69 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
             throw new ServiceException("批量下单失败!失败原因:" + StringUtils.join(errorMessages, "\n"));
         }
 
-        bizWaybillOrders.forEach(bizWaybillOrder -> {
-            // 保存到数据库
-            bizWaybillOrderMapper.insertBizWaybillOrder(bizWaybillOrder);
-        });
+        jdOrderImport(bizWaybillOrders);
         return bizWaybillOrders.size();
     }
 
+    @Async
+    private void jdOrderImport(List<BizWaybillOrder> bizWaybillOrders) {
+        String batchNum = redisIdGenerator.generateUniqueId("JDPC");
+
+        int successCount = 0;
+        int failCount = 0;
+        List<String> errorMessages = new ArrayList<>();
+        for (BizWaybillOrder dto : bizWaybillOrders) {
+            try {
+                // 调用下单接口
+                JSONObject orderObject = logisticsOrderService.createOrder(dto);
+                if (!orderObject.getBooleanValue("success")) {
+                    log.warn("下单失败!发件人:{}, 收件人:{}, 原因:{}",
+                            dto.getSenderName(), dto.getReceiverName(), orderObject.getString("msg"));
+                    failCount++;
+                    errorMessages.add(String.format("订单 %s-%s 下单失败:%s",
+                            dto.getSenderName(), dto.getReceiverName(), orderObject.getString("msg")));
+                    continue;
+                }
+
+                dto.setBatchNum(batchNum);
+                // 保存到数据库
+                int result = bizWaybillOrderMapper.insertBizWaybillOrder(dto);
+                if (result > 0) {
+                    successCount++;
+                    // 保存最近使用地址
+                    saveRecentAddresses(dto, dto.getUserId());
+                } else {
+                    failCount++;
+                    errorMessages.add(String.format("订单 %s-%s 保存失败",
+                            dto.getSenderName(), dto.getReceiverName()));
+                }
+            } catch (Exception e) {
+                log.error("批量下单异常!发件人:{}, 收件人:{}",
+                        dto.getSenderName(), dto.getReceiverName(), e);
+                failCount++;
+                errorMessages.add(String.format("订单 %s-%s 异常:%s",
+                        dto.getSenderName(), dto.getReceiverName(), e.getMessage()));
+            }
+        }
+        log.info("批量下单完成!总数:{}, 成功:{}, 失败:{}", bizWaybillOrders.size(), successCount, failCount);
+    }
+
     private void preDataVerify(JDOrderDTO dto, Set<String> collect) {
+        StringBuilder errorMsg = new StringBuilder();
         if (dto == null) {
-            throw new ServiceException("数据异常!订单数据不能为空");
+            errorMsg.append("订单数据不能为空");
+            return;
         }
 
         // 校验寄件人信息
         if (StringUtils.isBlank(dto.getSenderName())) {
-            throw new ServiceException("数据异常!寄件人姓名不能为空");
+            errorMsg.append("寄件人姓名不能为空;");
         }
         if (StringUtils.isBlank(dto.getSenderPhone())) {
-            throw new ServiceException("数据异常!寄件人电话不能为空");
+            errorMsg.append("寄件人电话不能为空;");
         }
         if (StringUtils.isBlank(dto.getSenderAddress())) {
-            throw new ServiceException("数据异常!寄件详细地址不能为空");
+            errorMsg.append("寄件详细地址不能为空;");
         }
 
         Map param = new HashMap();
@@ -483,20 +536,20 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
             dto.setSenderCity(receiverCity);
             dto.setSenderCounty(receiverDistrict);
         } catch (Exception e) {
-            throw new ServiceException("数据异常!寄件详细地址识别有误");
+            errorMsg.append("寄件详细地址识别有误;");
         }
 
         // 校验收件人信息
         if (StringUtils.isBlank(dto.getReceiverName())) {
-            throw new ServiceException("数据异常!收件人姓名不能为空");
+            errorMsg.append("收件人姓名不能为空;");
         }
         if (StringUtils.isBlank(dto.getReceiverPhone())) {
-            throw new ServiceException("数据异常!收件人电话不能为空");
+            errorMsg.append("收件人电话不能为空;");
         }
         if (StringUtils.isBlank(dto.getReceiverAddress())) {
-            throw new ServiceException("数据异常!收件详细地址不能为空");
+            errorMsg.append("收件详细地址不能为空;");
         }
-        param.put("param", dto.getSenderAddress());
+        param.put("param", dto.getReceiverAddress());
         try {
             Map result = kuaidi100Service.queryIcrExpres(param);
             Map<String, Object> receiverData = (Map<String, Object>) result.get("data");
@@ -513,42 +566,53 @@ public class BizWaybillOrderServiceImpl implements IBizWaybillOrderService
             dto.setReceiverCity(receiverCity);
             dto.setReceiverCounty(receiverDistrict);
         } catch (Exception e) {
-            throw new ServiceException("数据异常!收件详细地址识别有误");
+            errorMsg.append("收件详细地址识别有误;");
         }
 
         // 校验货物信息
         if (StringUtils.isBlank(dto.getGoodsName())) {
-            throw new ServiceException("数据异常!物品名称不能为空");
+            errorMsg.append("物品名称不能为空;");
         }
         if (dto.getGoodsWeight() == null) {
-            throw new ServiceException("数据异常!物品重量不能为空");
+            errorMsg.append("物品重量不能为空;");
         }
         if (dto.getGoodsVolume() == null) {
-            throw new ServiceException("数据异常!物品体积不能为空");
+            errorMsg.append("物品体积不能为空;");
         }
         if (dto.getGoodsQty() == null) {
-            throw new ServiceException("数据异常!物品数量不能为空");
+            errorMsg.append("物品数量不能为空;");
         }
 
         // 校验取件时间
         if (dto.getSendStartTime() == null || dto.getSendEndTime() == null) {
-            throw new ServiceException("数据异常!上门取件开始时间和结束时间不能为空");
+            errorMsg.append("上门取件开始时间和结束时间不能为空;");
+        }
+        try {
+            dto.setPickupStartTime(DateUtils.parseDate(dto.getSendStartTime(), "yyyy-MM-dd HH:mm:ss"));
+        } catch (ParseException e) {
+            errorMsg.append("上门取件开始时间格式不正确");
+        }
+        try {
+            dto.setPickupEndTime(DateUtils.parseDate(dto.getSendEndTime(), "yyyy-MM-dd HH:mm:ss"));
+        } catch (ParseException e) {
+            errorMsg.append("上门取件开始时间格式不正确");
         }
-        dto.setPickupStartTime(DateUtils.dateTime(dto.getSendStartTime(), "yyyy-MM-dd HH:mm:ss"));
-        dto.setPickupEndTime(DateUtils.dateTime(dto.getSendEndTime(), "yyyy-MM-dd HH:mm:ss"));
         if (dto.getPickupStartTime().getTime() > dto.getPickupEndTime().getTime()) {
-            throw new ServiceException("数据异常!上门取件开始时间不能大于上门取件结束时间");
+            errorMsg.append("上门取件开始时间不能大于上门取件结束时间;");
         }
 
         // 校验产品类型
         if (StringUtils.isBlank(dto.getProductCode())) {
-            throw new ServiceException("数据异常!产品类型不能为空");
+            errorMsg.append("产品类型不能为空;");
         }
+        dto.setProductCode(getProductCode(dto.getProductCode()));
         if (!collect.contains(dto.getProductCode())) {
-            throw new ServiceException("数据异常!产品类型不存在");
+            errorMsg.append("产品类型不存在;");
         }
 
-
+        if (StringUtils.isNotBlank(errorMsg)) {
+            throw new ServiceException(errorMsg.toString());
+        }
     }
     @Async
     @Override