guomengjiao il y a 3 mois
Parent
commit
06765c7573

+ 95 - 6
ruoyi-admin/src/main/java/com/ruoyi/web/controller/shop/order/ShopOrderController.java

@@ -20,29 +20,42 @@ import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.enums.FilePathSplicingType;
+import com.ruoyi.common.enums.order.OrderType;
+import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.filepathsplicing.FilePathSplicing;
+import com.ruoyi.common.utils.importverify.ImportVerifyHandler;
 import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.utils.poi.ImportUtil;
+import com.ruoyi.message.domain.bo.MessageBo;
+import com.ruoyi.message.enums.MessageType;
+import com.ruoyi.message.enums.ModelType;
+import com.ruoyi.message.service.ISendPrivateMessageMsgService;
+import com.ruoyi.shop.order.domain.ShopOrderPackage;
 import com.ruoyi.shop.order.domain.bo.BusinessCountBo;
 import com.ruoyi.shop.order.domain.bo.ShopOrderBo;
 import com.ruoyi.shop.order.domain.bo.ShopOrderBusinessRemarkBo;
 import com.ruoyi.shop.order.domain.vo.*;
-import com.ruoyi.common.enums.order.OrderType;
 import com.ruoyi.shop.order.enums.CancellationMethod;
 import com.ruoyi.shop.order.enums.ShippingMethod;
 import com.ruoyi.shop.order.enums.ShippingStatus;
 import com.ruoyi.shop.order.enums.TransactionStatus;
+import com.ruoyi.shop.order.service.IShopOrderPackageService;
 import com.ruoyi.shop.order.service.IShopOrderService;
-import com.ruoyi.shop.product.domain.bo.ProductBo;
-import com.ruoyi.shop.product.domain.vo.ProductVo;
+import com.ruoyi.shop.order.service.mqproduct.IShopOrderMqProductService;
 import com.ruoyi.shop.rights.service.ISaleRightsOrderService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
+import jodd.util.StringUtil;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.ss.usermodel.Workbook;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.util.CollectionUtils;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.activation.MimetypesFileTypeMap;
 import javax.servlet.http.HttpServletResponse;
@@ -51,8 +64,7 @@ import java.io.IOException;
 import java.math.BigDecimal;
 import java.net.URLEncoder;
 import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
+import java.util.concurrent.*;
 import java.util.stream.Collectors;
 
 /**
@@ -61,6 +73,7 @@ import java.util.stream.Collectors;
  * @author lubo
  * @date 2025-10-23
  */
+@Slf4j
 @Validated
 @Api(value = "订单控制器", tags = {"订单管理"})
 @RequiredArgsConstructor
@@ -71,8 +84,12 @@ public class ShopOrderController extends BaseController {
     private final IShopOrderService iShopOrderService;
     private final ISaleRightsOrderService rightsOrderService;
     private final IBusinessService iBusinessService;
-
     private final ThreadPoolTaskExecutor threadPoolTaskExecutor;
+    private final ImportVerifyHandler importVerifyHandler;
+    private final ThreadPoolExecutor executor;
+    private final IShopOrderPackageService shopOrderPackageService;
+    private final IShopOrderMqProductService shopOrderMqProductService;
+    private final ISendPrivateMessageMsgService sendPrivateMessageMsgService;
 
     /**
      * 平台分页查询订单列表
@@ -578,6 +595,78 @@ public class ShopOrderController extends BaseController {
         ExcelUtil.exportExcel(list, "待发货列表", ShopOrderWaitShipVo.class, response);
     }
 
+    /**
+     * 导入设置好的发货订单文件,批量发货
+     * @param multipartFile
+     * @param response
+     * @return
+     * @throws Exception
+     */
+    @PostMapping("/import_ship")
+    public R importUser(@RequestParam("file") MultipartFile multipartFile, HttpServletResponse response) throws Exception {
+        Long businessId = getBusinessId(true);
+        //获得excel中的数据
+        Map<String, Object> map = ImportUtil.importExcel(1, 1, ShopOrderWaitShipVo.class, importVerifyHandler, multipartFile, true);
+        List<ShopOrderWaitShipVo> importList = (List<ShopOrderWaitShipVo>) map.get("success");
+        // 创建 Future 集合,用来存储 Future 实例
+        List<Future<ShopOrderWaitShipVo>> futureList = new ArrayList<>();
+        if (!CollectionUtils.isEmpty(importList)) {
+            if (importList.size() > 0) {
+                importList.forEach(importRow -> {
+                    if (StringUtils.isNotEmpty(importRow.getLogisticCode())) {
+                        //批量导入数据库
+                        Future<ShopOrderWaitShipVo> future = executor.submit(new Callable<ShopOrderWaitShipVo>() {
+                            @Override
+                            public ShopOrderWaitShipVo call() throws Exception {
+                                if (StringUtils.isEmpty(importRow.getLogisticCode())) {
+                                    importRow.setErrorMsg("运单号没有填");
+                                    return importRow;
+                                }
+                                try {
+                                    ShopOrderPackage shopOrderPackage = shopOrderPackageService.expressShipForImport(businessId, importRow);
+                                    try
+                                    {
+                                        // 发送自动收货消息
+                                        shopOrderMqProductService.orderPackageReceivingMqProductSend(shopOrderPackage.getPackageId());
+                                        // 发送物流消息
+                                        sendPrivateMessageMsgService.send(new MessageBo(MessageType.LOGISTICS_MESSAGE,
+                                            ModelType.LOGISTICS, shopOrderPackage.getPackageId()));
+                                    }
+                                    catch (Exception e)
+                                    {
+                                        log.error("MQ发送自动收货消息失败", e);
+                                    }
+                                } catch (Exception ex) {
+                                    importRow.setErrorMsg(ex.getMessage());
+                                    return importRow;
+                                }
+                                return null;
+                            }
+                        });
+                        futureList.add(future);
+                    }
+                });
+                List<ShopOrderWaitShipVo> resultList = new ArrayList<>();
+                for (Future<ShopOrderWaitShipVo> future : futureList) {
+                    // 获取每一个线程的返回结果,如果该线程未完成,会阻塞
+                    ShopOrderWaitShipVo vo = future.get(30, TimeUnit.SECONDS);
+                    if (vo != null) {
+                        resultList.add(vo);
+                    }
+                }
+                StringBuffer sbf = new StringBuffer();
+                resultList.forEach(e ->
+                {
+                    sbf.append("第" + (e.getRowNum() + 1) + "行存在错误:" + e.getErrorMsg()+"");
+                });
+                if (StringUtil.isNotEmpty(sbf.toString())) {
+                    throw new ServiceException(sbf.toString());
+                }
+            }
+        }
+        return R.ok();
+    }
+
     /**
      * 总店导出连锁店订单列表
      */

+ 2 - 0
ruoyi-base/src/main/java/com/ruoyi/base/expressCompany/service/IExpressCompanyService.java

@@ -75,4 +75,6 @@ public interface IExpressCompanyService {
     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
 
     ExpressCompanyVo queryByExpressCompany(String expressCompany);
+
+    ExpressCompany loadByName(String expressName);
 }

+ 5 - 0
ruoyi-base/src/main/java/com/ruoyi/base/expressCompany/service/impl/ExpressCompanyServiceImpl.java

@@ -173,4 +173,9 @@ public class ExpressCompanyServiceImpl implements IExpressCompanyService {
         return this.baseMapper.selectVoOne(Wrappers.<ExpressCompany>lambdaQuery().eq(ExpressCompany::getCompanyName, expressCompany).last("limit 1"));
     }
 
+    @Override
+    public ExpressCompany loadByName(String expressName) {
+        return this.baseMapper.selectOne(Wrappers.<ExpressCompany>lambdaQuery().eq(ExpressCompany::getCompanyName, expressName));
+    }
+
 }

+ 44 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/importverify/BaseImportDto.java

@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2016-2019 人人开源 All rights reserved.
+ * <p>
+ * https://www.renren.io
+ * <p>
+ * 版权所有,侵权必究!
+ */
+
+package com.ruoyi.common.utils.importverify;
+
+import cn.afterturn.easypoi.handler.inter.IExcelDataModel;
+import cn.afterturn.easypoi.handler.inter.IExcelModel;
+import lombok.Data;
+
+
+/**
+ * 系统日志
+ *
+ * @author Mark sunlightcs@gmail.com
+ */
+@Data
+public class BaseImportDto implements IExcelDataModel, IExcelModel {
+
+
+    @Override
+    public Integer getRowNum() {
+        return null;
+    }
+
+    @Override
+    public void setRowNum(Integer rowNum) {
+
+    }
+
+    @Override
+    public String getErrorMsg() {
+        return null;
+    }
+
+    @Override
+    public void setErrorMsg(String errorMsg) {
+
+    }
+}

+ 45 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/importverify/ImportVerifyHandler.java

@@ -0,0 +1,45 @@
+package com.ruoyi.common.utils.importverify;
+
+import cn.afterturn.easypoi.excel.entity.result.ExcelVerifyHandlerResult;
+import cn.afterturn.easypoi.handler.inter.IExcelVerifyHandler;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringJoiner;
+
+@Component
+public class ImportVerifyHandler implements IExcelVerifyHandler<BaseImportDto> {
+
+    private final ThreadLocal<List<BaseImportDto>> threadLocal = new ThreadLocal<>();
+
+    @Override
+    public ExcelVerifyHandlerResult verifyHandler(BaseImportDto inputEntity) {
+        StringJoiner joiner = new StringJoiner(",");
+
+        List<BaseImportDto> threadLocalVal = threadLocal.get();
+        if (threadLocalVal == null) {
+            threadLocalVal = new ArrayList<>();
+        }
+
+        for (BaseImportDto dto:threadLocalVal) {
+            if (dto.equals(inputEntity)) {
+                int lineNumber = dto.getRowNum() + 1;
+                joiner.add("数据与第" + lineNumber + "行重复");
+                break;
+            }
+        }
+
+        // 添加本行数据对象到ThreadLocal中
+        threadLocalVal.add(inputEntity);
+        threadLocal.set(threadLocalVal);
+        if (joiner.length() != 0) {
+            return new ExcelVerifyHandlerResult(false, joiner.toString());
+        }
+        return new ExcelVerifyHandlerResult(true);
+    }
+
+    public ThreadLocal<List<BaseImportDto>> getThreadLocal() {
+        return threadLocal;
+    }
+}

+ 26 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadConfig.java

@@ -0,0 +1,26 @@
+package com.ruoyi.framework.config.properties;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 线程池
+ */
+@Configuration
+public class ThreadConfig {
+    @Bean
+    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolProperties poolProperties) {
+        return new ThreadPoolExecutor(poolProperties.getCorePoolSize(),
+                poolProperties.getMaxPoolSize(),
+                poolProperties.getKeepAliveSeconds(),
+                TimeUnit.SECONDS,
+                new LinkedBlockingDeque<>(poolProperties.getQueueCapacity()),
+                Executors.defaultThreadFactory(),
+                new ThreadPoolExecutor.AbortPolicy());
+    }
+}

+ 6 - 21
ruoyi-shop/src/main/java/com/ruoyi/shop/order/domain/vo/ShopOrderWaitShipVo.java

@@ -1,36 +1,21 @@
 package com.ruoyi.shop.order.domain.vo;
 
 import cn.afterturn.easypoi.excel.annotation.Excel;
-import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
-import cn.afterturn.easypoi.excel.annotation.ExcelEntity;
 import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
-import cn.hutool.core.collection.CollectionUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.extra.spring.SpringUtil;
+import cn.afterturn.easypoi.handler.inter.IExcelDataModel;
+import cn.afterturn.easypoi.handler.inter.IExcelModel;
 import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
 import com.alibaba.excel.annotation.ExcelProperty;
-import com.ruoyi.business.domain.vo.BusinessVo;
-import com.ruoyi.business.service.IBusinessService;
 import com.ruoyi.common.annotation.ExcelDictFormat;
-import com.ruoyi.common.convert.ExcelBooleanConvert;
 import com.ruoyi.common.convert.ExcelDateTimeConvert;
 import com.ruoyi.common.convert.ExcelEnumConvert;
-import com.ruoyi.common.core.domain.BaseVo;
-import com.ruoyi.common.core.validate.AddGroup;
-import com.ruoyi.common.core.validate.EditGroup;
-import com.ruoyi.common.enums.CallInterfaceStatus;
-import com.ruoyi.common.enums.order.MarketingType;
-import com.ruoyi.common.enums.order.OrderType;
-import com.ruoyi.common.filepathsplicing.FilePathValue;
-import com.ruoyi.shop.order.domain.ShopOrderDetail;
-import com.ruoyi.shop.order.enums.*;
-import com.ruoyi.shop.order.service.*;
+import com.ruoyi.common.utils.importverify.BaseImportDto;
+import com.ruoyi.shop.order.enums.PaymentStatus;
+import com.ruoyi.shop.order.enums.SellerMark;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
-import javax.validation.constraints.NotBlank;
-import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
@@ -46,7 +31,7 @@ import java.util.List;
 @ApiModel("代发货视图对象")
 @ExcelTarget("ShopOrderWaitShipVo")
 @ExcelIgnoreUnannotated
-public class ShopOrderWaitShipVo implements Serializable {
+public class ShopOrderWaitShipVo extends BaseImportDto implements IExcelDataModel, IExcelModel {
 
     private static final long serialVersionUID = 1L;
 

+ 5 - 4
ruoyi-shop/src/main/java/com/ruoyi/shop/order/service/IShopOrderPackageService.java

@@ -1,16 +1,15 @@
 package com.ruoyi.shop.order.service;
 
 import com.alibaba.fastjson.JSONObject;
-import com.google.gson.JsonObject;
+import com.ruoyi.common.core.domain.PageQuery;
+import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.shop.order.domain.ShopOrder;
 import com.ruoyi.shop.order.domain.ShopOrderPackage;
 import com.ruoyi.shop.order.domain.bo.*;
 import com.ruoyi.shop.order.domain.vo.ShopOrderPackageVo;
-import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.shop.order.domain.vo.ShopOrderVo;
+import com.ruoyi.shop.order.domain.vo.ShopOrderWaitShipVo;
 
-import javax.validation.constraints.NotNull;
 import java.util.Collection;
 import java.util.List;
 
@@ -184,4 +183,6 @@ public interface IShopOrderPackageService {
      * @return 订单的发货包裹
      */
     Long businessSimpleCount(BusinessCountBo today);
+
+    ShopOrderPackage expressShipForImport(Long businessId, ShopOrderWaitShipVo importRow);
 }

+ 2 - 0
ruoyi-shop/src/main/java/com/ruoyi/shop/order/service/IShopOrderService.java

@@ -238,4 +238,6 @@ public interface IShopOrderService {
      * @return 订单集合
      */
     List<ShopOrderWaitShipVo> businessWaitExport(ShopOrderBo bo);
+
+    ShopOrder loadByBusinessIdAndOrderNo(Long businessId, String orderNo, boolean tw);
 }

+ 17 - 1
ruoyi-shop/src/main/java/com/ruoyi/shop/order/service/impl/ShopOrderPackageServiceImpl.java

@@ -9,6 +9,8 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.base.expressCompany.domain.ExpressCompany;
+import com.ruoyi.base.expressCompany.service.IExpressCompanyService;
 import com.ruoyi.business.domain.vo.BusinessLogisticsConfigVo;
 import com.ruoyi.business.domain.vo.BusinessVerifierVo;
 import com.ruoyi.business.service.IBusinessLogisticsConfigService;
@@ -31,6 +33,7 @@ import com.ruoyi.shop.order.domain.bo.*;
 import com.ruoyi.shop.order.domain.vo.ShopOrderAddressVo;
 import com.ruoyi.shop.order.domain.vo.ShopOrderPackageVo;
 import com.ruoyi.shop.order.domain.vo.ShopOrderVo;
+import com.ruoyi.shop.order.domain.vo.ShopOrderWaitShipVo;
 import com.ruoyi.shop.order.enums.*;
 import com.ruoyi.shop.order.exception.ShopOrderExceptionEnum;
 import com.ruoyi.shop.order.exception.ShopOrderPackageExceptionEnum;
@@ -77,7 +80,7 @@ public class ShopOrderPackageServiceImpl implements IShopOrderPackageService {
     private final IUserService iUserService;
     private final ISysUserService sysUserService;
     private final ISaleRightsOrderService saleRightsOrderService;
-
+    private final IExpressCompanyService expressCompanyService;
     private final KD100Util kd100Util;
 
     @Lazy
@@ -785,4 +788,17 @@ public class ShopOrderPackageServiceImpl implements IShopOrderPackageService {
 
         );
     }
+
+    @Override
+    public ShopOrderPackage expressShipForImport(Long businessId, ShopOrderWaitShipVo importRow) {
+        ShopOrder order = shopOrderService.loadByBusinessIdAndOrderNo(businessId, importRow.getOrderNo(), true);
+        ShopShipExpressBo expressBo = new ShopShipExpressBo();
+        expressBo.setOrderId(order.getOrderId());
+        ExpressCompany expressCompany = expressCompanyService.loadByName(importRow.getExpressName());
+        expressBo.setExpressCode(ObjectUtil.isNull(expressCompany) ? "无" : expressCompany.getCompanyCode());
+        expressBo.setExpressName(ObjectUtil.isNull(expressCompany) ? "无" : expressCompany.getCompanyName());
+        expressBo.setLogisticCode(importRow.getLogisticCode());
+        expressBo.setAll(true);
+        return ship(expressBo);
+    }
 }

+ 23 - 9
ruoyi-shop/src/main/java/com/ruoyi/shop/order/service/impl/ShopOrderServiceImpl.java

@@ -10,23 +10,22 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.base.revenue.domain.vo.RevenueSharingConfigVo;
 import com.ruoyi.base.revenue.service.IRevenueSharingConfigService;
 import com.ruoyi.business.domain.Business;
+import com.ruoyi.business.domain.vo.BusinessLogisticsConfigVo;
+import com.ruoyi.business.service.IBusinessLogisticsConfigService;
 import com.ruoyi.business.service.IBusinessService;
 import com.ruoyi.businessDayBill.domain.bo.BusinessDayBillChangeBo;
 import com.ruoyi.businessDayBill.enums.BusinessDayBillChangeType;
 import com.ruoyi.businessDayBill.service.IBusinessDayBillService;
-import com.ruoyi.common.enums.CallInterfaceStatus;
-import com.ruoyi.common.enums.order.OrderType;
-import com.ruoyi.common.utils.MathUtils;
-import com.ruoyi.fubeiPay.domain.PayBo;
-import com.ruoyi.fubeiPay.service.FubeiPayService;
-import com.ruoyi.shop.order.domain.bo.BusinessCountBo;
-import com.ruoyi.business.domain.vo.BusinessLogisticsConfigVo;
-import com.ruoyi.business.service.IBusinessLogisticsConfigService;
 import com.ruoyi.common.core.domain.PageQuery;
 import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.CallInterfaceStatus;
+import com.ruoyi.common.enums.order.OrderType;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.BeanCopyUtils;
+import com.ruoyi.common.utils.MathUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.fubeiPay.domain.PayBo;
+import com.ruoyi.fubeiPay.service.FubeiPayService;
 import com.ruoyi.newwxpay.pay.PayNotifyResult;
 import com.ruoyi.shop.business.domain.bo.UserBusinessChangeIntegralBo;
 import com.ruoyi.shop.business.service.IUserBusinessRoleService;
@@ -57,7 +56,10 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.math.BigDecimal;
-import java.util.*;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -600,6 +602,18 @@ public class ShopOrderServiceImpl implements IShopOrderService {
         return this.baseMapper.businessWaitExport(bo);
     }
 
+    @Override
+    public ShopOrder loadByBusinessIdAndOrderNo(Long businessId, String orderNo, boolean tw) {
+        ShopOrder order = this.baseMapper.selectOne(new LambdaQueryWrapper<ShopOrder>()
+            .eq(ShopOrder::getBusinessId, businessId)
+            .eq(ShopOrder::getOrderNo, orderNo)
+            .last("limit 1"));
+        if (tw && ObjectUtil.isNull(order)) {
+            throw new ServiceException(ShopOrderExceptionEnum.ShopOrder_IS_NOT_EXISTS);
+        }
+        return order;
+    }
+
     @Override
     public void endRefundOrderSync(Long orderDetailId, Long orderId) {
         ShopOrder shopOrder = this.loadByLockId(orderId, true);