product-sku-rpc

This commit is contained in:
q2118cs 2020-05-11 16:26:02 +08:00
parent a4ca27d68c
commit b996ddfa1e
14 changed files with 280 additions and 34 deletions

View File

@ -130,6 +130,4 @@ public interface ProductSpuConvert {
return spuDetailList;
}
}

View File

@ -1,10 +1,19 @@
package cn.iocoder.mall.product.biz.dao.product;
import cn.iocoder.mall.product.biz.dataobject.product.ProductBrandDO;
import cn.iocoder.mall.product.biz.dataobject.product.ProductSkuDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductSkuMapper extends BaseMapper<ProductBrandDO> {
import java.util.List;
@Repository
public interface ProductSkuMapper extends BaseMapper<ProductSkuDO> {
default List<ProductSkuDO> selectListBySpuIdAndStatus(Integer spuId, Integer status) {
return selectList(Wrappers.<ProductSkuDO>query().lambda()
.eq(ProductSkuDO::getSpuId, spuId)
.eq(ProductSkuDO::getStatus, status)
.eq(ProductSkuDO::getDeleted, false));
}
}

View File

@ -1,11 +1,11 @@
package cn.iocoder.mall.product.biz.dao.product;
import cn.iocoder.mall.product.biz.dataobject.product.ProductBrandDO;
import cn.iocoder.mall.product.biz.dataobject.product.ProductSpuDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductSpuMapper extends BaseMapper<ProductBrandDO> {
public interface ProductSpuMapper extends BaseMapper<ProductSpuDO> {
}

View File

@ -7,9 +7,11 @@ import cn.iocoder.mall.product.biz.bo.attr.ProductAttrBO;
import cn.iocoder.mall.product.biz.bo.attr.ProductAttrSimpleWithValueBO;
import cn.iocoder.mall.product.biz.bo.attr.ProductAttrValueBO;
import cn.iocoder.mall.product.biz.bo.attr.ProductAttrWithValueBO;
import cn.iocoder.mall.product.biz.bo.product.ProductAttrAndValuePairBO;
import cn.iocoder.mall.product.biz.dto.attr.*;
import java.util.List;
import java.util.Set;
public interface ProductAttrService {
/**
@ -64,4 +66,5 @@ public interface ProductAttrService {
Boolean updateProductAttrValueStatus(Integer adminId, Integer productAttrValueId,
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") Integer status);
List<ProductAttrAndValuePairBO> validProductAttrAndValue(Set<Integer> productAttrValueIds, boolean validStatus);
}

View File

@ -0,0 +1,15 @@
package cn.iocoder.mall.product.biz.service.product;
import cn.iocoder.mall.product.biz.bo.product.ProductSpuDetailBO;
public interface ProductSpuService {
/**
* 获取SPU明细
*
* @param id spuId
* @return SPU明细
*/
ProductSpuDetailBO getProductSpuDetail(Integer id);
}

View File

@ -204,6 +204,7 @@ public class ProductAttrServiceImpl implements ProductAttrService {
return i > 0;
}
@Override
public List<ProductAttrAndValuePairBO> validProductAttrAndValue(Set<Integer> productAttrValueIds, boolean validStatus) {
// 首先校验规格值
List<ProductAttrValueDO> attrValues = productAttrValueMapper.selectBatchIds(productAttrValueIds);

View File

@ -0,0 +1,59 @@
package cn.iocoder.mall.product.biz.service.product.impl;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.util.StringUtil;
import cn.iocoder.mall.product.biz.bo.product.ProductAttrAndValuePairBO;
import cn.iocoder.mall.product.biz.bo.product.ProductSpuDetailBO;
import cn.iocoder.mall.product.biz.convert.product.ProductSpuConvert;
import cn.iocoder.mall.product.biz.dao.product.ProductCategoryMapper;
import cn.iocoder.mall.product.biz.dao.product.ProductSkuMapper;
import cn.iocoder.mall.product.biz.dao.product.ProductSpuMapper;
import cn.iocoder.mall.product.biz.dataobject.product.ProductCategoryDO;
import cn.iocoder.mall.product.biz.dataobject.product.ProductSkuDO;
import cn.iocoder.mall.product.biz.dataobject.product.ProductSpuDO;
import cn.iocoder.mall.product.biz.enums.ProductErrorCodeEnum;
import cn.iocoder.mall.product.biz.enums.product.ProductSpuConstants;
import cn.iocoder.mall.product.biz.service.product.ProductAttrService;
import cn.iocoder.mall.product.biz.service.product.ProductSpuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
public class ProductSpuServiceImpl implements ProductSpuService {
@Autowired
private ProductSpuMapper productSpuMapper;
@Autowired
private ProductSkuMapper productSkuMapper;
@Autowired
private ProductCategoryMapper productCategoryMapper;
@Autowired
private ProductAttrService productAttrService;
@Override
public ProductSpuDetailBO getProductSpuDetail(Integer spuId) {
// 校验商品 spu 存在
ProductSpuDO spu = productSpuMapper.selectById(spuId);
if (spu == null) {
throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_SPU_NOT_EXISTS.getCode());
}
// 获得商品分类分类
ProductCategoryDO category = productCategoryMapper.selectById(spu.getCid());
Assert.notNull(category, String.format("分类编号(%d) 对应", spu.getCid()));
// 获得商品 sku 数组
List<ProductSkuDO> skus = productSkuMapper.selectListBySpuIdAndStatus(spuId, ProductSpuConstants.SKU_STATUS_ENABLE);
// 获得规格
Set<Integer> productAttrValueIds = new HashSet<>();
skus.forEach(sku -> productAttrValueIds.addAll(StringUtil.splitToInt(sku.getAttrs(), ",")));
// 读取规格时不考虑规格是否被禁用
List<ProductAttrAndValuePairBO> attrAndValuePairList = productAttrService.validProductAttrAndValue(productAttrValueIds, false);
// 返回成功
return ProductSpuConvert.INSTANCE.convert2(spu, skus, attrAndValuePairList, category);
}
}

View File

@ -0,0 +1,12 @@
package cn.iocoder.mall.product.rpc.api;
import cn.iocoder.mall.product.rpc.response.ProductSpuDetailResponse;
/**
* @author Rai
*/
public interface ProductSpuRpc {
ProductSpuDetailResponse getProductSpuDetail(Integer spuId);
}

View File

@ -0,0 +1,127 @@
package cn.iocoder.mall.product.rpc.response;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* 商品 Spu 明细 BO包括 Sku 明细
*/
@Data
@Accessors(chain = true)
public class ProductSpuDetailResponse implements Serializable {
/**
* SPU 编号
*/
private Integer id;
// ========== 基本信息 =========
/**
* SPU 名字
*/
private String name;
/**
* 卖点
*/
private String sellPoint;
/**
* 描述
*/
private String description;
/**
* 分类编号
*/
private Integer cid;
/**
* 分类名
*/
private String categoryName;
/**
* 商品主图地址
* <p>
* 数组以逗号分隔
* <p>
* 建议尺寸800*800像素你可以拖拽图片调整顺序最多上传15张
*/
private List<String> picUrls;
// ========== 其他信息 =========
/**
* 是否上架商品是否可见
* <p>
* true 为已上架
* false 为已下架
*/
private Boolean visible;
/**
* 排序字段
*/
private Integer sort;
// ========== SKU =========
/**
* SKU 数组
*/
private List<Sku> skus;
/**
* 商品 Sku 明细 BO
*/
@Data
@Accessors(chain = true)
public static class Sku implements Serializable {
/**
* sku 编号
*/
private Integer id;
/**
* 商品编号
*/
private Integer spuId;
/**
* 图片地址
*/
private String picURL;
/**
* 规格值数组
*/
private List<ProductAttrAndValuePair> attrs;
/**
* 价格单位
*/
private Integer price;
/**
* 库存数量
*/
private Integer quantity;
}
@Data
@Accessors(chain = true)
public static class ProductAttrAndValuePair implements Serializable {
/**
* 规格编号
*/
private Integer attrId;
/**
* 规格名
*/
private String attrName;
/**
* 规格值
*/
private Integer attrValueId;
/**
* 规格值名
*/
private String attrValueName;
}
}

View File

@ -0,0 +1,16 @@
package cn.iocoder.mall.product.rpc.convert;
import cn.iocoder.mall.product.biz.bo.product.ProductSpuDetailBO;
import cn.iocoder.mall.product.rpc.response.ProductSpuDetailResponse;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public interface ProductSpuConvert {
ProductSpuConvert INSTANCE = Mappers.getMapper(ProductSpuConvert.class);
@Mappings({})
ProductSpuDetailResponse convertDetail(ProductSpuDetailBO productSpuDetail);
}

View File

@ -0,0 +1,24 @@
package cn.iocoder.mall.product.rpc.rpc;
import cn.iocoder.mall.product.biz.bo.product.ProductSpuDetailBO;
import cn.iocoder.mall.product.biz.service.product.ProductSpuService;
import cn.iocoder.mall.product.rpc.api.ProductSpuRpc;
import cn.iocoder.mall.product.rpc.convert.ProductSpuConvert;
import cn.iocoder.mall.product.rpc.response.ProductSpuDetailResponse;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service(validation = "true", version = "${dubbo.provider.ProductSpuService.version}")
public class ProductSpuRpcImpl implements ProductSpuRpc {
@Autowired
private ProductSpuService productSpuService;
@Override
public ProductSpuDetailResponse getProductSpuDetail(Integer spuId) {
ProductSpuDetailBO productSpuDetail = productSpuService.getProductSpuDetail(spuId);
return ProductSpuConvert.INSTANCE.convertDetail(productSpuDetail);
}
}

View File

@ -2,39 +2,21 @@
dubbo:
# Spring Cloud Alibaba Dubbo 专属配置
cloud:
subscribed-services: 'system-application' # 设置订阅的应用列表,默认为 * 订阅所有应用
subscribed-services: 'product-application' # 设置订阅的应用列表,默认为 * 订阅所有应用
# Dubbo 提供者的协议
protocol:
name: dubbo
port: -1
# Dubbo 提供服务的扫描基础包
scan:
base-packages: cn.iocoder.mall.system.rpc.rpc
base-packages: cn.iocoder.mall.product.rpc.rpc
# Dubbo 服务提供者的配置
provider:
filter: -exception
SystemLogRPC:
version: 1.0.0
OAuth2RPC:
version: 1.0.0
AuthorizationRPC:
version: 1.0.0
AdminRPC:
version: 1.0.0
UserRPC:
version: 1.0.0
UserAddressRPC:
ProductSpuService:
version: 1.0.0
# Dubbo 服务消费者的配置
consumer:
SystemLogRPC: # 用于 AccessLogInterceptor 等拦截器,记录 HTTP API 请求的访问日志
version: 1.0.0
OAuth2RPC: # 用于 AccountAuthInterceptor 拦截器,执行认证
version: 1.0.0
AuthorizationRPC: # 用于 AccountAuthInterceptor 拦截器,执行鉴权(权限验证)
version: 1.0.0
AdminRPC:
version: 1.0.0
UserRPC:
ProductSpuService:
version: 1.0.0

View File

@ -25,7 +25,7 @@
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>product-service-api</artifactId>
<artifactId>product-rpc-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

View File

@ -3,7 +3,7 @@ package cn.iocoder.mall.promotion.biz.service;
import cn.iocoder.common.framework.constant.CommonStatusEnum;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.mall.mybatis.enums.DeletedStatusEnum;
import cn.iocoder.mall.product.api.ProductSpuService;
import cn.iocoder.mall.product.rpc.api.ProductSpuRpc;
import cn.iocoder.mall.promotion.api.ProductRecommendService;
import cn.iocoder.mall.promotion.api.bo.ProductRecommendBO;
import cn.iocoder.mall.promotion.api.bo.ProductRecommendPageBO;
@ -26,7 +26,7 @@ import java.util.List;
public class ProductRecommendServiceImpl implements ProductRecommendService {
@Reference(validation = "true", version = "${dubbo.consumer.ProductSpuService.version}")
private ProductSpuService productSpuService;
private ProductSpuRpc productSpuRpc;
@Autowired
private ProductRecommendMapper productRecommendMapper;
@ -52,7 +52,7 @@ public class ProductRecommendServiceImpl implements ProductRecommendService {
@Override
public ProductRecommendBO addProductRecommend(Integer adminId, ProductRecommendAddDTO productRecommendAddDTO) {
// 校验商品不存在
if (productSpuService.getProductSpuDetail(productRecommendAddDTO.getProductSpuId()) == null) {
if (productSpuRpc.getProductSpuDetail(productRecommendAddDTO.getProductSpuId()) == null) {
throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.PRODUCT_RECOMMEND_PRODUCT_NOT_EXISTS.getCode());
}
// 校验商品是否已经推荐
@ -74,7 +74,7 @@ public class ProductRecommendServiceImpl implements ProductRecommendService {
throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.PRODUCT_RECOMMEND_NOT_EXISTS.getCode());
}
// 校验商品不存在
if (productSpuService.getProductSpuDetail(productRecommendUpdateDTO.getProductSpuId()) == null) {
if (productSpuRpc.getProductSpuDetail(productRecommendUpdateDTO.getProductSpuId()) == null) {
throw ServiceExceptionUtil.exception(PromotionErrorCodeEnum.PRODUCT_RECOMMEND_PRODUCT_NOT_EXISTS.getCode());
}
// 校验商品是否已经推荐