mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-09-19 03:25:06 +08:00
Merge branch 'feature/mall_product' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/mall_product_org
This commit is contained in:
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.product.api.comment.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -15,6 +16,7 @@ public class ProductCommentCreateReqDTO {
|
||||
/**
|
||||
* 商品 SKU 编号
|
||||
*/
|
||||
@NotNull(message = "商品 SKU 编号不能为空")
|
||||
private Long skuId;
|
||||
/**
|
||||
* 订单编号
|
||||
@@ -25,21 +27,20 @@ public class ProductCommentCreateReqDTO {
|
||||
*/
|
||||
private Long orderItemId;
|
||||
|
||||
/**
|
||||
* 评分星级 1-5 分
|
||||
*/
|
||||
private Integer scores;
|
||||
/**
|
||||
* 描述星级 1-5 分
|
||||
*/
|
||||
@NotNull(message = "描述星级不能为空")
|
||||
private Integer descriptionScores;
|
||||
/**
|
||||
* 服务星级 1-5 分
|
||||
*/
|
||||
@NotNull(message = "服务星级不能为空")
|
||||
private Integer benefitScores;
|
||||
/**
|
||||
* 评论内容
|
||||
*/
|
||||
@NotNull(message = "评论内容不能为空")
|
||||
private String content;
|
||||
/**
|
||||
* 评论图片地址数组,以逗号分隔最多上传 9 张
|
||||
@@ -49,11 +50,12 @@ public class ProductCommentCreateReqDTO {
|
||||
/**
|
||||
* 是否匿名
|
||||
*/
|
||||
@NotNull(message = "是否匿名不能为空")
|
||||
private Boolean anonymous;
|
||||
/**
|
||||
* 评价人
|
||||
*/
|
||||
@NotNull(message = "评价人不能为空")
|
||||
private Long userId;
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,23 +0,0 @@
|
||||
package cn.iocoder.yudao.module.product.api.property;
|
||||
|
||||
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品属性值 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface ProductPropertyValueApi {
|
||||
|
||||
/**
|
||||
* 根据编号数组,获得属性值列表
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 属性值明细列表
|
||||
*/
|
||||
List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids);
|
||||
|
||||
}
|
@@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.product.api.spu.dto;
|
||||
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// TODO @LeeYan9: ProductSpuRespDTO
|
||||
/**
|
||||
* 商品 SPU 信息 Response DTO
|
||||
@@ -26,55 +24,22 @@ public class ProductSpuRespDTO {
|
||||
* 商品名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 关键字
|
||||
*/
|
||||
private String keyword;
|
||||
/**
|
||||
* 单位
|
||||
*
|
||||
* 对应 product_unit 数据字典
|
||||
*/
|
||||
private Integer unit;
|
||||
/**
|
||||
* 商品简介
|
||||
*/
|
||||
private String introduction;
|
||||
/**
|
||||
* 商品详情
|
||||
*/
|
||||
private String description;
|
||||
// TODO @芋艿:是不是要删除
|
||||
/**
|
||||
* 商品条码(一维码)
|
||||
*/
|
||||
private String barCode;
|
||||
|
||||
/**
|
||||
* 商品分类编号
|
||||
*/
|
||||
private Long categoryId;
|
||||
/**
|
||||
* 商品品牌编号
|
||||
*/
|
||||
private Long brandId;
|
||||
/**
|
||||
* 商品封面图
|
||||
*/
|
||||
private String picUrl;
|
||||
/**
|
||||
* 商品轮播图
|
||||
*/
|
||||
private List<String> sliderPicUrls;
|
||||
/**
|
||||
* 商品视频
|
||||
*/
|
||||
private String videoUrl;
|
||||
|
||||
/**
|
||||
* 排序字段
|
||||
*/
|
||||
private Integer sort;
|
||||
/**
|
||||
* 商品状态
|
||||
* <p>
|
||||
@@ -124,22 +89,6 @@ public class ProductSpuRespDTO {
|
||||
*/
|
||||
private Integer giveIntegral;
|
||||
|
||||
// ========== 统计相关字段 =========
|
||||
|
||||
/**
|
||||
* 商品销量
|
||||
*/
|
||||
private Integer salesCount;
|
||||
/**
|
||||
* 虚拟销量
|
||||
*/
|
||||
private Integer virtualSalesCount;
|
||||
/**
|
||||
* 商品点击量
|
||||
*/
|
||||
private Integer clickCount;
|
||||
|
||||
|
||||
// ========== 分销相关字段 =========
|
||||
|
||||
/**
|
||||
|
@@ -1,38 +0,0 @@
|
||||
package cn.iocoder.yudao.module.product.enums.group;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 商品分组的样式枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ProductGroupStyleEnum implements IntArrayValuable {
|
||||
|
||||
ONE(1, "每列一个"),
|
||||
TWO(2, "每列两个"),
|
||||
THREE(2, "每列三个"),;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductGroupStyleEnum::getStyle).toArray();
|
||||
|
||||
/**
|
||||
* 列表样式
|
||||
*/
|
||||
private final Integer style;
|
||||
/**
|
||||
* 状态名
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public int[] array() {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
package cn.iocoder.yudao.module.product.api.property;
|
||||
|
||||
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
|
||||
import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;
|
||||
import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品属性值 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class ProductPropertyValueApiImpl implements ProductPropertyValueApi {
|
||||
|
||||
@Resource
|
||||
private ProductPropertyValueService productPropertyValueService;
|
||||
|
||||
@Override
|
||||
public List<ProductPropertyValueDetailRespDTO> getPropertyValueDetailList(Collection<Long> ids) {
|
||||
return ProductPropertyValueConvert.INSTANCE.convertList02(
|
||||
productPropertyValueService.getPropertyValueDetailList(ids));
|
||||
}
|
||||
|
||||
}
|
@@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.product.api.sku;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuUpdateStockReqDTO;
|
||||
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
|
||||
@@ -11,7 +10,6 @@ import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -35,18 +33,12 @@ public class ProductSkuApiImpl implements ProductSkuApi {
|
||||
|
||||
@Override
|
||||
public List<ProductSkuRespDTO> getSkuList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<ProductSkuDO> skus = productSkuService.getSkuList(ids);
|
||||
return ProductSkuConvert.INSTANCE.convertList04(skus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProductSkuRespDTO> getSkuListBySpuId(Collection<Long> spuIds) {
|
||||
if (CollUtil.isEmpty(spuIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spuIds);
|
||||
return ProductSkuConvert.INSTANCE.convertList04(skus);
|
||||
}
|
||||
|
@@ -27,9 +27,6 @@ public class ProductSpuApiImpl implements ProductSpuApi {
|
||||
|
||||
@Override
|
||||
public List<ProductSpuRespDTO> getSpuList(Collection<Long> ids) {
|
||||
if (CollectionUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return ProductSpuConvert.INSTANCE.convertList2(spuService.getSpuList(ids));
|
||||
}
|
||||
|
||||
|
@@ -1,22 +1,14 @@
|
||||
package cn.iocoder.yudao.module.product.convert.property;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
|
||||
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* 属性值 Convert
|
||||
@@ -38,18 +30,4 @@ public interface ProductPropertyValueConvert {
|
||||
|
||||
PageResult<ProductPropertyValueRespVO> convertPage(PageResult<ProductPropertyValueDO> page);
|
||||
|
||||
default List<ProductPropertyValueDetailRespBO> convertList(List<ProductPropertyValueDO> values, List<ProductPropertyDO> keys) {
|
||||
Map<Long, ProductPropertyDO> keyMap = convertMap(keys, ProductPropertyDO::getId);
|
||||
return CollectionUtils.convertList(values, value -> {
|
||||
ProductPropertyValueDetailRespBO valueDetail = new ProductPropertyValueDetailRespBO()
|
||||
.setValueId(value.getId()).setValueName(value.getName());
|
||||
// 设置属性项
|
||||
MapUtils.findAndThen(keyMap, value.getPropertyId(),
|
||||
key -> valueDetail.setPropertyId(key.getId()).setPropertyName(key.getName()));
|
||||
return valueDetail;
|
||||
});
|
||||
}
|
||||
|
||||
List<ProductPropertyValueDetailRespDTO> convertList02(List<ProductPropertyValueDetailRespBO> list);
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.Produc
|
||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -56,14 +55,6 @@ public interface ProductPropertyValueService {
|
||||
*/
|
||||
List<ProductPropertyValueDO> getPropertyValueListByPropertyId(Collection<Long> propertyIds);
|
||||
|
||||
/**
|
||||
* 根据编号数组,获得属性值列表
|
||||
*
|
||||
* @param ids 编号数组
|
||||
* @return 属性值明细列表
|
||||
*/
|
||||
List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据属性项编号,活的属性值数量
|
||||
*
|
||||
|
@@ -1,15 +1,12 @@
|
||||
package cn.iocoder.yudao.module.product.service.property;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueCreateReqVO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValuePageReqVO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.product.convert.property.ProductPropertyValueConvert;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
|
||||
import cn.iocoder.yudao.module.product.dal.mysql.property.ProductPropertyValueMapper;
|
||||
import cn.iocoder.yudao.module.product.service.property.bo.ProductPropertyValueDetailRespBO;
|
||||
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -17,11 +14,9 @@ import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_EXISTS;
|
||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.PROPERTY_VALUE_NOT_EXISTS;
|
||||
|
||||
@@ -99,23 +94,6 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
|
||||
return productPropertyValueMapper.selectListByPropertyId(propertyIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProductPropertyValueDetailRespBO> getPropertyValueDetailList(Collection<Long> ids) {
|
||||
// 获得属性值列表
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<ProductPropertyValueDO> values = productPropertyValueMapper.selectBatchIds(ids);
|
||||
if (CollUtil.isEmpty(values)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 获得属性项列表
|
||||
List<ProductPropertyDO> keys = productPropertyService.getPropertyList(
|
||||
convertSet(values, ProductPropertyValueDO::getPropertyId));
|
||||
// 组装明细
|
||||
return ProductPropertyValueConvert.INSTANCE.convertList(values, keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPropertyValueCountByPropertyId(Long propertyId) {
|
||||
return productPropertyValueMapper.selectCountByPropertyId(propertyId);
|
||||
|
@@ -1,33 +0,0 @@
|
||||
package cn.iocoder.yudao.module.product.service.property.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 商品属性项的明细 Response BO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class ProductPropertyValueDetailRespBO {
|
||||
|
||||
/**
|
||||
* 属性的编号
|
||||
*/
|
||||
private Long propertyId;
|
||||
|
||||
/**
|
||||
* 属性的名称
|
||||
*/
|
||||
private String propertyName;
|
||||
|
||||
/**
|
||||
* 属性值的编号
|
||||
*/
|
||||
private Long valueId;
|
||||
|
||||
/**
|
||||
* 属性值的名称
|
||||
*/
|
||||
private String valueName;
|
||||
|
||||
}
|
@@ -153,6 +153,9 @@ public class ProductSkuServiceImpl implements ProductSkuService {
|
||||
|
||||
@Override
|
||||
public List<ProductSkuDO> getSkuListBySpuId(Collection<Long> spuIds) {
|
||||
if (CollUtil.isEmpty(spuIds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return productSkuMapper.selectListBySpuId(spuIds);
|
||||
}
|
||||
|
||||
|
@@ -188,6 +188,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
||||
|
||||
@Override
|
||||
public List<ProductSpuDO> getSpuList(Collection<Long> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return productSpuMapper.selectBatchIds(ids);
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,7 @@
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
<description>
|
||||
market 模块 API,暴露给其它模块调用
|
||||
promotion 模块 API,暴露给其它模块调用
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
@@ -1,10 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.combination;
|
||||
|
||||
/**
|
||||
* 拼团活动 Api 接口
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
public interface CombinationActivityApi {
|
||||
|
||||
}
|
@@ -41,14 +41,6 @@ public interface CombinationRecordApi {
|
||||
*/
|
||||
boolean isCombinationRecordSuccess(Long userId, Long orderId);
|
||||
|
||||
/**
|
||||
* 更新拼团状态为【失败】
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param orderId 订单编号
|
||||
*/
|
||||
void updateRecordStatusToFailed(Long userId, Long orderId);
|
||||
|
||||
/**
|
||||
* 【下单前】校验是否满足拼团活动条件
|
||||
*
|
||||
|
@@ -1,21 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.price;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
|
||||
/**
|
||||
* 价格 API 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface PriceApi {
|
||||
|
||||
/**
|
||||
* 计算商品的价格
|
||||
*
|
||||
* @param calculateReqDTO 价格请求
|
||||
* @return 价格相应
|
||||
*/
|
||||
PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO);
|
||||
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.price.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 优惠劵的匹配信息 Response DTO
|
||||
*
|
||||
* why 放在 price 包下?主要获取的时候,需要涉及到较多的价格计算逻辑,放在 price 可以更好的复用逻辑
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class CouponMeetRespDTO {
|
||||
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
// ========== 非优惠劵的基本信息字段 ==========
|
||||
/**
|
||||
* 是否匹配
|
||||
*/
|
||||
private Boolean meet;
|
||||
/**
|
||||
* 不匹配的提示,即 {@link #meet} = true 才有值
|
||||
*
|
||||
* 例如说:
|
||||
* 1. 所结算商品没有符合条件的商品
|
||||
* 2. 差 XXX 元可用优惠劵
|
||||
* 3. 优惠劵未到使用时间
|
||||
*/
|
||||
private String meetTip;
|
||||
|
||||
}
|
@@ -1,62 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.price.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 价格计算 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@Deprecated
|
||||
public class PriceCalculateReqDTO {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*
|
||||
* 对应 MemberUserDO 的 id 编号
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
private Long couponId;
|
||||
|
||||
/**
|
||||
* 收货地址编号
|
||||
*/
|
||||
private Long addressId;
|
||||
|
||||
/**
|
||||
* 商品 SKU 数组
|
||||
*/
|
||||
@NotNull(message = "商品数组不能为空")
|
||||
private List<Item> items;
|
||||
|
||||
/**
|
||||
* 商品 SKU
|
||||
*/
|
||||
@Data
|
||||
public static class Item {
|
||||
|
||||
/**
|
||||
* SKU 编号
|
||||
*/
|
||||
@NotNull(message = "商品 SKU 编号不能为空")
|
||||
private Long skuId;
|
||||
|
||||
/**
|
||||
* SKU 数量
|
||||
*/
|
||||
@NotNull(message = "商品 SKU 数量不能为空")
|
||||
@Min(value = 0L, message = "商品 SKU 数量必须大于等于 0") // 可传递 0 数量,用于购物车未选中的情况
|
||||
private Integer count;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,252 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.price.dto;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 价格计算 Response DTO
|
||||
*
|
||||
* 整体设计,参考 taobao 的技术文档:
|
||||
* 1. <a href="https://developer.alibaba.com/docs/doc.htm?treeId=1&articleId=1029&docType=1">订单管理</a>
|
||||
* 2. <a href="https://open.taobao.com/docV3.htm?docId=108471&docType=1">常用订单金额说明</a>
|
||||
*
|
||||
* 举个例子:<a href="https://img.alicdn.com/top/i1/LB1mALAi4HI8KJjy1zbXXaxdpXa">订单图</a>
|
||||
* 输入:
|
||||
* 1. 订单实付: trade.payment = 198.00;订单邮费:5 元;
|
||||
* 2. 商品级优惠 圣诞价: 省 29.00 元 和 圣诞价:省 150.00 元; 订单级优惠,圣诞 2:省 5.00 元;
|
||||
* 分摊:
|
||||
* 1. 商品 1:原价 108 元,优惠 29 元,子订单实付 79 元,分摊主订单优惠 1.99 元;
|
||||
* 2. 商品 2:原价 269 元,优惠 150 元,子订单实付 119 元,分摊主订单优惠 3.01 元;
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@Deprecated
|
||||
public class PriceCalculateRespDTO {
|
||||
|
||||
/**
|
||||
* 订单
|
||||
*/
|
||||
private Order order;
|
||||
|
||||
/**
|
||||
* 营销活动数组
|
||||
*
|
||||
* 只对应 {@link Order#items} 商品匹配的活动
|
||||
*/
|
||||
private List<Promotion> promotions;
|
||||
|
||||
// TODO @芋艿:需要改造下,主要是价格字段
|
||||
/**
|
||||
* 订单
|
||||
*/
|
||||
@Data
|
||||
public static class Order {
|
||||
|
||||
/**
|
||||
* 商品原价(总),单位:分
|
||||
*
|
||||
* 基于 {@link OrderItem#getOriginalPrice()} 求和
|
||||
*
|
||||
* 对应 taobao 的 trade.total_fee 字段
|
||||
*/
|
||||
private Integer totalPrice;
|
||||
/**
|
||||
* 订单优惠(总),单位:分
|
||||
*
|
||||
* 订单级优惠:对主订单的优惠,常见如:订单满 200 元减 10 元;订单满 80 包邮。
|
||||
*
|
||||
* 对应 taobao 的 order.discount_fee 字段
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
/**
|
||||
* 优惠劵减免金额(总),单位:分
|
||||
*
|
||||
* 对应 taobao 的 trade.coupon_fee 字段
|
||||
*/
|
||||
private Integer couponPrice;
|
||||
/**
|
||||
* 积分减免金额(总),单位:分
|
||||
*
|
||||
* 对应 taobao 的 trade.point_fee 字段
|
||||
*/
|
||||
private Integer pointPrice;
|
||||
/**
|
||||
* 运费金额,单位:分
|
||||
*/
|
||||
private Integer deliveryPrice;
|
||||
/**
|
||||
* 最终购买金额(总),单位:分
|
||||
*
|
||||
* = {@link OrderItem#getPayPrice()} 求和
|
||||
* - {@link #couponPrice}
|
||||
* - {@link #pointPrice}
|
||||
* + {@link #deliveryPrice}
|
||||
* - {@link #discountPrice}
|
||||
*/
|
||||
private Integer payPrice;
|
||||
/**
|
||||
* 商品 SKU 数组
|
||||
*/
|
||||
private List<OrderItem> items;
|
||||
|
||||
// ========== 营销基本信息 ==========
|
||||
/**
|
||||
* 优惠劵编号
|
||||
*/
|
||||
private Long couponId;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单商品 SKU
|
||||
*/
|
||||
@Data
|
||||
public static class OrderItem {
|
||||
|
||||
/**
|
||||
* SPU 编号
|
||||
*/
|
||||
private Long spuId;
|
||||
/**
|
||||
* SKU 编号
|
||||
*/
|
||||
private Long skuId;
|
||||
/**
|
||||
* 购买数量
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 商品原价(总),单位:分
|
||||
*
|
||||
* = {@link #originalUnitPrice} * {@link #getCount()}
|
||||
*/
|
||||
private Integer originalPrice;
|
||||
/**
|
||||
* 商品原价(单),单位:分
|
||||
*
|
||||
* 对应 ProductSkuDO 的 price 字段
|
||||
* 对应 taobao 的 order.price 字段
|
||||
*/
|
||||
private Integer originalUnitPrice;
|
||||
/**
|
||||
* 商品优惠(总),单位:分
|
||||
*
|
||||
* 商品级优惠:对单个商品的,常见如:商品原价的 8 折;商品原价的减 50 元
|
||||
*
|
||||
* 对应 taobao 的 order.discount_fee 字段
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
/**
|
||||
* 子订单实付金额,不算主订单分摊金额,单位:分
|
||||
*
|
||||
* = {@link #originalPrice}
|
||||
* - {@link #discountPrice}
|
||||
*
|
||||
* 对应 taobao 的 order.payment 字段
|
||||
*/
|
||||
private Integer payPrice;
|
||||
|
||||
/**
|
||||
* 子订单分摊金额(总),单位:分
|
||||
* 需要分摊 {@link Order#discountPrice}、{@link Order#couponPrice}、{@link Order#pointPrice}
|
||||
*
|
||||
* 对应 taobao 的 order.part_mjz_discount 字段
|
||||
* 淘宝说明:子订单分摊优惠基础逻辑:一般正常优惠券和满减优惠按照子订单的金额进行分摊,特殊情况如果优惠券是指定商品使用的,只会分摊到对应商品子订单上不分摊。
|
||||
*/
|
||||
private Integer orderPartPrice;
|
||||
/**
|
||||
* 分摊后子订单实付金额(总),单位:分
|
||||
*
|
||||
* = {@link #payPrice}
|
||||
* - {@link #orderPartPrice}
|
||||
*
|
||||
* 对应 taobao 的 divide_order_fee 字段
|
||||
*/
|
||||
private Integer orderDividePrice;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 营销明细
|
||||
*/
|
||||
@Data
|
||||
@Deprecated
|
||||
public static class Promotion {
|
||||
|
||||
/**
|
||||
* 营销编号
|
||||
*
|
||||
* 例如说:营销活动的编号、优惠劵的编号
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 营销名字
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 营销类型
|
||||
*
|
||||
* 枚举 {@link PromotionTypeEnum}
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 营销级别
|
||||
*
|
||||
* 枚举 @link PromotionLevelEnum} TODO PromotionLevelEnum 没有这个枚举类
|
||||
*/
|
||||
private Integer level;
|
||||
/**
|
||||
* 计算时的原价(总),单位:分
|
||||
*/
|
||||
private Integer totalPrice;
|
||||
/**
|
||||
* 计算时的优惠(总),单位:分
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
/**
|
||||
* 匹配的商品 SKU 数组
|
||||
*/
|
||||
private List<PromotionItem> items;
|
||||
|
||||
// ========== 匹配情况 ==========
|
||||
|
||||
/**
|
||||
* 是否满足优惠条件
|
||||
*/
|
||||
private Boolean match;
|
||||
/**
|
||||
* 满足条件的提示
|
||||
*
|
||||
* 如果 {@link #match} = true 满足,则提示“圣诞价:省 150.00 元”
|
||||
* 如果 {@link #match} = false 不满足,则提示“购满 85 元,可减 40 元”
|
||||
*/
|
||||
private String description;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 营销匹配的商品 SKU
|
||||
*/
|
||||
@Data
|
||||
public static class PromotionItem {
|
||||
|
||||
/**
|
||||
* 商品 SKU 编号
|
||||
*/
|
||||
private Long skuId;
|
||||
/**
|
||||
* 计算时的原价(总),单位:分
|
||||
*/
|
||||
private Integer originalPrice;
|
||||
/**
|
||||
* 计算时的优惠(总),单位:分
|
||||
*/
|
||||
private Integer discountPrice;
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -118,9 +118,11 @@ public interface ErrorCodeConstants {
|
||||
|
||||
// ========== 装修模板 1-013-017-000 ==========
|
||||
ErrorCode DIY_TEMPLATE_NOT_EXISTS = new ErrorCode(1_013_017_000, "装修模板不存在");
|
||||
ErrorCode DIY_TEMPLATE_USED_CANNOT_DELETE = new ErrorCode(1_013_017_001, "不能删除正在使用的装修模板");
|
||||
ErrorCode DIY_TEMPLATE_NAME_USED = new ErrorCode(1_013_017_001, "装修模板名称({})已经被使用");
|
||||
ErrorCode DIY_TEMPLATE_USED_CANNOT_DELETE = new ErrorCode(1_013_017_002, "不能删除正在使用的装修模板");
|
||||
|
||||
// ========== 装修页面 1-013-018-000 ==========
|
||||
ErrorCode DIY_PAGE_NOT_EXISTS = new ErrorCode(1_013_018_000, "装修页面不存在");
|
||||
ErrorCode DIY_PAGE_NAME_USED = new ErrorCode(1_013_018_001, "装修页面名称({})已经被使用");
|
||||
|
||||
}
|
||||
|
@@ -14,8 +14,8 @@
|
||||
<name>${project.artifactId}</name>
|
||||
|
||||
<description>
|
||||
market模块,主要实现营销相关功能
|
||||
例如:营销活动、banner广告、优惠券、优惠码等功能。
|
||||
promotion 模块,主要实现营销相关功能
|
||||
例如:营销活动、banner 广告、优惠券、优惠码等功能。
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
@@ -49,10 +49,6 @@
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
|
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.bargain;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.service.bargain.BargainActivityService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -11,6 +12,7 @@ import javax.annotation.Resource;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BargainActivityApiImpl implements BargainActivityApi {
|
||||
|
||||
@Resource
|
||||
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.bargain;
|
||||
import cn.iocoder.yudao.module.promotion.api.bargain.dto.BargainValidateJoinRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.service.bargain.BargainRecordService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -12,6 +13,7 @@ import javax.annotation.Resource;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BargainRecordApiImpl implements BargainRecordApi {
|
||||
|
||||
@Resource
|
||||
|
@@ -1,13 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.combination;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 拼团活动 Api 接口实现类
|
||||
*
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Service
|
||||
public class CombinationActivityApiImpl implements CombinationActivityApi {
|
||||
|
||||
}
|
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationR
|
||||
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.combination.CombinationRecordService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -20,6 +21,7 @@ import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINA
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class CombinationRecordApiImpl implements CombinationRecordApi {
|
||||
|
||||
@Resource
|
||||
@@ -44,11 +46,6 @@ public class CombinationRecordApiImpl implements CombinationRecordApi {
|
||||
return CombinationRecordStatusEnum.isSuccess(record.getStatus());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRecordStatusToFailed(Long userId, Long orderId) {
|
||||
recordService.updateCombinationRecordStatusByUserIdAndOrderId(CombinationRecordStatusEnum.FAILED.getStatus(), userId, orderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId, Long skuId, Integer count) {
|
||||
return recordService.validateJoinCombination(userId, activityId, headId, skuId, count);
|
||||
|
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -17,6 +18,7 @@ import javax.annotation.Resource;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class CouponApiImpl implements CouponApi {
|
||||
|
||||
@Resource
|
||||
|
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO
|
||||
import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
|
||||
import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
@@ -15,6 +16,7 @@ import java.util.List;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class DiscountActivityApiImpl implements DiscountActivityApi {
|
||||
|
||||
@Resource
|
||||
|
@@ -1,28 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.price;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.service.price.PriceService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 价格 API 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
public class PriceApiImpl implements PriceApi {
|
||||
|
||||
@Resource
|
||||
private PriceService priceService;
|
||||
|
||||
@Override
|
||||
public PriceCalculateRespDTO calculatePrice(PriceCalculateReqDTO calculateReqDTO) {
|
||||
//return priceService.calculatePrice(calculateReqDTO); TODO 没有 calculatePrice 这个方法
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.reward;
|
||||
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collection;
|
||||
@@ -14,6 +15,7 @@ import java.util.List;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class RewardActivityApiImpl implements RewardActivityApi {
|
||||
|
||||
@Resource
|
||||
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.seckill;
|
||||
import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@@ -12,6 +13,7 @@ import javax.annotation.Resource;
|
||||
* @author HUIHUI
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class SeckillActivityApiImpl implements SeckillActivityApi {
|
||||
|
||||
@Resource
|
||||
|
@@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - Banner Response VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
@@ -12,4 +14,7 @@ public class BannerRespVO extends BannerBaseVO {
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022-07-01 23:59:59")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
@@ -2,10 +2,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.diy;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPagePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.*;
|
||||
import cn.iocoder.yudao.module.promotion.convert.diy.DiyPageConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyPageDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.diy.DiyPageService;
|
||||
@@ -82,4 +79,21 @@ public class DiyPageController {
|
||||
return success(DiyPageConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/get-property")
|
||||
@Operation(summary = "获得装修页面属性")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:diy-page:query')")
|
||||
public CommonResult<DiyPagePropertyRespVO> getDiyPageProperty(@RequestParam("id") Long id) {
|
||||
DiyPageDO diyPage = diyPageService.getDiyPage(id);
|
||||
return success(DiyPageConvert.INSTANCE.convertPropertyVo(diyPage));
|
||||
}
|
||||
|
||||
@PutMapping("/update-property")
|
||||
@Operation(summary = "更新装修页面属性")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:diy-page:update')")
|
||||
public CommonResult<Boolean> updateDiyPageProperty(@Valid @RequestBody DiyPagePropertyUpdateRequestVO updateReqVO) {
|
||||
diyPageService.updateDiyPageProperty(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,12 +2,11 @@ package cn.iocoder.yudao.module.promotion.controller.admin.diy;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.*;
|
||||
import cn.iocoder.yudao.module.promotion.convert.diy.DiyTemplateConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyPageDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.diy.DiyPageService;
|
||||
import cn.iocoder.yudao.module.promotion.service.diy.DiyTemplateService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@@ -19,6 +18,8 @@ import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 装修模板")
|
||||
@@ -29,6 +30,8 @@ public class DiyTemplateController {
|
||||
|
||||
@Resource
|
||||
private DiyTemplateService diyTemplateService;
|
||||
@Resource
|
||||
private DiyPageService diyPageService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建装修模板")
|
||||
@@ -79,4 +82,22 @@ public class DiyTemplateController {
|
||||
return success(DiyTemplateConvert.INSTANCE.convertPage(pageResult));
|
||||
}
|
||||
|
||||
@GetMapping("/get-property")
|
||||
@Operation(summary = "获得装修模板属性")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:diy-template:query')")
|
||||
public CommonResult<DiyTemplatePropertyRespVO> getDiyTemplateProperty(@RequestParam("id") Long id) {
|
||||
DiyTemplateDO diyTemplate = diyTemplateService.getDiyTemplate(id);
|
||||
List<DiyPageDO> pages = diyPageService.getDiyPageByTemplateId(id);
|
||||
return success(DiyTemplateConvert.INSTANCE.convertPropertyVo(diyTemplate, pages));
|
||||
}
|
||||
|
||||
@PutMapping("/update-property")
|
||||
@Operation(summary = "更新装修模板属性")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:diy-template:update')")
|
||||
public CommonResult<Boolean> updateDiyTemplateProperty(@Valid @RequestBody DiyTemplatePropertyUpdateRequestVO updateReqVO) {
|
||||
diyTemplateService.updateDiyTemplateProperty(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -26,7 +26,4 @@ public class DiyPageBaseVO {
|
||||
@Schema(description = "预览图")
|
||||
private List<String> previewImageUrls;
|
||||
|
||||
@Schema(description = "页面属性", example = "[]")
|
||||
private String property;
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "管理后台 - 装修页面属性 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DiyPagePropertyRespVO extends DiyPageBaseVO {
|
||||
|
||||
@Schema(description = "装修页面编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31209")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "页面属性", example = "[]")
|
||||
private String property;
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 装修页面属性更新 Request VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class DiyPagePropertyUpdateRequestVO {
|
||||
|
||||
@Schema(description = "装修页面编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31209")
|
||||
@NotNull(message = "装修页面编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "页面属性,JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
@NotBlank(message = "页面属性不能为空")
|
||||
private String property;
|
||||
|
||||
}
|
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -14,7 +14,7 @@ import java.util.List;
|
||||
public class DiyTemplateBaseVO {
|
||||
|
||||
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "默认主题")
|
||||
@NotNull(message = "模板名称不能为空")
|
||||
@NotEmpty(message = "模板名称不能为空")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "备注", example = "默认主题")
|
||||
@@ -23,7 +23,4 @@ public class DiyTemplateBaseVO {
|
||||
@Schema(description = "预览图", example = "[https://www.iocoder.cn/1.jpg]")
|
||||
private List<String> previewImageUrls;
|
||||
|
||||
@Schema(description = "模板属性,JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
private String property;
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPagePropertyRespVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "管理后台 - 装修模板属性 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class DiyTemplatePropertyRespVO extends DiyTemplateBaseVO {
|
||||
|
||||
@Schema(description = "装修模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31209")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "模板属性,JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
private String property;
|
||||
|
||||
@Schema(description = "模板页面", requiredMode = Schema.RequiredMode.REQUIRED, example = "[]")
|
||||
private List<DiyPagePropertyRespVO> pages;
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 装修模板属性更新 Request VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class DiyTemplatePropertyUpdateRequestVO {
|
||||
|
||||
@Schema(description = "装修模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31209")
|
||||
@NotNull(message = "装修模板编号不能为空")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "模板属性,JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
@NotBlank(message = "模板属性不能为空")
|
||||
private String property;
|
||||
|
||||
}
|
@@ -96,13 +96,13 @@ public class AppCouponTemplateController {
|
||||
*/
|
||||
private Long getProductScopeValue(Integer productScope, Long spuId) {
|
||||
// 通用券:没有商品范围
|
||||
if (productScope == null || ObjectUtils.equalsAny(productScope, PromotionProductScopeEnum.ALL.getScope(), null)) {
|
||||
if (ObjectUtils.equalsAny(productScope, PromotionProductScopeEnum.ALL.getScope(), null)) {
|
||||
return null;
|
||||
}
|
||||
// 品类券:查询商品的品类编号
|
||||
if (Objects.equals(productScope, PromotionProductScopeEnum.CATEGORY.getScope()) && spuId != null) {
|
||||
return Optional.ofNullable(productSpuApi.getSpu(spuId))
|
||||
.map(ProductSpuRespDTO::getCategoryId).orElse(null);
|
||||
ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
|
||||
return spu != null ? spu.getCategoryId() : null;
|
||||
}
|
||||
// 商品卷:直接返回
|
||||
return spuId;
|
||||
|
@@ -0,0 +1,63 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.diy;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.diy.vo.AppDiyTemplatePropertyRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.diy.DiyTemplateConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyPageDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.diy.DiyPageService;
|
||||
import cn.iocoder.yudao.module.promotion.service.diy.DiyTemplateService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst;
|
||||
|
||||
@Tag(name = "用户 APP - 装修模板")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/diy-template")
|
||||
@Validated
|
||||
public class AppDiyTemplateController {
|
||||
|
||||
@Resource
|
||||
private DiyTemplateService diyTemplateService;
|
||||
@Resource
|
||||
private DiyPageService diyPageService;
|
||||
|
||||
@GetMapping("/used")
|
||||
@Operation(summary = "使用中的装修模板")
|
||||
public CommonResult<AppDiyTemplatePropertyRespVO> getUsedDiyTemplate() {
|
||||
DiyTemplateDO diyTemplate = diyTemplateService.getUsedDiyTemplate();
|
||||
return success(buildVo(diyTemplate));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得装修模板")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
public CommonResult<AppDiyTemplatePropertyRespVO> getDiyTemplate(@RequestParam("id") Long id) {
|
||||
DiyTemplateDO diyTemplate = diyTemplateService.getDiyTemplate(id);
|
||||
return success(buildVo(diyTemplate));
|
||||
}
|
||||
|
||||
private AppDiyTemplatePropertyRespVO buildVo(DiyTemplateDO diyTemplate) {
|
||||
if (diyTemplate == null) {
|
||||
return null;
|
||||
}
|
||||
// 查询模板下的页面
|
||||
List<DiyPageDO> pages = diyPageService.getDiyPageByTemplateId(diyTemplate.getId());
|
||||
String home = findFirst(pages, page -> "首页".equals(page.getName()), DiyPageDO::getProperty);
|
||||
String user = findFirst(pages, page -> "我的".equals(page.getName()), DiyPageDO::getProperty);
|
||||
// 拼接返回
|
||||
return DiyTemplateConvert.INSTANCE.convertPropertyVo2(diyTemplate, home, user);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.diy.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "用户 App - 装修页面属性 Response VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class AppDiyPagePropertyRespVO {
|
||||
|
||||
@Schema(description = "装修页面编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31209")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "页面名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "页面属性", example = "[]")
|
||||
private String property;
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.app.diy.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonRawValue;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
@Schema(description = "用户 App - 装修模板属性 Response VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class AppDiyTemplatePropertyRespVO {
|
||||
|
||||
@Schema(description = "装修模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31209")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "模板名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "默认主题")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "模板属性", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
@JsonRawValue
|
||||
private String property;
|
||||
|
||||
@Schema(description = "首页", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
@JsonRawValue
|
||||
private String home;
|
||||
|
||||
@Schema(description = "我的", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
@JsonRawValue
|
||||
private String user;
|
||||
|
||||
}
|
@@ -1,9 +1,7 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.diy;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyPageDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@@ -30,4 +28,10 @@ public interface DiyPageConvert {
|
||||
|
||||
PageResult<DiyPageRespVO> convertPage(PageResult<DiyPageDO> page);
|
||||
|
||||
DiyPageCreateReqVO convertCreateVo(Long templateId, String name, String remark);
|
||||
|
||||
DiyPagePropertyRespVO convertPropertyVo(DiyPageDO diyPage);
|
||||
|
||||
DiyPageDO convert(DiyPagePropertyUpdateRequestVO updateReqVO);
|
||||
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.diy;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.diy.vo.AppDiyTemplatePropertyRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyPageDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyTemplateDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@@ -30,4 +30,10 @@ public interface DiyTemplateConvert {
|
||||
|
||||
PageResult<DiyTemplateRespVO> convertPage(PageResult<DiyTemplateDO> page);
|
||||
|
||||
DiyTemplatePropertyRespVO convertPropertyVo(DiyTemplateDO diyTemplate, List<DiyPageDO> pages);
|
||||
|
||||
AppDiyTemplatePropertyRespVO convertPropertyVo2(DiyTemplateDO diyTemplate, String home, String user);
|
||||
|
||||
DiyTemplateDO convert(DiyTemplatePropertyUpdateRequestVO updateReqVO);
|
||||
|
||||
}
|
||||
|
@@ -1,49 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.convert.price;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface PriceConvert {
|
||||
|
||||
PriceConvert INSTANCE = Mappers.getMapper(PriceConvert.class);
|
||||
|
||||
default PriceCalculateRespDTO convert(PriceCalculateReqDTO calculateReqDTO, List<ProductSkuRespDTO> skuList) {
|
||||
// 创建 PriceCalculateRespDTO 对象
|
||||
PriceCalculateRespDTO priceCalculate = new PriceCalculateRespDTO();
|
||||
// 创建它的 Order 属性
|
||||
PriceCalculateRespDTO.Order order = new PriceCalculateRespDTO.Order().setTotalPrice(0).setDiscountPrice(0)
|
||||
.setCouponPrice(0).setPointPrice(0).setDeliveryPrice(0).setPayPrice(0)
|
||||
.setItems(new ArrayList<>()).setCouponId(calculateReqDTO.getCouponId());
|
||||
priceCalculate.setOrder(order).setPromotions(new ArrayList<>());
|
||||
// 创建它的 OrderItem 属性
|
||||
Map<Long, Integer> skuIdCountMap = CollectionUtils.convertMap(calculateReqDTO.getItems(),
|
||||
PriceCalculateReqDTO.Item::getSkuId, PriceCalculateReqDTO.Item::getCount);
|
||||
skuList.forEach(sku -> {
|
||||
Integer count = skuIdCountMap.get(sku.getId());
|
||||
PriceCalculateRespDTO.OrderItem orderItem = new PriceCalculateRespDTO.OrderItem()
|
||||
.setSpuId(sku.getSpuId()).setSkuId(sku.getId()).setCount(count)
|
||||
.setOriginalUnitPrice(sku.getPrice()).setOriginalPrice(sku.getPrice() * count)
|
||||
.setDiscountPrice(0).setOrderPartPrice(0);
|
||||
orderItem.setPayPrice(orderItem.getOriginalPrice()).setOrderDividePrice(orderItem.getOriginalPrice());
|
||||
priceCalculate.getOrder().getItems().add(orderItem);
|
||||
// 补充价格信息到 Order 中
|
||||
order.setTotalPrice(order.getTotalPrice() + orderItem.getOriginalPrice())
|
||||
.setPayPrice(order.getTotalPrice());
|
||||
});
|
||||
return priceCalculate;
|
||||
}
|
||||
|
||||
CouponMeetRespDTO convert(CouponDO coupon);
|
||||
|
||||
}
|
@@ -32,6 +32,8 @@ public class DiyPageDO extends BaseDO {
|
||||
private Long id;
|
||||
/**
|
||||
* 装修模板编号
|
||||
*
|
||||
* 关联 {@link DiyTemplateDO#getId()}
|
||||
*/
|
||||
private Long templateId;
|
||||
/**
|
||||
|
@@ -14,6 +14,9 @@ import java.util.List;
|
||||
/**
|
||||
* 装修模板 DO
|
||||
*
|
||||
* 1. 新建一个模版,下面可以包含多个 {@link DiyPageDO} 页面,例如说首页、我的
|
||||
* 2. 如果需要使用某个模版,则将 {@link #used} 设置为 true,表示已使用,有且仅有一个
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@TableName(value = "promotion_diy_template", autoResultMap = true)
|
||||
|
@@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPagePag
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyPageDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 装修页面 Mapper
|
||||
*
|
||||
@@ -19,8 +21,19 @@ public interface DiyPageMapper extends BaseMapperX<DiyPageDO> {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<DiyPageDO>()
|
||||
.likeIfPresent(DiyPageDO::getName, reqVO.getName())
|
||||
.betweenIfPresent(DiyPageDO::getCreateTime, reqVO.getCreateTime())
|
||||
// 模板下面的页面,在模板中管理
|
||||
.isNull(DiyPageDO::getTemplateId)
|
||||
.orderByDesc(DiyPageDO::getId));
|
||||
}
|
||||
|
||||
default List<DiyPageDO> selectListByTemplateId(Long templateId) {
|
||||
return selectList(DiyPageDO::getTemplateId, templateId);
|
||||
}
|
||||
|
||||
default DiyPageDO selectByNameAndTemplateIdIsNull(String name) {
|
||||
return selectOne(new LambdaQueryWrapperX<DiyPageDO>()
|
||||
.eq(DiyPageDO::getName, name)
|
||||
.isNull(DiyPageDO::getTemplateId));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -29,4 +29,8 @@ public interface DiyTemplateMapper extends BaseMapperX<DiyTemplateDO> {
|
||||
return selectOne(DiyTemplateDO::getUsed, used);
|
||||
}
|
||||
|
||||
default DiyTemplateDO selectByName(String name) {
|
||||
return selectOne(DiyTemplateDO::getName, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.promotion.mq.consumer.coupon;
|
||||
|
||||
import cn.iocoder.yudao.module.member.message.user.MemberUserCreateMessage;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 用户注册时,发送优惠劵的消费者,基 {@link MemberUserCreateMessage} 消息
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class CouponTakeByRegisterConsumer {
|
||||
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
|
||||
@EventListener
|
||||
@Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
|
||||
public void onMessage(MemberUserCreateMessage message) {
|
||||
log.info("[onMessage][消息内容({})]", message);
|
||||
couponService.takeCouponByRegister(message.getUserId());
|
||||
}
|
||||
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.mq.consumer.coupon;
|
||||
|
||||
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;
|
||||
import cn.iocoder.yudao.module.promotion.mq.message.coupon.UserCreateMessage;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 针对 {@link UserCreateMessage} 的消费者
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
public class UserCreateConsumer extends AbstractStreamMessageListener<UserCreateMessage> {
|
||||
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
|
||||
@Override
|
||||
public void onMessage(UserCreateMessage message) {
|
||||
log.info("[onMessage][消息内容({})]", message);
|
||||
couponService.takeCouponByRegister(message.getUserId());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 消息队列的消费者
|
||||
*/
|
||||
package cn.iocoder.yudao.module.promotion.mq.consumer;
|
@@ -1,29 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.mq.message.coupon;
|
||||
|
||||
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 会员用户创建消息
|
||||
*
|
||||
* @author owen
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserCreateMessage extends AbstractStreamMessage {
|
||||
|
||||
/**
|
||||
* 用户编号
|
||||
*/
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
@Override
|
||||
public String getStreamKey() {
|
||||
return "member.create.send";
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 消息队列的消息
|
||||
*/
|
||||
package cn.iocoder.yudao.module.promotion.mq.message;
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 消息队列的生产者
|
||||
*/
|
||||
package cn.iocoder.yudao.module.promotion.mq.producer;
|
@@ -108,8 +108,8 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
|
||||
}
|
||||
|
||||
// 2. 校验商品 sku 都存在
|
||||
Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),
|
||||
ProductSkuRespDTO::getId);
|
||||
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(singletonList(spuId));
|
||||
Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
|
||||
products.forEach(product -> {
|
||||
if (!skuMap.containsKey(product.getSkuId())) {
|
||||
throw exception(SKU_NOT_EXISTS);
|
||||
|
@@ -21,15 +21,6 @@ import java.util.Map;
|
||||
*/
|
||||
public interface CombinationRecordService {
|
||||
|
||||
/**
|
||||
* 更新拼团状态
|
||||
*
|
||||
* @param status 状态
|
||||
* @param userId 用户编号
|
||||
* @param orderId 订单编号
|
||||
*/
|
||||
void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId);
|
||||
|
||||
/**
|
||||
* 【下单前】校验是否满足拼团活动条件
|
||||
*
|
||||
@@ -62,15 +53,6 @@ public interface CombinationRecordService {
|
||||
*/
|
||||
CombinationRecordDO getCombinationRecord(Long userId, Long orderId);
|
||||
|
||||
/**
|
||||
* 获取拼团记录
|
||||
*
|
||||
* @param userId 用户 id
|
||||
* @param activityId 活动 id
|
||||
* @return 拼团记录列表
|
||||
*/
|
||||
List<CombinationRecordDO> getCombinationRecordListByUserIdAndActivityId(Long userId, Long activityId);
|
||||
|
||||
/**
|
||||
* 【下单前】校验是否满足拼团活动条件
|
||||
*
|
||||
|
@@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.combination.CombinationRecord
|
||||
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -64,27 +65,9 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
||||
private ProductSkuApi productSkuApi;
|
||||
|
||||
@Resource
|
||||
@Lazy
|
||||
private TradeOrderApi tradeOrderApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateCombinationRecordStatusByUserIdAndOrderId(Integer status, Long userId, Long orderId) {
|
||||
// 校验拼团是否存在
|
||||
CombinationRecordDO record = validateCombinationRecord(userId, orderId);
|
||||
|
||||
// 更新状态
|
||||
combinationRecordMapper.updateById(new CombinationRecordDO().setId(record.getId()).setStatus(status));
|
||||
}
|
||||
|
||||
private CombinationRecordDO validateCombinationRecord(Long userId, Long orderId) {
|
||||
// 校验拼团是否存在
|
||||
CombinationRecordDO recordDO = combinationRecordMapper.selectByUserIdAndOrderId(userId, orderId);
|
||||
if (recordDO == null) {
|
||||
throw exception(COMBINATION_RECORD_NOT_EXISTS);
|
||||
}
|
||||
return recordDO;
|
||||
}
|
||||
|
||||
// TODO @芋艿:在详细预览下;
|
||||
@Override
|
||||
public KeyValue<CombinationActivityDO, CombinationProductDO> validateCombinationRecord(
|
||||
@@ -229,11 +212,6 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
||||
return combinationRecordMapper.selectByUserIdAndOrderId(userId, orderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CombinationRecordDO> getCombinationRecordListByUserIdAndActivityId(Long userId, Long activityId) {
|
||||
return combinationRecordMapper.selectListByUserIdAndActivityId(userId, activityId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CombinationValidateJoinRespDTO validateJoinCombination(Long userId, Long activityId, Long headId,
|
||||
Long skuId, Integer count) {
|
||||
|
@@ -7,7 +7,6 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
@@ -80,12 +79,11 @@ public class CouponServiceImpl implements CouponService {
|
||||
public PageResult<CouponDO> getCouponPage(CouponPageReqVO pageReqVO) {
|
||||
// 获得用户编号
|
||||
if (StrUtil.isNotEmpty(pageReqVO.getNickname())) {
|
||||
Set<Long> userIds = CollectionUtils.convertSet(memberUserApi.getUserListByNickname(pageReqVO.getNickname()),
|
||||
MemberUserRespDTO::getId);
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
List<MemberUserRespDTO> users = memberUserApi.getUserListByNickname(pageReqVO.getNickname());
|
||||
if (CollUtil.isEmpty(users)) {
|
||||
return PageResult.empty();
|
||||
}
|
||||
pageReqVO.setUserIds(userIds);
|
||||
pageReqVO.setUserIds(convertSet(users, MemberUserRespDTO::getId));
|
||||
}
|
||||
// 分页查询
|
||||
return couponMapper.selectPage(pageReqVO);
|
||||
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.service.diy;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPagePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPagePropertyUpdateRequestVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyPageDO;
|
||||
|
||||
@@ -63,4 +64,19 @@ public interface DiyPageService {
|
||||
*/
|
||||
PageResult<DiyPageDO> getDiyPagePage(DiyPagePageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 更新装修页面属性
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateDiyPageProperty(DiyPagePropertyUpdateRequestVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 获得模板所属的页面列表
|
||||
*
|
||||
* @param templateId 模板编号
|
||||
* @return 装修页面列表
|
||||
*/
|
||||
List<DiyPageDO> getDiyPageByTemplateId(Long templateId);
|
||||
|
||||
}
|
||||
|
@@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.promotion.service.diy;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPagePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPagePropertyUpdateRequestVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.page.DiyPageUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.diy.DiyPageConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyPageDO;
|
||||
@@ -17,6 +19,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.DIY_PAGE_NAME_USED;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.DIY_PAGE_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
@@ -33,10 +36,12 @@ public class DiyPageServiceImpl implements DiyPageService {
|
||||
|
||||
@Override
|
||||
public Long createDiyPage(DiyPageCreateReqVO createReqVO) {
|
||||
// 校验名称唯一
|
||||
validateNameUnique(null, createReqVO.getTemplateId(), createReqVO.getName());
|
||||
// 插入
|
||||
DiyPageDO diyPage = DiyPageConvert.INSTANCE.convert(createReqVO);
|
||||
diyPage.setProperty("{}");
|
||||
diyPageMapper.insert(diyPage);
|
||||
// 返回
|
||||
return diyPage.getId();
|
||||
}
|
||||
|
||||
@@ -44,11 +49,37 @@ public class DiyPageServiceImpl implements DiyPageService {
|
||||
public void updateDiyPage(DiyPageUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateDiyPageExists(updateReqVO.getId());
|
||||
// 校验名称唯一
|
||||
validateNameUnique(updateReqVO.getId(), updateReqVO.getTemplateId(), updateReqVO.getName());
|
||||
// 更新
|
||||
DiyPageDO updateObj = DiyPageConvert.INSTANCE.convert(updateReqVO);
|
||||
diyPageMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 Page 页面,在一个 template 模版下的名字是唯一的
|
||||
*
|
||||
* @param id Page 编号
|
||||
* @param templateId 模版编号
|
||||
* @param name Page 名字
|
||||
*/
|
||||
void validateNameUnique(Long id, Long templateId, String name) {
|
||||
if (templateId != null || StrUtil.isBlank(name)) {
|
||||
return;
|
||||
}
|
||||
DiyPageDO page = diyPageMapper.selectByNameAndTemplateIdIsNull(name);
|
||||
if (page == null) {
|
||||
return;
|
||||
}
|
||||
// 如果 id 为空,说明不用比较是否为相同 id 的页面
|
||||
if (id == null) {
|
||||
throw exception(DIY_PAGE_NAME_USED, name);
|
||||
}
|
||||
if (!page.getId().equals(id)) {
|
||||
throw exception(DIY_PAGE_NAME_USED, name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDiyPage(Long id) {
|
||||
// 校验存在
|
||||
@@ -81,4 +112,18 @@ public class DiyPageServiceImpl implements DiyPageService {
|
||||
return diyPageMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiyPageDO> getDiyPageByTemplateId(Long templateId) {
|
||||
return diyPageMapper.selectListByTemplateId(templateId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDiyPageProperty(DiyPagePropertyUpdateRequestVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateDiyPageExists(updateReqVO.getId());
|
||||
// 更新
|
||||
DiyPageDO updateObj = DiyPageConvert.INSTANCE.convert(updateReqVO);
|
||||
diyPageMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.service.diy;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplatePropertyUpdateRequestVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyTemplateDO;
|
||||
|
||||
@@ -60,4 +61,18 @@ public interface DiyTemplateService {
|
||||
*/
|
||||
void useDiyTemplate(Long id);
|
||||
|
||||
/**
|
||||
* 更新装修模板属性
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updateDiyTemplateProperty(DiyTemplatePropertyUpdateRequestVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 获取使用中的装修模板
|
||||
*
|
||||
* @return 装修模板
|
||||
*/
|
||||
DiyTemplateDO getUsedDiyTemplate();
|
||||
|
||||
}
|
||||
|
@@ -1,22 +1,25 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.diy;
|
||||
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplatePropertyUpdateRequestVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.diy.vo.template.DiyTemplateUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.diy.DiyPageConvert;
|
||||
import cn.iocoder.yudao.module.promotion.convert.diy.DiyTemplateConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.diy.DiyTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.diy.DiyTemplateMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.DIY_TEMPLATE_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.DIY_TEMPLATE_USED_CANNOT_DELETE;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 装修模板 Service 实现类
|
||||
@@ -30,24 +33,64 @@ public class DiyTemplateServiceImpl implements DiyTemplateService {
|
||||
@Resource
|
||||
private DiyTemplateMapper diyTemplateMapper;
|
||||
|
||||
@Resource
|
||||
private DiyPageService diyPageService;
|
||||
|
||||
// TODO @疯狂:事务;
|
||||
@Override
|
||||
public Long createDiyTemplate(DiyTemplateCreateReqVO createReqVO) {
|
||||
// 校验名称唯一
|
||||
validateNameUnique(null, createReqVO.getName());
|
||||
// 插入
|
||||
DiyTemplateDO diyTemplate = DiyTemplateConvert.INSTANCE.convert(createReqVO);
|
||||
diyTemplate.setProperty("{}");
|
||||
diyTemplateMapper.insert(diyTemplate);
|
||||
// 创建默认页面
|
||||
createDefaultPage(diyTemplate);
|
||||
// 返回
|
||||
return diyTemplate.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建模板下面的默认页面
|
||||
* 默认创建两个页面:首页、我的
|
||||
*
|
||||
* @param diyTemplate 模板对象
|
||||
*/
|
||||
private void createDefaultPage(DiyTemplateDO diyTemplate) {
|
||||
String remark = String.format("模板【%s】自动创建", diyTemplate.getName());
|
||||
diyPageService.createDiyPage(DiyPageConvert.INSTANCE.convertCreateVo(diyTemplate.getId(), "首页", remark));
|
||||
diyPageService.createDiyPage(DiyPageConvert.INSTANCE.convertCreateVo(diyTemplate.getId(), "我的", remark));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDiyTemplate(DiyTemplateUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateDiyTemplateExists(updateReqVO.getId());
|
||||
// 校验名称唯一
|
||||
validateNameUnique(updateReqVO.getId(), updateReqVO.getName());
|
||||
// 更新
|
||||
DiyTemplateDO updateObj = DiyTemplateConvert.INSTANCE.convert(updateReqVO);
|
||||
diyTemplateMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
void validateNameUnique(Long id, String name) {
|
||||
if (StrUtil.isBlank(name)) {
|
||||
return;
|
||||
}
|
||||
DiyTemplateDO template = diyTemplateMapper.selectByName(name);
|
||||
if (template == null) {
|
||||
return;
|
||||
}
|
||||
// 如果 id 为空,说明不用比较是否为相同 id 的模板
|
||||
if (id == null) {
|
||||
throw exception(DIY_TEMPLATE_NAME_USED, name);
|
||||
}
|
||||
if (!template.getId().equals(id)) {
|
||||
throw exception(DIY_TEMPLATE_NAME_USED, name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteDiyTemplate(Long id) {
|
||||
// 校验存在
|
||||
@@ -79,18 +122,47 @@ public class DiyTemplateServiceImpl implements DiyTemplateService {
|
||||
}
|
||||
|
||||
@Override
|
||||
// TODO @疯狂:事务;
|
||||
public void useDiyTemplate(Long id) {
|
||||
// 校验存在
|
||||
validateDiyTemplateExists(id);
|
||||
// TODO @疯狂:要不已使用的情况,抛个业务异常?
|
||||
// 已使用的更新为未使用
|
||||
DiyTemplateDO used = diyTemplateMapper.selectByUsed(true);
|
||||
if (used != null) {
|
||||
// 如果 id 相同,说明未发生变化
|
||||
if (used.getId().equals(id)) {
|
||||
return;
|
||||
}
|
||||
this.updateUsed(used.getId(), false, null);
|
||||
}
|
||||
// 更新为已使用
|
||||
this.updateUsed(id, true, LocalDateTime.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateDiyTemplateProperty(DiyTemplatePropertyUpdateRequestVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateDiyTemplateExists(updateReqVO.getId());
|
||||
// 更新模板属性
|
||||
DiyTemplateDO updateObj = DiyTemplateConvert.INSTANCE.convert(updateReqVO);
|
||||
diyTemplateMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiyTemplateDO getUsedDiyTemplate() {
|
||||
return diyTemplateMapper.selectByUsed(true);
|
||||
}
|
||||
|
||||
// TODO @疯狂:挪到 useDiyTemplate 下面,改名 updateTemplateUsed 会不会好点哈;
|
||||
/**
|
||||
* 更新模板是否使用
|
||||
*
|
||||
* @param id 模板编号
|
||||
* @param used 是否使用
|
||||
* @param usedTime 使用时间
|
||||
*/
|
||||
private void updateUsed(Long id, Boolean used, LocalDateTime usedTime) {
|
||||
DiyTemplateDO updateObj = new DiyTemplateDO().setId(id)
|
||||
.setUsed(used).setUsedTime(usedTime);
|
||||
|
@@ -1,23 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.price;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 价格计算 Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface PriceService {
|
||||
|
||||
/**
|
||||
* 获得优惠劵的匹配信息列表
|
||||
*
|
||||
* @param calculateReqDTO 价格请求
|
||||
* @return 价格响应
|
||||
*/
|
||||
List<CouponMeetRespDTO> getMeetCouponList(PriceCalculateReqDTO calculateReqDTO);
|
||||
|
||||
}
|
@@ -1,96 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.price;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.price.PriceConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_VALID_TIME_NOT_NOW;
|
||||
|
||||
/**
|
||||
* 价格计算 Service 实现类
|
||||
*
|
||||
* 优惠计算顺序:min(限时折扣, 会员折扣) > 满减送 > 优惠券。
|
||||
* 参考文档:
|
||||
* 1. <a href="https://help.youzan.com/displaylist/detail_4_4-1-60384">有赞文档:限时折扣、满减送、优惠券哪个优先计算?</a>
|
||||
*
|
||||
* TODO 芋艿:进一步完善
|
||||
* 1. 限时折扣:指定金额、减免金额、折扣
|
||||
* 2. 满减送:循环、折扣
|
||||
* 3. 优惠劵:待定
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class PriceServiceImpl implements PriceService {
|
||||
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
|
||||
@Override
|
||||
public List<CouponMeetRespDTO> getMeetCouponList(PriceCalculateReqDTO calculateReqDTO) {
|
||||
// 先计算一轮价格
|
||||
// PriceCalculateRespDTO priceCalculate = calculatePrice(calculateReqDTO);
|
||||
PriceCalculateRespDTO priceCalculate = null;
|
||||
|
||||
// 获得用户的待使用优惠劵
|
||||
List<CouponDO> couponList = couponService.getCouponList(calculateReqDTO.getUserId(), CouponStatusEnum.UNUSED.getStatus());
|
||||
if (CollUtil.isEmpty(couponList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 获得优惠劵的匹配信息
|
||||
return CollectionUtils.convertList(couponList, coupon -> {
|
||||
CouponMeetRespDTO couponMeetRespDTO = PriceConvert.INSTANCE.convert(coupon);
|
||||
try {
|
||||
// 校验优惠劵
|
||||
couponService.validCoupon(coupon);
|
||||
|
||||
// 获得匹配的商品 SKU 数组
|
||||
// TODO 芋艿:后续处理
|
||||
// List<PriceCalculateRespDTO.OrderItem> orderItems = getMatchCouponOrderItems(priceCalculate, coupon);
|
||||
List<PriceCalculateRespDTO.OrderItem> orderItems = null;
|
||||
if (CollUtil.isEmpty(orderItems)) {
|
||||
return couponMeetRespDTO.setMeet(false).setMeetTip("所结算商品没有符合条件的商品");
|
||||
}
|
||||
|
||||
// 计算是否满足优惠劵的使用金额
|
||||
Integer originPrice = getSumValue(orderItems, PriceCalculateRespDTO.OrderItem::getOrderDividePrice, Integer::sum);
|
||||
assert originPrice != null;
|
||||
if (originPrice < coupon.getUsePrice()) {
|
||||
return couponMeetRespDTO.setMeet(false)
|
||||
// .setMeetTip(String.format("差 %s 元可用优惠劵", formatPrice(coupon.getUsePrice() - originPrice)));
|
||||
.setMeetTip("所结算的商品中未满足使用的金额");
|
||||
}
|
||||
} catch (ServiceException serviceException) {
|
||||
couponMeetRespDTO.setMeet(false);
|
||||
if (serviceException.getCode().equals(COUPON_VALID_TIME_NOT_NOW.getCode())) {
|
||||
couponMeetRespDTO.setMeetTip("优惠劵未到使用时间");
|
||||
} else {
|
||||
log.error("[getMeetCouponList][calculateReqDTO({}) 获得优惠劵匹配信息异常]", calculateReqDTO, serviceException);
|
||||
couponMeetRespDTO.setMeetTip("优惠劵不满足使用条件");
|
||||
}
|
||||
return couponMeetRespDTO;
|
||||
}
|
||||
// 满足
|
||||
return couponMeetRespDTO.setMeet(true);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@@ -123,8 +123,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
|
||||
}
|
||||
|
||||
// 2. 校验商品 sku 都存在
|
||||
Map<Long, ProductSkuRespDTO> skuMap = convertMap(productSkuApi.getSkuListBySpuId(singletonList(spuId)),
|
||||
ProductSkuRespDTO::getId);
|
||||
List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(singletonList(spuId));
|
||||
Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
|
||||
products.forEach(product -> {
|
||||
if (!skuMap.containsKey(product.getSkuId())) {
|
||||
throw exception(SKU_NOT_EXISTS);
|
||||
|
@@ -138,7 +138,7 @@ public class DiscountActivityServiceImplTest extends BaseDbUnitTest {
|
||||
Long id = dbDiscountActivity.getId();
|
||||
|
||||
// 调用
|
||||
discountActivityService.closeRewardActivity(id);
|
||||
discountActivityService.closeDiscountActivity(id);
|
||||
// 校验状态
|
||||
DiscountActivityDO discountActivity = discountActivityMapper.selectById(id);
|
||||
assertEquals(discountActivity.getStatus(), PromotionActivityStatusEnum.CLOSE.getStatus());
|
||||
|
@@ -1,104 +0,0 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.price;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.CouponMeetRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.service.coupon.CouponService;
|
||||
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_VALID_TIME_NOT_NOW;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* {@link PriceServiceImpl} 的单元测试
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class PriceServiceTest extends BaseMockitoUnitTest {
|
||||
|
||||
@InjectMocks
|
||||
private PriceServiceImpl priceService;
|
||||
|
||||
@Mock
|
||||
private RewardActivityService rewardActivityService;
|
||||
@Mock
|
||||
private CouponService couponService;
|
||||
@Mock
|
||||
private ProductSkuApi productSkuApi;
|
||||
|
||||
/**
|
||||
* 测试满减送活动,不匹配的情况
|
||||
*/
|
||||
@Test
|
||||
public void testCalculatePrice_rewardActivityNotMeet() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMeetCouponList() {
|
||||
// 准备参数
|
||||
PriceCalculateReqDTO calculateReqDTO = new PriceCalculateReqDTO().setUserId(1024L)
|
||||
.setItems(singletonList(new PriceCalculateReqDTO.Item().setSkuId(10L).setCount(2)));
|
||||
// mock 方法(商品 SKU 信息)
|
||||
ProductSkuRespDTO productSku = randomPojo(ProductSkuRespDTO.class, o -> o.setId(10L).setPrice(100));
|
||||
when(productSkuApi.getSkuList(eq(asSet(10L)))).thenReturn(singletonList(productSku));
|
||||
// mock 方法(情况一:优惠劵未到使用时间)
|
||||
CouponDO coupon01 = randomPojo(CouponDO.class);
|
||||
doThrow(new ServiceException(COUPON_VALID_TIME_NOT_NOW)).when(couponService).validCoupon(coupon01);
|
||||
// mock 方法(情况二:所结算商品没有符合条件的商品)
|
||||
CouponDO coupon02 = randomPojo(CouponDO.class);
|
||||
// mock 方法(情况三:使用金额不足)
|
||||
CouponDO coupon03 = randomPojo(CouponDO.class, o -> o.setProductScope(PromotionProductScopeEnum.ALL.getScope())
|
||||
.setUsePrice(300));
|
||||
// mock 方法(情况五:满足条件)
|
||||
CouponDO coupon04 = randomPojo(CouponDO.class, o -> o.setProductScope(PromotionProductScopeEnum.ALL.getScope())
|
||||
.setUsePrice(190));
|
||||
// mock 方法(获得用户的待使用优惠劵)
|
||||
when(couponService.getCouponList(eq(1024L), eq(CouponStatusEnum.UNUSED.getStatus())))
|
||||
.thenReturn(asList(coupon01, coupon02, coupon03, coupon04));
|
||||
// 调用
|
||||
List<CouponMeetRespDTO> list = priceService.getMeetCouponList(calculateReqDTO);
|
||||
// 断言
|
||||
assertEquals(list.size(), 4);
|
||||
// 断言情况一:优惠劵未到使用时间
|
||||
CouponMeetRespDTO couponMeetRespDTO01 = list.get(0);
|
||||
assertPojoEquals(couponMeetRespDTO01, coupon01);
|
||||
assertFalse(couponMeetRespDTO01.getMeet());
|
||||
assertEquals(couponMeetRespDTO01.getMeetTip(), "优惠劵未到使用时间");
|
||||
// 断言情况二:所结算商品没有符合条件的商品
|
||||
CouponMeetRespDTO couponMeetRespDTO02 = list.get(1);
|
||||
assertPojoEquals(couponMeetRespDTO02, coupon02);
|
||||
assertFalse(couponMeetRespDTO02.getMeet());
|
||||
assertEquals(couponMeetRespDTO02.getMeetTip(), "所结算商品没有符合条件的商品");
|
||||
// 断言情况三:差 %s 元可用优惠劵
|
||||
CouponMeetRespDTO couponMeetRespDTO03 = list.get(2);
|
||||
assertPojoEquals(couponMeetRespDTO03, coupon03);
|
||||
assertFalse(couponMeetRespDTO03.getMeet());
|
||||
assertEquals(couponMeetRespDTO03.getMeetTip(), "所结算的商品中未满足使用的金额");
|
||||
// 断言情况四:满足条件
|
||||
CouponMeetRespDTO couponMeetRespDTO04 = list.get(3);
|
||||
assertPojoEquals(couponMeetRespDTO04, coupon04);
|
||||
assertTrue(couponMeetRespDTO04.getMeet());
|
||||
assertNull(couponMeetRespDTO04.getMeetTip());
|
||||
}
|
||||
|
||||
}
|
@@ -58,7 +58,6 @@
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.yudao.module.statistics.dal.dataobject.member;
|
||||
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -23,7 +23,7 @@ import java.time.LocalDateTime;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MemberStatisticsDO extends TenantBaseDO {
|
||||
public class MemberStatisticsDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.yudao.module.statistics.dal.dataobject.trade;
|
||||
|
||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
@@ -23,7 +23,7 @@ import java.time.LocalDateTime;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class TradeStatisticsDO extends TenantBaseDO {
|
||||
public class TradeStatisticsDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 编号,主键自增
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package cn.iocoder.yudao.module.statistics.service.pay;
|
||||
|
||||
import cn.iocoder.yudao.module.pay.enums.member.PayWalletBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||
import cn.iocoder.yudao.module.statistics.dal.mysql.pay.PayWalletStatisticsMapper;
|
||||
|
@@ -77,6 +77,7 @@ public class BrokerageUserController {
|
||||
@PreAuthorize("@ss.hasPermission('trade:brokerage-user:query')")
|
||||
public CommonResult<BrokerageUserRespVO> getBrokerageUser(@RequestParam("id") Long id) {
|
||||
BrokerageUserDO brokerageUser = brokerageUserService.getBrokerageUser(id);
|
||||
// TODO @疯狂:是不是搞成一个统一的 convert?
|
||||
BrokerageUserRespVO respVO = BrokerageUserConvert.INSTANCE.convert(brokerageUser);
|
||||
return success(BrokerageUserConvert.INSTANCE.copyTo(memberUserApi.getUser(id), respVO));
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
|
||||
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
|
||||
import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.enums.DictTypeConstants;
|
||||
@@ -241,7 +241,7 @@ public interface TradeOrderConvert {
|
||||
return reqBO;
|
||||
}
|
||||
|
||||
default AppTradeOrderSettlementRespVO convert(TradePriceCalculateRespBO calculate, AddressRespDTO address) {
|
||||
default AppTradeOrderSettlementRespVO convert(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address) {
|
||||
AppTradeOrderSettlementRespVO respVO = convert0(calculate, address);
|
||||
if (address != null) {
|
||||
respVO.getAddress().setAreaName(AreaUtils.format(address.getAreaId()));
|
||||
@@ -249,7 +249,7 @@ public interface TradeOrderConvert {
|
||||
return respVO;
|
||||
}
|
||||
|
||||
AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, AddressRespDTO address);
|
||||
AppTradeOrderSettlementRespVO convert0(TradePriceCalculateRespBO calculate, MemberAddressRespDTO address);
|
||||
|
||||
List<AppOrderExpressTrackRespDTO> convertList02(List<ExpressTrackRespDTO> list);
|
||||
|
||||
|
@@ -232,7 +232,8 @@ public class BrokerageUserServiceImpl implements BrokerageUserService {
|
||||
return PageResult.empty();
|
||||
}
|
||||
// 1.2 根据昵称过滤下级用户
|
||||
Map<Long, MemberUserRespDTO> userMap = convertMapByFilter(memberUserApi.getUserList(childIds),
|
||||
List<MemberUserRespDTO> users = memberUserApi.getUserList(childIds);
|
||||
Map<Long, MemberUserRespDTO> userMap = convertMapByFilter(users,
|
||||
user -> StrUtil.contains(user.getNickname(), pageReqVO.getNickname()),
|
||||
MemberUserRespDTO::getId);
|
||||
if (CollUtil.isEmpty(userMap)) {
|
||||
|
@@ -11,8 +11,8 @@ import cn.iocoder.yudao.framework.common.core.KeyValue;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||
import cn.iocoder.yudao.module.member.api.address.AddressApi;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
|
||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
|
||||
@@ -98,7 +98,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
@Resource
|
||||
private PayOrderApi payOrderApi;
|
||||
@Resource
|
||||
private AddressApi addressApi;
|
||||
private MemberAddressApi addressApi;
|
||||
@Resource
|
||||
private ProductCommentApi productCommentApi;
|
||||
|
||||
@@ -110,7 +110,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
@Override
|
||||
public AppTradeOrderSettlementRespVO settlementOrder(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) {
|
||||
// 1. 获得收货地址
|
||||
AddressRespDTO address = getAddress(userId, settlementReqVO.getAddressId());
|
||||
MemberAddressRespDTO address = getAddress(userId, settlementReqVO.getAddressId());
|
||||
if (address != null) {
|
||||
settlementReqVO.setAddressId(address.getId());
|
||||
}
|
||||
@@ -129,7 +129,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
* @param addressId 地址编号
|
||||
* @return 地址
|
||||
*/
|
||||
private AddressRespDTO getAddress(Long userId, Long addressId) {
|
||||
private MemberAddressRespDTO getAddress(Long userId, Long addressId) {
|
||||
if (addressId != null) {
|
||||
return addressApi.getAddress(addressId, userId);
|
||||
}
|
||||
@@ -193,7 +193,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
// 物流信息
|
||||
order.setDeliveryType(createReqVO.getDeliveryType());
|
||||
if (Objects.equals(createReqVO.getDeliveryType(), DeliveryTypeEnum.EXPRESS.getType())) {
|
||||
AddressRespDTO address = addressApi.getAddress(createReqVO.getAddressId(), userId);
|
||||
MemberAddressRespDTO address = addressApi.getAddress(createReqVO.getAddressId(), userId);
|
||||
Assert.notNull(address, "地址({}) 不能为空", createReqVO.getAddressId()); // 价格计算时,已经计算
|
||||
order.setReceiverName(address.getName()).setReceiverMobile(address.getMobile())
|
||||
.setReceiverAreaId(address.getAreaId()).setReceiverDetailAddress(address.getDetailAddress());
|
||||
|
@@ -4,8 +4,8 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.module.member.api.address.AddressApi;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.delivery.DeliveryPickUpStoreDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
|
||||
@@ -41,7 +41,7 @@ import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
||||
public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
|
||||
|
||||
@Resource
|
||||
private AddressApi addressApi;
|
||||
private MemberAddressApi addressApi;
|
||||
|
||||
@Resource
|
||||
private DeliveryPickUpStoreService deliveryPickUpStoreService;
|
||||
@@ -81,7 +81,7 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
|
||||
// 价格计算时,如果为空就不算~最终下单,会校验该字段不允许空
|
||||
return;
|
||||
}
|
||||
AddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
|
||||
MemberAddressRespDTO address = addressApi.getAddress(param.getAddressId(), param.getUserId());
|
||||
Assert.notNull(address, "收件人({})的地址,不能为空", param.getUserId());
|
||||
|
||||
// 情况一:全局包邮
|
||||
|
@@ -1,32 +1,19 @@
|
||||
package cn.iocoder.yudao.module.trade.service.order;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.TerminalEnum;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.member.api.address.AddressApi;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
|
||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.product.api.property.dto.ProductPropertyValueDetailRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
|
||||
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
|
||||
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderItemAfterSaleStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
|
||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -36,17 +23,11 @@ import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
@@ -72,12 +53,12 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
|
||||
private ProductSpuApi productSpuApi;
|
||||
@MockBean
|
||||
private ProductSkuApi productSkuApi;
|
||||
@MockBean
|
||||
private PriceApi priceApi;
|
||||
// @MockBean
|
||||
// private PriceApi priceApi;
|
||||
@MockBean
|
||||
private PayOrderApi payOrderApi;
|
||||
@MockBean
|
||||
private AddressApi addressApi;
|
||||
private MemberAddressApi addressApi;
|
||||
@MockBean
|
||||
private CouponApi couponApi;
|
||||
|
||||
@@ -90,159 +71,159 @@ public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
|
||||
when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTradeOrder_success() {
|
||||
// 准备参数
|
||||
Long userId = 100L;
|
||||
String userIp = "127.0.0.1";
|
||||
// AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO()
|
||||
// .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true)
|
||||
// .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3),
|
||||
// new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4)));
|
||||
AppTradeOrderCreateReqVO reqVO = null;
|
||||
// TODO 芋艿:重新高下
|
||||
// mock 方法(商品 SKU 检查)
|
||||
ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L)
|
||||
.setPrice(50).setStock(100)
|
||||
.setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(111L).setValueId(222L))));
|
||||
ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L)
|
||||
.setPrice(20).setStock(50))
|
||||
.setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(333L).setValueId(444L)));
|
||||
when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02));
|
||||
// mock 方法(商品 SPU 检查)
|
||||
ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L)
|
||||
.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()).setName("商品 1"));
|
||||
ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L)
|
||||
.setStatus(ProductSpuStatusEnum.ENABLE.getStatus()));
|
||||
when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02));
|
||||
// mock 方法(用户收件地址的校验)
|
||||
AddressRespDTO addressRespDTO = new AddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")
|
||||
.setMobile("15601691300").setAreaId(3306).setDetailAddress("土豆村");
|
||||
when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO);
|
||||
// mock 方法(价格计算)
|
||||
PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem()
|
||||
.setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50)
|
||||
.setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35);
|
||||
PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem()
|
||||
.setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20)
|
||||
.setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25);
|
||||
PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order()
|
||||
.setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30)
|
||||
.setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30)
|
||||
.setItems(Arrays.asList(priceOrderItem01, priceOrderItem02));
|
||||
when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> {
|
||||
assertEquals(priceCalculateReqDTO.getUserId(), 100L);
|
||||
assertEquals(priceCalculateReqDTO.getCouponId(), 101L);
|
||||
assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L);
|
||||
assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3);
|
||||
assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L);
|
||||
assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4);
|
||||
return true;
|
||||
}))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder));
|
||||
// mock 方法(创建支付单)
|
||||
when(payOrderApi.createOrder(argThat(createReqDTO -> {
|
||||
assertEquals(createReqDTO.getAppId(), 888L);
|
||||
assertEquals(createReqDTO.getUserIp(), userIp);
|
||||
assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空
|
||||
assertEquals(createReqDTO.getSubject(), "商品 1 等多件");
|
||||
assertNull(createReqDTO.getBody());
|
||||
assertEquals(createReqDTO.getPrice(), 80);
|
||||
assertNotNull(createReqDTO.getExpireTime());
|
||||
return true;
|
||||
}))).thenReturn(1000L);
|
||||
|
||||
// 调用方法
|
||||
TradeOrderDO order = tradeOrderUpdateService.createOrder(userId, userIp, reqVO, null);
|
||||
// 断言 TradeOrderDO 订单
|
||||
List<TradeOrderDO> tradeOrderDOs = tradeOrderMapper.selectList();
|
||||
assertEquals(tradeOrderDOs.size(), 1);
|
||||
TradeOrderDO tradeOrderDO = tradeOrderDOs.get(0);
|
||||
assertEquals(tradeOrderDO.getId(), order.getId());
|
||||
assertNotNull(tradeOrderDO.getNo());
|
||||
assertEquals(tradeOrderDO.getType(), TradeOrderTypeEnum.NORMAL.getType());
|
||||
assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal());
|
||||
assertEquals(tradeOrderDO.getUserId(), userId);
|
||||
assertEquals(tradeOrderDO.getUserIp(), userIp);
|
||||
assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus());
|
||||
assertEquals(tradeOrderDO.getProductCount(), 7);
|
||||
assertNull(tradeOrderDO.getFinishTime());
|
||||
assertNull(tradeOrderDO.getCancelTime());
|
||||
assertNull(tradeOrderDO.getCancelType());
|
||||
assertEquals(tradeOrderDO.getUserRemark(), "我是备注");
|
||||
assertNull(tradeOrderDO.getRemark());
|
||||
assertFalse(tradeOrderDO.getPayStatus());
|
||||
assertNull(tradeOrderDO.getPayTime());
|
||||
assertEquals(tradeOrderDO.getTotalPrice(), 230);
|
||||
assertEquals(tradeOrderDO.getDiscountPrice(), 0);
|
||||
assertEquals(tradeOrderDO.getAdjustPrice(), 0);
|
||||
assertEquals(tradeOrderDO.getPayPrice(), 80);
|
||||
assertEquals(tradeOrderDO.getPayOrderId(), 1000L);
|
||||
assertNull(tradeOrderDO.getPayChannelCode());
|
||||
assertNull(tradeOrderDO.getLogisticsId());
|
||||
assertNull(tradeOrderDO.getDeliveryTime());
|
||||
assertNull(tradeOrderDO.getReceiveTime());
|
||||
assertEquals(tradeOrderDO.getReceiverName(), "芋艿");
|
||||
assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300");
|
||||
assertEquals(tradeOrderDO.getReceiverAreaId(), 3306);
|
||||
assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村");
|
||||
assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus());
|
||||
assertEquals(tradeOrderDO.getRefundPrice(), 0);
|
||||
assertEquals(tradeOrderDO.getCouponPrice(), 30);
|
||||
assertEquals(tradeOrderDO.getPointPrice(), 10);
|
||||
// 断言 TradeOrderItemDO 订单(第 1 个)
|
||||
List<TradeOrderItemDO> tradeOrderItemDOs = tradeOrderItemMapper.selectList();
|
||||
assertEquals(tradeOrderItemDOs.size(), 2);
|
||||
TradeOrderItemDO tradeOrderItemDO01 = tradeOrderItemDOs.get(0);
|
||||
assertNotNull(tradeOrderItemDO01.getId());
|
||||
assertEquals(tradeOrderItemDO01.getUserId(), userId);
|
||||
assertEquals(tradeOrderItemDO01.getOrderId(), order.getId());
|
||||
assertEquals(tradeOrderItemDO01.getSpuId(), 11L);
|
||||
assertEquals(tradeOrderItemDO01.getSkuId(), 1L);
|
||||
assertEquals(tradeOrderItemDO01.getProperties().size(), 1);
|
||||
assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L);
|
||||
assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L);
|
||||
//assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); TODO 找不到spuName
|
||||
assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl());
|
||||
assertEquals(tradeOrderItemDO01.getCount(), 3);
|
||||
// assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150);
|
||||
assertEquals(tradeOrderItemDO01.getPrice(), 50);
|
||||
assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20);
|
||||
assertEquals(tradeOrderItemDO01.getPayPrice(), 130);
|
||||
assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
|
||||
// 断言 TradeOrderItemDO 订单(第 2 个)
|
||||
TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1);
|
||||
assertNotNull(tradeOrderItemDO02.getId());
|
||||
assertEquals(tradeOrderItemDO02.getUserId(), userId);
|
||||
assertEquals(tradeOrderItemDO02.getOrderId(), order.getId());
|
||||
assertEquals(tradeOrderItemDO02.getSpuId(), 21L);
|
||||
assertEquals(tradeOrderItemDO02.getSkuId(), 2L);
|
||||
assertEquals(tradeOrderItemDO02.getProperties().size(), 1);
|
||||
assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L);
|
||||
assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L);
|
||||
//assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); TODO 找不到spuName
|
||||
assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl());
|
||||
assertEquals(tradeOrderItemDO02.getCount(), 4);
|
||||
// assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80);
|
||||
assertEquals(tradeOrderItemDO02.getPrice(), 20);
|
||||
assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40);
|
||||
assertEquals(tradeOrderItemDO02.getPayPrice(), 40);
|
||||
assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
|
||||
// 校验调用
|
||||
verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> {
|
||||
assertEquals(updateStockReqDTO.getItems().size(), 2);
|
||||
assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L);
|
||||
assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3);
|
||||
assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L);
|
||||
assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4);
|
||||
return true;
|
||||
}));
|
||||
verify(couponApi).useCoupon(argThat(reqDTO -> {
|
||||
assertEquals(reqDTO.getId(), reqVO.getCouponId());
|
||||
assertEquals(reqDTO.getUserId(), userId);
|
||||
assertEquals(reqDTO.getOrderId(), order.getId());
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
// @Test
|
||||
// public void testCreateTradeOrder_success() {
|
||||
// // 准备参数
|
||||
// Long userId = 100L;
|
||||
// String userIp = "127.0.0.1";
|
||||
//// AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO()
|
||||
//// .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true)
|
||||
//// .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3),
|
||||
//// new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4)));
|
||||
// AppTradeOrderCreateReqVO reqVO = null;
|
||||
// // TODO 芋艿:重新高下
|
||||
// // mock 方法(商品 SKU 检查)
|
||||
// ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L)
|
||||
// .setPrice(50).setStock(100)
|
||||
// .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(111L).setValueId(222L))));
|
||||
// ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L)
|
||||
// .setPrice(20).setStock(50))
|
||||
// .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(333L).setValueId(444L)));
|
||||
// when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02));
|
||||
// // mock 方法(商品 SPU 检查)
|
||||
// ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L)
|
||||
// .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()).setName("商品 1"));
|
||||
// ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L)
|
||||
// .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()));
|
||||
// when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02));
|
||||
// // mock 方法(用户收件地址的校验)
|
||||
// MemberAddressRespDTO addressRespDTO = new MemberAddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")
|
||||
// .setMobile("15601691300").setAreaId(3306).setDetailAddress("土豆村");
|
||||
// when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO);
|
||||
// // mock 方法(价格计算)
|
||||
// PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem()
|
||||
// .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50)
|
||||
// .setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35);
|
||||
// PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem()
|
||||
// .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20)
|
||||
// .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25);
|
||||
// PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order()
|
||||
// .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30)
|
||||
// .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30)
|
||||
// .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02));
|
||||
// when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> {
|
||||
// assertEquals(priceCalculateReqDTO.getUserId(), 100L);
|
||||
// assertEquals(priceCalculateReqDTO.getCouponId(), 101L);
|
||||
// assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L);
|
||||
// assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3);
|
||||
// assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L);
|
||||
// assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4);
|
||||
// return true;
|
||||
// }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder));
|
||||
// // mock 方法(创建支付单)
|
||||
// when(payOrderApi.createOrder(argThat(createReqDTO -> {
|
||||
// assertEquals(createReqDTO.getAppId(), 888L);
|
||||
// assertEquals(createReqDTO.getUserIp(), userIp);
|
||||
// assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空
|
||||
// assertEquals(createReqDTO.getSubject(), "商品 1 等多件");
|
||||
// assertNull(createReqDTO.getBody());
|
||||
// assertEquals(createReqDTO.getPrice(), 80);
|
||||
// assertNotNull(createReqDTO.getExpireTime());
|
||||
// return true;
|
||||
// }))).thenReturn(1000L);
|
||||
//
|
||||
// // 调用方法
|
||||
// TradeOrderDO order = tradeOrderUpdateService.createOrder(userId, userIp, reqVO, null);
|
||||
// // 断言 TradeOrderDO 订单
|
||||
// List<TradeOrderDO> tradeOrderDOs = tradeOrderMapper.selectList();
|
||||
// assertEquals(tradeOrderDOs.size(), 1);
|
||||
// TradeOrderDO tradeOrderDO = tradeOrderDOs.get(0);
|
||||
// assertEquals(tradeOrderDO.getId(), order.getId());
|
||||
// assertNotNull(tradeOrderDO.getNo());
|
||||
// assertEquals(tradeOrderDO.getType(), TradeOrderTypeEnum.NORMAL.getType());
|
||||
// assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal());
|
||||
// assertEquals(tradeOrderDO.getUserId(), userId);
|
||||
// assertEquals(tradeOrderDO.getUserIp(), userIp);
|
||||
// assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus());
|
||||
// assertEquals(tradeOrderDO.getProductCount(), 7);
|
||||
// assertNull(tradeOrderDO.getFinishTime());
|
||||
// assertNull(tradeOrderDO.getCancelTime());
|
||||
// assertNull(tradeOrderDO.getCancelType());
|
||||
// assertEquals(tradeOrderDO.getUserRemark(), "我是备注");
|
||||
// assertNull(tradeOrderDO.getRemark());
|
||||
// assertFalse(tradeOrderDO.getPayStatus());
|
||||
// assertNull(tradeOrderDO.getPayTime());
|
||||
// assertEquals(tradeOrderDO.getTotalPrice(), 230);
|
||||
// assertEquals(tradeOrderDO.getDiscountPrice(), 0);
|
||||
// assertEquals(tradeOrderDO.getAdjustPrice(), 0);
|
||||
// assertEquals(tradeOrderDO.getPayPrice(), 80);
|
||||
// assertEquals(tradeOrderDO.getPayOrderId(), 1000L);
|
||||
// assertNull(tradeOrderDO.getPayChannelCode());
|
||||
// assertNull(tradeOrderDO.getLogisticsId());
|
||||
// assertNull(tradeOrderDO.getDeliveryTime());
|
||||
// assertNull(tradeOrderDO.getReceiveTime());
|
||||
// assertEquals(tradeOrderDO.getReceiverName(), "芋艿");
|
||||
// assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300");
|
||||
// assertEquals(tradeOrderDO.getReceiverAreaId(), 3306);
|
||||
// assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村");
|
||||
// assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus());
|
||||
// assertEquals(tradeOrderDO.getRefundPrice(), 0);
|
||||
// assertEquals(tradeOrderDO.getCouponPrice(), 30);
|
||||
// assertEquals(tradeOrderDO.getPointPrice(), 10);
|
||||
// // 断言 TradeOrderItemDO 订单(第 1 个)
|
||||
// List<TradeOrderItemDO> tradeOrderItemDOs = tradeOrderItemMapper.selectList();
|
||||
// assertEquals(tradeOrderItemDOs.size(), 2);
|
||||
// TradeOrderItemDO tradeOrderItemDO01 = tradeOrderItemDOs.get(0);
|
||||
// assertNotNull(tradeOrderItemDO01.getId());
|
||||
// assertEquals(tradeOrderItemDO01.getUserId(), userId);
|
||||
// assertEquals(tradeOrderItemDO01.getOrderId(), order.getId());
|
||||
// assertEquals(tradeOrderItemDO01.getSpuId(), 11L);
|
||||
// assertEquals(tradeOrderItemDO01.getSkuId(), 1L);
|
||||
// assertEquals(tradeOrderItemDO01.getProperties().size(), 1);
|
||||
// assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L);
|
||||
// assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L);
|
||||
// //assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); TODO 找不到spuName
|
||||
// assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl());
|
||||
// assertEquals(tradeOrderItemDO01.getCount(), 3);
|
||||
//// assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150);
|
||||
// assertEquals(tradeOrderItemDO01.getPrice(), 50);
|
||||
// assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20);
|
||||
// assertEquals(tradeOrderItemDO01.getPayPrice(), 130);
|
||||
// assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
|
||||
// // 断言 TradeOrderItemDO 订单(第 2 个)
|
||||
// TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1);
|
||||
// assertNotNull(tradeOrderItemDO02.getId());
|
||||
// assertEquals(tradeOrderItemDO02.getUserId(), userId);
|
||||
// assertEquals(tradeOrderItemDO02.getOrderId(), order.getId());
|
||||
// assertEquals(tradeOrderItemDO02.getSpuId(), 21L);
|
||||
// assertEquals(tradeOrderItemDO02.getSkuId(), 2L);
|
||||
// assertEquals(tradeOrderItemDO02.getProperties().size(), 1);
|
||||
// assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L);
|
||||
// assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L);
|
||||
// //assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); TODO 找不到spuName
|
||||
// assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl());
|
||||
// assertEquals(tradeOrderItemDO02.getCount(), 4);
|
||||
//// assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80);
|
||||
// assertEquals(tradeOrderItemDO02.getPrice(), 20);
|
||||
// assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40);
|
||||
// assertEquals(tradeOrderItemDO02.getPayPrice(), 40);
|
||||
// assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
|
||||
// // 校验调用
|
||||
// verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> {
|
||||
// assertEquals(updateStockReqDTO.getItems().size(), 2);
|
||||
// assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L);
|
||||
// assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3);
|
||||
// assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L);
|
||||
// assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4);
|
||||
// return true;
|
||||
// }));
|
||||
// verify(couponApi).useCoupon(argThat(reqDTO -> {
|
||||
// assertEquals(reqDTO.getId(), reqVO.getCouponId());
|
||||
// assertEquals(reqDTO.getUserId(), userId);
|
||||
// assertEquals(reqDTO.getOrderId(), order.getId());
|
||||
// return true;
|
||||
// }));
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testUpdateOrderPaid() {
|
||||
|
@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.trade.service.price.calculator;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.yudao.module.member.api.address.AddressApi;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
|
||||
import cn.iocoder.yudao.module.member.api.address.dto.MemberAddressRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryExpressChargeModeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
||||
@@ -38,7 +38,7 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
|
||||
private TradeDeliveryPriceCalculator calculator;
|
||||
|
||||
@Mock
|
||||
private AddressApi addressApi;
|
||||
private MemberAddressApi addressApi;
|
||||
|
||||
@Mock
|
||||
private DeliveryExpressTemplateService deliveryExpressTemplateService;
|
||||
@@ -80,7 +80,7 @@ public class TradeDeliveryPriceCalculatorTest extends BaseMockitoUnitTest {
|
||||
TradePriceCalculatorHelper.recountAllPrice(resultBO);
|
||||
|
||||
// 准备收件地址数据
|
||||
AddressRespDTO addressResp = randomPojo(AddressRespDTO.class, item -> item.setAreaId(10));
|
||||
MemberAddressRespDTO addressResp = randomPojo(MemberAddressRespDTO.class, item -> item.setAreaId(10));
|
||||
when(addressApi.getAddress(eq(10L), eq(1L))).thenReturn(addressResp);
|
||||
|
||||
// 准备运费模板费用配置数据
|
||||
|
Reference in New Issue
Block a user