商品模块代码提交
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package com.czg.controller.user;
|
||||
|
||||
import com.czg.log.annotation.OperationLog;
|
||||
import com.czg.product.param.MiniHomeProductParam;
|
||||
import com.czg.product.service.UProductService;
|
||||
import com.czg.product.vo.MiniAppHomeProductVo;
|
||||
import com.czg.resp.CzgResult;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
/**
|
||||
* 用户端商品相关接口
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-16
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/user/product")
|
||||
public class UProductController {
|
||||
private final UProductService uProductService;
|
||||
|
||||
|
||||
/**
|
||||
* 小程序点餐-首页-商品列表
|
||||
*/
|
||||
@GetMapping("/miniApp/home/queryProduct")
|
||||
@OperationLog("小程序点餐-首页-商品列表")
|
||||
public CzgResult<MiniAppHomeProductVo> queryProductForMiniAppHome(MiniHomeProductParam param) {
|
||||
MiniAppHomeProductVo data = uProductService.queryProductForMiniAppHome(param);
|
||||
return CzgResult.success(data);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 商品分组
|
||||
@@ -100,9 +99,4 @@ public class ProdGroupDTO implements Serializable {
|
||||
* 商品简要信息列表
|
||||
*/
|
||||
private List<ProductBriefDTO> productList;
|
||||
|
||||
/**
|
||||
* 分组商品信息,用于小程序首页展示
|
||||
*/
|
||||
private List<Map<String,Object>> products;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public class ProductDTO implements Serializable {
|
||||
@NotBlank(message = "商品类型不能为空", groups = DefaultGroup.class)
|
||||
private String type;
|
||||
/**
|
||||
* 0 固定套餐 1可选套餐
|
||||
* 套餐类型 0 固定套餐 1可选套餐
|
||||
*/
|
||||
private Integer groupType;
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.czg.product.param;
|
||||
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 小程序首页商品请求参数
|
||||
* @author tankaikai
|
||||
* @since 2025-02-17 15:02
|
||||
*/
|
||||
@Data
|
||||
public class MiniHomeProductParam implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 商品分组ID
|
||||
*/
|
||||
private Long prodGroupId;
|
||||
|
||||
/**
|
||||
* 商品分组ID
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
private List<Long> productIdList;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.czg.product.service;
|
||||
|
||||
import com.czg.product.entity.Product;
|
||||
import com.czg.product.param.MiniHomeProductParam;
|
||||
import com.czg.product.vo.MiniAppHomeProductVo;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
/**
|
||||
* 用户端商品Service
|
||||
* @author tankaikai
|
||||
* @since 2025-02-17 14:57
|
||||
*/
|
||||
public interface UProductService extends IService<Product> {
|
||||
|
||||
MiniAppHomeProductVo queryProductForMiniAppHome(MiniHomeProductParam param);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.czg.product.vo;
|
||||
|
||||
import com.czg.product.entity.ProdGroup;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分组商品信息,用于小程序首页展示
|
||||
* @author tankaikai
|
||||
* @since 2025-02-18 09:34
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MiniAppHomeProdGroupVo extends ProdGroup {
|
||||
/**
|
||||
* 分组商品信息,用于小程序首页展示
|
||||
*/
|
||||
private List<MiniAppHomeProductInfoVo> products;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.czg.product.vo;
|
||||
|
||||
import com.czg.product.dto.ProdSkuDTO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 小程序首页商品信息VO
|
||||
* @author tankaikai
|
||||
* @since 2025-02-17 14:41
|
||||
*/
|
||||
@Data
|
||||
public class MiniAppHomeProductInfoVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 商品id
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 商品封面图
|
||||
*/
|
||||
private String coverImg;
|
||||
/**
|
||||
* 商品图片集url
|
||||
*/
|
||||
private Object images;
|
||||
/**
|
||||
* 单位名称
|
||||
*/
|
||||
private String unitName;
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
private String categoryName;
|
||||
/**
|
||||
* 商品类型 single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券
|
||||
*/
|
||||
private String type;
|
||||
/**
|
||||
* 套餐类型 0 固定套餐 1可选套餐
|
||||
*/
|
||||
private Integer groupType;
|
||||
/**
|
||||
* 商品可选规格 {"口味":[{"甜度":["少甜","中甜","多甜"]},{"辣度":["微辣","重辣","变态辣"]},{"小料":["葱花","香菜","折耳根"]}]}
|
||||
*/
|
||||
private Object selectSpecInfo;
|
||||
/**
|
||||
* 最低售价
|
||||
*/
|
||||
private BigDecimal lowPrice;
|
||||
/**
|
||||
* 会员最低售价
|
||||
*/
|
||||
private BigDecimal lowMemberPrice;
|
||||
/**
|
||||
* 商品SKU列表
|
||||
*/
|
||||
private List<ProdSkuDTO> skuList;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.czg.product.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 小程序首页商品展示VO
|
||||
* @author tankaikai
|
||||
* @since 2025-02-17 14:41
|
||||
*/
|
||||
@Data
|
||||
public class MiniAppHomeProductVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 热销商品
|
||||
*/
|
||||
List<MiniAppHomeProductInfoVo> hots;
|
||||
|
||||
|
||||
/**
|
||||
* 分组商品信息
|
||||
*/
|
||||
List<MiniAppHomeProdGroupVo> productInfo;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.czg.service.product.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.czg.enums.DeleteEnum;
|
||||
import com.czg.enums.StatusEnum;
|
||||
import com.czg.enums.YesNoEnum;
|
||||
import com.czg.product.dto.ProdSkuDTO;
|
||||
import com.czg.product.dto.ProductDTO;
|
||||
import com.czg.product.entity.ProdGroup;
|
||||
import com.czg.product.entity.ProdGroupRelation;
|
||||
import com.czg.product.entity.ProdSku;
|
||||
import com.czg.product.entity.Product;
|
||||
import com.czg.product.param.MiniHomeProductParam;
|
||||
import com.czg.product.service.UProductService;
|
||||
import com.czg.product.vo.MiniAppHomeProdGroupVo;
|
||||
import com.czg.product.vo.MiniAppHomeProductInfoVo;
|
||||
import com.czg.product.vo.MiniAppHomeProductVo;
|
||||
import com.czg.sa.StpKit;
|
||||
import com.czg.service.product.mapper.ProdGroupMapper;
|
||||
import com.czg.service.product.mapper.ProdGroupRelationMapper;
|
||||
import com.czg.service.product.mapper.ProdSkuMapper;
|
||||
import com.czg.service.product.mapper.ProductMapper;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.TextStyle;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.czg.product.entity.table.ProductTableDef.PRODUCT;
|
||||
import static com.czg.product.entity.table.ShopProdCategoryTableDef.SHOP_PROD_CATEGORY;
|
||||
import static com.czg.product.entity.table.ShopProdSpecTableDef.SHOP_PROD_SPEC;
|
||||
import static com.czg.product.entity.table.ShopProdUnitTableDef.SHOP_PROD_UNIT;
|
||||
|
||||
/**
|
||||
* 商品
|
||||
*
|
||||
* @author Tankaikai tankaikai@aliyun.com
|
||||
* @since 1.0 2025-02-16
|
||||
*/
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
public class UProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements UProductService {
|
||||
|
||||
private final ProductMapper productMapper;
|
||||
private final ProdSkuMapper prodSkuMapper;
|
||||
private final ProdGroupMapper prodGroupMapper;
|
||||
private final ProdGroupRelationMapper prodGroupRelationMapper;
|
||||
|
||||
private QueryWrapper buildQueryWrapper(MiniHomeProductParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
String weekDayEnName = getWeekDayEnName();
|
||||
LocalTime now = LocalTime.now().withNano(0);
|
||||
QueryWrapper queryWrapper = query();
|
||||
queryWrapper.select(PRODUCT.ALL_COLUMNS)
|
||||
.select(SHOP_PROD_UNIT.NAME.as(ProductDTO::getUnitName))
|
||||
.select(SHOP_PROD_CATEGORY.NAME.as(ProductDTO::getCategoryName))
|
||||
.select(SHOP_PROD_SPEC.NAME.as(ProductDTO::getSpecName), SHOP_PROD_SPEC.FULL_NAME.as(ProductDTO::getSpecFullName))
|
||||
.from(PRODUCT)
|
||||
.leftJoin(SHOP_PROD_UNIT).on(SHOP_PROD_UNIT.ID.eq(PRODUCT.UNIT_ID))
|
||||
.leftJoin(SHOP_PROD_CATEGORY).on(SHOP_PROD_CATEGORY.ID.eq(PRODUCT.CATEGORY_ID))
|
||||
.leftJoin(SHOP_PROD_SPEC).on(SHOP_PROD_SPEC.ID.eq(PRODUCT.SPEC_ID))
|
||||
.where(PRODUCT.SHOP_ID.eq(shopId))
|
||||
.and(PRODUCT.DAYS.like(weekDayEnName))
|
||||
.and(PRODUCT.START_TIME.le(now))
|
||||
.and(PRODUCT.END_TIME.ge(now))
|
||||
.and(PRODUCT.IS_DEL.eq(DeleteEnum.NORMAL.value()))
|
||||
.and(PRODUCT.IS_SALE.eq(YesNoEnum.YES.value()))
|
||||
.orderBy(PRODUCT.SORT, false)
|
||||
.orderBy(PRODUCT.ID, false);
|
||||
if (CollUtil.isNotEmpty(param.getProductIdList())) {
|
||||
queryWrapper.and(PRODUCT.ID.in(param.getProductIdList()));
|
||||
}
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
private QueryWrapper buildHotsQueryWrapper(MiniHomeProductParam param) {
|
||||
// 查询在可售时间内的热门商品
|
||||
QueryWrapper queryWrapper = buildQueryWrapper(param);
|
||||
queryWrapper.and(PRODUCT.IS_HOT.eq(YesNoEnum.YES.value()));
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
private List<MiniAppHomeProductInfoVo> buildProductList(QueryWrapper queryWrapper) {
|
||||
List<ProductDTO> dtoList = productMapper.selectListByQueryAs(queryWrapper, ProductDTO.class);
|
||||
List<Long> prodIdList = dtoList.stream().map(ProductDTO::getId).distinct().toList();
|
||||
List<ProdSkuDTO> skuList = prodSkuMapper.selectListByQueryAs(query().in(ProdSku::getProductId, prodIdList), ProdSkuDTO.class);
|
||||
Map<Long, List<ProdSkuDTO>> collect = skuList.stream().collect(Collectors.groupingBy(ProdSkuDTO::getProductId));
|
||||
List<MiniAppHomeProductInfoVo> products = new ArrayList<>();
|
||||
for (ProductDTO dto : dtoList) {
|
||||
MiniAppHomeProductInfoVo prod = new MiniAppHomeProductInfoVo();
|
||||
prod.setId(dto.getId());
|
||||
prod.setName(dto.getName());
|
||||
prod.setCoverImg(dto.getCoverImg());
|
||||
prod.setImages(dto.getImages());
|
||||
prod.setUnitName(dto.getUnitName());
|
||||
prod.setCategoryName(dto.getCategoryName());
|
||||
prod.setType(dto.getType());
|
||||
prod.setGroupType(dto.getGroupType());
|
||||
prod.setSelectSpecInfo(dto.getSelectSpecInfo());
|
||||
|
||||
List<ProdSkuDTO> list = collect.getOrDefault(dto.getId(), Collections.emptyList());
|
||||
Optional<BigDecimal> lowPriceIsPresent = list.stream().map(ProdSkuDTO::getSalePrice).min(BigDecimal::compareTo);
|
||||
lowPriceIsPresent.ifPresent(prod::setLowPrice);
|
||||
|
||||
Optional<BigDecimal> lowMemberPriceIsPresent = list.stream().map(ProdSkuDTO::getMemberPrice).min(BigDecimal::compareTo);
|
||||
lowMemberPriceIsPresent.ifPresent(prod::setLowMemberPrice);
|
||||
|
||||
prod.setSkuList(list);
|
||||
products.add(prod);
|
||||
}
|
||||
return products;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniAppHomeProductVo queryProductForMiniAppHome(MiniHomeProductParam param) {
|
||||
Long shopId = StpKit.USER.getShopId(0L);
|
||||
MiniAppHomeProductVo vo = new MiniAppHomeProductVo();
|
||||
|
||||
List<MiniAppHomeProductInfoVo> hots = buildProductList(buildHotsQueryWrapper(param));
|
||||
vo.setHots(hots);
|
||||
// 查询可用商品分组,构建分组商品数据
|
||||
QueryWrapper queryWrapper = query()
|
||||
.eq(ProdGroup::getShopId, shopId)
|
||||
.eq(ProdGroup::getStatus, StatusEnum.ENABLED.value())
|
||||
.orderBy(ProdGroup::getSort, true);
|
||||
if (param.getProdGroupId() != null) {
|
||||
queryWrapper.eq(ProdGroup::getId, param.getProdGroupId());
|
||||
}
|
||||
List<MiniAppHomeProdGroupVo> groupList = prodGroupMapper.selectListByQueryAs(queryWrapper, MiniAppHomeProdGroupVo.class);
|
||||
for (MiniAppHomeProdGroupVo dto : groupList) {
|
||||
List<Long> productIdList = prodGroupRelationMapper.selectObjectListByQueryAs(query().select(ProdGroupRelation::getProductId).eq(ProdGroupRelation::getProdGroupId, dto.getId()).orderBy(ProdGroupRelation::getSort, true), Long.class);
|
||||
if (CollUtil.isNotEmpty(productIdList)) {
|
||||
param.setProductIdList(productIdList);
|
||||
List<MiniAppHomeProductInfoVo> products = buildProductList(buildQueryWrapper(param));
|
||||
dto.setProducts(products);
|
||||
} else {
|
||||
dto.setProducts(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
vo.setProductInfo(groupList);
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前日期是星期几的英文名称
|
||||
*
|
||||
* @return 星期几的英文名称,例如 "Monday" 或 "Friday"
|
||||
*/
|
||||
private String getWeekDayEnName() {
|
||||
// 获取当前日期
|
||||
LocalDate currentDate = LocalDate.now();
|
||||
// 获取当前日期是星期几,返回一个 DayOfWeek 枚举类型的实例
|
||||
DayOfWeek dayOfWeek = currentDate.getDayOfWeek();
|
||||
return dayOfWeek.getDisplayName(TextStyle.FULL, Locale.ENGLISH);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user