Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product

# Conflicts:
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateReqBO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/bo/TradePriceCalculateRespBO.java
This commit is contained in:
puhui999
2023-09-25 15:06:57 +08:00
191 changed files with 3419 additions and 1168 deletions

View File

@@ -24,14 +24,12 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
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.convertList;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COMBINATION_ACTIVITY_APP_STATUS_DISABLE;
@Tag(name = "用户 APP - 拼团活动")
@RestController
@@ -44,7 +42,7 @@ public class AppCombinationActivityController {
@Resource
private ProductSpuApi spuApi;
// TODO 芋艿:增加 Spring Cache
@GetMapping("/list")
@Operation(summary = "获得拼团活动列表", description = "用于小程序首页")
@Parameter(name = "count", description = "需要展示的数量", example = "6")
@@ -52,11 +50,10 @@ public class AppCombinationActivityController {
@RequestParam(name = "count", defaultValue = "6") Integer count) {
List<CombinationActivityDO> list = activityService.getCombinationActivityListByCount(defaultIfNull(count, 6));
if (CollUtil.isEmpty(list)) {
return success(CombinationActivityConvert.INSTANCE.convertAppList(list));
return success(Collections.emptyList());
}
// 拼接返回
List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(list, CombinationActivityDO::getSpuId));
// TODO 芋艿:增加 Spring Cache
return success(CombinationActivityConvert.INSTANCE.convertAppList(list, spuList));
}
@@ -67,7 +64,7 @@ public class AppCombinationActivityController {
if (CollUtil.isEmpty(result.getList())) {
return success(PageResult.empty(result.getTotal()));
}
// 拼接返回
List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(result.getList(), CombinationActivityDO::getSpuId));
return success(CombinationActivityConvert.INSTANCE.convertAppPage(result, spuList));
}
@@ -78,15 +75,12 @@ public class AppCombinationActivityController {
public CommonResult<AppCombinationActivityDetailRespVO> getCombinationActivityDetail(@RequestParam("id") Long id) {
// 1、获取活动
CombinationActivityDO combinationActivity = activityService.getCombinationActivity(id);
if (combinationActivity == null) {
if (combinationActivity == null
|| ObjectUtil.equal(combinationActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
return success(null);
}
if (ObjectUtil.equal(combinationActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
throw exception(COMBINATION_ACTIVITY_APP_STATUS_DISABLE);
}
// 2、获取活动商品
List<CombinationProductDO> products = activityService.getCombinationProductsByActivityIds(Arrays.asList(combinationActivity.getId()));
List<CombinationProductDO> products = activityService.getCombinationProductsByActivityId(combinationActivity.getId());
return success(CombinationActivityConvert.INSTANCE.convert3(combinationActivity, products));
}

View File

@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.promotion.controller.app.seckill;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@@ -29,10 +30,8 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
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.convertList;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_APP_STATUS_CLOSED;
@Tag(name = "用户 App - 秒杀活动")
@RestController
@@ -48,6 +47,7 @@ public class AppSeckillActivityController {
@Resource
private ProductSpuApi spuApi;
// TODO 芋艿:需要增加 spring cache
@GetMapping("/get-now")
@Operation(summary = "获得当前秒杀活动", description = "获取当前正在进行的活动,提供给首页使用")
public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() {
@@ -61,7 +61,6 @@ public class AppSeckillActivityController {
List<SeckillActivityDO> activityList = activityService.getSeckillActivityListByConfigIdAndStatus(configList.getId(), CommonStatusEnum.ENABLE.getStatus());
// 3 获取 spu 信息
List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(activityList, SeckillActivityDO::getSpuId));
// TODO 芋艿:需要增加 spring cache
return success(SeckillActivityConvert.INSTANCE.convert(configList, activityList, spuList));
}
@@ -70,7 +69,9 @@ public class AppSeckillActivityController {
public CommonResult<PageResult<AppSeckillActivityRespVO>> getSeckillActivityPage(AppSeckillActivityPageReqVO pageReqVO) {
// 1. 查询满足当前阶段的活动
PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(PageResult.empty(pageResult.getTotal()));
}
// 2. 拼接数据
List<ProductSpuRespDTO> spuList = spuApi.getSpuList(convertList(pageResult.getList(), SeckillActivityDO::getSpuId));
return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, spuList));
@@ -88,16 +89,14 @@ public class AppSeckillActivityController {
// 2. 获取活动
SeckillActivityDO seckillActivity = activityService.getSeckillActivity(id);
if (seckillActivity == null) {
if (seckillActivity == null
|| ObjectUtil.equal(seckillActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
return success(null);
}
if (ObjectUtil.equal(seckillActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
throw exception(SECKILL_ACTIVITY_APP_STATUS_CLOSED);
}
// 3. 拼接数据
List<SeckillProductDO> products = activityService.getSeckillProductListByActivityId(seckillActivity.getId());
return success(SeckillActivityConvert.INSTANCE.convert3(seckillActivity, products, configList));
List<SeckillProductDO> productList = activityService.getSeckillProductListByActivityId(seckillActivity.getId());
return success(SeckillActivityConvert.INSTANCE.convert3(seckillActivity, productList, configList));
}
}

View File

@@ -28,7 +28,8 @@ public class AppSeckillConfigController {
@GetMapping("/list")
@Operation(summary = "获得秒杀时间段列表")
public CommonResult<List<AppSeckillConfigRespVO>> getSeckillConfigList() {
return success(SeckillConfigConvert.INSTANCE.convertList2(configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus())));
return success(SeckillConfigConvert.INSTANCE.convertList2(
configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus())));
}
}

View File

@@ -73,9 +73,7 @@ public interface BargainActivityConvert {
// 拼接关联属性
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
List<AppBargainActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> {
findAndThen(spuMap, item.getSpuId(), spu -> {
item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice());
});
findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
return item;
});
result.setList(list);
@@ -88,9 +86,7 @@ public interface BargainActivityConvert {
List<AppBargainActivityRespVO> activityList = convertAppList(list);
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
return CollectionUtils.convertList(activityList, item -> {
findAndThen(spuMap, item.getSpuId(), spu -> {
item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice());
});
findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
return item;
});
}

View File

@@ -61,9 +61,7 @@ public interface CombinationActivityConvert {
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
PageResult<CombinationActivityRespVO> pageResult = convertPage(page);
pageResult.getList().forEach(item -> {
MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> {
item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl());
});
MapUtils.findAndThen(spuMap, item.getSpuId(), spu -> item.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()));
item.setProducts(convertList2(productList));
});
return pageResult;
@@ -118,9 +116,7 @@ public interface CombinationActivityConvert {
List<AppCombinationActivityRespVO> activityList = convertAppList(list);
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
return CollectionUtils.convertList(activityList, item -> {
findAndThen(spuMap, item.getSpuId(), spu -> {
item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice());
});
findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
return item;
});
}

View File

@@ -114,11 +114,8 @@ public interface SeckillActivityConvert {
PageResult<AppSeckillActivityRespVO> result = convertPage1(pageResult);
Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
List<AppSeckillActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> {
findAndThen(spuMap, item.getSpuId(), spu -> {
item.setPicUrl(spu.getPicUrl())
.setMarketPrice(spu.getMarketPrice())
.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
});
findAndThen(spuMap, item.getSpuId(), spu -> item.setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice())
.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit())));
return item;
});
result.setList(list);
@@ -132,6 +129,7 @@ public interface SeckillActivityConvert {
default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) {
return convert2(seckillActivity)
.setProducts(convertList1(products))
// TODO @puhui999要不要在里面 default 一个方法,处理这个事件;简洁一点;
.setStartTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getStartTime(), "yyyy-MM-dd") + " " + filteredConfig.getStartTime(),
"yyyy-MM-dd HH:mm:ss")) // 活动开始日期和时段结合
.setEndTime(LocalDateTimeUtil.parse(LocalDateTimeUtil.format(seckillActivity.getEndTime(), "yyyy-MM-dd") + " " + filteredConfig.getEndTime(),

View File

@@ -38,7 +38,7 @@ public interface BargainActivityMapper extends BaseMapperX<BargainActivityDO> {
* @param count 扣减的库存数量
* @return 影响的行数
*/
default int updateActivityStock(Long id, int count) {
default int updateStock(Long id, int count) {
return update(null, new LambdaUpdateWrapper<BargainActivityDO>()
.eq(BargainActivityDO::getId, id)
.ge(BargainActivityDO::getStock, count)

View File

@@ -29,26 +29,12 @@ public interface CombinationActivityMapper extends BaseMapperX<CombinationActivi
return selectList(CombinationActivityDO::getStatus, status);
}
/**
* 查询 status 状态的活动分页
*
* @param pageParam 分页参数
* @param status 状态
* @return 活动分页
*/
default PageResult<CombinationActivityDO> selectPage(PageParam pageParam, Integer status) {
return selectPage(pageParam, new LambdaQueryWrapperX<CombinationActivityDO>()
.eq(CombinationActivityDO::getStatus, status));
}
/**
* 查询 status 状态的活动分页
*
* @param status 状态
* @param count 限制条数
* @return 活动分页
*/
default List<CombinationActivityDO> selectList(Integer status, Integer count) {
default List<CombinationActivityDO> selectListByStatus(Integer status, Integer count) {
return selectList(new LambdaQueryWrapperX<CombinationActivityDO>()
.eq(CombinationActivityDO::getStatus, status)
.last("LIMIT " + count));

View File

@@ -41,7 +41,7 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
* @param count 扣减的库存数量
* @return 影响的行数
*/
default int updateActivityStock(Long id, int count) {
default int updateStock(Long id, int count) {
return update(null, new LambdaUpdateWrapper<SeckillActivityDO>()
.eq(SeckillActivityDO::getId, id)
.gt(SeckillActivityDO::getTotalStock, 0)

View File

@@ -16,8 +16,13 @@ import java.util.List;
@Mapper
public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
default List<SeckillProductDO> selectListByActivityId(Long id) {
return selectList(SeckillProductDO::getActivityId, id);
default List<SeckillProductDO> selectListByActivityId(Long activityId) {
return selectList(SeckillProductDO::getActivityId, activityId);
}
default SeckillProductDO selectByActivityIdAndSkuId(Long activityId, Long skuId) {
return selectOne(SeckillProductDO::getActivityId, activityId,
SeckillProductDO::getSkuId, skuId);
}
default List<SeckillProductDO> selectListByActivityId(Collection<Long> ids) {
@@ -31,7 +36,7 @@ public interface SeckillProductMapper extends BaseMapperX<SeckillProductDO> {
* @param count 扣减的库存数量
* @return 影响的行数
*/
default int updateActivityStock(Long id, int count) {
default int updateStock(Long id, int count) {
return update(null, new LambdaUpdateWrapper<SeckillProductDO>()
.eq(SeckillProductDO::getId, id)
.gt(SeckillProductDO::getStock, count)

View File

@@ -75,16 +75,18 @@ public class BargainActivityServiceImpl implements BargainActivityService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateBargainActivityStock(Long id, Integer count) {
// 查询砍价活动
BargainActivityDO activity = getBargainActivity(id);
if (activity == null) {
throw exception(BARGAIN_ACTIVITY_NOT_EXISTS);
}
if (count > activity.getStock()) {
throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL);
}
// 更新砍价库存
int updateCount = bargainActivityMapper.updateActivityStock(id, count);
int updateCount = bargainActivityMapper.updateStock(id, count);
if (updateCount == 0) {
throw exception(BARGAIN_ACTIVITY_UPDATE_STOCK_FAIL);
}

View File

@@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationP
import javax.validation.Valid;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -65,6 +66,16 @@ public interface CombinationActivityService {
*/
PageResult<CombinationActivityDO> getCombinationActivityPage(CombinationActivityPageReqVO pageReqVO);
/**
* 获得拼团活动商品列表
*
* @param activityId 拼团活动 id
* @return 拼团活动的商品列表
*/
default List<CombinationProductDO> getCombinationProductsByActivityId(Long activityId) {
return getCombinationProductsByActivityIds(Collections.singletonList(activityId));
}
/**
* 获得拼团活动商品列表
*

View File

@@ -247,7 +247,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic
@Override
public List<CombinationActivityDO> getCombinationActivityListByCount(Integer count) {
return combinationActivityMapper.selectList(CommonStatusEnum.ENABLE.getStatus(), count);
return combinationActivityMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus(), count);
}
@Override

View File

@@ -96,12 +96,15 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
return recordDO;
}
// TODO @puhui999有一个应该在创建那要做下就是当前 activityId 已经有未支付的订单,不允许在发起新的;要么支付,要么去掉先;
@Override
@Transactional(rollbackFor = Exception.class)
public void createCombinationRecord(CombinationRecordCreateReqDTO reqDTO) {
// 1.1 校验拼团活动
CombinationActivityDO activity = combinationActivityService.validateCombinationActivityExists(reqDTO.getActivityId());
// 1.2 需要校验下,他当前是不是已经参加了该拼团;
// TODO @puhui999拼团应该可以重复参加应该去校验总共的上限哈就是 activity.totalLimitCount
CombinationRecordDO recordDO = recordMapper.selectByUserIdAndOrderId(reqDTO.getUserId(), reqDTO.getOrderId());
if (recordDO != null) {
throw exception(COMBINATION_RECORD_EXISTS);
@@ -111,6 +114,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
if (CollUtil.isNotEmpty(recordDOList)) {
throw exception(COMBINATION_RECORD_FAILED_HAVE_JOINED);
}
// TODO @puhui999有个开始时间未校验
// 1.4 校验当前活动是否过期
if (LocalDateTime.now().isAfter(activity.getEndTime())) {
throw exception(COMBINATION_RECORD_FAILED_TIME_END);
@@ -128,6 +132,8 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
}
}
// TODO @puhui999单次限购
// 2. 创建拼团记录
MemberUserRespDTO user = memberUserApi.getUser(reqDTO.getUserId());
ProductSpuRespDTO spu = productSpuApi.getSpu(reqDTO.getSpuId());

View File

@@ -150,31 +150,25 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
@Override
@Transactional(rollbackFor = Exception.class)
public void updateSeckillStock(Long id, Long skuId, Integer count) {
// 1、校验秒杀活动是否存在
// 1.1 校验活动库存是否充足
SeckillActivityDO seckillActivity = getSeckillActivity(id);
// 1.1、校验库存是否充足
if (seckillActivity.getTotalStock() < count) {
if (count > seckillActivity.getTotalStock()) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
}
// 1.2 校验商品库存是否充足
SeckillProductDO product = seckillProductMapper.selectByActivityIdAndSkuId(id, skuId);
if (product == null || count > product.getStock()) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
}
// 2、获取活动商品
List<SeckillProductDO> products = getSeckillProductListByActivityId(id);
// 2.1、过滤出购买的商品
SeckillProductDO product = findFirst(products, item -> ObjectUtil.equal(skuId, item.getSkuId()));
// 2.2、检查活动商品库存是否充足
boolean isSufficient = product == null || (product.getStock() == 0 || (product.getStock() < count) || (product.getStock() - count) < 0);
if (isSufficient) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
}
// 3、更新活动商品库存
int updateCount = seckillProductMapper.updateActivityStock(product.getId(), count);
// 2.1 更新活动商品库存
int updateCount = seckillProductMapper.updateStock(product.getId(), count);
if (updateCount == 0) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
}
// 4、更新活动库存
updateCount = seckillActivityMapper.updateActivityStock(seckillActivity.getId(), count);
// 2.2 更新活动库存
updateCount = seckillActivityMapper.updateStock(seckillActivity.getId(), count);
if (updateCount == 0) {
throw exception(SECKILL_ACTIVITY_UPDATE_STOCK_FAIL);
}