mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 01:01:52 +08:00
【功能】完成商品列表价格计算时,需要支持减免金额的功能
This commit is contained in:
parent
e47b3f0aab
commit
e44c0e668e
@ -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 不存在");
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get();
|
||||
activityList.add(new AppActivityRespVO(rewardActivityDO.getId(), PromotionTypeEnum.REWARD_ACTIVITY.getType(),
|
||||
rewardActivityDO.getName(), supId, rewardActivityDO.getStartTime(), rewardActivityDO.getEndTime()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,19 @@
|
||||
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 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 +30,47 @@ 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, 2).and(i1 -> i1.apply(productScopeValuesFindInSetFunc.apply(spuIds))))
|
||||
.or(i -> i.eq(RewardActivityDO::getProductScope, 1))
|
||||
.or(i -> i. eq(RewardActivityDO::getProductScope, 3).and(i1 -> i1.apply(productScopeValuesFindInSetFunc.apply(categoryIds))))
|
||||
.orderByDesc(RewardActivityDO::getId)
|
||||
.last("limit 1")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
@ -22,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;
|
||||
@ -205,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
</foreach>
|
||||
</if>
|
||||
AND pda.start_time <= CURRENT_TIME AND pda.end_time >= CURRENT_TIME
|
||||
AND pda.`status` = 20
|
||||
AND pda.`status` = 0
|
||||
AND pda.deleted != 1
|
||||
</where>
|
||||
</select>
|
||||
|
@ -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,51 @@ 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());
|
||||
if(skuDiscount != null){
|
||||
skus.add(skuDiscount);
|
||||
}
|
||||
|
||||
//查询会员价
|
||||
AppTradeProductSettlementRespVO.Sku skuVip = calculateVipPrice(sku.getId(), sku.getPrice(), memberLevel);
|
||||
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 +260,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(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)
|
||||
.rewardId(rewardActivityMatchRespDTO.getId()).build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
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 = "商品编号", 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 rewardId;
|
||||
|
||||
@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") //PromotionTypeEnum
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "限时优惠id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Long discountId;
|
||||
|
||||
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime endTime;
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice;
|
||||
|
||||
@ -47,8 +48,8 @@ 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;
|
||||
}
|
||||
|
@ -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
Block a user