Compare commits
8 Commits
v2.2.0(jdk
...
add-delive
Author | SHA1 | Date | |
---|---|---|---|
![]() |
224b4a0833 | ||
![]() |
ce610131f4 | ||
![]() |
fd42e1711d | ||
![]() |
7ba3b12313 | ||
![]() |
8c2b8ed894 | ||
![]() |
55fec9e8ef | ||
![]() |
760b4c147d | ||
![]() |
08e1c69d10 |
@@ -3,11 +3,15 @@ package cn.iocoder.yudao.framework.common.util.spring;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.springframework.context.expression.BeanFactoryResolver;
|
||||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||||
import org.springframework.core.ParameterNameDiscoverer;
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
import org.springframework.expression.EvaluationContext;
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.ExpressionParser;
|
import org.springframework.expression.ExpressionParser;
|
||||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
@@ -86,4 +90,20 @@ public class SpringExpressionUtils {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 Bean 工厂,解析 EL 表达式的结果
|
||||||
|
*
|
||||||
|
* @param expressionString EL 表达式
|
||||||
|
* @return 执行界面
|
||||||
|
*/
|
||||||
|
public static Object parseExpression(String expressionString) {
|
||||||
|
if (StrUtil.isBlank(expressionString)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Expression expression = EXPRESSION_PARSER.parseExpression(expressionString);
|
||||||
|
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||||
|
context.setBeanResolver(new BeanFactoryResolver(SpringUtil.getApplicationContext()));
|
||||||
|
return expression.getValue(context);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -185,10 +185,6 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
|
|||||||
return Db.updateBatchById(entities, size);
|
return Db.updateBatchById(entities, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean insertOrUpdate(T entity) {
|
|
||||||
return Db.saveOrUpdate(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
default Boolean insertOrUpdateBatch(Collection<T> collection) {
|
default Boolean insertOrUpdateBatch(Collection<T> collection) {
|
||||||
return Db.saveOrUpdateBatch(collection);
|
return Db.saveOrUpdateBatch(collection);
|
||||||
}
|
}
|
||||||
|
@@ -32,6 +32,11 @@
|
|||||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
<scope>provided</scope> <!-- 解决工具类 SpringExpressionUtils 加载的时候访问不到 org.aspectj.lang.JoinPoint 问题 -->
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
package cn.iocoder.yudao.framework.desensitize.core.base.handler;
|
package cn.iocoder.yudao.framework.desensitize.core.base.handler;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,4 +20,21 @@ public interface DesensitizationHandler<T extends Annotation> {
|
|||||||
*/
|
*/
|
||||||
String desensitize(String origin, T annotation);
|
String desensitize(String origin, T annotation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏的 Spring EL 表达式
|
||||||
|
*
|
||||||
|
* 如果返回 true 则跳过脱敏
|
||||||
|
*
|
||||||
|
* @param annotation 注解信息
|
||||||
|
* @return 是否禁用脱敏的 Spring EL 表达式
|
||||||
|
*/
|
||||||
|
default String getDisable(T annotation) {
|
||||||
|
// 约定:默认就是 enable() 属性。如果不符合,子类重写
|
||||||
|
try {
|
||||||
|
return (String) ReflectUtil.invoke(annotation, "disable");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -33,4 +33,12 @@ public @interface EmailDesensitize {
|
|||||||
* 比如:example@gmail.com 脱敏之后为 e****@gmail.com
|
* 比如:example@gmail.com 脱敏之后为 e****@gmail.com
|
||||||
*/
|
*/
|
||||||
String replacer() default "$1****$2";
|
String replacer() default "$1****$2";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -35,4 +35,12 @@ public @interface RegexDesensitize {
|
|||||||
* 脱敏后字符串 ******456789
|
* 脱敏后字符串 ******456789
|
||||||
*/
|
*/
|
||||||
String replacer() default "******";
|
String replacer() default "******";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.framework.desensitize.core.regex.handler;
|
package cn.iocoder.yudao.framework.desensitize.core.regex.handler;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
|
||||||
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
|
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
@@ -14,6 +15,13 @@ public abstract class AbstractRegexDesensitizationHandler<T extends Annotation>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String desensitize(String origin, T annotation) {
|
public String desensitize(String origin, T annotation) {
|
||||||
|
// 1. 判断是否禁用脱敏
|
||||||
|
Object disable = SpringExpressionUtils.parseExpression(getDisable(annotation));
|
||||||
|
if (Boolean.TRUE.equals(disable)) {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 执行脱敏
|
||||||
String regex = getRegex(annotation);
|
String regex = getRegex(annotation);
|
||||||
String replacer = getReplacer(annotation);
|
String replacer = getReplacer(annotation);
|
||||||
return origin.replaceAll(regex, replacer);
|
return origin.replaceAll(regex, replacer);
|
||||||
|
@@ -18,4 +18,10 @@ public class DefaultRegexDesensitizationHandler extends AbstractRegexDesensitiza
|
|||||||
String getReplacer(RegexDesensitize annotation) {
|
String getReplacer(RegexDesensitize annotation) {
|
||||||
return annotation.replacer();
|
return annotation.replacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisable(RegexDesensitize annotation) {
|
||||||
|
return annotation.disable();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,4 +37,11 @@ public @interface BankCardDesensitize {
|
|||||||
*/
|
*/
|
||||||
String replacer() default "*";
|
String replacer() default "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,4 +37,11 @@ public @interface CarLicenseDesensitize {
|
|||||||
*/
|
*/
|
||||||
String replacer() default "*";
|
String replacer() default "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,4 +37,11 @@ public @interface ChineseNameDesensitize {
|
|||||||
*/
|
*/
|
||||||
String replacer() default "*";
|
String replacer() default "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,4 +37,11 @@ public @interface FixedPhoneDesensitize {
|
|||||||
*/
|
*/
|
||||||
String replacer() default "*";
|
String replacer() default "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,4 +37,11 @@ public @interface IdCardDesensitize {
|
|||||||
*/
|
*/
|
||||||
String replacer() default "*";
|
String replacer() default "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,4 +37,11 @@ public @interface MobileDesensitize {
|
|||||||
*/
|
*/
|
||||||
String replacer() default "*";
|
String replacer() default "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -39,4 +39,11 @@ public @interface PasswordDesensitize {
|
|||||||
*/
|
*/
|
||||||
String replacer() default "*";
|
String replacer() default "*";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -40,4 +40,12 @@ public @interface SliderDesensitize {
|
|||||||
* 前缀保留长度
|
* 前缀保留长度
|
||||||
*/
|
*/
|
||||||
int prefixKeep() default 0;
|
int prefixKeep() default 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用脱敏
|
||||||
|
*
|
||||||
|
* 支持 Spring EL 表达式,如果返回 true 则跳过脱敏
|
||||||
|
*/
|
||||||
|
String disable() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.framework.desensitize.core.slider.handler;
|
package cn.iocoder.yudao.framework.desensitize.core.slider.handler;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
|
||||||
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
|
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
@@ -14,6 +15,13 @@ public abstract class AbstractSliderDesensitizationHandler<T extends Annotation>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String desensitize(String origin, T annotation) {
|
public String desensitize(String origin, T annotation) {
|
||||||
|
// 1. 判断是否禁用脱敏
|
||||||
|
Object disable = SpringExpressionUtils.parseExpression(getDisable(annotation));
|
||||||
|
if (Boolean.FALSE.equals(disable)) {
|
||||||
|
return origin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 执行脱敏
|
||||||
int prefixKeep = getPrefixKeep(annotation);
|
int prefixKeep = getPrefixKeep(annotation);
|
||||||
int suffixKeep = getSuffixKeep(annotation);
|
int suffixKeep = getSuffixKeep(annotation);
|
||||||
String replacer = getReplacer(annotation);
|
String replacer = getReplacer(annotation);
|
||||||
|
@@ -24,4 +24,9 @@ public class BankCardDesensitization extends AbstractSliderDesensitizationHandle
|
|||||||
return annotation.replacer();
|
return annotation.replacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisable(BankCardDesensitize annotation) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.CarLicenseD
|
|||||||
* @author gaibu
|
* @author gaibu
|
||||||
*/
|
*/
|
||||||
public class CarLicenseDesensitization extends AbstractSliderDesensitizationHandler<CarLicenseDesensitize> {
|
public class CarLicenseDesensitization extends AbstractSliderDesensitizationHandler<CarLicenseDesensitize> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Integer getPrefixKeep(CarLicenseDesensitize annotation) {
|
Integer getPrefixKeep(CarLicenseDesensitize annotation) {
|
||||||
return annotation.prefixKeep();
|
return annotation.prefixKeep();
|
||||||
@@ -22,4 +23,10 @@ public class CarLicenseDesensitization extends AbstractSliderDesensitizationHand
|
|||||||
String getReplacer(CarLicenseDesensitize annotation) {
|
String getReplacer(CarLicenseDesensitize annotation) {
|
||||||
return annotation.replacer();
|
return annotation.replacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDisable(CarLicenseDesensitize annotation) {
|
||||||
|
return annotation.disable();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.SliderDesen
|
|||||||
* @author gaibu
|
* @author gaibu
|
||||||
*/
|
*/
|
||||||
public class DefaultDesensitizationHandler extends AbstractSliderDesensitizationHandler<SliderDesensitize> {
|
public class DefaultDesensitizationHandler extends AbstractSliderDesensitizationHandler<SliderDesensitize> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Integer getPrefixKeep(SliderDesensitize annotation) {
|
Integer getPrefixKeep(SliderDesensitize annotation) {
|
||||||
return annotation.prefixKeep();
|
return annotation.prefixKeep();
|
||||||
@@ -22,4 +23,5 @@ public class DefaultDesensitizationHandler extends AbstractSliderDesensitization
|
|||||||
String getReplacer(SliderDesensitize annotation) {
|
String getReplacer(SliderDesensitize annotation) {
|
||||||
return annotation.replacer();
|
return annotation.replacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.FixedPhoneD
|
|||||||
* @author gaibu
|
* @author gaibu
|
||||||
*/
|
*/
|
||||||
public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHandler<FixedPhoneDesensitize> {
|
public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHandler<FixedPhoneDesensitize> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Integer getPrefixKeep(FixedPhoneDesensitize annotation) {
|
Integer getPrefixKeep(FixedPhoneDesensitize annotation) {
|
||||||
return annotation.prefixKeep();
|
return annotation.prefixKeep();
|
||||||
@@ -22,4 +23,5 @@ public class FixedPhoneDesensitization extends AbstractSliderDesensitizationHand
|
|||||||
String getReplacer(FixedPhoneDesensitize annotation) {
|
String getReplacer(FixedPhoneDesensitize annotation) {
|
||||||
return annotation.replacer();
|
return annotation.replacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,4 +22,5 @@ public class IdCardDesensitization extends AbstractSliderDesensitizationHandler<
|
|||||||
String getReplacer(IdCardDesensitize annotation) {
|
String getReplacer(IdCardDesensitize annotation) {
|
||||||
return annotation.replacer();
|
return annotation.replacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -23,4 +23,5 @@ public class MobileDesensitization extends AbstractSliderDesensitizationHandler<
|
|||||||
String getReplacer(MobileDesensitize annotation) {
|
String getReplacer(MobileDesensitize annotation) {
|
||||||
return annotation.replacer();
|
return annotation.replacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -22,4 +22,5 @@ public class PasswordDesensitization extends AbstractSliderDesensitizationHandle
|
|||||||
String getReplacer(PasswordDesensitize annotation) {
|
String getReplacer(PasswordDesensitize annotation) {
|
||||||
return annotation.replacer();
|
return annotation.replacer();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,8 @@ package cn.iocoder.yudao.module.product.api.spu.dto;
|
|||||||
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
// TODO @LeeYan9: ProductSpuRespDTO
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品 SPU 信息 Response DTO
|
* 商品 SPU 信息 Response DTO
|
||||||
*
|
*
|
||||||
@@ -76,6 +77,11 @@ public class ProductSpuRespDTO {
|
|||||||
*/
|
*/
|
||||||
private Long deliveryTemplateId;
|
private Long deliveryTemplateId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支持的配送方式
|
||||||
|
*/
|
||||||
|
private List<Integer> deliveryTypes;
|
||||||
|
|
||||||
// ========== 营销相关字段 =========
|
// ========== 营销相关字段 =========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -4,6 +4,7 @@ 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.sku.dto.ProductSkuRespDTO;
|
||||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
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.api.spu.dto.ProductSpuRespDTO;
|
||||||
|
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
|
||||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
|
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
|
||||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
|
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
|
||||||
import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator;
|
import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator;
|
||||||
@@ -15,6 +16,8 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
@@ -22,6 +25,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
|
|||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
|
||||||
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH;
|
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_STOCK_NOT_ENOUGH;
|
||||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL;
|
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_PAY_PRICE_ILLEGAL;
|
||||||
|
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_DELIVERY_TYPE_NOT_SUPPORTED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 价格计算 Service 实现类
|
* 价格计算 Service 实现类
|
||||||
@@ -48,6 +52,9 @@ public class TradePriceServiceImpl implements TradePriceService {
|
|||||||
// 1.2 获得商品 SPU 数组
|
// 1.2 获得商品 SPU 数组
|
||||||
List<ProductSpuRespDTO> spuList = checkSpuList(skuList);
|
List<ProductSpuRespDTO> spuList = checkSpuList(skuList);
|
||||||
|
|
||||||
|
// 1.3 校验配送方式是否匹配
|
||||||
|
checkDeliveryType(calculateReqBO, spuList);
|
||||||
|
|
||||||
// 2.1 计算价格
|
// 2.1 计算价格
|
||||||
TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper
|
TradePriceCalculateRespBO calculateRespBO = TradePriceCalculatorHelper
|
||||||
.buildCalculateResp(calculateReqBO, spuList, skuList);
|
.buildCalculateResp(calculateReqBO, spuList, skuList);
|
||||||
@@ -85,4 +92,17 @@ public class TradePriceServiceImpl implements TradePriceService {
|
|||||||
return productSpuApi.validateSpuList(convertSet(skuList, ProductSkuRespDTO::getSpuId));
|
return productSpuApi.validateSpuList(convertSet(skuList, ProductSkuRespDTO::getSpuId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkDeliveryType(TradePriceCalculateReqBO reqBO, List<ProductSpuRespDTO> spuList) {
|
||||||
|
if (reqBO.getDeliveryType() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Integer> supportedDeliveryTypes = spuList.stream()
|
||||||
|
.flatMap(spu -> spu.getDeliveryTypes().stream())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
if (!supportedDeliveryTypes.contains(reqBO.getDeliveryType())) {
|
||||||
|
log.error("[checkDeliveryType][配送方式不匹配,请求 deliveryType({}),支持的 deliveryTypes({})]",
|
||||||
|
reqBO.getDeliveryType(), supportedDeliveryTypes);
|
||||||
|
throw exception(PRICE_CALCULATE_DELIVERY_TYPE_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -223,4 +223,17 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkDeliveryType(TradePriceCalculateReqBO param, List<ProductSpuRespDTO> spuList) {
|
||||||
|
if (param.getDeliveryType() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Integer> supportedDeliveryTypes = spuList.stream()
|
||||||
|
.flatMap(spu -> spu.getDeliveryTypes().stream())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
if (!supportedDeliveryTypes.contains(param.getDeliveryType())) {
|
||||||
|
log.error("[checkDeliveryType][配送方式不匹配,请求 deliveryType({}),支持的 deliveryTypes({})]",
|
||||||
|
param.getDeliveryType(), supportedDeliveryTypes);
|
||||||
|
throw exception(PRICE_CALCULATE_DELIVERY_TYPE_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,6 @@ import static org.mockito.Mockito.when;
|
|||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Disabled // TODO 芋艿:后续 fix 补充的单测
|
|
||||||
public class TradePriceServiceImplTest extends BaseMockitoUnitTest {
|
public class TradePriceServiceImplTest extends BaseMockitoUnitTest {
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
@@ -134,4 +133,34 @@ public class TradePriceServiceImplTest extends BaseMockitoUnitTest {
|
|||||||
assertEquals(skuList.get(2).getProperties(), calculateRespBO.getItems().get(2).getProperties());
|
assertEquals(skuList.get(2).getProperties(), calculateRespBO.getItems().get(2).getProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCalculatePrice_DeliveryTypeMismatch() {
|
||||||
|
// 准备参数
|
||||||
|
TradePriceCalculateReqBO calculateReqBO = new TradePriceCalculateReqBO()
|
||||||
|
.setUserId(10L)
|
||||||
|
.setCouponId(20L).setAddressId(30L)
|
||||||
|
.setDeliveryType(DeliveryTypeEnum.EXPRESS.getType()) // 设置配送方式
|
||||||
|
.setItems(Arrays.asList(
|
||||||
|
new TradePriceCalculateReqBO.Item().setSkuId(100L).setCount(1).setSelected(true),
|
||||||
|
new TradePriceCalculateReqBO.Item().setSkuId(200L).setCount(3).setSelected(true)
|
||||||
|
));
|
||||||
|
// mock 方法
|
||||||
|
List<ProductSkuRespDTO> skuList = Arrays.asList(
|
||||||
|
new ProductSkuRespDTO().setId(100L).setStock(500).setPrice(1000).setPicUrl("https://t.cn/1.png").setSpuId(1001L)
|
||||||
|
.setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(1L).setPropertyName("颜色")
|
||||||
|
.setValueId(2L).setValueName("红色"))),
|
||||||
|
new ProductSkuRespDTO().setId(200L).setStock(400).setPrice(2000).setPicUrl("https://t.cn/2.png").setSpuId(1001L)
|
||||||
|
.setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(1L).setPropertyName("颜色")
|
||||||
|
.setValueId(3L).setValueName("黄色")))
|
||||||
|
);
|
||||||
|
when(productSkuApi.getSkuList(Mockito.eq(asSet(100L, 200L)))).thenReturn(skuList);
|
||||||
|
when(productSpuApi.getSpuList(Mockito.eq(asSet(1001L))))
|
||||||
|
.thenReturn(singletonList(new ProductSpuRespDTO().setId(1001L).setName("小菜").setCategoryId(666L)
|
||||||
|
.setStatus(ProductSpuStatusEnum.ENABLE.getStatus())
|
||||||
|
.setDeliveryTypes(singletonList(DeliveryTypeEnum.PICK_UP.getType())))); // 设置不支持的配送方式
|
||||||
|
|
||||||
|
// 调用并断言抛出异常
|
||||||
|
assertThrows(ServiceException.class, () -> tradePriceService.calculatePrice(calculateReqBO));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user