From 0ce0c3f3d2c6a82550eaf14c64798c50557d3510 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 2 Sep 2024 13:15:10 +0800 Subject: [PATCH 01/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E5=B7=A5=E4=BD=9C=E6=B5=81=EF=BC=9AbpmnBytes?= =?UTF-8?q?=20=E5=9C=A8=E9=9D=9E=20UTF-8=20=E7=8E=AF=E5=A2=83=E4=B8=8B?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E8=83=BD=E5=AD=98=E5=9C=A8=E4=B9=B1=E7=A0=81?= =?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 --- .../module/bpm/convert/definition/BpmModelConvert.java | 3 ++- .../framework/flowable/core/util/BpmnModelUtils.java | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java index 3fe5cc068..ec053b8d0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/definition/BpmModelConvert.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.BpmModel import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; import org.flowable.common.engine.impl.db.SuspensionState; import org.flowable.engine.repository.Deployment; @@ -55,7 +56,7 @@ public interface BpmModelConvert { BpmModelMetaInfoRespDTO metaInfo = buildMetaInfo(model); BpmModelRespVO modelVO = buildModel0(model, metaInfo, null, null, null, null); if (ArrayUtil.isNotEmpty(bpmnBytes)) { - modelVO.setBpmnXml(new String(bpmnBytes)); + modelVO.setBpmnXml(BpmnModelUtils.getBpmnXml(bpmnBytes)); } return modelVO; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index bcf82d731..c046011b0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; import org.flowable.bpmn.converter.BpmnXMLConverter; @@ -108,7 +109,14 @@ public class BpmnModelUtils { return null; } BpmnXMLConverter converter = new BpmnXMLConverter(); - return new String(converter.convertToXML(model)); + return StrUtil.utf8Str(converter.convertToXML(model)); + } + + public static String getBpmnXml(byte[] bpmnBytes) { + if (ArrayUtil.isEmpty(bpmnBytes)) { + return null; + } + return StrUtil.utf8Str(bpmnBytes); } // ========== 遍历相关的方法 ========== From b8c653d18b0aeb325abff9cbea1d9510843ea93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E8=B6=8A?= <552369664@qq.com> Date: Tue, 3 Sep 2024 16:16:22 +0800 Subject: [PATCH 02/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E6=8B=BC=E5=9B=A2=E8=A3=85=E4=BF=AE=E9=87=8D?= =?UTF-8?q?=E6=9E=84=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CombinationActivityController.java | 45 +++++++++++++++++-- .../activity/CombinationActivityRespVO.java | 12 +++++ .../AppCombinationActivityController.java | 38 ++++++++++++++++ 3 files changed, 92 insertions(+), 3 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java index 9ba319463..9dbe45503 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java @@ -16,19 +16,21 @@ import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordSe import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; import static cn.hutool.core.collection.CollectionUtil.newArrayList; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @Tag(name = "管理后台 - 拼团活动") @RestController @@ -87,6 +89,43 @@ public class CombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convert(activity, products)); } + @GetMapping("/list") + @Operation(summary = "获得拼团活动详情列表") + @Parameter(name = "combinationActivityIds", description = "拼团活动编号列表", required = true, example = "[1,2,3]") + @PreAuthorize("@ss.hasPermission('product:spu:query')") + public CommonResult> getCombinationActivityDetailList(@RequestParam("combinationActivityIds") Collection combinationActivityIds) { + // 查询拼团活动列表 + List activities = combinationActivityService.getCombinationActivityListByIds(combinationActivityIds); + + // 转换活动列表 + List activityVOs = CombinationActivityConvert.INSTANCE.convertList(activities); + + // 获取商品SPU列表和拼团产品列表 + Set spuIds = activities.stream().map(CombinationActivityDO::getSpuId).collect(Collectors.toSet()); + List spuList = productSpuApi.getSpuList(spuIds); + + Set activityIds = activities.stream().map(CombinationActivityDO::getId).collect(Collectors.toSet()); + List productList = combinationActivityService.getCombinationProductListByActivityIds(activityIds); + + // 创建SPU和产品的映射 + Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); + Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); + + // 更新VO列表 + activityVOs.forEach(vo -> { + ProductSpuRespDTO spu = spuMap.get(vo.getSpuId()); + if (spu != null) { + vo.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()) + .setMarketPrice(spu.getMarketPrice()); + } + vo.setProducts(CombinationActivityConvert.INSTANCE.convertList2(productMap.get(vo.getId()))); + }); + + return success(activityVOs); + } + + @GetMapping("/page") @Operation(summary = "获得拼团活动分页") @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java index 0ac77c559..e4880970e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java @@ -27,4 +27,16 @@ public class CombinationActivityRespVO extends CombinationActivityBaseVO { @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) private List products; + // ========== 商品字段 ========== + + @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 name 读取 + example = "618大促") + private String spuName; + @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 picUrl 读取 + example = "https://www.iocoder.cn/xx.png") + private String picUrl; + @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 marketPrice 读取 + example = "50") + private Integer marketPrice; + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java index 867c2d4b8..11a3cfd96 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java @@ -26,9 +26,13 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import jakarta.annotation.Resource; + import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; @@ -109,4 +113,38 @@ public class AppCombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convert3(activity, products)); } + @GetMapping("/get-detail-list") + @Operation(summary = "获得拼团活动明细") + @Parameter(name = "combinationActivityIds", description = "活动编号列表", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityDetailList(@RequestParam("combinationActivityIds") Collection combinationActivityIds) { + // 1. 获取活动 + List combinationActivityDOList = activityService.getCombinationActivityListByIds(combinationActivityIds); + + // 过滤掉无效的活动 + List validActivities = combinationActivityDOList.stream() + .filter(combinationActivityDO -> combinationActivityDO != null && + !ObjectUtil.equal(combinationActivityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) + .toList(); + + // 如果没有有效的活动,返回 null 或者适当的错误信息 + if (validActivities.isEmpty()) { + return success(null); // 或者 return error("没有有效的活动"); + } + + // 2. 构建结果列表 + List detailRespVOList = new ArrayList<>(); + for (CombinationActivityDO activity : validActivities) { + // 获取活动商品 + List products = activityService.getCombinationProductsByActivityId(activity.getId()); + + // 调用转换方法并添加到结果列表 + AppCombinationActivityDetailRespVO detailRespVO = CombinationActivityConvert.INSTANCE.convert3(activity, products); + detailRespVOList.add(detailRespVO); + } + + // 3. 返回转换后的结果 + return success(detailRespVOList); + } + + } From 819323d3dba064772478a35b392724e3b987f6c2 Mon Sep 17 00:00:00 2001 From: heyho Date: Wed, 4 Sep 2024 05:24:04 +0000 Subject: [PATCH 03/22] =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=AB=AF?= =?UTF-8?q?=E9=87=87=E7=94=A8=E9=93=B6=E8=A1=8C=E5=8D=A1=E6=8F=90=E7=8E=B0?= =?UTF-8?q?=EF=BC=8C=E6=8F=90=E4=BA=A4=E5=90=8E=E6=8A=A5=EF=BC=9A=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=8F=82=E6=95=B0bankName=E7=B1=BB=E5=9E=8B=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E3=80=82=20=E5=8E=9F=E5=9B=A0=EF=BC=9Ayudao-module-ma?= =?UTF-8?q?ll/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module?= =?UTF-8?q?/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdra?= =?UTF-8?q?wCreateReqVO.java=E4=B8=AD=E7=9A=84=E5=AD=97=E6=AE=B5=EF=BC=9Ap?= =?UTF-8?q?rivate=20Integer=20bankName=E5=AE=9E=E9=99=85=E5=BA=94=E4=B8=BA?= =?UTF-8?q?String=E5=9E=8B=EF=BC=8C=E5=9B=A0=E4=B8=BA=E6=97=A0=E8=AE=BA?= =?UTF-8?q?=E6=98=AF=E7=94=A8=E6=88=B7=E6=89=8B=E5=8A=A8=E8=BE=93=E5=85=A5?= =?UTF-8?q?=E9=93=B6=E8=A1=8C=E5=90=8D=E5=AD=97=EF=BC=8C=E6=88=96=E6=98=AF?= =?UTF-8?q?=E9=87=87=E7=94=A8=E6=9F=A5=E8=AF=A2=E5=AD=97=E5=85=B8=E8=A1=A8?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B"brokerage=5Fbank=5Fname"=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E5=AD=97=E5=85=B8=E5=80=BC"value"=EF=BC=8C=E9=83=BD=E5=BA=94?= =?UTF-8?q?=E8=AF=A5=E6=98=AFString=E5=9E=8B=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 经检查其相所有相关的DO,VO的属性bankName均为String,所以AppBrokerageWithdrawCreateReqVO的bankName改为String为宜。 Signed-off-by: heyho --- .../brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java index feb6eae89..83d473825 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java @@ -44,7 +44,7 @@ public class AppBrokerageWithdrawCreateReqVO { private String name; @Schema(description = "提现银行", example = "1") @NotNull(message = "提现银行不能为空", groups = {Bank.class}) - private Integer bankName; + private String bankName; @Schema(description = "开户地址", example = "海淀支行") private String bankAddress; From c935312bf805d74651002ce8a3009a55c9d7025d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E8=B6=8A?= <552369664@qq.com> Date: Wed, 4 Sep 2024 22:32:30 +0800 Subject: [PATCH 04/22] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/combination/AppCombinationActivityController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java index 11a3cfd96..42d6c8535 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java @@ -128,7 +128,7 @@ public class AppCombinationActivityController { // 如果没有有效的活动,返回 null 或者适当的错误信息 if (validActivities.isEmpty()) { - return success(null); // 或者 return error("没有有效的活动"); + return success(null); } // 2. 构建结果列表 From efd0a86007c3b71113383268a2aa386ace5cdb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E8=B6=8A?= <552369664@qq.com> Date: Wed, 4 Sep 2024 22:55:12 +0800 Subject: [PATCH 05/22] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/combination/CombinationActivityController.java | 8 ++++---- .../app/combination/AppCombinationActivityController.java | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java index 9dbe45503..1dba7345f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java @@ -89,13 +89,13 @@ public class CombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convert(activity, products)); } - @GetMapping("/list") + @GetMapping("/detail-list") @Operation(summary = "获得拼团活动详情列表") - @Parameter(name = "combinationActivityIds", description = "拼团活动编号列表", required = true, example = "[1,2,3]") + @Parameter(name = "ids", description = "拼团活动编号列表", required = true, example = "[1,2,3]") @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult> getCombinationActivityDetailList(@RequestParam("combinationActivityIds") Collection combinationActivityIds) { + public CommonResult> getCombinationActivityDetailList(@RequestParam("ids") Collection ids) { // 查询拼团活动列表 - List activities = combinationActivityService.getCombinationActivityListByIds(combinationActivityIds); + List activities = combinationActivityService.getCombinationActivityListByIds(ids); // 转换活动列表 List activityVOs = CombinationActivityConvert.INSTANCE.convertList(activities); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java index 42d6c8535..9ae93e263 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java @@ -113,12 +113,12 @@ public class AppCombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convert3(activity, products)); } - @GetMapping("/get-detail-list") + @GetMapping("/detail-list") @Operation(summary = "获得拼团活动明细") - @Parameter(name = "combinationActivityIds", description = "活动编号列表", required = true, example = "[1024, 1025]") - public CommonResult> getCombinationActivityDetailList(@RequestParam("combinationActivityIds") Collection combinationActivityIds) { + @Parameter(name = "ids", description = "活动编号列表", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityDetailList(@RequestParam("ids") Collection ids) { // 1. 获取活动 - List combinationActivityDOList = activityService.getCombinationActivityListByIds(combinationActivityIds); + List combinationActivityDOList = activityService.getCombinationActivityListByIds(ids); // 过滤掉无效的活动 List validActivities = combinationActivityDOList.stream() From 39a6eb4792b11df14100a65573a52bc3419c86bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E8=B6=8A?= <552369664@qq.com> Date: Thu, 5 Sep 2024 10:55:23 +0800 Subject: [PATCH 06/22] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E6=8B=BC=E5=9B=A2=E6=B4=BB=E5=8A=A8=E5=92=8C?= =?UTF-8?q?SPU=E8=AF=A6=E6=83=85=E5=88=86=E5=BC=80=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CombinationActivityController.java | 19 +++---------------- .../activity/CombinationActivityRespVO.java | 12 ------------ .../AppCombinationActivityController.java | 5 +++-- 3 files changed, 6 insertions(+), 30 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java index 1dba7345f..f166b010d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java @@ -100,32 +100,19 @@ public class CombinationActivityController { // 转换活动列表 List activityVOs = CombinationActivityConvert.INSTANCE.convertList(activities); - // 获取商品SPU列表和拼团产品列表 - Set spuIds = activities.stream().map(CombinationActivityDO::getSpuId).collect(Collectors.toSet()); - List spuList = productSpuApi.getSpuList(spuIds); - + // 获取拼团产品列表 Set activityIds = activities.stream().map(CombinationActivityDO::getId).collect(Collectors.toSet()); List productList = combinationActivityService.getCombinationProductListByActivityIds(activityIds); // 创建SPU和产品的映射 - Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); - // 更新VO列表 - activityVOs.forEach(vo -> { - ProductSpuRespDTO spu = spuMap.get(vo.getSpuId()); - if (spu != null) { - vo.setSpuName(spu.getName()) - .setPicUrl(spu.getPicUrl()) - .setMarketPrice(spu.getMarketPrice()); - } - vo.setProducts(CombinationActivityConvert.INSTANCE.convertList2(productMap.get(vo.getId()))); - }); + // 往活动VO赋值产品列表 + activityVOs.forEach(vo -> vo.setProducts(CombinationActivityConvert.INSTANCE.convertList2(productMap.get(vo.getId())))); return success(activityVOs); } - @GetMapping("/page") @Operation(summary = "获得拼团活动分页") @PreAuthorize("@ss.hasPermission('promotion:combination-activity:query')") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java index e4880970e..0ac77c559 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java @@ -27,16 +27,4 @@ public class CombinationActivityRespVO extends CombinationActivityBaseVO { @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) private List products; - // ========== 商品字段 ========== - - @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 name 读取 - example = "618大促") - private String spuName; - @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 picUrl 读取 - example = "https://www.iocoder.cn/xx.png") - private String picUrl; - @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 marketPrice 读取 - example = "50") - private Integer marketPrice; - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java index 9ae93e263..f113ab0d2 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.controller.app.combination; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -126,9 +127,9 @@ public class AppCombinationActivityController { !ObjectUtil.equal(combinationActivityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) .toList(); - // 如果没有有效的活动,返回 null 或者适当的错误信息 + // 如果没有有效的活动,返回空列表 if (validActivities.isEmpty()) { - return success(null); + return success(ListUtil.empty()); } // 2. 构建结果列表 From 73a7ccbd754fb1b77470fda682d6514a02d30b3a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 5 Sep 2024 13:56:46 +0800 Subject: [PATCH 07/22] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E6=8B=BC=E5=9B=A2=E6=B4=BB=E5=8A=A8=EF=BC=9A?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8B=BC=E5=9B=A2=E6=B4=BB=E5=8A=A8=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E7=9A=84=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CombinationActivityController.java | 44 ++++----- .../activity/CombinationActivityRespVO.java | 10 ++ .../AppCombinationActivityController.java | 95 ++++--------------- .../AppCombinationActivityRespVO.java | 11 +-- .../CombinationActivityConvert.java | 43 +++++---- .../CombinationActivityService.java | 8 -- .../CombinationActivityServiceImpl.java | 5 - 7 files changed, 75 insertions(+), 141 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java index f166b010d..2f9e7863f 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/CombinationActivityController.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.combination; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; @@ -22,15 +23,15 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import static cn.hutool.core.collection.CollectionUtil.newArrayList; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 拼团活动") @RestController @@ -89,28 +90,21 @@ public class CombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convert(activity, products)); } - @GetMapping("/detail-list") - @Operation(summary = "获得拼团活动详情列表") - @Parameter(name = "ids", description = "拼团活动编号列表", required = true, example = "[1,2,3]") - @PreAuthorize("@ss.hasPermission('product:spu:query')") - public CommonResult> getCombinationActivityDetailList(@RequestParam("ids") Collection ids) { - // 查询拼团活动列表 - List activities = combinationActivityService.getCombinationActivityListByIds(ids); - - // 转换活动列表 - List activityVOs = CombinationActivityConvert.INSTANCE.convertList(activities); - - // 获取拼团产品列表 - Set activityIds = activities.stream().map(CombinationActivityDO::getId).collect(Collectors.toSet()); - List productList = combinationActivityService.getCombinationProductListByActivityIds(activityIds); - - // 创建SPU和产品的映射 - Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); - - // 往活动VO赋值产品列表 - activityVOs.forEach(vo -> vo.setProducts(CombinationActivityConvert.INSTANCE.convertList2(productMap.get(vo.getId())))); - - return success(activityVOs); + @GetMapping("/list-by-ids") + @Operation(summary = "获得拼团活动列表,基于活动编号数组") + @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityListByIds(@RequestParam("ids") List ids) { + // 1. 获得开启的活动列表 + List activityList = combinationActivityService.getCombinationActivityListByIds(ids); + activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus())); + if (CollUtil.isEmpty(activityList)) { + return success(Collections.emptyList()); + } + // 2. 拼接返回 + List productList = combinationActivityService.getCombinationProductListByActivityIds( + convertList(activityList, CombinationActivityDO::getId)); + List spuList = productSpuApi.getSpuList(convertList(activityList, CombinationActivityDO::getSpuId)); + return success(CombinationActivityConvert.INSTANCE.convertList(activityList, productList, spuList)); } @GetMapping("/page") diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java index 0ac77c559..d65ecfe10 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/combination/vo/activity/CombinationActivityRespVO.java @@ -27,4 +27,14 @@ public class CombinationActivityRespVO extends CombinationActivityBaseVO { @Schema(description = "拼团商品", requiredMode = Schema.RequiredMode.REQUIRED) private List products; + @Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "一个白菜") + private String spuName; // 从 SPU 的 name 读取 + @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") + private String picUrl; // 从 SPU 的 picUrl 读取 + @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") + private Integer marketPrice; // 从 SPU 的 marketPrice 读取 + + @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer combinationPrice; // 从 products 获取最小 price 读取 + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java index f113ab0d2..90a9fd8d7 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.app.combination; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -15,28 +14,20 @@ import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivity import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import jakarta.annotation.Resource; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "用户 APP - 拼团活动") @@ -45,45 +36,12 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @Validated public class AppCombinationActivityController { - /** - * {@link AppCombinationActivityRespVO} 缓存,通过它异步刷新 {@link #getCombinationActivityList0(Integer)} 所要的首页数据 - */ - private final LoadingCache> combinationActivityListCache = buildAsyncReloadingCache(Duration.ofSeconds(10L), - new CacheLoader>() { - - @Override - public List load(Integer count) { - return getCombinationActivityList0(count); - } - - }); - @Resource private CombinationActivityService activityService; @Resource private ProductSpuApi spuApi; - @GetMapping("/list") - @Operation(summary = "获得拼团活动列表", description = "用于小程序首页") - @Parameter(name = "count", description = "需要展示的数量", example = "6") - public CommonResult> getCombinationActivityList( - @RequestParam(name = "count", defaultValue = "6") Integer count) { - return success(combinationActivityListCache.getUnchecked(count)); - } - - private List getCombinationActivityList0(Integer count) { - List activityList = activityService.getCombinationActivityListByCount(count); - if (CollUtil.isEmpty(activityList)) { - return Collections.emptyList(); - } - // 拼接返回 - List productList = activityService.getCombinationProductListByActivityIds( - convertList(activityList, CombinationActivityDO::getId)); - List spuList = spuApi.getSpuList(convertList(activityList, CombinationActivityDO::getSpuId)); - return CombinationActivityConvert.INSTANCE.convertAppList(activityList, productList, spuList); - } - @GetMapping("/page") @Operation(summary = "获得拼团活动分页") public CommonResult> getCombinationActivityPage(PageParam pageParam) { @@ -98,6 +56,23 @@ public class AppCombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convertAppPage(pageResult, productList, spuList)); } + @GetMapping("/list-by-ids") + @Operation(summary = "获得拼团活动列表,基于活动编号数组") + @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityListByIds(@RequestParam("ids") List ids) { + // 1. 获得开启的活动列表 + List activityList = activityService.getCombinationActivityListByIds(ids); + activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus())); + if (CollUtil.isEmpty(activityList)) { + return success(Collections.emptyList()); + } + // 2. 拼接返回 + List productList = activityService.getCombinationProductListByActivityIds( + convertList(activityList, CombinationActivityDO::getId)); + List spuList = spuApi.getSpuList(convertList(activityList, CombinationActivityDO::getSpuId)); + return success(CombinationActivityConvert.INSTANCE.convertAppList(activityList, productList, spuList)); + } + @GetMapping("/get-detail") @Operation(summary = "获得拼团活动明细") @Parameter(name = "id", description = "活动编号", required = true, example = "1024") @@ -114,38 +89,4 @@ public class AppCombinationActivityController { return success(CombinationActivityConvert.INSTANCE.convert3(activity, products)); } - @GetMapping("/detail-list") - @Operation(summary = "获得拼团活动明细") - @Parameter(name = "ids", description = "活动编号列表", required = true, example = "[1024, 1025]") - public CommonResult> getCombinationActivityDetailList(@RequestParam("ids") Collection ids) { - // 1. 获取活动 - List combinationActivityDOList = activityService.getCombinationActivityListByIds(ids); - - // 过滤掉无效的活动 - List validActivities = combinationActivityDOList.stream() - .filter(combinationActivityDO -> combinationActivityDO != null && - !ObjectUtil.equal(combinationActivityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) - .toList(); - - // 如果没有有效的活动,返回空列表 - if (validActivities.isEmpty()) { - return success(ListUtil.empty()); - } - - // 2. 构建结果列表 - List detailRespVOList = new ArrayList<>(); - for (CombinationActivityDO activity : validActivities) { - // 获取活动商品 - List products = activityService.getCombinationProductsByActivityId(activity.getId()); - - // 调用转换方法并添加到结果列表 - AppCombinationActivityDetailRespVO detailRespVO = CombinationActivityConvert.INSTANCE.convert3(activity, products); - detailRespVOList.add(detailRespVO); - } - - // 3. 返回转换后的结果 - return success(detailRespVOList); - } - - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java index 64462a377..8f933fa3e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java @@ -19,15 +19,14 @@ public class AppCombinationActivityRespVO { @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") private Long spuId; + @Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "一个白菜") + private String spuName; // 从 SPU 的 name 读取 @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096") - // 从 SPU 的 picUrl 读取 - private String picUrl; - + private String picUrl; // 从 SPU 的 picUrl 读取 @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") - // 从 SPU 的 marketPrice 读取 - private Integer marketPrice; + private Integer marketPrice; // 从 SPU 的 marketPrice 读取 @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - private Integer combinationPrice; + private Integer combinationPrice; // 从 products 获取最小 price 读取 } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java index 8acdac6ee..3ee4a8190 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; @@ -127,40 +128,42 @@ public interface CombinationActivityConvert { .setSpuName(spu.getName()).setPicUrl(sku.getPicUrl()); } - List convertAppList(List list); - - default List convertAppList(List list, - List productList, - List spuList) { - List activityList = convertAppList(list); + default List convertList(List list, + List productList, + List spuList) { + List activityList = BeanUtils.toBean(list, CombinationActivityRespVO.class); Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); return CollectionUtils.convertList(activityList, item -> { // 设置 product 信息 item.setCombinationPrice(getMinValue(productMap.get(item.getId()), CombinationProductDO::getCombinationPrice)); // 设置 SPU 信息 - findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); + findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); return item; }); } - PageResult convertAppPage(PageResult result); + default List convertAppList(List list, + List productList, + List spuList) { + List activityList = BeanUtils.toBean(list, AppCombinationActivityRespVO.class); + Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); + Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); + return CollectionUtils.convertList(activityList, item -> { + // 设置 product 信息 + item.setCombinationPrice(getMinValue(productMap.get(item.getId()), CombinationProductDO::getCombinationPrice)); + // 设置 SPU 信息 + findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); + return item; + }); + } default PageResult convertAppPage(PageResult result, List productList, List spuList) { - PageResult appPage = convertAppPage(result); - Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); - Map> productMap = convertMultiMap(productList, CombinationProductDO::getActivityId); - List list = CollectionUtils.convertList(appPage.getList(), item -> { - // 设置 product 信息 - item.setCombinationPrice(getMinValue(productMap.get(item.getId()), CombinationProductDO::getCombinationPrice)); - // 设置 SPU 信息 - findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); - return item; - }); - appPage.setList(list); - return appPage; + return new PageResult<>(convertAppList(result.getList(), productList, spuList), result.getTotal()); } AppCombinationActivityDetailRespVO convert2(CombinationActivityDO combinationActivity); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java index 8637a9607..6f9b62729 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java @@ -100,14 +100,6 @@ public interface CombinationActivityService { */ List getCombinationActivityListByIds(Collection ids); - /** - * 获取正在进行的活动分页数据 - * - * @param count 需要的数量 - * @return 拼团活动分页 - */ - List getCombinationActivityListByCount(Integer count); - /** * 获取正在进行的活动分页数据 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java index 6d51bde6c..f45a2168e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java @@ -225,11 +225,6 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic return combinationActivityMapper.selectList(CombinationActivityDO::getId, ids); } - @Override - public List getCombinationActivityListByCount(Integer count) { - return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count); - } - @Override public PageResult getCombinationActivityPage(PageParam pageParam) { return combinationActivityMapper.selectPage(pageParam, CommonStatusEnum.ENABLE.getStatus()); From 12ce87b3056718a28d2f5d9c0e5344bab6dacc8a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 6 Sep 2024 21:43:59 +0800 Subject: [PATCH 08/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E6=A1=86=E6=9E=B6=EF=BC=9A=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E5=BC=82=E6=AD=A5=E8=AE=B0=E5=BD=95=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E4=B8=A2=E5=A4=B1=20request=20=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../operatelog/core/service/LogRecordServiceImpl.java | 4 +--- .../crm/dal/mysql/receivable/CrmReceivableMapper.java | 2 +- .../yudao/module/system/api/logger/OperateLogApi.java | 11 +++++++++++ .../module/system/api/logger/OperateLogApiImpl.java | 2 -- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java index e2ed4c314..68cdf65ad 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/operatelog/core/service/LogRecordServiceImpl.java @@ -11,7 +11,6 @@ import com.mzt.logapi.service.ILogRecordService; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; import java.util.List; @@ -29,7 +28,6 @@ public class LogRecordServiceImpl implements ILogRecordService { private OperateLogApi operateLogApi; @Override - @Async public void record(LogRecord logRecord) { OperateLogCreateReqDTO reqDTO = new OperateLogCreateReqDTO(); try { @@ -42,7 +40,7 @@ public class LogRecordServiceImpl implements ILogRecordService { fillRequestFields(reqDTO); // 2. 异步记录日志 - operateLogApi.createOperateLog(reqDTO); + operateLogApi.createOperateLogAsync(reqDTO); } catch (Throwable ex) { // 由于 @Async 异步调用,这里打印下日志,更容易跟进 log.error("[record][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index 0c821c8c2..99bc09f0b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -92,7 +92,7 @@ public interface CrmReceivableMapper extends BaseMapperX { List> result = selectMaps(new QueryWrapper() .select("contract_id, SUM(price) AS total_price") .in("audit_status", CrmAuditStatusEnum.DRAFT.getStatus(), // 草稿 + 审批中 + 审批通过 - CrmAuditStatusEnum.PROCESS, CrmAuditStatusEnum.APPROVE.getStatus()) + CrmAuditStatusEnum.PROCESS.getStatus(), CrmAuditStatusEnum.APPROVE.getStatus()) .groupBy("contract_id") .in("contract_id", contractIds)); // 获得金额 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java index 2ac5343e2..43ac01d0f 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApi.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogCreateReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogPageReqDTO; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogRespDTO; import jakarta.validation.Valid; +import org.springframework.scheduling.annotation.Async; /** * 操作日志 API 接口 @@ -20,6 +21,16 @@ public interface OperateLogApi { */ void createOperateLog(@Valid OperateLogCreateReqDTO createReqDTO); + /** + * 【异步】创建操作日志 + * + * @param createReqDTO 请求 + */ + @Async + default void createOperateLogAsync(OperateLogCreateReqDTO createReqDTO) { + createOperateLog(createReqDTO); + } + /** * 获取指定模块的指定数据的操作日志分页 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java index 07f70d1cf..7be537e62 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/logger/OperateLogApiImpl.java @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.service.logger.OperateLogService; import com.fhs.core.trans.anno.TransMethodResult; import jakarta.annotation.Resource; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -26,7 +25,6 @@ public class OperateLogApiImpl implements OperateLogApi { private OperateLogService operateLogService; @Override - @Async public void createOperateLog(OperateLogCreateReqDTO createReqDTO) { operateLogService.createOperateLog(createReqDTO); } From 2f9d9723b3f5e8143a1d3570657a79bc4376b0f7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 6 Sep 2024 22:38:42 +0800 Subject: [PATCH 09/22] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E6=A1=86=E6=9E=B6=EF=BC=9A=E7=AE=80=E5=8C=96?= =?UTF-8?q?=20api=20=E8=AE=BF=E9=97=AE=E6=97=A5=E5=BF=97=E3=80=81=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=97=A5=E5=BF=97=E7=9A=84=E8=AE=B0=E5=BD=95=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/YudaoApiLogAutoConfiguration.java | 21 ++---------- .../core/filter/ApiAccessLogFilter.java | 12 +++---- .../service/ApiAccessLogFrameworkService.java | 19 ----------- .../ApiAccessLogFrameworkServiceImpl.java | 33 ------------------- .../service/ApiErrorLogFrameworkService.java | 19 ----------- .../ApiErrorLogFrameworkServiceImpl.java | 33 ------------------- .../web/config/YudaoWebAutoConfiguration.java | 12 +++---- .../core/handler/GlobalExceptionHandler.java | 13 +++----- .../infra/api/logger/ApiAccessLogApi.java | 11 +++++++ .../infra/api/logger/ApiErrorLogApi.java | 11 +++++++ 10 files changed, 40 insertions(+), 144 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java index d1f7453b6..cf76036c8 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/config/YudaoApiLogAutoConfiguration.java @@ -2,15 +2,10 @@ package cn.iocoder.yudao.framework.apilog.config; import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter; import cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor; -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkServiceImpl; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkServiceImpl; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration; import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; -import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; import jakarta.servlet.Filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -23,18 +18,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @AutoConfiguration(after = YudaoWebAutoConfiguration.class) public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer { - @Bean - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") - public ApiAccessLogFrameworkService apiAccessLogFrameworkService(ApiAccessLogApi apiAccessLogApi) { - return new ApiAccessLogFrameworkServiceImpl(apiAccessLogApi); - } - - @Bean - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") - public ApiErrorLogFrameworkService apiErrorLogFrameworkService(ApiErrorLogApi apiErrorLogApi) { - return new ApiErrorLogFrameworkServiceImpl(apiErrorLogApi); - } - /** * 创建 ApiAccessLogFilter Bean,记录 API 请求日志 */ @@ -42,8 +25,8 @@ public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer { @ConditionalOnProperty(prefix = "yudao.access-log", value = "enable", matchIfMissing = true) // 允许使用 yudao.access-log.enable=false 禁用访问日志 public FilterRegistrationBean apiAccessLogFilter(WebProperties webProperties, @Value("${spring.application.name}") String applicationName, - ApiAccessLogFrameworkService apiAccessLogFrameworkService) { - ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogFrameworkService); + ApiAccessLogApi apiAccessLogApi) { + ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogApi); return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java index 479a5fb9f..d798b7044 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java @@ -9,7 +9,6 @@ import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; import cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum; -import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -18,6 +17,7 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.config.WebProperties; import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; import com.fasterxml.jackson.databind.JsonNode; import io.swagger.v3.oas.annotations.Operation; @@ -36,7 +36,7 @@ import java.time.temporal.ChronoUnit; import java.util.Iterator; import java.util.Map; -import static cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor.*; +import static cn.iocoder.yudao.framework.apilog.core.interceptor.ApiAccessLogInterceptor.ATTRIBUTE_HANDLER_METHOD; import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; /** @@ -53,12 +53,12 @@ public class ApiAccessLogFilter extends ApiRequestFilter { private final String applicationName; - private final ApiAccessLogFrameworkService apiAccessLogFrameworkService; + private final ApiAccessLogApi apiAccessLogApi; - public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogFrameworkService apiAccessLogFrameworkService) { + public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogApi apiAccessLogApi) { super(webProperties); this.applicationName = applicationName; - this.apiAccessLogFrameworkService = apiAccessLogFrameworkService; + this.apiAccessLogApi = apiAccessLogApi; } @Override @@ -91,7 +91,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter { if (!enable) { return; } - apiAccessLogFrameworkService.createApiAccessLog(accessLog); + apiAccessLogApi.createApiAccessLogAsync(accessLog); } catch (Throwable th) { log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th); } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java deleted file mode 100644 index 2f3c78f60..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; - -/** - * API 访问日志 Framework Service 接口 - * - * @author 芋道源码 - */ -public interface ApiAccessLogFrameworkService { - - /** - * 创建 API 访问日志 - * - * @param reqDTO API 访问日志 - */ - void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO); - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java deleted file mode 100644 index 934f8141c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiAccessLogFrameworkServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import cn.iocoder.yudao.module.infra.api.logger.ApiAccessLogApi; -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; - -/** - * API 访问日志 Framework Service 实现类 - * - * 基于 {@link ApiAccessLogApi} 服务,记录访问日志 - * - * @author 芋道源码 - */ -@RequiredArgsConstructor -@Slf4j -public class ApiAccessLogFrameworkServiceImpl implements ApiAccessLogFrameworkService { - - private final ApiAccessLogApi apiAccessLogApi; - - @Override - @Async - public void createApiAccessLog(ApiAccessLogCreateReqDTO reqDTO) { - try { - apiAccessLogApi.createApiAccessLog(reqDTO); - } catch (Throwable ex) { - // 由于 @Async 异步调用,这里打印下日志,更容易跟进 - log.error("[createApiAccessLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex); - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java deleted file mode 100644 index 33bebb711..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; - -/** - * API 错误日志 Framework Service 接口 - * - * @author 芋道源码 - */ -public interface ApiErrorLogFrameworkService { - - /** - * 创建 API 错误日志 - * - * @param reqDTO API 错误日志 - */ - void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO); - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java deleted file mode 100644 index e4e19fb32..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/service/ApiErrorLogFrameworkServiceImpl.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.framework.apilog.core.service; - -import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; -import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.Async; - -/** - * API 错误日志 Framework Service 实现类 - * - * 基于 {@link ApiErrorLogApi} 服务,记录错误日志 - * - * @author 芋道源码 - */ -@RequiredArgsConstructor -@Slf4j -public class ApiErrorLogFrameworkServiceImpl implements ApiErrorLogFrameworkService { - - private final ApiErrorLogApi apiErrorLogApi; - - @Override - @Async - public void createApiErrorLog(ApiErrorLogCreateReqDTO reqDTO) { - try { - apiErrorLogApi.createApiErrorLog(reqDTO); - } catch (Throwable ex) { - // 由于 @Async 异步调用,这里打印下日志,更容易跟进 - log.error("[createApiErrorLog][url({}) log({}) 发生异常]", reqDTO.getRequestUrl(), reqDTO, ex); - } - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index 1bdda5723..e3684dfac 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.framework.web.config; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; +import jakarta.annotation.Resource; +import jakarta.servlet.Filter; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -25,9 +27,6 @@ import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import jakarta.annotation.Resource; -import jakarta.servlet.Filter; - @AutoConfiguration @EnableConfigurationProperties(WebProperties.class) public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @@ -59,8 +58,9 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { } @Bean - public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogFrameworkService apiErrorLogFrameworkService) { - return new GlobalExceptionHandler(applicationName, apiErrorLogFrameworkService); + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogApi apiErrorLogApi) { + return new GlobalExceptionHandler(applicationName, apiErrorLogApi); } @Bean diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index 41646d7ef..6628f116c 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -5,7 +5,6 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.JakartaServletUtil; -import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -14,6 +13,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.module.infra.api.logger.ApiErrorLogApi; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import jakarta.servlet.http.HttpServletRequest; @@ -40,12 +40,7 @@ import java.time.LocalDateTime; import java.util.Map; import java.util.Set; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.BAD_REQUEST; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.METHOD_NOT_ALLOWED; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_FOUND; -import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.NOT_IMPLEMENTED; +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.*; /** * 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号 @@ -65,7 +60,7 @@ public class GlobalExceptionHandler { @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") private final String applicationName; - private final ApiErrorLogFrameworkService apiErrorLogFrameworkService; + private final ApiErrorLogApi apiErrorLogApi; /** * 处理所有异常,主要是提供给 Filter 使用 @@ -288,7 +283,7 @@ public class GlobalExceptionHandler { // 初始化 errorLog buildExceptionLog(errorLog, req, e); // 执行插入 errorLog - apiErrorLogFrameworkService.createApiErrorLog(errorLog); + apiErrorLogApi.createApiErrorLogAsync(errorLog); } catch (Throwable th) { log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(), JsonUtils.toJsonString(errorLog), th); } diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApi.java index 0a28d2563..84f598959 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApi.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiAccessLogApi.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.api.logger; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiAccessLogCreateReqDTO; import jakarta.validation.Valid; +import org.springframework.scheduling.annotation.Async; /** * API 访问日志的 API 接口 @@ -18,4 +19,14 @@ public interface ApiAccessLogApi { */ void createApiAccessLog(@Valid ApiAccessLogCreateReqDTO createDTO); + /** + * 【异步】创建 API 访问日志 + * + * @param createDTO 访问日志 DTO + */ + @Async + default void createApiAccessLogAsync(ApiAccessLogCreateReqDTO createDTO) { + createApiAccessLog(createDTO); + } + } diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiErrorLogApi.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiErrorLogApi.java index 3544a8977..23ce3bd0d 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiErrorLogApi.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/api/logger/ApiErrorLogApi.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.infra.api.logger; import cn.iocoder.yudao.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO; import jakarta.validation.Valid; +import org.springframework.scheduling.annotation.Async; /** * API 错误日志的 API 接口 @@ -18,4 +19,14 @@ public interface ApiErrorLogApi { */ void createApiErrorLog(@Valid ApiErrorLogCreateReqDTO createDTO); + /** + * 【异步】创建 API 异常日志 + * + * @param createDTO 异常日志 DTO + */ + @Async + default void createApiErrorLogAsync(ApiErrorLogCreateReqDTO createDTO) { + createApiErrorLog(createDTO); + } + } From 54956fcbb9fb12fd05c2c8d85c8a82206723f30b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Sep 2024 08:25:51 +0800 Subject: [PATCH 10/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91INFRA=EF=BC=9AVBEN=20=E7=9A=84=20dict=20?= =?UTF-8?q?=E4=B8=8B=E6=8B=89=E7=B1=BB=E5=9E=8B=E4=B8=8D=E7=B2=BE=E5=87=86?= =?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 --- .../codegen/vue3_vben/views/data.ts.vm | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm index 92d3b2d75..56f4e82ca 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben/views/data.ts.vm @@ -42,9 +42,17 @@ export const searchFormSchema: FormSchema[] = [ #foreach($column in $columns) #if ($column.listOperation) #set ($dictType=$column.dictType) + #set ($javaType = $column.javaType) #set ($javaField = $column.javaField) #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($comment=$column.columnComment) + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") + #set ($dictMethod = "number") + #elseif ($javaType == "String") + #set ($dictMethod = "string") + #elseif ($javaType == "Boolean") + #set ($dictMethod = "boolean") + #end { label: '${comment}', field: '${javaField}', @@ -54,16 +62,16 @@ export const searchFormSchema: FormSchema[] = [ component: 'Select', componentProps: { #if ("" != $dictType)## 设置了 dictType 数据字典的情况 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase()), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else## 未设置 dictType 数据字典的情况 options: [], #end }, #elseif ($column.htmlType == "radio") - component: 'Radio', + component: 'RadioButtonGroup', componentProps: { #if ("" != $dictType)## 设置了 dictType 数据字典的情况 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase()), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else## 未设置 dictType 数据字典的情况 options: [], #end @@ -87,9 +95,17 @@ export const createFormSchema: FormSchema[] = [ #foreach($column in $columns) #if ($column.createOperation) #set ($dictType = $column.dictType) + #set ($javaType = $column.javaType) #set ($javaField = $column.javaField) #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($comment = $column.columnComment) + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") + #set ($dictMethod = "number") + #elseif ($javaType == "String") + #set ($dictMethod = "string") + #elseif ($javaType == "Boolean") + #set ($dictMethod = "boolean") + #end #if (!$column.primaryKey)## 忽略主键,不用在表单里 { label: '${comment}', @@ -117,7 +133,7 @@ export const createFormSchema: FormSchema[] = [ component: 'Select', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -126,7 +142,7 @@ export const createFormSchema: FormSchema[] = [ component: 'Checkbox', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -135,7 +151,7 @@ export const createFormSchema: FormSchema[] = [ component: 'RadioButtonGroup', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -166,9 +182,17 @@ export const updateFormSchema: FormSchema[] = [ #foreach($column in $columns) #if ($column.updateOperation) #set ($dictType = $column.dictType) +#set ($javaType = $column.javaType) #set ($javaField = $column.javaField) #set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)}) #set ($comment = $column.columnComment) +#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") + #set ($dictMethod = "number") +#elseif ($javaType == "String") + #set ($dictMethod = "string") +#elseif ($javaType == "Boolean") + #set ($dictMethod = "boolean") +#end #if (!$column.primaryKey)## 忽略主键,不用在表单里 { label: '${comment}', @@ -196,7 +220,7 @@ export const updateFormSchema: FormSchema[] = [ component: 'Select', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -205,7 +229,7 @@ export const updateFormSchema: FormSchema[] = [ component: 'Checkbox', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end @@ -214,7 +238,7 @@ export const updateFormSchema: FormSchema[] = [ component: 'RadioButtonGroup', componentProps: { #if ("" != $dictType)## 有数据字典 - options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), 'number'), + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), #else##没数据字典 options:[], #end From 2759a323312f9ce66d536f558faa437e55dce3d9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Sep 2024 08:30:29 +0800 Subject: [PATCH 11/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E3=80=91INFRA=EF=BC=9A=E7=A7=BB=E9=99=A4=20Vue3=20+?= =?UTF-8?q?=20Element=20Plus=20schema=20=E6=A8=A1=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/codegen/CodegenFrontTypeEnum.java | 1 - .../service/codegen/inner/CodegenEngine.java | 13 -- .../codegen/vue3_schema/api/api.ts.vm | 46 ------- .../codegen/vue3_schema/views/data.ts.vm | 124 ------------------ .../codegen/vue3_schema/views/form.vue.vm | 65 --------- .../codegen/vue3_schema/views/index.vue.vm | 85 ------------ .../src/main/resources/application.yaml | 2 +- 7 files changed, 1 insertion(+), 335 deletions(-) delete mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/api/api.ts.vm delete mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm delete mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm delete mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/index.vue.vm diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java index b7d2403dc..101781c48 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java @@ -14,7 +14,6 @@ public enum CodegenFrontTypeEnum { VUE2(10), // Vue2 Element UI 标准模版 VUE3(20), // Vue3 Element Plus 标准模版 - VUE3_SCHEMA(21), // Vue3 Element Plus Schema 模版 VUE3_VBEN(30), // Vue3 VBEN 模版 ; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index 4e742539d..63e0c92ac 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -135,15 +135,6 @@ public class CodegenEngine { vue3FilePath("views/${table.moduleName}/${table.businessName}/components/${subSimpleClassName}List.vue")) .put(CodegenFrontTypeEnum.VUE3.getType(), vue3TemplatePath("api/api.ts"), vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) - // Vue3 Schema 模版 - .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) - .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) - .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Form.vue")) - .put(CodegenFrontTypeEnum.VUE3_SCHEMA.getType(), vue3SchemaTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) // Vue3 vben 模版 .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("views/data.ts"), vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) @@ -496,10 +487,6 @@ public class CodegenEngine { "src/" + path; } - private static String vue3SchemaTemplatePath(String path) { - return "codegen/vue3_schema/" + path + ".vm"; - } - private static String vue3VbenTemplatePath(String path) { return "codegen/vue3_vben/" + path + ".vm"; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/api/api.ts.vm deleted file mode 100644 index 48cd5422b..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/api/api.ts.vm +++ /dev/null @@ -1,46 +0,0 @@ -import request from '@/config/axios' -#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") - -export interface ${simpleClassName}VO { - #foreach ($column in $columns) - #if ($column.createOperation || $column.updateOperation) - #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") - ${column.javaField}: number - #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdatetime") - ${column.javaField}: Date - #else - ${column.javaField}: ${column.javaType.toLowerCase()} - #end - #end - #end -} - -// 查询${table.classComment}列表 -export const get${simpleClassName}Page = async (params) => { - return await request.get({ url: '${baseURL}/page', params }) -} - -// 查询${table.classComment}详情 -export const get${simpleClassName} = async (id: number) => { - return await request.get({ url: '${baseURL}/get?id=' + id }) -} - -// 新增${table.classComment} -export const create${simpleClassName} = async (data: ${simpleClassName}VO) => { - return await request.post({ url: '${baseURL}/create', data }) -} - -// 修改${table.classComment} -export const update${simpleClassName} = async (data: ${simpleClassName}VO) => { - return await request.put({ url: '${baseURL}/update', data }) -} - -// 删除${table.classComment} -export const delete${simpleClassName} = async (id: number) => { - return await request.delete({ url: '${baseURL}/delete?id=' + id }) -} - -// 导出${table.classComment} Excel -export const export${simpleClassName}Api = async (params) => { - return await request.download({ url: '${baseURL}/export-excel', params }) -} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm deleted file mode 100644 index ff4fa810a..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/data.ts.vm +++ /dev/null @@ -1,124 +0,0 @@ -import type { CrudSchema } from '@/hooks/web/useCrudSchemas' -import { dateFormatter } from '@/utils/formatTime' - -// 表单校验 -export const rules = reactive({ -#foreach ($column in $columns) -#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键 -#set($comment=$column.columnComment) - $column.javaField: [required], -#end -#end -}) - -// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/ -const crudSchemas = reactive([ -#foreach($column in $columns) -#if ($column.listOperation || $column.listOperationResult || $column.createOperation || $column.updateOperation) -#set ($dictType = $column.dictType) -#set ($javaField = $column.javaField) -#set ($javaType = $column.javaType) - { - label: '${column.columnComment}', - field: '${column.javaField}', -## ========= 字典部分 ========= - #if ("" != $dictType)## 有数据字典 - dictType: DICT_TYPE.$dictType.toUpperCase(), - #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") - dictClass: 'number', - #elseif ($javaType == "String") - dictClass: 'string', - #elseif ($javaType == "Boolean") - dictClass: 'boolean', - #end - #end -## ========= Table 表格部分 ========= - #if (!$column.listOperationResult) - isTable: false, - #else - #if ($column.htmlType == "datetime") - formatter: dateFormatter, - #end - #end -## ========= Search 表格部分 ========= - #if ($column.listOperation) - isSearch: true, - #if ($column.htmlType == "datetime") - search: { - component: 'DatePicker', - componentProps: { - valueFormat: 'YYYY-MM-DD HH:mm:ss', - type: 'daterange', - defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] - } - }, - #end - #end -## ========= Form 表单部分 ========= - #if ((!$column.createOperation && !$column.updateOperation) || $column.primaryKey) - isForm: false, - #else - #if($column.htmlType == "imageUpload")## 图片上传 - form: { - component: 'UploadImg' - }, - #elseif($column.htmlType == "fileUpload")## 文件上传 - form: { - component: 'UploadFile' - }, - #elseif($column.htmlType == "editor")## 文本编辑器 - form: { - component: 'Editor', - componentProps: { - valueHtml: '', - height: 200 - } - }, - #elseif($column.htmlType == "select")## 下拉框 - form: { - component: 'SelectV2' - }, - #elseif($column.htmlType == "checkbox")## 多选框 - form: { - component: 'Checkbox' - }, - #elseif($column.htmlType == "radio")## 单选框 - form: { - component: 'Radio' - }, - #elseif($column.htmlType == "datetime")## 时间框 - form: { - component: 'DatePicker', - componentProps: { - type: 'datetime', - valueFormat: 'x' - } - }, - #elseif($column.htmlType == "textarea")## 文本框 - form: { - component: 'Input', - componentProps: { - type: 'textarea', - rows: 4 - }, - colProps: { - span: 24 - } - }, - #elseif(${javaType.toLowerCase()} == "long" || ${javaType.toLowerCase()} == "integer")## 文本框 - form: { - component: 'InputNumber', - value: 0 - }, - #end - #end - }, -#end -#end - { - label: '操作', - field: 'action', - isForm: false - } -]) -export const { allSchemas } = useCrudSchemas(crudSchemas) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm deleted file mode 100644 index 52f20a2f5..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/form.vue.vm +++ /dev/null @@ -1,65 +0,0 @@ - - diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/index.vue.vm deleted file mode 100644 index 6e8f1403a..000000000 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_schema/views/index.vue.vm +++ /dev/null @@ -1,85 +0,0 @@ - - diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 8d63d9593..72ad7b2ed 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -245,7 +245,7 @@ yudao: codegen: base-package: ${yudao.info.base-package} db-schemas: ${spring.datasource.dynamic.datasource.master.name} - front-type: 10 # 前端模版的类型,参见 CodegenFrontTypeEnum 枚举类 + front-type: 20 # 前端模版的类型,参见 CodegenFrontTypeEnum 枚举类 tenant: # 多租户相关配置项 enable: true ignore-urls: From 840cfad84aa45e70b1ec11f6ce7529b5f6e2a247 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Sep 2024 12:05:42 +0800 Subject: [PATCH 12/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E4=BB=B7=E6=A0=BC?= =?UTF-8?q?=E8=AE=A1=E7=AE=97=E6=97=B6=EF=BC=8C=E8=BF=94=E5=9B=9E=E5=8F=AF?= =?UTF-8?q?=E7=94=A8=20+=20=E4=B8=8D=E5=8F=AF=E7=94=A8=E7=9A=84=E4=BC=98?= =?UTF-8?q?=E6=83=A0=E5=8A=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 +- .../promotion/api/coupon/CouponApi.java | 18 ++-- .../api/coupon/dto/CouponValidReqDTO.java | 27 ------ .../promotion/enums/ErrorCodeConstants.java | 2 - .../promotion/api/coupon/CouponApiImpl.java | 15 ++- .../app/coupon/AppCouponController.java | 17 +--- .../coupon/vo/coupon/AppCouponMatchReqVO.java | 30 ------ .../vo/coupon/AppCouponMatchRespVO.java | 16 ---- .../app/coupon/vo/coupon/AppCouponRespVO.java | 2 - .../convert/coupon/CouponConvert.java | 3 - .../dal/mysql/coupon/CouponMapper.java | 20 ---- .../mysql/reward/RewardActivityMapper.java | 8 +- .../service/coupon/CouponService.java | 30 ------ .../service/coupon/CouponServiceImpl.java | 30 +----- .../trade/enums/ErrorCodeConstants.java | 2 +- .../vo/AppTradeOrderSettlementRespVO.java | 45 ++++++++- .../price/bo/TradePriceCalculateRespBO.java | 65 ++++++++++++- .../TradeCouponPriceCalculator.java | 94 +++++++++++++------ .../TradeCouponPriceCalculatorTest.java | 11 ++- .../oauth2/OAuth2TokenServiceImplTest.java | 2 +- yudao-server/pom.xml | 60 ++++++------ 21 files changed, 240 insertions(+), 263 deletions(-) delete mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java delete mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java delete mode 100755 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchRespVO.java diff --git a/pom.xml b/pom.xml index 4634d345e..86dfebcc3 100644 --- a/pom.xml +++ b/pom.xml @@ -15,12 +15,12 @@ yudao-module-system yudao-module-infra - yudao-module-member + - yudao-module-pay - yudao-module-mall + + diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java index 789a4526d..10d4eb64c 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApi.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.promotion.api.coupon; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; import jakarta.validation.Valid; import java.util.List; @@ -15,6 +14,15 @@ import java.util.Map; */ public interface CouponApi { + /** + * 获得用户的优惠劵列表 + * + * @param userId 用户编号 + * @param status 优惠劵状态 + * @return 优惠劵列表 + */ + List getCouponListByUserId(Long userId, Integer status); + /** * 使用优惠劵 * @@ -29,14 +37,6 @@ public interface CouponApi { */ void returnUsedCoupon(Long id); - /** - * 校验优惠劵 - * - * @param validReqDTO 校验请求 - * @return 优惠劵 - */ - CouponRespDTO validateCoupon(@Valid CouponValidReqDTO validReqDTO); - /** * 【管理员】给指定用户批量发送优惠券 * diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java deleted file mode 100644 index f219b6fdd..000000000 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/dto/CouponValidReqDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.promotion.api.coupon.dto; - -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -/** - * 优惠劵使用 Request DTO - * - * @author 芋道源码 - */ -@Data -public class CouponValidReqDTO { - - /** - * 优惠劵编号 - */ - @NotNull(message = "优惠劵编号不能为空") - private Long id; - - /** - * 用户编号 - */ - @NotNull(message = "用户编号不能为空") - private Long userId; - -} diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java index e1efb9c91..c1af1b874 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java @@ -20,8 +20,6 @@ public interface ErrorCodeConstants { ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在"); // ========== Coupon 相关 1-013-003-000 ============ - ErrorCode COUPON_NO_MATCH_SPU = new ErrorCode(1_013_003_000, "优惠劵没有可使用的商品!"); - ErrorCode COUPON_NO_MATCH_MIN_PRICE = new ErrorCode(1_013_003_001, "所结算的商品中未满足使用的金额"); // ========== 优惠劵模板 1-013-004-000 ========== ErrorCode COUPON_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_004_000, "优惠劵模板不存在"); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java index edc8f1b7f..167883e0b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/coupon/CouponApiImpl.java @@ -1,11 +1,9 @@ package cn.iocoder.yudao.module.promotion.api.coupon; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; -import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; -import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.service.coupon.CouponService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -26,6 +24,11 @@ public class CouponApiImpl implements CouponApi { @Resource private CouponService couponService; + @Override + public List getCouponListByUserId(Long userId, Integer status) { + return BeanUtils.toBean(couponService.getCouponList(userId, status), CouponRespDTO.class); + } + @Override public void useCoupon(CouponUseReqDTO useReqDTO) { couponService.useCoupon(useReqDTO.getId(), useReqDTO.getUserId(), @@ -37,12 +40,6 @@ public class CouponApiImpl implements CouponApi { couponService.returnUsedCoupon(id); } - @Override - public CouponRespDTO validateCoupon(CouponValidReqDTO validReqDTO) { - CouponDO coupon = couponService.validCoupon(validReqDTO.getId(), validReqDTO.getUserId()); - return CouponConvert.INSTANCE.convert(coupon); - } - @Override public List takeCouponsByAdmin(Map giveCoupons, Long userId) { return couponService.takeCouponsByAdmin(giveCoupons, userId); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java index ed19d9141..bde2d8f91 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java @@ -5,7 +5,9 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.*; +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; +import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponTakeReqVO; import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; @@ -15,13 +17,12 @@ import cn.iocoder.yudao.module.promotion.service.coupon.CouponTemplateService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.util.Collections; -import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -56,14 +57,6 @@ public class AppCouponController { return success(canTakeAgain); } - @GetMapping("/match-list") - @Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表") - public CommonResult> getMatchCouponList(AppCouponMatchReqVO matchReqVO) { - // todo: 优化:优惠金额倒序 - List list = couponService.getMatchCouponList(getLoginUserId(), matchReqVO); - return success(BeanUtils.toBean(list, AppCouponMatchRespVO.class)); - } - @GetMapping("/page") @Operation(summary = "我的优惠劵列表") @PreAuthenticated diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java deleted file mode 100755 index 6dc287d98..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchReqVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import java.util.List; - -@Schema(description = "用户 App - 优惠劵的匹配 Request VO") -@Data -public class AppCouponMatchReqVO { - - @Schema(description = "商品金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "商品金额不能为空") - private Integer price; - - @Schema(description = "商品 SPU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]") - @NotEmpty(message = "商品 SPU 编号不能为空") - private List spuIds; - - @Schema(description = "商品 SKU 编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1, 2]") - @NotEmpty(message = "商品 SKU 编号不能为空") - private List skuIds; - - @Schema(description = "分类编号的数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "[10, 20]") - @NotEmpty(message = "分类编号不能为空") - private List categoryIds; - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchRespVO.java deleted file mode 100755 index da60390fe..000000000 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponMatchRespVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "用户 App - 优惠劵 Response VO") -@Data -public class AppCouponMatchRespVO extends AppCouponRespVO { - - @Schema(description = "是否匹配", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") - private Boolean match; - - @Schema(description = "匹配条件的提示", example = "所结算商品没有符合条件的商品") - private String description; - -} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java index c0949f671..f6084a2c4 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/coupon/AppCouponRespVO.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import jakarta.validation.constraints.Min; import java.time.LocalDateTime; import java.util.List; @@ -42,7 +41,6 @@ public class AppCouponRespVO { private Integer discountPercent; @Schema(description = "优惠金额", example = "10") - @Min(value = 0, message = "优惠金额需要大于等于 0") private Integer discountPrice; @Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java index 542a77e84..0ac9c58da 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/coupon/CouponConvert.java @@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageItemRespVO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO; import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponRespVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; @@ -16,7 +14,6 @@ import org.mapstruct.factory.Mappers; import java.time.LocalDateTime; import java.util.Collection; -import java.util.List; /** * 优惠劵 Convert diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java index e5f1daf6c..ce89b0593 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponMapper.java @@ -1,13 +1,11 @@ package cn.iocoder.yudao.module.promotion.dal.mysql.coupon; import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; -import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.github.yulichang.toolkit.MPJWrappers; import org.apache.ibatis.annotations.Mapper; @@ -16,8 +14,6 @@ import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; @@ -84,22 +80,6 @@ public interface CouponMapper extends BaseMapperX { return convertMap(list, map -> MapUtil.getLong(map, templateIdAlias), map -> MapUtil.getInt(map, countAlias)); } - default List selectListByUserIdAndStatusAndUsePriceLeAndProductScope( - Long userId, Integer status, Integer usePrice, List spuIds, List categoryIds) { - Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream() - .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id)) - .collect(Collectors.joining(" OR ")); - return selectList(new LambdaQueryWrapperX() - .eq(CouponDO::getUserId, userId) - .eq(CouponDO::getStatus, status) - .le(CouponDO::getUsePrice, usePrice) // 价格小于等于,满足价格使用条件 - .and(w -> w.eq(CouponDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()) // 商品范围一:全部 - .or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.SPU.getScope()) // 商品范围二:满足指定商品 - .apply(productScopeValuesFindInSetFunc.apply(spuIds))) - .or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope()) // 商品范围三:满足指定分类 - .apply(productScopeValuesFindInSetFunc.apply(categoryIds))))); - } - default List selectListByStatusAndValidEndTimeLe(Integer status, LocalDateTime validEndTime) { return selectList(new LambdaQueryWrapperX() .eq(CouponDO::getStatus, status) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java index 915696967..cc9010d93 100755 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java @@ -30,15 +30,9 @@ public interface RewardActivityMapper extends BaseMapperX { .orderByDesc(RewardActivityDO::getId)); } - default List selectListByProductScopeAndStatus(Integer productScope, Integer status) { - return selectList(new LambdaQueryWrapperX() - .eq(RewardActivityDO::getProductScope, productScope) - .eq(RewardActivityDO::getStatus, status)); - } - default List selectListBySpuIdsAndStatus(Collection spuIds, Integer status) { Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream() - .map(id -> StrUtil.format("FIND_IN_SET({}, product_spu_ids) ", id)) + .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id)) .collect(Collectors.joining(" OR ")); return selectList(new QueryWrapper() .eq("status", status) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java index 5fdcd0669..c24cf3ac9 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponService.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum; @@ -18,26 +17,6 @@ import java.util.*; */ public interface CouponService { - /** - * 校验优惠劵,包括状态、有限期 - *

- * 1. 如果校验通过,则返回优惠劵信息 - * 2. 如果校验不通过,则直接抛出业务异常 - * - * @param id 优惠劵编号 - * @param userId 用户编号 - * @return 优惠劵信息 - */ - CouponDO validCoupon(Long id, Long userId); - - /** - * 校验优惠劵,包括状态、有限期 - * - * @param coupon 优惠劵 - * @see #validCoupon(Long, Long) 逻辑相同,只是入参不同 - */ - void validCoupon(CouponDO coupon); - /** * 使用优惠劵 * @@ -171,15 +150,6 @@ public interface CouponService { return MapUtil.getInt(map, templateId, 0); } - /** - * 获取用户匹配的优惠券列表 - * - * @param userId 用户编号 - * @param matchReqVO 匹配参数 - * @return 优惠券列表 - */ - List getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO); - /** * 获取用户是否可以领取优惠券 * diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index e6cd4ba0e..cff17f9da 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -12,7 +12,6 @@ import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.module.member.api.user.MemberUserApi; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO; -import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO; import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO; @@ -56,18 +55,9 @@ public class CouponServiceImpl implements CouponService { private MemberUserApi memberUserApi; @Override - public CouponDO validCoupon(Long id, Long userId) { - CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId); - if (coupon == null) { - throw exception(COUPON_NOT_EXISTS); - } - validCoupon(coupon); - return coupon; - } - - @Override - public void validCoupon(CouponDO coupon) { + public void useCoupon(Long id, Long userId, Long orderId) { // 校验状态 + CouponDO coupon = couponMapper.selectByIdAndUserId(id, userId); if (ObjectUtil.notEqual(coupon.getStatus(), CouponStatusEnum.UNUSED.getStatus())) { throw exception(COUPON_STATUS_NOT_UNUSED); } @@ -75,12 +65,6 @@ public class CouponServiceImpl implements CouponService { if (!LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())) { throw exception(COUPON_VALID_TIME_NOT_NOW); } - } - - @Override - public void useCoupon(Long id, Long userId, Long orderId) { - // 校验优惠劵 - validCoupon(id, userId); // 更新状态 int updateCount = couponMapper.updateByIdAndStatus(id, CouponStatusEnum.UNUSED.getStatus(), @@ -354,16 +338,6 @@ public class CouponServiceImpl implements CouponService { return couponMapper.selectCountByUserIdAndTemplateIdIn(userId, templateIds); } - @Override - public List getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) { - List list = couponMapper.selectListByUserIdAndStatusAndUsePriceLeAndProductScope(userId, - CouponStatusEnum.UNUSED.getStatus(), - matchReqVO.getPrice(), matchReqVO.getSpuIds(), matchReqVO.getCategoryIds()); - // 兜底逻辑:如果 CouponExpireJob 未执行,status 未变成 EXPIRE ,但是 validEndTime 已经过期了,需要进行过滤 - list.removeIf(coupon -> !LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime())); - return list; - } - @Override public Map getUserCanCanTakeMap(Long userId, List templates) { // 1. 未登录时,都显示可以领取 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 5613cae8e..c3a42e40e 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 @@ -61,7 +61,7 @@ public interface ErrorCodeConstants { ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵"); ErrorCode PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_005, "参与秒杀的商品,超过了秒杀总限购数量"); ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL = new ErrorCode(1_011_003_006, "计算快递运费异常,配送方式不匹配"); - ErrorCode PRICE_CALCULATE_COUPON_PRICE_TOO_MUCH = new ErrorCode(1_011_003_007, "该优惠劵无法使用,原因:优惠金额超过订单金额"); + ErrorCode PRICE_CALCULATE_COUPON_CAN_NOT_USE = new ErrorCode(1_011_003_007, "该优惠劵无法使用,原因:{}」"); // ========== 物流 Express 模块 1-011-004-000 ========== ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在"); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java index 9aab1b68b..42f035a10 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.trade.controller.app.order.vo; import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; import java.util.List; @Schema(description = "用户 App - 交易订单结算信息 Response VO") @@ -19,6 +19,9 @@ public class AppTradeOrderSettlementRespVO { @Schema(description = "购物项数组", requiredMode = Schema.RequiredMode.REQUIRED) private List items; + @Schema(description = "优惠劵数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List coupons; // 可用 + 不可用 + @Schema(description = "费用", requiredMode = Schema.RequiredMode.REQUIRED) private Price price; @@ -109,7 +112,6 @@ public class AppTradeOrderSettlementRespVO { private String mobile; @Schema(description = "地区编号", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "地区编号不能为空") private Long areaId; @Schema(description = "地区名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海上海市普陀区") private String areaName; @@ -122,4 +124,43 @@ public class AppTradeOrderSettlementRespVO { } + @Schema(description = "优惠劵信息") + @Data + public static class Coupon { + + @Schema(description = "优惠劵编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long id; + + @Schema(description = "优惠劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "春节送送送") + private String name; + + @Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位:分;0 - 不限制 + private Integer usePrice; + + @Schema(description = "固定日期 - 生效开始时间") + private LocalDateTime validStartTime; + + @Schema(description = "固定日期 - 生效结束时间") + private LocalDateTime validEndTime; + + @Schema(description = "优惠类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer discountType; + + @Schema(description = "折扣百分比", example = "80") // 例如说,80% 为 80 + private Integer discountPercent; + + @Schema(description = "优惠金额", example = "10") + private Integer discountPrice; + + @Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用 + private Integer discountLimitPrice; + + @Schema(description = "是否可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + private Boolean match; + + @Schema(description = "不可用原因", example = "优惠劵已过期") + private String mismatchReason; + + } + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java index 4f65f33d1..7fed25899 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import lombok.Data; +import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -45,9 +46,13 @@ public class TradePriceCalculateRespBO { private List promotions; /** - * 优惠劵编号 + * 使用的优惠劵编号 */ private Long couponId; + /** + * 用户的优惠劵列表(可用 + 不可用) + */ + private List coupons; /** * 会员剩余积分 @@ -339,4 +344,62 @@ public class TradePriceCalculateRespBO { } + /** + * 优惠劵信息 + */ + @Data + public static class Coupon { + + /** + * 优惠劵编号 + */ + private Long id; + /** + * 优惠劵名 + */ + private String name; + + /** + * 是否设置满多少金额可用,单位:分 + */ + private Integer usePrice; + + /** + * 生效开始时间 + */ + private LocalDateTime validStartTime; + /** + * 生效结束时间 + */ + private LocalDateTime validEndTime; + + /** + * 优惠类型 + */ + private Integer discountType; + /** + * 折扣百分比 + */ + private Integer discountPercent; + /** + * 优惠金额,单位:分 + */ + private Integer discountPrice; + /** + * 折扣上限,单位:分 + */ + private Integer discountLimitPrice; + + /** + * 是否匹配 + */ + private Boolean match; + /** + * 不匹配的原因 + */ + private String mismatchReason; + + } + + } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java index 1c7294be5..3f3b7f70d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java @@ -1,31 +1,31 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; +import jakarta.annotation.Resource; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; -import jakarta.annotation.Resource; import java.util.List; import java.util.function.Predicate; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_MIN_PRICE; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_SPU; +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_COUPON_CAN_NOT_USE; import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER; -import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_COUPON_PRICE_TOO_MUCH; /** * 优惠劵的 {@link TradePriceCalculator} 实现类 @@ -41,34 +41,37 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { @Override public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { - // 1.1 校验优惠劵 + // 只有【普通】订单,才允许使用优惠劵 + if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { + if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { + throw exception(PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER); + } + return; + } + + // 1.1 加载用户的优惠劵列表 + List coupons = couponApi.getCouponListByUserId(param.getUserId(), CouponStatusEnum.UNUSED.getStatus()); + coupons.removeIf(coupon -> LocalDateTimeUtils.beforeNow(coupon.getValidEndTime())); + // 1.2 计算优惠劵的使用条件 + result.setCoupons(calculateCoupons(coupons, result)); + + // 2. 校验优惠劵是否可用 if (param.getCouponId() == null) { return; } - CouponRespDTO coupon = couponApi.validateCoupon(new CouponValidReqDTO() - .setId(param.getCouponId()).setUserId(param.getUserId())); - Assert.notNull(coupon, "校验通过的优惠劵({}),不能为空", param.getCouponId()); - // 1.2 只有【普通】订单,才允许使用优惠劵 - if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { - throw exception(PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER); + TradePriceCalculateRespBO.Coupon couponBO = CollUtil.findOne(result.getCoupons(), item -> item.getId().equals(param.getCouponId())); + CouponRespDTO coupon = CollUtil.findOne(coupons, item -> item.getId().equals(param.getCouponId())); + if (couponBO == null || coupon == null) { + throw exception(PRICE_CALCULATE_COUPON_CAN_NOT_USE, "优惠劵不存在"); } - - // 2.1 获得匹配的商品 SKU 数组 - List orderItems = filterMatchCouponOrderItems(result, coupon); - if (CollUtil.isEmpty(orderItems)) { - throw exception(COUPON_NO_MATCH_SPU); - } - // 2.2 计算是否满足优惠劵的使用金额 - Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); - if (totalPayPrice < coupon.getUsePrice()) { - throw exception(COUPON_NO_MATCH_MIN_PRICE); + if (Boolean.FALSE.equals(couponBO.getMatch())) { + throw exception(PRICE_CALCULATE_COUPON_CAN_NOT_USE, couponBO.getMismatchReason()); } // 3.1 计算可以优惠的金额 + List orderItems = filterMatchCouponOrderItems(result, coupon); + Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); Integer couponPrice = getCouponPrice(coupon, totalPayPrice); - if (couponPrice <= totalPayPrice) { - throw exception(PRICE_CALCULATE_COUPON_PRICE_TOO_MUCH); - } // 3.2 计算分摊的优惠金额 List divideCouponPrices = TradePriceCalculatorHelper.dividePrice(orderItems, couponPrice); @@ -76,7 +79,7 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { result.setCouponId(param.getCouponId()); // 4.2 记录优惠明细 TradePriceCalculatorHelper.addPromotion(result, orderItems, - param.getCouponId(), coupon.getName(), PromotionTypeEnum.COUPON.getType(), + param.getCouponId(), couponBO.getName(), PromotionTypeEnum.COUPON.getType(), StrUtil.format("优惠劵:省 {} 元", TradePriceCalculatorHelper.formatPrice(couponPrice)), divideCouponPrices); // 4.3 更新 SKU 优惠金额 @@ -88,6 +91,43 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { TradePriceCalculatorHelper.recountAllPrice(result); } + /** + * 计算用户的优惠劵列表(可用 + 不可用) + * + * @param coupons 优惠劵 + * @param result 计算结果 + * @return 优惠劵列表 + */ + private List calculateCoupons(List coupons, + TradePriceCalculateRespBO result) { + return convertList(coupons, coupon -> { + TradePriceCalculateRespBO.Coupon matchCoupon = BeanUtils.toBean(coupon, TradePriceCalculateRespBO.Coupon.class); + // 1.1 优惠劵未到使用时间 + if (LocalDateTimeUtils.afterNow(coupon.getValidStartTime())) { + return matchCoupon.setMatch(false).setMismatchReason("优惠劵未到使用时间"); + } + // 1.2 优惠劵没有匹配的商品 + List orderItems = filterMatchCouponOrderItems(result, coupon); + if (CollUtil.isEmpty(orderItems)) { + return matchCoupon.setMatch(false).setMismatchReason("优惠劵没有匹配的商品"); + } + // 1.3 差 %1$,.2f 元可用优惠劵 + Integer totalPayPrice = TradePriceCalculatorHelper.calculateTotalPayPrice(orderItems); + if (totalPayPrice < coupon.getUsePrice()) { + return matchCoupon.setMatch(false) + .setMismatchReason(String.format("差 %1$,.2f 元可用优惠劵", (coupon.getUsePrice() - totalPayPrice) / 100D)); + } + // 1.4 优惠金额超过订单金额 + Integer couponPrice = getCouponPrice(coupon, totalPayPrice); + if (couponPrice >= totalPayPrice) { + return matchCoupon.setMatch(false).setMismatchReason("优惠金额超过订单金额"); + } + + // 2. 满足条件 + return matchCoupon.setMatch(true); + }); + } + private Integer getCouponPrice(CouponRespDTO coupon, Integer totalPayPrice) { if (PromotionDiscountTypeEnum.PRICE.getType().equals(coupon.getDiscountType())) { // 减价 return coupon.getDiscountPrice(); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculatorTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculatorTest.java index 06655e0b2..373a4581d 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculatorTest.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculatorTest.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; +import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; -import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; +import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; @@ -14,8 +15,10 @@ import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import java.time.Duration; import java.util.ArrayList; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -69,8 +72,10 @@ public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { CouponRespDTO coupon = randomPojo(CouponRespDTO.class, o -> o.setId(1024L).setName("程序员节") .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)) .setUsePrice(350).setDiscountType(PromotionDiscountTypeEnum.PERCENT.getType()) - .setDiscountPercent(50).setDiscountLimitPrice(70)); - when(couponApi.validateCoupon(eq(new CouponValidReqDTO().setId(1024L).setUserId(233L)))).thenReturn(coupon); + .setDiscountPercent(50).setDiscountLimitPrice(70)) + .setValidStartTime(addTime(Duration.ofDays(1))).setValidEndTime(addTime(Duration.ofDays(2))); + when(couponApi.getCouponListByUserId(eq(233L), eq(CouponStatusEnum.UNUSED.getStatus()))) + .thenReturn(ListUtil.toList(coupon)); // 调用 tradeCouponPriceCalculator.calculate(param, result); diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java index c548940d6..89c59b7ee 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImplTest.java @@ -144,7 +144,7 @@ public class OAuth2TokenServiceImplTest extends BaseDbAndRedisUnitTest { // 调用,并断言 assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId), new ErrorCode(401, "刷新令牌已过期")); - assertEquals(0, oauth2RefreshTokenMapper.selectCount()); + assertEquals(0, oauth2AccessTokenMapper.selectCount()); } @Test diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index d0c429aab..3b16fa192 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -33,11 +33,11 @@ - - cn.iocoder.boot - yudao-module-member-biz - ${revision} - + + + + + @@ -52,11 +52,11 @@ - - cn.iocoder.boot - yudao-module-pay-biz - ${revision} - + + + + + @@ -66,26 +66,26 @@ - - cn.iocoder.boot - yudao-module-promotion-biz - ${revision} - - - cn.iocoder.boot - yudao-module-product-biz - ${revision} - - - cn.iocoder.boot - yudao-module-trade-biz - ${revision} - - - cn.iocoder.boot - yudao-module-statistics-biz - ${revision} - + + + + + + + + + + + + + + + + + + + + From 75ed4486c47ec2fe0cddba58e9bd01ee690deb99 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Sep 2024 14:07:07 +0800 Subject: [PATCH 13/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E6=8B=BC=E5=9B=A2?= =?UTF-8?q?=E4=B8=AD=E6=97=B6=EF=BC=8C=E7=A6=81=E6=AD=A2=E5=8F=91=E8=B5=B7?= =?UTF-8?q?=E5=94=AE=E5=90=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/combination/CombinationRecordApi.java | 8 +- .../dto/CombinationRecordRespDTO.java | 110 ++++++++++++++++++ .../combination/CombinationRecordApiImpl.java | 13 +-- .../trade/enums/ErrorCodeConstants.java | 1 + .../aftersale/AfterSaleServiceImpl.java | 14 +++ .../order/TradeOrderUpdateServiceImpl.java | 2 +- .../handler/TradeCombinationOrderHandler.java | 6 +- .../TradeCouponPriceCalculator.java | 2 +- 8 files changed, 140 insertions(+), 16 deletions(-) create mode 100644 yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordRespDTO.java diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java index 942ededec..50dae948f 100644 --- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApi.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.promotion.api.combination; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateRespDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; - import jakarta.validation.Valid; /** @@ -33,13 +33,13 @@ public interface CombinationRecordApi { CombinationRecordCreateRespDTO createCombinationRecord(@Valid CombinationRecordCreateReqDTO reqDTO); /** - * 查询拼团记录是否成功 + * 基于订单编号,查询拼团记录 * * @param userId 用户编号 * @param orderId 订单编号 - * @return 拼团是否成功 + * @return 拼团记录 */ - boolean isCombinationRecordSuccess(Long userId, Long orderId); + CombinationRecordRespDTO getCombinationRecordByOrderId(Long userId, Long orderId); /** * 【下单前】校验是否满足拼团活动条件 diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordRespDTO.java new file mode 100644 index 000000000..82fe21257 --- /dev/null +++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/dto/CombinationRecordRespDTO.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.promotion.api.combination.dto; + +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 拼团记录 Response DTO + * + * @author 芋道源码 + */ +@Data +public class CombinationRecordRespDTO { + + /** + * 编号,主键自增 + */ + private Long id; + + /** + * 拼团活动编号 + * + * 关联 CombinationActivityDO 的 id 字段 + */ + private Long activityId; + /** + * 拼团商品单价 + * + * 冗余 CombinationProductDO 的 combinationPrice 字段 + */ + private Integer combinationPrice; + /** + * SPU 编号 + */ + private Long spuId; + /** + * 商品名字 + */ + private String spuName; + /** + * 商品图片 + */ + private String picUrl; + /** + * SKU 编号 + */ + private Long skuId; + /** + * 购买的商品数量 + */ + private Integer count; + + /** + * 用户编号 + */ + private Long userId; + + /** + * 用户昵称 + */ + private String nickname; + /** + * 用户头像 + */ + private String avatar; + + /** + * 团长编号 + */ + private Long headId; + /** + * 开团状态 + * + * 关联 {@link CombinationRecordStatusEnum} + */ + private Integer status; + /** + * 订单编号 + */ + private Long orderId; + /** + * 开团需要人数 + * + * 关联 CombinationActivityDO 的 userSize 字段 + */ + private Integer userSize; + /** + * 已加入拼团人数 + */ + private Integer userCount; + /** + * 是否虚拟成团 + */ + private Boolean virtualGroup; + + /** + * 过期时间 + */ + private LocalDateTime expireTime; + /** + * 开始时间 (订单付款后开始的时间) + */ + private LocalDateTime startTime; + /** + * 结束时间(成团时间/失败时间) + */ + private LocalDateTime endTime; + +} diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java index 354f5b359..32f9ea426 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/combination/CombinationRecordApiImpl.java @@ -1,19 +1,17 @@ package cn.iocoder.yudao.module.promotion.api.combination; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateReqDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateRespDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationValidateJoinRespDTO; import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; -import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_RECORD_NOT_EXISTS; - /** * 拼团活动 API 实现类 * @@ -37,12 +35,9 @@ public class CombinationRecordApiImpl implements CombinationRecordApi { } @Override - public boolean isCombinationRecordSuccess(Long userId, Long orderId) { + public CombinationRecordRespDTO getCombinationRecordByOrderId(Long userId, Long orderId) { CombinationRecordDO record = combinationRecordService.getCombinationRecord(userId, orderId); - if (record == null) { - throw exception(COMBINATION_RECORD_NOT_EXISTS); - } - return CombinationRecordStatusEnum.isSuccess(record.getStatus()); + return BeanUtils.toBean(record, CombinationRecordRespDTO.class); } @Override 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 c3a42e40e..2ab726ec4 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 @@ -51,6 +51,7 @@ public interface ErrorCodeConstants { ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1_011_000_110, "退款失败,售后单状态不是【待退款】"); ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY = new ErrorCode(1_011_000_111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】"); + ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_COMBINATION_IN_PROGRESS = new ErrorCode(1_011_000_112, "订单拼团中,无法申请售后"); // ========== Cart 模块 1-011-002-000 ========== ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1_011_002_000, "购物车项不存在"); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java index df3d2db60..7d57ead11 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java @@ -8,6 +8,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; +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.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO; import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO; import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO; @@ -26,6 +29,7 @@ import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleTypeEnum; import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleWayEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; import cn.iocoder.yudao.module.trade.framework.aftersale.core.annotations.AfterSaleLog; import cn.iocoder.yudao.module.trade.framework.aftersale.core.utils.AfterSaleLogUtils; import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; @@ -71,6 +75,8 @@ public class AfterSaleServiceImpl implements AfterSaleService { @Resource private PayRefundApi payRefundApi; + @Resource + private CombinationRecordApi combinationRecordApi; @Resource private TradeOrderProperties tradeOrderProperties; @@ -148,6 +154,14 @@ public class AfterSaleServiceImpl implements AfterSaleService { && !TradeOrderStatusEnum.haveDelivered(order.getStatus())) { throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_NO_DELIVERED); } + // 如果是拼团订单,则进行中不允许售后 + if (TradeOrderTypeEnum.isCombination(order.getType())) { + CombinationRecordRespDTO combinationRecord = combinationRecordApi.getCombinationRecordByOrderId( + order.getUserId(), order.getId()); + if (combinationRecord != null && CombinationRecordStatusEnum.isInProgress(combinationRecord.getStatus())) { + throw exception(AFTER_SALE_CREATE_FAIL_ORDER_STATUS_COMBINATION_IN_PROGRESS); + } + } return orderItem; } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index ce0c953e1..300da3f9f 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -887,7 +887,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { .setAppKey(tradeOrderProperties.getPayAppKey()).setUserIp(getClientIP()) // 支付应用 .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号 .setMerchantRefundId(String.valueOf(order.getId())) - .setReason(TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getName()).setPrice(order.getPayPrice()));// 价格信息 + .setReason(TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getName()).setPrice(order.getPayPrice())); // 价格信息 } @Override diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationOrderHandler.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationOrderHandler.java index 9216258db..6fdcf24f6 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationOrderHandler.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeCombinationOrderHandler.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.trade.service.order.handler; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordCreateRespDTO; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; @@ -84,7 +86,9 @@ public class TradeCombinationOrderHandler implements TradeOrderHandler { return; } // 校验订单拼团是否成功 - if (!combinationRecordApi.isCombinationRecordSuccess(order.getUserId(), order.getId())) { + CombinationRecordRespDTO combinationRecord = combinationRecordApi.getCombinationRecordByOrderId(order.getUserId(), order.getId()); + Assert.notNull(combinationRecord, "订单({})对应的拼团记录不存在", order.getId()); + if (!CombinationRecordStatusEnum.isSuccess(combinationRecord.getStatus())) { throw exception(ORDER_DELIVERY_FAIL_COMBINATION_RECORD_STATUS_NOT_SUCCESS); } } diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java index 3f3b7f70d..1292a2f85 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java @@ -43,7 +43,7 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { // 只有【普通】订单,才允许使用优惠劵 if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { - if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { + if (param.getCouponId() != null) { throw exception(PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER); } return; From 74492d65f03c8749fc13cfbdf610e352ad2230ed Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Sep 2024 14:57:36 +0800 Subject: [PATCH 14/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91AI=EF=BC=9Amodel-uri=E3=80=81tokenizer=20?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index fe04d1ee4..baf68657e 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -154,9 +154,9 @@ spring: embedding: transformer: onnx: - model-uri: http://test.yudao.iocoder.cn/model.onnx + model-uri: https://raw.gitcode.com/yudaocode/yudao-demo/raw/master/yudao-static/ai/model.onnx tokenizer: - uri: http://test.yudao.iocoder.cn/tokenizer.json + uri: https://raw.gitcode.com/yudaocode/yudao-demo/raw/master/yudao-static/ai/tokenizer.json qianfan: # 文心一言 api-key: x0cuLZ7XsaTCU08vuJWO87Lg secret-key: R9mYF9dl9KASgi5RUq0FQt3wRisSnOcK From 9f271c3d962d9b96caac650240fc845a718076a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E8=B6=8A?= <552369664@qq.com> Date: Sun, 8 Sep 2024 11:11:22 +0800 Subject: [PATCH 15/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E7=A7=92=E6=9D=80?= =?UTF-8?q?=E8=A3=85=E4=BF=AE=E9=87=8D=E6=9E=84=EF=BC=88PC=E7=AB=AF?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seckill/SeckillActivityController.java | 25 ++++++++++++++++--- .../vo/activity/SeckillActivityRespVO.java | 4 +++ .../seckill/AppSeckillActivityController.java | 6 ++--- .../seckill/SeckillActivityConvert.java | 17 +++++++++++++ .../seckill/SeckillActivityService.java | 12 +++++++-- .../seckill/SeckillActivityServiceImpl.java | 9 +++++-- 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java index dd64870e4..0c41071e8 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.seckill; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; @@ -13,15 +14,17 @@ import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @Tag(name = "管理后台 - 秒杀活动") @@ -89,11 +92,27 @@ public class SeckillActivityController { } // 拼接数据 - List products = seckillActivityService.getSeckillProductListByActivityId( + List products = seckillActivityService.getSeckillProductListByActivityIds( convertSet(pageResult.getList(), SeckillActivityDO::getId)); List spuList = productSpuApi.getSpuList( convertSet(pageResult.getList(), SeckillActivityDO::getSpuId)); return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, products, spuList)); } + @GetMapping("/list-by-ids") + @Operation(summary = "获得秒杀活动列表,基于活动编号数组") + @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityListByIds(@RequestParam("ids") List ids) { + // 1. 获得开启的活动列表 + List activityList = seckillActivityService.getSeckillActivityListByIds(ids); + activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus())); + if (CollUtil.isEmpty(activityList)) { + return success(Collections.emptyList()); + } + // 2. 拼接返回 + List productList = seckillActivityService.getSeckillProductListByActivityIds( + convertList(activityList, SeckillActivityDO::getId)); + List spuList = productSpuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId)); + return success(SeckillActivityConvert.INSTANCE.convertList(activityList, productList, spuList)); + } } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java index 742c73ba6..b6a868585 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java @@ -54,4 +54,8 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO { example = "50") private Integer marketPrice; + @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") + private Integer seckillPrice; // 从 products 获取最小 price 读取 + + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java index c91de0ee7..62627a203 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java @@ -23,6 +23,7 @@ import com.google.common.cache.LoadingCache; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -30,7 +31,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import jakarta.annotation.Resource; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; @@ -86,7 +86,7 @@ public class AppSeckillActivityController { // 2.1 查询满足当前阶段的活动 List activityList = activityService.getSeckillActivityListByConfigIdAndStatus(config.getId(), CommonStatusEnum.ENABLE.getStatus()); - List productList = activityService.getSeckillProductListByActivityId( + List productList = activityService.getSeckillProductListByActivityIds( convertList(activityList, SeckillActivityDO::getId)); // 2.2 获取 spu 信息 List spuList = spuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId)); @@ -101,7 +101,7 @@ public class AppSeckillActivityController { if (CollUtil.isEmpty(pageResult.getList())) { return success(PageResult.empty(pageResult.getTotal())); } - List productList = activityService.getSeckillProductListByActivityId( + List productList = activityService.getSeckillProductListByActivityIds( convertList(pageResult.getList(), SeckillActivityDO::getId)); // 2. 拼接数据 diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java index 10259cb69..eca4ae9b0 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.convert.seckill; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO; @@ -87,6 +88,22 @@ public interface SeckillActivityConvert { return CollectionUtils.convertList(products, item -> convert(activity, item).setActivityStatus(activity.getStatus())); } + default List convertList(List list, + List productList, + List spuList) { + List activityList = BeanUtils.toBean(list, SeckillActivityRespVO.class); + Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); + Map> productMap = convertMultiMap(productList, SeckillProductDO::getActivityId); + return CollectionUtils.convertList(activityList, item -> { + // 设置 product 信息 + item.setSeckillPrice(getMinValue(productMap.get(item.getId()), SeckillProductDO::getSeckillPrice)); + // 设置 SPU 信息 + findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); + return item; + }); + } + List convertList2(List list); List convertList3(List activityList); diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index a47bbec7c..65d20f87d 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -8,8 +8,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillActivityDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; - import jakarta.validation.Valid; + import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -98,7 +98,7 @@ public interface SeckillActivityService { * @param activityIds 活动编号 * @return 活动商品列表 */ - List getSeckillProductListByActivityId(Collection activityIds); + List getSeckillProductListByActivityIds(Collection activityIds); /** * 通过活动时段编号获取指定 status 的秒杀活动 @@ -139,4 +139,12 @@ public interface SeckillActivityService { */ List getSeckillActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime); + /** + * 获得拼团活动列表 + * + * @param ids 拼团活动 ids + * @return 拼团活动的列表 + */ + List getSeckillActivityListByIds(Collection ids); + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index dff4d7c7b..56e5135f7 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -23,11 +23,11 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillConfigDO; import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO; import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper; import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper; +import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; import java.time.LocalDateTime; import java.util.Collection; import java.util.Collections; @@ -276,7 +276,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { } @Override - public List getSeckillProductListByActivityId(Collection activityIds) { + public List getSeckillProductListByActivityIds(Collection activityIds) { return seckillProductMapper.selectListByActivityId(activityIds); } @@ -336,4 +336,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { convertSet(spuIdAndActivityIdMaps, map -> MapUtil.getLong(map, "activityId")), dateTime); } + @Override + public List getSeckillActivityListByIds(Collection ids) { + return seckillActivityMapper.selectList(SeckillActivityDO::getId, ids); + } + } From 19c4a5c9616f8598db2abb9552cce6e738bbee1a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 9 Sep 2024 09:16:56 +0800 Subject: [PATCH 16/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E7=A7=92=E6=9D=80?= =?UTF-8?q?=E8=A3=85=E4=BF=AE=E9=87=8D=E6=9E=84=EF=BC=88PC=E7=AB=AF?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/seckill/SeckillActivityController.java | 1 + .../admin/seckill/vo/activity/SeckillActivityRespVO.java | 1 - .../promotion/service/seckill/SeckillActivityService.java | 2 +- .../price/calculator/TradeRewardActivityPriceCalculator.java | 3 ++- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java index 0c41071e8..de90c0977 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/SeckillActivityController.java @@ -115,4 +115,5 @@ public class SeckillActivityController { List spuList = productSpuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId)); return success(SeckillActivityConvert.INSTANCE.convertList(activityList, productList, spuList)); } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java index b6a868585..18b2170e3 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/seckill/vo/activity/SeckillActivityRespVO.java @@ -57,5 +57,4 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO { @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") private Integer seckillPrice; // 从 products 获取最小 price 读取 - } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java index 65d20f87d..48b2a4264 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java @@ -142,7 +142,7 @@ public interface SeckillActivityService { /** * 获得拼团活动列表 * - * @param ids 拼团活动 ids + * @param ids 拼团活动编号数组 * @return 拼团活动的列表 */ List getSeckillActivityListByIds(Collection ids); diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java index 50d424c29..9abb69cd2 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; @@ -146,7 +147,7 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator return filterList(result.getItems(), orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getCategoryId())); } - return List.of(); + return ListUtil.of(); } /** From 8283f203dd174986d981b7a700f9ebcd56ae5f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A2=E8=B6=8A?= <552369664@qq.com> Date: Mon, 9 Sep 2024 13:37:52 +0800 Subject: [PATCH 17/22] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9Auni-app=E7=AB=AF?= =?UTF-8?q?=E7=A7=92=E6=9D=80=E5=88=97=E8=A1=A8=E7=9A=84=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seckill/AppSeckillActivityController.java | 18 ++++++++++++++++++ .../vo/activity/AppSeckillActivityRespVO.java | 3 +++ .../seckill/SeckillActivityConvert.java | 16 ++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java index 62627a203..6105f9516 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java @@ -35,6 +35,7 @@ import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -149,4 +150,21 @@ public class AppSeckillActivityController { return success(SeckillActivityConvert.INSTANCE.convert3(activity, productList, startTime, endTime)); } + @GetMapping("/list-by-ids") + @Operation(summary = "获得拼团活动列表,基于活动编号数组") + @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]") + public CommonResult> getCombinationActivityListByIds(@RequestParam("ids") List ids) { + // 1. 获得开启的活动列表 + List activityList = activityService.getSeckillActivityListByIds(ids); + activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus())); + if (CollUtil.isEmpty(activityList)) { + return success(Collections.emptyList()); + } + // 2. 拼接返回 + List productList = activityService.getSeckillProductListByActivityIds( + convertList(activityList, SeckillActivityDO::getId)); + List spuList = spuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId)); + return success(SeckillActivityConvert.INSTANCE.convertAppList(activityList, productList, spuList)); + } + } diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java index 68e7ff829..907a3ce08 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java @@ -16,6 +16,9 @@ public class AppSeckillActivityRespVO { @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") private Long spuId; + @Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "一个白菜") + private String spuName; // 从 SPU 的 name 读取 + @Schema(description = "商品图片", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 picUrl 读取 example = "https://www.iocoder.cn/xx.png") private String picUrl; diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java index eca4ae9b0..5c3277d0e 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/SeckillActivityConvert.java @@ -104,6 +104,22 @@ public interface SeckillActivityConvert { }); } + default List convertAppList(List list, + List productList, + List spuList) { + List activityList = BeanUtils.toBean(list, AppSeckillActivityRespVO.class); + Map spuMap = convertMap(spuList, ProductSpuRespDTO::getId); + Map> productMap = convertMultiMap(productList, SeckillProductDO::getActivityId); + return CollectionUtils.convertList(activityList, item -> { + // 设置 product 信息 + item.setSeckillPrice(getMinValue(productMap.get(item.getId()), SeckillProductDO::getSeckillPrice)); + // 设置 SPU 信息 + findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()) + .setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); + return item; + }); + } + List convertList2(List list); List convertList3(List activityList); From e5dcf0f1cd5e9abd1e8892297b40b2e4460e7825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=AE=87=E5=BA=86?= Date: Wed, 11 Sep 2024 06:37:44 +0000 Subject: [PATCH 18/22] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=8D=95=E4=BB=B7=E6=A0=BC=E7=9A=84=E6=A3=80?= =?UTF-8?q?=E8=A7=86=E6=84=8F=E8=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 杨宇庆 --- .../yudao/module/pay/service/order/PayOrderServiceImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java index 31c1f8b55..1111daa26 100755 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java @@ -431,9 +431,7 @@ public class PayOrderServiceImpl implements PayOrderService { return; } - // TODO 芋艿:应该 new 出来更新 - order.setPrice(payPrice); - orderMapper.updateById(order); + orderMapper.updateById(new PayOrderDO().setId(order.getId()).setPrice(payPrice)); } @Override From d8d385e489f3ee87a76fd5ace123fc7bad4a56ed Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 12 Sep 2024 13:39:19 +0800 Subject: [PATCH 19/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E5=9C=A8?= =?UTF-8?q?=E5=A4=9A=E7=A7=9F=E6=88=B7=E4=B8=8B=EF=BC=8C=E6=B2=A1=E6=9C=89?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=89=A7=E8=A1=8C=E7=9A=84=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E7=BB=93=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/tenant/core/job/TenantJobAspect.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java index ce9eb1631..de409a4a3 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/job/TenantJobAspect.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.tenant.core.job; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.exceptions.ExceptionUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; @@ -44,7 +45,8 @@ public class TenantJobAspect { // TODO 芋艿:先通过 parallel 实现并行;1)多个租户,是一条执行日志;2)异常的情况 TenantUtils.execute(tenantId, () -> { try { - joinPoint.proceed(); + Object result = joinPoint.proceed(); + results.put(tenantId, StrUtil.toStringOrNull(result)); } catch (Throwable e) { log.error("[execute][租户({}) 执行 Job 发生异常", tenantId, e); results.put(tenantId, ExceptionUtil.getRootCauseMessage(e)); From c71182dda98cdb1993cf9d439cf12ff3f58a485b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 12 Sep 2024 13:44:13 +0800 Subject: [PATCH 20/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E7=9A=84?= =?UTF-8?q?=20Bean=20=E4=B8=8D=E5=AD=98=E5=9C=A8=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E6=8A=A5=E9=94=99=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/infra/enums/ErrorCodeConstants.java | 2 +- .../module/infra/service/job/JobServiceImpl.java | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java index e9f39a81f..4cce820b7 100644 --- a/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java +++ b/yudao-module-infra/yudao-module-infra-api/src/main/java/cn/iocoder/yudao/module/infra/enums/ErrorCodeConstants.java @@ -22,7 +22,7 @@ public interface ErrorCodeConstants { ErrorCode JOB_CHANGE_STATUS_EQUALS = new ErrorCode(1_001_001_003, "定时任务已经处于该状态,无需修改"); ErrorCode JOB_UPDATE_ONLY_NORMAL_STATUS = new ErrorCode(1_001_001_004, "只有开启状态的任务,才可以修改"); ErrorCode JOB_CRON_EXPRESSION_VALID = new ErrorCode(1_001_001_005, "CRON 表达式不正确"); - ErrorCode JOB_HANDLER_BEAN_NOT_EXISTS = new ErrorCode(1_001_001_006, "定时任务的处理器 Bean 不存在"); + ErrorCode JOB_HANDLER_BEAN_NOT_EXISTS = new ErrorCode(1_001_001_006, "定时任务的处理器 Bean 不存在,注意 Bean 默认首字母小写"); ErrorCode JOB_HANDLER_BEAN_TYPE_ERROR = new ErrorCode(1_001_001_007, "定时任务的处理器 Bean 类型不正确,未实现 JobHandler 接口"); // ========== API 错误日志 1-001-002-000 ========== diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java index cfc52d29d..2ebf06619 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/job/JobServiceImpl.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.infra.enums.job.JobStatusEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.quartz.SchedulerException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -91,13 +92,15 @@ public class JobServiceImpl implements JobService { } private void validateJobHandlerExists(String handlerName) { - Object handler = SpringUtil.getBean(handlerName); - if (handler == null) { + try { + Object handler = SpringUtil.getBean(handlerName); + assert handler != null; + if (!(handler instanceof JobHandler)) { + throw exception(JOB_HANDLER_BEAN_TYPE_ERROR); + } + } catch (NoSuchBeanDefinitionException e) { throw exception(JOB_HANDLER_BEAN_NOT_EXISTS); } - if (!(handler instanceof JobHandler)) { - throw exception(JOB_HANDLER_BEAN_TYPE_ERROR); - } } @Override From 01660355ccabee1f50ba376d1dc0cc2ba30c0775 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 12 Sep 2024 13:59:42 +0800 Subject: [PATCH 21/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91websocket=20=E5=85=81=E8=AE=B8=E4=B8=8D?= =?UTF-8?q?=E4=BC=A0=E9=80=92=20token=20=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../websocket/config/YudaoWebSocketAutoConfiguration.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java index 0f08b7cf5..cabceb807 100644 --- a/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/config/YudaoWebSocketAutoConfiguration.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mq.redis.core.RedisMQTemplate; import cn.iocoder.yudao.framework.websocket.core.handler.JsonWebSocketMessageHandler; import cn.iocoder.yudao.framework.websocket.core.listener.WebSocketMessageListener; import cn.iocoder.yudao.framework.websocket.core.security.LoginUserHandshakeInterceptor; +import cn.iocoder.yudao.framework.websocket.core.security.WebSocketAuthorizeRequestsCustomizer; import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageConsumer; import cn.iocoder.yudao.framework.websocket.core.sender.kafka.KafkaWebSocketMessageSender; import cn.iocoder.yudao.framework.websocket.core.sender.local.LocalWebSocketMessageSender; @@ -76,6 +77,11 @@ public class YudaoWebSocketAutoConfiguration { return new WebSocketSessionManagerImpl(); } + @Bean + public WebSocketAuthorizeRequestsCustomizer webSocketAuthorizeRequestsCustomizer(WebSocketProperties webSocketProperties) { + return new WebSocketAuthorizeRequestsCustomizer(webSocketProperties); + } + // ==================== Sender 相关 ==================== @Configuration From 57a562b8e3dbdb1107d66f0bf381db858eddac04 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 12 Sep 2024 19:39:29 +0800 Subject: [PATCH 22/22] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E6=94=AF=E4=BB=98=EF=BC=9A=E5=8F=91=E8=B5=B7?= =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E9=80=80=E6=AC=BE=E8=B0=83=E7=94=A8=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E6=97=B6=EF=BC=8C=E8=AE=BE=E7=BD=AE=E7=9A=84=20outNo?= =?UTF-8?q?=20=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pay/core/client/impl/weixin/AbstractWxPayClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java index 36c305553..298e314d8 100644 --- a/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java +++ b/yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java @@ -266,7 +266,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient