code review:营销活动+订单

This commit is contained in:
YunaiV 2023-09-09 01:27:55 +08:00
parent 5235aff8ad
commit 87c55784c4
18 changed files with 96 additions and 67 deletions

View File

@ -68,14 +68,6 @@ public class CommonResult<T> implements Serializable {
return result; return result;
} }
public static <T> CommonResult<T> success(T data, String msg) {
CommonResult<T> result = new CommonResult<>();
result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
result.data = data;
result.msg = msg;
return result;
}
public static boolean isSuccess(Integer code) { public static boolean isSuccess(Integer code) {
return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode()); return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode());
} }

View File

@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillActivityUpdateSt
*/ */
public interface SeckillActivityApi { public interface SeckillActivityApi {
/** /**
* 更新秒杀库存 * 更新秒杀库存
* *

View File

@ -12,6 +12,10 @@ import java.util.List;
@Data @Data
public class SeckillActivityUpdateStockReqDTO { public class SeckillActivityUpdateStockReqDTO {
// TODO @puhui999参数校验
// TODO @puhui999秒杀的话一次只能购买一种商品哈不能多个哈
/** /**
* 活动编号 * 活动编号
*/ */

View File

@ -23,6 +23,7 @@ public class BargainActivityApiImpl implements BargainActivityApi {
@Override @Override
public void updateBargainActivityStock(Long activityId, Integer count) { public void updateBargainActivityStock(Long activityId, Integer count) {
// TODO @puhui999可以整个实现到 bargainActivityService
// 查询砍价活动 // 查询砍价活动
BargainActivityDO activity = bargainActivityService.getBargainActivity(activityId); BargainActivityDO activity = bargainActivityService.getBargainActivity(activityId);
if (activity == null) { if (activity == null) {
@ -30,6 +31,7 @@ public class BargainActivityApiImpl implements BargainActivityApi {
} }
// 更新砍价库存 // 更新砍价库存
// TODO @puhui999考虑下并发更新问题
BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO(); BargainActivityUpdateReqVO reqVO = new BargainActivityUpdateReqVO();
reqVO.setId(activityId); reqVO.setId(activityId);
reqVO.setStock(activity.getStock() - count); reqVO.setStock(activity.getStock() - count);

View File

@ -27,14 +27,19 @@ public class SeckillActivityApiImpl implements SeckillActivityApi {
@Resource @Resource
private SeckillActivityService activityService; private SeckillActivityService activityService;
// TODO @puhui建议这块弄到 activityService 实现哈
// TODO @puhui这个方法要考虑事务性
@Override @Override
public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) { public void updateSeckillStock(SeckillActivityUpdateStockReqDTO updateStockReqDTO) {
// TODO @puhui999长方法最好有 1.1 1.2 2.1 这种步骤哈
SeckillActivityDO seckillActivity = activityService.getSeckillActivity(updateStockReqDTO.getActivityId()); SeckillActivityDO seckillActivity = activityService.getSeckillActivity(updateStockReqDTO.getActivityId());
if (seckillActivity.getStock() < updateStockReqDTO.getCount()) { if (seckillActivity.getStock() < updateStockReqDTO.getCount()) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
} }
// 获取活动商品 // 获取活动商品
// TODO @puhui999在一个方法里dos dolist 最好保持一致要么用 s要么用 list
List<SeckillProductDO> productDOs = activityService.getSeckillProductListByActivityId(updateStockReqDTO.getActivityId()); List<SeckillProductDO> productDOs = activityService.getSeckillProductListByActivityId(updateStockReqDTO.getActivityId());
// TODO @puhui999这个是不是搞成 CollectionUtils.convertMultiMap()
List<SeckillActivityUpdateStockReqDTO.Item> items = updateStockReqDTO.getItems(); List<SeckillActivityUpdateStockReqDTO.Item> items = updateStockReqDTO.getItems();
Map<Long, List<Long>> map = new HashMap<>(); Map<Long, List<Long>> map = new HashMap<>();
items.forEach(item -> { items.forEach(item -> {
@ -49,9 +54,11 @@ public class SeckillActivityApiImpl implements SeckillActivityApi {
} }
}); });
// 过滤出购买的商品 // 过滤出购买的商品
// TODO @puhui999productDOList 可以简化成 productList一般来说do 之类不用带着哈在变量里
List<SeckillProductDO> productDOList = CollectionUtils.filterList(productDOs, item -> map.get(item.getSpuId()).contains(item.getSkuId())); List<SeckillProductDO> productDOList = CollectionUtils.filterList(productDOs, item -> map.get(item.getSpuId()).contains(item.getSkuId()));
Map<Long, SeckillActivityUpdateStockReqDTO.Item> productDOMap = CollectionUtils.convertMap(items, SeckillActivityUpdateStockReqDTO.Item::getSkuId, p -> p); Map<Long, SeckillActivityUpdateStockReqDTO.Item> productDOMap = CollectionUtils.convertMap(items, SeckillActivityUpdateStockReqDTO.Item::getSkuId, p -> p);
// 检查活动商品库存是否充足 // 检查活动商品库存是否充足
// TODO @puhui999避免 b 这种无业务含义的变量
boolean b = CollectionUtils.anyMatch(productDOList, item -> { boolean b = CollectionUtils.anyMatch(productDOList, item -> {
SeckillActivityUpdateStockReqDTO.Item item1 = productDOMap.get(item.getSkuId()); SeckillActivityUpdateStockReqDTO.Item item1 = productDOMap.get(item.getSkuId());
return (item.getStock() < item1.getCount()) || (item.getStock() - item1.getCount()) < 0; return (item.getStock() < item1.getCount()) || (item.getStock() - item1.getCount()) < 0;
@ -59,17 +66,19 @@ public class SeckillActivityApiImpl implements SeckillActivityApi {
if (b) { if (b) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL); throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
} }
// TODO @puhui999类似 doList应该和下面的 update 逻辑粘的更紧密一点so 在空行的时候应该挪到 74 之后里去甚至更合理应该是 79 之后说白了逻辑要分块每个模块涉及的代码要紧密在一起
List<SeckillProductDO> doList = CollectionUtils.convertList(productDOList, item -> { List<SeckillProductDO> doList = CollectionUtils.convertList(productDOList, item -> {
item.setStock(item.getStock() - productDOMap.get(item.getSkuId()).getCount()); item.setStock(item.getStock() - productDOMap.get(item.getSkuId()).getCount());
return item; return item;
}); });
// 更新活动库存 // 更新活动库存
// TODO @puhui999考虑下并发更新
seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount()); seckillActivity.setStock(seckillActivity.getStock() + updateStockReqDTO.getCount());
seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount()); seckillActivity.setTotalStock(seckillActivity.getTotalStock() - updateStockReqDTO.getCount());
activityService.updateSeckillActivity(seckillActivity); activityService.updateSeckillActivity(seckillActivity);
// 更新活动商品库存 // 更新活动商品库存
activityService.updateSeckillActivityProductByList(doList); activityService.updateSeckillActivityProductList(doList);
} }
} }

View File

@ -9,6 +9,7 @@ import lombok.*;
import java.time.LocalDateTime; import java.time.LocalDateTime;
// TODO 芋艿把字段的顺序 do 顺序对齐下
/** /**
* 拼团记录 DO * 拼团记录 DO
* *
@ -27,34 +28,28 @@ import java.time.LocalDateTime;
@AllArgsConstructor @AllArgsConstructor
public class CombinationRecordDO extends BaseDO { public class CombinationRecordDO extends BaseDO {
/**
* 编号主键自增
*/
@TableId @TableId
private Long id; private Long id;
/** /**
* 拼团活动编号 * 拼团活动编号
*
* 关联 {@link CombinationActivityDO#getId()}
*/ */
private Long activityId; private Long activityId;
/**
* 拼团商品单价
*
* 冗余 {@link CombinationProductDO#getCombinationPrice()}
*/
private Integer combinationPrice;
/** /**
* SPU 编号 * SPU 编号
*/ */
private Long spuId; private Long spuId;
/**
* SKU 编号
*/
private Long skuId;
/**
* 用户编号
*/
private Long userId;
/**
* 订单编号
*/
private Long orderId;
/**
* 团长编号
*
* 关联 {@link CombinationRecordDO#getId()}
*/
private Long headId;
/** /**
* 商品名字 * 商品名字
*/ */
@ -64,9 +59,14 @@ public class CombinationRecordDO extends BaseDO {
*/ */
private String picUrl; private String picUrl;
/** /**
* 拼团商品单价 * SKU 编号
*/ */
private Integer combinationPrice; private Long skuId;
/**
* 用户编号
*/
private Long userId;
/** /**
* 用户昵称 * 用户昵称
*/ */
@ -75,6 +75,13 @@ public class CombinationRecordDO extends BaseDO {
* 用户头像 * 用户头像
*/ */
private String avatar; private String avatar;
/**
* 团长编号
*
* 关联 {@link CombinationRecordDO#getId()}
*/
private Long headId;
/** /**
* 开团状态 * 开团状态
* *
@ -82,23 +89,9 @@ public class CombinationRecordDO extends BaseDO {
*/ */
private Integer status; private Integer status;
/** /**
* 是否虚拟成团 * 订单编号
*/ */
private Boolean virtualGroup; private Long orderId;
/**
* 过期时间
*
* {@link CombinationRecordDO#getStartTime()} + {@link CombinationActivityDO#getLimitDuration()} 计算
*/
private LocalDateTime expireTime;
/**
* 开始时间 (订单付款后开始的时间)
*/
private LocalDateTime startTime;
/**
* 结束时间成团时间/失败时间
*/
private LocalDateTime endTime;
/** /**
* 开团需要人数 * 开团需要人数
* *
@ -109,5 +102,24 @@ public class CombinationRecordDO extends BaseDO {
* 已加入拼团人数 * 已加入拼团人数
*/ */
private Integer userCount; private Integer userCount;
/**
* 是否虚拟成团
*/
private Boolean virtualGroup;
/**
* 过期时间
*
* 基于 {@link CombinationRecordDO#getStartTime()} + {@link CombinationActivityDO#getLimitDuration()} 计算
*/
private LocalDateTime expireTime;
/**
* 开始时间 (订单付款后开始的时间)
*/
private LocalDateTime startTime;
/**
* 结束时间成团时间/失败时间
*/
private LocalDateTime endTime;
} }

View File

@ -43,9 +43,9 @@ public interface SeckillActivityService {
/** /**
* 更新秒杀活动商品 * 更新秒杀活动商品
* *
* @param productDOList 活动商品列表 * @param productList 活动商品列表
*/ */
void updateSeckillActivityProductByList(List<SeckillProductDO> productDOList); void updateSeckillActivityProductList(List<SeckillProductDO> productList);
/** /**
* 关闭秒杀活动 * 关闭秒杀活动

View File

@ -93,8 +93,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId));
} }
// 2.2 过滤出所有 configIds 有交集的活动判断是否存在重叠 // 2.2 过滤出所有 configIds 有交集的活动判断是否存在重叠
List<SeckillActivityDO> activityDOs = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds)); List<SeckillActivityDO> conflictActivityList = filterList(activityList, s -> containsAny(s.getConfigIds(), configIds));
if (isNotEmpty(activityDOs)) { if (isNotEmpty(conflictActivityList)) {
throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS); throw exception(SECKILL_ACTIVITY_SPU_CONFLICTS);
} }
} }
@ -150,8 +150,8 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
} }
@Override @Override
public void updateSeckillActivityProductByList(List<SeckillProductDO> productDOList) { public void updateSeckillActivityProductList(List<SeckillProductDO> productList) {
seckillProductMapper.updateBatch(productDOList); seckillProductMapper.updateBatch(productList);
} }
/** /**

View File

@ -36,7 +36,6 @@ 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.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.AFTER_SALE_NOT_FOUND;
@Tag(name = "管理后台 - 售后订单") @Tag(name = "管理后台 - 售后订单")
@RestController @RestController
@ -77,9 +76,11 @@ public class TradeAfterSaleController {
public CommonResult<TradeAfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) { public CommonResult<TradeAfterSaleDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
// 查询订单 // 查询订单
TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id); TradeAfterSaleDO afterSale = afterSaleService.getAfterSale(id);
if (afterSale == null) { // TODO @puhui999这里建议改成如果为 null直接返回 success null主要查询操作尽量不要有非空的提示哈交给前端处理
return success(null, AFTER_SALE_NOT_FOUND.getMsg()); // if (afterSale == null) {
} // return success(null, AFTER_SALE_NOT_FOUND.getMsg());
// }
// 查询订单 // 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId()); TradeOrderDO order = tradeOrderQueryService.getOrder(afterSale.getOrderId());
// 查询订单项 // 查询订单项

View File

@ -25,7 +25,6 @@ import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 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.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;
@Tag(name = "管理后台 - 交易订单") @Tag(name = "管理后台 - 交易订单")
@RestController @RestController
@ -68,9 +67,11 @@ public class TradeOrderController {
public CommonResult<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) { public CommonResult<TradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id) {
// 查询订单 // 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(id); TradeOrderDO order = tradeOrderQueryService.getOrder(id);
if (order == null) { // TODO @puhui999这里建议改成如果为 null直接返回 success null主要查询操作尽量不要有非空的提示哈交给前端处理
return success(null, ORDER_NOT_FOUND.getMsg()); // if (order == null) {
} // return success(null, ORDER_NOT_FOUND.getMsg());
// }
// 查询订单项 // 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id); List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(id);
// orderLog // orderLog

View File

@ -33,7 +33,6 @@ 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.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;
@Tag(name = "用户 App - 交易订单") @Tag(name = "用户 App - 交易订单")
@RestController @RestController
@ -82,9 +81,10 @@ public class AppTradeOrderController {
public CommonResult<AppTradeOrderDetailRespVO> getOrder(@RequestParam("id") Long id) { public CommonResult<AppTradeOrderDetailRespVO> getOrder(@RequestParam("id") Long id) {
// 查询订单 // 查询订单
TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id); TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id);
if (order == null) { // TODO @puhui999这里建议改成如果为 null直接返回 success null主要查询操作尽量不要有非空的提示哈交给前端处理
return success(null, ORDER_NOT_FOUND.getMsg()); // if (order == null) {
} // return success(null, ORDER_NOT_FOUND.getMsg());
// }
// 查询订单项 // 查询订单项
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId()); List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());

View File

@ -50,6 +50,7 @@ public class AppTradeOrderSettlementReqVO {
private Long seckillActivityId; private Long seckillActivityId;
// ========== 拼团活动相关字段 ========== // ========== 拼团活动相关字段 ==========
// TODO @puhui999是不是拼团记录的编号哈
@Schema(description = "拼团活动编号", example = "1024") @Schema(description = "拼团活动编号", example = "1024")
private Long combinationActivityId; private Long combinationActivityId;
@ -57,6 +58,7 @@ public class AppTradeOrderSettlementReqVO {
private Long combinationHeadId; private Long combinationHeadId;
// ========== 砍价活动相关字段 ========== // ========== 砍价活动相关字段 ==========
// TODO @puhui999是不是砍价记录的编号哈
@Schema(description = "砍价活动编号", example = "123") @Schema(description = "砍价活动编号", example = "123")
private Long bargainActivityId; private Long bargainActivityId;

View File

@ -15,6 +15,7 @@ import java.time.LocalDateTime;
*/ */
@Repository @Repository
public class TradeOrderNoRedisDAO { public class TradeOrderNoRedisDAO {
public static final String TRADE_ORDER_NO_PREFIX = "O"; public static final String TRADE_ORDER_NO_PREFIX = "O";
@Resource @Resource

View File

@ -561,6 +561,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
} }
@Override @Override
// TODO @puhui999考虑事务性
public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) { public void updateOrderPrice(TradeOrderUpdatePriceReqVO reqVO) {
// 校验交易订单 // 校验交易订单
TradeOrderDO order = validateOrderExists(reqVO.getId()); TradeOrderDO order = validateOrderExists(reqVO.getId());
@ -571,6 +572,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
throw exception(ORDER_UPDATE_PRICE_FAIL_EQUAL); throw exception(ORDER_UPDATE_PRICE_FAIL_EQUAL);
} }
// TODO @puhui999应该是按照 payPrice 分配并且要考虑取余问题payPrice 也要考虑item 里的
List<TradeOrderItemDO> itemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId()); List<TradeOrderItemDO> itemDOs = tradeOrderItemMapper.selectListByOrderId(order.getId());
// TradeOrderItemDO 需要做 adjustPrice 的分摊 // TradeOrderItemDO 需要做 adjustPrice 的分摊
int price = reqVO.getAdjustPrice() / itemDOs.size(); int price = reqVO.getAdjustPrice() / itemDOs.size();
@ -578,8 +580,10 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
item.setAdjustPrice(price); item.setAdjustPrice(price);
}); });
// 更新 TradeOrderItem // 更新 TradeOrderItem
// TODO @puhui999不要整个对象去更新哈应该 new 一下
tradeOrderItemMapper.updateBatch(itemDOs); tradeOrderItemMapper.updateBatch(itemDOs);
// 更新订单 // 更新订单
// TODO @puhui999要考虑多次修改价格不能单单的 payPrice + 价格
TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO); TradeOrderDO update = TradeOrderConvert.INSTANCE.convert(reqVO);
update.setPayPrice(update.getPayPrice() + update.getAdjustPrice()); update.setPayPrice(update.getPayPrice() + update.getAdjustPrice());
// TODO @芋艿改价时赠送的积分要不要做改动 // TODO @芋艿改价时赠送的积分要不要做改动

View File

@ -29,6 +29,7 @@ public interface PayOrderApi {
*/ */
PayOrderRespDTO getOrder(Long id); PayOrderRespDTO getOrder(Long id);
// TODO @puhui999可以去掉 byId然后 payOrderId 参数改成 id
/** /**
* 更新支付订单价格 * 更新支付订单价格
* *
@ -36,4 +37,5 @@ public interface PayOrderApi {
* @param payPrice 支付单价格 * @param payPrice 支付单价格
*/ */
void updatePayOrderPriceById(Long payOrderId, Integer payPrice); void updatePayOrderPriceById(Long payOrderId, Integer payPrice);
} }

View File

@ -36,5 +36,4 @@ public class PayOrderApiImpl implements PayOrderApi {
payOrderService.updatePayOrderPriceById(payOrderId, payPrice); payOrderService.updatePayOrderPriceById(payOrderId, payPrice);
} }
} }

View File

@ -413,6 +413,7 @@ public class PayOrderServiceImpl implements PayOrderService {
@Override @Override
public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) { public void updatePayOrderPriceById(Long payOrderId, Integer payPrice) {
// TODO @puhui999不能直接这样修改哈应该只有未支付状态的订单才可以改另外如果价格如果没变可以直接 return
PayOrderDO order = orderMapper.selectById(payOrderId); PayOrderDO order = orderMapper.selectById(payOrderId);
if (order == null) { if (order == null) {
throw exception(ORDER_NOT_FOUND); throw exception(ORDER_NOT_FOUND);