From 3b2a3dd0ea75b4288b615436af0c1c98f32e1118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=8B=E9=81=93=E6=BA=90=E7=A0=81?= Date: Mon, 9 Jun 2025 06:36:11 +0000 Subject: [PATCH 01/11] =?UTF-8?q?fix:=20ERP=E7=BB=9F=E8=AE=A1=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=9C=A8=E5=A4=9A=E7=A7=9F=E6=88=B7=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=97=B6=E7=9A=84NullPointerException=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复ErpSaleStatisticsMapper.xml中硬编码使用getRequiredTenantId()导致的空指针异常 - 修复ErpPurchaseStatisticsMapper.xml中硬编码使用getRequiredTenantId()导致的空指针异常 - 使用条件判断getTenantId() != null来决定是否添加租户条件 - 添加单元测试验证多租户开启和关闭时的统计查询功能 - 确保向后兼容,多租户开启时正常工作,关闭时不报错 --- .../ErpPurchaseStatisticsMapper.xml | 8 +- .../statistics/ErpSaleStatisticsMapper.xml | 8 +- .../statistics/ErpStatisticsServiceTest.java | 155 ++++++++++++++++++ 3 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java diff --git a/yudao-module-erp/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml b/yudao-module-erp/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml index 699286b5da..a88fb3a88c 100644 --- a/yudao-module-erp/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml +++ b/yudao-module-erp/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml @@ -10,7 +10,9 @@ AND in_time < #{endTime} - AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()} + + AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()} + AND deleted = 0) - (SELECT IFNULL(SUM(total_price), 0) FROM erp_purchase_return @@ -18,7 +20,9 @@ AND return_time < #{endTime} - AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()} + + AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()} + AND deleted = 0) diff --git a/yudao-module-erp/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml b/yudao-module-erp/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml index 324cbd432b..3e04ee706e 100644 --- a/yudao-module-erp/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml +++ b/yudao-module-erp/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml @@ -10,7 +10,9 @@ AND out_time < #{endTime} - AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()} + + AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()} + AND deleted = 0) - (SELECT IFNULL(SUM(total_price), 0) FROM erp_sale_return @@ -18,7 +20,9 @@ AND return_time < #{endTime} - AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()} + + AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()} + AND deleted = 0) diff --git a/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java b/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java new file mode 100644 index 0000000000..c96f2d35fa --- /dev/null +++ b/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java @@ -0,0 +1,155 @@ +package cn.iocoder.yudao.module.erp.service.statistics; + +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpPurchaseStatisticsMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpSaleStatisticsMapper; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; + +import jakarta.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +/** + * ERP 统计服务测试类 + * 主要测试在多租户关闭情况下,统计查询是否能正常工作 + * + * @author 芋道源码 + */ +@SpringBootTest +@ActiveProfiles("unit-test") +public class ErpStatisticsServiceTest { + + @Resource + private ErpSaleStatisticsService saleStatisticsService; + + @Resource + private ErpPurchaseStatisticsService purchaseStatisticsService; + + @MockBean + private ErpSaleStatisticsMapper saleStatisticsMapper; + + @MockBean + private ErpPurchaseStatisticsMapper purchaseStatisticsMapper; + + @BeforeEach + void setUp() { + // 清理租户上下文 + TenantContextHolder.clear(); + } + + @AfterEach + void tearDown() { + // 清理租户上下文 + TenantContextHolder.clear(); + } + + @Test + void testSaleStatisticsWithoutTenant() { + // 准备参数 + LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); + BigDecimal expectedPrice = new BigDecimal("1000.00"); + + // Mock 返回值 + when(saleStatisticsMapper.getSalePrice(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(expectedPrice); + + // 测试:在没有租户ID的情况下调用销售统计 + assertDoesNotThrow(() -> { + BigDecimal result = saleStatisticsService.getSalePrice(beginTime, endTime); + assertEquals(expectedPrice, result); + }, "在多租户关闭时,销售统计查询应该能正常工作"); + } + + @Test + void testPurchaseStatisticsWithoutTenant() { + // 准备参数 + LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); + BigDecimal expectedPrice = new BigDecimal("800.00"); + + // Mock 返回值 + when(purchaseStatisticsMapper.getPurchasePrice(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(expectedPrice); + + // 测试:在没有租户ID的情况下调用采购统计 + assertDoesNotThrow(() -> { + BigDecimal result = purchaseStatisticsService.getPurchasePrice(beginTime, endTime); + assertEquals(expectedPrice, result); + }, "在多租户关闭时,采购统计查询应该能正常工作"); + } + + @Test + void testSaleStatisticsWithTenant() { + // 设置租户ID + Long tenantId = 1L; + TenantContextHolder.setTenantId(tenantId); + + // 准备参数 + LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); + BigDecimal expectedPrice = new BigDecimal("1500.00"); + + // Mock 返回值 + when(saleStatisticsMapper.getSalePrice(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(expectedPrice); + + // 测试:在有租户ID的情况下调用销售统计 + assertDoesNotThrow(() -> { + BigDecimal result = saleStatisticsService.getSalePrice(beginTime, endTime); + assertEquals(expectedPrice, result); + }, "在多租户开启时,销售统计查询应该能正常工作"); + + // 验证租户ID是否正确设置 + assertEquals(tenantId, TenantContextHolder.getTenantId()); + } + + @Test + void testPurchaseStatisticsWithTenant() { + // 设置租户ID + Long tenantId = 2L; + TenantContextHolder.setTenantId(tenantId); + + // 准备参数 + LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); + BigDecimal expectedPrice = new BigDecimal("1200.00"); + + // Mock 返回值 + when(purchaseStatisticsMapper.getPurchasePrice(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(expectedPrice); + + // 测试:在有租户ID的情况下调用采购统计 + assertDoesNotThrow(() -> { + BigDecimal result = purchaseStatisticsService.getPurchasePrice(beginTime, endTime); + assertEquals(expectedPrice, result); + }, "在多租户开启时,采购统计查询应该能正常工作"); + + // 验证租户ID是否正确设置 + assertEquals(tenantId, TenantContextHolder.getTenantId()); + } + + @Test + void testTenantContextHolderMethods() { + // 测试 getTenantId() 在没有设置租户时返回 null + assertNull(TenantContextHolder.getTenantId(), "未设置租户时应该返回 null"); + + // 设置租户ID + Long tenantId = 3L; + TenantContextHolder.setTenantId(tenantId); + assertEquals(tenantId, TenantContextHolder.getTenantId(), "设置租户后应该能正确获取"); + + // 清理租户上下文 + TenantContextHolder.clear(); + assertNull(TenantContextHolder.getTenantId(), "清理后应该返回 null"); + } +} From a5ad8bb708d708ef5e9d2a2e7bc12deb99ee924e Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 18 Jun 2025 12:45:22 +0800 Subject: [PATCH 02/11] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0MP4=E6=96=87=E4=BB=B6=E4=B9=8B=E5=90=8E=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E4=B8=8B=E8=BD=BD=E8=BF=9E=E6=8E=A5=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?MP4=E6=96=87=E4=BB=B6=E6=BA=90=E6=96=87=E4=BB=B6=E8=83=BD?= =?UTF-8?q?=E9=80=9A=E8=BF=87windows=E8=87=AA=E5=B8=A6=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E6=92=AD=E6=94=BE=E4=B8=8B=E8=BD=BD=E4=B8=8B=E6=9D=A5?= =?UTF-8?q?=E7=9A=84=E6=92=AD=E6=94=BE=E4=B8=8D=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/framework/file/core/utils/FileTypeUtils.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java index e2c607842f..9cc4175884 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.infra.framework.file.core.utils; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; -import com.alibaba.ttl.TransmittableThreadLocal; import jakarta.servlet.http.HttpServletResponse; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -86,8 +85,8 @@ public class FileTypeUtils { response.setContentType(contentType); // 针对 video 的特殊处理,解决视频地址在移动端播放的兼容性问题 if (StrUtil.containsIgnoreCase(contentType, "video")) { - response.setHeader("Content-Length", String.valueOf(content.length - 1)); - response.setHeader("Content-Range", String.valueOf(content.length - 1)); + response.setHeader("Content-Length", String.valueOf(content.length)); + response.setHeader("Content-Range", "bytes 0-" + (content.length - 1) + "/" + content.length); response.setHeader("Accept-Ranges", "bytes"); } // 输出附件 From 9fc4a4061fc9a5a32ad339338610126a85e1b785 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 18 Jun 2025 15:40:51 +0800 Subject: [PATCH 03/11] =?UTF-8?q?fix:=20=E5=88=9B=E5=BB=BA=E6=8B=BC?= =?UTF-8?q?=E5=9B=A2=E6=B4=BB=E5=8A=A8=E6=97=B6=E6=A0=A1=E9=AA=8C=E5=95=86?= =?UTF-8?q?=E5=93=81=E6=98=AF=E5=90=A6=E5=8F=82=E4=B8=8E=E4=BA=86=E5=85=B6?= =?UTF-8?q?=E5=AE=83=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/combination/CombinationActivityServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java index 8e168f4f9f..f5b38a13cc 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java @@ -86,7 +86,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); } // 查找是否有其它活动,选择了该产品 - List matchActivityList = filterList(activityList, activity -> ObjectUtil.equal(activity.getId(), spuId)); + List matchActivityList = filterList(activityList, activity -> ObjectUtil.equal(activity.getSpuId(), spuId)); if (CollUtil.isNotEmpty(matchActivityList)) { throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS); } From cac82a13a7db455751159901c666a77d74feb171 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 18 Jun 2025 17:23:59 +0800 Subject: [PATCH 04/11] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8B=BC?= =?UTF-8?q?=E5=9B=A2=E8=BF=98=E6=B2=A1=E6=88=90=E5=9B=A2=EF=BC=8C=E8=99=9A?= =?UTF-8?q?=E6=8B=9F=E6=88=90=E5=9B=A2=E6=98=AF=E5=90=A6=EF=BC=8C=E8=BF=99?= =?UTF-8?q?=E4=B8=AA=E6=97=B6=E5=80=99=E6=A0=B8=E9=94=80=E4=B9=9F=E8=83=BD?= =?UTF-8?q?=E6=A0=B8=E9=94=80=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/trade/enums/ErrorCodeConstants.java | 3 ++- .../service/order/TradeOrderUpdateServiceImpl.java | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index b2d72e4b01..8ec1159244 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -39,7 +39,8 @@ public interface ErrorCodeConstants { ErrorCode ORDER_UPDATE_PAID_ORDER_REFUNDED_FAIL_REFUND_NOT_FOUND = new ErrorCode(1_011_000_034, "交易订单更新支付订单退款状态失败,原因:退款单不存在"); ErrorCode ORDER_UPDATE_PAID_ORDER_REFUNDED_FAIL_REFUND_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_035, "交易订单更新支付订单退款状态失败,原因:退款单状态不是【退款成功】"); ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_036, "交易订单自提失败,原因:你没有核销该门店订单的权限"); - ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_037, "交易订单创建失败,原因:用户积分不足"); + ErrorCode ORDER_PICK_UP_FAIL_COMBINATION_NOT_SUCCESS = new ErrorCode(1_011_000_037, "交易订单自提失败,原因:商品拼团记录不是【成功】状态"); + ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_038, "交易订单创建失败,原因:用户积分不足"); // ========== After Sale 模块 1-011-000-100 ========== ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在"); diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 8dcc0ad75e..bafe56c5be 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -25,6 +25,9 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; +import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.system.api.social.SocialClientApi; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; @@ -121,6 +124,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { public SocialClientApi socialClientApi; @Resource public PayRefundApi payRefundApi; + @Resource + private CombinationRecordApi combinationRecordApi; @Resource private TradeOrderProperties tradeOrderProperties; @@ -775,6 +780,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (ObjUtil.notEqual(DeliveryTypeEnum.PICK_UP.getType(), order.getDeliveryType())) { throw exception(ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP); } + // 情况一:如果是拼团订单,则校验拼团是否成功 + if (TradeOrderTypeEnum.isCombination(order.getType())) { + CombinationRecordRespDTO combinationRecord = combinationRecordApi.getCombinationRecordByOrderId( + order.getUserId(), order.getId()); + if (!CombinationRecordStatusEnum.isSuccess(combinationRecord.getStatus())) { + throw exception(ORDER_PICK_UP_FAIL_COMBINATION_NOT_SUCCESS); + } + } DeliveryPickUpStoreDO deliveryPickUpStore = pickUpStoreService.getDeliveryPickUpStore(order.getPickUpStoreId()); if (deliveryPickUpStore == null || !CollUtil.contains(deliveryPickUpStore.getVerifyUserIds(), userId)) { From a6901845248a56c65b2a01d43110cbde8dc45a7f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 6 Jul 2025 16:19:45 +0800 Subject: [PATCH 05/11] =?UTF-8?q?feat=EF=BC=9A=E3=80=90ERP=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E3=80=91=E6=B8=85=E7=90=86=E5=A4=9A=E4=BD=99=E7=9A=84?= =?UTF-8?q?=20ErpStatisticsServiceTest=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/ErpStatisticsServiceTest.java | 155 ------------------ 1 file changed, 155 deletions(-) delete mode 100644 yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java diff --git a/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java b/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java deleted file mode 100644 index c96f2d35fa..0000000000 --- a/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java +++ /dev/null @@ -1,155 +0,0 @@ -package cn.iocoder.yudao.module.erp.service.statistics; - -import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; -import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpPurchaseStatisticsMapper; -import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpSaleStatisticsMapper; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ActiveProfiles; - -import jakarta.annotation.Resource; -import java.math.BigDecimal; -import java.time.LocalDateTime; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -/** - * ERP 统计服务测试类 - * 主要测试在多租户关闭情况下,统计查询是否能正常工作 - * - * @author 芋道源码 - */ -@SpringBootTest -@ActiveProfiles("unit-test") -public class ErpStatisticsServiceTest { - - @Resource - private ErpSaleStatisticsService saleStatisticsService; - - @Resource - private ErpPurchaseStatisticsService purchaseStatisticsService; - - @MockBean - private ErpSaleStatisticsMapper saleStatisticsMapper; - - @MockBean - private ErpPurchaseStatisticsMapper purchaseStatisticsMapper; - - @BeforeEach - void setUp() { - // 清理租户上下文 - TenantContextHolder.clear(); - } - - @AfterEach - void tearDown() { - // 清理租户上下文 - TenantContextHolder.clear(); - } - - @Test - void testSaleStatisticsWithoutTenant() { - // 准备参数 - LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); - LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); - BigDecimal expectedPrice = new BigDecimal("1000.00"); - - // Mock 返回值 - when(saleStatisticsMapper.getSalePrice(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(expectedPrice); - - // 测试:在没有租户ID的情况下调用销售统计 - assertDoesNotThrow(() -> { - BigDecimal result = saleStatisticsService.getSalePrice(beginTime, endTime); - assertEquals(expectedPrice, result); - }, "在多租户关闭时,销售统计查询应该能正常工作"); - } - - @Test - void testPurchaseStatisticsWithoutTenant() { - // 准备参数 - LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); - LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); - BigDecimal expectedPrice = new BigDecimal("800.00"); - - // Mock 返回值 - when(purchaseStatisticsMapper.getPurchasePrice(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(expectedPrice); - - // 测试:在没有租户ID的情况下调用采购统计 - assertDoesNotThrow(() -> { - BigDecimal result = purchaseStatisticsService.getPurchasePrice(beginTime, endTime); - assertEquals(expectedPrice, result); - }, "在多租户关闭时,采购统计查询应该能正常工作"); - } - - @Test - void testSaleStatisticsWithTenant() { - // 设置租户ID - Long tenantId = 1L; - TenantContextHolder.setTenantId(tenantId); - - // 准备参数 - LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); - LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); - BigDecimal expectedPrice = new BigDecimal("1500.00"); - - // Mock 返回值 - when(saleStatisticsMapper.getSalePrice(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(expectedPrice); - - // 测试:在有租户ID的情况下调用销售统计 - assertDoesNotThrow(() -> { - BigDecimal result = saleStatisticsService.getSalePrice(beginTime, endTime); - assertEquals(expectedPrice, result); - }, "在多租户开启时,销售统计查询应该能正常工作"); - - // 验证租户ID是否正确设置 - assertEquals(tenantId, TenantContextHolder.getTenantId()); - } - - @Test - void testPurchaseStatisticsWithTenant() { - // 设置租户ID - Long tenantId = 2L; - TenantContextHolder.setTenantId(tenantId); - - // 准备参数 - LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); - LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); - BigDecimal expectedPrice = new BigDecimal("1200.00"); - - // Mock 返回值 - when(purchaseStatisticsMapper.getPurchasePrice(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(expectedPrice); - - // 测试:在有租户ID的情况下调用采购统计 - assertDoesNotThrow(() -> { - BigDecimal result = purchaseStatisticsService.getPurchasePrice(beginTime, endTime); - assertEquals(expectedPrice, result); - }, "在多租户开启时,采购统计查询应该能正常工作"); - - // 验证租户ID是否正确设置 - assertEquals(tenantId, TenantContextHolder.getTenantId()); - } - - @Test - void testTenantContextHolderMethods() { - // 测试 getTenantId() 在没有设置租户时返回 null - assertNull(TenantContextHolder.getTenantId(), "未设置租户时应该返回 null"); - - // 设置租户ID - Long tenantId = 3L; - TenantContextHolder.setTenantId(tenantId); - assertEquals(tenantId, TenantContextHolder.getTenantId(), "设置租户后应该能正确获取"); - - // 清理租户上下文 - TenantContextHolder.clear(); - assertNull(TenantContextHolder.getTenantId(), "清理后应该返回 null"); - } -} From eca9307344e235e506b53eddae12c3fdabeb224c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 6 Jul 2025 16:38:14 +0800 Subject: [PATCH 06/11] =?UTF-8?q?fix=EF=BC=9A=E3=80=90MALL=20=E5=95=86?= =?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BF=AE=E5=A4=8D=E9=80=80=E6=AC=BE=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E4=B8=AD=20merchantRefundId=20=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E8=BD=AC=E6=8D=A2=20Long=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/aftersale/AfterSaleController.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java index d2165cb868..2bc654b290 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java @@ -141,9 +141,8 @@ public class AfterSaleController { public CommonResult updateAfterSaleRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) { log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO); if (StrUtil.startWithAny(notifyReqDTO.getMerchantRefundId(), "order-")) { - tradeOrderUpdateService.updatePaidOrderRefunded( - Long.parseLong(notifyReqDTO.getMerchantRefundId()), - notifyReqDTO.getPayRefundId()); + Long orderId = Long.parseLong(StrUtil.subAfter(notifyReqDTO.getMerchantRefundId(), "order-", true)); + tradeOrderUpdateService.updatePaidOrderRefunded(orderId, notifyReqDTO.getPayRefundId()); } else { afterSaleService.updateAfterSaleRefunded( Long.parseLong(notifyReqDTO.getMerchantRefundId()), From d8e1610495fb3dfc66c1d368d4e26af952e8d37f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 8 Jul 2025 09:39:44 +0800 Subject: [PATCH 07/11] feat: enhance MyBatis utility for sorting and update SQL aliases in TradeOrderStatisticsMapper --- .../mybatis/core/mapper/BaseMapperX.java | 1 + .../mybatis/core/util/MyBatisUtils.java | 27 ++++++++++++++----- .../trade/TradeOrderStatisticsMapper.xml | 8 +++--- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index d7ad5fad8f..52ca947cc5 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -42,6 +42,7 @@ public interface BaseMapperX extends MPJBaseMapper { default PageResult selectPage(PageParam pageParam, Collection sortingFields, @Param("ew") Wrapper queryWrapper) { // 特殊:不分页,直接查询全部 if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) { + MyBatisUtils.addOrder(queryWrapper, sortingFields); List list = selectList(queryWrapper); return new PageResult<>(list, (long) list.size()); } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java index 784f699e44..ac33ba8eff 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.mybatis.core.util; -import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.func.Func1; import cn.hutool.core.lang.func.LambdaUtil; import cn.hutool.core.util.StrUtil; @@ -8,6 +8,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.SortingField; import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum; import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; @@ -20,7 +22,6 @@ import net.sf.jsqlparser.schema.Table; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; /** * MyBatis 工具类 @@ -37,15 +38,27 @@ public class MyBatisUtils { // 页码 + 数量 Page page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize()); // 排序字段 - if (!CollectionUtil.isEmpty(sortingFields)) { - page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) - ? OrderItem.asc(StrUtil.toUnderlineCase(sortingField.getField())) - : OrderItem.desc(StrUtil.toUnderlineCase(sortingField.getField()))) - .collect(Collectors.toList())); + if (CollUtil.isNotEmpty(sortingFields)) { + for (SortingField sortingField : sortingFields) { + page.addOrder(new OrderItem().setAsc(SortingField.ORDER_ASC.equals(sortingField.getOrder())) + .setColumn(StrUtil.toUnderlineCase(sortingField.getField()))); + } } return page; } + public static void addOrder(Wrapper wrapper, Collection sortingFields) { + if (CollUtil.isEmpty(sortingFields)) { + return; + } + QueryWrapper query = (QueryWrapper) wrapper; + for (SortingField sortingField : sortingFields) { + query.orderBy(true, + SortingField.ORDER_ASC.equals(sortingField.getOrder()), + StrUtil.toUnderlineCase(sortingField.getField())); + } + } + /** * 将拦截器添加到链中 * 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置 diff --git a/yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml index 07d2f0d580..e47c85e9b4 100644 --- a/yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml @@ -76,8 +76,8 @@ - SELECT IFNULL(SUM(pay_price), 0) AS orderPayPrice, - COUNT(1) AS orderPayCount + SELECT IFNULL(SUM(pay_price), 0) AS order_pay_price, + COUNT(1) AS order_pay_count FROM trade_order WHERE pay_status = #{payStatus} AND pay_time BETWEEN #{beginTime} AND #{endTime} From 563985dcfc9e68ddc208f72c811ff0b2ced83cf2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 9 Jul 2025 19:17:50 +0800 Subject: [PATCH 08/11] =?UTF-8?q?feat=EF=BC=9A=E3=80=90MP=20=E5=85=AC?= =?UTF-8?q?=E4=BC=97=E5=8F=B7=E3=80=91=E5=85=BC=E5=AE=B9=E6=97=A0=20API=20?= =?UTF-8?q?=E6=9D=83=E9=99=90=E7=9A=84=E4=B8=AA=E4=BA=BA=E5=85=AC=E4=BC=97?= =?UTF-8?q?=E5=8F=B7=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mp/service/handler/user/SubscribeHandler.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java b/yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java index 14540836a7..0f68baf39e 100644 --- a/yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java +++ b/yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.mp.service.handler.user; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder; import cn.iocoder.yudao.module.mp.service.message.MpAutoReplyService; import cn.iocoder.yudao.module.mp.service.user.MpUserService; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.error.WxMpErrorMsgEnum; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.mp.api.WxMpMessageHandler; import me.chanjar.weixin.mp.api.WxMpService; @@ -13,7 +16,6 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.result.WxMpUser; import org.springframework.stereotype.Component; -import jakarta.annotation.Resource; import java.util.Map; /** @@ -40,6 +42,13 @@ public class SubscribeHandler implements WxMpMessageHandler { wxMpUser = weixinService.getUserService().userInfo(wxMessage.getFromUser()); } catch (WxErrorException e) { log.error("[handle][粉丝({})] 获取粉丝信息失败!", wxMessage.getFromUser(), e); + // 特殊情况(个人账号,无接口权限):https://t.zsxq.com/cLFq5 + if (ObjUtil.equal(e.getError().getErrorCode(), WxMpErrorMsgEnum.CODE_48001)) { + wxMpUser = new WxMpUser(); + wxMpUser.setOpenId(wxMessage.getFromUser()); + wxMpUser.setSubscribe(true); + wxMpUser.setSubscribeTime(System.currentTimeMillis() / 1000L); + } } // 第二步,保存粉丝信息 From 7fc522938d1eadd09ea1a0c43413b47b92a523b7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 9 Jul 2025 19:27:07 +0800 Subject: [PATCH 09/11] =?UTF-8?q?fix=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91=E7=A4=BE=E4=BA=A4=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=EF=BC=8C=E4=BD=BF=E7=94=A8=20code=20=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E7=A0=81=E7=9A=84=E5=8F=82=E6=95=B0=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/admin/socail/SocialUserController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java index 77a77daa1f..f26ca4d937 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java @@ -38,7 +38,8 @@ public class SocialUserController { @PostMapping("/bind") @Operation(summary = "社交绑定,使用 code 授权码") public CommonResult socialBind(@RequestBody @Valid SocialUserBindReqVO reqVO) { - socialUserService.bindSocialUser(BeanUtils.toBean(reqVO, SocialUserBindReqDTO.class) + socialUserService.bindSocialUser(new SocialUserBindReqDTO().setSocialType(reqVO.getType()) + .setCode(reqVO.getCode()).setState(reqVO.getState()) .setUserId(getLoginUserId()).setUserType(UserTypeEnum.ADMIN.getValue())); return CommonResult.success(true); } From bda357508a825557877b43a7d1b7ba864d659b87 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 9 Jul 2025 22:37:48 +0800 Subject: [PATCH 10/11] =?UTF-8?q?feat=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91SecurityFrameworkUtils=20?= =?UTF-8?q?=E7=9A=84=20setLoginUser=20=E6=96=B9=E6=B3=95=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=AF=B9=20request=20=E5=BC=BA=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E7=94=A8=E4=BA=8E=20Job=20=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/core/util/SecurityFrameworkUtils.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java index 98dc7afb8d..4f8024474b 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java @@ -126,8 +126,10 @@ public class SecurityFrameworkUtils { // 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号; // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息 - WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); - WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); + if (request != null) { + WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); + WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); + } } private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) { From 569ff42e6f9d2a4499ca0cfe113585e705ab59f2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 9 Jul 2025 23:24:17 +0800 Subject: [PATCH 11/11] =?UTF-8?q?feat=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91=E4=BC=98=E5=8C=96=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20SimpleAsyncTaskExecutor=20=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/YudaoAsyncAutoConfiguration.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java index 6d517e5e40..4b08210971 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java @@ -7,6 +7,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.core.task.SimpleAsyncTaskExecutor; /** * 异步任务 Configuration @@ -21,13 +22,20 @@ public class YudaoAsyncAutoConfiguration { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (!(bean instanceof ThreadPoolTaskExecutor)) { - return bean; + // 处理 ThreadPoolTaskExecutor + if (bean instanceof ThreadPoolTaskExecutor) { + ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean; + executor.setTaskDecorator(TtlRunnable::get); + return executor; } - // 修改提交的任务,接入 TransmittableThreadLocal - ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean; - executor.setTaskDecorator(TtlRunnable::get); - return executor; + // 处理 SimpleAsyncTaskExecutor + // 参考 https://t.zsxq.com/CBoks 增加 + if (bean instanceof SimpleAsyncTaskExecutor) { + SimpleAsyncTaskExecutor executor = (SimpleAsyncTaskExecutor) bean; + executor.setTaskDecorator(TtlRunnable::get); + return executor; + } + return bean; } };