commit
241957507c
|
@ -69,8 +69,8 @@ public class AppProductSpuController {
|
|||
list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
|
||||
List<AppProductSpuRespVO> voList = BeanUtils.toBean(list, AppProductSpuRespVO.class);
|
||||
// 处理 vip 价格
|
||||
MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
// MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
// voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
return success(voList);
|
||||
}
|
||||
|
||||
|
@ -86,8 +86,8 @@ public class AppProductSpuController {
|
|||
pageResult.getList().forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
|
||||
PageResult<AppProductSpuRespVO> voPageResult = BeanUtils.toBean(pageResult, AppProductSpuRespVO.class);
|
||||
// 处理 vip 价格
|
||||
MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
// MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
// voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
|
||||
return success(voPageResult);
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ public class AppProductSpuController {
|
|||
*/
|
||||
public Integer calculateVipPrice(Integer price, MemberLevelRespDTO memberLevel) {
|
||||
if (memberLevel == null || memberLevel.getDiscountPercent() == null) {
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
Integer newPrice = price * memberLevel.getDiscountPercent() / 100;
|
||||
return price - newPrice;
|
||||
|
|
|
@ -38,8 +38,8 @@ public class AppProductSpuRespVO {
|
|||
@Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
|
||||
private Integer marketPrice;
|
||||
|
||||
@Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
|
||||
private Integer vipPrice;
|
||||
// @Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
|
||||
// private Integer vipPrice;
|
||||
|
||||
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
private Integer stock;
|
||||
|
|
|
@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.promotion.api.discount.dto;
|
|||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 限时折扣活动商品 Response DTO
|
||||
*
|
||||
|
@ -44,5 +46,12 @@ public class DiscountProductRespDTO {
|
|||
* 活动标题
|
||||
*/
|
||||
private String activityName;
|
||||
/**
|
||||
* 活动结束时间点
|
||||
*
|
||||
* 冗余 {@link DiscountActivityDO#getEndTime()}
|
||||
*/
|
||||
private LocalDateTime activityEndTime;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.reward;
|
|||
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -21,4 +22,13 @@ public interface RewardActivityApi {
|
|||
*/
|
||||
List<RewardActivityMatchRespDTO> getRewardActivityListByStatusAndNow(Integer status, LocalDateTime dateTime);
|
||||
|
||||
/**
|
||||
* 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
|
||||
*
|
||||
* @param spuIds spu 编号
|
||||
* @param status 状态
|
||||
* @param dateTime 当前日期时间
|
||||
* @return 满减送活动列表
|
||||
*/
|
||||
List<RewardActivityMatchRespDTO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_002, "限时折扣活动已关闭,不能修改");
|
||||
ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除");
|
||||
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭");
|
||||
ErrorCode DISCOUNT_ACTIVITY_TYPE_NOT_EXISTS = new ErrorCode(1_013_001_005, "限时折扣活动类型不存在");
|
||||
|
||||
// ========== Banner 相关 1-013-002-000 ============
|
||||
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在");
|
||||
|
@ -45,6 +46,7 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
|
||||
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
|
||||
ErrorCode REWARD_ACTIVITY_SCOPE_EXISTS = new ErrorCode(1_013_006_005, "与该时间段已存在的满减送活动商品范围冲突");
|
||||
ErrorCode REWARD_ACTIVITY_TYPE_NOT_EXISTS = new ErrorCode(1_013_006_006, "满减送活动类型不存在");
|
||||
|
||||
// ========== TODO 空着 1-013-007-000 ============
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public class DiscountActivityApiImpl implements DiscountActivityApi {
|
|||
|
||||
@Override
|
||||
public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds) {
|
||||
return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds));
|
||||
return discountActivityService.getMatchDiscountProductList(skuIds);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.reward;
|
|||
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
|
||||
import jakarta.annotation.Resource;
|
||||
|
@ -9,6 +10,7 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -29,4 +31,10 @@ public class RewardActivityApiImpl implements RewardActivityApi {
|
|||
return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RewardActivityMatchRespDTO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
|
||||
List<RewardActivityDO> rewardActivityBySpuIdsAndStatusAndDateTimeLt = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(spuIds, status, dateTime);
|
||||
return RewardActivityConvert.INSTANCE.convertList(rewardActivityBySpuIdsAndStatusAndDateTimeLt);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.template;
|
|||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
@ -12,6 +14,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.constraints.AssertTrue;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
@ -37,11 +40,11 @@ public class CouponTemplateBaseVO {
|
|||
private String description;
|
||||
|
||||
@Schema(description = "发行总量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") // -1 - 则表示不限制发放数量
|
||||
@NotNull(message = "发行总量不能为空")
|
||||
@NotNull(message = "发行总量不能为空", groups = {User.class})
|
||||
private Integer totalCount;
|
||||
|
||||
@Schema(description = "每人限领个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "66") // -1 - 则表示不限制
|
||||
@NotNull(message = "每人限领个数不能为空")
|
||||
@NotNull(message = "每人限领个数不能为空", groups = {User.class})
|
||||
private Integer takeLimitCount;
|
||||
|
||||
@Schema(description = "领取方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
|
@ -89,13 +92,16 @@ public class CouponTemplateBaseVO {
|
|||
private Integer discountType;
|
||||
|
||||
@Schema(description = "折扣百分比", example = "80") // 例如说,80% 为 80
|
||||
@NotNull(message = "折扣百分比不能为空", groups = {Percent.class})
|
||||
private Integer discountPercent;
|
||||
|
||||
@Schema(description = "优惠金额", example = "10")
|
||||
@Min(value = 0, message = "优惠金额需要大于等于 0")
|
||||
@NotNull(message = "优惠金额不能为空", groups = {Price.class})
|
||||
private Integer discountPrice;
|
||||
|
||||
@Schema(description = "折扣上限", example = "100") // 单位:分,仅在 discountType 为 PERCENT 使用
|
||||
@NotNull(message = "折扣上限不能为空", groups = {Percent.class})
|
||||
private Integer discountLimitPrice;
|
||||
|
||||
@AssertTrue(message = "商品范围编号的数组不能为空")
|
||||
|
@ -154,4 +160,54 @@ public class CouponTemplateBaseVO {
|
|||
|| discountLimitPrice != null;
|
||||
}
|
||||
|
||||
//-------------------------领取方式校验start----------------------------
|
||||
|
||||
/**
|
||||
* 直接领取
|
||||
*/
|
||||
public interface User {
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定发放
|
||||
*/
|
||||
public interface Admin {
|
||||
}
|
||||
|
||||
//-------------------------领取方式校验end------------------------------
|
||||
|
||||
//-------------------------优惠类型校验start----------------------------
|
||||
|
||||
/**
|
||||
* 满减
|
||||
*/
|
||||
public interface Price {
|
||||
}
|
||||
|
||||
/**
|
||||
* 折扣
|
||||
*/
|
||||
public interface Percent {
|
||||
}
|
||||
|
||||
//-------------------------优惠类型校验end------------------------------
|
||||
|
||||
public void validate(Validator validator) {
|
||||
|
||||
//领取方式校验
|
||||
if (CouponTakeTypeEnum.USER.getType().equals(takeType)) {
|
||||
ValidationUtils.validate(validator, this, User.class);
|
||||
} else if (CouponTakeTypeEnum.ADMIN.getType().equals(takeType)) {
|
||||
ValidationUtils.validate(validator, this, Admin.class);
|
||||
}
|
||||
|
||||
//优惠类型校验
|
||||
if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountType)){
|
||||
ValidationUtils.validate(validator, this, Price.class);
|
||||
} else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountType)) {
|
||||
ValidationUtils.validate(validator, this, Percent.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
|
||||
|
@ -150,36 +151,32 @@ public class AppActivityController {
|
|||
}
|
||||
|
||||
private void getRewardActivityList(Collection<Long> spuIds, LocalDateTime now, List<AppActivityRespVO> activityList) {
|
||||
// 1.1 获得所有的活动
|
||||
List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityListByStatusAndDateTimeLt(
|
||||
CommonStatusEnum.ENABLE.getStatus(), now);
|
||||
// TODO @puhui999:有 3 范围,不只 spuId,还有 categoryId,全部,下次 fix
|
||||
List<RewardActivityDO> rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(
|
||||
spuIds, CommonStatusEnum.ENABLE.getStatus(), now);
|
||||
if (CollUtil.isEmpty(rewardActivityList)) {
|
||||
return;
|
||||
}
|
||||
// 1.2 获得所有的商品信息
|
||||
List<ProductSpuRespDTO> spuList = productSpuApi.getSpuList(spuIds);
|
||||
if (CollUtil.isEmpty(spuList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 构建活动
|
||||
for (RewardActivityDO rewardActivity : rewardActivityList) {
|
||||
// 情况一:所有商品都能参加
|
||||
if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
|
||||
buildAppActivityRespVO(rewardActivity, spuIds, activityList);
|
||||
}
|
||||
// 情况二:指定商品参加
|
||||
if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
|
||||
List<Long> fSpuIds = spuList.stream().map(ProductSpuRespDTO::getId).filter(id ->
|
||||
rewardActivity.getProductScopeValues().contains(id)).toList();
|
||||
buildAppActivityRespVO(rewardActivity, fSpuIds, activityList);
|
||||
}
|
||||
// 情况三:指定商品类型参加
|
||||
if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
|
||||
List<Long> fSpuIds = spuList.stream().filter(spuItem -> rewardActivity.getProductScopeValues()
|
||||
.contains(spuItem.getCategoryId())).map(ProductSpuRespDTO::getId).toList();
|
||||
buildAppActivityRespVO(rewardActivity, fSpuIds, activityList);
|
||||
Map<Long, Optional<RewardActivityDO>> spuIdAndActivityMap = spuIds.stream()
|
||||
.collect(Collectors.toMap(
|
||||
spuId -> spuId,
|
||||
spuId -> rewardActivityList.stream()
|
||||
.filter(activity ->
|
||||
( activity.getProductScopeValues()!=null &&
|
||||
(activity.getProductScopeValues().contains(spuId) ||
|
||||
activity.getProductScopeValues().contains(productSpuApi.getSpu(spuId).getCategoryId()))) ||
|
||||
activity.getProductScope()==1
|
||||
)
|
||||
.max(Comparator.comparing(RewardActivityDO::getCreateTime))));
|
||||
for (Long supId : spuIdAndActivityMap.keySet()) {
|
||||
if (spuIdAndActivityMap.get(supId).isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get();
|
||||
activityList.add(new AppActivityRespVO(rewardActivityDO.getId(), PromotionTypeEnum.REWARD_ACTIVITY.getType(),
|
||||
rewardActivityDO.getName(), supId, rewardActivityDO.getStartTime(), rewardActivityDO.getEndTime()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,8 +60,8 @@ public class AppCouponController {
|
|||
@Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表")
|
||||
public CommonResult<List<AppCouponMatchRespVO>> getMatchCouponList(AppCouponMatchReqVO matchReqVO) {
|
||||
// todo: 优化:优惠金额倒序
|
||||
List<CouponDO> list = couponService.getMatchCouponList(getLoginUserId(), matchReqVO);
|
||||
return success(BeanUtils.toBean(list, AppCouponMatchRespVO.class));
|
||||
List<AppCouponMatchRespVO> list = couponService.getMatchCouponList(getLoginUserId(), matchReqVO);
|
||||
return success(list);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
|
|
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi
|
|||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户 App - 满减送活动 Response VO")
|
||||
|
@ -26,9 +27,15 @@ public class AppRewardActivityRespVO {
|
|||
private Integer productScope;
|
||||
|
||||
@Schema(description = "商品 SPU 编号的数组", example = "1,2,3")
|
||||
private List<Long> productSpuIds;
|
||||
private List<Long> productScopeValues;
|
||||
|
||||
@Schema(description = "优惠规则的数组")
|
||||
private List<RewardActivityBaseVO.Rule> rules;
|
||||
|
||||
@Schema(description = "开始时间")
|
||||
private LocalDateTime startTime;
|
||||
|
||||
@Schema(description = "结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ public interface CouponConvert {
|
|||
|
||||
CouponRespDTO convert(CouponDO bean);
|
||||
|
||||
AppCouponMatchRespVO convert2(CouponDO bean);
|
||||
|
||||
default CouponDO convert(CouponTemplateDO template, Long userId) {
|
||||
CouponDO couponDO = new CouponDO()
|
||||
.setTemplateId(template.getId())
|
||||
|
|
|
@ -121,7 +121,10 @@ public interface DiscountActivityConvert {
|
|||
default boolean isEquals(DiscountProductDO productDO, DiscountProductDO productVO) {
|
||||
if (ObjectUtil.notEqual(productDO.getSpuId(), productVO.getSpuId())
|
||||
|| ObjectUtil.notEqual(productDO.getSkuId(), productVO.getSkuId())
|
||||
|| ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())) {
|
||||
|| ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())
|
||||
|| ObjectUtil.notEqual(productDO.getActivityEndTime(), productVO.getActivityEndTime())
|
||||
|| ObjectUtil.notEqual(productDO.getActivityStartTime(), productVO.getActivityStartTime())
|
||||
|| ObjectUtil.notEqual(productDO.getActivityStatus(), productVO.getActivityStatus())) {
|
||||
return false;
|
||||
}
|
||||
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PRICE.getType())) {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package cn.iocoder.yudao.module.promotion.convert.reward;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 满减送活动 Convert
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Mapper
|
||||
public interface RewardActivityConvert {
|
||||
|
||||
RewardActivityConvert INSTANCE = Mappers.getMapper(RewardActivityConvert.class);
|
||||
|
||||
RewardActivityDO convert(RewardActivityCreateReqVO bean);
|
||||
|
||||
RewardActivityDO convert(RewardActivityUpdateReqVO bean);
|
||||
|
||||
RewardActivityRespVO convert(RewardActivityDO bean);
|
||||
|
||||
PageResult<RewardActivityRespVO> convertPage(PageResult<RewardActivityDO> page);
|
||||
|
||||
List<RewardActivityMatchRespDTO> convertList(List<RewardActivityDO> rewardActivityBySpuIdsAndStatusAndDateTimeLt);
|
||||
}
|
|
@ -85,19 +85,12 @@ public interface CouponMapper extends BaseMapperX<CouponDO> {
|
|||
}
|
||||
|
||||
default List<CouponDO> selectListByUserIdAndStatusAndUsePriceLeAndProductScope(
|
||||
Long userId, Integer status, Integer usePrice, List<Long> spuIds, List<Long> categoryIds) {
|
||||
Function<List<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
|
||||
.map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
|
||||
.collect(Collectors.joining(" OR "));
|
||||
return selectList(new LambdaQueryWrapperX<CouponDO>()
|
||||
Long userId, Integer status) {
|
||||
List<CouponDO> couponDOS = selectList(new LambdaQueryWrapperX<CouponDO>()
|
||||
.eq(CouponDO::getUserId, userId)
|
||||
.eq(CouponDO::getStatus, status)
|
||||
.le(CouponDO::getUsePrice, usePrice) // 价格小于等于,满足价格使用条件
|
||||
.and(w -> w.eq(CouponDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()) // 商品范围一:全部
|
||||
.or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.SPU.getScope()) // 商品范围二:满足指定商品
|
||||
.apply(productScopeValuesFindInSetFunc.apply(spuIds)))
|
||||
.or(ww -> ww.eq(CouponDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope()) // 商品范围三:满足指定分类
|
||||
.apply(productScopeValuesFindInSetFunc.apply(categoryIds)))));
|
||||
);
|
||||
return couponDOS;
|
||||
}
|
||||
|
||||
default List<CouponDO> selectListByStatusAndValidEndTimeLe(Integer status, LocalDateTime validEndTime) {
|
||||
|
|
|
@ -70,7 +70,7 @@ public interface CouponTemplateMapper extends BaseMapperX<CouponTemplateDO> {
|
|||
.in(CouponTemplateDO::getTakeType, canTakeTypes) // 2. 领取方式一致
|
||||
.and(ww -> ww.gt(CouponTemplateDO::getValidEndTime, LocalDateTime.now()) // 3.1 未过期
|
||||
.or().eq(CouponTemplateDO::getValidityType, CouponTemplateValidityTypeEnum.TERM.getType())) // 3.2 领取之后
|
||||
.apply(" (take_count < total_count OR total_count = -1 )"); // 4. 剩余数量大于 0,或者无限领取
|
||||
.apply(" (take_count < total_count OR total_count = -1 or total_count is null)"); // 4. 剩余数量大于 0,或者无限领取,或者是指定发放的券
|
||||
}
|
||||
return canTakeConsumer;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
@ -31,7 +32,7 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> {
|
|||
}
|
||||
|
||||
// TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的
|
||||
List<DiscountProductDO> getMatchDiscountProductList(@Param("skuIds") Collection<Long> skuIds);
|
||||
List<DiscountProductRespDTO> getMatchDiscountProductList(@Param("skuIds") Collection<Long> skuIds);
|
||||
|
||||
/**
|
||||
* 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
package cn.iocoder.yudao.module.promotion.dal.mysql.reward;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 满减送活动 Mapper
|
||||
|
@ -25,13 +31,48 @@ public interface RewardActivityMapper extends BaseMapperX<RewardActivityDO> {
|
|||
.orderByDesc(RewardActivityDO::getId));
|
||||
}
|
||||
|
||||
default List<RewardActivityDO> selectListBySpuIdsAndStatus(Collection<Long> spuIds, Integer status) {
|
||||
Function<Collection<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
|
||||
.map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
|
||||
.collect(Collectors.joining(" OR "));
|
||||
return selectList(new QueryWrapper<RewardActivityDO>()
|
||||
.eq("status", status)
|
||||
.apply(productScopeValuesFindInSetFunc.apply(spuIds)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定活动编号的活动列表且
|
||||
* 开始时间和结束时间小于给定时间 dateTime 的活动列表
|
||||
*
|
||||
* @param status 状态
|
||||
* @param dateTime 指定日期
|
||||
* @return 活动列表
|
||||
*/
|
||||
default List<RewardActivityDO> selectListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
|
||||
return selectList(new LambdaQueryWrapperX<RewardActivityDO>()
|
||||
.eq(RewardActivityDO::getStatus, status)
|
||||
// 开始时间 < 指定时间(dateTime) < 结束时间,也就是说获取指定时间段的活动
|
||||
.lt(RewardActivityDO::getStartTime, dateTime).gt(RewardActivityDO::getEndTime, dateTime)
|
||||
.lt(RewardActivityDO::getStartTime, dateTime)
|
||||
.gt(RewardActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动
|
||||
.orderByAsc(RewardActivityDO::getStartTime)
|
||||
);
|
||||
}
|
||||
|
||||
default List<RewardActivityDO> getRewardActivityByStatusAndDateTimeLt(Collection<Long> spuIds,Collection<Long> categoryIds, Integer status, LocalDateTime dateTime) {
|
||||
//拼接通用券查询语句
|
||||
Function<Collection<Long>, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
|
||||
.map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
|
||||
.collect(Collectors.joining(" OR "));
|
||||
return selectList(new LambdaQueryWrapperX<RewardActivityDO>()
|
||||
.eq(RewardActivityDO::getStatus,status)
|
||||
.lt(RewardActivityDO::getStartTime, dateTime)
|
||||
.gt(RewardActivityDO::getEndTime, dateTime)
|
||||
.and(i -> i.eq(RewardActivityDO::getProductScope, PromotionProductScopeEnum.SPU.getScope())
|
||||
.and(i1 -> i1.apply(productScopeValuesFindInSetFunc.apply(spuIds)))
|
||||
.or(i1 -> i1.eq(RewardActivityDO::getProductScope, PromotionProductScopeEnum.ALL.getScope()))
|
||||
.or(i1 -> i1.eq(RewardActivityDO::getProductScope, PromotionProductScopeEnum.CATEGORY.getScope())
|
||||
.and(i2 -> i2.apply(productScopeValuesFindInSetFunc.apply(categoryIds)))))
|
||||
.orderByDesc(RewardActivityDO::getId)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
|
|||
Assert.isTrue(count > 0);
|
||||
return update(null, new LambdaUpdateWrapper<SeckillActivityDO>()
|
||||
.eq(SeckillActivityDO::getId, id)
|
||||
.gt(SeckillActivityDO::getStock, count)
|
||||
.ge(SeckillActivityDO::getStock, count)
|
||||
.setSql("stock = stock - " + count));
|
||||
}
|
||||
|
||||
|
@ -69,9 +69,11 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
|
|||
.setSql("stock = stock + " + count));
|
||||
}
|
||||
|
||||
default PageResult<SeckillActivityDO> selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status) {
|
||||
default PageResult<SeckillActivityDO> selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status, LocalDateTime dateTime) {
|
||||
return selectPage(pageReqVO, new LambdaQueryWrapperX<SeckillActivityDO>()
|
||||
.eqIfPresent(SeckillActivityDO::getStatus, status)
|
||||
.lt(SeckillActivityDO::getStartTime, dateTime)
|
||||
.gt(SeckillActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动
|
||||
.apply(ObjectUtil.isNotNull(pageReqVO.getConfigId()), "FIND_IN_SET(" + pageReqVO.getConfigId() + ",config_ids) > 0"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillConfigDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
|
|
|
@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
|
|||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
|
@ -178,7 +179,7 @@ public interface CouponService {
|
|||
* @param matchReqVO 匹配参数
|
||||
* @return 优惠券列表
|
||||
*/
|
||||
List<CouponDO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO);
|
||||
List<AppCouponMatchRespVO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO);
|
||||
|
||||
/**
|
||||
* 获取用户是否可以领取优惠券
|
||||
|
|
|
@ -13,10 +13,12 @@ import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
|||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.coupon.vo.coupon.CouponPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.app.coupon.vo.coupon.AppCouponMatchRespVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.coupon.CouponConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.coupon.CouponTemplateDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponMapper;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTemplateValidityTypeEnum;
|
||||
|
@ -286,6 +288,7 @@ public class CouponServiceImpl implements CouponService {
|
|||
}
|
||||
// 校验剩余数量(仅在 CouponTakeTypeEnum.USER 用户领取时)
|
||||
if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeCount())
|
||||
&& couponTemplate.getTotalCount() != null
|
||||
&& couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
|
||||
throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
|
||||
}
|
||||
|
@ -308,7 +311,7 @@ public class CouponServiceImpl implements CouponService {
|
|||
* @param couponTemplate 优惠劵模版
|
||||
*/
|
||||
private void removeTakeLimitUser(Set<Long> userIds, CouponTemplateDO couponTemplate) {
|
||||
if (couponTemplate.getTakeLimitCount() <= 0) {
|
||||
if (couponTemplate.getTakeLimitCount() == null || couponTemplate.getTakeLimitCount() <= 0) {
|
||||
return;
|
||||
}
|
||||
// 查询已领过券的用户
|
||||
|
@ -356,13 +359,45 @@ public class CouponServiceImpl implements CouponService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<CouponDO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) {
|
||||
public List<AppCouponMatchRespVO> getMatchCouponList(Long userId, AppCouponMatchReqVO matchReqVO) {
|
||||
List<AppCouponMatchRespVO> couponMatchist = new ArrayList<>();
|
||||
List<CouponDO> list = couponMapper.selectListByUserIdAndStatusAndUsePriceLeAndProductScope(userId,
|
||||
CouponStatusEnum.UNUSED.getStatus(),
|
||||
matchReqVO.getPrice(), matchReqVO.getSpuIds(), matchReqVO.getCategoryIds());
|
||||
// 兜底逻辑:如果 CouponExpireJob 未执行,status 未变成 EXPIRE ,但是 validEndTime 已经过期了,需要进行过滤
|
||||
list.removeIf(coupon -> !LocalDateTimeUtils.isBetween(coupon.getValidStartTime(), coupon.getValidEndTime()));
|
||||
return list;
|
||||
CouponStatusEnum.UNUSED.getStatus());
|
||||
for (CouponDO couponDO : list) {
|
||||
AppCouponMatchRespVO appCouponMatchRespVO = CouponConvert.INSTANCE.convert2(couponDO);
|
||||
Integer productScope = appCouponMatchRespVO.getProductScope();
|
||||
List<Long> productScopeValues = appCouponMatchRespVO.getProductScopeValues();
|
||||
Integer usePrice = appCouponMatchRespVO.getUsePrice();
|
||||
if(matchReqVO.getPrice() < usePrice){
|
||||
// 价格小于等于,满足价格使用条件
|
||||
appCouponMatchRespVO.setMatch(false);
|
||||
appCouponMatchRespVO.setDescription("未达到使用门槛");
|
||||
}else if(!LocalDateTimeUtils.isBetween(appCouponMatchRespVO.getValidStartTime(), appCouponMatchRespVO.getValidEndTime())) {
|
||||
//判断时间
|
||||
appCouponMatchRespVO.setMatch(false);
|
||||
appCouponMatchRespVO.setDescription("使用时间未到");
|
||||
}else if (PromotionProductScopeEnum.ALL.getScope().equals(productScope)){
|
||||
appCouponMatchRespVO.setMatch(true);
|
||||
}else if (PromotionProductScopeEnum.SPU.getScope().equals(productScope)){
|
||||
boolean spu = new HashSet<>(productScopeValues).containsAll(matchReqVO.getSpuIds());
|
||||
if(spu){
|
||||
appCouponMatchRespVO.setMatch(true);
|
||||
}else {
|
||||
appCouponMatchRespVO.setMatch(false);
|
||||
appCouponMatchRespVO.setDescription("与商品不匹配");
|
||||
}
|
||||
}else if (PromotionProductScopeEnum.CATEGORY.getScope().equals(productScope)){
|
||||
boolean category = new HashSet<>(productScopeValues).containsAll(matchReqVO.getCategoryIds());
|
||||
if(category){
|
||||
appCouponMatchRespVO.setMatch(true);
|
||||
}else {
|
||||
appCouponMatchRespVO.setMatch(false);
|
||||
appCouponMatchRespVO.setDescription("与商品类型不匹配");
|
||||
}
|
||||
}
|
||||
couponMatchist.add(appCouponMatchRespVO);
|
||||
}
|
||||
return couponMatchist;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.promotion.dal.mysql.coupon.CouponTemplateMapper;
|
|||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.coupon.CouponTakeTypeEnum;
|
||||
import org.springframework.stereotype.Service;
|
||||
import jakarta.validation.Validator;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
@ -40,9 +41,13 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
|
|||
private ProductCategoryApi productCategoryApi;
|
||||
@Resource
|
||||
private ProductSpuApi productSpuApi;
|
||||
@Resource
|
||||
private Validator validator;
|
||||
|
||||
@Override
|
||||
public Long createCouponTemplate(CouponTemplateCreateReqVO createReqVO) {
|
||||
// 校验参数
|
||||
createReqVO.validate(validator);
|
||||
// 校验商品范围
|
||||
validateProductScope(createReqVO.getProductScope(), createReqVO.getProductScopeValues());
|
||||
// 插入
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.promotion.service.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
|
||||
|
@ -27,7 +28,7 @@ public interface DiscountActivityService {
|
|||
* @param skuIds SKU 编号数组
|
||||
* @return 匹配的限时折扣商品
|
||||
*/
|
||||
List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds);
|
||||
List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds);
|
||||
|
||||
/**
|
||||
* 创建限时折扣活动
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.hutool.core.map.MapUtil;
|
|||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
|
||||
|
@ -49,7 +50,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
|
|||
private DiscountProductMapper discountProductMapper;
|
||||
|
||||
@Override
|
||||
public List<DiscountProductDO> getMatchDiscountProductList(Collection<Long> skuIds) {
|
||||
public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds) {
|
||||
return discountProductMapper.getMatchDiscountProductList(skuIds);
|
||||
}
|
||||
|
||||
|
@ -130,7 +131,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
|
|||
List<DiscountProductDO> list = discountProductMapper.selectListByActivityId(id);
|
||||
// TODO @zhangshuai:一般简单的 stream 方法,建议是使用 CollectionUtils,例如说这里是 convertList 对把。
|
||||
List<Long> skuIds = list.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
|
||||
List<DiscountProductDO> matchDiscountProductList = getMatchDiscountProductList(skuIds);
|
||||
List<DiscountProductRespDTO> matchDiscountProductList = getMatchDiscountProductList(skuIds);
|
||||
if (id != null) { // 排除自己这个活动
|
||||
matchDiscountProductList.removeIf(product -> id.equals(product.getActivityId()));
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
|||
import jakarta.validation.Valid;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -71,4 +72,14 @@ public interface RewardActivityService {
|
|||
*/
|
||||
List<RewardActivityDO> getRewardActivityListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime);
|
||||
|
||||
/**
|
||||
* 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
|
||||
*
|
||||
* @param spuIds SPU 编号数组
|
||||
* @param status 状态
|
||||
* @param dateTime 当前日期时间
|
||||
* @return 满减送活动列表
|
||||
*/
|
||||
List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cn.iocoder.yudao.module.promotion.service.reward;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
|
@ -11,8 +12,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi
|
|||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
|
@ -20,8 +23,11 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
@ -52,9 +58,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
|
|||
// 1.2 校验商品是否冲突
|
||||
validateRewardActivitySpuConflicts(null, createReqVO);
|
||||
|
||||
// 2. 插入
|
||||
RewardActivityDO rewardActivity = BeanUtils.toBean(createReqVO, RewardActivityDO.class)
|
||||
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()));
|
||||
// 插入
|
||||
RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO)
|
||||
.setStatus(
|
||||
PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()).equals(CommonStatusEnum.DISABLE.getStatus())?
|
||||
PromotionActivityStatusEnum.WAIT.getStatus():
|
||||
PromotionActivityStatusEnum.RUN.getStatus()
|
||||
);
|
||||
rewardActivityMapper.insert(rewardActivity);
|
||||
// 返回
|
||||
return rewardActivity.getId();
|
||||
|
@ -199,4 +209,19 @@ public class RewardActivityServiceImpl implements RewardActivityService {
|
|||
return rewardActivityMapper.selectListByStatusAndDateTimeLt(status, dateTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RewardActivityDO> getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection<Long> spuIds, Integer status, LocalDateTime dateTime) {
|
||||
List<ProductSpuRespDTO> spuList = productSpuApi.validateSpuList(spuIds);
|
||||
//查询出商品的分类ids
|
||||
List<Long> categoryIds = spuList.stream().map(ProductSpuRespDTO::getCategoryId).collect(Collectors.toList());
|
||||
// 1. 查询出指定 spuId 的 spu 参加的活动
|
||||
List<RewardActivityDO> rewardActivityList = rewardActivityMapper.getRewardActivityByStatusAndDateTimeLt(spuIds, categoryIds,status,dateTime);
|
||||
if (CollUtil.isEmpty(rewardActivityList)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 2. 查询活动详情
|
||||
return rewardActivityList;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ public interface SeckillActivityService {
|
|||
List<SeckillActivityDO> getSeckillActivityListByConfigIdAndStatus(Long configId, Integer status);
|
||||
|
||||
/**
|
||||
* 通过活动时段获取秒杀活动
|
||||
* 通过活动时段获取开始的秒杀活动
|
||||
*
|
||||
* @param pageReqVO 请求
|
||||
* @return 秒杀活动列表
|
||||
|
|
|
@ -23,6 +23,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillConfigDO;
|
|||
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.SeckillProductDO;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillActivityMapper;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillactivity.SeckillProductMapper;
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.seckill.seckillconfig.SeckillConfigMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
@ -57,6 +58,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
|
|||
@Resource
|
||||
private SeckillProductMapper seckillProductMapper;
|
||||
@Resource
|
||||
private SeckillConfigMapper seckillConfigMapper;
|
||||
@Resource
|
||||
private SeckillConfigService seckillConfigService;
|
||||
@Resource
|
||||
private ProductSpuApi productSpuApi;
|
||||
|
@ -289,7 +292,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
|
|||
|
||||
@Override
|
||||
public PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO) {
|
||||
return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus());
|
||||
return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus(),LocalDateTime.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<mapper namespace="cn.iocoder.yudao.module.promotion.dal.mysql.discount.DiscountProductMapper">
|
||||
|
||||
|
||||
<select id="getMatchDiscountProductList" resultType="cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO">
|
||||
SELECT pdp.*
|
||||
<select id="getMatchDiscountProductList" resultType="cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO">
|
||||
SELECT pdp.*,pda.name as activity_name
|
||||
FROM promotion_discount_product pdp
|
||||
LEFT JOIN promotion_discount_activity pda
|
||||
ON pdp.activity_id = pda.id
|
||||
|
@ -16,9 +16,11 @@
|
|||
</foreach>
|
||||
</if>
|
||||
AND pda.start_time <= CURRENT_TIME AND pda.end_time >= CURRENT_TIME
|
||||
AND pda.`status` = 20
|
||||
AND pda.deleted != 1
|
||||
AND pda.`status` = 0
|
||||
AND pda.deleted =0
|
||||
AND pdp.deleted = 0
|
||||
</where>
|
||||
ORDER BY pdp.id DESC
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
|
|
@ -1,9 +1,23 @@
|
|||
package cn.iocoder.yudao.module.trade.controller.app.order;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
|
||||
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
|
||||
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.discount.DiscountActivityApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
|
||||
|
@ -27,12 +41,14 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.DISCOUNT_ACTIVITY_TYPE_NOT_EXISTS;
|
||||
|
||||
@Tag(name = "用户 App - 交易订单")
|
||||
@RestController
|
||||
|
@ -54,6 +70,17 @@ public class AppTradeOrderController {
|
|||
@Resource
|
||||
private TradeOrderProperties tradeOrderProperties;
|
||||
|
||||
@Resource
|
||||
private MemberLevelApi memberLevelApi;
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
@Resource
|
||||
private DiscountActivityApi discountActivityApi;
|
||||
@Resource
|
||||
private RewardActivityApi rewardActivityApi;
|
||||
@Resource
|
||||
private ProductSkuApi productKpuApi;
|
||||
|
||||
@GetMapping("/settlement")
|
||||
@Operation(summary = "获得订单结算信息")
|
||||
@PreAuthenticated
|
||||
|
@ -61,6 +88,58 @@ public class AppTradeOrderController {
|
|||
return success(tradeOrderUpdateService.settlementOrder(getLoginUserId(), settlementReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/settlementProduct")
|
||||
@Operation(summary = "获得商品结算信息")
|
||||
public CommonResult<List<AppTradeProductSettlementRespVO>> settlementProduct(@RequestParam("ids") Set<Long> ids) {
|
||||
List<AppTradeProductSettlementRespVO> appTradeProductSettlementRespVOS = new ArrayList<>();
|
||||
MemberLevelRespDTO memberLevel = getMemberLevel();
|
||||
ids.forEach(spuId -> {
|
||||
List<AppTradeProductSettlementRespVO.Sku> skus = new ArrayList<>();
|
||||
List<ProductSkuRespDTO> skuList = productKpuApi.getSkuListBySpuId(Collections.singletonList(spuId));
|
||||
//查询sku的会员和限时优惠
|
||||
skuList.forEach(sku -> {
|
||||
//查询限时优惠价格
|
||||
AppTradeProductSettlementRespVO.Sku skuDiscount = calculateDiscountPrice(sku.getId(), sku.getPrice());
|
||||
|
||||
//查询会员价
|
||||
AppTradeProductSettlementRespVO.Sku skuVip = calculateVipPrice(sku.getId(), sku.getPrice(), memberLevel);
|
||||
|
||||
if(skuDiscount != null && skuVip != null){
|
||||
if(skuDiscount.getPrice() > skuVip.getPrice()){
|
||||
skus.add(skuVip);
|
||||
}else{
|
||||
skus.add(skuDiscount);
|
||||
}
|
||||
}else if(skuDiscount != null){
|
||||
skus.add(skuDiscount);
|
||||
}else if(skuVip != null){
|
||||
skus.add(skuVip);
|
||||
}
|
||||
|
||||
});
|
||||
AppTradeProductSettlementRespVO.Reward reward = calculateReward(spuId);
|
||||
AppTradeProductSettlementRespVO respVO = AppTradeProductSettlementRespVO.builder().id(spuId).skus(skus).build();
|
||||
if(reward != null){
|
||||
//创建满减活动对象
|
||||
respVO.setReward(reward);
|
||||
}
|
||||
appTradeProductSettlementRespVOS.add(respVO);
|
||||
});
|
||||
return success(appTradeProductSettlementRespVOS);
|
||||
}
|
||||
|
||||
private MemberLevelRespDTO getMemberLevel() {
|
||||
Long userId = getLoginUserId();
|
||||
if (userId == null) {
|
||||
return null;
|
||||
}
|
||||
MemberUserRespDTO user = memberUserApi.getUser(userId);
|
||||
if (user.getLevelId() == null || user.getLevelId() <= 0) {
|
||||
return null;
|
||||
}
|
||||
return memberLevelApi.getMemberLevel(user.getLevelId());
|
||||
}
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建订单")
|
||||
@PreAuthenticated
|
||||
|
@ -188,4 +267,78 @@ public class AppTradeOrderController {
|
|||
return success(tradeOrderUpdateService.createOrderItemCommentByMember(getLoginUserId(), createReqVO));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算会员 VIP 优惠价格
|
||||
*
|
||||
* @param price 原价
|
||||
* @param memberLevel 会员等级
|
||||
* @return 优惠价格
|
||||
*/
|
||||
public AppTradeProductSettlementRespVO.Sku calculateVipPrice(Long skuId, Integer price, MemberLevelRespDTO memberLevel) {
|
||||
if (memberLevel == null || memberLevel.getDiscountPercent() == null) {
|
||||
return null;
|
||||
}
|
||||
Integer newPrice = price * memberLevel.getDiscountPercent() / 100;
|
||||
return AppTradeProductSettlementRespVO.Sku.builder().
|
||||
skuId(skuId).
|
||||
type(PromotionTypeEnum.MEMBER_LEVEL.getType()).
|
||||
price(newPrice).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算限时优惠信息
|
||||
*
|
||||
* @param price 原价
|
||||
* @param skuId 商品规格id
|
||||
* @return 优惠价格
|
||||
*/
|
||||
private AppTradeProductSettlementRespVO.Sku calculateDiscountPrice(Long skuId, Integer price) {
|
||||
if (skuId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//根据商品id查询限时优惠
|
||||
List<DiscountProductRespDTO> matchDiscountProductList = discountActivityApi.getMatchDiscountProductList(Collections.singletonList(skuId));
|
||||
if (matchDiscountProductList != null && !matchDiscountProductList.isEmpty()) {
|
||||
DiscountProductRespDTO discountProductRespDTO = matchDiscountProductList.get(matchDiscountProductList.size() - 1);
|
||||
AppTradeProductSettlementRespVO.Sku sku = AppTradeProductSettlementRespVO.Sku.builder().
|
||||
skuId(skuId).
|
||||
discountId(discountProductRespDTO.getId()).
|
||||
type(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).
|
||||
endTime(discountProductRespDTO.getActivityEndTime()).
|
||||
build();
|
||||
Integer discountType = discountProductRespDTO.getDiscountType();
|
||||
if(Objects.equals(PromotionDiscountTypeEnum.PRICE.getType(), discountType)){
|
||||
sku.setPrice(price - discountProductRespDTO.getDiscountPrice() * 100);
|
||||
}else if(Objects.equals(PromotionDiscountTypeEnum.PERCENT.getType(), discountType)){
|
||||
Integer newPrice = price * discountProductRespDTO.getDiscountPercent() / 100;
|
||||
sku.setPrice(price - newPrice);
|
||||
}else{
|
||||
throw exception(DISCOUNT_ACTIVITY_TYPE_NOT_EXISTS);
|
||||
}
|
||||
return sku;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取第一层满减活动
|
||||
*
|
||||
* @param spuId 商品规格id
|
||||
* @return 优惠价格
|
||||
*/
|
||||
private AppTradeProductSettlementRespVO.Reward calculateReward(Long spuId) {
|
||||
List<RewardActivityMatchRespDTO> matchRewardActivityList = rewardActivityApi.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collections.singletonList(spuId), CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
|
||||
if(matchRewardActivityList != null && !matchRewardActivityList.isEmpty()){
|
||||
RewardActivityMatchRespDTO rewardActivityMatchRespDTO = matchRewardActivityList.get(matchRewardActivityList.size() - 1);
|
||||
if(rewardActivityMatchRespDTO != null){
|
||||
RewardActivityMatchRespDTO.Rule rule = rewardActivityMatchRespDTO.getRules().get(0);
|
||||
return AppTradeProductSettlementRespVO.Reward.builder().
|
||||
rewardActivity("满" + rule.getLimit() / 100 + (Objects.equals(rewardActivityMatchRespDTO.getConditionType(), PromotionConditionTypeEnum.PRICE.getType())?"元":"件"+"减") +rule.getDiscountPrice() / 100)
|
||||
.id(rewardActivityMatchRespDTO.getId()).build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cn.iocoder.yudao.module.trade.controller.app.order.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
|
||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
@ -31,6 +32,13 @@ public class AppTradeOrderSettlementRespVO {
|
|||
@Schema(description = "总积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Integer totalPoint;
|
||||
|
||||
/**
|
||||
* 营销活动数组
|
||||
*
|
||||
* 只对应 {@link TradePriceCalculateRespBO.Price#items} 商品匹配的活动
|
||||
*/
|
||||
private List<TradePriceCalculateRespBO.Promotion> promotions;
|
||||
|
||||
@Schema(description = "购物项")
|
||||
@Data
|
||||
public static class Item {
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package cn.iocoder.yudao.module.trade.controller.app.order.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户 App - 商品结算信息 Response VO")
|
||||
@Data
|
||||
@Builder
|
||||
public class AppTradeProductSettlementRespVO {
|
||||
|
||||
@Schema(description = "spu 商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "满减活动对象", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Reward reward;
|
||||
|
||||
@Schema(description = "sku 活动信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private List<Sku> skus;
|
||||
|
||||
/**
|
||||
* 满减活动
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public static class Reward implements Serializable {
|
||||
|
||||
@Schema(description = "满减活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "满减活动信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private String rewardActivity;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* SKU 数组
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
public static class Sku implements Serializable {
|
||||
|
||||
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Long skuId;
|
||||
|
||||
@Schema(description = "价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "营销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer type; // 对应 PromotionTypeEnum 枚举
|
||||
|
||||
@Schema(description = "限时优惠id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long discountId;
|
||||
|
||||
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime endTime;
|
||||
|
||||
}
|
||||
}
|
|
@ -43,11 +43,9 @@ public interface AfterSaleConvert {
|
|||
@Mapping(source = "afterSale.orderId", target = "merchantOrderId"),
|
||||
@Mapping(source = "afterSale.id", target = "merchantRefundId"),
|
||||
@Mapping(source = "afterSale.applyReason", target = "reason"),
|
||||
@Mapping(source = "afterSale.refundPrice", target = "price"),
|
||||
@Mapping(source = "orderProperties.payAppKey", target = "appKey")
|
||||
@Mapping(source = "afterSale.refundPrice", target = "price")
|
||||
})
|
||||
PayRefundCreateReqDTO convert(String userIp, AfterSaleDO afterSale,
|
||||
TradeOrderProperties orderProperties);
|
||||
PayRefundCreateReqDTO convert(String userIp, AfterSaleDO afterSale);
|
||||
|
||||
MemberUserRespVO convert(MemberUserRespDTO bean);
|
||||
|
||||
|
|
|
@ -371,8 +371,9 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
|||
@Override
|
||||
public void afterCommit() {
|
||||
// 创建退款单
|
||||
PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties)
|
||||
PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale)
|
||||
.setReason(StrUtil.format("退款【{}】", afterSale.getSpuName()));
|
||||
createReqDTO.setAppKey(tradeOrderProperties.getPayAppKey());
|
||||
Long payRefundId = payRefundApi.createRefund(createReqDTO);
|
||||
// 更新售后单的退款单号
|
||||
tradeAfterSaleMapper.updateById(new AfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId));
|
||||
|
|
|
@ -68,10 +68,11 @@ public class TradePriceCalculateRespBO {
|
|||
*/
|
||||
private Long bargainActivityId;
|
||||
|
||||
|
||||
/**
|
||||
* 是否包邮
|
||||
*/
|
||||
private Boolean freeDelivery;
|
||||
private Boolean freeDelivery = false;
|
||||
|
||||
/**
|
||||
* 赠送的优惠劵
|
||||
|
|
|
@ -121,10 +121,13 @@ public class TradeDeliveryPriceCalculator implements TradePriceCalculator {
|
|||
* @return 是否包邮
|
||||
*/
|
||||
private boolean isGlobalExpressFree(TradePriceCalculateRespBO result) {
|
||||
|
||||
TradeConfigDO config = tradeConfigService.getTradeConfig();
|
||||
return config != null
|
||||
return result.getFreeDelivery() ||
|
||||
(config != null
|
||||
&& Boolean.TRUE.equals(config.getDeliveryExpressFreeEnabled()) // 开启包邮
|
||||
&& result.getPrice().getPayPrice() >= config.getDeliveryExpressFreePrice(); // 满足包邮的价格
|
||||
&& result.getPrice().getPayPrice() >= config.getDeliveryExpressFreePrice()
|
||||
); // 满足包邮的价格
|
||||
}
|
||||
|
||||
private void calculateDeliveryPrice(List<OrderItem> selectedSkus,
|
||||
|
|
|
@ -3,6 +3,10 @@ package cn.iocoder.yudao.module.trade.service.price.calculator;
|
|||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
|
||||
import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
|
||||
|
@ -14,6 +18,8 @@ import org.springframework.core.annotation.Order;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -32,6 +38,10 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
|
|||
|
||||
@Resource
|
||||
private DiscountActivityApi discountActivityApi;
|
||||
@Resource
|
||||
private MemberLevelApi memberLevelApi;
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@Override
|
||||
public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
|
||||
|
@ -39,35 +49,101 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
|
|||
if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean discount;
|
||||
boolean vip;
|
||||
|
||||
//----------------------------------限时折扣计算-----------------------------------------
|
||||
// 获得 SKU 对应的限时折扣活动
|
||||
List<DiscountProductRespDTO> discountProducts = discountActivityApi.getMatchDiscountProductList(
|
||||
convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId));
|
||||
if (CollUtil.isEmpty(discountProducts)) {
|
||||
return;
|
||||
discount = false;
|
||||
}else {
|
||||
discount = true;
|
||||
}
|
||||
Map<Long, DiscountProductRespDTO> discountProductMap = convertMap(discountProducts, DiscountProductRespDTO::getSkuId);
|
||||
|
||||
// 处理每个 SKU 的限时折扣
|
||||
result.getItems().forEach(orderItem -> {
|
||||
// 1. 获取该 SKU 的优惠信息
|
||||
DiscountProductRespDTO discountProduct = discountProductMap.get(orderItem.getSkuId());
|
||||
if (discountProduct == null) {
|
||||
return;
|
||||
}
|
||||
// 2. 计算优惠金额
|
||||
Integer newPayPrice = calculatePayPrice(discountProduct, orderItem);
|
||||
Integer newDiscountPrice = orderItem.getPayPrice() - newPayPrice;
|
||||
|
||||
// 3.1 记录优惠明细
|
||||
if (orderItem.getSelected()) {
|
||||
// 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
|
||||
TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||
discountProduct.getActivityId(), discountProduct.getActivityName(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(),
|
||||
StrUtil.format("限时折扣:省 {} 元", formatPrice(newDiscountPrice)),
|
||||
newDiscountPrice);
|
||||
|
||||
//----------------------------------会员计算-----------------------------------------
|
||||
MemberLevelRespDTO level;
|
||||
// 获得用户的会员等级
|
||||
MemberUserRespDTO user = memberUserApi.getUser(param.getUserId());
|
||||
if (user.getLevelId() != null && user.getLevelId() > 0) {
|
||||
level = memberLevelApi.getMemberLevel(user.getLevelId());
|
||||
if (level != null && level.getDiscountPercent() != null) {
|
||||
vip = true;
|
||||
}else {
|
||||
vip = false;
|
||||
}
|
||||
// 3.2 更新 SKU 优惠金额
|
||||
orderItem.setDiscountPrice(orderItem.getDiscountPrice() + newDiscountPrice);
|
||||
}else {
|
||||
level = null;
|
||||
vip = false;
|
||||
}
|
||||
|
||||
|
||||
// 2. 计算每个 SKU 的优惠金额
|
||||
result.getItems().forEach(orderItem -> {
|
||||
|
||||
//----------------------------------限时折扣计算-----------------------------------------
|
||||
DiscountProductRespDTO discountProduct = null;
|
||||
Integer newDiscountPrice = 0;
|
||||
if (discount){
|
||||
// 2.1 计算限时折扣优惠信息
|
||||
discountProduct = discountProductMap.get(orderItem.getSkuId());
|
||||
if (discountProduct != null) {
|
||||
// 2.2 计算优惠金额
|
||||
Integer newPayPrice = calculatePayPrice(discountProduct, orderItem);
|
||||
newDiscountPrice = orderItem.getPayPrice() - newPayPrice;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------会员计算-----------------------------------------
|
||||
Integer vipPrice = 0;
|
||||
if (vip){
|
||||
// 2.3 计算会员优惠金额
|
||||
vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent());
|
||||
}
|
||||
|
||||
|
||||
// 2.4 记录优惠明细
|
||||
// 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
|
||||
if (orderItem.getSelected()) {
|
||||
if (discount && vip){
|
||||
if(newDiscountPrice > vipPrice){
|
||||
TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||
discountProduct.getActivityId(), discountProduct.getActivityName(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(),
|
||||
StrUtil.format("限时折扣:省 {} 元", formatPrice(newDiscountPrice)),
|
||||
newDiscountPrice);
|
||||
// 2.5 更新 SKU 优惠金额
|
||||
orderItem.setDiscountPrice(orderItem.getDiscountPrice() + newDiscountPrice);
|
||||
}else{
|
||||
TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||
level.getId(), level.getName(), PromotionTypeEnum.MEMBER_LEVEL.getType(),
|
||||
String.format("会员等级折扣:省 %s 元", formatPrice(vipPrice)),
|
||||
vipPrice);
|
||||
// 2.5 更新 SKU 的优惠金额
|
||||
orderItem.setVipPrice(vipPrice);
|
||||
}
|
||||
}else if (discount){
|
||||
TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||
discountProduct.getActivityId(), discountProduct.getActivityName(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(),
|
||||
StrUtil.format("限时折扣:省 {} 元", formatPrice(newDiscountPrice)),
|
||||
newDiscountPrice);
|
||||
// 2.5 更新 SKU 优惠金额
|
||||
orderItem.setDiscountPrice(orderItem.getDiscountPrice() + newDiscountPrice);
|
||||
}else if (vip){
|
||||
TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||
level.getId(), level.getName(), PromotionTypeEnum.MEMBER_LEVEL.getType(),
|
||||
String.format("会员等级折扣:省 %s 元", formatPrice(vipPrice)),
|
||||
vipPrice);
|
||||
// 2.5 更新 SKU 的优惠金额
|
||||
orderItem.setVipPrice(vipPrice);
|
||||
}
|
||||
}
|
||||
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
});
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
|
@ -86,4 +162,20 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
|
|||
return price;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算会员 VIP 优惠价格
|
||||
*
|
||||
* @param price 原价
|
||||
* @param discountPercent 折扣
|
||||
* @return 优惠价格
|
||||
*/
|
||||
public Integer calculateVipPrice(Integer price, Integer discountPercent) {
|
||||
if (discountPercent == null) {
|
||||
return 0;
|
||||
}
|
||||
BigDecimal divide = new BigDecimal(price).multiply(new BigDecimal(discountPercent)).divide(new BigDecimal(100));
|
||||
Integer newPrice = divide.intValue();
|
||||
return price - newPrice;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,44 +30,49 @@ public class TradeMemberLevelPriceCalculator implements TradePriceCalculator {
|
|||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
/**
|
||||
* 会员计算迁移到限时优惠计算里
|
||||
* @param param
|
||||
* @param result
|
||||
*/
|
||||
@Override
|
||||
public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
|
||||
// 0. 只有【普通】订单,才计算该优惠
|
||||
if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) {
|
||||
return;
|
||||
}
|
||||
// 1. 获得用户的会员等级
|
||||
MemberUserRespDTO user = memberUserApi.getUser(param.getUserId());
|
||||
if (user.getLevelId() == null || user.getLevelId() <= 0) {
|
||||
return;
|
||||
}
|
||||
MemberLevelRespDTO level = memberLevelApi.getMemberLevel(user.getLevelId());
|
||||
if (level == null || level.getDiscountPercent() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 计算每个 SKU 的优惠金额
|
||||
result.getItems().forEach(orderItem -> {
|
||||
// 2.1 计算优惠金额
|
||||
Integer vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent());
|
||||
if (vipPrice <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2.2 记录优惠明细
|
||||
if (orderItem.getSelected()) {
|
||||
// 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
|
||||
TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||
level.getId(), level.getName(), PromotionTypeEnum.MEMBER_LEVEL.getType(),
|
||||
String.format("会员等级折扣:省 %s 元", formatPrice(vipPrice)),
|
||||
vipPrice);
|
||||
}
|
||||
|
||||
// 2.3 更新 SKU 的优惠金额
|
||||
orderItem.setVipPrice(vipPrice);
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
});
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
// // 0. 只有【普通】订单,才计算该优惠
|
||||
// if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) {
|
||||
// return;
|
||||
// }
|
||||
// // 1. 获得用户的会员等级
|
||||
// MemberUserRespDTO user = memberUserApi.getUser(param.getUserId());
|
||||
// if (user.getLevelId() == null || user.getLevelId() <= 0) {
|
||||
// return;
|
||||
// }
|
||||
// MemberLevelRespDTO level = memberLevelApi.getMemberLevel(user.getLevelId());
|
||||
// if (level == null || level.getDiscountPercent() == null) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 2. 计算每个 SKU 的优惠金额
|
||||
// result.getItems().forEach(orderItem -> {
|
||||
// // 2.1 计算优惠金额
|
||||
// Integer vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent());
|
||||
// if (vipPrice <= 0) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 2.2 记录优惠明细
|
||||
// if (orderItem.getSelected()) {
|
||||
// // 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
|
||||
// TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||
// level.getId(), level.getName(), PromotionTypeEnum.MEMBER_LEVEL.getType(),
|
||||
// String.format("会员等级折扣:省 %s 元", formatPrice(vipPrice)),
|
||||
// vipPrice);
|
||||
// }
|
||||
//
|
||||
// // 2.3 更新 SKU 的优惠金额
|
||||
// orderItem.setVipPrice(vipPrice);
|
||||
// TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
// });
|
||||
// TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,7 +23,10 @@ import java.util.Comparator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.framework.common.util.collection.CollectionUtils.filterList;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.REWARD_ACTIVITY_TYPE_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice;
|
||||
|
||||
// TODO @puhui999:相关的单测,建议改一改
|
||||
|
@ -47,14 +50,15 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
|
|||
return;
|
||||
}
|
||||
// 获得 SKU 对应的满减送活动
|
||||
List<RewardActivityMatchRespDTO> rewardActivities = rewardActivityApi.getRewardActivityListByStatusAndNow(
|
||||
CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
|
||||
List<RewardActivityMatchRespDTO> rewardActivities = rewardActivityApi.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(
|
||||
convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId), CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
|
||||
if (CollUtil.isEmpty(rewardActivities)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理每个满减送活动
|
||||
rewardActivities.forEach(rewardActivity -> calculate(param, result, rewardActivity));
|
||||
// 处理最新的满减送活动
|
||||
if(!rewardActivities.isEmpty()){
|
||||
calculate(param, result, rewardActivities.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
private void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result,
|
||||
|
@ -77,6 +81,8 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
|
|||
Integer newDiscountPrice = rule.getDiscountPrice();
|
||||
// 2.2 计算分摊的优惠金额
|
||||
List<Integer> divideDiscountPrices = TradePriceCalculatorHelper.dividePrice(orderItems, newDiscountPrice);
|
||||
//计算是否包邮
|
||||
result.setFreeDelivery(rule.getFreeDelivery());
|
||||
|
||||
// 3.1 记录使用的优惠劵
|
||||
result.setCouponId(param.getCouponId());
|
||||
|
@ -119,27 +125,24 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
|
|||
/**
|
||||
* 获得满减送的订单项(商品)列表
|
||||
*
|
||||
* @param result 计算结果
|
||||
* @param result 计算结果
|
||||
* @param rewardActivity 满减送活动
|
||||
* @return 订单项(商品)列表
|
||||
*/
|
||||
private List<TradePriceCalculateRespBO.OrderItem> filterMatchActivityOrderItems(TradePriceCalculateRespBO result,
|
||||
RewardActivityMatchRespDTO rewardActivity) {
|
||||
// 情况一:全部商品都可以参与
|
||||
if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
|
||||
Integer productScope = rewardActivity.getProductScope();
|
||||
if(PromotionProductScopeEnum.isAll(productScope)){
|
||||
return result.getItems();
|
||||
}
|
||||
// 情况二:指定商品参与
|
||||
if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
|
||||
}else if (PromotionProductScopeEnum.isSpu(productScope)) {
|
||||
return filterList(result.getItems(),
|
||||
orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getSpuId()));
|
||||
}
|
||||
// 情况三:指定商品类型参与
|
||||
if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
|
||||
}else if (PromotionProductScopeEnum.isCategory(productScope)) {
|
||||
return filterList(result.getItems(),
|
||||
orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getCategoryId()));
|
||||
}else{
|
||||
throw exception(REWARD_ACTIVITY_TYPE_NOT_EXISTS);
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
|
||||
import cn.iocoder.yudao.module.infra.api.file.FileApi;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
|
||||
|
@ -104,6 +105,7 @@ public class AdminUserServiceImpl implements AdminUserService {
|
|||
AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class);
|
||||
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
|
||||
user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码
|
||||
user.setTenantId(TenantContextHolder.getRequiredTenantId());
|
||||
userMapper.insert(user);
|
||||
// 2.2 插入关联岗位
|
||||
if (CollectionUtil.isNotEmpty(user.getPostIds())) {
|
||||
|
|
|
@ -6,7 +6,7 @@ spring:
|
|||
# 数据源配置项
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置
|
||||
#- org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置
|
||||
- de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
|
||||
- de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
|
||||
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
|
||||
|
@ -45,7 +45,7 @@ spring:
|
|||
primary: master
|
||||
datasource:
|
||||
master:
|
||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
|
||||
url: jdbc:mysql://192.168.10.207:3306/specialty?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
|
||||
# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例
|
||||
# url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
|
||||
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
|
||||
|
@ -61,19 +61,19 @@ spring:
|
|||
# password: SYSDBA001 # DM 连接的示例
|
||||
# username: root # OpenGauss 连接的示例
|
||||
# password: Yudao@2024 # OpenGauss 连接的示例
|
||||
slave: # 模拟从库,可根据自己需要修改
|
||||
lazy: true # 开启懒加载,保证启动速度
|
||||
url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: 123456
|
||||
# slave: # 模拟从库,可根据自己需要修改
|
||||
# lazy: true # 开启懒加载,保证启动速度
|
||||
# url: jdbc:mysql://192.168.10.207:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
|
||||
# username: root
|
||||
# password: 123456
|
||||
|
||||
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
|
||||
data:
|
||||
redis:
|
||||
host: 127.0.0.1 # 地址
|
||||
host: 192.168.10.207 # 地址
|
||||
port: 6379 # 端口
|
||||
database: 0 # 数据库索引
|
||||
# password: dev # 密码,建议生产环境开启
|
||||
password: 123456 # 密码,建议生产环境开启
|
||||
|
||||
--- #################### 定时任务相关配置 ####################
|
||||
|
||||
|
@ -200,8 +200,8 @@ wx:
|
|||
# secret: 6f270509224a7ae1296bbf1c8cb97aed
|
||||
# appid: wxc4598c446f8a9cb3 # 测试号(Kongdy 提供的)
|
||||
# secret: 4a1a04e07f6a4a0751b39c3064a92c8b
|
||||
appid: wx66186af0759f47c9 # 测试号(puhui 提供的)
|
||||
secret: 3218bcbd112cbc614c7264ceb20144ac
|
||||
appid: wx9a0a5b259d852380 # 测试号(puhui 提供的)
|
||||
secret: 70e65fa9d1a4f2c4e1b2aa8751d3b75e
|
||||
config-storage:
|
||||
type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取
|
||||
key-prefix: wa # Redis Key 的前缀
|
||||
|
|
Loading…
Reference in New Issue