diff --git a/cash-api/product-server/src/main/java/com/czg/controller/user/UProductController.java b/cash-api/product-server/src/main/java/com/czg/controller/user/UProductController.java index cd10349b..3f09f8c1 100644 --- a/cash-api/product-server/src/main/java/com/czg/controller/user/UProductController.java +++ b/cash-api/product-server/src/main/java/com/czg/controller/user/UProductController.java @@ -2,13 +2,16 @@ package com.czg.controller.user; import com.czg.log.annotation.OperationLog; import com.czg.product.param.MiniHomeProductParam; +import com.czg.product.param.ShopProductSkuParam; import com.czg.product.service.UProductService; -import com.czg.product.vo.MiniAppHomeProductVo; -import com.czg.product.vo.ShopGroupProductVo; -import com.czg.product.vo.ShopProductVo; +import com.czg.product.vo.*; import com.czg.resp.CzgResult; +import com.czg.utils.AssertUtil; +import com.czg.validator.ValidatorUtil; +import com.czg.validator.group.DefaultGroup; import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -58,4 +61,28 @@ public class UProductController { return CzgResult.success(list); } + /** + * 小程序点餐-商品详情 + * + * @param id 商品id + */ + @GetMapping("/miniApp/info/{id}") + @OperationLog("小程序点餐-商品详情") + public CzgResult getProductInfo(@PathVariable("id") Long id) { + AssertUtil.isNull(id, "商品id不能为空"); + ShopProductInfoVo data = uProductService.getProductInfo(id); + return CzgResult.success(data); + } + + /** + * 小程序点餐-商品SKU详情 + */ + @GetMapping("/miniApp/sku/info") + @OperationLog("小程序点餐-商品SKU详情") + public CzgResult getProductSkuInfo(ShopProductSkuParam param) { + ValidatorUtil.validateEntity(param, DefaultGroup.class); + ShopProductSkuInfoVo data = uProductService.getProductSkuInfo(param); + return CzgResult.success(data); + } + } \ No newline at end of file diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/param/ShopProductSkuParam.java b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ShopProductSkuParam.java new file mode 100644 index 00000000..03aeb04e --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/param/ShopProductSkuParam.java @@ -0,0 +1,31 @@ +package com.czg.product.param; + +import com.czg.validator.group.DefaultGroup; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 商品SKU查询参数 + * + * @author tankaikai + * @since 2025-02-19 09:23 + */ +@Data +public class ShopProductSkuParam implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 商品id + */ + @NotNull(message = "商品id不能为空", groups = DefaultGroup.class) + private Long id; + /** + * 选中的规格名称,单规格传:null,多规格:如选择微辣+常温,则传递:微辣,常温,顺序不能变 + */ + private String specInfo; +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/service/UProductService.java b/cash-common/cash-common-service/src/main/java/com/czg/product/service/UProductService.java index e247d35e..8813563f 100644 --- a/cash-common/cash-common-service/src/main/java/com/czg/product/service/UProductService.java +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/service/UProductService.java @@ -2,9 +2,8 @@ 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.czg.product.vo.ShopGroupProductVo; -import com.czg.product.vo.ShopProductVo; +import com.czg.product.param.ShopProductSkuParam; +import com.czg.product.vo.*; import com.mybatisflex.core.service.IService; import java.util.List; @@ -21,4 +20,8 @@ public interface UProductService extends IService { List queryHotsProductList(); List queryGroupProductList(); + + ShopProductInfoVo getProductInfo(Long id); + + ShopProductSkuInfoVo getProductSkuInfo(ShopProductSkuParam param); } diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/vo/ShopProductInfoVo.java b/cash-common/cash-common-service/src/main/java/com/czg/product/vo/ShopProductInfoVo.java new file mode 100644 index 00000000..5ab7bda0 --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/vo/ShopProductInfoVo.java @@ -0,0 +1,115 @@ +package com.czg.product.vo; + +import cn.hutool.core.convert.Convert; +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.annotation.JSONField; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalTime; + +/** + * 商品规格详情 + * + * @author tankaikai + * @since 2025-02-19 09:23 + */ +@Data +public class ShopProductInfoVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 商品id + */ + private Long id; + /** + * 商品名称 + */ + private String name; + /** + * 短标题--促销语 + */ + private String shortTitle; + /** + * 封面图url + */ + private String coverImg; + /** + * 商品图集 + */ + private Object images; + /** + * 单位名称 + */ + private String unitName; + /** + * 原价 + */ + private BigDecimal originPrice; + /** + * 销售价 + */ + private BigDecimal salePrice; + /** + * 会员价 + */ + private BigDecimal memberPrice; + /** + * 是否售罄 1-是 0-否 + */ + private Integer isSoldStock; + /** + * 库存数量 + */ + private Integer stockNumber; + /** + * 商品类型 single-单规格商品 sku-多规格商品 package-套餐商品 weight-称重商品 coupon-团购券 + */ + private String type; + /** + * 套餐类型 0-固定套餐 1-可选套餐 + */ + private String groupType; + /** + * 是否可售时间 1-是 0-否 + */ + private Integer isSaleTime; + /** + * 起售数量 + */ + private Integer suitNum; + /** + * 商品规格 + */ + private Object selectSpecInfo; + /** + * 商品每周销售日 如:Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday + */ + @JSONField(serialize = false) + private String days; + /** + * 可售卖起始时间 + */ + @JSONField(serialize = false) + private LocalTime startTime; + /** + * 可售卖截止时间 + */ + @JSONField(serialize = false) + private LocalTime endTime; + + public Object getImages() { + return JSON.parseArray(Convert.toStr(images, "[]")); + } + + /** + * {"口味":[{"甜度":["少甜","中甜","多甜"]},{"辣度":["微辣","重辣","变态辣"]},{"小料":["葱花","香菜","折耳根"]}]} + */ + public Object getSelectSpecInfo() { + return JSON.parseObject(Convert.toStr(selectSpecInfo, "{}")); + } +} diff --git a/cash-common/cash-common-service/src/main/java/com/czg/product/vo/ShopProductSkuInfoVo.java b/cash-common/cash-common-service/src/main/java/com/czg/product/vo/ShopProductSkuInfoVo.java new file mode 100644 index 00000000..79cc436d --- /dev/null +++ b/cash-common/cash-common-service/src/main/java/com/czg/product/vo/ShopProductSkuInfoVo.java @@ -0,0 +1,77 @@ +package com.czg.product.vo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * 商品SKU详情 + * + * @author tankaikai + * @since 2025-02-19 09:23 + */ +@Data +public class ShopProductSkuInfoVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * id + */ + private Long id; + /** + * 条形码 + */ + private String barCode; + /** + * 商品Id + */ + private Long productId; + /** + * 原价 + */ + private BigDecimal originPrice; + /** + * 成本价 + */ + private BigDecimal costPrice; + /** + * 会员价 + */ + private BigDecimal memberPrice; + /** + * 售价 + */ + private BigDecimal salePrice; + /** + * 起售数量 + */ + private Integer suitNum; + /** + * 规格详情 + */ + private String specInfo; + /** + * 商品封面图 + */ + private String coverImg; + /** + * 重量 + */ + private BigDecimal weight; + /** + * 销量 + */ + private BigDecimal realSalesNumber; + /** + * 是否售罄 + */ + private Integer isPauseSale; + /** + * 商品库存 + */ + private Integer stockNumber; +} diff --git a/cash-service/product-service/src/main/java/com/czg/service/product/mapper/ProductMapper.java b/cash-service/product-service/src/main/java/com/czg/service/product/mapper/ProductMapper.java index c2d73c45..ecf1c910 100644 --- a/cash-service/product-service/src/main/java/com/czg/service/product/mapper/ProductMapper.java +++ b/cash-service/product-service/src/main/java/com/czg/service/product/mapper/ProductMapper.java @@ -1,6 +1,7 @@ package com.czg.service.product.mapper; import com.czg.product.entity.Product; +import com.czg.product.vo.ShopProductInfoVo; import com.czg.product.vo.ShopProductVo; import com.mybatisflex.core.BaseMapper; import org.apache.ibatis.annotations.Mapper; @@ -20,4 +21,6 @@ public interface ProductMapper extends BaseMapper { List selectHotsProductList(@Param("shopId") Long shopId); List selectGroupProductList(@Param("shopId") Long shopId); + + ShopProductInfoVo selectOneProductInfo(@Param("id") Long id, @Param("shopId") Long shopId); } \ No newline at end of file diff --git a/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/UProductServiceImpl.java b/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/UProductServiceImpl.java index b3607945..ff3cfc81 100644 --- a/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/UProductServiceImpl.java +++ b/cash-service/product-service/src/main/java/com/czg/service/product/service/impl/UProductServiceImpl.java @@ -6,13 +6,16 @@ import cn.hutool.core.util.StrUtil; import com.czg.enums.DeleteEnum; import com.czg.enums.StatusEnum; import com.czg.enums.YesNoEnum; +import com.czg.exception.CzgException; 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.enums.ProductTypeEnum; import com.czg.product.param.MiniHomeProductParam; +import com.czg.product.param.ShopProductSkuParam; import com.czg.product.service.UProductService; import com.czg.product.vo.*; import com.czg.sa.StpKit; @@ -197,6 +200,43 @@ public class UProductServiceImpl extends ServiceImpl imp return groupList.stream().filter(group -> CollUtil.isNotEmpty(group.getProductList())).toList(); } + @Override + public ShopProductInfoVo getProductInfo(Long id) { + Long shopId = StpKit.USER.getShopId(0L); + ShopProductInfoVo data = productMapper.selectOneProductInfo(id, shopId); + if (data == null) { + throw new CzgException("商品不可售"); + } + return data; + } + + @Override + public ShopProductSkuInfoVo getProductSkuInfo(ShopProductSkuParam param) { + Long shopId = StpKit.USER.getShopId(0L); + Product product = productMapper.selectOneById(param.getId()); + if (product == null) { + throw new CzgException("商品信息不存在"); + } + String specInfo = StrUtil.blankToDefault(param.getSpecInfo(), null); + ShopProductSkuInfoVo data = prodSkuMapper.selectOneByQueryAs( + query().eq(ProdSku::getProductId, param.getId()) + .eq(ProdSku::getShopId, shopId) + .eq(ProdSku::getIsDel, DeleteEnum.NORMAL.value()) + .eq(ProdSku::getIsGrounding, YesNoEnum.YES.value()) + .eq(ProdSku::getSpecInfo, specInfo) + , ShopProductSkuInfoVo.class); + if (data == null) { + throw new CzgException("商品SKU不可售或不存在"); + } + if (ProductTypeEnum.SINGLE.value().equals(product.getType())) { + data.setStockNumber(product.getStockNumber()); + } else { + // TODO 临时数据,后续对接库存系统 + data.setStockNumber(1000); + } + return data; + } + /** * 计算是否在可售时间内 * diff --git a/cash-service/product-service/src/main/resources/mapper/ProductMapper.xml b/cash-service/product-service/src/main/resources/mapper/ProductMapper.xml index 349fc070..4f88620f 100644 --- a/cash-service/product-service/src/main/resources/mapper/ProductMapper.xml +++ b/cash-service/product-service/src/main/resources/mapper/ProductMapper.xml @@ -5,10 +5,12 @@ select t1.id, t1.name, + t1.short_title, t2.origin_price, t2.sale_price, t2.member_price, t1.cover_img, + t1.images, t3.name as unit_name, t1.is_sold_stock, t1.stock_number, @@ -17,7 +19,8 @@ t1.days, t1.start_time, t1.end_time, - ifnull(t2.suit_num, 1) as suit_num + ifnull(t2.suit_num, 1) as suit_num, + t1.select_spec_info from tb_product t1 left join (select x.product_id, MIN(x.sale_price) as sale_price, @@ -53,4 +56,14 @@ order by t1.sort desc,t1.id desc + \ No newline at end of file