mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-08-08 07:11:53 +08:00
Merge remote-tracking branch 'yudao/feature/mall_product' into feature/mall_product
# Conflicts: # yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/AppCommentController.java # yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentBaseVO.java # yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/comment/vo/AppProductCommentRespVO.java # yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java # yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.product.controller.app.comment.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@@ -27,6 +28,9 @@ public class AppProductCommentBaseVO {
|
||||
@NotNull(message = "商品SKU编号不能为空")
|
||||
private Long skuId;
|
||||
|
||||
@Schema(description = "商品 SKU 属性", required = true)
|
||||
private List<AppProductPropertyValueDetailRespVO> skuProperties; // TODO puhui999:这个需要从数据库查询哈
|
||||
|
||||
@Schema(description = "评分星级 1-5分", required = true, example = "5")
|
||||
@NotNull(message = "评分星级 1-5分不能为空")
|
||||
private Integer scores;
|
||||
|
@@ -9,8 +9,6 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "用户APP - 商品评价 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
|
@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.product.controller.app.spu;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRespVO;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||
import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||
@@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
|
||||
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -40,9 +41,22 @@ public class AppProductSpuController {
|
||||
@Resource
|
||||
private ProductSkuService productSkuService;
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获得商品 SPU 列表")
|
||||
@Parameters({
|
||||
@Parameter(name = "recommendType", description = "推荐类型", required = true), // 参见 AppProductSpuPageReqVO.RECOMMEND_TYPE_XXX 常量
|
||||
@Parameter(name = "count", description = "数量", required = true)
|
||||
})
|
||||
public CommonResult<List<AppProductSpuPageRespVO>> getSpuList(
|
||||
@RequestParam("recommendType") String recommendType,
|
||||
@RequestParam(value = "count", defaultValue = "10") Integer count) {
|
||||
List<ProductSpuDO> list = productSpuService.getSpuList(recommendType, count);
|
||||
return success(ProductSpuConvert.INSTANCE.convertListForGetSpuList(list));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得商品 SPU 分页")
|
||||
public CommonResult<PageResult<AppProductSpuPageItemRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
|
||||
public CommonResult<PageResult<AppProductSpuPageRespVO>> getSpuPage(@Valid AppProductSpuPageReqVO pageVO) {
|
||||
PageResult<ProductSpuDO> pageResult = productSpuService.getSpuPage(pageVO);
|
||||
return success(ProductSpuConvert.INSTANCE.convertPageForGetSpuPage(pageResult));
|
||||
}
|
||||
|
@@ -39,6 +39,11 @@ public class AppProductSpuDetailRespVO {
|
||||
@Schema(description = "单位名", required = true, example = "个")
|
||||
private String unitName;
|
||||
|
||||
// ========== 营销相关字段 =========
|
||||
|
||||
@Schema(description = "活动排序数组", required = true, example = "1024")
|
||||
private List<Integer> activityOrders;
|
||||
|
||||
// ========== SKU 相关字段 =========
|
||||
|
||||
@Schema(description = "规格类型", required = true, example = "true")
|
||||
|
@@ -20,6 +20,7 @@ public class AppProductSpuPageReqVO extends PageParam {
|
||||
public static final String SORT_FIELD_SALES_COUNT = "salesCount";
|
||||
|
||||
public static final String RECOMMEND_TYPE_HOT = "hot";
|
||||
public static final String RECOMMEND_TYPE_GOOD = "good";
|
||||
|
||||
@Schema(description = "分类编号", example = "1")
|
||||
private Long categoryId;
|
||||
@@ -33,7 +34,7 @@ public class AppProductSpuPageReqVO extends PageParam {
|
||||
@Schema(description = "排序方式", example = "true")
|
||||
private Boolean sortAsc;
|
||||
|
||||
@Schema(description = "推荐类型", example = "hot") // 参见 AppProductSpuPageReqVO.RECOMMEND_TYPE_XXX 常亮
|
||||
@Schema(description = "推荐类型", example = "hot") // 参见 AppProductSpuPageReqVO.RECOMMEND_TYPE_XXX 常量
|
||||
private String recommendType;
|
||||
|
||||
@AssertTrue(message = "排序字段不合法")
|
||||
|
@@ -5,9 +5,9 @@ import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Schema(description = "用户 App - 商品 SPU 分页项 Response VO")
|
||||
@Schema(description = "用户 App - 商品 SPU Response VO")
|
||||
@Data
|
||||
public class AppProductSpuPageItemRespVO {
|
||||
public class AppProductSpuPageRespVO {
|
||||
|
||||
@Schema(description = "商品 SPU 编号", required = true, example = "1")
|
||||
private Long id;
|
||||
@@ -35,6 +35,11 @@ public class AppProductSpuPageItemRespVO {
|
||||
@Schema(description = "库存", required = true, example = "666")
|
||||
private Integer stock;
|
||||
|
||||
// ========== 营销相关字段 =========
|
||||
|
||||
@Schema(description = "活动排序数组", required = true, example = "1024")
|
||||
private List<Integer> activityOrders;
|
||||
|
||||
// ========== 统计相关字段 =========
|
||||
|
||||
@Schema(description = "商品销量", required = true, example = "1024")
|
@@ -1,14 +1,12 @@
|
||||
package cn.iocoder.yudao.module.product.convert.spu;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageItemRespVO;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageRespVO;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||
import cn.iocoder.yudao.module.product.convert.sku.ProductSkuConvert;
|
||||
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
||||
@@ -80,14 +78,15 @@ public interface ProductSpuConvert {
|
||||
|
||||
// ========== 用户 App 相关 ==========
|
||||
|
||||
default PageResult<AppProductSpuPageItemRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page) {
|
||||
// 累加虚拟销量
|
||||
page.getList().forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
|
||||
// 然后进行转换
|
||||
return convertPageForGetSpuPage0(page);
|
||||
}
|
||||
PageResult<AppProductSpuPageRespVO> convertPageForGetSpuPage(PageResult<ProductSpuDO> page);
|
||||
|
||||
PageResult<AppProductSpuPageItemRespVO> convertPageForGetSpuPage0(PageResult<ProductSpuDO> page);
|
||||
default List<AppProductSpuPageRespVO> convertListForGetSpuList(List<ProductSpuDO> list) {
|
||||
// 处理虚拟销量
|
||||
list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
|
||||
return convertListForGetSpuList0(list);
|
||||
}
|
||||
@Named("convertListForGetSpuList0")
|
||||
List<AppProductSpuPageRespVO> convertListForGetSpuList0(List<ProductSpuDO> list);
|
||||
|
||||
default AppProductSpuDetailRespVO convertForGetSpuDetail(ProductSpuDO spu, List<ProductSkuDO> skus) {
|
||||
// 处理 SPU
|
||||
@@ -109,15 +108,9 @@ public interface ProductSpuConvert {
|
||||
List<AppProductSpuDetailRespVO.Sku> convertListForGetSpuDetail(List<ProductSkuDO> skus);
|
||||
|
||||
default ProductSpuDetailRespVO convertForSpuDetailRespVO(ProductSpuDO spu, List<ProductSkuDO> skus) {
|
||||
ProductSpuDetailRespVO productSpuDetailRespVO = convert03(spu);
|
||||
// skus 为空直接返回
|
||||
if (CollUtil.isEmpty(skus)) {
|
||||
return productSpuDetailRespVO;
|
||||
}
|
||||
List<ProductSkuRespVO> skuVOs = ProductSkuConvert.INSTANCE.convertList(skus);
|
||||
// fix: 因为现在已改为 sku 属性列表 属性 已包含 属性名字 属性值名字 所以不需要再额外处理,属性更新时更新 sku 中的属性相关冗余即可
|
||||
productSpuDetailRespVO.setSkus(skuVOs);
|
||||
return productSpuDetailRespVO;
|
||||
ProductSpuDetailRespVO detailRespVO = convert03(spu);
|
||||
detailRespVO.setSkus(ProductSkuConvert.INSTANCE.convertList(skus));
|
||||
return detailRespVO;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ public class ProductCommentDO extends BaseDO {
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 评价人 用户编号
|
||||
* 评价人的用户编号
|
||||
*
|
||||
* 关联 MemberUserDO 的 id 编号
|
||||
*/
|
||||
|
@@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
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.framework.mybatis.core.query.QueryWrapperX;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuExportReqVO;
|
||||
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
|
||||
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
|
||||
@@ -66,7 +67,10 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
|
||||
// 推荐类型的过滤条件
|
||||
if (ObjUtil.equal(pageReqVO.getRecommendType(), AppProductSpuPageReqVO.RECOMMEND_TYPE_HOT)) {
|
||||
query.eq(ProductSpuDO::getRecommendHot, true);
|
||||
} else if (ObjUtil.equal(pageReqVO.getRecommendType(), AppProductSpuPageReqVO.RECOMMEND_TYPE_GOOD)) {
|
||||
query.eq(ProductSpuDO::getRecommendGood, true);
|
||||
}
|
||||
|
||||
// 排序逻辑
|
||||
if (Objects.equals(pageReqVO.getSortField(), AppProductSpuPageReqVO.SORT_FIELD_SALES_COUNT)) {
|
||||
query.last(String.format(" ORDER BY (sales_count + virtual_sales_count) %s, sort DESC, id DESC",
|
||||
@@ -80,6 +84,21 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
|
||||
return selectPage(pageReqVO, query);
|
||||
}
|
||||
|
||||
default List<ProductSpuDO> selectListByRecommendType(String recommendType, Integer count) {
|
||||
QueryWrapperX<ProductSpuDO> query = new QueryWrapperX<>();
|
||||
// 上架状态 且有库存
|
||||
query.eq("status", ProductSpuStatusEnum.ENABLE.getStatus()).gt("stock", 0);
|
||||
// 推荐类型的过滤条件
|
||||
if (ObjUtil.equal(recommendType, AppProductSpuPageReqVO.RECOMMEND_TYPE_HOT)) {
|
||||
query.eq("recommend_hot", true);
|
||||
} else if (ObjUtil.equal(recommendType, AppProductSpuPageReqVO.RECOMMEND_TYPE_GOOD)) {
|
||||
query.eq("recommend_good", true);
|
||||
}
|
||||
// 设置最大长度
|
||||
query.limitN(count);
|
||||
return selectList(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品 SPU 库存
|
||||
*
|
||||
@@ -111,33 +130,34 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证选项卡类型构建条件
|
||||
* 添加后台 Tab 选项的查询条件
|
||||
*
|
||||
* @param tabType 标签类型
|
||||
* @param queryWrapper 查询条件
|
||||
* @param query 查询条件
|
||||
*/
|
||||
static void appendTabQuery(Integer tabType, LambdaQueryWrapperX<ProductSpuDO> queryWrapper) {
|
||||
static void appendTabQuery(Integer tabType, LambdaQueryWrapperX<ProductSpuDO> query) {
|
||||
// 出售中商品
|
||||
if (ObjectUtil.equals(ProductSpuPageReqVO.FOR_SALE, tabType)) {
|
||||
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus());
|
||||
query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus());
|
||||
}
|
||||
// 仓储中商品
|
||||
if (ObjectUtil.equals(ProductSpuPageReqVO.IN_WAREHOUSE, tabType)) {
|
||||
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus());
|
||||
query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.DISABLE.getStatus());
|
||||
}
|
||||
// 已售空商品
|
||||
if (ObjectUtil.equals(ProductSpuPageReqVO.SOLD_OUT, tabType)) {
|
||||
queryWrapper.eqIfPresent(ProductSpuDO::getStock, 0);
|
||||
query.eqIfPresent(ProductSpuDO::getStock, 0);
|
||||
}
|
||||
// 警戒库存
|
||||
if (ObjectUtil.equals(ProductSpuPageReqVO.ALERT_STOCK, tabType)) {
|
||||
queryWrapper.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK)
|
||||
query.le(ProductSpuDO::getStock, ProductConstants.ALERT_STOCK)
|
||||
// 如果库存触发警戒库存且状态为回收站的话则不在警戒库存列表展示
|
||||
.notIn(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus());
|
||||
}
|
||||
// 回收站
|
||||
if (ObjectUtil.equals(ProductSpuPageReqVO.RECYCLE_BIN, tabType)) {
|
||||
queryWrapper.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus());
|
||||
query.eqIfPresent(ProductSpuDO::getStatus, ProductSpuStatusEnum.RECYCLE.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -98,6 +98,15 @@ public interface ProductSpuService {
|
||||
*/
|
||||
PageResult<ProductSpuDO> getSpuPage(AppProductSpuPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得商品 SPU 列表,提供给用户 App 使用
|
||||
*
|
||||
* @param recommendType 推荐类型
|
||||
* @param count 数量
|
||||
* @return 商品 SPU 列表
|
||||
*/
|
||||
List<ProductSpuDO> getSpuList(String recommendType, Integer count);
|
||||
|
||||
/**
|
||||
* 更新商品 SPU 库存(增量)
|
||||
*
|
||||
|
@@ -201,6 +201,11 @@ public class ProductSpuServiceImpl implements ProductSpuService {
|
||||
return productSpuMapper.selectPage(pageReqVO, categoryIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProductSpuDO> getSpuList(String recommendType, Integer count) {
|
||||
return productSpuMapper.selectListByRecommendType(recommendType, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateSpuStock(Map<Long, Integer> stockIncrCounts) {
|
||||
|
@@ -192,9 +192,4 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
|
||||
assertEquals("测试", productCommentDO.getReplyContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateComment_success() {
|
||||
// mock 测试
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user