Commit f7296d18b90ee68d9ba120c7d09b5a2b20098ed7
Merge remote-tracking branch 'origin/feature/mall_product' into brokerate
# Conflicts: # yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java # yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java # yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java
Showing
73 changed files
with
908 additions
and
420 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
| @@ -43,17 +43,6 @@ public class LocalDateTimeUtils { | @@ -43,17 +43,6 @@ public class LocalDateTimeUtils { | ||
| 43 | return LocalDateTime.of(year, mouth, day, 0, 0, 0); | 43 | return LocalDateTime.of(year, mouth, day, 0, 0, 0); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | - /** | ||
| 47 | - * 创建指定时间 | ||
| 48 | - * | ||
| 49 | - * @param timeStr 时间字符串 | ||
| 50 | - * @return 指定时间 | ||
| 51 | - */ | ||
| 52 | - public static LocalDateTime buildTime(String timeStr) { | ||
| 53 | - // TODO @puhui999:这个方法的实现,和 LocalDateTimeUtil.parse() 的差异点是啥呀 | ||
| 54 | - return LocalDateTime.of(LocalDate.now(), LocalTime.parse(timeStr)); | ||
| 55 | - } | ||
| 56 | - | ||
| 57 | public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1, | 46 | public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1, |
| 58 | int year2, int mouth2, int day2) { | 47 | int year2, int mouth2, int day2) { |
| 59 | return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)}; | 48 | return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)}; |
yudao-module-mall/yudao-module-product-biz/pom.xml
| @@ -23,12 +23,6 @@ | @@ -23,12 +23,6 @@ | ||
| 23 | <artifactId>yudao-module-product-api</artifactId> | 23 | <artifactId>yudao-module-product-api</artifactId> |
| 24 | <version>${revision}</version> | 24 | <version>${revision}</version> |
| 25 | </dependency> | 25 | </dependency> |
| 26 | - <!-- TODO 芋艿:看看~~~ --> | ||
| 27 | - <dependency> | ||
| 28 | - <groupId>cn.iocoder.boot</groupId> | ||
| 29 | - <artifactId>yudao-module-trade-api</artifactId> | ||
| 30 | - <version>${revision}</version> | ||
| 31 | - </dependency> | ||
| 32 | <dependency> | 26 | <dependency> |
| 33 | <groupId>cn.iocoder.boot</groupId> | 27 | <groupId>cn.iocoder.boot</groupId> |
| 34 | <artifactId>yudao-module-member-api</artifactId> | 28 | <artifactId>yudao-module-member-api</artifactId> |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/api/property/ProductPropertyValueApiImpl.java
| 1 | package cn.iocoder.yudao.module.product.api.property; | 1 | package cn.iocoder.yudao.module.product.api.property; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; | 3 | import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; |
| 4 | -import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; | 4 | +import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert; |
| 5 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; | 5 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; |
| 6 | import org.springframework.stereotype.Service; | 6 | import org.springframework.stereotype.Service; |
| 7 | import org.springframework.validation.annotation.Validated; | 7 | import org.springframework.validation.annotation.Validated; |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/property/ProductPropertyValueController.java
| 1 | package cn.iocoder.yudao.module.product.controller.admin.property; | 1 | package cn.iocoder.yudao.module.product.controller.admin.property; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.collection.CollectionUtil; | ||
| 4 | -import cn.hutool.crypto.symmetric.AES; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; | 5 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; |
| 8 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; | 6 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; |
| 9 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; | 7 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; |
| 10 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; | 8 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; |
| 11 | -import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; | 9 | +import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert; |
| 12 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; | 10 | import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; |
| 13 | import io.swagger.v3.oas.annotations.Operation; | 11 | import io.swagger.v3.oas.annotations.Operation; |
| 14 | import io.swagger.v3.oas.annotations.Parameter; | 12 | import io.swagger.v3.oas.annotations.Parameter; |
| @@ -20,9 +18,6 @@ import org.springframework.web.bind.annotation.*; | @@ -20,9 +18,6 @@ import org.springframework.web.bind.annotation.*; | ||
| 20 | import javax.annotation.Resource; | 18 | import javax.annotation.Resource; |
| 21 | import javax.validation.Valid; | 19 | import javax.validation.Valid; |
| 22 | 20 | ||
| 23 | -import java.util.Arrays; | ||
| 24 | -import java.util.List; | ||
| 25 | - | ||
| 26 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 21 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 27 | 22 | ||
| 28 | @Tag(name = "管理后台 - 商品属性值") | 23 | @Tag(name = "管理后台 - 商品属性值") |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
| 1 | package cn.iocoder.yudao.module.product.controller.app.spu; | 1 | package cn.iocoder.yudao.module.product.controller.app.spu; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | +import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; | ||
| 7 | +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; | ||
| 8 | +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||
| 9 | +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | ||
| 5 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; | 10 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; |
| 6 | -import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRespVO; | ||
| 7 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; | 11 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; |
| 12 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRespVO; | ||
| 8 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | 13 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; |
| 9 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | 14 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 10 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | 15 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| @@ -23,10 +28,12 @@ import org.springframework.web.bind.annotation.RestController; | @@ -23,10 +28,12 @@ import org.springframework.web.bind.annotation.RestController; | ||
| 23 | 28 | ||
| 24 | import javax.annotation.Resource; | 29 | import javax.annotation.Resource; |
| 25 | import javax.validation.Valid; | 30 | import javax.validation.Valid; |
| 31 | +import java.util.Collections; | ||
| 26 | import java.util.List; | 32 | import java.util.List; |
| 27 | 33 | ||
| 28 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 34 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 29 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 35 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 36 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | ||
| 30 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE; | 37 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_ENABLE; |
| 31 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; | 38 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; |
| 32 | 39 | ||
| @@ -41,6 +48,11 @@ public class AppProductSpuController { | @@ -41,6 +48,11 @@ public class AppProductSpuController { | ||
| 41 | @Resource | 48 | @Resource |
| 42 | private ProductSkuService productSkuService; | 49 | private ProductSkuService productSkuService; |
| 43 | 50 | ||
| 51 | + @Resource | ||
| 52 | + private MemberLevelApi memberLevelApi; | ||
| 53 | + @Resource | ||
| 54 | + private MemberUserApi memberUserApi; | ||
| 55 | + | ||
| 44 | @GetMapping("/list") | 56 | @GetMapping("/list") |
| 45 | @Operation(summary = "获得商品 SPU 列表") | 57 | @Operation(summary = "获得商品 SPU 列表") |
| 46 | @Parameters({ | 58 | @Parameters({ |
| @@ -51,14 +63,32 @@ public class AppProductSpuController { | @@ -51,14 +63,32 @@ public class AppProductSpuController { | ||
| 51 | @RequestParam("recommendType") String recommendType, | 63 | @RequestParam("recommendType") String recommendType, |
| 52 | @RequestParam(value = "count", defaultValue = "10") Integer count) { | 64 | @RequestParam(value = "count", defaultValue = "10") Integer count) { |
| 53 | List<ProductSpuDO> list = productSpuService.getSpuList(recommendType, count); | 65 | List<ProductSpuDO> list = productSpuService.getSpuList(recommendType, count); |
| 54 | - return success(ProductSpuConvert.INSTANCE.convertListForGetSpuList(list)); | 66 | + if (CollUtil.isEmpty(list)) { |
| 67 | + return success(Collections.emptyList()); | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + // 拼接返回 | ||
| 71 | + List<AppProductSpuPageRespVO> voList = ProductSpuConvert.INSTANCE.convertListForGetSpuList(list); | ||
| 72 | + // 处理 vip 价格 | ||
| 73 | + MemberLevelRespDTO memberLevel = getMemberLevel(); | ||
| 74 | + voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel))); | ||
| 75 | + return success(voList); | ||
| 55 | } | 76 | } |
| 56 | 77 | ||
| 57 | @GetMapping("/page") | 78 | @GetMapping("/page") |
| 58 | @Operation(summary = "获得商品 SPU 分页") | 79 | @Operation(summary = "获得商品 SPU 分页") |
| 59 | public CommonResult<PageResult<AppProductSpuPageRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) { | 80 | public CommonResult<PageResult<AppProductSpuPageRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) { |
| 60 | PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO); | 81 | PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO); |
| 61 | - return success(ProductSpuConvert.INSTANCE.convertPageForGetSpuPage(pageResult)); | 82 | + if (CollUtil.isEmpty(pageResult.getList())) { |
| 83 | + return success(PageResult.empty(pageResult.getTotal())); | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + // 拼接返回 | ||
| 87 | + PageResult<AppProductSpuPageRespVO> voPageResult = ProductSpuConvert.INSTANCE.convertPageForGetSpuPage(pageResult); | ||
| 88 | + // 处理 vip 价格 | ||
| 89 | + MemberLevelRespDTO memberLevel = getMemberLevel(); | ||
| 90 | + voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel))); | ||
| 91 | + return success(voPageResult); | ||
| 62 | } | 92 | } |
| 63 | 93 | ||
| 64 | @GetMapping("/get-detail") | 94 | @GetMapping("/get-detail") |
| @@ -74,10 +104,40 @@ public class AppProductSpuController { | @@ -74,10 +104,40 @@ public class AppProductSpuController { | ||
| 74 | throw exception(SPU_NOT_ENABLE); | 104 | throw exception(SPU_NOT_ENABLE); |
| 75 | } | 105 | } |
| 76 | 106 | ||
| 77 | - // 查询商品 SKU | 107 | + // 拼接返回 |
| 78 | List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId()); | 108 | List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId()); |
| 79 | - // 拼接 | ||
| 80 | - return success(ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus)); | 109 | + AppProductSpuDetailRespVO detailVO = ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus); |
| 110 | + // 处理 vip 价格 | ||
| 111 | + MemberLevelRespDTO memberLevel = getMemberLevel(); | ||
| 112 | + detailVO.setVipPrice(calculateVipPrice(detailVO.getPrice(), memberLevel)); | ||
| 113 | + return success(detailVO); | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + private MemberLevelRespDTO getMemberLevel() { | ||
| 117 | + Long userId = getLoginUserId(); | ||
| 118 | + if (userId == null) { | ||
| 119 | + return null; | ||
| 120 | + } | ||
| 121 | + MemberUserRespDTO user = memberUserApi.getUser(userId); | ||
| 122 | + if (user.getLevelId() == null || user.getLevelId() <= 0) { | ||
| 123 | + return null; | ||
| 124 | + } | ||
| 125 | + return memberLevelApi.getMemberLevel(user.getLevelId()); | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + /** | ||
| 129 | + * 计算会员 VIP 优惠价格 | ||
| 130 | + * | ||
| 131 | + * @param price 原价 | ||
| 132 | + * @param memberLevel 会员等级 | ||
| 133 | + * @return 优惠价格 | ||
| 134 | + */ | ||
| 135 | + public Integer calculateVipPrice(Integer price, MemberLevelRespDTO memberLevel) { | ||
| 136 | + if (memberLevel == null || memberLevel.getDiscountPercent() == null) { | ||
| 137 | + return 0; | ||
| 138 | + } | ||
| 139 | + Integer newPrice = price * memberLevel.getDiscountPercent() / 100; | ||
| 140 | + return price - newPrice; | ||
| 81 | } | 141 | } |
| 82 | 142 | ||
| 83 | } | 143 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/propertyvalue/ProductPropertyValueConvert.java renamed to yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/property/ProductPropertyValueConvert.java
| 1 | -package cn.iocoder.yudao.module.product.convert.propertyvalue; | 1 | +package cn.iocoder.yudao.module.product.convert.property; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 4 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/spu/ProductSpuConvert.java
| @@ -79,8 +79,6 @@ public interface ProductSpuConvert { | @@ -79,8 +79,6 @@ public interface ProductSpuConvert { | ||
| 79 | ProductSpuDO spu = list.get(i); | 79 | ProductSpuDO spu = list.get(i); |
| 80 | AppProductSpuPageRespVO spuVO = voList.get(i); | 80 | AppProductSpuPageRespVO spuVO = voList.get(i); |
| 81 | spuVO.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())); | 81 | spuVO.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())); |
| 82 | - // 计算 vip 价格 TODO 芋艿:临时的逻辑,等 vip 支持后 | ||
| 83 | - spuVO.setVipPrice((int) (spuVO.getPrice() * 0.9)); | ||
| 84 | } | 82 | } |
| 85 | return voList; | 83 | return voList; |
| 86 | } | 84 | } |
| @@ -95,11 +93,6 @@ public interface ProductSpuConvert { | @@ -95,11 +93,6 @@ public interface ProductSpuConvert { | ||
| 95 | .setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())); | 93 | .setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())); |
| 96 | // 处理 SKU | 94 | // 处理 SKU |
| 97 | spuVO.setSkus(convertListForGetSpuDetail(skus)); | 95 | spuVO.setSkus(convertListForGetSpuDetail(skus)); |
| 98 | - // 计算 vip 价格 TODO 芋艿:临时的逻辑,等 vip 支持后 | ||
| 99 | - if (true) { | ||
| 100 | - spuVO.setVipPrice((int) (spuVO.getPrice() * 0.9)); | ||
| 101 | - spuVO.getSkus().forEach(sku -> sku.setVipPrice((int) (sku.getPrice() * 0.9))); | ||
| 102 | - } | ||
| 103 | return spuVO; | 96 | return spuVO; |
| 104 | } | 97 | } |
| 105 | 98 |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/package-info.java
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
| @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; | 5 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO; |
| 6 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; | 6 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO; |
| 7 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; | 7 | import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO; |
| 8 | -import cn.iocoder.yudao.module.product.convert.propertyvalue.ProductPropertyValueConvert; | 8 | +import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert; |
| 9 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; | 9 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; |
| 10 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; | 10 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; |
| 11 | import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; | 11 | import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper; |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/bargain/BargainActivityApi.java
| @@ -11,7 +11,7 @@ public interface BargainActivityApi { | @@ -11,7 +11,7 @@ public interface BargainActivityApi { | ||
| 11 | * 更新砍价活动库存 | 11 | * 更新砍价活动库存 |
| 12 | * | 12 | * |
| 13 | * @param id 砍价活动编号 | 13 | * @param id 砍价活动编号 |
| 14 | - * @param count 购买数量 | 14 | + * @param count 购买数量 |
| 15 | */ | 15 | */ |
| 16 | void updateBargainActivityStock(Long id, Integer count); | 16 | void updateBargainActivityStock(Long id, Integer count); |
| 17 | 17 |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApi.java
| @@ -7,14 +7,13 @@ package cn.iocoder.yudao.module.promotion.api.seckill; | @@ -7,14 +7,13 @@ package cn.iocoder.yudao.module.promotion.api.seckill; | ||
| 7 | */ | 7 | */ |
| 8 | public interface SeckillActivityApi { | 8 | public interface SeckillActivityApi { |
| 9 | 9 | ||
| 10 | - // TODO @puhui999:activityId 改成 id 好点哈; | ||
| 11 | /** | 10 | /** |
| 12 | * 更新秒杀库存 | 11 | * 更新秒杀库存 |
| 13 | * | 12 | * |
| 14 | - * @param activityId 活动编号 | 13 | + * @param id 活动编号 |
| 15 | * @param skuId sku 编号 | 14 | * @param skuId sku 编号 |
| 16 | * @param count 数量 | 15 | * @param count 数量 |
| 17 | */ | 16 | */ |
| 18 | - void updateSeckillStock(Long activityId, Long skuId, Integer count); | 17 | + void updateSeckillStock(Long id, Long skuId, Integer count); |
| 19 | 18 | ||
| 20 | } | 19 | } |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
| @@ -56,7 +56,6 @@ public interface ErrorCodeConstants { | @@ -56,7 +56,6 @@ public interface ErrorCodeConstants { | ||
| 56 | ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); | 56 | ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除"); |
| 57 | ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); | 57 | ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭"); |
| 58 | ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足"); | 58 | ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足"); |
| 59 | - ErrorCode SECKILL_ACTIVITY_FAIL_STATUS_CLOSED = new ErrorCode(1013008007, "秒杀活动已关闭"); | ||
| 60 | 59 | ||
| 61 | // ========== 秒杀时段 1013009000 ========== | 60 | // ========== 秒杀时段 1013009000 ========== |
| 62 | ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); | 61 | ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在"); |
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/common/PromotionTypeEnum.java
| @@ -22,7 +22,7 @@ public enum PromotionTypeEnum implements IntArrayValuable { | @@ -22,7 +22,7 @@ public enum PromotionTypeEnum implements IntArrayValuable { | ||
| 22 | DISCOUNT_ACTIVITY(4, "限时折扣"), | 22 | DISCOUNT_ACTIVITY(4, "限时折扣"), |
| 23 | REWARD_ACTIVITY(5, "满减送"), | 23 | REWARD_ACTIVITY(5, "满减送"), |
| 24 | 24 | ||
| 25 | - MEMBER(6, "会员折扣"), | 25 | + MEMBER_LEVEL(6, "会员折扣"), |
| 26 | COUPON(7, "优惠劵"), | 26 | COUPON(7, "优惠劵"), |
| 27 | POINT(8, "积分") | 27 | POINT(8, "积分") |
| 28 | ; | 28 | ; |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/seckill/SeckillActivityApiImpl.java
| @@ -17,8 +17,8 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { | @@ -17,8 +17,8 @@ public class SeckillActivityApiImpl implements SeckillActivityApi { | ||
| 17 | private SeckillActivityService activityService; | 17 | private SeckillActivityService activityService; |
| 18 | 18 | ||
| 19 | @Override | 19 | @Override |
| 20 | - public void updateSeckillStock(Long activityId, Long skuId, Integer count) { | ||
| 21 | - activityService.updateSeckillStock(activityId, skuId, count); | 20 | + public void updateSeckillStock(Long id, Long skuId, Integer count) { |
| 21 | + activityService.updateSeckillStock(id, skuId, count); | ||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | } | 24 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/bargain/AppBargainActivityController.java
| @@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController; | @@ -23,6 +23,7 @@ import org.springframework.web.bind.annotation.RestController; | ||
| 23 | import javax.annotation.Resource; | 23 | import javax.annotation.Resource; |
| 24 | import java.util.List; | 24 | import java.util.List; |
| 25 | 25 | ||
| 26 | +import static cn.hutool.core.util.ObjectUtil.defaultIfNull; | ||
| 26 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 27 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 27 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 28 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 28 | 29 | ||
| @@ -39,7 +40,7 @@ public class AppBargainActivityController { | @@ -39,7 +40,7 @@ public class AppBargainActivityController { | ||
| 39 | @GetMapping("/page") | 40 | @GetMapping("/page") |
| 40 | @Operation(summary = "获得砍价活动分页") | 41 | @Operation(summary = "获得砍价活动分页") |
| 41 | public CommonResult<PageResult<AppBargainActivityRespVO>> getBargainActivityPage(PageParam pageReqVO) { | 42 | public CommonResult<PageResult<AppBargainActivityRespVO>> getBargainActivityPage(PageParam pageReqVO) { |
| 42 | - PageResult<BargainActivityDO> result = bargainActivityService.getBargainActivityPageForApp(pageReqVO); | 43 | + PageResult<BargainActivityDO> result = bargainActivityService.getBargainActivityPage(pageReqVO); |
| 43 | if (CollUtil.isEmpty(result.getList())) { | 44 | if (CollUtil.isEmpty(result.getList())) { |
| 44 | return success(PageResult.empty(result.getTotal())); | 45 | return success(PageResult.empty(result.getTotal())); |
| 45 | } | 46 | } |
| @@ -54,7 +55,7 @@ public class AppBargainActivityController { | @@ -54,7 +55,7 @@ public class AppBargainActivityController { | ||
| 54 | @Parameter(name = "count", description = "需要展示的数量", example = "6") | 55 | @Parameter(name = "count", description = "需要展示的数量", example = "6") |
| 55 | public CommonResult<List<AppBargainActivityRespVO>> getBargainActivityList( | 56 | public CommonResult<List<AppBargainActivityRespVO>> getBargainActivityList( |
| 56 | @RequestParam(name = "count", defaultValue = "6") Integer count) { | 57 | @RequestParam(name = "count", defaultValue = "6") Integer count) { |
| 57 | - List<BargainActivityDO> list = bargainActivityService.getBargainActivityListForApp(count); | 58 | + List<BargainActivityDO> list = bargainActivityService.getBargainActivityListByCount(defaultIfNull(count, 6)); |
| 58 | if (CollUtil.isEmpty(list)) { | 59 | if (CollUtil.isEmpty(list)) { |
| 59 | return success(BargainActivityConvert.INSTANCE.convertAppList(list)); | 60 | return success(BargainActivityConvert.INSTANCE.convertAppList(list)); |
| 60 | } | 61 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/AppCombinationActivityController.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.app.combination; | 1 | package cn.iocoder.yudao.module.promotion.controller.app.combination; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 4 | +import cn.hutool.core.util.ObjectUtil; | ||
| 5 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageParam; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | ||
| 10 | +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | ||
| 6 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO; | 11 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO; |
| 7 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO; | 12 | import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO; |
| 13 | +import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert; | ||
| 14 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; | ||
| 15 | +import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; | ||
| 16 | +import cn.iocoder.yudao.module.promotion.service.combination.CombinationActivityService; | ||
| 8 | import io.swagger.v3.oas.annotations.Operation; | 17 | import io.swagger.v3.oas.annotations.Operation; |
| 9 | import io.swagger.v3.oas.annotations.Parameter; | 18 | import io.swagger.v3.oas.annotations.Parameter; |
| 10 | import io.swagger.v3.oas.annotations.tags.Tag; | 19 | import io.swagger.v3.oas.annotations.tags.Tag; |
| @@ -14,11 +23,13 @@ import org.springframework.web.bind.annotation.RequestMapping; | @@ -14,11 +23,13 @@ import org.springframework.web.bind.annotation.RequestMapping; | ||
| 14 | import org.springframework.web.bind.annotation.RequestParam; | 23 | import org.springframework.web.bind.annotation.RequestParam; |
| 15 | import org.springframework.web.bind.annotation.RestController; | 24 | import org.springframework.web.bind.annotation.RestController; |
| 16 | 25 | ||
| 17 | -import java.time.LocalDateTime; | ||
| 18 | -import java.util.ArrayList; | 26 | +import javax.annotation.Resource; |
| 27 | +import java.util.Collections; | ||
| 19 | import java.util.List; | 28 | import java.util.List; |
| 20 | 29 | ||
| 30 | +import static cn.hutool.core.util.ObjectUtil.defaultIfNull; | ||
| 21 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 31 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 32 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 22 | 33 | ||
| 23 | @Tag(name = "用户 APP - 拼团活动") | 34 | @Tag(name = "用户 APP - 拼团活动") |
| 24 | @RestController | 35 | @RestController |
| @@ -26,104 +37,51 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | @@ -26,104 +37,51 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | ||
| 26 | @Validated | 37 | @Validated |
| 27 | public class AppCombinationActivityController { | 38 | public class AppCombinationActivityController { |
| 28 | 39 | ||
| 40 | + @Resource | ||
| 41 | + private CombinationActivityService activityService; | ||
| 42 | + @Resource | ||
| 43 | + private ProductSpuApi spuApi; | ||
| 44 | + | ||
| 45 | + // TODO 芋艿:增加 Spring Cache | ||
| 29 | @GetMapping("/list") | 46 | @GetMapping("/list") |
| 30 | @Operation(summary = "获得拼团活动列表", description = "用于小程序首页") | 47 | @Operation(summary = "获得拼团活动列表", description = "用于小程序首页") |
| 31 | - // TODO 芋艿:增加 Spring Cache | ||
| 32 | - // TODO 芋艿:缺少 swagger 注解 | 48 | + @Parameter(name = "count", description = "需要展示的数量", example = "6") |
| 33 | public CommonResult<List<AppCombinationActivityRespVO>> getCombinationActivityList( | 49 | public CommonResult<List<AppCombinationActivityRespVO>> getCombinationActivityList( |
| 34 | @RequestParam(name = "count", defaultValue = "6") Integer count) { | 50 | @RequestParam(name = "count", defaultValue = "6") Integer count) { |
| 35 | - List<AppCombinationActivityRespVO> activityList = new ArrayList<>(); | ||
| 36 | - AppCombinationActivityRespVO activity1 = new AppCombinationActivityRespVO(); | ||
| 37 | - activity1.setId(1L); | ||
| 38 | - activity1.setName("618 大拼团"); | ||
| 39 | - activity1.setUserSize(3); | ||
| 40 | - activity1.setSpuId(2048L); | ||
| 41 | - activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg"); | ||
| 42 | - activity1.setMarketPrice(50); | ||
| 43 | - activity1.setCombinationPrice(100); | ||
| 44 | - activityList.add(activity1); | ||
| 45 | - | ||
| 46 | - AppCombinationActivityRespVO activity2 = new AppCombinationActivityRespVO(); | ||
| 47 | - activity2.setId(2L); | ||
| 48 | - activity2.setName("双十一拼团"); | ||
| 49 | - activity2.setUserSize(5); | ||
| 50 | - activity2.setSpuId(4096L); | ||
| 51 | - activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg"); | ||
| 52 | - activity2.setMarketPrice(100); | ||
| 53 | - activity2.setCombinationPrice(200); | ||
| 54 | - activityList.add(activity2); | ||
| 55 | - | ||
| 56 | - return success(activityList); | 51 | + List<CombinationActivityDO> list = activityService.getCombinationActivityListByCount(defaultIfNull(count, 6)); |
| 52 | + if (CollUtil.isEmpty(list)) { | ||
| 53 | + return success(Collections.emptyList()); | ||
| 54 | + } | ||
| 55 | + // 拼接返回 | ||
| 56 | + List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(list, CombinationActivityDO::getSpuId)); | ||
| 57 | + return success(CombinationActivityConvert.INSTANCE.convertAppList(list, spuList)); | ||
| 57 | } | 58 | } |
| 58 | 59 | ||
| 59 | @GetMapping("/page") | 60 | @GetMapping("/page") |
| 60 | @Operation(summary = "获得拼团活动分页") | 61 | @Operation(summary = "获得拼团活动分页") |
| 61 | public CommonResult<PageResult<AppCombinationActivityRespVO>> getCombinationActivityPage(PageParam pageParam) { | 62 | public CommonResult<PageResult<AppCombinationActivityRespVO>> getCombinationActivityPage(PageParam pageParam) { |
| 62 | - List<AppCombinationActivityRespVO> activityList = new ArrayList<>(); | ||
| 63 | - AppCombinationActivityRespVO activity1 = new AppCombinationActivityRespVO(); | ||
| 64 | - activity1.setId(1L); | ||
| 65 | - activity1.setName("618 大拼团"); | ||
| 66 | - activity1.setUserSize(3); | ||
| 67 | - activity1.setSpuId(2048L); | ||
| 68 | - activity1.setPicUrl("商品图片地址"); | ||
| 69 | - activity1.setMarketPrice(50); | ||
| 70 | - activity1.setCombinationPrice(100); | ||
| 71 | - activityList.add(activity1); | ||
| 72 | - | ||
| 73 | - AppCombinationActivityRespVO activity2 = new AppCombinationActivityRespVO(); | ||
| 74 | - activity2.setId(2L); | ||
| 75 | - activity2.setName("双十一拼团"); | ||
| 76 | - activity2.setUserSize(5); | ||
| 77 | - activity2.setSpuId(4096L); | ||
| 78 | - activity2.setPicUrl("商品图片地址"); | ||
| 79 | - activity2.setMarketPrice(100); | ||
| 80 | - activity2.setCombinationPrice(200); | ||
| 81 | - activityList.add(activity2); | ||
| 82 | - | ||
| 83 | - return success(new PageResult<>(activityList, 2L)); | 63 | + PageResult<CombinationActivityDO> result = activityService.getCombinationActivityPage(pageParam); |
| 64 | + if (CollUtil.isEmpty(result.getList())) { | ||
| 65 | + return success(PageResult.empty(result.getTotal())); | ||
| 66 | + } | ||
| 67 | + // 拼接返回 | ||
| 68 | + List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(result.getList(), CombinationActivityDO::getSpuId)); | ||
| 69 | + return success(CombinationActivityConvert.INSTANCE.convertAppPage(result, spuList)); | ||
| 84 | } | 70 | } |
| 85 | 71 | ||
| 86 | @GetMapping("/get-detail") | 72 | @GetMapping("/get-detail") |
| 87 | @Operation(summary = "获得拼团活动明细") | 73 | @Operation(summary = "获得拼团活动明细") |
| 88 | @Parameter(name = "id", description = "活动编号", required = true, example = "1024") | 74 | @Parameter(name = "id", description = "活动编号", required = true, example = "1024") |
| 89 | public CommonResult<AppCombinationActivityDetailRespVO> getCombinationActivityDetail(@RequestParam("id") Long id) { | 75 | public CommonResult<AppCombinationActivityDetailRespVO> getCombinationActivityDetail(@RequestParam("id") Long id) { |
| 90 | - // TODO 芋艿:如果禁用的时候,需要抛出异常; | ||
| 91 | - AppCombinationActivityDetailRespVO obj = new AppCombinationActivityDetailRespVO(); | ||
| 92 | - // 设置其属性的值 | ||
| 93 | - obj.setId(id); | ||
| 94 | - obj.setName("晚九点限时秒杀"); | ||
| 95 | - obj.setStatus(1); | ||
| 96 | - obj.setStartTime(LocalDateTime.of(2023, 6, 15, 0, 0, 0)); | ||
| 97 | - obj.setEndTime(LocalDateTime.of(2023, 6, 20, 23, 59, 0)); | ||
| 98 | - obj.setUserSize(2); | ||
| 99 | - obj.setSuccessCount(100); | ||
| 100 | - obj.setSpuId(633L); | ||
| 101 | - obj.setSingleLimitCount(2); | ||
| 102 | - obj.setTotalLimitCount(3); | ||
| 103 | - | ||
| 104 | - // 创建一个Product对象的列表 | ||
| 105 | - List<AppCombinationActivityDetailRespVO.Product> productList = new ArrayList<>(); | ||
| 106 | - // 创建三个新的Product对象并设置其属性的值 | ||
| 107 | - AppCombinationActivityDetailRespVO.Product product1 = new AppCombinationActivityDetailRespVO.Product(); | ||
| 108 | - product1.setSkuId(1L); | ||
| 109 | - product1.setCombinationPrice(100); | ||
| 110 | - // 将第一个Product对象添加到列表中 | ||
| 111 | - productList.add(product1); | ||
| 112 | - // 创建第二个Product对象并设置其属性的值 | ||
| 113 | - AppCombinationActivityDetailRespVO.Product product2 = new AppCombinationActivityDetailRespVO.Product(); | ||
| 114 | - product2.setSkuId(2L); | ||
| 115 | - product2.setCombinationPrice(200); | ||
| 116 | - // 将第二个Product对象添加到列表中 | ||
| 117 | - productList.add(product2); | ||
| 118 | - // 创建第三个Product对象并设置其属性的值 | ||
| 119 | - AppCombinationActivityDetailRespVO.Product product3 = new AppCombinationActivityDetailRespVO.Product(); | ||
| 120 | - product3.setSkuId(3L); | ||
| 121 | - product3.setCombinationPrice(300); | ||
| 122 | - // 将第三个Product对象添加到列表中 | ||
| 123 | - productList.add(product3); | ||
| 124 | - // 将Product列表设置为对象的属性值 | ||
| 125 | - obj.setProducts(productList); | ||
| 126 | - return success(obj); | 76 | + // 1、获取活动 |
| 77 | + CombinationActivityDO combinationActivity = activityService.getCombinationActivity(id); | ||
| 78 | + if (combinationActivity == null | ||
| 79 | + || ObjectUtil.equal(combinationActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { | ||
| 80 | + return success(null); | ||
| 81 | + } | ||
| 82 | + // 2、获取活动商品 | ||
| 83 | + List<CombinationProductDO> products = activityService.getCombinationProductsByActivityId(combinationActivity.getId()); | ||
| 84 | + return success(CombinationActivityConvert.INSTANCE.convert3(combinationActivity, products)); | ||
| 127 | } | 85 | } |
| 128 | 86 | ||
| 129 | } | 87 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/combination/vo/activity/AppCombinationActivityRespVO.java
| @@ -28,7 +28,6 @@ public class AppCombinationActivityRespVO { | @@ -28,7 +28,6 @@ public class AppCombinationActivityRespVO { | ||
| 28 | private Integer marketPrice; | 28 | private Integer marketPrice; |
| 29 | 29 | ||
| 30 | @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | 30 | @Schema(description = "拼团金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") |
| 31 | - // 从拼团商品里取最低价 | ||
| 32 | private Integer combinationPrice; | 31 | private Integer combinationPrice; |
| 33 | 32 | ||
| 34 | } | 33 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.app.seckill; | 1 | package cn.iocoder.yudao.module.promotion.controller.app.seckill; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.collection.CollUtil; | ||
| 3 | import cn.hutool.core.util.ObjectUtil; | 4 | import cn.hutool.core.util.ObjectUtil; |
| 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| @@ -27,14 +28,10 @@ import org.springframework.web.bind.annotation.RequestParam; | @@ -27,14 +28,10 @@ import org.springframework.web.bind.annotation.RequestParam; | ||
| 27 | import org.springframework.web.bind.annotation.RestController; | 28 | import org.springframework.web.bind.annotation.RestController; |
| 28 | 29 | ||
| 29 | import javax.annotation.Resource; | 30 | import javax.annotation.Resource; |
| 30 | -import java.util.Arrays; | ||
| 31 | import java.util.List; | 31 | import java.util.List; |
| 32 | 32 | ||
| 33 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 34 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 33 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 35 | -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | ||
| 36 | -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween; | ||
| 37 | -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_FAIL_STATUS_CLOSED; | 34 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| 38 | 35 | ||
| 39 | @Tag(name = "用户 App - 秒杀活动") | 36 | @Tag(name = "用户 App - 秒杀活动") |
| 40 | @RestController | 37 | @RestController |
| @@ -50,27 +47,21 @@ public class AppSeckillActivityController { | @@ -50,27 +47,21 @@ public class AppSeckillActivityController { | ||
| 50 | @Resource | 47 | @Resource |
| 51 | private ProductSpuApi spuApi; | 48 | private ProductSpuApi spuApi; |
| 52 | 49 | ||
| 53 | - @GetMapping("/get-now") | ||
| 54 | - @Operation(summary = "获得当前秒杀活动") // 提供给首页使用 | ||
| 55 | // TODO 芋艿:需要增加 spring cache | 50 | // TODO 芋艿:需要增加 spring cache |
| 51 | + @GetMapping("/get-now") | ||
| 52 | + @Operation(summary = "获得当前秒杀活动", description = "获取当前正在进行的活动,提供给首页使用") | ||
| 56 | public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() { | 53 | public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() { |
| 57 | // 1. 获取当前时间处在哪个秒杀阶段 | 54 | // 1. 获取当前时间处在哪个秒杀阶段 |
| 58 | - // TODO @puhui999:可以考虑在 service 写个方法;这样 controller 不用关注过多逻辑 | ||
| 59 | - List<SeckillConfigDO> configList = configService.getSeckillConfigList(); | ||
| 60 | - SeckillConfigDO filteredConfig = findFirst(configList, config -> ObjectUtil.equal(config.getStatus(), | ||
| 61 | - CommonStatusEnum.ENABLE.getStatus()) && isBetween(config.getStartTime(), config.getEndTime())); | ||
| 62 | - if (filteredConfig == null) { // 时段不存在直接返回 null | 55 | + SeckillConfigDO configList = configService.getSeckillConfigListByStatusOnCurrentTime(CommonStatusEnum.ENABLE.getStatus()); |
| 56 | + if (configList == null) { // 时段不存在直接返回 null | ||
| 63 | return success(null); | 57 | return success(null); |
| 64 | } | 58 | } |
| 65 | 59 | ||
| 66 | // 2. 查询满足当前阶段的活动 | 60 | // 2. 查询满足当前阶段的活动 |
| 67 | - // TODO @puhui999:最好直接返回开启的;不多查询数据 | ||
| 68 | - List<SeckillActivityDO> activityList = activityService.getSeckillActivityListByConfigIds(Arrays.asList(filteredConfig.getId())); | ||
| 69 | - List<SeckillActivityDO> filteredList = filterList(activityList, item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.ENABLE.getStatus())); | ||
| 70 | - | ||
| 71 | - // 3. 拼接数据 | ||
| 72 | - List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(filteredList, SeckillActivityDO::getSpuId)); | ||
| 73 | - return success(SeckillActivityConvert.INSTANCE.convert(filteredConfig, filteredList, spuList)); | 61 | + List<SeckillActivityDO> activityList = activityService.getSeckillActivityListByConfigIdAndStatus(configList.getId(), CommonStatusEnum.ENABLE.getStatus()); |
| 62 | + // 3 获取 spu 信息 | ||
| 63 | + List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId)); | ||
| 64 | + return success(SeckillActivityConvert.INSTANCE.convert(configList, activityList, spuList)); | ||
| 74 | } | 65 | } |
| 75 | 66 | ||
| 76 | @GetMapping("/page") | 67 | @GetMapping("/page") |
| @@ -78,7 +69,9 @@ public class AppSeckillActivityController { | @@ -78,7 +69,9 @@ public class AppSeckillActivityController { | ||
| 78 | public CommonResult<PageResult<AppSeckillActivityRespVO>> getSeckillActivityPage(AppSeckillActivityPageReqVO pageReqVO) { | 69 | public CommonResult<PageResult<AppSeckillActivityRespVO>> getSeckillActivityPage(AppSeckillActivityPageReqVO pageReqVO) { |
| 79 | // 1. 查询满足当前阶段的活动 | 70 | // 1. 查询满足当前阶段的活动 |
| 80 | PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO); | 71 | PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO); |
| 81 | - | 72 | + if (CollUtil.isEmpty(pageResult.getList())) { |
| 73 | + return success(PageResult.empty(pageResult.getTotal())); | ||
| 74 | + } | ||
| 82 | // 2. 拼接数据 | 75 | // 2. 拼接数据 |
| 83 | List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(pageResult.getList(), SeckillActivityDO::getSpuId)); | 76 | List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(pageResult.getList(), SeckillActivityDO::getSpuId)); |
| 84 | return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, spuList)); | 77 | return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, spuList)); |
| @@ -88,28 +81,22 @@ public class AppSeckillActivityController { | @@ -88,28 +81,22 @@ public class AppSeckillActivityController { | ||
| 88 | @Operation(summary = "获得秒杀活动明细") | 81 | @Operation(summary = "获得秒杀活动明细") |
| 89 | @Parameter(name = "id", description = "活动编号", required = true, example = "1024") | 82 | @Parameter(name = "id", description = "活动编号", required = true, example = "1024") |
| 90 | public CommonResult<AppSeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) { | 83 | public CommonResult<AppSeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) { |
| 91 | - // 1、获取当前时间处在哪个秒杀阶段 | ||
| 92 | - // TODO puhui999:这里,和 58 行是雷同的 | ||
| 93 | - List<SeckillConfigDO> configList = configService.getSeckillConfigList(); | ||
| 94 | - SeckillConfigDO filteredConfig = findFirst(configList, config -> ObjectUtil.equal(config.getStatus(), | ||
| 95 | - CommonStatusEnum.ENABLE.getStatus()) && isBetween(config.getStartTime(), config.getEndTime())); | ||
| 96 | - if (filteredConfig == null) { // 时段不存在直接返回 null | 84 | + // 1. 获取当前时间处在哪个秒杀阶段 |
| 85 | + SeckillConfigDO configList = configService.getSeckillConfigListByStatusOnCurrentTime(CommonStatusEnum.ENABLE.getStatus()); | ||
| 86 | + if (configList == null) { // 时段不存在直接返回 null | ||
| 97 | return success(null); | 87 | return success(null); |
| 98 | } | 88 | } |
| 99 | 89 | ||
| 100 | // 2. 获取活动 | 90 | // 2. 获取活动 |
| 101 | SeckillActivityDO seckillActivity = activityService.getSeckillActivity(id); | 91 | SeckillActivityDO seckillActivity = activityService.getSeckillActivity(id); |
| 102 | - if (seckillActivity == null) { | 92 | + if (seckillActivity == null |
| 93 | + || ObjectUtil.equal(seckillActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { | ||
| 103 | return success(null); | 94 | return success(null); |
| 104 | } | 95 | } |
| 105 | - // TODO 芋艿:如果禁用的时候,需要抛出异常; | ||
| 106 | - if (ObjectUtil.equal(seckillActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) { | ||
| 107 | - throw exception(SECKILL_ACTIVITY_FAIL_STATUS_CLOSED); | ||
| 108 | - } | ||
| 109 | 96 | ||
| 110 | // 3. 拼接数据 | 97 | // 3. 拼接数据 |
| 111 | - List<SeckillProductDO> products = activityService.getSeckillProductListByActivityId(seckillActivity.getId()); | ||
| 112 | - return success(SeckillActivityConvert.INSTANCE.convert3(seckillActivity, products, filteredConfig)); | 98 | + List<SeckillProductDO> productList = activityService.getSeckillProductListByActivityId(seckillActivity.getId()); |
| 99 | + return success(SeckillActivityConvert.INSTANCE.convert3(seckillActivity, productList, configList)); | ||
| 113 | } | 100 | } |
| 114 | 101 | ||
| 115 | } | 102 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java
| 1 | package cn.iocoder.yudao.module.promotion.controller.app.seckill; | 1 | package cn.iocoder.yudao.module.promotion.controller.app.seckill; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.collection.CollectionUtil; | ||
| 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 6 | import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO; | 5 | import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO; |
| 7 | import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert; | 6 | import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert; |
| 8 | -import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO; | ||
| 9 | import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService; | 7 | import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService; |
| 10 | import io.swagger.v3.oas.annotations.Operation; | 8 | import io.swagger.v3.oas.annotations.Operation; |
| 11 | import io.swagger.v3.oas.annotations.tags.Tag; | 9 | import io.swagger.v3.oas.annotations.tags.Tag; |
| @@ -15,7 +13,6 @@ import org.springframework.web.bind.annotation.RequestMapping; | @@ -15,7 +13,6 @@ import org.springframework.web.bind.annotation.RequestMapping; | ||
| 15 | import org.springframework.web.bind.annotation.RestController; | 13 | import org.springframework.web.bind.annotation.RestController; |
| 16 | 14 | ||
| 17 | import javax.annotation.Resource; | 15 | import javax.annotation.Resource; |
| 18 | -import java.util.Collections; | ||
| 19 | import java.util.List; | 16 | import java.util.List; |
| 20 | 17 | ||
| 21 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 18 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| @@ -31,13 +28,8 @@ public class AppSeckillConfigController { | @@ -31,13 +28,8 @@ public class AppSeckillConfigController { | ||
| 31 | @GetMapping("/list") | 28 | @GetMapping("/list") |
| 32 | @Operation(summary = "获得秒杀时间段列表") | 29 | @Operation(summary = "获得秒杀时间段列表") |
| 33 | public CommonResult<List<AppSeckillConfigRespVO>> getSeckillConfigList() { | 30 | public CommonResult<List<AppSeckillConfigRespVO>> getSeckillConfigList() { |
| 34 | - List<SeckillConfigDO> list = configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 35 | - // TODO @puhui999:如果这种,不用判空也问题不大; | ||
| 36 | - if (CollectionUtil.isEmpty(list)) { | ||
| 37 | - return success(Collections.emptyList()); | ||
| 38 | - } | ||
| 39 | - | ||
| 40 | - return success(SeckillConfigConvert.INSTANCE.convertList2(list)); | 31 | + return success(SeckillConfigConvert.INSTANCE.convertList2( |
| 32 | + configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus()))); | ||
| 41 | } | 33 | } |
| 42 | 34 | ||
| 43 | } | 35 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java
| @@ -25,6 +25,9 @@ public class AppSeckillActivityRespVO { | @@ -25,6 +25,9 @@ public class AppSeckillActivityRespVO { | ||
| 25 | // 从 SPU 的 marketPrice 读取 | 25 | // 从 SPU 的 marketPrice 读取 |
| 26 | private Integer marketPrice; | 26 | private Integer marketPrice; |
| 27 | 27 | ||
| 28 | + @Schema(description = "秒杀活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 29 | + private Integer status; | ||
| 30 | + | ||
| 28 | @Schema(description = "秒杀库存(剩余)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | 31 | @Schema(description = "秒杀库存(剩余)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") |
| 29 | private Integer stock; | 32 | private Integer stock; |
| 30 | @Schema(description = "秒杀库存(总共)", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") | 33 | @Schema(description = "秒杀库存(总共)", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/bargain/BargainActivityConvert.java
| @@ -46,9 +46,7 @@ public interface BargainActivityConvert { | @@ -46,9 +46,7 @@ public interface BargainActivityConvert { | ||
| 46 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); | 46 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); |
| 47 | List<BargainActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> { | 47 | List<BargainActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> { |
| 48 | findAndThen(spuMap, item.getSpuId(), spu -> { | 48 | findAndThen(spuMap, item.getSpuId(), spu -> { |
| 49 | - // TODO @puhui999:这里可以使用链式哈 | ||
| 50 | - item.setPicUrl(spu.getPicUrl()); | ||
| 51 | - item.setSpuName(spu.getName()); | 49 | + item.setPicUrl(spu.getPicUrl()).setSpuName(spu.getName()); |
| 52 | }); | 50 | }); |
| 53 | return item; | 51 | return item; |
| 54 | }); | 52 | }); |
| @@ -75,11 +73,7 @@ public interface BargainActivityConvert { | @@ -75,11 +73,7 @@ public interface BargainActivityConvert { | ||
| 75 | // 拼接关联属性 | 73 | // 拼接关联属性 |
| 76 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); | 74 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); |
| 77 | List<AppBargainActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> { | 75 | List<AppBargainActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> { |
| 78 | - findAndThen(spuMap, item.getSpuId(), spu -> { | ||
| 79 | - // TODO @puhui999:这里可以使用链式哈 | ||
| 80 | - item.setPicUrl(spu.getPicUrl()); | ||
| 81 | - item.setMarketPrice(spu.getMarketPrice()); | ||
| 82 | - }); | 76 | + findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); |
| 83 | return item; | 77 | return item; |
| 84 | }); | 78 | }); |
| 85 | result.setList(list); | 79 | result.setList(list); |
| @@ -92,11 +86,7 @@ public interface BargainActivityConvert { | @@ -92,11 +86,7 @@ public interface BargainActivityConvert { | ||
| 92 | List<AppBargainActivityRespVO> activityList = convertAppList(list); | 86 | List<AppBargainActivityRespVO> activityList = convertAppList(list); |
| 93 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); | 87 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); |
| 94 | return CollectionUtils.convertList(activityList, item -> { | 88 | return CollectionUtils.convertList(activityList, item -> { |
| 95 | - findAndThen(spuMap, item.getSpuId(), spu -> { | ||
| 96 | - // TODO @puhui999:这里可以使用链式哈 | ||
| 97 | - item.setPicUrl(spu.getPicUrl()); | ||
| 98 | - item.setMarketPrice(spu.getMarketPrice()); | ||
| 99 | - }); | 89 | + findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); |
| 100 | return item; | 90 | return item; |
| 101 | }); | 91 | }); |
| 102 | } | 92 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/combination/CombinationActivityConvert.java
| @@ -13,6 +13,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activit | @@ -13,6 +13,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activit | ||
| 13 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; | 13 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityUpdateReqVO; |
| 14 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; | 14 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO; |
| 15 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO; | 15 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductRespVO; |
| 16 | +import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO; | ||
| 17 | +import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO; | ||
| 16 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; | 18 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO; |
| 17 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; | 19 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO; |
| 18 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; | 20 | import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationRecordDO; |
| @@ -25,6 +27,7 @@ import java.util.List; | @@ -25,6 +27,7 @@ import java.util.List; | ||
| 25 | import java.util.Map; | 27 | import java.util.Map; |
| 26 | 28 | ||
| 27 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 29 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 30 | +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | ||
| 28 | 31 | ||
| 29 | /** | 32 | /** |
| 30 | * 拼团活动 Convert | 33 | * 拼团活动 Convert |
| @@ -58,10 +61,7 @@ public interface CombinationActivityConvert { | @@ -58,10 +61,7 @@ public interface CombinationActivityConvert { | ||
| 58 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); | 61 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); |
| 59 | PageResult<CombinationActivityRespVO> pageResult = convertPage(page); | 62 | PageResult<CombinationActivityRespVO> pageResult = convertPage(page); |
| 60 | pageResult.getList().forEach(item -> { | 63 | pageResult.getList().forEach(item -> { |
| 61 | - MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> { | ||
| 62 | - item.setSpuName(spu.getName()); | ||
| 63 | - item.setPicUrl(spu.getPicUrl()); | ||
| 64 | - }); | 64 | + MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl())); |
| 65 | item.setProducts(convertList2(productList)); | 65 | item.setProducts(convertList2(productList)); |
| 66 | }); | 66 | }); |
| 67 | return pageResult; | 67 | return pageResult; |
| @@ -97,18 +97,51 @@ public interface CombinationActivityConvert { | @@ -97,18 +97,51 @@ public interface CombinationActivityConvert { | ||
| 97 | default CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO, | 97 | default CombinationRecordDO convert(CombinationRecordCreateReqDTO reqDTO, |
| 98 | CombinationActivityDO activity, MemberUserRespDTO user, | 98 | CombinationActivityDO activity, MemberUserRespDTO user, |
| 99 | ProductSpuRespDTO spu, ProductSkuRespDTO sku) { | 99 | ProductSpuRespDTO spu, ProductSkuRespDTO sku) { |
| 100 | - // TODO @puhui999:搞成链式的 set;这样会更规整一点; | ||
| 101 | - CombinationRecordDO record = convert(reqDTO); | ||
| 102 | - record.setVirtualGroup(false); | ||
| 103 | - record.setExpireTime(record.getStartTime().plusHours(activity.getLimitDuration())); | ||
| 104 | - record.setUserSize(activity.getUserSize()); | ||
| 105 | - record.setNickname(user.getNickname()); | ||
| 106 | - record.setAvatar(user.getAvatar()); | ||
| 107 | - record.setSpuName(spu.getName()); | ||
| 108 | - record.setPicUrl(sku.getPicUrl()); | ||
| 109 | - return record; | 100 | + // TODO @puhui999:订单付款后需要设置开始时间和结束时间; |
| 101 | + return convert(reqDTO) | ||
| 102 | + .setVirtualGroup(false) | ||
| 103 | + .setExpireTime(activity.getStartTime().plusHours(activity.getLimitDuration())) | ||
| 104 | + .setUserSize(activity.getUserSize()) | ||
| 105 | + .setNickname(user.getNickname()) | ||
| 106 | + .setAvatar(user.getAvatar()) | ||
| 107 | + .setSpuName(spu.getName()) | ||
| 108 | + .setPicUrl(sku.getPicUrl()); | ||
| 110 | } | 109 | } |
| 111 | 110 | ||
| 112 | List<CombinationRecordRespDTO> convert(List<CombinationRecordDO> bean); | 111 | List<CombinationRecordRespDTO> convert(List<CombinationRecordDO> bean); |
| 113 | 112 | ||
| 113 | + List<AppCombinationActivityRespVO> convertAppList(List<CombinationActivityDO> list); | ||
| 114 | + | ||
| 115 | + default List<AppCombinationActivityRespVO> convertAppList(List<CombinationActivityDO> list, List<ProductSpuRespDTO> spuList) { | ||
| 116 | + List<AppCombinationActivityRespVO> activityList = convertAppList(list); | ||
| 117 | + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); | ||
| 118 | + return CollectionUtils.convertList(activityList, item -> { | ||
| 119 | + findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())); | ||
| 120 | + return item; | ||
| 121 | + }); | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + PageResult<AppCombinationActivityRespVO> convertAppPage(PageResult<CombinationActivityDO> result); | ||
| 125 | + | ||
| 126 | + default PageResult<AppCombinationActivityRespVO> convertAppPage(PageResult<CombinationActivityDO> result, List<ProductSpuRespDTO> spuList) { | ||
| 127 | + PageResult<AppCombinationActivityRespVO> appPage = convertAppPage(result); | ||
| 128 | + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); | ||
| 129 | + List<AppCombinationActivityRespVO> list = CollectionUtils.convertList(appPage.getList(), item -> { | ||
| 130 | + findAndThen(spuMap, item.getSpuId(), spu -> { | ||
| 131 | + item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()); | ||
| 132 | + }); | ||
| 133 | + return item; | ||
| 134 | + }); | ||
| 135 | + appPage.setList(list); | ||
| 136 | + return appPage; | ||
| 137 | + } | ||
| 138 | + | ||
| 139 | + AppCombinationActivityDetailRespVO convert2(CombinationActivityDO combinationActivity); | ||
| 140 | + | ||
| 141 | + List<AppCombinationActivityDetailRespVO.Product> convertList1(List<CombinationProductDO> products); | ||
| 142 | + | ||
| 143 | + default AppCombinationActivityDetailRespVO convert3(CombinationActivityDO combinationActivity, List<CombinationProductDO> products) { | ||
| 144 | + return convert2(combinationActivity).setProducts(convertList1(products)); | ||
| 145 | + } | ||
| 146 | + | ||
| 114 | } | 147 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
| 1 | package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; | 1 | package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.date.LocalDateTimeUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 5 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 5 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | 6 | import cn.iocoder.yudao.framework.common.util.collection.MapUtils; |
| @@ -29,7 +30,6 @@ import java.util.Map; | @@ -29,7 +30,6 @@ import java.util.Map; | ||
| 29 | 30 | ||
| 30 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | 31 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; |
| 31 | import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; | 32 | import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; |
| 32 | -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | ||
| 33 | 33 | ||
| 34 | /** | 34 | /** |
| 35 | * 秒杀活动 Convert | 35 | * 秒杀活动 Convert |
| @@ -98,10 +98,9 @@ public interface SeckillActivityConvert { | @@ -98,10 +98,9 @@ public interface SeckillActivityConvert { | ||
| 98 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); | 98 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); |
| 99 | respVO.setActivities(CollectionUtils.convertList(convertList3(activityList), item -> { | 99 | respVO.setActivities(CollectionUtils.convertList(convertList3(activityList), item -> { |
| 100 | findAndThen(spuMap, item.getSpuId(), spu -> { | 100 | findAndThen(spuMap, item.getSpuId(), spu -> { |
| 101 | - // TODO @puhui999:可以尝试链式 set 哈; | ||
| 102 | - item.setPicUrl(spu.getPicUrl()); | ||
| 103 | - item.setMarketPrice(spu.getMarketPrice()); | ||
| 104 | - item.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())); | 101 | + item.setPicUrl(spu.getPicUrl()) |
| 102 | + .setMarketPrice(spu.getMarketPrice()) | ||
| 103 | + .setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())); | ||
| 105 | }); | 104 | }); |
| 106 | return item; | 105 | return item; |
| 107 | })); | 106 | })); |
| @@ -114,12 +113,8 @@ public interface SeckillActivityConvert { | @@ -114,12 +113,8 @@ public interface SeckillActivityConvert { | ||
| 114 | PageResult<AppSeckillActivityRespVO> result = convertPage1(pageResult); | 113 | PageResult<AppSeckillActivityRespVO> result = convertPage1(pageResult); |
| 115 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); | 114 | Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId); |
| 116 | List<AppSeckillActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> { | 115 | List<AppSeckillActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> { |
| 117 | - findAndThen(spuMap, item.getSpuId(), spu -> { | ||
| 118 | - // TODO @puhui999:可以尝试链式 set 哈; | ||
| 119 | - item.setPicUrl(spu.getPicUrl()); | ||
| 120 | - item.setMarketPrice(spu.getMarketPrice()); | ||
| 121 | - item.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())); | ||
| 122 | - }); | 116 | + findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()) |
| 117 | + .setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()))); | ||
| 123 | return item; | 118 | return item; |
| 124 | }); | 119 | }); |
| 125 | result.setList(list); | 120 | result.setList(list); |
| @@ -131,12 +126,13 @@ public interface SeckillActivityConvert { | @@ -131,12 +126,13 @@ public interface SeckillActivityConvert { | ||
| 131 | List<AppSeckillActivityDetailRespVO.Product> convertList1(List<SeckillProductDO> products); | 126 | List<AppSeckillActivityDetailRespVO.Product> convertList1(List<SeckillProductDO> products); |
| 132 | 127 | ||
| 133 | default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) { | 128 | default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) { |
| 134 | - AppSeckillActivityDetailRespVO respVO = convert2(seckillActivity); | ||
| 135 | - respVO.setProducts(convertList1(products)); | ||
| 136 | - // TODO @puhui999:可以尝试链式 set 哈; | ||
| 137 | - respVO.setStartTime(buildTime(filteredConfig.getStartTime())); | ||
| 138 | - respVO.setEndTime(buildTime(filteredConfig.getEndTime())); | ||
| 139 | - return respVO; | 129 | + return convert2(seckillActivity) |
| 130 | + .setProducts(convertList1(products)) | ||
| 131 | + // TODO @puhui999:要不要在里面 default 一个方法,处理这个事件;简洁一点; | ||
| 132 | + .setStartTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getStartTime(), "yyyy-MM-dd") + " " + filteredConfig.getStartTime(), | ||
| 133 | + "yyyy-MM-dd HH:mm:ss")) // 活动开始日期和时段结合 | ||
| 134 | + .setEndTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getEndTime(), "yyyy-MM-dd") + " " + filteredConfig.getEndTime(), | ||
| 135 | + "yyyy-MM-dd HH:mm:ss")); // 活动结束日期和时段结合 | ||
| 140 | } | 136 | } |
| 141 | 137 | ||
| 142 | } | 138 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/bargain/BargainActivityMapper.java
| @@ -38,18 +38,41 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> { | @@ -38,18 +38,41 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> { | ||
| 38 | * @param count 扣减的库存数量 | 38 | * @param count 扣减的库存数量 |
| 39 | * @return 影响的行数 | 39 | * @return 影响的行数 |
| 40 | */ | 40 | */ |
| 41 | - default int updateActivityStock(Long id, int count) { | 41 | + default int updateStock(Long id, int count) { |
| 42 | return update(null, new LambdaUpdateWrapper<BargainActivityDO>() | 42 | return update(null, new LambdaUpdateWrapper<BargainActivityDO>() |
| 43 | .eq(BargainActivityDO::getId, id) | 43 | .eq(BargainActivityDO::getId, id) |
| 44 | .ge(BargainActivityDO::getStock, count) | 44 | .ge(BargainActivityDO::getStock, count) |
| 45 | .setSql("stock = stock - " + count)); | 45 | .setSql("stock = stock - " + count)); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | - default PageResult<BargainActivityDO> selectAppPage(PageParam pageReqVO, Integer status, LocalDateTime now) { | 48 | + /** |
| 49 | + * 查询处在 now 日期时间且是 status 状态的活动分页 | ||
| 50 | + * | ||
| 51 | + * @param pageReqVO 分页参数 | ||
| 52 | + * @param status 状态 | ||
| 53 | + * @param now 当前日期时间 | ||
| 54 | + * @return 活动分页 | ||
| 55 | + */ | ||
| 56 | + default PageResult<BargainActivityDO> selectPage(PageParam pageReqVO, Integer status, LocalDateTime now) { | ||
| 49 | return selectPage(pageReqVO, new LambdaQueryWrapperX<BargainActivityDO>() | 57 | return selectPage(pageReqVO, new LambdaQueryWrapperX<BargainActivityDO>() |
| 50 | .eq(BargainActivityDO::getStatus, status) | 58 | .eq(BargainActivityDO::getStatus, status) |
| 51 | .le(BargainActivityDO::getStartTime, now) | 59 | .le(BargainActivityDO::getStartTime, now) |
| 52 | .ge(BargainActivityDO::getEndTime, now)); | 60 | .ge(BargainActivityDO::getEndTime, now)); |
| 53 | } | 61 | } |
| 54 | 62 | ||
| 63 | + /** | ||
| 64 | + * 查询处在 now 日期时间且是 status 状态的活动分页 | ||
| 65 | + * | ||
| 66 | + * @param status 状态 | ||
| 67 | + * @param now 当前日期时间 | ||
| 68 | + * @return 活动分页 | ||
| 69 | + */ | ||
| 70 | + default List<BargainActivityDO> selectList(Integer count, Integer status, LocalDateTime now) { | ||
| 71 | + return selectList(new LambdaQueryWrapperX<BargainActivityDO>() | ||
| 72 | + .eq(BargainActivityDO::getStatus, status) | ||
| 73 | + .le(BargainActivityDO::getStartTime, now) | ||
| 74 | + .ge(BargainActivityDO::getEndTime, now) | ||
| 75 | + .last("LIMIT " + count)); | ||
| 76 | + } | ||
| 77 | + | ||
| 55 | } | 78 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/combination/CombinationActivityMapper.java
| 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.combination; | 1 | package cn.iocoder.yudao.module.promotion.dal.mysql.combination; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| @@ -28,4 +29,15 @@ public interface CombinationActivityMapper extends BaseMapperX<CombinationActivi | @@ -28,4 +29,15 @@ public interface CombinationActivityMapper extends BaseMapperX<CombinationActivi | ||
| 28 | return selectList(CombinationActivityDO::getStatus, status); | 29 | return selectList(CombinationActivityDO::getStatus, status); |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 32 | + default PageResult<CombinationActivityDO> selectPage(PageParam pageParam, Integer status) { | ||
| 33 | + return selectPage(pageParam, new LambdaQueryWrapperX<CombinationActivityDO>() | ||
| 34 | + .eq(CombinationActivityDO::getStatus, status)); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + default List<CombinationActivityDO> selectListByStatus(Integer status, Integer count) { | ||
| 38 | + return selectList(new LambdaQueryWrapperX<CombinationActivityDO>() | ||
| 39 | + .eq(CombinationActivityDO::getStatus, status) | ||
| 40 | + .last("LIMIT " + count)); | ||
| 41 | + } | ||
| 42 | + | ||
| 31 | } | 43 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java
| @@ -41,7 +41,7 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | @@ -41,7 +41,7 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { | ||
| 41 | * @param count 扣减的库存数量 | 41 | * @param count 扣减的库存数量 |
| 42 | * @return 影响的行数 | 42 | * @return 影响的行数 |
| 43 | */ | 43 | */ |
| 44 | - default int updateActivityStock(Long id, int count) { | 44 | + default int updateStock(Long id, int count) { |
| 45 | return update(null, new LambdaUpdateWrapper<SeckillActivityDO>() | 45 | return update(null, new LambdaUpdateWrapper<SeckillActivityDO>() |
| 46 | .eq(SeckillActivityDO::getId, id) | 46 | .eq(SeckillActivityDO::getId, id) |
| 47 | .gt(SeckillActivityDO::getTotalStock, 0) | 47 | .gt(SeckillActivityDO::getTotalStock, 0) |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillProductMapper.java
| @@ -16,8 +16,13 @@ import java.util.List; | @@ -16,8 +16,13 @@ import java.util.List; | ||
| 16 | @Mapper | 16 | @Mapper |
| 17 | public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> { | 17 | public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> { |
| 18 | 18 | ||
| 19 | - default List<SeckillProductDO> selectListByActivityId(Long id) { | ||
| 20 | - return selectList(SeckillProductDO::getActivityId, id); | 19 | + default List<SeckillProductDO> selectListByActivityId(Long activityId) { |
| 20 | + return selectList(SeckillProductDO::getActivityId, activityId); | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + default SeckillProductDO selectByActivityIdAndSkuId(Long activityId, Long skuId) { | ||
| 24 | + return selectOne(SeckillProductDO::getActivityId, activityId, | ||
| 25 | + SeckillProductDO::getSkuId, skuId); | ||
| 21 | } | 26 | } |
| 22 | 27 | ||
| 23 | default List<SeckillProductDO> selectListByActivityId(Collection<Long> ids) { | 28 | default List<SeckillProductDO> selectListByActivityId(Collection<Long> ids) { |
| @@ -31,7 +36,7 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> { | @@ -31,7 +36,7 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> { | ||
| 31 | * @param count 扣减的库存数量 | 36 | * @param count 扣减的库存数量 |
| 32 | * @return 影响的行数 | 37 | * @return 影响的行数 |
| 33 | */ | 38 | */ |
| 34 | - default int updateActivityStock(Long id, int count) { | 39 | + default int updateStock(Long id, int count) { |
| 35 | return update(null, new LambdaUpdateWrapper<SeckillProductDO>() | 40 | return update(null, new LambdaUpdateWrapper<SeckillProductDO>() |
| 36 | .eq(SeckillProductDO::getId, id) | 41 | .eq(SeckillProductDO::getId, id) |
| 37 | .gt(SeckillProductDO::getStock, count) | 42 | .gt(SeckillProductDO::getStock, count) |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityService.java
| @@ -63,22 +63,20 @@ public interface BargainActivityService { | @@ -63,22 +63,20 @@ public interface BargainActivityService { | ||
| 63 | */ | 63 | */ |
| 64 | PageResult<BargainActivityDO> getBargainActivityPage(BargainActivityPageReqVO pageReqVO); | 64 | PageResult<BargainActivityDO> getBargainActivityPage(BargainActivityPageReqVO pageReqVO); |
| 65 | 65 | ||
| 66 | - // TODO @puhui999:这里可以改成进行中的活动;尽量避免专门为 app 定制,或者类似的名字哈;mapper 那也是 | ||
| 67 | - | ||
| 68 | /** | 66 | /** |
| 69 | - * 获取 APP 端活动分页数据 | 67 | + * 获取正在进行的活动分页数据 |
| 70 | * | 68 | * |
| 71 | * @param pageReqVO 分页请求 | 69 | * @param pageReqVO 分页请求 |
| 72 | * @return 砍价活动分页 | 70 | * @return 砍价活动分页 |
| 73 | */ | 71 | */ |
| 74 | - PageResult<BargainActivityDO> getBargainActivityPageForApp(PageParam pageReqVO); | 72 | + PageResult<BargainActivityDO> getBargainActivityPage(PageParam pageReqVO); |
| 75 | 73 | ||
| 76 | /** | 74 | /** |
| 77 | - * 获取 APP 端活动展示数据 | 75 | + * 获取正在进行的活动分页数据 |
| 78 | * | 76 | * |
| 79 | * @param count 需要的数量 | 77 | * @param count 需要的数量 |
| 80 | * @return 砍价活动分页 | 78 | * @return 砍价活动分页 |
| 81 | */ | 79 | */ |
| 82 | - List<BargainActivityDO> getBargainActivityListForApp(Integer count); | 80 | + List<BargainActivityDO> getBargainActivityListByCount(Integer count); |
| 83 | 81 | ||
| 84 | } | 82 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/bargain/BargainActivityServiceImpl.java
| @@ -75,16 +75,18 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -75,16 +75,18 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | @Override | 77 | @Override |
| 78 | - @Transactional(rollbackFor = Exception.class) | ||
| 79 | public void updateBargainActivityStock(Long id, Integer count) { | 78 | public void updateBargainActivityStock(Long id, Integer count) { |
| 80 | // 查询砍价活动 | 79 | // 查询砍价活动 |
| 81 | BargainActivityDO activity = getBargainActivity(id); | 80 | BargainActivityDO activity = getBargainActivity(id); |
| 82 | if (activity == null) { | 81 | if (activity == null) { |
| 83 | throw exception(BARGAIN_ACTIVITY_NOT_EXISTS); | 82 | throw exception(BARGAIN_ACTIVITY_NOT_EXISTS); |
| 84 | } | 83 | } |
| 84 | + if (count > activity.getStock()) { | ||
| 85 | + throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL); | ||
| 86 | + } | ||
| 85 | 87 | ||
| 86 | // 更新砍价库存 | 88 | // 更新砍价库存 |
| 87 | - int updateCount = bargainActivityMapper.updateActivityStock(id, count); | 89 | + int updateCount = bargainActivityMapper.updateStock(id, count); |
| 88 | if (updateCount == 0) { | 90 | if (updateCount == 0) { |
| 89 | throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL); | 91 | throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL); |
| 90 | } | 92 | } |
| @@ -114,7 +116,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -114,7 +116,7 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 114 | public void deleteBargainActivity(Long id) { | 116 | public void deleteBargainActivity(Long id) { |
| 115 | // 校验存在 | 117 | // 校验存在 |
| 116 | BargainActivityDO activityDO = validateBargainActivityExists(id); | 118 | BargainActivityDO activityDO = validateBargainActivityExists(id); |
| 117 | - // 校验状态 | 119 | + // 校验状态 TODO puhui: 测试完成后需要恢复校验 |
| 118 | //if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { | 120 | //if (ObjectUtil.equal(activityDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) { |
| 119 | // throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END); | 121 | // throw exception(BARGAIN_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END); |
| 120 | //} | 122 | //} |
| @@ -142,21 +144,14 @@ public class BargainActivityServiceImpl implements BargainActivityService { | @@ -142,21 +144,14 @@ public class BargainActivityServiceImpl implements BargainActivityService { | ||
| 142 | } | 144 | } |
| 143 | 145 | ||
| 144 | @Override | 146 | @Override |
| 145 | - public PageResult<BargainActivityDO> getBargainActivityPageForApp(PageParam pageReqVO) { | 147 | + public PageResult<BargainActivityDO> getBargainActivityPage(PageParam pageReqVO) { |
| 146 | // 只查询进行中,且在时间范围内的 | 148 | // 只查询进行中,且在时间范围内的 |
| 147 | - return bargainActivityMapper.selectAppPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now()); | 149 | + return bargainActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now()); |
| 148 | } | 150 | } |
| 149 | 151 | ||
| 150 | @Override | 152 | @Override |
| 151 | - public List<BargainActivityDO> getBargainActivityListForApp(Integer count) { | ||
| 152 | - // TODO @puhui999:这种 default count 的逻辑,可以放到 controller 哈;然后可以使用 ObjectUtils.default 方法 | ||
| 153 | - if (count == null) { | ||
| 154 | - count = 6; | ||
| 155 | - } | ||
| 156 | - // TODO @puhui999:这种不要用 page;会浪费一次 count; | ||
| 157 | - PageResult<BargainActivityDO> result = bargainActivityMapper.selectAppPage(new PageParam().setPageSize(count), | ||
| 158 | - CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now()); | ||
| 159 | - return result.getList(); | 153 | + public List<BargainActivityDO> getBargainActivityListByCount(Integer count) { |
| 154 | + return bargainActivityMapper.selectList(count, CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now()); | ||
| 160 | } | 155 | } |
| 161 | 156 | ||
| 162 | } | 157 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityService.java
| 1 | package cn.iocoder.yudao.module.promotion.service.combination; | 1 | package cn.iocoder.yudao.module.promotion.service.combination; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; | 5 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; | 6 | import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.activity.CombinationActivityPageReqVO; |
| @@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationP | @@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationP | ||
| 9 | 10 | ||
| 10 | import javax.validation.Valid; | 11 | import javax.validation.Valid; |
| 11 | import java.util.Collection; | 12 | import java.util.Collection; |
| 13 | +import java.util.Collections; | ||
| 12 | import java.util.List; | 14 | import java.util.List; |
| 13 | 15 | ||
| 14 | /** | 16 | /** |
| @@ -67,6 +69,16 @@ public interface CombinationActivityService { | @@ -67,6 +69,16 @@ public interface CombinationActivityService { | ||
| 67 | /** | 69 | /** |
| 68 | * 获得拼团活动商品列表 | 70 | * 获得拼团活动商品列表 |
| 69 | * | 71 | * |
| 72 | + * @param activityId 拼团活动 id | ||
| 73 | + * @return 拼团活动的商品列表 | ||
| 74 | + */ | ||
| 75 | + default List<CombinationProductDO> getCombinationProductsByActivityId(Long activityId) { | ||
| 76 | + return getCombinationProductsByActivityIds(Collections.singletonList(activityId)); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 获得拼团活动商品列表 | ||
| 81 | + * | ||
| 70 | * @param activityIds 拼团活动 ids | 82 | * @param activityIds 拼团活动 ids |
| 71 | * @return 拼团活动的商品列表 | 83 | * @return 拼团活动的商品列表 |
| 72 | */ | 84 | */ |
| @@ -83,4 +95,20 @@ public interface CombinationActivityService { | @@ -83,4 +95,20 @@ public interface CombinationActivityService { | ||
| 83 | */ | 95 | */ |
| 84 | void validateCombination(Long activityId, Long userId, Long skuId, Integer count); | 96 | void validateCombination(Long activityId, Long userId, Long skuId, Integer count); |
| 85 | 97 | ||
| 98 | + /** | ||
| 99 | + * 获取正在进行的活动分页数据 | ||
| 100 | + * | ||
| 101 | + * @param count 需要的数量 | ||
| 102 | + * @return 拼团活动分页 | ||
| 103 | + */ | ||
| 104 | + List<CombinationActivityDO> getCombinationActivityListByCount(Integer count); | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * 获取正在进行的活动分页数据 | ||
| 108 | + * | ||
| 109 | + * @param pageParam 分页请求 | ||
| 110 | + * @return 拼团活动分页 | ||
| 111 | + */ | ||
| 112 | + PageResult<CombinationActivityDO> getCombinationActivityPage(PageParam pageParam); | ||
| 113 | + | ||
| 86 | } | 114 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java
| @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.service.combination; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.service.combination; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.util.ObjectUtil; | 4 | import cn.hutool.core.util.ObjectUtil; |
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 8 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 8 | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | 9 | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; |
| @@ -223,8 +224,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | @@ -223,8 +224,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | ||
| 223 | throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); | 224 | throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE); |
| 224 | } | 225 | } |
| 225 | // 1.3 校验是否超出单次限购数量 | 226 | // 1.3 校验是否超出单次限购数量 |
| 226 | - // TODO puhui999:count > activity.getSingleLimitCount() 会更好理解点; | ||
| 227 | - if (activity.getSingleLimitCount() < count) { | 227 | + if (count > activity.getSingleLimitCount()) { |
| 228 | throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); | 228 | throw exception(COMBINATION_RECORD_FAILED_SINGLE_LIMIT_COUNT_EXCEED); |
| 229 | } | 229 | } |
| 230 | 230 | ||
| @@ -245,4 +245,14 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | @@ -245,4 +245,14 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic | ||
| 245 | } | 245 | } |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | + @Override | ||
| 249 | + public List<CombinationActivityDO> getCombinationActivityListByCount(Integer count) { | ||
| 250 | + return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count); | ||
| 251 | + } | ||
| 252 | + | ||
| 253 | + @Override | ||
| 254 | + public PageResult<CombinationActivityDO> getCombinationActivityPage(PageParam pageParam) { | ||
| 255 | + return combinationActivityMapper.selectPage(pageParam, CommonStatusEnum.ENABLE.getStatus()); | ||
| 256 | + } | ||
| 257 | + | ||
| 248 | } | 258 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationRecordServiceImpl.java
| @@ -96,12 +96,15 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -96,12 +96,15 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 96 | return recordDO; | 96 | return recordDO; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | + // TODO @puhui999:有一个应该在创建那要做下;就是当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先; | ||
| 100 | + | ||
| 99 | @Override | 101 | @Override |
| 100 | @Transactional(rollbackFor = Exception.class) | 102 | @Transactional(rollbackFor = Exception.class) |
| 101 | public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { | 103 | public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) { |
| 102 | // 1.1 校验拼团活动 | 104 | // 1.1 校验拼团活动 |
| 103 | CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId()); | 105 | CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId()); |
| 104 | // 1.2 需要校验下,他当前是不是已经参加了该拼团; | 106 | // 1.2 需要校验下,他当前是不是已经参加了该拼团; |
| 107 | + // TODO @puhui999:拼团应该可以重复参加;应该去校验总共的上限哈,就是 activity.totalLimitCount | ||
| 105 | CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId()); | 108 | CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId()); |
| 106 | if (recordDO != null) { | 109 | if (recordDO != null) { |
| 107 | throw exception(COMBINATION_RECORD_EXISTS); | 110 | throw exception(COMBINATION_RECORD_EXISTS); |
| @@ -111,6 +114,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -111,6 +114,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 111 | if (CollUtil.isNotEmpty(recordDOList)) { | 114 | if (CollUtil.isNotEmpty(recordDOList)) { |
| 112 | throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED); | 115 | throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED); |
| 113 | } | 116 | } |
| 117 | + // TODO @puhui999:有个开始时间未校验 | ||
| 114 | // 1.4 校验当前活动是否过期 | 118 | // 1.4 校验当前活动是否过期 |
| 115 | if (LocalDateTime.now().isAfter(activity.getEndTime())) { | 119 | if (LocalDateTime.now().isAfter(activity.getEndTime())) { |
| 116 | throw exception(COMBINATION_RECORD_FAILED_TIME_END); | 120 | throw exception(COMBINATION_RECORD_FAILED_TIME_END); |
| @@ -128,6 +132,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | @@ -128,6 +132,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService { | ||
| 128 | } | 132 | } |
| 129 | } | 133 | } |
| 130 | 134 | ||
| 135 | + // TODO @puhui999:单次限购 | ||
| 136 | + | ||
| 131 | // 2. 创建拼团记录 | 137 | // 2. 创建拼团记录 |
| 132 | MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); | 138 | MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId()); |
| 133 | ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); | 139 | ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId()); |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
| @@ -37,11 +37,11 @@ public interface SeckillActivityService { | @@ -37,11 +37,11 @@ public interface SeckillActivityService { | ||
| 37 | /** | 37 | /** |
| 38 | * 更新秒杀库存 | 38 | * 更新秒杀库存 |
| 39 | * | 39 | * |
| 40 | - * @param activityId 活动编号 | 40 | + * @param id 活动编号 |
| 41 | * @param skuId sku 编号 | 41 | * @param skuId sku 编号 |
| 42 | * @param count 数量 | 42 | * @param count 数量 |
| 43 | */ | 43 | */ |
| 44 | - void updateSeckillStock(Long activityId, Long skuId, Integer count); | 44 | + void updateSeckillStock(Long id, Long skuId, Integer count); |
| 45 | 45 | ||
| 46 | /** | 46 | /** |
| 47 | * 关闭秒杀活动 | 47 | * 关闭秒杀活动 |
| @@ -98,6 +98,15 @@ public interface SeckillActivityService { | @@ -98,6 +98,15 @@ public interface SeckillActivityService { | ||
| 98 | List<SeckillActivityDO> getSeckillActivityListByConfigIds(Collection<Long> ids); | 98 | List<SeckillActivityDO> getSeckillActivityListByConfigIds(Collection<Long> ids); |
| 99 | 99 | ||
| 100 | /** | 100 | /** |
| 101 | + * 通过活动时段编号获取指定 status 的秒杀活动 | ||
| 102 | + * | ||
| 103 | + * @param configId 时段配置编号 | ||
| 104 | + * @param status 状态 | ||
| 105 | + * @return 秒杀活动列表 | ||
| 106 | + */ | ||
| 107 | + List<SeckillActivityDO> getSeckillActivityListByConfigIdAndStatus(Long configId, Integer status); | ||
| 108 | + | ||
| 109 | + /** | ||
| 101 | * 通过活动时段获取秒杀活动 | 110 | * 通过活动时段获取秒杀活动 |
| 102 | * | 111 | * |
| 103 | * @param pageReqVO 请求 | 112 | * @param pageReqVO 请求 |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.seckill; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.promotion.service.seckill; | ||
| 3 | import cn.hutool.core.util.ObjectUtil; | 3 | import cn.hutool.core.util.ObjectUtil; |
| 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 7 | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | 6 | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; |
| 8 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | 7 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; |
| 9 | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | 8 | import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; |
| @@ -31,6 +30,7 @@ import java.util.Map; | @@ -31,6 +30,7 @@ import java.util.Map; | ||
| 31 | import static cn.hutool.core.collection.CollUtil.isNotEmpty; | 30 | import static cn.hutool.core.collection.CollUtil.isNotEmpty; |
| 32 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 31 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 33 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | 32 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; |
| 33 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween; | ||
| 34 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; | 34 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS; |
| 35 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; | 35 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS; |
| 36 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 36 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| @@ -148,32 +148,26 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | @@ -148,32 +148,26 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||
| 148 | 148 | ||
| 149 | @Override | 149 | @Override |
| 150 | @Transactional(rollbackFor = Exception.class) | 150 | @Transactional(rollbackFor = Exception.class) |
| 151 | - public void updateSeckillStock(Long activityId, Long skuId, Integer count) { | ||
| 152 | - // 1、校验秒杀活动是否存在 | ||
| 153 | - SeckillActivityDO seckillActivity = getSeckillActivity(activityId); | ||
| 154 | - // 1.1、校验库存是否充足 | ||
| 155 | - if (seckillActivity.getTotalStock() < count) { | 151 | + public void updateSeckillStock(Long id, Long skuId, Integer count) { |
| 152 | + // 1.1 校验活动库存是否充足 | ||
| 153 | + SeckillActivityDO seckillActivity = getSeckillActivity(id); | ||
| 154 | + if (count > seckillActivity.getTotalStock()) { | ||
| 156 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | 155 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); |
| 157 | } | 156 | } |
| 158 | - | ||
| 159 | - // 2、获取活动商品 | ||
| 160 | - List<SeckillProductDO> products = getSeckillProductListByActivityId(activityId); | ||
| 161 | - // 2.1、过滤出购买的商品 | ||
| 162 | - SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(skuId, item.getSkuId())); | ||
| 163 | - // 2.2、检查活动商品库存是否充足 | ||
| 164 | - boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < count) || (product.getStock() - count) < 0); | ||
| 165 | - if (isSufficient) { | 157 | + // 1.2 校验商品库存是否充足 |
| 158 | + SeckillProductDO product = seckillProductMapper.selectByActivityIdAndSkuId(id, skuId); | ||
| 159 | + if (product == null || count > product.getStock()) { | ||
| 166 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | 160 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); |
| 167 | } | 161 | } |
| 168 | 162 | ||
| 169 | - // 3、更新活动商品库存 | ||
| 170 | - int updateCount = seckillProductMapper.updateActivityStock(product.getId(), count); | 163 | + // 2.1 更新活动商品库存 |
| 164 | + int updateCount = seckillProductMapper.updateStock(product.getId(), count); | ||
| 171 | if (updateCount == 0) { | 165 | if (updateCount == 0) { |
| 172 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | 166 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); |
| 173 | } | 167 | } |
| 174 | 168 | ||
| 175 | - // 4、更新活动库存 | ||
| 176 | - updateCount = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), count); | 169 | + // 2.2 更新活动库存 |
| 170 | + updateCount = seckillActivityMapper.updateStock(seckillActivity.getId(), count); | ||
| 177 | if (updateCount == 0) { | 171 | if (updateCount == 0) { |
| 178 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); | 172 | throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); |
| 179 | } | 173 | } |
| @@ -268,8 +262,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | @@ -268,8 +262,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { | ||
| 268 | 262 | ||
| 269 | @Override | 263 | @Override |
| 270 | public List<SeckillActivityDO> getSeckillActivityListByConfigIds(Collection<Long> ids) { | 264 | public List<SeckillActivityDO> getSeckillActivityListByConfigIds(Collection<Long> ids) { |
| 271 | - return CollectionUtils.filterList(seckillActivityMapper.selectList(), | ||
| 272 | - item -> CollectionUtils.anyMatch(item.getConfigIds(), ids::contains)); | 265 | + return filterList(seckillActivityMapper.selectList(), |
| 266 | + item -> anyMatch(item.getConfigIds(), ids::contains)); | ||
| 267 | + } | ||
| 268 | + | ||
| 269 | + @Override | ||
| 270 | + public List<SeckillActivityDO> getSeckillActivityListByConfigIdAndStatus(Long configId, Integer status) { | ||
| 271 | + return filterList(seckillActivityMapper.selectList(SeckillActivityDO::getStatus, status), | ||
| 272 | + item -> anyMatch(item.getConfigIds(), id -> ObjectUtil.equal(id, configId)) // 校验时段 | ||
| 273 | + && isBetween(item.getStartTime(), item.getEndTime())); // 追加当前日期是否处在活动日期之间的校验条件 | ||
| 273 | } | 274 | } |
| 274 | 275 | ||
| 275 | @Override | 276 | @Override |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigService.java
| @@ -54,6 +54,7 @@ public interface SeckillConfigService { | @@ -54,6 +54,7 @@ public interface SeckillConfigService { | ||
| 54 | */ | 54 | */ |
| 55 | List<SeckillConfigDO> getSeckillConfigList(); | 55 | List<SeckillConfigDO> getSeckillConfigList(); |
| 56 | 56 | ||
| 57 | + | ||
| 57 | /** | 58 | /** |
| 58 | * 校验秒杀时段是否存在 | 59 | * 校验秒杀时段是否存在 |
| 59 | * | 60 | * |
| @@ -85,4 +86,12 @@ public interface SeckillConfigService { | @@ -85,4 +86,12 @@ public interface SeckillConfigService { | ||
| 85 | */ | 86 | */ |
| 86 | void updateSeckillConfigStatus(Long id, Integer status); | 87 | void updateSeckillConfigStatus(Long id, Integer status); |
| 87 | 88 | ||
| 89 | + /** | ||
| 90 | + * 获取当前日期时间处于的秒杀时段且状态为 status | ||
| 91 | + * | ||
| 92 | + * @param status 状态 | ||
| 93 | + * @return 时段 | ||
| 94 | + */ | ||
| 95 | + SeckillConfigDO getSeckillConfigListByStatusOnCurrentTime(Integer status); | ||
| 96 | + | ||
| 88 | } | 97 | } |
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillConfigServiceImpl.java
| @@ -20,6 +20,8 @@ import java.util.Collection; | @@ -20,6 +20,8 @@ import java.util.Collection; | ||
| 20 | import java.util.List; | 20 | import java.util.List; |
| 21 | 21 | ||
| 22 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 22 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 23 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst; | ||
| 24 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween; | ||
| 23 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; | 25 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; |
| 24 | 26 | ||
| 25 | /** | 27 | /** |
| @@ -68,6 +70,12 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { | @@ -68,6 +70,12 @@ public class SeckillConfigServiceImpl implements SeckillConfigService { | ||
| 68 | } | 70 | } |
| 69 | 71 | ||
| 70 | @Override | 72 | @Override |
| 73 | + public SeckillConfigDO getSeckillConfigListByStatusOnCurrentTime(Integer status) { | ||
| 74 | + return findFirst(seckillConfigMapper.selectList(SeckillConfigDO::getStatus, status), | ||
| 75 | + config -> isBetween(config.getStartTime(), config.getEndTime())); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + @Override | ||
| 71 | public void deleteSeckillConfig(Long id) { | 79 | public void deleteSeckillConfig(Long id) { |
| 72 | // 校验存在 | 80 | // 校验存在 |
| 73 | validateSeckillConfigExists(id); | 81 | validateSeckillConfigExists(id); |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
| @@ -12,12 +12,6 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | @@ -12,12 +12,6 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; | ||
| 12 | public interface ErrorCodeConstants { | 12 | public interface ErrorCodeConstants { |
| 13 | 13 | ||
| 14 | // ========== Order 模块 1011000000 ========== | 14 | // ========== Order 模块 1011000000 ========== |
| 15 | - ErrorCode ORDER_CREATE_SKU_NOT_FOUND = new ErrorCode(1011000001, "商品 SKU 不存在"); | ||
| 16 | - ErrorCode ORDER_CREATE_SPU_NOT_SALE = new ErrorCode(1011000002, "商品 SPU 不可售卖"); | ||
| 17 | - ErrorCode ORDER_CREATE_SKU_STOCK_NOT_ENOUGH = new ErrorCode(1011000004, "商品 SKU 库存不足"); | ||
| 18 | - ErrorCode ORDER_CREATE_SPU_NOT_FOUND = new ErrorCode(1011000005, "商品 SPU 不可售卖"); | ||
| 19 | - ErrorCode ORDER_CREATE_ADDRESS_NOT_FOUND = new ErrorCode(1011000006, "收货地址不存在"); | ||
| 20 | - | ||
| 21 | ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在"); | 15 | ErrorCode ORDER_ITEM_NOT_FOUND = new ErrorCode(1011000010, "交易订单项不存在"); |
| 22 | ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在"); | 16 | ErrorCode ORDER_NOT_FOUND = new ErrorCode(1011000011, "交易订单不存在"); |
| 23 | ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试"); | 17 | ErrorCode ORDER_ITEM_UPDATE_AFTER_SALE_STATUS_FAIL = new ErrorCode(1011000012, "交易订单项更新售后状态失败,请重试"); |
| @@ -37,6 +31,7 @@ public interface ErrorCodeConstants { | @@ -37,6 +31,7 @@ public interface ErrorCodeConstants { | ||
| 37 | ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1011000026, "支付订单调价失败,原因:支付订单已付款,不能调价"); | 31 | ErrorCode ORDER_UPDATE_PRICE_FAIL_PAID = new ErrorCode(1011000026, "支付订单调价失败,原因:支付订单已付款,不能调价"); |
| 38 | ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1011000027, "支付订单调价失败,原因:价格没有变化"); | 32 | ErrorCode ORDER_UPDATE_PRICE_FAIL_EQUAL = new ErrorCode(1011000027, "支付订单调价失败,原因:价格没有变化"); |
| 39 | ErrorCode ORDER_UPDATE_PRICE_FAIL_NOT_ITEM = new ErrorCode(1011000028, "支付订单调价失败,原因:订单项不存在"); | 33 | ErrorCode ORDER_UPDATE_PRICE_FAIL_NOT_ITEM = new ErrorCode(1011000028, "支付订单调价失败,原因:订单项不存在"); |
| 34 | + ErrorCode ORDER_DELETE_FAIL_STATUS_NOT_CANCEL = new ErrorCode(1011000029, "交易订单删除失败,订单不是【已取消】状态"); | ||
| 40 | 35 | ||
| 41 | // ========== After Sale 模块 1011000100 ========== | 36 | // ========== After Sale 模块 1011000100 ========== |
| 42 | ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); | 37 | ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1011000100, "售后单不存在"); |
| @@ -58,9 +53,8 @@ public interface ErrorCodeConstants { | @@ -58,9 +53,8 @@ public interface ErrorCodeConstants { | ||
| 58 | 53 | ||
| 59 | // ========== Price 相关 1011003000 ============ | 54 | // ========== Price 相关 1011003000 ============ |
| 60 | ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0"); | 55 | ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0"); |
| 61 | - ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDRESS_IS_EMPTY = new ErrorCode(1011003001, "计算快递运费异常,收件人地址编号为空"); | ||
| 62 | ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板"); | 56 | ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板"); |
| 63 | - ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_PICK_UP_STORE_IS_EMPTY = new ErrorCode(1011003003, "计算快递运费异常,自提点为空"); | 57 | + ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1011003004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵"); |
| 64 | 58 | ||
| 65 | // ========== 物流 Express 模块 1011004000 ========== | 59 | // ========== 物流 Express 模块 1011004000 ========== |
| 66 | ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在"); | 60 | ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在"); |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/order/TradeOrderOperateTypeEnum.java
| @@ -14,7 +14,10 @@ import lombok.RequiredArgsConstructor; | @@ -14,7 +14,10 @@ import lombok.RequiredArgsConstructor; | ||
| 14 | public enum TradeOrderOperateTypeEnum { | 14 | public enum TradeOrderOperateTypeEnum { |
| 15 | 15 | ||
| 16 | MEMBER_CREATE(1, "用户下单"), | 16 | MEMBER_CREATE(1, "用户下单"), |
| 17 | - TEST(2, "用户({nickname})做了({thing})"), | 17 | + MEMBER_RECEIVE(30, "用户已收货"), |
| 18 | + MEMBER_COMMENT(31, "用户评价"), | ||
| 19 | + MEMBER_CANCEL(40, "取消订单"), | ||
| 20 | + MEMBER_DELETE(41, "删除订单"), | ||
| 18 | ; | 21 | ; |
| 19 | 22 | ||
| 20 | /** | 23 | /** |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
| @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | @@ -8,11 +8,11 @@ import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||
| 8 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | 8 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; |
| 9 | import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; | 9 | import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO; |
| 10 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.*; | 10 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.*; |
| 11 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO; | ||
| 11 | import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; | 12 | import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; |
| 12 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; | 13 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; |
| 13 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 14 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 14 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | 15 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 15 | -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO; | ||
| 16 | import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; | 16 | import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; |
| 17 | import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; | 17 | import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService; |
| 18 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; | 18 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; |
| @@ -87,13 +87,13 @@ public class TradeAfterSaleController { | @@ -87,13 +87,13 @@ public class TradeAfterSaleController { | ||
| 87 | // 拼接数据 | 87 | // 拼接数据 |
| 88 | MemberUserRespDTO user = memberUserApi.getUser(afterSale.getUserId()); | 88 | MemberUserRespDTO user = memberUserApi.getUser(afterSale.getUserId()); |
| 89 | // 获取售后日志 | 89 | // 获取售后日志 |
| 90 | - List<TradeAfterSaleLogRespDTO> logs = afterSaleLogService.getLog(afterSale.getId()); | 90 | + List<TradeAfterSaleLogRespVO> logs = afterSaleLogService.getLog(afterSale.getId()); |
| 91 | // TODO 方便测试看效果,review 后移除 | 91 | // TODO 方便测试看效果,review 后移除 |
| 92 | if (logs == null) { | 92 | if (logs == null) { |
| 93 | logs = new ArrayList<>(); | 93 | logs = new ArrayList<>(); |
| 94 | } | 94 | } |
| 95 | for (int i = 1; i <= 6; i++) { | 95 | for (int i = 1; i <= 6; i++) { |
| 96 | - TradeAfterSaleLogRespDTO respVO = new TradeAfterSaleLogRespDTO(); | 96 | + TradeAfterSaleLogRespVO respVO = new TradeAfterSaleLogRespVO(); |
| 97 | respVO.setId((long) i); | 97 | respVO.setId((long) i); |
| 98 | respVO.setUserId((long) i); | 98 | respVO.setUserId((long) i); |
| 99 | respVO.setUserType(i % 2 == 0 ? 2 : 1); | 99 | respVO.setUserType(i % 2 == 0 ? 2 : 1); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
| @@ -156,7 +156,7 @@ public class AppTradeOrderController { | @@ -156,7 +156,7 @@ public class AppTradeOrderController { | ||
| 156 | @Operation(summary = "删除交易订单") | 156 | @Operation(summary = "删除交易订单") |
| 157 | @Parameter(name = "id", description = "交易订单编号") | 157 | @Parameter(name = "id", description = "交易订单编号") |
| 158 | public CommonResult<Boolean> deleteOrder(@RequestParam("id") Long id) { | 158 | public CommonResult<Boolean> deleteOrder(@RequestParam("id") Long id) { |
| 159 | - // TODO @芋艿:未实现,mock 用 | 159 | + tradeOrderUpdateService.deleteOrder(getLoginUserId(), id); |
| 160 | return success(true); | 160 | return success(true); |
| 161 | } | 161 | } |
| 162 | 162 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java
| @@ -82,6 +82,9 @@ public class AppTradeOrderSettlementRespVO { | @@ -82,6 +82,9 @@ public class AppTradeOrderSettlementRespVO { | ||
| 82 | @Schema(description = "积分抵扣的金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") | 82 | @Schema(description = "积分抵扣的金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") |
| 83 | private Integer pointPrice; | 83 | private Integer pointPrice; |
| 84 | 84 | ||
| 85 | + @Schema(description = "VIP 减免金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "30") | ||
| 86 | + private Integer vipPrice; | ||
| 87 | + | ||
| 85 | @Schema(description = "实际支付金额(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "450") | 88 | @Schema(description = "实际支付金额(总),单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "450") |
| 86 | private Integer payPrice; | 89 | private Integer payPrice; |
| 87 | 90 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/TradeAfterSaleConvert.java
| @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; | @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO; | ||
| 16 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; | 16 | import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleLogDO; |
| 17 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 17 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 18 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | 18 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 19 | -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO; | ||
| 20 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; | 19 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; |
| 21 | import org.mapstruct.Mapper; | 20 | import org.mapstruct.Mapper; |
| 22 | import org.mapstruct.Mapping; | 21 | import org.mapstruct.Mapping; |
| @@ -68,10 +67,10 @@ public interface TradeAfterSaleConvert { | @@ -68,10 +67,10 @@ public interface TradeAfterSaleConvert { | ||
| 68 | 67 | ||
| 69 | PageResult<AppTradeAfterSaleRespVO> convertPage02(PageResult<TradeAfterSaleDO> page); | 68 | PageResult<AppTradeAfterSaleRespVO> convertPage02(PageResult<TradeAfterSaleDO> page); |
| 70 | 69 | ||
| 71 | - List<TradeAfterSaleLogRespDTO> convertList(List<TradeAfterSaleLogDO> list); | ||
| 72 | - | 70 | + List<TradeAfterSaleLogRespVO> convertList(List<TradeAfterSaleLogDO> list); |
| 71 | + | ||
| 73 | default TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, TradeOrderDO order, List<TradeOrderItemDO> orderItems, | 72 | default TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, TradeOrderDO order, List<TradeOrderItemDO> orderItems, |
| 74 | - MemberUserRespDTO user, List<TradeAfterSaleLogRespDTO> logs) { | 73 | + MemberUserRespDTO user, List<TradeAfterSaleLogRespVO> logs) { |
| 75 | TradeAfterSaleDetailRespVO respVO = convert(afterSale, orderItems); | 74 | TradeAfterSaleDetailRespVO respVO = convert(afterSale, orderItems); |
| 76 | // 处理用户信息 | 75 | // 处理用户信息 |
| 77 | respVO.setUser(convert(user)); | 76 | respVO.setUser(convert(user)); |
| @@ -81,7 +80,8 @@ public interface TradeAfterSaleConvert { | @@ -81,7 +80,8 @@ public interface TradeAfterSaleConvert { | ||
| 81 | respVO.setLogs(convertList1(logs)); | 80 | respVO.setLogs(convertList1(logs)); |
| 82 | return respVO; | 81 | return respVO; |
| 83 | } | 82 | } |
| 84 | - List<TradeAfterSaleLogRespVO> convertList1(List<TradeAfterSaleLogRespDTO> list); | 83 | + |
| 84 | + List<TradeAfterSaleLogRespVO> convertList1(List<TradeAfterSaleLogRespVO> list); | ||
| 85 | @Mapping(target = "id", source = "afterSale.id") | 85 | @Mapping(target = "id", source = "afterSale.id") |
| 86 | TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, List<TradeOrderItemDO> orderItems); | 86 | TradeAfterSaleDetailRespVO convert(TradeAfterSaleDO afterSale, List<TradeOrderItemDO> orderItems); |
| 87 | TradeOrderBaseVO convert(TradeOrderDO order); | 87 | TradeOrderBaseVO convert(TradeOrderDO order); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
| @@ -65,6 +65,7 @@ public interface TradeOrderConvert { | @@ -65,6 +65,7 @@ public interface TradeOrderConvert { | ||
| 65 | @Mapping(source = "calculateRespBO.price.deliveryPrice", target = "deliveryPrice"), | 65 | @Mapping(source = "calculateRespBO.price.deliveryPrice", target = "deliveryPrice"), |
| 66 | @Mapping(source = "calculateRespBO.price.couponPrice", target = "couponPrice"), | 66 | @Mapping(source = "calculateRespBO.price.couponPrice", target = "couponPrice"), |
| 67 | @Mapping(source = "calculateRespBO.price.pointPrice", target = "pointPrice"), | 67 | @Mapping(source = "calculateRespBO.price.pointPrice", target = "pointPrice"), |
| 68 | + @Mapping(source = "calculateRespBO.price.vipPrice", target = "vipPrice"), | ||
| 68 | @Mapping(source = "calculateRespBO.price.payPrice", target = "payPrice") | 69 | @Mapping(source = "calculateRespBO.price.payPrice", target = "payPrice") |
| 69 | }) | 70 | }) |
| 70 | TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, | 71 | TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderDO.java
| @@ -168,6 +168,7 @@ public class TradeOrderDO extends BaseDO { | @@ -168,6 +168,7 @@ public class TradeOrderDO extends BaseDO { | ||
| 168 | * - {@link #discountPrice} | 168 | * - {@link #discountPrice} |
| 169 | * + {@link #deliveryPrice} | 169 | * + {@link #deliveryPrice} |
| 170 | * + {@link #adjustPrice} | 170 | * + {@link #adjustPrice} |
| 171 | + * - {@link #vipPrice} | ||
| 171 | */ | 172 | */ |
| 172 | private Integer payPrice; | 173 | private Integer payPrice; |
| 173 | 174 | ||
| @@ -273,5 +274,9 @@ public class TradeOrderDO extends BaseDO { | @@ -273,5 +274,9 @@ public class TradeOrderDO extends BaseDO { | ||
| 273 | * 退还的使用的积分 | 274 | * 退还的使用的积分 |
| 274 | */ | 275 | */ |
| 275 | private Integer refundPoint; | 276 | private Integer refundPoint; |
| 277 | + /** | ||
| 278 | + * VIP 减免金额,单位:分 | ||
| 279 | + */ | ||
| 280 | + private Integer vipPrice; | ||
| 276 | 281 | ||
| 277 | } | 282 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java
| @@ -126,6 +126,7 @@ public class TradeOrderItemDO extends BaseDO { | @@ -126,6 +126,7 @@ public class TradeOrderItemDO extends BaseDO { | ||
| 126 | * - {@link #discountPrice} | 126 | * - {@link #discountPrice} |
| 127 | * + {@link #deliveryPrice} | 127 | * + {@link #deliveryPrice} |
| 128 | * + {@link #adjustPrice} | 128 | * + {@link #adjustPrice} |
| 129 | + * - {@link #vipPrice} | ||
| 129 | */ | 130 | */ |
| 130 | private Integer payPrice; | 131 | private Integer payPrice; |
| 131 | 132 | ||
| @@ -151,6 +152,10 @@ public class TradeOrderItemDO extends BaseDO { | @@ -151,6 +152,10 @@ public class TradeOrderItemDO extends BaseDO { | ||
| 151 | * 赠送的积分 | 152 | * 赠送的积分 |
| 152 | */ | 153 | */ |
| 153 | private Integer givePoint; | 154 | private Integer givePoint; |
| 155 | + /** | ||
| 156 | + * VIP 减免金额,单位:分 | ||
| 157 | + */ | ||
| 158 | + private Integer vipPrice; | ||
| 154 | // TODO @芋艿:如果商品 vip 折扣时,到底是新增一个 vipPrice 记录优惠记录,还是 vipDiscountPrice,记录 vip 的优惠;还是直接使用 vipPrice; | 159 | // TODO @芋艿:如果商品 vip 折扣时,到底是新增一个 vipPrice 记录优惠记录,还是 vipDiscountPrice,记录 vip 的优惠;还是直接使用 vipPrice; |
| 155 | // 目前 crmeb 的选择,单独一个 vipPrice 记录优惠价格;感觉不一定合理,可以在看看有赞的; | 160 | // 目前 crmeb 的选择,单独一个 vipPrice 记录优惠价格;感觉不一定合理,可以在看看有赞的; |
| 156 | 161 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/dto/TradeAfterSaleLogRespDTO.java deleted
| 1 | -package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto; | ||
| 2 | - | ||
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | -import lombok.AllArgsConstructor; | ||
| 5 | -import lombok.Data; | ||
| 6 | -import lombok.NoArgsConstructor; | ||
| 7 | - | ||
| 8 | -import javax.validation.constraints.NotNull; | ||
| 9 | -import java.time.LocalDateTime; | ||
| 10 | - | ||
| 11 | -// TODO @puhui999:这个是不是应该搞成 vo 啊? | ||
| 12 | -/** | ||
| 13 | - * 贸易售后日志详情 DTO | ||
| 14 | - * | ||
| 15 | - * @author HUIHUI | ||
| 16 | - */ | ||
| 17 | -@Data | ||
| 18 | -@NoArgsConstructor | ||
| 19 | -@AllArgsConstructor | ||
| 20 | -public class TradeAfterSaleLogRespDTO { | ||
| 21 | - | ||
| 22 | - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20669") | ||
| 23 | - private Long id; | ||
| 24 | - | ||
| 25 | - @Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "22634") | ||
| 26 | - @NotNull(message = "用户编号不能为空") | ||
| 27 | - private Long userId; | ||
| 28 | - | ||
| 29 | - @Schema(description = "用户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") | ||
| 30 | - @NotNull(message = "用户类型不能为空") | ||
| 31 | - private Integer userType; | ||
| 32 | - | ||
| 33 | - @Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3023") | ||
| 34 | - @NotNull(message = "售后编号不能为空") | ||
| 35 | - private Long afterSaleId; | ||
| 36 | - | ||
| 37 | - @Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "25870") | ||
| 38 | - @NotNull(message = "订单编号不能为空") | ||
| 39 | - private Long orderId; | ||
| 40 | - | ||
| 41 | - @Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23154") | ||
| 42 | - @NotNull(message = "订单项编号不能为空") | ||
| 43 | - private Long orderItemId; | ||
| 44 | - | ||
| 45 | - @Schema(description = "售后状态(之前)", example = "2") | ||
| 46 | - private Integer beforeStatus; | ||
| 47 | - | ||
| 48 | - @Schema(description = "售后状态(之后)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 49 | - @NotNull(message = "售后状态(之后)不能为空") | ||
| 50 | - private Integer afterStatus; | ||
| 51 | - | ||
| 52 | - @Schema(description = "操作明细", requiredMode = Schema.RequiredMode.REQUIRED, example = "维权完成,退款金额:¥37776.00") | ||
| 53 | - @NotNull(message = "操作明细不能为空") | ||
| 54 | - private String content; | ||
| 55 | - | ||
| 56 | - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 57 | - private LocalDateTime createTime; | ||
| 58 | - | ||
| 59 | -} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersalelog/core/service/AfterSaleLogService.java
| 1 | package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service; | 1 | package cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO; | ||
| 4 | import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; | 5 | import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; |
| 5 | -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO; | ||
| 6 | 6 | ||
| 7 | import java.util.List; | 7 | import java.util.List; |
| 8 | 8 | ||
| @@ -29,6 +29,6 @@ public interface AfterSaleLogService { | @@ -29,6 +29,6 @@ public interface AfterSaleLogService { | ||
| 29 | * @param afterSaleId 售后编号 | 29 | * @param afterSaleId 售后编号 |
| 30 | * @return 售后日志 | 30 | * @return 售后日志 |
| 31 | */ | 31 | */ |
| 32 | - List<TradeAfterSaleLogRespDTO> getLog(Long afterSaleId); | 32 | + List<TradeAfterSaleLogRespVO> getLog(Long afterSaleId); |
| 33 | 33 | ||
| 34 | } | 34 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java
| @@ -63,6 +63,9 @@ public class TradeOrderLogAspect { | @@ -63,6 +63,9 @@ public class TradeOrderLogAspect { | ||
| 63 | Long userId = getUserId(); | 63 | Long userId = getUserId(); |
| 64 | // 1.2 订单信息 | 64 | // 1.2 订单信息 |
| 65 | Long orderId = ORDER_ID.get(); | 65 | Long orderId = ORDER_ID.get(); |
| 66 | + if (orderId == null) { // 如果未设置,只有注解,说明不需要记录订单日志 | ||
| 67 | + return; | ||
| 68 | + } | ||
| 66 | Integer beforeStatus = BEFORE_STATUS.get(); | 69 | Integer beforeStatus = BEFORE_STATUS.get(); |
| 67 | Integer afterStatus = AFTER_STATUS.get(); | 70 | Integer afterStatus = AFTER_STATUS.get(); |
| 68 | Map<String, Object> exts = ObjectUtil.defaultIfNull(EXTS.get(), emptyMap()); | 71 | Map<String, Object> exts = ObjectUtil.defaultIfNull(EXTS.get(), emptyMap()); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/TradeAfterSaleServiceImpl.java
| @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | ||
| 11 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; | 11 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleDisagreeReqVO; |
| 12 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; | 12 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO; |
| 13 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; | 13 | import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO; |
| 14 | +import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.log.TradeAfterSaleLogRespVO; | ||
| 14 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; | 15 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO; |
| 15 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; | 16 | import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleDeliveryReqVO; |
| 16 | import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; | 17 | import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert; |
| @@ -26,7 +27,6 @@ import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; | @@ -26,7 +27,6 @@ import cn.iocoder.yudao.module.trade.enums.aftersale.TradeAfterSaleWayEnum; | ||
| 26 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; | 27 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum; |
| 27 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; | 28 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; |
| 28 | import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; | 29 | import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogCreateReqDTO; |
| 29 | -import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.dto.TradeAfterSaleLogRespDTO; | ||
| 30 | import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; | 30 | import cn.iocoder.yudao.module.trade.framework.aftersalelog.core.service.AfterSaleLogService; |
| 31 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; | 31 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; |
| 32 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; | 32 | import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService; |
| @@ -449,8 +449,9 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa | @@ -449,8 +449,9 @@ public class TradeAfterSaleServiceImpl implements TradeAfterSaleService, AfterSa | ||
| 449 | } | 449 | } |
| 450 | } | 450 | } |
| 451 | 451 | ||
| 452 | + // TODO @puhui999:应该返回 do 哈。 | ||
| 452 | @Override | 453 | @Override |
| 453 | - public List<TradeAfterSaleLogRespDTO> getLog(Long afterSaleId) { | 454 | + public List<TradeAfterSaleLogRespVO> getLog(Long afterSaleId) { |
| 454 | // TODO 不熟悉流程先这么滴 | 455 | // TODO 不熟悉流程先这么滴 |
| 455 | List<TradeAfterSaleLogDO> saleLogDOs = tradeAfterSaleLogMapper.selectList(TradeAfterSaleLogDO::getAfterSaleId, afterSaleId); | 456 | List<TradeAfterSaleLogDO> saleLogDOs = tradeAfterSaleLogMapper.selectList(TradeAfterSaleLogDO::getAfterSaleId, afterSaleId); |
| 456 | return TradeAfterSaleConvert.INSTANCE.convertList(saleLogDOs); | 457 | return TradeAfterSaleConvert.INSTANCE.convertList(saleLogDOs); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderQueryServiceImpl.java
| @@ -106,7 +106,7 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | @@ -106,7 +106,7 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | ||
| 106 | if (order == null) { | 106 | if (order == null) { |
| 107 | throw exception(ORDER_NOT_FOUND); | 107 | throw exception(ORDER_NOT_FOUND); |
| 108 | } | 108 | } |
| 109 | - | 109 | + // 查询物流 |
| 110 | return getExpressTrackList(order); | 110 | return getExpressTrackList(order); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| @@ -117,7 +117,7 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | @@ -117,7 +117,7 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService { | ||
| 117 | if (order == null) { | 117 | if (order == null) { |
| 118 | throw exception(ORDER_NOT_FOUND); | 118 | throw exception(ORDER_NOT_FOUND); |
| 119 | } | 119 | } |
| 120 | - | 120 | + // 查询物流 |
| 121 | return getExpressTrackList(order); | 121 | return getExpressTrackList(order); |
| 122 | } | 122 | } |
| 123 | 123 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
| @@ -63,6 +63,22 @@ public interface TradeOrderUpdateService { | @@ -63,6 +63,22 @@ public interface TradeOrderUpdateService { | ||
| 63 | void receiveOrder(Long userId, Long id); | 63 | void receiveOrder(Long userId, Long id); |
| 64 | 64 | ||
| 65 | /** | 65 | /** |
| 66 | + * 【会员】取消订单 | ||
| 67 | + * | ||
| 68 | + * @param userId 用户编号 | ||
| 69 | + * @param id 订单编号 | ||
| 70 | + */ | ||
| 71 | + void cancelOrder(Long userId, Long id); | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * 【会员】删除订单 | ||
| 75 | + * | ||
| 76 | + * @param userId 用户编号 | ||
| 77 | + * @param id 订单编号 | ||
| 78 | + */ | ||
| 79 | + void deleteOrder(Long userId, Long id); | ||
| 80 | + | ||
| 81 | + /** | ||
| 66 | * 【管理员】交易订单备注 | 82 | * 【管理员】交易订单备注 |
| 67 | * | 83 | * |
| 68 | * @param reqVO 请求 | 84 | * @param reqVO 请求 |
| @@ -117,11 +133,4 @@ public interface TradeOrderUpdateService { | @@ -117,11 +133,4 @@ public interface TradeOrderUpdateService { | ||
| 117 | */ | 133 | */ |
| 118 | Long createOrderItemComment(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO); | 134 | Long createOrderItemComment(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO); |
| 119 | 135 | ||
| 120 | - /** | ||
| 121 | - * 【会员】取消订单 | ||
| 122 | - * | ||
| 123 | - * @param userId 用户ID | ||
| 124 | - * @param id 订单编号 | ||
| 125 | - */ | ||
| 126 | - void cancelOrder(Long userId, Long id); | ||
| 127 | } | 136 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
| @@ -49,6 +49,7 @@ import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | @@ -49,6 +49,7 @@ import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | ||
| 49 | import cn.iocoder.yudao.module.trade.enums.order.*; | 49 | import cn.iocoder.yudao.module.trade.enums.order.*; |
| 50 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; | 50 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; |
| 51 | import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog; | 51 | import cn.iocoder.yudao.module.trade.framework.order.core.annotations.TradeOrderLog; |
| 52 | +import cn.iocoder.yudao.module.trade.framework.order.core.utils.TradeOrderLogUtils; | ||
| 52 | import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; | 53 | import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService; |
| 53 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; | 54 | import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageAddReqBO; |
| 54 | import cn.iocoder.yudao.module.trade.service.cart.CartService; | 55 | import cn.iocoder.yudao.module.trade.service.cart.CartService; |
| @@ -299,6 +300,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -299,6 +300,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 299 | // 5. 生成预支付 | 300 | // 5. 生成预支付 |
| 300 | createPayOrder(order, orderItems, calculateRespBO); | 301 | createPayOrder(order, orderItems, calculateRespBO); |
| 301 | 302 | ||
| 303 | + // 6. 插入订单日志 | ||
| 304 | + TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus()); | ||
| 305 | + | ||
| 302 | // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! | 306 | // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来! |
| 303 | } | 307 | } |
| 304 | 308 | ||
| @@ -482,6 +486,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -482,6 +486,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 482 | 486 | ||
| 483 | @Override | 487 | @Override |
| 484 | @Transactional(rollbackFor = Exception.class) | 488 | @Transactional(rollbackFor = Exception.class) |
| 489 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_RECEIVE) | ||
| 485 | public void receiveOrder(Long userId, Long id) { | 490 | public void receiveOrder(Long userId, Long id) { |
| 486 | // 校验并获得交易订单(可收货) | 491 | // 校验并获得交易订单(可收货) |
| 487 | TradeOrderDO order = validateOrderReceivable(userId, id); | 492 | TradeOrderDO order = validateOrderReceivable(userId, id); |
| @@ -492,7 +497,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -492,7 +497,6 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 492 | if (updateCount == 0) { | 497 | if (updateCount == 0) { |
| 493 | throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); | 498 | throw exception(ORDER_RECEIVE_FAIL_STATUS_NOT_DELIVERED); |
| 494 | } | 499 | } |
| 495 | - // TODO 芋艿:OrderLog | ||
| 496 | 500 | ||
| 497 | // TODO 芋艿:lili 发送订单变化的消息 | 501 | // TODO 芋艿:lili 发送订单变化的消息 |
| 498 | 502 | ||
| @@ -500,7 +504,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -500,7 +504,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 500 | 504 | ||
| 501 | // TODO 芋艿:销售佣金的记录; | 505 | // TODO 芋艿:销售佣金的记录; |
| 502 | 506 | ||
| 503 | - // TODO 芋艿:获得积分; | 507 | + // 插入订单日志 |
| 508 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus()); | ||
| 504 | } | 509 | } |
| 505 | 510 | ||
| 506 | @Override | 511 | @Override |
| @@ -541,41 +546,49 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -541,41 +546,49 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 541 | tradeOrderMapper.updateById(update); | 546 | tradeOrderMapper.updateById(update); |
| 542 | // TODO @芋艿:改价时,赠送的积分,要不要做改动??? | 547 | // TODO @芋艿:改价时,赠送的积分,要不要做改动??? |
| 543 | 548 | ||
| 544 | - // TODO @puhui999:应该是按照 payPrice 分配;并且要考虑取余问题;payPrice 也要考虑,item 里的 | ||
| 545 | - // TODO:先按 adjustPrice 实现,没明白 payPrice 怎么搞哈哈哈 | ||
| 546 | - // TODO @puhui999:就是对比新老 adjustPrice 的差值,然后计算补充的 adjustPrice 最终值;另外,可以不用区分 items.size 是不是 > 1 哈;应该是一致的逻辑;分摊的逻辑,有点类似 dividePrice 方法噢; | ||
| 547 | // 5、更新 TradeOrderItem | 549 | // 5、更新 TradeOrderItem |
| 548 | - if (items.size() > 1) { | ||
| 549 | - // TradeOrderItemDO 需要做 adjustPrice 的分摊 | ||
| 550 | - int price = reqVO.getAdjustPrice() / items.size(); | ||
| 551 | - int remainderPrice = reqVO.getAdjustPrice() % items.size(); | ||
| 552 | - List<TradeOrderItemDO> orders = new ArrayList<>(); | ||
| 553 | - for (int i = 0; i < items.size(); i++) { | ||
| 554 | - // 把平摊后剩余的金额加到第一个订单项 | ||
| 555 | - if (remainderPrice != 0 && i == 0) { | ||
| 556 | - orders.add(convertOrderItemPrice(items.get(i), price + remainderPrice)); | ||
| 557 | - } | ||
| 558 | - orders.add(convertOrderItemPrice(items.get(i), price)); | ||
| 559 | - } | ||
| 560 | - tradeOrderItemMapper.updateBatch(orders); | ||
| 561 | - } else { | ||
| 562 | - TradeOrderItemDO orderItem = items.get(0); | ||
| 563 | - TradeOrderItemDO updateItem = convertOrderItemPrice(orderItem, reqVO.getAdjustPrice()); | ||
| 564 | - tradeOrderItemMapper.updateById(updateItem); | 550 | + // TradeOrderItemDO 需要做 adjustPrice 的分摊 |
| 551 | + List<Integer> dividePrices = dividePrice(items, orderPayPrice); | ||
| 552 | + List<TradeOrderItemDO> updateItems = new ArrayList<>(); | ||
| 553 | + for (int i = 0; i < items.size(); i++) { | ||
| 554 | + TradeOrderItemDO item = items.get(i); | ||
| 555 | + Integer adjustPrice = item.getPrice() - dividePrices.get(i); // 计算调整的金额 | ||
| 556 | + updateItems.add(new TradeOrderItemDO().setId(item.getId()).setAdjustPrice(adjustPrice) | ||
| 557 | + .setPayPrice(item.getPayPrice() - adjustPrice)); | ||
| 565 | } | 558 | } |
| 559 | + tradeOrderItemMapper.updateBatch(updateItems); | ||
| 560 | + | ||
| 566 | 561 | ||
| 567 | // 6、更新支付订单 | 562 | // 6、更新支付订单 |
| 568 | payOrderApi.updatePayOrderPrice(order.getPayOrderId(), update.getPayPrice()); | 563 | payOrderApi.updatePayOrderPrice(order.getPayOrderId(), update.getPayPrice()); |
| 569 | } | 564 | } |
| 570 | 565 | ||
| 571 | - private TradeOrderItemDO convertOrderItemPrice(TradeOrderItemDO orderItem, Integer price) { | ||
| 572 | - TradeOrderItemDO newOrderItem = new TradeOrderItemDO(); | ||
| 573 | - newOrderItem.setId(orderItem.getId()); | ||
| 574 | - newOrderItem.setAdjustPrice(price); | ||
| 575 | - int payPrice = orderItem.getAdjustPrice() != null ? (orderItem.getPayPrice() - orderItem.getAdjustPrice()) | ||
| 576 | - + price : orderItem.getPayPrice() + price; | ||
| 577 | - newOrderItem.setPayPrice(payPrice); | ||
| 578 | - return newOrderItem; | 566 | + /** |
| 567 | + * 计算订单调价价格分摊 | ||
| 568 | + * | ||
| 569 | + * @param items 订单项 | ||
| 570 | + * @param orderPayPrice 订单支付金额 | ||
| 571 | + * @return 分摊金额数组,和传入的 orderItems 一一对应 | ||
| 572 | + */ | ||
| 573 | + private List<Integer> dividePrice(List<TradeOrderItemDO> items, Integer orderPayPrice) { | ||
| 574 | + Integer total = getSumValue(items, TradeOrderItemDO::getPrice, Integer::sum); | ||
| 575 | + assert total != null; | ||
| 576 | + // 遍历每一个,进行分摊 | ||
| 577 | + List<Integer> prices = new ArrayList<>(items.size()); | ||
| 578 | + int remainPrice = orderPayPrice; | ||
| 579 | + for (int i = 0; i < items.size(); i++) { | ||
| 580 | + TradeOrderItemDO orderItem = items.get(i); | ||
| 581 | + int partPrice; | ||
| 582 | + if (i < items.size() - 1) { // 减一的原因,是因为拆分时,如果按照比例,可能会出现.所以最后一个,使用反减 | ||
| 583 | + partPrice = (int) (orderPayPrice * (1.0D * orderItem.getPayPrice() / total)); | ||
| 584 | + remainPrice -= partPrice; | ||
| 585 | + } else { | ||
| 586 | + partPrice = remainPrice; | ||
| 587 | + } | ||
| 588 | + Assert.isTrue(partPrice >= 0, "分摊金额必须大于等于 0"); | ||
| 589 | + prices.add(partPrice); | ||
| 590 | + } | ||
| 591 | + return prices; | ||
| 579 | } | 592 | } |
| 580 | 593 | ||
| 581 | @Override | 594 | @Override |
| @@ -671,6 +684,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -671,6 +684,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 671 | 684 | ||
| 672 | @Override | 685 | @Override |
| 673 | @Transactional(rollbackFor = Exception.class) | 686 | @Transactional(rollbackFor = Exception.class) |
| 687 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_COMMENT) | ||
| 674 | public Long createOrderItemComment(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO) { | 688 | public Long createOrderItemComment(Long userId, AppTradeOrderItemCommentCreateReqVO createReqVO) { |
| 675 | // 先通过订单项 ID,查询订单项是否存在 | 689 | // 先通过订单项 ID,查询订单项是否存在 |
| 676 | TradeOrderItemDO orderItem = tradeOrderItemMapper.selectByIdAndUserId(createReqVO.getOrderItemId(), userId); | 690 | TradeOrderItemDO orderItem = tradeOrderItemMapper.selectByIdAndUserId(createReqVO.getOrderItemId(), userId); |
| @@ -698,24 +712,27 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -698,24 +712,27 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 698 | List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); | 712 | List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(order.getId()); |
| 699 | if (!anyMatch(orderItems, item -> Objects.equals(item.getCommentStatus(), Boolean.FALSE))) { | 713 | if (!anyMatch(orderItems, item -> Objects.equals(item.getCommentStatus(), Boolean.FALSE))) { |
| 700 | tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE)); | 714 | tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setCommentStatus(Boolean.TRUE)); |
| 701 | - // TODO 待实现:已完成评价,要不要写一条订单日志?目前 crmeb 会写,有赞可以研究下 | 715 | + // 增加订单日志 |
| 716 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus()); | ||
| 702 | } | 717 | } |
| 703 | return comment; | 718 | return comment; |
| 704 | } | 719 | } |
| 705 | 720 | ||
| 706 | @Override | 721 | @Override |
| 722 | + @Transactional(rollbackFor = Exception.class) | ||
| 723 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CANCEL) | ||
| 707 | public void cancelOrder(Long userId, Long id) { | 724 | public void cancelOrder(Long userId, Long id) { |
| 708 | - // 校验存在 | 725 | + // 1.1 校验存在 |
| 709 | TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | 726 | TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); |
| 710 | if (order == null) { | 727 | if (order == null) { |
| 711 | throw exception(ORDER_NOT_FOUND); | 728 | throw exception(ORDER_NOT_FOUND); |
| 712 | } | 729 | } |
| 713 | - // 校验状态 | 730 | + // 1.2 校验状态 |
| 714 | if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { | 731 | if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus())) { |
| 715 | throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | 732 | throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); |
| 716 | } | 733 | } |
| 717 | 734 | ||
| 718 | - // 1.更新 TradeOrderDO 状态为已取消 | 735 | + // 2. 更新 TradeOrderDO 状态为已取消 |
| 719 | int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), | 736 | int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(), |
| 720 | new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) | 737 | new TradeOrderDO().setStatus(TradeOrderStatusEnum.CANCELED.getStatus()) |
| 721 | .setCancelTime(LocalDateTime.now()) | 738 | .setCancelTime(LocalDateTime.now()) |
| @@ -724,22 +741,43 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -724,22 +741,43 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 724 | throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); | 741 | throw exception(ORDER_CANCEL_FAIL_STATUS_NOT_UNPAID); |
| 725 | } | 742 | } |
| 726 | 743 | ||
| 727 | - // TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来 | 744 | + // 3. TODO 活动相关库存回滚需要活动 id,活动 id 怎么获取?app 端能否传过来;回复:从订单里拿呀 |
| 728 | tradeOrderHandlers.forEach(handler -> handler.rollback()); | 745 | tradeOrderHandlers.forEach(handler -> handler.rollback()); |
| 729 | 746 | ||
| 730 | - // 2.回滚库存 | 747 | + // 4. 回滚库存 |
| 731 | List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); | 748 | List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id); |
| 732 | productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); | 749 | productSkuApi.updateSkuStock(TradeOrderConvert.INSTANCE.convert(orderItems)); |
| 733 | 750 | ||
| 734 | - // 3.回滚优惠券 | ||
| 735 | - couponApi.returnUsedCoupon(order.getCouponId()); | 751 | + // 5. 回滚优惠券 |
| 752 | + if (order.getCouponId() > 0) { | ||
| 753 | + couponApi.returnUsedCoupon(order.getCouponId()); | ||
| 754 | + } | ||
| 736 | 755 | ||
| 737 | - // 4.回滚积分(抵扣的) | 756 | + // 6. 回滚积分(抵扣的) |
| 738 | addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); | 757 | addUserPoint(order.getUserId(), order.getUsePoint(), MemberPointBizTypeEnum.ORDER_CANCEL, order.getId()); |
| 739 | 758 | ||
| 740 | - // TODO 芋艿:OrderLog | 759 | + // 7. 增加订单日志 |
| 760 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus()); | ||
| 761 | + } | ||
| 741 | 762 | ||
| 742 | - // TODO 芋艿:lili 发送订单变化的消息 | 763 | + @Override |
| 764 | + @Transactional(rollbackFor = Exception.class) | ||
| 765 | + @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_DELETE) | ||
| 766 | + public void deleteOrder(Long userId, Long id) { | ||
| 767 | + // 1.1 校验存在 | ||
| 768 | + TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(id, userId); | ||
| 769 | + if (order == null) { | ||
| 770 | + throw exception(ORDER_NOT_FOUND); | ||
| 771 | + } | ||
| 772 | + // 1.2 校验状态 | ||
| 773 | + if (ObjectUtil.notEqual(order.getStatus(), TradeOrderStatusEnum.CANCELED.getStatus())) { | ||
| 774 | + throw exception(ORDER_DELETE_FAIL_STATUS_NOT_CANCEL); | ||
| 775 | + } | ||
| 776 | + // 2. 删除订单 | ||
| 777 | + tradeOrderMapper.deleteById(id); | ||
| 778 | + | ||
| 779 | + // 3. 记录日志 | ||
| 780 | + TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), order.getStatus()); | ||
| 743 | } | 781 | } |
| 744 | 782 | ||
| 745 | /** | 783 | /** |
| @@ -766,6 +804,20 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -766,6 +804,20 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 766 | memberLevelApi.addExperience(userId, -refundPrice, bizType, String.valueOf(afterSaleId)); | 804 | memberLevelApi.addExperience(userId, -refundPrice, bizType, String.valueOf(afterSaleId)); |
| 767 | } | 805 | } |
| 768 | 806 | ||
| 807 | + /** | ||
| 808 | + * 添加用户积分 | ||
| 809 | + * <p> | ||
| 810 | + * 目前是支付成功后,就会创建积分记录。 | ||
| 811 | + * <p> | ||
| 812 | + * 业内还有两种做法,可以根据自己的业务调整: | ||
| 813 | + * 1. 确认收货后,才创建积分记录 | ||
| 814 | + * 2. 支付 or 下单成功时,创建积分记录(冻结),确认收货解冻或者 n 天后解冻 | ||
| 815 | + * | ||
| 816 | + * @param userId 用户编号 | ||
| 817 | + * @param point 增加积分数量 | ||
| 818 | + * @param bizType 业务编号 | ||
| 819 | + * @param bizId 业务编号 | ||
| 820 | + */ | ||
| 769 | protected void addUserPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { | 821 | protected void addUserPoint(Long userId, Integer point, MemberPointBizTypeEnum bizType, Long bizId) { |
| 770 | if (point != null && point > 0) { | 822 | if (point != null && point > 0) { |
| 771 | memberPointApi.addPoint(userId, point, bizType.getType(), String.valueOf(bizId)); | 823 | memberPointApi.addPoint(userId, point, bizType.getType(), String.valueOf(bizId)); |
| @@ -778,15 +830,27 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | @@ -778,15 +830,27 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { | ||
| 778 | } | 830 | } |
| 779 | } | 831 | } |
| 780 | 832 | ||
| 833 | + /** | ||
| 834 | + * 创建分销记录 | ||
| 835 | + * | ||
| 836 | + * 目前是支付成功后,就会创建分销记录。 | ||
| 837 | + * | ||
| 838 | + * 业内还有两种做法,可以根据自己的业务调整: | ||
| 839 | + * 1. 确认收货后,才创建分销记录 | ||
| 840 | + * 2. 支付 or 下单成功时,创建分销记录(冻结),确认收货解冻或者 n 天后解冻 | ||
| 841 | + * | ||
| 842 | + * @param userId 用户编号 | ||
| 843 | + * @param orderId 订单编号 | ||
| 844 | + */ | ||
| 781 | @Async | 845 | @Async |
| 782 | protected void addBrokerageAsync(Long userId, Long orderId) { | 846 | protected void addBrokerageAsync(Long userId, Long orderId) { |
| 783 | MemberUserRespDTO user = memberUserApi.getUser(userId); | 847 | MemberUserRespDTO user = memberUserApi.getUser(userId); |
| 784 | Assert.notNull(user); | 848 | Assert.notNull(user); |
| 785 | - | 849 | + // 每一个订单项,都会去生成分销记录 |
| 786 | List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); | 850 | List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(orderId); |
| 787 | - List<BrokerageAddReqBO> list = convertList(orderItems, | 851 | + List<BrokerageAddReqBO> addList = convertList(orderItems, |
| 788 | item -> TradeOrderConvert.INSTANCE.convert(user, item, productSkuApi.getSku(item.getSkuId()))); | 852 | item -> TradeOrderConvert.INSTANCE.convert(user, item, productSkuApi.getSku(item.getSkuId()))); |
| 789 | - brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, list); | 853 | + brokerageRecordService.addBrokerage(userId, BrokerageRecordBizTypeEnum.ORDER, addList); |
| 790 | } | 854 | } |
| 791 | 855 | ||
| 792 | @Async | 856 | @Async |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/bo/TradeBeforeOrderCreateReqBO.java
| 1 | package cn.iocoder.yudao.module.trade.service.order.bo; | 1 | package cn.iocoder.yudao.module.trade.service.order.bo; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 5 | import lombok.Data; |
| 5 | 6 | ||
| @@ -14,36 +15,73 @@ import javax.validation.constraints.NotNull; | @@ -14,36 +15,73 @@ import javax.validation.constraints.NotNull; | ||
| 14 | @Data | 15 | @Data |
| 15 | public class TradeBeforeOrderCreateReqBO { | 16 | public class TradeBeforeOrderCreateReqBO { |
| 16 | 17 | ||
| 17 | - // TODO @puhui999:注释也写下哈;bo 还是写注释噢 | ||
| 18 | - | 18 | + /** |
| 19 | + * 订单类型 | ||
| 20 | + * | ||
| 21 | + * 枚举 {@link TradeOrderTypeEnum} | ||
| 22 | + */ | ||
| 19 | @NotNull(message = "订单类型不能为空") | 23 | @NotNull(message = "订单类型不能为空") |
| 20 | private Integer orderType; | 24 | private Integer orderType; |
| 21 | 25 | ||
| 26 | + /** | ||
| 27 | + * 用户编号 | ||
| 28 | + * | ||
| 29 | + * 关联 MemberUserDO 的 id 编号 | ||
| 30 | + */ | ||
| 31 | + @NotNull(message = "用户编号不能为空") | ||
| 32 | + private Long userId; | ||
| 33 | + | ||
| 22 | // ========== 秒杀活动相关字段 ========== | 34 | // ========== 秒杀活动相关字段 ========== |
| 23 | 35 | ||
| 36 | + /** | ||
| 37 | + * | ||
| 38 | + */ | ||
| 24 | @Schema(description = "秒杀活动编号", example = "1024") | 39 | @Schema(description = "秒杀活动编号", example = "1024") |
| 25 | private Long seckillActivityId; | 40 | private Long seckillActivityId; |
| 26 | 41 | ||
| 27 | // ========== 拼团活动相关字段 ========== | 42 | // ========== 拼团活动相关字段 ========== |
| 28 | 43 | ||
| 44 | + /** | ||
| 45 | + * 拼团活动编号 | ||
| 46 | + */ | ||
| 29 | @Schema(description = "拼团活动编号", example = "1024") | 47 | @Schema(description = "拼团活动编号", example = "1024") |
| 30 | private Long combinationActivityId; | 48 | private Long combinationActivityId; |
| 31 | 49 | ||
| 50 | + /** | ||
| 51 | + * 拼团团长编号 | ||
| 52 | + */ | ||
| 32 | @Schema(description = "拼团团长编号", example = "2048") | 53 | @Schema(description = "拼团团长编号", example = "2048") |
| 33 | private Long combinationHeadId; | 54 | private Long combinationHeadId; |
| 34 | 55 | ||
| 56 | + // ========== 砍价活动相关字段 ========== | ||
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 砍价活动编号 | ||
| 60 | + */ | ||
| 35 | @Schema(description = "砍价活动编号", example = "123") | 61 | @Schema(description = "砍价活动编号", example = "123") |
| 36 | private Long bargainActivityId; | 62 | private Long bargainActivityId; |
| 37 | 63 | ||
| 64 | + // ========== 活动购买商品相关字段 ========== | ||
| 65 | + | ||
| 66 | + /** | ||
| 67 | + * 商品 SPU 编号 | ||
| 68 | + * | ||
| 69 | + * 关联 ProductSkuDO 的 spuId 编号 | ||
| 70 | + */ | ||
| 38 | @NotNull(message = "SPU 编号不能为空") | 71 | @NotNull(message = "SPU 编号不能为空") |
| 39 | private Long spuId; | 72 | private Long spuId; |
| 40 | 73 | ||
| 74 | + /** | ||
| 75 | + * 商品 SKU 编号 | ||
| 76 | + * | ||
| 77 | + * 关联 ProductSkuDO 的 id 编号 | ||
| 78 | + */ | ||
| 41 | @NotNull(message = "SKU 编号活动商品不能为空") | 79 | @NotNull(message = "SKU 编号活动商品不能为空") |
| 42 | private Long skuId; | 80 | private Long skuId; |
| 43 | 81 | ||
| 44 | - @NotNull(message = "用户编号不能为空") | ||
| 45 | - private Long userId; | ||
| 46 | - | 82 | + /** |
| 83 | + * 购买的商品数量 | ||
| 84 | + */ | ||
| 47 | @NotNull(message = "购买数量不能为空") | 85 | @NotNull(message = "购买数量不能为空") |
| 48 | private Integer count; | 86 | private Integer count; |
| 49 | 87 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBargainHandler.java
| @@ -20,14 +20,17 @@ public class TradeBargainHandler implements TradeOrderHandler { | @@ -20,14 +20,17 @@ public class TradeBargainHandler implements TradeOrderHandler { | ||
| 20 | @Resource | 20 | @Resource |
| 21 | private BargainActivityApi bargainActivityApi; | 21 | private BargainActivityApi bargainActivityApi; |
| 22 | 22 | ||
| 23 | + // TODO @puhui999:先临时写在这里;在价格计算时,如果是秒杀商品,需要校验如下条件: | ||
| 24 | + // 1. 商品存在、库存充足、单次限购; | ||
| 25 | + // 2. 活动进行中、时间段符合 | ||
| 26 | + | ||
| 23 | @Override | 27 | @Override |
| 24 | public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { | 28 | public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { |
| 25 | // 如果是砍价订单 | 29 | // 如果是砍价订单 |
| 26 | if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) { | 30 | if (ObjectUtil.notEqual(TradeOrderTypeEnum.BARGAIN.getType(), reqBO.getOrderType())) { |
| 27 | return; | 31 | return; |
| 28 | } | 32 | } |
| 29 | - | ||
| 30 | - // 额外扣减砍价的库存 | 33 | + // 扣减砍价活动的库存 |
| 31 | bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount()); | 34 | bargainActivityApi.updateBargainActivityStock(reqBO.getBargainActivityId(), reqBO.getCount()); |
| 32 | } | 35 | } |
| 33 | 36 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java
| @@ -24,9 +24,12 @@ public interface TradeOrderHandler { | @@ -24,9 +24,12 @@ public interface TradeOrderHandler { | ||
| 24 | */ | 24 | */ |
| 25 | void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO); | 25 | void afterOrderCreate(TradeAfterOrderCreateReqBO reqBO); |
| 26 | 26 | ||
| 27 | + // TODO @puhui999:这个搞成订单取消 | ||
| 27 | /** | 28 | /** |
| 28 | * 回滚 | 29 | * 回滚 |
| 29 | */ | 30 | */ |
| 30 | void rollback(); | 31 | void rollback(); |
| 31 | 32 | ||
| 33 | + // TODO @puhui999:再搞个订单项取消哈 | ||
| 34 | + | ||
| 32 | } | 35 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeSeckillHandler.java
| @@ -20,13 +20,17 @@ public class TradeSeckillHandler implements TradeOrderHandler { | @@ -20,13 +20,17 @@ public class TradeSeckillHandler implements TradeOrderHandler { | ||
| 20 | @Resource | 20 | @Resource |
| 21 | private SeckillActivityApi seckillActivityApi; | 21 | private SeckillActivityApi seckillActivityApi; |
| 22 | 22 | ||
| 23 | + // TODO @puhui999:先临时写在这里;在价格计算时,如果是秒杀商品,需要校验如下条件: | ||
| 24 | + // 1. 商品存在、库存充足、单次限购; | ||
| 25 | + // 2. 活动进行中、时间段符合 | ||
| 26 | + | ||
| 23 | @Override | 27 | @Override |
| 24 | public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { | 28 | public void beforeOrderCreate(TradeBeforeOrderCreateReqBO reqBO) { |
| 25 | // 如果是秒杀订单:额外扣减秒杀的库存; | 29 | // 如果是秒杀订单:额外扣减秒杀的库存; |
| 26 | if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) { | 30 | if (ObjectUtil.notEqual(TradeOrderTypeEnum.SECKILL.getType(), reqBO.getOrderType())) { |
| 27 | return; | 31 | return; |
| 28 | } | 32 | } |
| 29 | - | 33 | + // 扣减秒杀活动的库存 |
| 30 | seckillActivityApi.updateSeckillStock(reqBO.getSeckillActivityId(), reqBO.getSkuId(), reqBO.getCount()); | 34 | seckillActivityApi.updateSeckillStock(reqBO.getSeckillActivityId(), reqBO.getSkuId(), reqBO.getCount()); |
| 31 | } | 35 | } |
| 32 | 36 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
| @@ -95,6 +95,10 @@ public class TradePriceCalculateRespBO { | @@ -95,6 +95,10 @@ public class TradePriceCalculateRespBO { | ||
| 95 | */ | 95 | */ |
| 96 | private Integer pointPrice; | 96 | private Integer pointPrice; |
| 97 | /** | 97 | /** |
| 98 | + * VIP 减免金额,单位:分 | ||
| 99 | + */ | ||
| 100 | + private Integer vipPrice; | ||
| 101 | + /** | ||
| 98 | * 最终购买金额(总),单位:分 | 102 | * 最终购买金额(总),单位:分 |
| 99 | * | 103 | * |
| 100 | * = {@link #totalPrice} | 104 | * = {@link #totalPrice} |
| @@ -102,6 +106,7 @@ public class TradePriceCalculateRespBO { | @@ -102,6 +106,7 @@ public class TradePriceCalculateRespBO { | ||
| 102 | * - {@link #pointPrice} | 106 | * - {@link #pointPrice} |
| 103 | * - {@link #discountPrice} | 107 | * - {@link #discountPrice} |
| 104 | * + {@link #deliveryPrice} | 108 | * + {@link #deliveryPrice} |
| 109 | + * - {@link #vipPrice} | ||
| 105 | */ | 110 | */ |
| 106 | private Integer payPrice; | 111 | private Integer payPrice; |
| 107 | 112 | ||
| @@ -168,6 +173,10 @@ public class TradePriceCalculateRespBO { | @@ -168,6 +173,10 @@ public class TradePriceCalculateRespBO { | ||
| 168 | */ | 173 | */ |
| 169 | private Integer usePoint; | 174 | private Integer usePoint; |
| 170 | /** | 175 | /** |
| 176 | + * VIP 减免金额,单位:分 | ||
| 177 | + */ | ||
| 178 | + private Integer vipPrice; | ||
| 179 | + /** | ||
| 171 | * 应付金额(总),单位:分 | 180 | * 应付金额(总),单位:分 |
| 172 | * | 181 | * |
| 173 | * = {@link #price} * {@link #count} | 182 | * = {@link #price} * {@link #count} |
| @@ -175,6 +184,7 @@ public class TradePriceCalculateRespBO { | @@ -175,6 +184,7 @@ public class TradePriceCalculateRespBO { | ||
| 175 | * - {@link #pointPrice} | 184 | * - {@link #pointPrice} |
| 176 | * - {@link #discountPrice} | 185 | * - {@link #discountPrice} |
| 177 | * + {@link #deliveryPrice} | 186 | * + {@link #deliveryPrice} |
| 187 | + * - {@link #vipPrice} | ||
| 178 | */ | 188 | */ |
| 179 | private Integer payPrice; | 189 | private Integer payPrice; |
| 180 | 190 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculator.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.service.price.calculator; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.lang.Assert; | 4 | import cn.hutool.core.lang.Assert; |
| 5 | +import cn.hutool.core.util.ObjectUtil; | ||
| 5 | import cn.hutool.core.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| 6 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; | 7 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; |
| 7 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; | 8 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO; |
| @@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | @@ -9,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | ||
| 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | 10 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| 10 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | 11 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; |
| 11 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 12 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 13 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 14 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 13 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 15 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 14 | import org.springframework.core.annotation.Order; | 16 | import org.springframework.core.annotation.Order; |
| @@ -22,6 +24,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU | @@ -22,6 +24,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU | ||
| 22 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; | 24 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; |
| 23 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_MIN_PRICE; | 25 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_MIN_PRICE; |
| 24 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_SPU; | 26 | import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_NO_MATCH_SPU; |
| 27 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER; | ||
| 25 | 28 | ||
| 26 | /** | 29 | /** |
| 27 | * 优惠劵的 {@link TradePriceCalculator} 实现类 | 30 | * 优惠劵的 {@link TradePriceCalculator} 实现类 |
| @@ -44,6 +47,10 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { | @@ -44,6 +47,10 @@ public class TradeCouponPriceCalculator implements TradePriceCalculator { | ||
| 44 | CouponRespDTO coupon = couponApi.validateCoupon(new CouponValidReqDTO() | 47 | CouponRespDTO coupon = couponApi.validateCoupon(new CouponValidReqDTO() |
| 45 | .setId(param.getCouponId()).setUserId(param.getUserId())); | 48 | .setId(param.getCouponId()).setUserId(param.getUserId())); |
| 46 | Assert.notNull(coupon, "校验通过的优惠劵({}),不能为空", param.getCouponId()); | 49 | Assert.notNull(coupon, "校验通过的优惠劵({}),不能为空", param.getCouponId()); |
| 50 | + // 1.2 只有【普通】订单,才允许使用优惠劵 | ||
| 51 | + if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { | ||
| 52 | + throw exception(PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER); | ||
| 53 | + } | ||
| 47 | 54 | ||
| 48 | // 2.1 获得匹配的商品 SKU 数组 | 55 | // 2.1 获得匹配的商品 SKU 数组 |
| 49 | List<TradePriceCalculateRespBO.OrderItem> orderItems = filterMatchCouponOrderItems(result, coupon); | 56 | List<TradePriceCalculateRespBO.OrderItem> orderItems = filterMatchCouponOrderItems(result, coupon); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.java
| @@ -64,7 +64,8 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | @@ -64,7 +64,8 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | ||
| 64 | 64 | ||
| 65 | private void calculateByPickUp(TradePriceCalculateReqBO param) { | 65 | private void calculateByPickUp(TradePriceCalculateReqBO param) { |
| 66 | if (param.getPickUpStoreId() == null) { | 66 | if (param.getPickUpStoreId() == null) { |
| 67 | - throw exception(PRICE_CALCULATE_DELIVERY_PRICE_PICK_UP_STORE_IS_EMPTY); | 67 | + // 价格计算时,如果为空就不算~最终下单,会校验该字段不允许空 |
| 68 | + return; | ||
| 68 | } | 69 | } |
| 69 | DeliveryPickUpStoreDO pickUpStore = deliveryPickUpStoreService.getDeliveryPickUpStore(param.getPickUpStoreId()); | 70 | DeliveryPickUpStoreDO pickUpStore = deliveryPickUpStoreService.getDeliveryPickUpStore(param.getPickUpStoreId()); |
| 70 | if (pickUpStore == null || CommonStatusEnum.DISABLE.getStatus().equals(pickUpStore.getStatus())) { | 71 | if (pickUpStore == null || CommonStatusEnum.DISABLE.getStatus().equals(pickUpStore.getStatus())) { |
| @@ -77,7 +78,8 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | @@ -77,7 +78,8 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | ||
| 77 | private void calculateExpress(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | 78 | private void calculateExpress(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { |
| 78 | // 0. 得到收件地址区域 | 79 | // 0. 得到收件地址区域 |
| 79 | if (param.getAddressId() == null) { | 80 | if (param.getAddressId() == null) { |
| 80 | - throw exception(PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDRESS_IS_EMPTY); | 81 | + // 价格计算时,如果为空就不算~最终下单,会校验该字段不允许空 |
| 82 | + return; | ||
| 81 | } | 83 | } |
| 82 | AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId()); | 84 | AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId()); |
| 83 | Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId()); | 85 | Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId()); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
| 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; | 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.util.ObjectUtil; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; | 6 | import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; |
| 6 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; | 7 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; |
| 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 10 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 9 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 11 | import org.springframework.core.annotation.Order; | 13 | import org.springframework.core.annotation.Order; |
| @@ -33,6 +35,10 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato | @@ -33,6 +35,10 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato | ||
| 33 | 35 | ||
| 34 | @Override | 36 | @Override |
| 35 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | 37 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { |
| 38 | + // 0. 只有【普通】订单,才计算该优惠 | ||
| 39 | + if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { | ||
| 40 | + return; | ||
| 41 | + } | ||
| 36 | // 获得 SKU 对应的限时折扣活动 | 42 | // 获得 SKU 对应的限时折扣活动 |
| 37 | List<DiscountProductRespDTO> discountProducts = discountActivityApi.getMatchDiscountProductList( | 43 | List<DiscountProductRespDTO> discountProducts = discountActivityApi.getMatchDiscountProductList( |
| 38 | convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId)); | 44 | convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId)); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeMemberLevelPriceCalculator.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | ||
| 2 | + | ||
| 3 | +import cn.hutool.core.util.ObjectUtil; | ||
| 4 | +import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; | ||
| 5 | +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; | ||
| 6 | +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||
| 7 | +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | ||
| 8 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | ||
| 9 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 10 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | ||
| 11 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | ||
| 12 | +import org.springframework.core.annotation.Order; | ||
| 13 | +import org.springframework.stereotype.Component; | ||
| 14 | + | ||
| 15 | +import javax.annotation.Resource; | ||
| 16 | + | ||
| 17 | +import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 会员 VIP 折扣的 {@link TradePriceCalculator} 实现类 | ||
| 21 | + * | ||
| 22 | + * @author 芋道源码 | ||
| 23 | + */ | ||
| 24 | +@Component | ||
| 25 | +@Order(TradePriceCalculator.ORDER_MEMBER_LEVEL) | ||
| 26 | +public class TradeMemberLevelPriceCalculator implements TradePriceCalculator { | ||
| 27 | + | ||
| 28 | + @Resource | ||
| 29 | + private MemberLevelApi memberLevelApi; | ||
| 30 | + @Resource | ||
| 31 | + private MemberUserApi memberUserApi; | ||
| 32 | + | ||
| 33 | + @Override | ||
| 34 | + public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | ||
| 35 | + // 0. 只有【普通】订单,才计算该优惠 | ||
| 36 | + if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { | ||
| 37 | + return; | ||
| 38 | + } | ||
| 39 | + // 1. 获得用户的会员等级 | ||
| 40 | + MemberUserRespDTO user = memberUserApi.getUser(param.getUserId()); | ||
| 41 | + if (user.getLevelId() == null || user.getLevelId() <= 0) { | ||
| 42 | + return; | ||
| 43 | + } | ||
| 44 | + MemberLevelRespDTO level = memberLevelApi.getMemberLevel(user.getLevelId()); | ||
| 45 | + if (level == null || level.getDiscountPercent() == null) { | ||
| 46 | + return; | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + // 2. 计算每个 SKU 的优惠金额 | ||
| 50 | + result.getItems().forEach(orderItem -> { | ||
| 51 | + // 2.1 计算优惠金额 | ||
| 52 | + Integer vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent()); | ||
| 53 | + if (vipPrice <= 0) { | ||
| 54 | + return; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + // 2.2 记录优惠明细 | ||
| 58 | + if (orderItem.getSelected()) { | ||
| 59 | + // 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示 | ||
| 60 | + TradePriceCalculatorHelper.addPromotion(result, orderItem, | ||
| 61 | + level.getId(), level.getName(), PromotionTypeEnum.MEMBER_LEVEL.getType(), | ||
| 62 | + String.format("会员等级折扣:省 %s 元", formatPrice(vipPrice)), | ||
| 63 | + vipPrice); | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + // 2.3 更新 SKU 的优惠金额 | ||
| 67 | + orderItem.setVipPrice(vipPrice); | ||
| 68 | + TradePriceCalculatorHelper.recountPayPrice(orderItem); | ||
| 69 | + }); | ||
| 70 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + /** | ||
| 74 | + * 计算会员 VIP 优惠价格 | ||
| 75 | + * | ||
| 76 | + * @param price 原价 | ||
| 77 | + * @param discountPercent 折扣 | ||
| 78 | + * @return 优惠价格 | ||
| 79 | + */ | ||
| 80 | + public Integer calculateVipPrice(Integer price, Integer discountPercent) { | ||
| 81 | + if (discountPercent == null) { | ||
| 82 | + return 0; | ||
| 83 | + } | ||
| 84 | + Integer newPrice = price * discountPercent / 100; | ||
| 85 | + return price - newPrice; | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculator.java
| @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | ||
| 13 | */ | 13 | */ |
| 14 | public interface TradePriceCalculator { | 14 | public interface TradePriceCalculator { |
| 15 | 15 | ||
| 16 | + int ORDER_MEMBER_LEVEL = 5; | ||
| 16 | int ORDER_DISCOUNT_ACTIVITY = 10; | 17 | int ORDER_DISCOUNT_ACTIVITY = 10; |
| 17 | int ORDER_REWARD_ACTIVITY = 20; | 18 | int ORDER_REWARD_ACTIVITY = 20; |
| 18 | int ORDER_COUPON = 30; | 19 | int ORDER_COUPON = 30; |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradePriceCalculatorHelper.java
| @@ -52,7 +52,7 @@ public class TradePriceCalculatorHelper { | @@ -52,7 +52,7 @@ public class TradePriceCalculatorHelper { | ||
| 52 | .setCount(item.getCount()).setCartId(item.getCartId()).setSelected(item.getSelected()); | 52 | .setCount(item.getCount()).setCartId(item.getCartId()).setSelected(item.getSelected()); |
| 53 | // sku 价格 | 53 | // sku 价格 |
| 54 | orderItem.setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * item.getCount()) | 54 | orderItem.setPrice(sku.getPrice()).setPayPrice(sku.getPrice() * item.getCount()) |
| 55 | - .setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0); | 55 | + .setDiscountPrice(0).setDeliveryPrice(0).setCouponPrice(0).setPointPrice(0).setVipPrice(0); |
| 56 | // sku 信息 | 56 | // sku 信息 |
| 57 | orderItem.setPicUrl(sku.getPicUrl()).setProperties(sku.getProperties()) | 57 | orderItem.setPicUrl(sku.getPicUrl()).setProperties(sku.getProperties()) |
| 58 | .setWeight(sku.getWeight()).setVolume(sku.getVolume()); | 58 | .setWeight(sku.getWeight()).setVolume(sku.getVolume()); |
| @@ -98,7 +98,7 @@ public class TradePriceCalculatorHelper { | @@ -98,7 +98,7 @@ public class TradePriceCalculatorHelper { | ||
| 98 | // 先重置 | 98 | // 先重置 |
| 99 | TradePriceCalculateRespBO.Price price = result.getPrice(); | 99 | TradePriceCalculateRespBO.Price price = result.getPrice(); |
| 100 | price.setTotalPrice(0).setDiscountPrice(0).setDeliveryPrice(0) | 100 | price.setTotalPrice(0).setDiscountPrice(0).setDeliveryPrice(0) |
| 101 | - .setCouponPrice(0).setPointPrice(0).setPayPrice(0); | 101 | + .setCouponPrice(0).setPointPrice(0).setVipPrice(0).setPayPrice(0); |
| 102 | // 再合计 item | 102 | // 再合计 item |
| 103 | result.getItems().forEach(item -> { | 103 | result.getItems().forEach(item -> { |
| 104 | if (!item.getSelected()) { | 104 | if (!item.getSelected()) { |
| @@ -109,6 +109,7 @@ public class TradePriceCalculatorHelper { | @@ -109,6 +109,7 @@ public class TradePriceCalculatorHelper { | ||
| 109 | price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice()); | 109 | price.setDeliveryPrice(price.getDeliveryPrice() + item.getDeliveryPrice()); |
| 110 | price.setCouponPrice(price.getCouponPrice() + item.getCouponPrice()); | 110 | price.setCouponPrice(price.getCouponPrice() + item.getCouponPrice()); |
| 111 | price.setPointPrice(price.getPointPrice() + item.getPointPrice()); | 111 | price.setPointPrice(price.getPointPrice() + item.getPointPrice()); |
| 112 | + price.setVipPrice(price.getVipPrice() + item.getVipPrice()); | ||
| 112 | price.setPayPrice(price.getPayPrice() + item.getPayPrice()); | 113 | price.setPayPrice(price.getPayPrice() + item.getPayPrice()); |
| 113 | }); | 114 | }); |
| 114 | } | 115 | } |
| @@ -132,7 +133,9 @@ public class TradePriceCalculatorHelper { | @@ -132,7 +133,9 @@ public class TradePriceCalculatorHelper { | ||
| 132 | - orderItem.getDiscountPrice() | 133 | - orderItem.getDiscountPrice() |
| 133 | + orderItem.getDeliveryPrice() | 134 | + orderItem.getDeliveryPrice() |
| 134 | - orderItem.getCouponPrice() | 135 | - orderItem.getCouponPrice() |
| 135 | - - orderItem.getPointPrice()); | 136 | + - orderItem.getPointPrice() |
| 137 | + - orderItem.getVipPrice() | ||
| 138 | + ); | ||
| 136 | } | 139 | } |
| 137 | 140 | ||
| 138 | /** | 141 | /** |
| @@ -162,6 +165,9 @@ public class TradePriceCalculatorHelper { | @@ -162,6 +165,9 @@ public class TradePriceCalculatorHelper { | ||
| 162 | if (orderItem.getGivePoint() == null) { | 165 | if (orderItem.getGivePoint() == null) { |
| 163 | orderItem.setGivePoint(0); | 166 | orderItem.setGivePoint(0); |
| 164 | } | 167 | } |
| 168 | + if (orderItem.getVipPrice() == null) { | ||
| 169 | + orderItem.setVipPrice(0); | ||
| 170 | + } | ||
| 165 | recountPayPrice(orderItem); | 171 | recountPayPrice(orderItem); |
| 166 | }); | 172 | }); |
| 167 | } | 173 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
| 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; | 1 | package cn.iocoder.yudao.module.trade.service.price.calculator; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | +import cn.hutool.core.util.ObjectUtil; | ||
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; | 6 | import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; |
| 6 | import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; | 7 | import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; |
| 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; | 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; |
| 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 10 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 9 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 11 | import org.springframework.core.annotation.Order; | 13 | import org.springframework.core.annotation.Order; |
| @@ -32,6 +34,10 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator | @@ -32,6 +34,10 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator | ||
| 32 | 34 | ||
| 33 | @Override | 35 | @Override |
| 34 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | 36 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { |
| 37 | + // 0. 只有【普通】订单,才计算该优惠 | ||
| 38 | + if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) { | ||
| 39 | + return; | ||
| 40 | + } | ||
| 35 | // 获得 SKU 对应的满减送活动 | 41 | // 获得 SKU 对应的满减送活动 |
| 36 | List<RewardActivityMatchRespDTO> rewardActivities = rewardActivityApi.getMatchRewardActivityList( | 42 | List<RewardActivityMatchRespDTO> rewardActivities = rewardActivityApi.getMatchRewardActivityList( |
| 37 | convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId)); | 43 | convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId)); |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeCouponPriceCalculatorTest.java
| @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO; | ||
| 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; | 8 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum; |
| 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 9 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 10 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 11 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 12 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 12 | import org.junit.jupiter.api.Test; | 13 | import org.junit.jupiter.api.Test; |
| @@ -47,6 +48,7 @@ public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { | @@ -47,6 +48,7 @@ public class TradeCouponPriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 47 | new TradePriceCalculateReqBO.Item().setSkuId(40L).setCount(5).setSelected(false) // 匹配优惠劵,但是未选中 | 48 | new TradePriceCalculateReqBO.Item().setSkuId(40L).setCount(5).setSelected(false) // 匹配优惠劵,但是未选中 |
| 48 | )); | 49 | )); |
| 49 | TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | 50 | TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() |
| 51 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 50 | .setPrice(new TradePriceCalculateRespBO.Price()) | 52 | .setPrice(new TradePriceCalculateRespBO.Price()) |
| 51 | .setPromotions(new ArrayList<>()) | 53 | .setPromotions(new ArrayList<>()) |
| 52 | .setItems(asList( | 54 | .setItems(asList( |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculatorTest.java
| @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi; | ||
| 5 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; | 5 | import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO; |
| 6 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; | 6 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum; |
| 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 8 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 8 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 9 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 9 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 10 | import org.junit.jupiter.api.Test; | 11 | import org.junit.jupiter.api.Test; |
| @@ -42,6 +43,7 @@ public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTes | @@ -42,6 +43,7 @@ public class TradeDiscountActivityPriceCalculatorTest extends BaseMockitoUnitTes | ||
| 42 | new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(false) // 匹配活动,但未选中 | 43 | new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(false) // 匹配活动,但未选中 |
| 43 | )); | 44 | )); |
| 44 | TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | 45 | TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() |
| 46 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 45 | .setPrice(new TradePriceCalculateRespBO.Price()) | 47 | .setPrice(new TradePriceCalculateRespBO.Price()) |
| 46 | .setPromotions(new ArrayList<>()) | 48 | .setPromotions(new ArrayList<>()) |
| 47 | .setItems(asList( | 49 | .setItems(asList( |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeMemberLevelPriceCalculatorTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.price.calculator; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; | ||
| 4 | +import cn.iocoder.yudao.module.member.api.level.MemberLevelApi; | ||
| 5 | +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; | ||
| 6 | +import cn.iocoder.yudao.module.member.api.user.MemberUserApi; | ||
| 7 | +import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | ||
| 8 | +import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | ||
| 9 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 10 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | ||
| 11 | +import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | ||
| 12 | +import org.junit.jupiter.api.Test; | ||
| 13 | +import org.mockito.InjectMocks; | ||
| 14 | +import org.mockito.Mock; | ||
| 15 | + | ||
| 16 | +import java.util.ArrayList; | ||
| 17 | + | ||
| 18 | +import static java.util.Arrays.asList; | ||
| 19 | +import static org.junit.jupiter.api.Assertions.*; | ||
| 20 | +import static org.mockito.ArgumentMatchers.eq; | ||
| 21 | +import static org.mockito.Mockito.when; | ||
| 22 | + | ||
| 23 | +/** | ||
| 24 | + * {@link TradeMemberLevelPriceCalculator} 的单元测试类 | ||
| 25 | + * | ||
| 26 | + * @author 芋道源码 | ||
| 27 | + */ | ||
| 28 | +public class TradeMemberLevelPriceCalculatorTest extends BaseMockitoUnitTest { | ||
| 29 | + | ||
| 30 | + @InjectMocks | ||
| 31 | + private TradeMemberLevelPriceCalculator memberLevelPriceCalculator; | ||
| 32 | + | ||
| 33 | + @Mock | ||
| 34 | + private MemberLevelApi memberLevelApi; | ||
| 35 | + @Mock | ||
| 36 | + private MemberUserApi memberUserApi; | ||
| 37 | + | ||
| 38 | + @Test | ||
| 39 | + public void testCalculate() { | ||
| 40 | + // 准备参数 | ||
| 41 | + TradePriceCalculateReqBO param = new TradePriceCalculateReqBO() | ||
| 42 | + .setUserId(1024L) | ||
| 43 | + .setItems(asList( | ||
| 44 | + new TradePriceCalculateReqBO.Item().setSkuId(10L).setCount(2).setSelected(true), // 匹配活动,且已选中 | ||
| 45 | + new TradePriceCalculateReqBO.Item().setSkuId(20L).setCount(3).setSelected(false) // 匹配活动,但未选中 | ||
| 46 | + )); | ||
| 47 | + TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | ||
| 48 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 49 | + .setPrice(new TradePriceCalculateRespBO.Price()) | ||
| 50 | + .setPromotions(new ArrayList<>()) | ||
| 51 | + .setItems(asList( | ||
| 52 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(10L).setCount(2).setSelected(true) | ||
| 53 | + .setPrice(100), | ||
| 54 | + new TradePriceCalculateRespBO.OrderItem().setSkuId(20L).setCount(3).setSelected(false) | ||
| 55 | + .setPrice(50) | ||
| 56 | + )); | ||
| 57 | + // 保证价格被初始化上 | ||
| 58 | + TradePriceCalculatorHelper.recountPayPrice(result.getItems()); | ||
| 59 | + TradePriceCalculatorHelper.recountAllPrice(result); | ||
| 60 | + | ||
| 61 | + // mock 方法(会员等级) | ||
| 62 | + when(memberUserApi.getUser(eq(1024L))).thenReturn(new MemberUserRespDTO().setLevelId(2048L)); | ||
| 63 | + when(memberLevelApi.getMemberLevel(eq(2048L))).thenReturn( | ||
| 64 | + new MemberLevelRespDTO().setId(2048L).setName("VIP 会员").setDiscountPercent(60)); | ||
| 65 | + | ||
| 66 | + // 调用 | ||
| 67 | + memberLevelPriceCalculator.calculate(param, result); | ||
| 68 | + // 断言:Price 部分 | ||
| 69 | + TradePriceCalculateRespBO.Price price = result.getPrice(); | ||
| 70 | + assertEquals(price.getTotalPrice(), 200); | ||
| 71 | + assertEquals(price.getDiscountPrice(), 0); | ||
| 72 | + assertEquals(price.getPointPrice(), 0); | ||
| 73 | + assertEquals(price.getDeliveryPrice(), 0); | ||
| 74 | + assertEquals(price.getCouponPrice(), 0); | ||
| 75 | + assertEquals(price.getVipPrice(), 80); | ||
| 76 | + assertEquals(price.getPayPrice(), 120); | ||
| 77 | + assertNull(result.getCouponId()); | ||
| 78 | + // 断言:SKU 1 | ||
| 79 | + assertEquals(result.getItems().size(), 2); | ||
| 80 | + TradePriceCalculateRespBO.OrderItem orderItem01 = result.getItems().get(0); | ||
| 81 | + assertEquals(orderItem01.getSkuId(), 10L); | ||
| 82 | + assertEquals(orderItem01.getCount(), 2); | ||
| 83 | + assertEquals(orderItem01.getPrice(), 100); | ||
| 84 | + assertEquals(orderItem01.getDiscountPrice(), 0); | ||
| 85 | + assertEquals(orderItem01.getDeliveryPrice(), 0); | ||
| 86 | + assertEquals(orderItem01.getCouponPrice(), 0); | ||
| 87 | + assertEquals(orderItem01.getPointPrice(), 0); | ||
| 88 | + assertEquals(orderItem01.getVipPrice(), 80); | ||
| 89 | + assertEquals(orderItem01.getPayPrice(), 120); | ||
| 90 | + // 断言:SKU 2 | ||
| 91 | + TradePriceCalculateRespBO.OrderItem orderItem02 = result.getItems().get(1); | ||
| 92 | + assertEquals(orderItem02.getSkuId(), 20L); | ||
| 93 | + assertEquals(orderItem02.getCount(), 3); | ||
| 94 | + assertEquals(orderItem02.getPrice(), 50); | ||
| 95 | + assertEquals(orderItem02.getDiscountPrice(), 0); | ||
| 96 | + assertEquals(orderItem02.getDeliveryPrice(), 0); | ||
| 97 | + assertEquals(orderItem02.getCouponPrice(), 0); | ||
| 98 | + assertEquals(orderItem02.getPointPrice(), 0); | ||
| 99 | + assertEquals(orderItem02.getVipPrice(), 60); | ||
| 100 | + assertEquals(orderItem02.getPayPrice(), 90); | ||
| 101 | + // 断言:Promotion 部分 | ||
| 102 | + assertEquals(result.getPromotions().size(), 1); | ||
| 103 | + TradePriceCalculateRespBO.Promotion promotion01 = result.getPromotions().get(0); | ||
| 104 | + assertEquals(promotion01.getId(), 2048L); | ||
| 105 | + assertEquals(promotion01.getName(), "VIP 会员"); | ||
| 106 | + assertEquals(promotion01.getType(), PromotionTypeEnum.MEMBER_LEVEL.getType()); | ||
| 107 | + assertEquals(promotion01.getTotalPrice(), 200); | ||
| 108 | + assertEquals(promotion01.getDiscountPrice(), 80); | ||
| 109 | + assertTrue(promotion01.getMatch()); | ||
| 110 | + assertEquals(promotion01.getDescription(), "会员等级折扣:省 0.80 元"); | ||
| 111 | + TradePriceCalculateRespBO.PromotionItem promotionItem01 = promotion01.getItems().get(0); | ||
| 112 | + assertEquals(promotion01.getItems().size(), 1); | ||
| 113 | + assertEquals(promotionItem01.getSkuId(), 10L); | ||
| 114 | + assertEquals(promotionItem01.getTotalPrice(), 200); | ||
| 115 | + assertEquals(promotionItem01.getDiscountPrice(), 80); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | +} |
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculatorTest.java
| @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; | @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi; | ||
| 5 | import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; | 5 | import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO; |
| 6 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; | 6 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum; |
| 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; | 7 | import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum; |
| 8 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 8 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 9 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 9 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 10 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 10 | import org.junit.jupiter.api.Test; | 11 | import org.junit.jupiter.api.Test; |
| @@ -44,6 +45,7 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest | @@ -44,6 +45,7 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest | ||
| 44 | new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true) // 匹配活动 2 | 45 | new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true) // 匹配活动 2 |
| 45 | )); | 46 | )); |
| 46 | TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | 47 | TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() |
| 48 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 47 | .setPrice(new TradePriceCalculateRespBO.Price()) | 49 | .setPrice(new TradePriceCalculateRespBO.Price()) |
| 48 | .setPromotions(new ArrayList<>()) | 50 | .setPromotions(new ArrayList<>()) |
| 49 | .setItems(asList( | 51 | .setItems(asList( |
| @@ -157,6 +159,7 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest | @@ -157,6 +159,7 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest | ||
| 157 | new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true) | 159 | new TradePriceCalculateReqBO.Item().setSkuId(30L).setCount(4).setSelected(true) |
| 158 | )); | 160 | )); |
| 159 | TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() | 161 | TradePriceCalculateRespBO result = new TradePriceCalculateRespBO() |
| 162 | + .setType(TradeOrderTypeEnum.NORMAL.getType()) | ||
| 160 | .setPrice(new TradePriceCalculateRespBO.Price()) | 163 | .setPrice(new TradePriceCalculateRespBO.Price()) |
| 161 | .setPromotions(new ArrayList<>()) | 164 | .setPromotions(new ArrayList<>()) |
| 162 | .setItems(asList( | 165 | .setItems(asList( |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApi.java
| 1 | package cn.iocoder.yudao.module.member.api.level; | 1 | package cn.iocoder.yudao.module.member.api.level; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; | ||
| 3 | import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; | 4 | import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; |
| 4 | 5 | ||
| 5 | /** | 6 | /** |
| @@ -10,6 +11,14 @@ import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; | @@ -10,6 +11,14 @@ import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; | ||
| 10 | public interface MemberLevelApi { | 11 | public interface MemberLevelApi { |
| 11 | 12 | ||
| 12 | /** | 13 | /** |
| 14 | + * 获得会员等级 | ||
| 15 | + * | ||
| 16 | + * @param id 会员等级编号 | ||
| 17 | + * @return 会员等级 | ||
| 18 | + */ | ||
| 19 | + MemberLevelRespDTO getMemberLevel(Long id); | ||
| 20 | + | ||
| 21 | + /** | ||
| 13 | * 增加会员经验 | 22 | * 增加会员经验 |
| 14 | * | 23 | * |
| 15 | * @param userId 会员ID | 24 | * @param userId 会员ID |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/level/dto/MemberLevelRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.member.api.level.dto; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 会员等级 Resp DTO | ||
| 8 | + * | ||
| 9 | + * @author 芋道源码 | ||
| 10 | + */ | ||
| 11 | +@Data | ||
| 12 | +public class MemberLevelRespDTO { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 编号 | ||
| 16 | + */ | ||
| 17 | + private Long id; | ||
| 18 | + /** | ||
| 19 | + * 等级名称 | ||
| 20 | + */ | ||
| 21 | + private String name; | ||
| 22 | + /** | ||
| 23 | + * 等级 | ||
| 24 | + */ | ||
| 25 | + private Integer level; | ||
| 26 | + /** | ||
| 27 | + * 升级经验 | ||
| 28 | + */ | ||
| 29 | + private Integer experience; | ||
| 30 | + /** | ||
| 31 | + * 享受折扣 | ||
| 32 | + */ | ||
| 33 | + private Integer discountPercent; | ||
| 34 | + /** | ||
| 35 | + * 状态 | ||
| 36 | + * | ||
| 37 | + * 枚举 {@link CommonStatusEnum} | ||
| 38 | + */ | ||
| 39 | + private Integer status; | ||
| 40 | + | ||
| 41 | +} |
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/MemberUserRespDTO.java
| @@ -33,6 +33,14 @@ public class MemberUserRespDTO { | @@ -33,6 +33,14 @@ public class MemberUserRespDTO { | ||
| 33 | * 手机 | 33 | * 手机 |
| 34 | */ | 34 | */ |
| 35 | private String mobile; | 35 | private String mobile; |
| 36 | + | ||
| 37 | + // ========== 其它信息 ========== | ||
| 38 | + | ||
| 39 | + /** | ||
| 40 | + * 会员级别编号 | ||
| 41 | + */ | ||
| 42 | + private Long levelId; | ||
| 43 | + | ||
| 36 | /** | 44 | /** |
| 37 | * 积分 | 45 | * 积分 |
| 38 | */ | 46 | */ |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/api/level/MemberLevelApiImpl.java
| 1 | package cn.iocoder.yudao.module.member.api.level; | 1 | package cn.iocoder.yudao.module.member.api.level; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; | ||
| 4 | +import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert; | ||
| 3 | import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; | 5 | import cn.iocoder.yudao.module.member.enums.MemberExperienceBizTypeEnum; |
| 4 | import cn.iocoder.yudao.module.member.service.level.MemberLevelService; | 6 | import cn.iocoder.yudao.module.member.service.level.MemberLevelService; |
| 5 | import org.springframework.stereotype.Service; | 7 | import org.springframework.stereotype.Service; |
| @@ -23,6 +25,11 @@ public class MemberLevelApiImpl implements MemberLevelApi { | @@ -23,6 +25,11 @@ public class MemberLevelApiImpl implements MemberLevelApi { | ||
| 23 | private MemberLevelService memberLevelService; | 25 | private MemberLevelService memberLevelService; |
| 24 | 26 | ||
| 25 | @Override | 27 | @Override |
| 28 | + public MemberLevelRespDTO getMemberLevel(Long id) { | ||
| 29 | + return MemberLevelConvert.INSTANCE.convert02(memberLevelService.getLevel(id)); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + @Override | ||
| 26 | public void addExperience(Long userId, Integer experience, Integer bizType, String bizId) { | 33 | public void addExperience(Long userId, Integer experience, Integer bizType, String bizId) { |
| 27 | MemberExperienceBizTypeEnum bizTypeEnum = MemberExperienceBizTypeEnum.getByType(bizType); | 34 | MemberExperienceBizTypeEnum bizTypeEnum = MemberExperienceBizTypeEnum.getByType(bizType); |
| 28 | if (bizTypeEnum == null) { | 35 | if (bizTypeEnum == null) { |
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/convert/level/MemberLevelConvert.java
| 1 | package cn.iocoder.yudao.module.member.convert.level; | 1 | package cn.iocoder.yudao.module.member.convert.level; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO; | ||
| 3 | import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO; | 4 | import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelCreateReqVO; |
| 4 | import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelRespVO; | 5 | import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelRespVO; |
| 5 | import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelSimpleRespVO; | 6 | import cn.iocoder.yudao.module.member.controller.admin.level.vo.level.MemberLevelSimpleRespVO; |
| @@ -33,4 +34,6 @@ public interface MemberLevelConvert { | @@ -33,4 +34,6 @@ public interface MemberLevelConvert { | ||
| 33 | 34 | ||
| 34 | List<AppMemberLevelRespVO> convertList02(List<MemberLevelDO> list); | 35 | List<AppMemberLevelRespVO> convertList02(List<MemberLevelDO> list); |
| 35 | 36 | ||
| 37 | + MemberLevelRespDTO convert02(MemberLevelDO bean); | ||
| 38 | + | ||
| 36 | } | 39 | } |