Commit 4126e37d910e2cbd80f7f5a5571cc97ef8aef0f2
Merge remote-tracking branch 'origin/feature/mall_product' into feature/mall_product
# Conflicts: # yudao-module-mall/yudao-module-product-biz/pom.xml # yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
Showing
40 changed files
with
861 additions
and
289 deletions
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/ProductSpuRespDTO.java
| @@ -103,6 +103,15 @@ public class ProductSpuRespDTO { | @@ -103,6 +103,15 @@ public class ProductSpuRespDTO { | ||
| 103 | */ | 103 | */ |
| 104 | private Integer stock; | 104 | private Integer stock; |
| 105 | 105 | ||
| 106 | + // ========== 物流相关字段 ========= | ||
| 107 | + | ||
| 108 | + /** | ||
| 109 | + * 物流配置模板编号 | ||
| 110 | + * | ||
| 111 | + * 对应 TradeDeliveryExpressTemplateDO 的 id 编号 | ||
| 112 | + */ | ||
| 113 | + private Long deliveryTemplateId; | ||
| 114 | + | ||
| 106 | // ========== 统计相关字段 ========= | 115 | // ========== 统计相关字段 ========= |
| 107 | 116 | ||
| 108 | /** | 117 | /** |
yudao-module-mall/yudao-module-product-biz/pom.xml
| @@ -23,7 +23,12 @@ | @@ -23,7 +23,12 @@ | ||
| 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 | - | 26 | + <!-- TODO 芋艿:看看~~~ --> |
| 27 | + <dependency> | ||
| 28 | + <groupId>cn.iocoder.boot</groupId> | ||
| 29 | + <artifactId>yudao-module-trade-api</artifactId> | ||
| 30 | + <version>${revision}</version> | ||
| 31 | + </dependency> | ||
| 27 | <dependency> | 32 | <dependency> |
| 28 | <groupId>cn.iocoder.boot</groupId> | 33 | <groupId>cn.iocoder.boot</groupId> |
| 29 | <artifactId>yudao-module-member-api</artifactId> | 34 | <artifactId>yudao-module-member-api</artifactId> |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.java
| @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentCreat | @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentCreat | ||
| 9 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; | 9 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; |
| 10 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO; | 10 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO; |
| 11 | import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; | 11 | import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; |
| 12 | -import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; | ||
| 13 | import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; | 12 | import cn.iocoder.yudao.module.product.service.comment.ProductCommentService; |
| 14 | import io.swagger.v3.oas.annotations.Operation; | 13 | import io.swagger.v3.oas.annotations.Operation; |
| 15 | import io.swagger.v3.oas.annotations.tags.Tag; | 14 | import io.swagger.v3.oas.annotations.tags.Tag; |
| @@ -18,6 +17,7 @@ import org.springframework.web.bind.annotation.*; | @@ -18,6 +17,7 @@ import org.springframework.web.bind.annotation.*; | ||
| 18 | 17 | ||
| 19 | import javax.annotation.Resource; | 18 | import javax.annotation.Resource; |
| 20 | import javax.validation.Valid; | 19 | import javax.validation.Valid; |
| 20 | +import java.util.Map; | ||
| 21 | 21 | ||
| 22 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 22 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 23 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | 23 | import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; |
| @@ -37,8 +37,13 @@ public class AppCommentController { | @@ -37,8 +37,13 @@ public class AppCommentController { | ||
| 37 | @GetMapping("/page") | 37 | @GetMapping("/page") |
| 38 | @Operation(summary = "获得商品评价分页") | 38 | @Operation(summary = "获得商品评价分页") |
| 39 | public CommonResult<PageResult<AppCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) { | 39 | public CommonResult<PageResult<AppCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) { |
| 40 | - PageResult<ProductCommentDO> pageResult = productCommentService.getCommentPage(pageVO, Boolean.TRUE); | ||
| 41 | - return success(ProductCommentConvert.INSTANCE.convertPage02(pageResult)); | 40 | + return success(productCommentService.getCommentPage(pageVO, Boolean.TRUE)); |
| 41 | + } | ||
| 42 | + | ||
| 43 | + @GetMapping("/get-count") | ||
| 44 | + @Operation(summary = "获得商品评价分页 tab count") | ||
| 45 | + public CommonResult<Map<String, Long>> getCommentPage(@Valid Long spuId) { | ||
| 46 | + return success(productCommentService.getCommentPageTabsCount(spuId, Boolean.TRUE)); | ||
| 42 | } | 47 | } |
| 43 | 48 | ||
| 44 | @PostMapping(value = "/create") | 49 | @PostMapping(value = "/create") |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentPageReqVO.java
| @@ -14,8 +14,57 @@ import javax.validation.constraints.NotNull; | @@ -14,8 +14,57 @@ import javax.validation.constraints.NotNull; | ||
| 14 | @ToString(callSuper = true) | 14 | @ToString(callSuper = true) |
| 15 | public class AppCommentPageReqVO extends PageParam { | 15 | public class AppCommentPageReqVO extends PageParam { |
| 16 | 16 | ||
| 17 | + /** | ||
| 18 | + * 所有 | ||
| 19 | + */ | ||
| 20 | + public static final Integer ALL = 0; | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 所有数量 key | ||
| 24 | + */ | ||
| 25 | + public static final String ALL_COUNT = "allCount"; | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 好评 | ||
| 29 | + */ | ||
| 30 | + public static final Integer FAVOURABLE_COMMENT = 1; | ||
| 31 | + | ||
| 32 | + /** | ||
| 33 | + * 好评数量 key | ||
| 34 | + */ | ||
| 35 | + public static final String FAVOURABLE_COMMENT_COUNT = "favourableCommentCount"; | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 中评 | ||
| 39 | + */ | ||
| 40 | + public static final Integer MEDIOCRE_COMMENT = 2; | ||
| 41 | + | ||
| 42 | + /** | ||
| 43 | + * 中评数量 key | ||
| 44 | + */ | ||
| 45 | + public static final String MEDIOCRE_COMMENT_COUNT = "mediocreCommentCount"; | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * 差评 | ||
| 49 | + */ | ||
| 50 | + public static final Integer NEGATIVE_COMMENT = 3; | ||
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * 差评数量 key | ||
| 54 | + */ | ||
| 55 | + public static final String NEGATIVE_COMMENT_COUNT = "negativeCommentCount"; | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * 默认匿名昵称 | ||
| 59 | + */ | ||
| 60 | + public static final String ANONYMOUS_NICKNAME = "匿名用户"; | ||
| 61 | + | ||
| 17 | @Schema(description = "商品SPU编号", example = "29502") | 62 | @Schema(description = "商品SPU编号", example = "29502") |
| 18 | @NotNull(message = "商品SPU编号不能为空") | 63 | @NotNull(message = "商品SPU编号不能为空") |
| 19 | private Long spuId; | 64 | private Long spuId; |
| 20 | 65 | ||
| 66 | + @Schema(description = "app 评论页 tab 类型 (0 全部、1 好评、2 中评、3 差评)", example = "0") | ||
| 67 | + @NotNull(message = "商品SPU编号不能为空") | ||
| 68 | + private Integer type; | ||
| 69 | + | ||
| 21 | } | 70 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppCommentRespVO.java
| @@ -5,7 +5,6 @@ import lombok.Data; | @@ -5,7 +5,6 @@ import lombok.Data; | ||
| 5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
| 6 | import lombok.ToString; | 6 | import lombok.ToString; |
| 7 | 7 | ||
| 8 | -import javax.validation.constraints.NotNull; | ||
| 9 | import java.time.LocalDateTime; | 8 | import java.time.LocalDateTime; |
| 10 | import java.util.List; | 9 | import java.util.List; |
| 11 | 10 | ||
| @@ -27,7 +26,7 @@ public class AppCommentRespVO extends AppCommentBaseVO { | @@ -27,7 +26,7 @@ public class AppCommentRespVO extends AppCommentBaseVO { | ||
| 27 | @Schema(description = "订单项编号", required = true, example = "24965") | 26 | @Schema(description = "订单项编号", required = true, example = "24965") |
| 28 | private Long id; | 27 | private Long id; |
| 29 | 28 | ||
| 30 | - @Schema(description = "是否匿名:[0:不匿名 1:匿名]", required = true) | 29 | + @Schema(description = "是否匿名", required = true) |
| 31 | private Boolean anonymous; | 30 | private Boolean anonymous; |
| 32 | 31 | ||
| 33 | @Schema(description = "交易订单编号", required = true, example = "24428") | 32 | @Schema(description = "交易订单编号", required = true, example = "24428") |
| @@ -36,7 +35,7 @@ public class AppCommentRespVO extends AppCommentBaseVO { | @@ -36,7 +35,7 @@ public class AppCommentRespVO extends AppCommentBaseVO { | ||
| 36 | @Schema(description = "交易订单项编号", required = true, example = "8233") | 35 | @Schema(description = "交易订单项编号", required = true, example = "8233") |
| 37 | private Long orderItemId; | 36 | private Long orderItemId; |
| 38 | 37 | ||
| 39 | - @Schema(description = "商家是否回复:[1:回复 0:未回复]", required = true) | 38 | + @Schema(description = "商家是否回复", required = true) |
| 40 | private Boolean replied; | 39 | private Boolean replied; |
| 41 | 40 | ||
| 42 | @Schema(description = "回复管理员编号", example = "22212") | 41 | @Schema(description = "回复管理员编号", example = "22212") |
| @@ -60,4 +59,6 @@ public class AppCommentRespVO extends AppCommentBaseVO { | @@ -60,4 +59,6 @@ public class AppCommentRespVO extends AppCommentBaseVO { | ||
| 60 | @Schema(description = "创建时间", required = true) | 59 | @Schema(description = "创建时间", required = true) |
| 61 | private LocalDateTime createTime; | 60 | private LocalDateTime createTime; |
| 62 | 61 | ||
| 62 | + @Schema(description = "最终评分", required = true) | ||
| 63 | + private Integer finalScore; | ||
| 63 | } | 64 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
| @@ -6,11 +6,7 @@ import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetail | @@ -6,11 +6,7 @@ import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetail | ||
| 6 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO; | 6 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO; |
| 7 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; | 7 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; |
| 8 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | 8 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; |
| 9 | -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | ||
| 10 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | 9 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 11 | -import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | ||
| 12 | -import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; | ||
| 13 | -import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; | ||
| 14 | import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | 10 | import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; |
| 15 | import io.swagger.v3.oas.annotations.Operation; | 11 | import io.swagger.v3.oas.annotations.Operation; |
| 16 | import io.swagger.v3.oas.annotations.Parameter; | 12 | import io.swagger.v3.oas.annotations.Parameter; |
| @@ -23,12 +19,8 @@ import org.springframework.web.bind.annotation.RestController; | @@ -23,12 +19,8 @@ import org.springframework.web.bind.annotation.RestController; | ||
| 23 | 19 | ||
| 24 | import javax.annotation.Resource; | 20 | import javax.annotation.Resource; |
| 25 | import javax.validation.Valid; | 21 | import javax.validation.Valid; |
| 26 | -import java.util.List; | ||
| 27 | 22 | ||
| 28 | -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||
| 29 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | 23 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 30 | -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; | ||
| 32 | 24 | ||
| 33 | @Tag(name = "用户 APP - 商品 SPU") | 25 | @Tag(name = "用户 APP - 商品 SPU") |
| 34 | @RestController | 26 | @RestController |
| @@ -38,10 +30,6 @@ public class AppProductSpuController { | @@ -38,10 +30,6 @@ public class AppProductSpuController { | ||
| 38 | 30 | ||
| 39 | @Resource | 31 | @Resource |
| 40 | private ProductSpuService productSpuService; | 32 | private ProductSpuService productSpuService; |
| 41 | - @Resource | ||
| 42 | - private ProductSkuService productSkuService; | ||
| 43 | - @Resource | ||
| 44 | - private ProductPropertyValueService productPropertyValueService; | ||
| 45 | 33 | ||
| 46 | @GetMapping("/page") | 34 | @GetMapping("/page") |
| 47 | @Operation(summary = "获得商品 SPU 分页") | 35 | @Operation(summary = "获得商品 SPU 分页") |
| @@ -50,23 +38,12 @@ public class AppProductSpuController { | @@ -50,23 +38,12 @@ public class AppProductSpuController { | ||
| 50 | return success(ProductSpuConvert.INSTANCE.convertPageForGetSpuPage(pageResult)); | 38 | return success(ProductSpuConvert.INSTANCE.convertPageForGetSpuPage(pageResult)); |
| 51 | } | 39 | } |
| 52 | 40 | ||
| 41 | + // TODO 芋艿:等会看看 | ||
| 53 | @GetMapping("/get-detail") | 42 | @GetMapping("/get-detail") |
| 54 | @Operation(summary = "获得商品 SPU 明细") | 43 | @Operation(summary = "获得商品 SPU 明细") |
| 55 | @Parameter(name = "id", description = "编号", required = true) | 44 | @Parameter(name = "id", description = "编号", required = true) |
| 56 | public CommonResult<AppProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) { | 45 | public CommonResult<AppProductSpuDetailRespVO> getSpuDetail(@RequestParam("id") Long id) { |
| 57 | - // 获得商品 SPU | ||
| 58 | - ProductSpuDO spu = productSpuService.getSpu(id); | ||
| 59 | - if (spu == null) { | ||
| 60 | - throw exception(SPU_NOT_EXISTS); | ||
| 61 | - } | ||
| 62 | - if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { | ||
| 63 | - throw exception(SPU_NOT_ENABLE); | ||
| 64 | - } | ||
| 65 | - | ||
| 66 | - // 查询商品 SKU | ||
| 67 | - List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId()); | ||
| 68 | - // 拼接 | ||
| 69 | - return success(ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus)); | 46 | + return success(productSpuService.getAppProductSpuDetail(id)); |
| 70 | } | 47 | } |
| 71 | 48 | ||
| 72 | } | 49 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyDO.java
| @@ -22,6 +22,15 @@ import lombok.*; | @@ -22,6 +22,15 @@ import lombok.*; | ||
| 22 | public class ProductPropertyDO extends BaseDO { | 22 | public class ProductPropertyDO extends BaseDO { |
| 23 | 23 | ||
| 24 | /** | 24 | /** |
| 25 | + * 默认属性id | ||
| 26 | + */ | ||
| 27 | + public static final Long PROPERTY_ID = 0L; | ||
| 28 | + /** | ||
| 29 | + * 默认属性名字 | ||
| 30 | + */ | ||
| 31 | + public static final String PROPERTY_NAME = "默认"; | ||
| 32 | + | ||
| 33 | + /** | ||
| 25 | * 主键 | 34 | * 主键 |
| 26 | */ | 35 | */ |
| 27 | @TableId | 36 | @TableId |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/property/ProductPropertyValueDO.java
| @@ -23,6 +23,15 @@ import lombok.*; | @@ -23,6 +23,15 @@ import lombok.*; | ||
| 23 | public class ProductPropertyValueDO extends BaseDO { | 23 | public class ProductPropertyValueDO extends BaseDO { |
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| 26 | + * 默认属性值id | ||
| 27 | + */ | ||
| 28 | + public static final Long VALUE_ID = 0L; | ||
| 29 | + /** | ||
| 30 | + * 默认属性值名字 | ||
| 31 | + */ | ||
| 32 | + public static final String VALUE_NAME = "默认"; | ||
| 33 | + | ||
| 34 | + /** | ||
| 26 | * 主键 | 35 | * 主键 |
| 27 | */ | 36 | */ |
| 28 | @TableId | 37 | @TableId |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
| 1 | package cn.iocoder.yudao.module.product.dal.mysql.comment; | 1 | package cn.iocoder.yudao.module.product.dal.mysql.comment; |
| 2 | 2 | ||
| 3 | 3 | ||
| 4 | +import cn.hutool.core.util.ObjectUtil; | ||
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 6 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 7 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| @@ -34,11 +35,33 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> { | @@ -34,11 +35,33 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> { | ||
| 34 | .orderByDesc(ProductCommentDO::getId)); | 35 | .orderByDesc(ProductCommentDO::getId)); |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 38 | + static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) { | ||
| 39 | + // 构建好评查询语句 | ||
| 40 | + if (ObjectUtil.equal(type, AppCommentPageReqVO.FAVOURABLE_COMMENT)) { | ||
| 41 | + // 好评计算 (商品评分星级+服务评分星级) >= 8 | ||
| 42 | + queryWrapper.apply("(scores + benefit_scores) >= 8"); | ||
| 43 | + } | ||
| 44 | + // 构建中评查询语句 | ||
| 45 | + if (ObjectUtil.equal(type, AppCommentPageReqVO.MEDIOCRE_COMMENT)) { | ||
| 46 | + // 中评计算 (商品评分星级+服务评分星级) > 4 且 (商品评分星级+服务评分星级) < 8 | ||
| 47 | + queryWrapper.apply("(scores + benefit_scores) > 4 and (scores + benefit_scores) < 8"); | ||
| 48 | + } | ||
| 49 | + // 构建差评查询语句 | ||
| 50 | + if (ObjectUtil.equal(type, AppCommentPageReqVO.NEGATIVE_COMMENT)) { | ||
| 51 | + // 差评计算 (商品评分星级+服务评分星级) <= 4 | ||
| 52 | + queryWrapper.apply("(scores + benefit_scores) <= 4"); | ||
| 53 | + } | ||
| 54 | + } | ||
| 55 | + | ||
| 37 | default PageResult<ProductCommentDO> selectPage(AppCommentPageReqVO reqVO, Boolean visible) { | 56 | default PageResult<ProductCommentDO> selectPage(AppCommentPageReqVO reqVO, Boolean visible) { |
| 38 | - return selectPage(reqVO, new LambdaQueryWrapperX<ProductCommentDO>() | 57 | + LambdaQueryWrapperX<ProductCommentDO> queryWrapper = new LambdaQueryWrapperX<ProductCommentDO>() |
| 39 | .eqIfPresent(ProductCommentDO::getSpuId, reqVO.getSpuId()) | 58 | .eqIfPresent(ProductCommentDO::getSpuId, reqVO.getSpuId()) |
| 40 | - .eqIfPresent(ProductCommentDO::getVisible, visible) | ||
| 41 | - .orderByDesc(ProductCommentDO::getId)); | 59 | + .eqIfPresent(ProductCommentDO::getVisible, visible); |
| 60 | + // 构建评价查询语句 | ||
| 61 | + appendTabQuery(queryWrapper, reqVO.getType()); | ||
| 62 | + // 按评价时间排序最新的显示在前面 | ||
| 63 | + queryWrapper.orderByDesc(ProductCommentDO::getCreateTime); | ||
| 64 | + return selectPage(reqVO, queryWrapper); | ||
| 42 | } | 65 | } |
| 43 | 66 | ||
| 44 | default void updateCommentVisible(Long id, Boolean visible) { | 67 | default void updateCommentVisible(Long id, Boolean visible) { |
| @@ -74,4 +97,13 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> { | @@ -74,4 +97,13 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> { | ||
| 74 | update(null, lambdaUpdateWrapper); | 97 | update(null, lambdaUpdateWrapper); |
| 75 | } | 98 | } |
| 76 | 99 | ||
| 100 | + default Long selectTabCount(Long spuId, Boolean visible, Integer type) { | ||
| 101 | + LambdaQueryWrapperX<ProductCommentDO> queryWrapper = new LambdaQueryWrapperX<ProductCommentDO>() | ||
| 102 | + .eqIfPresent(ProductCommentDO::getSpuId, spuId) | ||
| 103 | + .eqIfPresent(ProductCommentDO::getVisible, visible); | ||
| 104 | + // 构建评价查询语句 | ||
| 105 | + appendTabQuery(queryWrapper, type); | ||
| 106 | + return selectCount(queryWrapper); | ||
| 107 | + } | ||
| 108 | + | ||
| 77 | } | 109 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
| 1 | package cn.iocoder.yudao.module.product.dal.mysql.sku; | 1 | package cn.iocoder.yudao.module.product.dal.mysql.sku; |
| 2 | 2 | ||
| 3 | import cn.hutool.core.lang.Assert; | 3 | import cn.hutool.core.lang.Assert; |
| 4 | -import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 5 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 6 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | 4 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 7 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | 5 | import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; |
| 8 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | 6 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 9 | -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||
| 10 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 7 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| 11 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | 8 | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| 12 | import org.apache.ibatis.annotations.Mapper; | 9 | import org.apache.ibatis.annotations.Mapper; |
| @@ -63,23 +60,4 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> { | @@ -63,23 +60,4 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> { | ||
| 63 | return selectList(new QueryWrapper<ProductSkuDO>().apply("stock <= warn_stock")); | 60 | return selectList(new QueryWrapper<ProductSkuDO>().apply("stock <= warn_stock")); |
| 64 | } | 61 | } |
| 65 | 62 | ||
| 66 | - // TODO @puhui999:貌似 IN 不出来数据哈。直接全部查询出来,处理就好列; | ||
| 67 | - /** | ||
| 68 | - * 更新 sku 属性值时使用的分页查询 | ||
| 69 | - * | ||
| 70 | - * @param pageParam 页面参数 | ||
| 71 | - * @return {@link PageResult}<{@link ProductSkuDO}> | ||
| 72 | - */ | ||
| 73 | - default PageResult<ProductSkuDO> selectPage(PageParam pageParam) { | ||
| 74 | - return selectPage(pageParam, new LambdaQueryWrapper<ProductSkuDO>().isNotNull(ProductSkuDO::getProperties)); | ||
| 75 | - } | ||
| 76 | - | ||
| 77 | - /** | ||
| 78 | - * 查询 sku properties 不等于 null 的数量 | ||
| 79 | - * | ||
| 80 | - * @return {@link Long} | ||
| 81 | - */ | ||
| 82 | - default Long selectCountByPropertyNotNull() { | ||
| 83 | - return selectCount(new LambdaQueryWrapper<ProductSkuDO>().isNotNull(ProductSkuDO::getProperties)); | ||
| 84 | - } | ||
| 85 | } | 63 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/category/ProductCategoryServiceImpl.java
| @@ -68,7 +68,10 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { | @@ -68,7 +68,10 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { | ||
| 68 | throw exception(CATEGORY_EXISTS_CHILDREN); | 68 | throw exception(CATEGORY_EXISTS_CHILDREN); |
| 69 | } | 69 | } |
| 70 | // 校验分类是否绑定了 SPU | 70 | // 校验分类是否绑定了 SPU |
| 71 | - validateProductCategoryIsHaveBindSpu(id); | 71 | + Long count = productSpuService.getSpuCountByCategoryId(id); |
| 72 | + if (0 != count) { | ||
| 73 | + throw exception(CATEGORY_HAVE_BIND_SPU); | ||
| 74 | + } | ||
| 72 | // 删除 | 75 | // 删除 |
| 73 | productCategoryMapper.deleteById(id); | 76 | productCategoryMapper.deleteById(id); |
| 74 | } | 77 | } |
| @@ -96,14 +99,6 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { | @@ -96,14 +99,6 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { | ||
| 96 | } | 99 | } |
| 97 | } | 100 | } |
| 98 | 101 | ||
| 99 | - // TODO @puhui999:不用抽方法,因为不太会复用这个方法哈。 | ||
| 100 | - private void validateProductCategoryIsHaveBindSpu(Long id) { | ||
| 101 | - Long count = productSpuService.getSpuCountByCategoryId(id); | ||
| 102 | - if (0 != count) { | ||
| 103 | - throw exception(CATEGORY_HAVE_BIND_SPU); | ||
| 104 | - } | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | @Override | 102 | @Override |
| 108 | public ProductCategoryDO getCategory(Long id) { | 103 | public ProductCategoryDO getCategory(Long id) { |
| 109 | return productCategoryMapper.selectById(id); | 104 | return productCategoryMapper.selectById(id); |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
| @@ -7,10 +7,13 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen | @@ -7,10 +7,13 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen | ||
| 7 | import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; | 7 | import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; |
| 8 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentAdditionalReqVO; | 8 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentAdditionalReqVO; |
| 9 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; | 9 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; |
| 10 | +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO; | ||
| 10 | import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; | 11 | import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; |
| 11 | import org.springframework.stereotype.Service; | 12 | import org.springframework.stereotype.Service; |
| 12 | import org.springframework.validation.annotation.Validated; | 13 | import org.springframework.validation.annotation.Validated; |
| 13 | 14 | ||
| 15 | +import java.util.Map; | ||
| 16 | + | ||
| 14 | /** | 17 | /** |
| 15 | * 商品评论 Service 接口 | 18 | * 商品评论 Service 接口 |
| 16 | * | 19 | * |
| @@ -50,7 +53,7 @@ public interface ProductCommentService { | @@ -50,7 +53,7 @@ public interface ProductCommentService { | ||
| 50 | * @param visible 是否可见 | 53 | * @param visible 是否可见 |
| 51 | * @return 商品评价分页 | 54 | * @return 商品评价分页 |
| 52 | */ | 55 | */ |
| 53 | - PageResult<ProductCommentDO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible); | 56 | + PageResult<AppCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible); |
| 54 | 57 | ||
| 55 | /** | 58 | /** |
| 56 | * 创建商品评论 | 59 | * 创建商品评论 |
| @@ -68,4 +71,12 @@ public interface ProductCommentService { | @@ -68,4 +71,12 @@ public interface ProductCommentService { | ||
| 68 | */ | 71 | */ |
| 69 | void additionalComment(MemberUserRespDTO user, AppCommentAdditionalReqVO createReqVO); | 72 | void additionalComment(MemberUserRespDTO user, AppCommentAdditionalReqVO createReqVO); |
| 70 | 73 | ||
| 74 | + /** | ||
| 75 | + * 评论页面标签数 | ||
| 76 | + * | ||
| 77 | + * @param spuId spu id | ||
| 78 | + * @param visible 是否可见 | ||
| 79 | + * @return 获得商品评价分页 tab count | ||
| 80 | + */ | ||
| 81 | + Map<String, Long> getCommentPageTabsCount(Long spuId, Boolean visible); | ||
| 71 | } | 82 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
| 1 | package cn.iocoder.yudao.module.product.service.comment; | 1 | package cn.iocoder.yudao.module.product.service.comment; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.util.ObjectUtil; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; | 5 | import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; |
| 5 | import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; | 6 | import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; |
| @@ -7,17 +8,28 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen | @@ -7,17 +8,28 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen | ||
| 7 | import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; | 8 | import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; |
| 8 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentAdditionalReqVO; | 9 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentAdditionalReqVO; |
| 9 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; | 10 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; |
| 11 | +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO; | ||
| 12 | +import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; | ||
| 10 | import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; | 13 | import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; |
| 14 | +import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | ||
| 11 | import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; | 15 | import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; |
| 16 | +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | ||
| 17 | +import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; | ||
| 18 | +import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; | ||
| 12 | import org.springframework.stereotype.Service; | 19 | import org.springframework.stereotype.Service; |
| 13 | import org.springframework.util.StringUtils; | 20 | import org.springframework.util.StringUtils; |
| 14 | import org.springframework.validation.annotation.Validated; | 21 | import org.springframework.validation.annotation.Validated; |
| 15 | 22 | ||
| 16 | import javax.annotation.Resource; | 23 | import javax.annotation.Resource; |
| 24 | +import java.math.BigDecimal; | ||
| 25 | +import java.math.RoundingMode; | ||
| 26 | +import java.util.HashMap; | ||
| 27 | +import java.util.Map; | ||
| 17 | import java.util.Objects; | 28 | import java.util.Objects; |
| 18 | 29 | ||
| 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 30 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 20 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; | 31 | import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; |
| 32 | +import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND; | ||
| 21 | 33 | ||
| 22 | /** | 34 | /** |
| 23 | * 商品评论 Service 实现类 | 35 | * 商品评论 Service 实现类 |
| @@ -30,6 +42,11 @@ public class ProductCommentServiceImpl implements ProductCommentService { | @@ -30,6 +42,11 @@ public class ProductCommentServiceImpl implements ProductCommentService { | ||
| 30 | 42 | ||
| 31 | @Resource | 43 | @Resource |
| 32 | private ProductCommentMapper productCommentMapper; | 44 | private ProductCommentMapper productCommentMapper; |
| 45 | + @Resource | ||
| 46 | + private TradeOrderApi tradeOrderApi; | ||
| 47 | + | ||
| 48 | + @Resource | ||
| 49 | + private ProductSpuService productSpuService; | ||
| 33 | 50 | ||
| 34 | @Override | 51 | @Override |
| 35 | public PageResult<ProductCommentDO> getCommentPage(ProductCommentPageReqVO pageReqVO) { | 52 | public PageResult<ProductCommentDO> getCommentPage(ProductCommentPageReqVO pageReqVO) { |
| @@ -53,13 +70,48 @@ public class ProductCommentServiceImpl implements ProductCommentService { | @@ -53,13 +70,48 @@ public class ProductCommentServiceImpl implements ProductCommentService { | ||
| 53 | } | 70 | } |
| 54 | 71 | ||
| 55 | @Override | 72 | @Override |
| 56 | - public PageResult<ProductCommentDO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) { | ||
| 57 | - return productCommentMapper.selectPage(pageVO, visible); | 73 | + public Map<String, Long> getCommentPageTabsCount(Long spuId, Boolean visible) { |
| 74 | + Map<String, Long> countMap = new HashMap<>(4); | ||
| 75 | + // 查询商品 id = spuId 的所有评论数量 | ||
| 76 | + countMap.put(AppCommentPageReqVO.ALL_COUNT, productCommentMapper.selectTabCount(spuId, visible, AppCommentPageReqVO.ALL)); | ||
| 77 | + // 查询商品 id = spuId 的所有好评数量 | ||
| 78 | + countMap.put(AppCommentPageReqVO.FAVOURABLE_COMMENT_COUNT, productCommentMapper.selectTabCount(spuId, visible, AppCommentPageReqVO.FAVOURABLE_COMMENT)); | ||
| 79 | + // 查询商品 id = spuId 的所有中评数量 | ||
| 80 | + countMap.put(AppCommentPageReqVO.MEDIOCRE_COMMENT_COUNT, productCommentMapper.selectTabCount(spuId, visible, AppCommentPageReqVO.MEDIOCRE_COMMENT)); | ||
| 81 | + // 查询商品 id = spuId 的所有差评数量 | ||
| 82 | + countMap.put(AppCommentPageReqVO.NEGATIVE_COMMENT_COUNT, productCommentMapper.selectTabCount(spuId, visible, AppCommentPageReqVO.NEGATIVE_COMMENT)); | ||
| 83 | + return countMap; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + @Override | ||
| 87 | + public PageResult<AppCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) { | ||
| 88 | + PageResult<AppCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage02(productCommentMapper.selectPage(pageVO, visible)); | ||
| 89 | + result.getList().forEach(item -> { | ||
| 90 | + // 判断用户是否选择匿名 | ||
| 91 | + if (ObjectUtil.equal(item.getAnonymous(), true)) { | ||
| 92 | + item.setUserNickname(AppCommentPageReqVO.ANONYMOUS_NICKNAME); | ||
| 93 | + } | ||
| 94 | + // 计算评价最终综合评分 最终星数 = (商品评星 + 服务评星) / 2 | ||
| 95 | + BigDecimal sumScore = new BigDecimal(item.getScores() + item.getBenefitScores()); | ||
| 96 | + BigDecimal divide = sumScore.divide(BigDecimal.valueOf(2L), 0, RoundingMode.DOWN); | ||
| 97 | + item.setFinalScore(divide.intValue()); | ||
| 98 | + }); | ||
| 99 | + return result; | ||
| 58 | } | 100 | } |
| 59 | 101 | ||
| 60 | @Override | 102 | @Override |
| 61 | public void createComment(ProductCommentDO productComment, Boolean system) { | 103 | public void createComment(ProductCommentDO productComment, Boolean system) { |
| 62 | if (!system) { | 104 | if (!system) { |
| 105 | + // TODO 判断订单是否存在 fix | ||
| 106 | + TradeOrderRespDTO order = tradeOrderApi.getOrder(productComment.getOrderId()); | ||
| 107 | + if (null == order) { | ||
| 108 | + throw exception(ORDER_NOT_FOUND); | ||
| 109 | + } | ||
| 110 | + // TODO 判断 SPU 是否存在 fix | ||
| 111 | + ProductSpuDO spu = productSpuService.getSpu(productComment.getSpuId()); | ||
| 112 | + if (null == spu) { | ||
| 113 | + throw exception(SPU_NOT_EXISTS); | ||
| 114 | + } | ||
| 63 | // 判断当前订单的当前商品用户是否评价过 | 115 | // 判断当前订单的当前商品用户是否评价过 |
| 64 | ProductCommentDO exist = productCommentMapper.findByUserIdAndOrderIdAndSpuId(productComment.getId(), productComment.getOrderId(), productComment.getSpuId()); | 116 | ProductCommentDO exist = productCommentMapper.findByUserIdAndOrderIdAndSpuId(productComment.getId(), productComment.getOrderId(), productComment.getSpuId()); |
| 65 | if (null != exist) { | 117 | if (null != exist) { |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyServiceImpl.java
| @@ -71,8 +71,8 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { | @@ -71,8 +71,8 @@ public class ProductPropertyServiceImpl implements ProductPropertyService { | ||
| 71 | // 更新 | 71 | // 更新 |
| 72 | ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO); | 72 | ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO); |
| 73 | productPropertyMapper.updateById(updateObj); | 73 | productPropertyMapper.updateById(updateObj); |
| 74 | - // TODO @puhui:是不是只要传递变量,不传递整个 updateObj 变量哈 | ||
| 75 | - productSkuService.updateSkuProperty(updateObj); | 74 | + // 更新 sku 相关属性 |
| 75 | + productSkuService.updateSkuProperty(updateObj.getId(), updateObj.getName()); | ||
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | @Override | 78 | @Override |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/property/ProductPropertyValueServiceImpl.java
| @@ -73,10 +73,8 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ | @@ -73,10 +73,8 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ | ||
| 73 | // 更新 | 73 | // 更新 |
| 74 | ProductPropertyValueDO updateObj = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO); | 74 | ProductPropertyValueDO updateObj = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO); |
| 75 | productPropertyValueMapper.updateById(updateObj); | 75 | productPropertyValueMapper.updateById(updateObj); |
| 76 | - | ||
| 77 | - // TODO 芋艿:更新时,需要看看 sku 表 fix | ||
| 78 | - // TODO @puhui:是不是只要传递变量,不传递整个 updateObj 变量哈 | ||
| 79 | - productSkuService.updateSkuPropertyValue(updateObj); | 76 | + // 更新 sku 相关属性 |
| 77 | + productSkuService.updateSkuPropertyValue(updateObj.getId(), updateObj.getName()); | ||
| 80 | } | 78 | } |
| 81 | 79 | ||
| 82 | @Override | 80 | @Override |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
| @@ -2,8 +2,6 @@ package cn.iocoder.yudao.module.product.service.sku; | @@ -2,8 +2,6 @@ package cn.iocoder.yudao.module.product.service.sku; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; | 3 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 4 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; | 4 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; |
| 5 | -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; | ||
| 6 | -import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; | ||
| 7 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | 5 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 8 | 6 | ||
| 9 | import java.util.Collection; | 7 | import java.util.Collection; |
| @@ -111,16 +109,18 @@ public interface ProductSkuService { | @@ -111,16 +109,18 @@ public interface ProductSkuService { | ||
| 111 | /** | 109 | /** |
| 112 | * 更新 sku 属性 | 110 | * 更新 sku 属性 |
| 113 | * | 111 | * |
| 114 | - * @param updateObj 属性对象 | 112 | + * @param propertyId 属性 id |
| 113 | + * @param propertyName 属性名 | ||
| 115 | * @return int 影响的行数 | 114 | * @return int 影响的行数 |
| 116 | */ | 115 | */ |
| 117 | - int updateSkuProperty(ProductPropertyDO updateObj); | 116 | + int updateSkuProperty(Long propertyId, String propertyName); |
| 118 | 117 | ||
| 119 | /** | 118 | /** |
| 120 | * 更新 sku 属性值 | 119 | * 更新 sku 属性值 |
| 121 | * | 120 | * |
| 122 | - * @param updateObj 属性值对象 | 121 | + * @param propertyValueId 属性值 id |
| 122 | + * @param propertyValueName 属性值名字 | ||
| 123 | * @return int 影响的行数 | 123 | * @return int 影响的行数 |
| 124 | */ | 124 | */ |
| 125 | - int updateSkuPropertyValue(ProductPropertyValueDO updateObj); | 125 | + int updateSkuPropertyValue(Long propertyValueId, String propertyValueName); |
| 126 | } | 126 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
| @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.product.service.sku; | @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.product.service.sku; | ||
| 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.ObjectUtil; |
| 5 | -import cn.iocoder.yudao.framework.common.pojo.PageParam; | ||
| 6 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 7 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; | 5 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 6 | +import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; | ||
| 8 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; | 7 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; |
| 9 | import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; | 8 | import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert; |
| 10 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; | 9 | import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; |
| @@ -80,16 +79,25 @@ public class ProductSkuServiceImpl implements ProductSkuService { | @@ -80,16 +79,25 @@ public class ProductSkuServiceImpl implements ProductSkuService { | ||
| 80 | 79 | ||
| 81 | @Override | 80 | @Override |
| 82 | public void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> skus, Boolean specType) { | 81 | public void validateSkuList(List<ProductSkuCreateOrUpdateReqVO> skus, Boolean specType) { |
| 83 | - // 非多规格,不需要校验 | ||
| 84 | - if (ObjectUtil.notEqual(specType, true)) { | ||
| 85 | - return; | ||
| 86 | - } | ||
| 87 | - | ||
| 88 | // 0、校验skus是否为空 | 82 | // 0、校验skus是否为空 |
| 89 | if (CollUtil.isEmpty(skus)) { | 83 | if (CollUtil.isEmpty(skus)) { |
| 90 | throw exception(SKU_NOT_EXISTS); | 84 | throw exception(SKU_NOT_EXISTS); |
| 91 | } | 85 | } |
| 92 | - | 86 | + // 单规格处理 |
| 87 | + if (ObjectUtil.equal(specType, false)) { | ||
| 88 | + ProductSkuCreateOrUpdateReqVO skuVO = skus.get(0); | ||
| 89 | + // 赋予单规格默认属性 | ||
| 90 | + List<ProductSkuBaseVO.Property> properties = new ArrayList<>(); | ||
| 91 | + ProductSkuBaseVO.Property property = new ProductSkuBaseVO.Property(); | ||
| 92 | + property.setPropertyId(ProductPropertyDO.PROPERTY_ID); | ||
| 93 | + property.setPropertyName(ProductPropertyDO.PROPERTY_NAME); | ||
| 94 | + property.setValueId(ProductPropertyValueDO.VALUE_ID); | ||
| 95 | + property.setValueName(ProductPropertyValueDO.VALUE_NAME); | ||
| 96 | + properties.add(property); | ||
| 97 | + skuVO.setProperties(properties); | ||
| 98 | + // 单规格不需要后续的校验 | ||
| 99 | + return; | ||
| 100 | + } | ||
| 93 | // 1、校验属性项存在 | 101 | // 1、校验属性项存在 |
| 94 | Set<Long> propertyIds = skus.stream().filter(p -> p.getProperties() != null) | 102 | Set<Long> propertyIds = skus.stream().filter(p -> p.getProperties() != null) |
| 95 | // 遍历多个 Property 属性 | 103 | // 遍历多个 Property 属性 |
| @@ -156,81 +164,51 @@ public class ProductSkuServiceImpl implements ProductSkuService { | @@ -156,81 +164,51 @@ public class ProductSkuServiceImpl implements ProductSkuService { | ||
| 156 | } | 164 | } |
| 157 | 165 | ||
| 158 | @Override | 166 | @Override |
| 159 | - public int updateSkuProperty(ProductPropertyDO updateObj) { | ||
| 160 | - // TODO 看了一下数据库有关于 json 字符串的处理,怕数据库出现兼容问题这里还是用数据库常规操作来实现 | ||
| 161 | - // TODO @puhui999:直接全部查询处理,批量处理就好列;一般项目的商品不会超过几十万的哈。 | ||
| 162 | - Long count = productSkuMapper.selectCountByPropertyNotNull(); | ||
| 163 | - int currentPage = 1; | 167 | + public int updateSkuProperty(Long propertyId, String propertyName) { |
| 168 | + // 获取所有的 sku | ||
| 169 | + List<ProductSkuDO> skuDOList = productSkuMapper.selectList(); | ||
| 170 | + // 处理后需要更新的 sku | ||
| 164 | List<ProductSkuDO> updateSkus = new ArrayList<>(); | 171 | List<ProductSkuDO> updateSkus = new ArrayList<>(); |
| 165 | - if (count == 0) { | 172 | + if (CollUtil.isEmpty(skuDOList)) { |
| 166 | return 0; | 173 | return 0; |
| 167 | } | 174 | } |
| 168 | - int pageSize = 100; | ||
| 169 | - for (int i = 0; i <= count / 100; i++) { | ||
| 170 | - PageParam pageParam = new PageParam().setPageNo(currentPage + i).setPageSize(pageSize); | ||
| 171 | - // 分页查找出 sku 属性不为 null 的 | ||
| 172 | - PageResult<ProductSkuDO> skuPage = productSkuMapper.selectPage(pageParam); | ||
| 173 | - List<ProductSkuDO> records = skuPage.getList(); | ||
| 174 | - if (CollUtil.isEmpty(records)) { | ||
| 175 | - break; | ||
| 176 | - } | ||
| 177 | - records.stream().filter(sku -> sku.getProperties() != null) | ||
| 178 | - .forEach(sku -> sku.getProperties().forEach(property -> { | ||
| 179 | - if (property.getPropertyId().equals(updateObj.getId())) { | ||
| 180 | - property.setPropertyName(updateObj.getName()); | ||
| 181 | - updateSkus.add(sku); | ||
| 182 | - } | ||
| 183 | - })); | ||
| 184 | - } | 175 | + skuDOList.stream().filter(sku -> sku.getProperties() != null) |
| 176 | + .forEach(sku -> sku.getProperties().forEach(property -> { | ||
| 177 | + if (property.getPropertyId().equals(propertyId)) { | ||
| 178 | + property.setPropertyName(propertyName); | ||
| 179 | + updateSkus.add(sku); | ||
| 180 | + } | ||
| 181 | + })); | ||
| 185 | if (CollUtil.isEmpty(updateSkus)) { | 182 | if (CollUtil.isEmpty(updateSkus)) { |
| 186 | return 0; | 183 | return 0; |
| 187 | } | 184 | } |
| 188 | - // TODO @puhui999:貌似 updateBatch 自己会拆分批次,这里不用再拆分了 | ||
| 189 | - // 每批处理的大小 | ||
| 190 | - int batchSize = 1000; | ||
| 191 | - for (int i = 0; i < updateSkus.size(); i += batchSize) { | ||
| 192 | - List<ProductSkuDO> batchSkuDOs = updateSkus.subList(i, Math.min(i + batchSize, updateSkus.size())); | ||
| 193 | - productSkuMapper.updateBatch(batchSkuDOs, batchSize); | ||
| 194 | - } | 185 | + |
| 186 | + productSkuMapper.updateBatch(updateSkus); | ||
| 195 | return updateSkus.size(); | 187 | return updateSkus.size(); |
| 196 | } | 188 | } |
| 197 | 189 | ||
| 198 | @Override | 190 | @Override |
| 199 | - public int updateSkuPropertyValue(ProductPropertyValueDO updateObj) { | ||
| 200 | - // TODO 看了一下数据库有关于 json 字符串的处理,怕数据库出现兼容问题这里还是用数据库常规操作来实现 | ||
| 201 | - Long count = productSkuMapper.selectCountByPropertyNotNull(); | ||
| 202 | - int currentPage = 1; | 191 | + public int updateSkuPropertyValue(Long propertyValueId, String propertyValueName) { |
| 192 | + // 获取所有的 sku | ||
| 193 | + List<ProductSkuDO> skuDOList = productSkuMapper.selectList(); | ||
| 194 | + // 处理后需要更新的 sku | ||
| 203 | List<ProductSkuDO> updateSkus = new ArrayList<>(); | 195 | List<ProductSkuDO> updateSkus = new ArrayList<>(); |
| 204 | - if (count == 0) { | 196 | + if (CollUtil.isEmpty(skuDOList)) { |
| 205 | return 0; | 197 | return 0; |
| 206 | } | 198 | } |
| 207 | - int pageSize = 100; | ||
| 208 | - for (int i = 0; i <= count / 100; i++) { | ||
| 209 | - PageParam pageParam = new PageParam().setPageNo(currentPage + i).setPageSize(pageSize); | ||
| 210 | - // 分页查找出 sku 属性不为 null 的 | ||
| 211 | - PageResult<ProductSkuDO> skuPage = productSkuMapper.selectPage(pageParam); | ||
| 212 | - List<ProductSkuDO> records = skuPage.getList(); | ||
| 213 | - if (CollUtil.isEmpty(records)) { | ||
| 214 | - break; | ||
| 215 | - } | ||
| 216 | - records.stream() | ||
| 217 | - .filter(sku -> sku.getProperties() != null) | ||
| 218 | - .forEach(sku -> sku.getProperties().forEach(property -> { | ||
| 219 | - if (property.getValueId().equals(updateObj.getId())) { | ||
| 220 | - property.setValueName(updateObj.getName()); | ||
| 221 | - updateSkus.add(sku); | ||
| 222 | - } | ||
| 223 | - })); | ||
| 224 | - } | 199 | + skuDOList.stream() |
| 200 | + .filter(sku -> sku.getProperties() != null) | ||
| 201 | + .forEach(sku -> sku.getProperties().forEach(property -> { | ||
| 202 | + if (property.getValueId().equals(propertyValueId)) { | ||
| 203 | + property.setValueName(propertyValueName); | ||
| 204 | + updateSkus.add(sku); | ||
| 205 | + } | ||
| 206 | + })); | ||
| 225 | if (CollUtil.isEmpty(updateSkus)) { | 207 | if (CollUtil.isEmpty(updateSkus)) { |
| 226 | return 0; | 208 | return 0; |
| 227 | } | 209 | } |
| 228 | - // 每批处理的大小 | ||
| 229 | - int batchSize = 1000; | ||
| 230 | - for (int i = 0; i < updateSkus.size(); i += batchSize) { | ||
| 231 | - List<ProductSkuDO> batchSkuDOs = updateSkus.subList(i, Math.min(i + batchSize, updateSkus.size())); | ||
| 232 | - productSkuMapper.updateBatch(batchSkuDOs, batchSize); | ||
| 233 | - } | 210 | + |
| 211 | + productSkuMapper.updateBatch(updateSkus); | ||
| 234 | return updateSkus.size(); | 212 | return updateSkus.size(); |
| 235 | } | 213 | } |
| 236 | 214 |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.service.spu; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.service.spu; | ||
| 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.module.product.controller.admin.spu.vo.*; | 4 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; |
| 5 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; | ||
| 5 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; | 6 | import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; |
| 6 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | 7 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 7 | 8 | ||
| @@ -135,4 +136,11 @@ public interface ProductSpuService { | @@ -135,4 +136,11 @@ public interface ProductSpuService { | ||
| 135 | */ | 136 | */ |
| 136 | Long getSpuCountByCategoryId(Long id); | 137 | Long getSpuCountByCategoryId(Long id); |
| 137 | 138 | ||
| 139 | + /** | ||
| 140 | + * 通过 spu id 获取商品 SPU 明细 | ||
| 141 | + * | ||
| 142 | + * @param id id | ||
| 143 | + * @return 用户 App - 商品 SPU 明细 | ||
| 144 | + */ | ||
| 145 | + AppProductSpuDetailRespVO getAppProductSpuDetail(Long id); | ||
| 138 | } | 146 | } |
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
| @@ -7,15 +7,21 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | @@ -7,15 +7,21 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | ||
| 7 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; | 7 | import cn.iocoder.yudao.module.product.controller.admin.category.vo.ProductCategoryListReqVO; |
| 8 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; | 8 | import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; |
| 9 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; | 9 | import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*; |
| 10 | +import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO; | ||
| 10 | 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.convert.sku.ProductSkuConvert; | ||
| 11 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; | 13 | import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert; |
| 12 | import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; | 14 | import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO; |
| 15 | +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO; | ||
| 16 | +import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO; | ||
| 13 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; | 17 | import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; |
| 14 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; | 18 | import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; |
| 15 | import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; | 19 | import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper; |
| 16 | import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; | 20 | import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; |
| 17 | import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; | 21 | import cn.iocoder.yudao.module.product.service.brand.ProductBrandService; |
| 18 | import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; | 22 | import cn.iocoder.yudao.module.product.service.category.ProductCategoryService; |
| 23 | +import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; | ||
| 24 | +import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO; | ||
| 19 | import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; | 25 | import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; |
| 20 | import com.google.common.collect.Maps; | 26 | import com.google.common.collect.Maps; |
| 21 | import org.springframework.context.annotation.Lazy; | 27 | import org.springframework.context.annotation.Lazy; |
| @@ -51,6 +57,9 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -51,6 +57,9 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 51 | private ProductBrandService brandService; | 57 | private ProductBrandService brandService; |
| 52 | @Resource | 58 | @Resource |
| 53 | private ProductCategoryService categoryService; | 59 | private ProductCategoryService categoryService; |
| 60 | + @Resource | ||
| 61 | + @Lazy // 循环依赖,避免报错 | ||
| 62 | + private ProductPropertyValueService productPropertyValueService; | ||
| 54 | 63 | ||
| 55 | @Override | 64 | @Override |
| 56 | @Transactional(rollbackFor = Exception.class) | 65 | @Transactional(rollbackFor = Exception.class) |
| @@ -141,7 +150,11 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -141,7 +150,11 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 141 | // 校验存在 | 150 | // 校验存在 |
| 142 | validateSpuExists(id); | 151 | validateSpuExists(id); |
| 143 | // 校验商品状态不是回收站不能删除 | 152 | // 校验商品状态不是回收站不能删除 |
| 144 | - validateSpuStatus(id); | 153 | + ProductSpuDO spuDO = productSpuMapper.selectById(id); |
| 154 | + // 判断 SPU 状态是否为回收站 | ||
| 155 | + if (ObjectUtil.notEqual(spuDO.getStatus(), ProductSpuStatusEnum.RECYCLE.getStatus())) { | ||
| 156 | + throw exception(SPU_NOT_RECYCLE); | ||
| 157 | + } | ||
| 145 | 158 | ||
| 146 | // 删除 SPU | 159 | // 删除 SPU |
| 147 | productSpuMapper.deleteById(id); | 160 | productSpuMapper.deleteById(id); |
| @@ -155,20 +168,6 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -155,20 +168,6 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 155 | } | 168 | } |
| 156 | } | 169 | } |
| 157 | 170 | ||
| 158 | - /** | ||
| 159 | - * 验证 SPU 状态是否为回收站 | ||
| 160 | - * | ||
| 161 | - * @param id id | ||
| 162 | - */ | ||
| 163 | - // TODO puhui999:感觉不用独立出来一个方法,直接在 deleteSpu 方法中校验即可 | ||
| 164 | - private void validateSpuStatus(Long id) { | ||
| 165 | - ProductSpuDO spuDO = productSpuMapper.selectById(id); | ||
| 166 | - // 判断 SPU 状态是否为回收站 | ||
| 167 | - if (ObjectUtil.notEqual(spuDO.getStatus(), ProductSpuStatusEnum.RECYCLE.getStatus())) { | ||
| 168 | - throw exception(SPU_NOT_RECYCLE); | ||
| 169 | - } | ||
| 170 | - } | ||
| 171 | - | ||
| 172 | @Override | 171 | @Override |
| 173 | public ProductSpuDO getSpu(Long id) { | 172 | public ProductSpuDO getSpu(Long id) { |
| 174 | return productSpuMapper.selectById(id); | 173 | return productSpuMapper.selectById(id); |
| @@ -263,4 +262,35 @@ public class ProductSpuServiceImpl implements ProductSpuService { | @@ -263,4 +262,35 @@ public class ProductSpuServiceImpl implements ProductSpuService { | ||
| 263 | return productSpuMapper.selectCount(ProductSpuDO::getCategoryId, id); | 262 | return productSpuMapper.selectCount(ProductSpuDO::getCategoryId, id); |
| 264 | } | 263 | } |
| 265 | 264 | ||
| 265 | + @Override | ||
| 266 | + public AppProductSpuDetailRespVO getAppProductSpuDetail(Long id) { | ||
| 267 | + // 获得商品 SPU | ||
| 268 | + ProductSpuDO spu = getSpu(id); | ||
| 269 | + if (spu == null) { | ||
| 270 | + throw exception(SPU_NOT_EXISTS); | ||
| 271 | + } | ||
| 272 | + if (!ProductSpuStatusEnum.isEnable(spu.getStatus())) { | ||
| 273 | + throw exception(SPU_NOT_ENABLE); | ||
| 274 | + } | ||
| 275 | + | ||
| 276 | + // 查询商品 SKU | ||
| 277 | + List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId()); | ||
| 278 | + List<ProductPropertyValueDetailRespBO> propertyValues = new ArrayList<>(); | ||
| 279 | + // 单规格商品 赋予默认属性值 | ||
| 280 | + if (ObjectUtil.equal(spu.getSpecType(), false)) { | ||
| 281 | + ProductPropertyValueDetailRespBO respBO = new ProductPropertyValueDetailRespBO(); | ||
| 282 | + respBO.setPropertyId(ProductPropertyDO.PROPERTY_ID); | ||
| 283 | + respBO.setPropertyName(ProductPropertyDO.PROPERTY_NAME); | ||
| 284 | + respBO.setValueId(ProductPropertyValueDO.VALUE_ID); | ||
| 285 | + respBO.setValueName(ProductPropertyValueDO.VALUE_NAME); | ||
| 286 | + propertyValues.add(respBO); | ||
| 287 | + } else { | ||
| 288 | + // 多规格商品则查询商品属性 | ||
| 289 | + propertyValues = productPropertyValueService | ||
| 290 | + .getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus)); | ||
| 291 | + } | ||
| 292 | + // 拼接 | ||
| 293 | + return ProductSpuConvert.INSTANCE.convertForGetSpuDetail(spu, skus, propertyValues); | ||
| 294 | + } | ||
| 295 | + | ||
| 266 | } | 296 | } |
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
| @@ -11,15 +11,22 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen | @@ -11,15 +11,22 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen | ||
| 11 | import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; | 11 | import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; |
| 12 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentAdditionalReqVO; | 12 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentAdditionalReqVO; |
| 13 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; | 13 | import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; |
| 14 | +import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO; | ||
| 14 | import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; | 15 | import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; |
| 15 | import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; | 16 | import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; |
| 16 | import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; | 17 | import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; |
| 17 | import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; | 18 | import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; |
| 19 | +import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; | ||
| 20 | +import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi; | ||
| 18 | import org.junit.jupiter.api.Test; | 21 | import org.junit.jupiter.api.Test; |
| 22 | +import org.springframework.boot.test.mock.mockito.MockBean; | ||
| 19 | import org.springframework.context.annotation.Import; | 23 | import org.springframework.context.annotation.Import; |
| 24 | +import org.springframework.context.annotation.Lazy; | ||
| 20 | 25 | ||
| 21 | import javax.annotation.Resource; | 26 | import javax.annotation.Resource; |
| 27 | +import java.time.LocalDateTime; | ||
| 22 | import java.util.Date; | 28 | import java.util.Date; |
| 29 | +import java.util.Map; | ||
| 23 | 30 | ||
| 24 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | 31 | import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; |
| 25 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | 32 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| @@ -39,8 +46,14 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | @@ -39,8 +46,14 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | ||
| 39 | private ProductCommentMapper productCommentMapper; | 46 | private ProductCommentMapper productCommentMapper; |
| 40 | 47 | ||
| 41 | @Resource | 48 | @Resource |
| 49 | + @Lazy | ||
| 42 | private ProductCommentServiceImpl productCommentService; | 50 | private ProductCommentServiceImpl productCommentService; |
| 43 | 51 | ||
| 52 | + @MockBean | ||
| 53 | + private TradeOrderApi tradeOrderApi; | ||
| 54 | + @MockBean | ||
| 55 | + private ProductSpuService productSpuService; | ||
| 56 | + | ||
| 44 | public String generateNo() { | 57 | public String generateNo() { |
| 45 | return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); | 58 | return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999); |
| 46 | } | 59 | } |
| @@ -70,6 +83,23 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | @@ -70,6 +83,23 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | ||
| 70 | o.setScores(ProductCommentScoresEnum.FOUR.getScores()); | 83 | o.setScores(ProductCommentScoresEnum.FOUR.getScores()); |
| 71 | o.setReplied(Boolean.TRUE); | 84 | o.setReplied(Boolean.TRUE); |
| 72 | o.setVisible(Boolean.TRUE); | 85 | o.setVisible(Boolean.TRUE); |
| 86 | + o.setId(generateId()); | ||
| 87 | + o.setUserId(generateId()); | ||
| 88 | + o.setAnonymous(Boolean.TRUE); | ||
| 89 | + o.setOrderId(generateId()); | ||
| 90 | + o.setOrderItemId(generateId()); | ||
| 91 | + o.setSpuId(generateId()); | ||
| 92 | + o.setSkuId(generateId()); | ||
| 93 | + o.setDescriptionScores(ProductCommentScoresEnum.FOUR.getScores()); | ||
| 94 | + o.setBenefitScores(ProductCommentScoresEnum.FOUR.getScores()); | ||
| 95 | + o.setDeliveryScores(ProductCommentScoresEnum.FOUR.getScores()); | ||
| 96 | + o.setContent("真好吃"); | ||
| 97 | + o.setReplyUserId(generateId()); | ||
| 98 | + o.setReplyContent("确实"); | ||
| 99 | + o.setReplyTime(LocalDateTime.now()); | ||
| 100 | + o.setAdditionalTime(LocalDateTime.now()); | ||
| 101 | + o.setCreateTime(LocalDateTime.now()); | ||
| 102 | + o.setUpdateTime(LocalDateTime.now()); | ||
| 73 | }); | 103 | }); |
| 74 | productCommentMapper.insert(productComment); | 104 | productCommentMapper.insert(productComment); |
| 75 | 105 | ||
| @@ -77,7 +107,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | @@ -77,7 +107,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | ||
| 77 | Long spuId = productComment.getSpuId(); | 107 | Long spuId = productComment.getSpuId(); |
| 78 | 108 | ||
| 79 | // 测试 userNickname 不匹配 | 109 | // 测试 userNickname 不匹配 |
| 80 | - productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setUserNickname("王三"))); | 110 | + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setUserNickname("王三").setScores(ProductCommentScoresEnum.ONE.getScores()))); |
| 81 | // 测试 orderId 不匹配 | 111 | // 测试 orderId 不匹配 |
| 82 | productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setOrderId(generateId()))); | 112 | productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setOrderId(generateId()))); |
| 83 | // 测试 spuId 不匹配 | 113 | // 测试 spuId 不匹配 |
| @@ -107,8 +137,25 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | @@ -107,8 +137,25 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { | ||
| 107 | PageResult<ProductCommentDO> all = productCommentService.getCommentPage(new ProductCommentPageReqVO()); | 137 | PageResult<ProductCommentDO> all = productCommentService.getCommentPage(new ProductCommentPageReqVO()); |
| 108 | assertEquals(8, all.getTotal()); | 138 | assertEquals(8, all.getTotal()); |
| 109 | 139 | ||
| 110 | - PageResult<ProductCommentDO> visible = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE); | ||
| 111 | - assertEquals(7, visible.getTotal()); | 140 | + // 测试获取所有商品分页评论数据 |
| 141 | + PageResult<AppCommentRespVO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE); | ||
| 142 | + assertEquals(7, result1.getTotal()); | ||
| 143 | + | ||
| 144 | + // 测试获取所有商品分页中评数据 | ||
| 145 | + PageResult<AppCommentRespVO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); | ||
| 146 | + assertEquals(2, result2.getTotal()); | ||
| 147 | + | ||
| 148 | + // 测试获取指定 spuId 商品分页中评数据 | ||
| 149 | + PageResult<AppCommentRespVO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE); | ||
| 150 | + assertEquals(2, result3.getTotal()); | ||
| 151 | + | ||
| 152 | + // 测试分页 tab count | ||
| 153 | + Map<String, Long> tabsCount = productCommentService.getCommentPageTabsCount(spuId, Boolean.TRUE); | ||
| 154 | + assertEquals(6, tabsCount.get(AppCommentPageReqVO.ALL_COUNT)); | ||
| 155 | + assertEquals(4, tabsCount.get(AppCommentPageReqVO.FAVOURABLE_COMMENT_COUNT)); | ||
| 156 | + assertEquals(2, tabsCount.get(AppCommentPageReqVO.MEDIOCRE_COMMENT_COUNT)); | ||
| 157 | + assertEquals(0, tabsCount.get(AppCommentPageReqVO.NEGATIVE_COMMENT_COUNT)); | ||
| 158 | + | ||
| 112 | } | 159 | } |
| 113 | 160 | ||
| 114 | @Test | 161 | @Test |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApi.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.api.order; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 订单 API 接口 | ||
| 7 | + * | ||
| 8 | + * @author HUIHUI | ||
| 9 | + */ | ||
| 10 | +public interface TradeOrderApi { | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * 获取订单通过订单 id | ||
| 14 | + * | ||
| 15 | + * @param id id | ||
| 16 | + * @return 订单信息 Response DTO | ||
| 17 | + */ | ||
| 18 | + TradeOrderRespDTO getOrder(Long id); | ||
| 19 | + | ||
| 20 | +} |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/order/dto/TradeOrderRespDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.api.order.dto; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.TerminalEnum; | ||
| 4 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderCancelTypeEnum; | ||
| 5 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum; | ||
| 6 | +import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | ||
| 7 | +import lombok.Data; | ||
| 8 | + | ||
| 9 | +import java.time.LocalDateTime; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 订单信息 Response DTO | ||
| 13 | + * | ||
| 14 | + * @author HUIHUI | ||
| 15 | + */ | ||
| 16 | +@Data | ||
| 17 | +public class TradeOrderRespDTO { | ||
| 18 | + | ||
| 19 | + // ========== 订单基本信息 ========== | ||
| 20 | + /** | ||
| 21 | + * 订单编号,主键自增 | ||
| 22 | + */ | ||
| 23 | + private Long id; | ||
| 24 | + /** | ||
| 25 | + * 订单流水号 | ||
| 26 | + * <p> | ||
| 27 | + * 例如说,1146347329394184195 | ||
| 28 | + */ | ||
| 29 | + private String no; | ||
| 30 | + /** | ||
| 31 | + * 订单类型 | ||
| 32 | + * <p> | ||
| 33 | + * 枚举 {@link TradeOrderTypeEnum} | ||
| 34 | + */ | ||
| 35 | + private Integer type; | ||
| 36 | + /** | ||
| 37 | + * 订单来源 | ||
| 38 | + * <p> | ||
| 39 | + * 枚举 {@link TerminalEnum} | ||
| 40 | + */ | ||
| 41 | + private Integer terminal; | ||
| 42 | + /** | ||
| 43 | + * 用户编号 | ||
| 44 | + * <p> | ||
| 45 | + * 关联 MemberUserDO 的 id 编号 | ||
| 46 | + */ | ||
| 47 | + private Long userId; | ||
| 48 | + /** | ||
| 49 | + * 用户 IP | ||
| 50 | + */ | ||
| 51 | + private String userIp; | ||
| 52 | + /** | ||
| 53 | + * 用户备注 | ||
| 54 | + */ | ||
| 55 | + private String userRemark; | ||
| 56 | + /** | ||
| 57 | + * 订单状态 | ||
| 58 | + * <p> | ||
| 59 | + * 枚举 {@link TradeOrderStatusEnum} | ||
| 60 | + */ | ||
| 61 | + private Integer status; | ||
| 62 | + /** | ||
| 63 | + * 购买的商品数量 | ||
| 64 | + */ | ||
| 65 | + private Integer productCount; | ||
| 66 | + /** | ||
| 67 | + * 订单完成时间 | ||
| 68 | + */ | ||
| 69 | + private LocalDateTime finishTime; | ||
| 70 | + /** | ||
| 71 | + * 订单取消时间 | ||
| 72 | + */ | ||
| 73 | + private LocalDateTime cancelTime; | ||
| 74 | + /** | ||
| 75 | + * 取消类型 | ||
| 76 | + * <p> | ||
| 77 | + * 枚举 {@link TradeOrderCancelTypeEnum} | ||
| 78 | + */ | ||
| 79 | + private Integer cancelType; | ||
| 80 | + /** | ||
| 81 | + * 商家备注 | ||
| 82 | + */ | ||
| 83 | + private String remark; | ||
| 84 | + /** | ||
| 85 | + * 是否评价 | ||
| 86 | + * <p> | ||
| 87 | + * true - 已评价 | ||
| 88 | + * false - 未评价 | ||
| 89 | + */ | ||
| 90 | + private Boolean commentStatus; | ||
| 91 | + | ||
| 92 | +} |
yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/api/package-info.java
0 → 100644
yudao-module-mall/yudao-module-trade-biz/pom.xml
| @@ -23,7 +23,6 @@ | @@ -23,7 +23,6 @@ | ||
| 23 | <artifactId>yudao-module-trade-api</artifactId> | 23 | <artifactId>yudao-module-trade-api</artifactId> |
| 24 | <version>${revision}</version> | 24 | <version>${revision}</version> |
| 25 | </dependency> | 25 | </dependency> |
| 26 | - | ||
| 27 | <dependency> | 26 | <dependency> |
| 28 | <groupId>cn.iocoder.boot</groupId> | 27 | <groupId>cn.iocoder.boot</groupId> |
| 29 | <artifactId>yudao-module-product-api</artifactId> | 28 | <artifactId>yudao-module-product-api</artifactId> |
| @@ -44,6 +43,11 @@ | @@ -44,6 +43,11 @@ | ||
| 44 | <artifactId>yudao-module-member-api</artifactId> | 43 | <artifactId>yudao-module-member-api</artifactId> |
| 45 | <version>${revision}</version> | 44 | <version>${revision}</version> |
| 46 | </dependency> | 45 | </dependency> |
| 46 | + <dependency> | ||
| 47 | + <groupId>cn.iocoder.boot</groupId> | ||
| 48 | + <artifactId>yudao-module-system-api</artifactId> | ||
| 49 | + <version>${revision}</version> | ||
| 50 | + </dependency> | ||
| 47 | 51 | ||
| 48 | <!-- 业务组件 --> | 52 | <!-- 业务组件 --> |
| 49 | <dependency> | 53 | <dependency> |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/order/TradeOrderApiImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.api.order; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; | ||
| 4 | +import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | ||
| 5 | +import cn.iocoder.yudao.module.trade.service.order.TradeOrderService; | ||
| 6 | +import org.springframework.stereotype.Service; | ||
| 7 | +import org.springframework.validation.annotation.Validated; | ||
| 8 | + | ||
| 9 | +import javax.annotation.Resource; | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | + * 订单 API 接口实现类 | ||
| 13 | + * | ||
| 14 | + * @author HUIHUI | ||
| 15 | + */ | ||
| 16 | +@Service | ||
| 17 | +@Validated | ||
| 18 | +public class TradeOrderApiImpl implements TradeOrderApi { | ||
| 19 | + | ||
| 20 | + @Resource | ||
| 21 | + private TradeOrderService tradeOrderService; | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + public TradeOrderRespDTO getOrder(Long id) { | ||
| 25 | + return TradeOrderConvert.INSTANCE.convert(tradeOrderService.getOrder(id)); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/api/package-info.java
0 → 100644
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/DeliveryExpressTemplateController.java
| @@ -70,14 +70,14 @@ public class DeliveryExpressTemplateController { | @@ -70,14 +70,14 @@ public class DeliveryExpressTemplateController { | ||
| 70 | return success(DeliveryExpressTemplateConvert.INSTANCE.convertList(list)); | 70 | return success(DeliveryExpressTemplateConvert.INSTANCE.convertList(list)); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | - // TODO @puhui999:DeliveryExpressTemplateRespVO 搞个 simple 的哈 | 73 | + // TODO @puhui999:DeliveryExpressTemplateRespVO 搞个 simple 的哈 fix |
| 74 | @GetMapping("/list-all-simple") | 74 | @GetMapping("/list-all-simple") |
| 75 | @Operation(summary = "获取快递模版精简信息列表", description = "主要用于前端的下拉选项") | 75 | @Operation(summary = "获取快递模版精简信息列表", description = "主要用于前端的下拉选项") |
| 76 | - public CommonResult<List<DeliveryExpressTemplateRespVO>> getSimpleTemplateList() { | 76 | + public CommonResult<List<DeliveryExpressTemplateSimpleRespVO>> getSimpleTemplateList() { |
| 77 | // 获取运费模版列表,只要开启状态的 | 77 | // 获取运费模版列表,只要开启状态的 |
| 78 | List<DeliveryExpressTemplateDO> list = deliveryExpressTemplateService.getDeliveryExpressTemplateList(); | 78 | List<DeliveryExpressTemplateDO> list = deliveryExpressTemplateService.getDeliveryExpressTemplateList(); |
| 79 | // 排序后,返回给前端 | 79 | // 排序后,返回给前端 |
| 80 | - return success(DeliveryExpressTemplateConvert.INSTANCE.convertList(list)); | 80 | + return success(DeliveryExpressTemplateConvert.INSTANCE.convertList1(list)); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | @GetMapping("/page") | 83 | @GetMapping("/page") |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/expresstemplate/DeliveryExpressTemplateSimpleRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.AllArgsConstructor; | ||
| 5 | +import lombok.Data; | ||
| 6 | +import lombok.NoArgsConstructor; | ||
| 7 | + | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - 模版精简信息 Response VO") | ||
| 10 | +@Data | ||
| 11 | +@NoArgsConstructor | ||
| 12 | +@AllArgsConstructor | ||
| 13 | +public class DeliveryExpressTemplateSimpleRespVO { | ||
| 14 | + | ||
| 15 | + @Schema(description = "模版编号", required = true, example = "1024") | ||
| 16 | + private Long id; | ||
| 17 | + | ||
| 18 | + @Schema(description = "模板名称", required = true, example = "测试模版") | ||
| 19 | + private String name; | ||
| 20 | + | ||
| 21 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/delivery/DeliveryExpressTemplateConvert.java
| @@ -28,11 +28,13 @@ public interface DeliveryExpressTemplateConvert { | @@ -28,11 +28,13 @@ public interface DeliveryExpressTemplateConvert { | ||
| 28 | 28 | ||
| 29 | List<DeliveryExpressTemplateRespVO> convertList(List<DeliveryExpressTemplateDO> list); | 29 | List<DeliveryExpressTemplateRespVO> convertList(List<DeliveryExpressTemplateDO> list); |
| 30 | 30 | ||
| 31 | + List<DeliveryExpressTemplateSimpleRespVO> convertList1(List<DeliveryExpressTemplateDO> list); | ||
| 32 | + | ||
| 31 | PageResult<DeliveryExpressTemplateRespVO> convertPage(PageResult<DeliveryExpressTemplateDO> page); | 33 | PageResult<DeliveryExpressTemplateRespVO> convertPage(PageResult<DeliveryExpressTemplateDO> page); |
| 32 | 34 | ||
| 33 | default DeliveryExpressTemplateDetailRespVO convert(DeliveryExpressTemplateDO bean, | 35 | default DeliveryExpressTemplateDetailRespVO convert(DeliveryExpressTemplateDO bean, |
| 34 | List<DeliveryExpressTemplateChargeDO> chargeList, | 36 | List<DeliveryExpressTemplateChargeDO> chargeList, |
| 35 | - List<DeliveryExpressTemplateFreeDO> freeList){ | 37 | + List<DeliveryExpressTemplateFreeDO> freeList) { |
| 36 | DeliveryExpressTemplateDetailRespVO respVO = convert2(bean); | 38 | DeliveryExpressTemplateDetailRespVO respVO = convert2(bean); |
| 37 | respVO.setTemplateCharge(convertTemplateChargeList(chargeList)); | 39 | respVO.setTemplateCharge(convertTemplateChargeList(chargeList)); |
| 38 | respVO.setTemplateFree(convertTemplateFreeList(freeList)); | 40 | respVO.setTemplateFree(convertTemplateFreeList(freeList)); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
| @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; | ||
| 11 | import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; | 11 | import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO; |
| 12 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; | 12 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 13 | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; | 13 | import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO; |
| 14 | +import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO; | ||
| 14 | import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; | 15 | import cn.iocoder.yudao.module.trade.controller.admin.base.member.user.MemberUserRespVO; |
| 15 | import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; | 16 | import cn.iocoder.yudao.module.trade.controller.admin.base.product.property.ProductPropertyValueDetailRespVO; |
| 16 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO; | 17 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDetailRespVO; |
| @@ -62,6 +63,8 @@ public interface TradeOrderConvert { | @@ -62,6 +63,8 @@ public interface TradeOrderConvert { | ||
| 62 | TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, | 63 | TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO, |
| 63 | TradePriceCalculateRespBO calculateRespBO, AddressRespDTO address); | 64 | TradePriceCalculateRespBO calculateRespBO, AddressRespDTO address); |
| 64 | 65 | ||
| 66 | + TradeOrderRespDTO convert(TradeOrderDO orderDO); | ||
| 67 | + | ||
| 65 | default List<TradeOrderItemDO> convertList(TradeOrderDO tradeOrderDO, TradePriceCalculateRespBO calculateRespBO) { | 68 | default List<TradeOrderItemDO> convertList(TradeOrderDO tradeOrderDO, TradePriceCalculateRespBO calculateRespBO) { |
| 66 | return CollectionUtils.convertList(calculateRespBO.getItems(), item -> { | 69 | return CollectionUtils.convertList(calculateRespBO.getItems(), item -> { |
| 67 | TradeOrderItemDO orderItem = convert(item); | 70 | TradeOrderItemDO orderItem = convert(item); |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateService.java
| @@ -6,10 +6,12 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplat | @@ -6,10 +6,12 @@ import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplat | ||
| 6 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO; | 6 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplatePageReqVO; |
| 7 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateUpdateReqVO; | 7 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.DeliveryExpressTemplateUpdateReqVO; |
| 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; | 8 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; |
| 9 | +import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO; | ||
| 9 | 10 | ||
| 10 | import javax.validation.Valid; | 11 | import javax.validation.Valid; |
| 11 | import java.util.Collection; | 12 | import java.util.Collection; |
| 12 | import java.util.List; | 13 | import java.util.List; |
| 14 | +import java.util.Map; | ||
| 13 | 15 | ||
| 14 | /** | 16 | /** |
| 15 | * 快递运费模板 Service 接口 | 17 | * 快递运费模板 Service 接口 |
| @@ -73,11 +75,21 @@ public interface DeliveryExpressTemplateService { | @@ -73,11 +75,21 @@ public interface DeliveryExpressTemplateService { | ||
| 73 | 75 | ||
| 74 | /** | 76 | /** |
| 75 | * 校验快递运费模板 | 77 | * 校验快递运费模板 |
| 76 | - * | 78 | + * <p> |
| 77 | * 如果校验不通过,抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 异常 | 79 | * 如果校验不通过,抛出 {@link cn.iocoder.yudao.framework.common.exception.ServiceException} 异常 |
| 78 | * | 80 | * |
| 79 | * @param templateId 模板编号 | 81 | * @param templateId 模板编号 |
| 80 | * @return 快递运费模板 | 82 | * @return 快递运费模板 |
| 81 | */ | 83 | */ |
| 82 | DeliveryExpressTemplateDO validateDeliveryExpressTemplate(Long templateId); | 84 | DeliveryExpressTemplateDO validateDeliveryExpressTemplate(Long templateId); |
| 85 | + | ||
| 86 | + /** | ||
| 87 | + * 基于指定的 SPU 编号数组和收件人地址区域编号. 获取匹配运费模板 | ||
| 88 | + * | ||
| 89 | + * @param ids SPU 编号列表 | ||
| 90 | + * @param areaId 区域编号 | ||
| 91 | + * @return Map (spuId -> 运费模板设置) | ||
| 92 | + */ | ||
| 93 | + Map<Long, SpuDeliveryExpressTemplateRespBO> getExpressTemplateBySpuIdsAndArea(Collection<Long> ids, Integer areaId); | ||
| 94 | + | ||
| 83 | } | 95 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/DeliveryExpressTemplateServiceImpl.java
| 1 | package cn.iocoder.yudao.module.trade.service.delivery; | 1 | package cn.iocoder.yudao.module.trade.service.delivery; |
| 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.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; | ||
| 7 | +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO; | ||
| 5 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*; | 8 | import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*; |
| 6 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; | 9 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; |
| 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; | 10 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; |
| @@ -9,6 +12,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemp | @@ -9,6 +12,7 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemp | ||
| 9 | import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper; | 12 | import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper; |
| 10 | import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper; | 13 | import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper; |
| 11 | import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateMapper; | 14 | import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateMapper; |
| 15 | +import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO; | ||
| 12 | import org.springframework.stereotype.Service; | 16 | import org.springframework.stereotype.Service; |
| 13 | import org.springframework.transaction.annotation.Transactional; | 17 | import org.springframework.transaction.annotation.Transactional; |
| 14 | import org.springframework.validation.annotation.Validated; | 18 | import org.springframework.validation.annotation.Validated; |
| @@ -17,6 +21,7 @@ import javax.annotation.Resource; | @@ -17,6 +21,7 @@ import javax.annotation.Resource; | ||
| 17 | import java.util.*; | 21 | import java.util.*; |
| 18 | 22 | ||
| 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 23 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 24 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; | ||
| 20 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | 25 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 21 | import static cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressTemplateConvert.INSTANCE; | 26 | import static cn.iocoder.yudao.module.trade.convert.delivery.DeliveryExpressTemplateConvert.INSTANCE; |
| 22 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_TEMPLATE_NAME_DUPLICATE; | 27 | import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.EXPRESS_TEMPLATE_NAME_DUPLICATE; |
| @@ -37,6 +42,8 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla | @@ -37,6 +42,8 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla | ||
| 37 | private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper; | 42 | private DeliveryExpressTemplateChargeMapper expressTemplateChargeMapper; |
| 38 | @Resource | 43 | @Resource |
| 39 | private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper; | 44 | private DeliveryExpressTemplateFreeMapper expressTemplateFreeMapper; |
| 45 | + @Resource | ||
| 46 | + private ProductSpuApi productSpuApi; | ||
| 40 | 47 | ||
| 41 | @Override | 48 | @Override |
| 42 | @Transactional(rollbackFor = Exception.class) | 49 | @Transactional(rollbackFor = Exception.class) |
| @@ -216,4 +223,50 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla | @@ -216,4 +223,50 @@ public class DeliveryExpressTemplateServiceImpl implements DeliveryExpressTempla | ||
| 216 | return template; | 223 | return template; |
| 217 | } | 224 | } |
| 218 | 225 | ||
| 226 | + @Override | ||
| 227 | + public Map<Long, SpuDeliveryExpressTemplateRespBO> getExpressTemplateBySpuIdsAndArea(Collection<Long> spuIds, Integer areaId) { | ||
| 228 | + Assert.notNull(areaId, "区域编号 {} 不能为空", areaId); | ||
| 229 | + List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds); | ||
| 230 | + if (CollUtil.isEmpty(spuList)) { | ||
| 231 | + return Collections.emptyMap(); | ||
| 232 | + } | ||
| 233 | + Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getDeliveryTemplateId); | ||
| 234 | + List<DeliveryExpressTemplateDO> templateList = expressTemplateMapper.selectBatchIds(spuMap.keySet()); | ||
| 235 | + Map<Long, SpuDeliveryExpressTemplateRespBO> result = new HashMap<>(templateList.size()); | ||
| 236 | + templateList.forEach(item -> { | ||
| 237 | + if (spuMap.containsKey(item.getId())) { | ||
| 238 | + ProductSpuRespDTO spuDTO = spuMap.get(item.getId()); | ||
| 239 | + SpuDeliveryExpressTemplateRespBO bo = new SpuDeliveryExpressTemplateRespBO() | ||
| 240 | + .setSpuId(spuDTO.getId()).setAreaId(areaId) | ||
| 241 | + .setChargeMode(item.getChargeMode()) | ||
| 242 | + .setTemplateCharge(findMatchExpressTemplateCharge(item.getId(), areaId)) | ||
| 243 | + .setTemplateFree(findMatchExpressTemplateFree(item.getId(), areaId)); | ||
| 244 | + result.put(spuDTO.getId(), bo); | ||
| 245 | + } | ||
| 246 | + }); | ||
| 247 | + return result; | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + private DeliveryExpressTemplateChargeDO findMatchExpressTemplateCharge(Long templateId, Integer areaId) { | ||
| 251 | + List<DeliveryExpressTemplateChargeDO> list = expressTemplateChargeMapper.selectListByTemplateId(templateId); | ||
| 252 | + for (DeliveryExpressTemplateChargeDO item : list) { | ||
| 253 | + // 第一个匹配的返回。 areaId 不能重复 | ||
| 254 | + if (item.getAreaIds().contains(areaId)) { | ||
| 255 | + return item; | ||
| 256 | + } | ||
| 257 | + } | ||
| 258 | + return null; | ||
| 259 | + } | ||
| 260 | + | ||
| 261 | + private DeliveryExpressTemplateFreeDO findMatchExpressTemplateFree(Long templateId, Integer areaId) { | ||
| 262 | + List<DeliveryExpressTemplateFreeDO> list = expressTemplateFreeMapper.selectListByTemplateId(templateId); | ||
| 263 | + for (DeliveryExpressTemplateFreeDO item : list) { | ||
| 264 | + // 第一个匹配的返回。 areaId 不能重复 | ||
| 265 | + if (item.getAreaIds().contains(areaId)) { | ||
| 266 | + return item; | ||
| 267 | + } | ||
| 268 | + } | ||
| 269 | + return null; | ||
| 270 | + } | ||
| 271 | + | ||
| 219 | } | 272 | } |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/delivery/bo/SpuDeliveryExpressTemplateRespBO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.trade.service.delivery.bo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; | ||
| 4 | +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO; | ||
| 5 | +import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; | ||
| 6 | +import lombok.Data; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * SPU 运费模板配置 Resp BO | ||
| 10 | + * | ||
| 11 | + * @author jason | ||
| 12 | + */ | ||
| 13 | +@Data | ||
| 14 | +public class SpuDeliveryExpressTemplateRespBO { | ||
| 15 | + | ||
| 16 | + /** | ||
| 17 | + * 配送计费方式 | ||
| 18 | + * <p> | ||
| 19 | + * 枚举 {@link DeliveryExpressChargeModeEnum} | ||
| 20 | + */ | ||
| 21 | + private Integer chargeMode; | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 运费模板快递运费设置 | ||
| 25 | + */ | ||
| 26 | + private DeliveryExpressTemplateChargeDO templateCharge; | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 运费模板包邮设置 | ||
| 30 | + */ | ||
| 31 | + private DeliveryExpressTemplateFreeDO templateFree; | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * SPU 编号 | ||
| 35 | + * <p> | ||
| 36 | + * 关联 ProductSpuDO 的 id 编号 | ||
| 37 | + */ | ||
| 38 | + private Long spuId; | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 区域编号 | ||
| 42 | + */ | ||
| 43 | + private Integer areaId; | ||
| 44 | + | ||
| 45 | +} |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
| @@ -6,7 +6,9 @@ import cn.hutool.core.util.IdUtil; | @@ -6,7 +6,9 @@ import cn.hutool.core.util.IdUtil; | ||
| 6 | import cn.hutool.core.util.ObjectUtil; | 6 | import cn.hutool.core.util.ObjectUtil; |
| 7 | import cn.hutool.core.util.StrUtil; | 7 | import cn.hutool.core.util.StrUtil; |
| 8 | import cn.iocoder.yudao.framework.common.core.KeyValue; | 8 | import cn.iocoder.yudao.framework.common.core.KeyValue; |
| 9 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 9 | import cn.iocoder.yudao.framework.common.enums.TerminalEnum; | 10 | import cn.iocoder.yudao.framework.common.enums.TerminalEnum; |
| 11 | +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; | ||
| 10 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 12 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 11 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 13 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 12 | import cn.iocoder.yudao.module.member.api.address.AddressApi; | 14 | import cn.iocoder.yudao.module.member.api.address.AddressApi; |
| @@ -21,6 +23,11 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | @@ -21,6 +23,11 @@ import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | ||
| 21 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; | 23 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO; |
| 22 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; | 24 | import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi; |
| 23 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; | 25 | import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO; |
| 26 | +import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; | ||
| 27 | +import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; | ||
| 28 | +import cn.iocoder.yudao.module.system.api.notify.dto.NotifyTemplateReqDTO; | ||
| 29 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | ||
| 30 | +import cn.iocoder.yudao.module.system.enums.notify.NotifyTemplateTypeEnum; | ||
| 24 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; | 31 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; |
| 25 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; | 32 | import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO; |
| 26 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; | 33 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO; |
| @@ -29,6 +36,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle | @@ -29,6 +36,7 @@ import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettle | ||
| 29 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; | 36 | import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderSettlementRespVO; |
| 30 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; | 37 | import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert; |
| 31 | import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; | 38 | import cn.iocoder.yudao.module.trade.dal.dataobject.cart.TradeCartDO; |
| 39 | +import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressDO; | ||
| 32 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; | 40 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO; |
| 33 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; | 41 | import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO; |
| 34 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; | 42 | import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper; |
| @@ -38,6 +46,7 @@ import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | @@ -38,6 +46,7 @@ import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | ||
| 38 | import cn.iocoder.yudao.module.trade.enums.order.*; | 46 | import cn.iocoder.yudao.module.trade.enums.order.*; |
| 39 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; | 47 | import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties; |
| 40 | import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; | 48 | import cn.iocoder.yudao.module.trade.service.cart.TradeCartService; |
| 49 | +import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService; | ||
| 41 | import cn.iocoder.yudao.module.trade.service.price.TradePriceService; | 50 | import cn.iocoder.yudao.module.trade.service.price.TradePriceService; |
| 42 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 51 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 43 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 52 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| @@ -74,6 +83,8 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -74,6 +83,8 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 74 | private TradeCartService tradeCartService; | 83 | private TradeCartService tradeCartService; |
| 75 | @Resource | 84 | @Resource |
| 76 | private TradePriceService tradePriceService; | 85 | private TradePriceService tradePriceService; |
| 86 | + @Resource | ||
| 87 | + private DeliveryExpressService deliveryExpressService; | ||
| 77 | 88 | ||
| 78 | @Resource | 89 | @Resource |
| 79 | private ProductSkuApi productSkuApi; | 90 | private ProductSkuApi productSkuApi; |
| @@ -85,7 +96,10 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -85,7 +96,10 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 85 | private CouponApi couponApi; | 96 | private CouponApi couponApi; |
| 86 | @Resource | 97 | @Resource |
| 87 | private MemberUserApi memberUserApi; | 98 | private MemberUserApi memberUserApi; |
| 88 | - | 99 | + @Resource |
| 100 | + private AdminUserApi adminUserApi; | ||
| 101 | + @Resource | ||
| 102 | + private NotifyMessageSendApi notifyMessageSendApi; | ||
| 89 | @Resource | 103 | @Resource |
| 90 | private TradeOrderProperties tradeOrderProperties; | 104 | private TradeOrderProperties tradeOrderProperties; |
| 91 | 105 | ||
| @@ -123,7 +137,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -123,7 +137,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 123 | /** | 137 | /** |
| 124 | * 计算订单价格 | 138 | * 计算订单价格 |
| 125 | * | 139 | * |
| 126 | - * @param userId 用户编号 | 140 | + * @param userId 用户编号 |
| 127 | * @param settlementReqVO 结算信息 | 141 | * @param settlementReqVO 结算信息 |
| 128 | * @return 订单价格 | 142 | * @return 订单价格 |
| 129 | */ | 143 | */ |
| @@ -162,7 +176,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -162,7 +176,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 162 | /** | 176 | /** |
| 163 | * 校验收件地址是否存在 | 177 | * 校验收件地址是否存在 |
| 164 | * | 178 | * |
| 165 | - * @param userId 用户编号 | 179 | + * @param userId 用户编号 |
| 166 | * @param addressId 收件地址编号 | 180 | * @param addressId 收件地址编号 |
| 167 | * @return 收件地址 | 181 | * @return 收件地址 |
| 168 | */ | 182 | */ |
| @@ -181,7 +195,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -181,7 +195,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 181 | order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); | 195 | order.setStatus(TradeOrderStatusEnum.UNPAID.getStatus()); |
| 182 | order.setType(TradeOrderTypeEnum.NORMAL.getType()); | 196 | order.setType(TradeOrderTypeEnum.NORMAL.getType()); |
| 183 | order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); | 197 | order.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()); |
| 184 | - order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); | 198 | + order.setProductCount(getSumValue(calculateRespBO.getItems(), TradePriceCalculateRespBO.OrderItem::getCount, Integer::sum)); |
| 185 | order.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? | 199 | order.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源? |
| 186 | // 支付信息 | 200 | // 支付信息 |
| 187 | order.setAdjustPrice(0).setPayed(false); | 201 | order.setAdjustPrice(0).setPayed(false); |
| @@ -201,12 +215,12 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -201,12 +215,12 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 201 | 215 | ||
| 202 | /** | 216 | /** |
| 203 | * 执行创建完创建完订单后的逻辑 | 217 | * 执行创建完创建完订单后的逻辑 |
| 204 | - * | 218 | + * <p> |
| 205 | * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等 | 219 | * 例如说:优惠劵的扣减、积分的扣减、支付单的创建等等 |
| 206 | * | 220 | * |
| 207 | - * @param userId 用户编号 | ||
| 208 | - * @param createReqVO 创建订单请求 | ||
| 209 | - * @param tradeOrderDO 交易订单 | 221 | + * @param userId 用户编号 |
| 222 | + * @param createReqVO 创建订单请求 | ||
| 223 | + * @param tradeOrderDO 交易订单 | ||
| 210 | * @param calculateRespBO 订单价格计算结果 | 224 | * @param calculateRespBO 订单价格计算结果 |
| 211 | */ | 225 | */ |
| 212 | private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, | 226 | private void afterCreateTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO, |
| @@ -265,11 +279,11 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -265,11 +279,11 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 265 | 279 | ||
| 266 | /** | 280 | /** |
| 267 | * 校验交易订单满足被支付的条件 | 281 | * 校验交易订单满足被支付的条件 |
| 268 | - * | 282 | + * <p> |
| 269 | * 1. 交易订单未支付 | 283 | * 1. 交易订单未支付 |
| 270 | * 2. 支付单已支付 | 284 | * 2. 支付单已支付 |
| 271 | * | 285 | * |
| 272 | - * @param id 交易订单编号 | 286 | + * @param id 交易订单编号 |
| 273 | * @param payOrderId 支付订单编号 | 287 | * @param payOrderId 支付订单编号 |
| 274 | * @return 交易订单 | 288 | * @return 交易订单 |
| 275 | */ | 289 | */ |
| @@ -324,8 +338,11 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -324,8 +338,11 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 324 | public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) { | 338 | public void deliveryOrder(Long userId, TradeOrderDeliveryReqVO deliveryReqVO) { |
| 325 | // 校验并获得交易订单(可发货) | 339 | // 校验并获得交易订单(可发货) |
| 326 | TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); | 340 | TradeOrderDO order = validateOrderDeliverable(deliveryReqVO.getId()); |
| 327 | - | ||
| 328 | - // TODO 芋艿:logisticsId 校验存在 | 341 | + // TODO 芋艿:logisticsId 校验存在 发货物流公司 fix |
| 342 | + DeliveryExpressDO deliveryExpress = deliveryExpressService.getDeliveryExpress(deliveryReqVO.getLogisticsId()); | ||
| 343 | + if (deliveryExpress == null) { | ||
| 344 | + throw exception(DELIVERY_EXPRESS_NOT_EXISTS); | ||
| 345 | + } | ||
| 329 | 346 | ||
| 330 | // 更新 TradeOrderDO 状态为已发货,等待收货 | 347 | // 更新 TradeOrderDO 状态为已发货,等待收货 |
| 331 | int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), | 348 | int updateCount = tradeOrderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), |
| @@ -338,8 +355,32 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -338,8 +355,32 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 338 | 355 | ||
| 339 | // TODO 芋艿:发送订单变化的消息 | 356 | // TODO 芋艿:发送订单变化的消息 |
| 340 | 357 | ||
| 341 | - // TODO 芋艿:发送站内信 | ||
| 342 | - | 358 | + // TODO 芋艿:发送站内信 fix |
| 359 | + // 1、获取模版编码为 order_delivery 的模版,判断是否存在 存在放回 true | ||
| 360 | + if (!notifyMessageSendApi.validateNotifyTemplate("order_delivery")) { | ||
| 361 | + // 1、1 站内信模版不存在则创建模版 | ||
| 362 | + NotifyTemplateReqDTO templateReqDTO = new NotifyTemplateReqDTO(); | ||
| 363 | + templateReqDTO.setName("订单发货通知模版"); | ||
| 364 | + templateReqDTO.setCode("order_delivery"); | ||
| 365 | + templateReqDTO.setType(NotifyTemplateTypeEnum.NOTIFICATION_MESSAGE.getType()); // 系统消息 | ||
| 366 | + // 获取操作用户 | ||
| 367 | + // AdminUserRespDTO user = adminUserApi.getUser(userId); | ||
| 368 | + // templateReqDTO.setNickname(user.getNickname()); | ||
| 369 | + templateReqDTO.setNickname(UserTypeEnum.ADMIN.getName()); | ||
| 370 | + templateReqDTO.setContent("订单:{orderId}{msg}"); | ||
| 371 | + templateReqDTO.setStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 372 | + notifyMessageSendApi.createNotifyTemplate(templateReqDTO); | ||
| 373 | + } | ||
| 374 | + // 2、构造消息 | ||
| 375 | + Map<String, Object> msgMap = new HashMap<>(); | ||
| 376 | + msgMap.put("orderId", deliveryReqVO.getId()); | ||
| 377 | + msgMap.put("msg", TradeOrderStatusEnum.DELIVERED.getStatus()); | ||
| 378 | + // 2、发送站内信 | ||
| 379 | + notifyMessageSendApi.sendSingleMessageToAdmin( | ||
| 380 | + new NotifySendSingleToUserReqDTO() | ||
| 381 | + .setUserId(userId) | ||
| 382 | + .setTemplateCode("order_delivery") | ||
| 383 | + .setTemplateParams(msgMap)); | ||
| 343 | // TODO 芋艿:OrderLog | 384 | // TODO 芋艿:OrderLog |
| 344 | 385 | ||
| 345 | // TODO 设计:like:是否要单独一个 delivery 发货单表??? | 386 | // TODO 设计:like:是否要单独一个 delivery 发货单表??? |
| @@ -349,7 +390,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -349,7 +390,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 349 | 390 | ||
| 350 | /** | 391 | /** |
| 351 | * 校验交易订单满足被发货的条件 | 392 | * 校验交易订单满足被发货的条件 |
| 352 | - * | 393 | + * <p> |
| 353 | * 1. 交易订单未发货 | 394 | * 1. 交易订单未发货 |
| 354 | * | 395 | * |
| 355 | * @param id 交易订单编号 | 396 | * @param id 交易订单编号 |
| @@ -363,7 +404,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -363,7 +404,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 363 | } | 404 | } |
| 364 | // 校验订单是否是待发货状态 | 405 | // 校验订单是否是待发货状态 |
| 365 | if (!TradeOrderStatusEnum.isUndelivered(order.getStatus()) | 406 | if (!TradeOrderStatusEnum.isUndelivered(order.getStatus()) |
| 366 | - || ObjectUtil.notEqual(order.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus())) { | 407 | + || ObjectUtil.notEqual(order.getDeliveryStatus(), TradeOrderDeliveryStatusEnum.UNDELIVERED.getStatus())) { |
| 367 | throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); | 408 | throw exception(ORDER_DELIVERY_FAIL_STATUS_NOT_UNDELIVERED); |
| 368 | } | 409 | } |
| 369 | return order; | 410 | return order; |
| @@ -397,11 +438,11 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -397,11 +438,11 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 397 | 438 | ||
| 398 | /** | 439 | /** |
| 399 | * 校验交易订单满足可售货的条件 | 440 | * 校验交易订单满足可售货的条件 |
| 400 | - * | 441 | + * <p> |
| 401 | * 1. 交易订单待收货 | 442 | * 1. 交易订单待收货 |
| 402 | * | 443 | * |
| 403 | * @param userId 用户编号 | 444 | * @param userId 用户编号 |
| 404 | - * @param id 交易订单编号 | 445 | + * @param id 交易订单编号 |
| 405 | * @return 交易订单 | 446 | * @return 交易订单 |
| 406 | */ | 447 | */ |
| 407 | private TradeOrderDO validateOrderReceivable(Long userId, Long id) { | 448 | private TradeOrderDO validateOrderReceivable(Long userId, Long id) { |
| @@ -476,7 +517,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | @@ -476,7 +517,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { | ||
| 476 | public void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, Integer refundPrice) { | 517 | public void updateOrderItemAfterSaleStatus(Long id, Integer oldAfterSaleStatus, Integer newAfterSaleStatus, Integer refundPrice) { |
| 477 | // 如果退款成功,则 refundPrice 非空 | 518 | // 如果退款成功,则 refundPrice 非空 |
| 478 | if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()) | 519 | if (Objects.equals(newAfterSaleStatus, TradeOrderItemAfterSaleStatusEnum.SUCCESS.getStatus()) |
| 479 | - && refundPrice == null) { | 520 | + && refundPrice == null) { |
| 480 | throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); | 521 | throw new IllegalArgumentException(StrUtil.format("id({}) 退款成功,退款金额不能为空", id)); |
| 481 | } | 522 | } |
| 482 | 523 |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java
| 1 | package cn.iocoder.yudao.module.trade.service.price.bo; | 1 | package cn.iocoder.yudao.module.trade.service.price.bo; |
| 2 | 2 | ||
| 3 | -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; | ||
| 4 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | 3 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; |
| 5 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; | 4 | import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum; |
| 6 | import lombok.Data; | 5 | import lombok.Data; |
| @@ -54,14 +53,6 @@ public class TradePriceCalculateReqBO { | @@ -54,14 +53,6 @@ public class TradePriceCalculateReqBO { | ||
| 54 | private Integer deliveryType; | 53 | private Integer deliveryType; |
| 55 | 54 | ||
| 56 | /** | 55 | /** |
| 57 | - * 配送模板编号 | ||
| 58 | - * | ||
| 59 | - * 关联 {@link DeliveryExpressTemplateDO#getId()} | ||
| 60 | - */ | ||
| 61 | - // TODO @jason:运费模版,是不是每个 SKU 传入哈 | ||
| 62 | - private Long templateId; | ||
| 63 | - | ||
| 64 | - /** | ||
| 65 | * 商品 SKU 数组 | 56 | * 商品 SKU 数组 |
| 66 | */ | 57 | */ |
| 67 | @NotNull(message = "商品数组不能为空") | 58 | @NotNull(message = "商品数组不能为空") |
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDeliveryPriceCalculator.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; | ||
| 4 | +import cn.hutool.core.lang.Assert; | ||
| 3 | import cn.iocoder.yudao.module.member.api.address.AddressApi; | 5 | import cn.iocoder.yudao.module.member.api.address.AddressApi; |
| 4 | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; | 6 | import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO; |
| 5 | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; | 7 | import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; |
| 6 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; | 8 | import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; |
| 7 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; | 9 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateChargeDO; |
| 8 | -import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateDO; | ||
| 9 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO; | 10 | import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryExpressTemplateFreeDO; |
| 10 | -import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateChargeMapper; | ||
| 11 | -import cn.iocoder.yudao.module.trade.dal.mysql.delivery.DeliveryExpressTemplateFreeMapper; | ||
| 12 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; | 11 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum; |
| 13 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; | 12 | import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum; |
| 14 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService; | 13 | import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressTemplateService; |
| 14 | +import cn.iocoder.yudao.module.trade.service.delivery.bo.SpuDeliveryExpressTemplateRespBO; | ||
| 15 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; | 15 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO; |
| 16 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; | 16 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO; |
| 17 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO.OrderItem; | 17 | import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO.OrderItem; |
| @@ -19,7 +19,6 @@ import org.springframework.core.annotation.Order; | @@ -19,7 +19,6 @@ import org.springframework.core.annotation.Order; | ||
| 19 | import org.springframework.stereotype.Component; | 19 | import org.springframework.stereotype.Component; |
| 20 | 20 | ||
| 21 | import javax.annotation.Resource; | 21 | import javax.annotation.Resource; |
| 22 | -import java.util.HashMap; | ||
| 23 | import java.util.List; | 22 | import java.util.List; |
| 24 | import java.util.Map; | 23 | import java.util.Map; |
| 25 | import java.util.Set; | 24 | import java.util.Set; |
| @@ -39,14 +38,8 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | @@ -39,14 +38,8 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | ||
| 39 | private AddressApi addressApi; | 38 | private AddressApi addressApi; |
| 40 | @Resource | 39 | @Resource |
| 41 | private ProductSkuApi productSkuApi; | 40 | private ProductSkuApi productSkuApi; |
| 42 | - | ||
| 43 | @Resource | 41 | @Resource |
| 44 | private DeliveryExpressTemplateService deliveryExpressTemplateService; | 42 | private DeliveryExpressTemplateService deliveryExpressTemplateService; |
| 45 | - // TODO @jason:走 Service 哈。Mapper 只允许自己的 Service 调用,保护好数据结构; | ||
| 46 | - @Resource | ||
| 47 | - private DeliveryExpressTemplateChargeMapper templateChargeMapper; | ||
| 48 | - @Resource | ||
| 49 | - private DeliveryExpressTemplateFreeMapper templateFreeMapper; | ||
| 50 | 43 | ||
| 51 | @Override | 44 | @Override |
| 52 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { | 45 | public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) { |
| @@ -54,66 +47,45 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | @@ -54,66 +47,45 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | ||
| 54 | if (param.getDeliveryType() == null || DeliveryTypeEnum.PICK_UP.getMode().equals(param.getDeliveryType())) { | 47 | if (param.getDeliveryType() == null || DeliveryTypeEnum.PICK_UP.getMode().equals(param.getDeliveryType())) { |
| 55 | return; | 48 | return; |
| 56 | } | 49 | } |
| 57 | - | ||
| 58 | - if (param.getTemplateId() == null || param.getAddressId() == null) { | 50 | + // 1.2 得到收件地址区域 |
| 51 | + if (param.getAddressId() == null) { | ||
| 59 | return; | 52 | return; |
| 60 | } | 53 | } |
| 61 | - // 1.2 校验运费模板是否存在 | ||
| 62 | - DeliveryExpressTemplateDO template = deliveryExpressTemplateService.validateDeliveryExpressTemplate(param.getTemplateId()); | ||
| 63 | - | ||
| 64 | - // 得到包邮配置 | ||
| 65 | - List<DeliveryExpressTemplateFreeDO> expressTemplateFreeList = templateFreeMapper.selectListByTemplateId(template.getId()); | ||
| 66 | - Map<Integer, DeliveryExpressTemplateFreeDO> areaTemplateFreeMap = new HashMap<>(); | ||
| 67 | - expressTemplateFreeList.forEach(item -> { | ||
| 68 | - for (Integer areaId : item.getAreaIds()) { | ||
| 69 | - // TODO 需要保证 areaId 不能重复 | ||
| 70 | - if (!areaTemplateFreeMap.containsKey(areaId)) { | ||
| 71 | - areaTemplateFreeMap.put(areaId, item); | ||
| 72 | - } | ||
| 73 | - } | ||
| 74 | - }); | ||
| 75 | - // 得到快递运费配置 | ||
| 76 | - List<DeliveryExpressTemplateChargeDO> expressTemplateChargeList = templateChargeMapper.selectListByTemplateId(template.getId()); | ||
| 77 | - Map<Integer, DeliveryExpressTemplateChargeDO> areaTemplateChargeMap = new HashMap<>(); | ||
| 78 | - expressTemplateChargeList.forEach(item -> { | ||
| 79 | - for (Integer areaId : item.getAreaIds()) { | ||
| 80 | - // areaId 不能重复 | ||
| 81 | - if (!areaTemplateChargeMap.containsKey(areaId)) { | ||
| 82 | - areaTemplateChargeMap.put(areaId, item); | ||
| 83 | - } | ||
| 84 | - } | ||
| 85 | - }); | ||
| 86 | - // 得到收件地址区域 | ||
| 87 | AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId()); | 54 | AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId()); |
| 88 | - // 1.3 计算快递费用 | ||
| 89 | - calculateDeliveryPrice(address.getAreaId(), template.getChargeMode(), | ||
| 90 | - areaTemplateFreeMap, areaTemplateChargeMap, result); | 55 | + Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId()); |
| 56 | + | ||
| 57 | + //1.3 过滤出已选中的商品SKU | ||
| 58 | + List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected); | ||
| 59 | + | ||
| 60 | + Map<Long, SpuDeliveryExpressTemplateRespBO> spuExpressTemplateMap = | ||
| 61 | + deliveryExpressTemplateService.getExpressTemplateBySpuIdsAndArea( | ||
| 62 | + convertSet(selectedItem, OrderItem::getSpuId), address.getAreaId()); | ||
| 63 | + | ||
| 64 | + // 1.4 计算配送费用 | ||
| 65 | + if (CollUtil.isNotEmpty(spuExpressTemplateMap)) { | ||
| 66 | + calculateDeliveryPrice(selectedItem, spuExpressTemplateMap, result); | ||
| 67 | + } | ||
| 68 | + | ||
| 91 | } | 69 | } |
| 92 | 70 | ||
| 93 | - /** | ||
| 94 | - * 校验订单是否满足包邮条件 | ||
| 95 | - * | ||
| 96 | - * @param receiverAreaId 收件人地区的区域编号 | ||
| 97 | - * @param chargeMode 配送计费方式 | ||
| 98 | - * @param areaTemplateFreeMap 运费模板包邮区域设置 Map | ||
| 99 | - * @param areaTemplateChargeMap 运费模板快递费用设置 Map | ||
| 100 | - */ | ||
| 101 | - private void calculateDeliveryPrice(Integer receiverAreaId, | ||
| 102 | - Integer chargeMode, | ||
| 103 | - Map<Integer, DeliveryExpressTemplateFreeDO> areaTemplateFreeMap, | ||
| 104 | - Map<Integer, DeliveryExpressTemplateChargeDO> areaTemplateChargeMap, | 71 | + private void calculateDeliveryPrice(List<OrderItem> selectedSkus, |
| 72 | + Map<Long, SpuDeliveryExpressTemplateRespBO> spuExpressTemplateMap, | ||
| 105 | TradePriceCalculateRespBO result) { | 73 | TradePriceCalculateRespBO result) { |
| 106 | - // 过滤出已选中的商品SKU | ||
| 107 | - List<OrderItem> selectedItem = filterList(result.getItems(), OrderItem::getSelected); | ||
| 108 | - Set<Long> skuIds = convertSet(selectedItem, OrderItem::getSkuId); | 74 | + Set<Long> skuIds = convertSet(selectedSkus, OrderItem::getSkuId); |
| 109 | // 得到SKU 详情。得到 重量体积 | 75 | // 得到SKU 详情。得到 重量体积 |
| 110 | Map<Long, ProductSkuRespDTO> skuRespMap = convertMap(productSkuApi.getSkuList(skuIds), ProductSkuRespDTO::getId); | 76 | Map<Long, ProductSkuRespDTO> skuRespMap = convertMap(productSkuApi.getSkuList(skuIds), ProductSkuRespDTO::getId); |
| 111 | - // 一个 spuId 可能对应多条订单商品 SKU | ||
| 112 | - // TODO @jason:得确认下,按照 sku 算,还是 spu 算; | ||
| 113 | - Map<Long, List<OrderItem>> spuIdItemMap = convertMultiMap(selectedItem, OrderItem::getSpuId); | 77 | + // 按spu 来计算商品的运费 一个 spuId 可能对应多条订单商品 SKU, |
| 78 | + Map<Long, List<OrderItem>> spuIdItemMap = convertMultiMap(selectedSkus, OrderItem::getSpuId); | ||
| 79 | + | ||
| 114 | // 依次计算每个 SPU 的快递运费 | 80 | // 依次计算每个 SPU 的快递运费 |
| 115 | for (Map.Entry<Long, List<OrderItem>> entry : spuIdItemMap.entrySet()) { | 81 | for (Map.Entry<Long, List<OrderItem>> entry : spuIdItemMap.entrySet()) { |
| 82 | + Long spuId = entry.getKey(); | ||
| 116 | List<OrderItem> orderItems = entry.getValue(); | 83 | List<OrderItem> orderItems = entry.getValue(); |
| 84 | + SpuDeliveryExpressTemplateRespBO templateBO = spuExpressTemplateMap.get(spuId); | ||
| 85 | + if (templateBO == null) { | ||
| 86 | + // 记录错误日志 | ||
| 87 | + continue; | ||
| 88 | + } | ||
| 117 | // 总件数, 总金额, 总重量, 总体积 | 89 | // 总件数, 总金额, 总重量, 总体积 |
| 118 | int totalCount = 0; | 90 | int totalCount = 0; |
| 119 | int totalPrice = 0; | 91 | int totalPrice = 0; |
| @@ -121,51 +93,67 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | @@ -121,51 +93,67 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | ||
| 121 | double totalVolume = 0; | 93 | double totalVolume = 0; |
| 122 | for (OrderItem orderItem : orderItems) { | 94 | for (OrderItem orderItem : orderItems) { |
| 123 | totalCount += orderItem.getCount(); | 95 | totalCount += orderItem.getCount(); |
| 124 | - totalPrice += orderItem.getPrice(); // TODO jason:应该按照 payPrice? | 96 | + totalPrice += orderItem.getPayPrice(); // 先按应付总金额来算,后面确认一下 |
| 125 | ProductSkuRespDTO skuResp = skuRespMap.get(orderItem.getSkuId()); | 97 | ProductSkuRespDTO skuResp = skuRespMap.get(orderItem.getSkuId()); |
| 126 | if (skuResp != null) { | 98 | if (skuResp != null) { |
| 127 | - totalWeight = totalWeight + skuResp.getWeight(); // TODO @jason:* 数量 | ||
| 128 | - totalVolume = totalVolume + skuResp.getVolume(); | 99 | + totalWeight = totalWeight + skuResp.getWeight() * orderItem.getCount(); |
| 100 | + totalVolume = totalVolume + skuResp.getVolume() * orderItem.getCount(); | ||
| 129 | } | 101 | } |
| 130 | } | 102 | } |
| 131 | // 优先判断是否包邮. 如果包邮不计算快递运费 | 103 | // 优先判断是否包邮. 如果包邮不计算快递运费 |
| 132 | - if (areaTemplateFreeMap.containsKey(receiverAreaId) && | ||
| 133 | - checkExpressFree(chargeMode, totalCount, totalWeight, | ||
| 134 | - totalVolume, totalPrice, areaTemplateFreeMap.get(receiverAreaId))) { | 104 | + if (checkExpressFree(templateBO.getChargeMode(), totalCount, totalWeight, |
| 105 | + totalVolume, totalPrice, templateBO.getTemplateFree())) { | ||
| 135 | continue; | 106 | continue; |
| 136 | } | 107 | } |
| 137 | - // 计算快递运费 | ||
| 138 | - // TODO @jason:貌似也可以抽成 checkExpressFree 类似方法 | ||
| 139 | - if (areaTemplateChargeMap.containsKey(receiverAreaId)) { | ||
| 140 | - DeliveryExpressTemplateChargeDO templateCharge = areaTemplateChargeMap.get(receiverAreaId); | ||
| 141 | - DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode); | ||
| 142 | - switch (chargeModeEnum) { | ||
| 143 | - case PIECE: { | ||
| 144 | - calculateExpressFeeBySpu(totalCount, templateCharge, orderItems); | ||
| 145 | - break; | ||
| 146 | - } | ||
| 147 | - case WEIGHT: { | ||
| 148 | - calculateExpressFeeBySpu(totalWeight, templateCharge, orderItems); | ||
| 149 | - break; | ||
| 150 | - } | ||
| 151 | - case VOLUME: { | ||
| 152 | - calculateExpressFeeBySpu(totalVolume, templateCharge, orderItems); | ||
| 153 | - break; | ||
| 154 | - } | ||
| 155 | - } | 108 | + if (templateBO.getTemplateCharge() == null) { |
| 109 | + continue; | ||
| 156 | } | 110 | } |
| 111 | + // 计算快递运费 | ||
| 112 | + calculateExpressFeeByChargeMode(totalCount, totalWeight, totalVolume, | ||
| 113 | + templateBO.getChargeMode(), templateBO.getTemplateCharge(), orderItems); | ||
| 114 | + | ||
| 157 | } | 115 | } |
| 158 | TradePriceCalculatorHelper.recountAllPrice(result); | 116 | TradePriceCalculatorHelper.recountAllPrice(result); |
| 159 | } | 117 | } |
| 160 | 118 | ||
| 161 | /** | 119 | /** |
| 162 | - * 按 spu 来计算快递费用 | 120 | + * 按配送方式来计算运费 |
| 121 | + * | ||
| 122 | + * @param totalCount 总件数 | ||
| 123 | + * @param totalWeight 总重量 | ||
| 124 | + * @param totalVolume 总体积 | ||
| 125 | + * @param chargeMode 配送计费方式 | ||
| 126 | + * @param templateCharge 快递运费配置 | ||
| 127 | + * @param orderItems SKU 商品项目 | ||
| 128 | + */ | ||
| 129 | + private void calculateExpressFeeByChargeMode(double totalCount, double totalWeight, double totalVolume, | ||
| 130 | + int chargeMode, DeliveryExpressTemplateChargeDO templateCharge, | ||
| 131 | + List<OrderItem> orderItems) { | ||
| 132 | + DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode); | ||
| 133 | + switch (chargeModeEnum) { | ||
| 134 | + case PIECE: { | ||
| 135 | + calculateExpressFee(totalCount, templateCharge, orderItems); | ||
| 136 | + break; | ||
| 137 | + } | ||
| 138 | + case WEIGHT: { | ||
| 139 | + calculateExpressFee(totalWeight, templateCharge, orderItems); | ||
| 140 | + break; | ||
| 141 | + } | ||
| 142 | + case VOLUME: { | ||
| 143 | + calculateExpressFee(totalVolume, templateCharge, orderItems); | ||
| 144 | + break; | ||
| 145 | + } | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + /** | ||
| 150 | + * 计算 SKU 商品快递费用 | ||
| 163 | * | 151 | * |
| 164 | * @param total 总件数/总重量/总体积 | 152 | * @param total 总件数/总重量/总体积 |
| 165 | * @param templateCharge 快递运费配置 | 153 | * @param templateCharge 快递运费配置 |
| 166 | * @param orderItems SKU 商品项目 | 154 | * @param orderItems SKU 商品项目 |
| 167 | */ | 155 | */ |
| 168 | - private void calculateExpressFeeBySpu(double total, DeliveryExpressTemplateChargeDO templateCharge, List<OrderItem> orderItems) { | 156 | + private void calculateExpressFee(double total, DeliveryExpressTemplateChargeDO templateCharge, List<OrderItem> orderItems) { |
| 169 | int deliveryPrice; | 157 | int deliveryPrice; |
| 170 | if (total <= templateCharge.getStartCount()) { | 158 | if (total <= templateCharge.getStartCount()) { |
| 171 | deliveryPrice = templateCharge.getStartPrice(); | 159 | deliveryPrice = templateCharge.getStartPrice(); |
| @@ -176,8 +164,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | @@ -176,8 +164,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | ||
| 176 | int extraPrice = templateCharge.getExtraPrice() * extraNum; | 164 | int extraPrice = templateCharge.getExtraPrice() * extraNum; |
| 177 | deliveryPrice = templateCharge.getStartPrice() + extraPrice; | 165 | deliveryPrice = templateCharge.getStartPrice() + extraPrice; |
| 178 | } | 166 | } |
| 179 | - // TODO @芋艿 分摊快递费用到 SKU. 是不是搞复杂了; | ||
| 180 | - // TODO @jason:因为退费的时候,可能按照 SKU 考虑退费金额 | 167 | + // 分摊快递费用到 SKU. 退费的时候,可能按照 SKU 考虑退费金额 |
| 181 | divideDeliveryPrice(deliveryPrice, orderItems); | 168 | divideDeliveryPrice(deliveryPrice, orderItems); |
| 182 | } | 169 | } |
| 183 | 170 | ||
| @@ -207,6 +194,9 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | @@ -207,6 +194,9 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator { | ||
| 207 | */ | 194 | */ |
| 208 | private boolean checkExpressFree(Integer chargeMode, int totalCount, double totalWeight, | 195 | private boolean checkExpressFree(Integer chargeMode, int totalCount, double totalWeight, |
| 209 | double totalVolume, int totalPrice, DeliveryExpressTemplateFreeDO templateFree) { | 196 | double totalVolume, int totalPrice, DeliveryExpressTemplateFreeDO templateFree) { |
| 197 | + if (templateFree == null) { | ||
| 198 | + return false; | ||
| 199 | + } | ||
| 210 | DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode); | 200 | DeliveryExpressChargeModeEnum chargeModeEnum = DeliveryExpressChargeModeEnum.valueOf(chargeMode); |
| 211 | switch (chargeModeEnum) { | 201 | switch (chargeModeEnum) { |
| 212 | case PIECE: | 202 | case PIECE: |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/notify/NotifyMessageSendApi.java
| 1 | package cn.iocoder.yudao.module.system.api.notify; | 1 | package cn.iocoder.yudao.module.system.api.notify; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; | 3 | import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; |
| 4 | +import cn.iocoder.yudao.module.system.api.notify.dto.NotifyTemplateReqDTO; | ||
| 4 | 5 | ||
| 5 | import javax.validation.Valid; | 6 | import javax.validation.Valid; |
| 6 | 7 | ||
| @@ -27,4 +28,8 @@ public interface NotifyMessageSendApi { | @@ -27,4 +28,8 @@ public interface NotifyMessageSendApi { | ||
| 27 | */ | 28 | */ |
| 28 | Long sendSingleMessageToMember(@Valid NotifySendSingleToUserReqDTO reqDTO); | 29 | Long sendSingleMessageToMember(@Valid NotifySendSingleToUserReqDTO reqDTO); |
| 29 | 30 | ||
| 31 | + | ||
| 32 | + boolean validateNotifyTemplate(String orderDelivery); | ||
| 33 | + | ||
| 34 | + void createNotifyTemplate(NotifyTemplateReqDTO templateReqDTO); | ||
| 30 | } | 35 | } |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/notify/dto/NotifyTemplateReqDTO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.api.notify.dto; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotEmpty; | ||
| 8 | +import javax.validation.constraints.NotNull; | ||
| 9 | + | ||
| 10 | +@Data | ||
| 11 | +public class NotifyTemplateReqDTO { | ||
| 12 | + | ||
| 13 | + @NotEmpty(message = "模版名称不能为空") | ||
| 14 | + private String name; | ||
| 15 | + | ||
| 16 | + @NotNull(message = "模版编码不能为空") | ||
| 17 | + private String code; | ||
| 18 | + | ||
| 19 | + @NotNull(message = "模版类型不能为空") | ||
| 20 | + private Integer type; | ||
| 21 | + | ||
| 22 | + @NotEmpty(message = "发送人名称不能为空") | ||
| 23 | + private String nickname; | ||
| 24 | + | ||
| 25 | + @NotEmpty(message = "模版内容不能为空") | ||
| 26 | + private String content; | ||
| 27 | + | ||
| 28 | + @NotNull(message = "状态不能为空") | ||
| 29 | + @InEnum(value = CommonStatusEnum.class, message = "状态必须是 {value}") | ||
| 30 | + private Integer status; | ||
| 31 | + | ||
| 32 | + private String remark; | ||
| 33 | + | ||
| 34 | +} |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/notify/NotifyTemplateTypeEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.enums.notify; | ||
| 2 | + | ||
| 3 | +import lombok.AllArgsConstructor; | ||
| 4 | +import lombok.Getter; | ||
| 5 | + | ||
| 6 | +/** | ||
| 7 | + * 通知模板类型枚举 | ||
| 8 | + * | ||
| 9 | + * @author HUIHUI | ||
| 10 | + */ | ||
| 11 | +@Getter | ||
| 12 | +@AllArgsConstructor | ||
| 13 | +public enum NotifyTemplateTypeEnum { | ||
| 14 | + | ||
| 15 | + /** | ||
| 16 | + * 系统消息 | ||
| 17 | + */ | ||
| 18 | + SYSTEM_MESSAGE(2), | ||
| 19 | + /** | ||
| 20 | + * 通知消息 | ||
| 21 | + */ | ||
| 22 | + NOTIFICATION_MESSAGE(1); | ||
| 23 | + | ||
| 24 | + private final Integer type; | ||
| 25 | + | ||
| 26 | +} |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/notify/NotifyMessageSendApiImpl.java
| 1 | package cn.iocoder.yudao.module.system.api.notify; | 1 | package cn.iocoder.yudao.module.system.api.notify; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; | 3 | import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; |
| 4 | -import cn.iocoder.yudao.module.system.service.notify.NotifyMessageService; | 4 | +import cn.iocoder.yudao.module.system.api.notify.dto.NotifyTemplateReqDTO; |
| 5 | import cn.iocoder.yudao.module.system.service.notify.NotifySendService; | 5 | import cn.iocoder.yudao.module.system.service.notify.NotifySendService; |
| 6 | import org.springframework.stereotype.Service; | 6 | import org.springframework.stereotype.Service; |
| 7 | 7 | ||
| @@ -30,4 +30,14 @@ public class NotifyMessageSendApiImpl implements NotifyMessageSendApi { | @@ -30,4 +30,14 @@ public class NotifyMessageSendApiImpl implements NotifyMessageSendApi { | ||
| 30 | reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); | 30 | reqDTO.getTemplateCode(), reqDTO.getTemplateParams()); |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | + @Override | ||
| 34 | + public boolean validateNotifyTemplate(String orderDelivery) { | ||
| 35 | + return false; | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | + @Override | ||
| 39 | + public void createNotifyTemplate(NotifyTemplateReqDTO templateReqDTO) { | ||
| 40 | + | ||
| 41 | + } | ||
| 42 | + | ||
| 33 | } | 43 | } |