商品 SPU + SKU 添加
parent
abf1f25033
commit
2243f6db55
|
@ -0,0 +1,20 @@
|
||||||
|
package cn.iocoder.common.framework.util;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class StringUtil {
|
||||||
|
|
||||||
|
public static String join(Collection<?> coll, String delim) {
|
||||||
|
return StringUtils.collectionToDelimitedString(coll, delim);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> split(String toSplit, String delim) {
|
||||||
|
String[] stringArray = StringUtils.tokenizeToStringArray(toSplit, delim);
|
||||||
|
return Arrays.asList(stringArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ import cn.iocoder.mall.product.api.constant.ProductCategoryConstants;
|
||||||
import cn.iocoder.mall.product.api.dto.ProductCategoryAddDTO;
|
import cn.iocoder.mall.product.api.dto.ProductCategoryAddDTO;
|
||||||
import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO;
|
import cn.iocoder.mall.product.api.dto.ProductCategoryUpdateDTO;
|
||||||
import cn.iocoder.mall.product.application.convert.ProductCategoryConvert;
|
import cn.iocoder.mall.product.application.convert.ProductCategoryConvert;
|
||||||
import cn.iocoder.mall.product.application.vo.admins.AdminProductCategoryTreeNodeVO;
|
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryTreeNodeVO;
|
||||||
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryVO;
|
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryVO;
|
||||||
import com.alibaba.dubbo.config.annotation.Reference;
|
import com.alibaba.dubbo.config.annotation.Reference;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
|
@ -33,16 +33,16 @@ public class AdminsProductCategoryController {
|
||||||
|
|
||||||
@GetMapping("/tree")
|
@GetMapping("/tree")
|
||||||
@ApiOperation("获得分类树结构")
|
@ApiOperation("获得分类树结构")
|
||||||
public CommonResult<List<AdminProductCategoryTreeNodeVO>> tree() {
|
public CommonResult<List<AdminsProductCategoryTreeNodeVO>> tree() {
|
||||||
List<ProductCategoryBO> productCategories = productCategoryService.getAll().getData();
|
List<ProductCategoryBO> productCategories = productCategoryService.getAll().getData();
|
||||||
// 创建 ProductCategoryTreeNodeVO Map
|
// 创建 ProductCategoryTreeNodeVO Map
|
||||||
Map<Integer, AdminProductCategoryTreeNodeVO> treeNodeMap = productCategories.stream().collect(Collectors.toMap(ProductCategoryBO::getId, ProductCategoryConvert.INSTANCE::convert));
|
Map<Integer, AdminsProductCategoryTreeNodeVO> treeNodeMap = productCategories.stream().collect(Collectors.toMap(ProductCategoryBO::getId, ProductCategoryConvert.INSTANCE::convert));
|
||||||
// 处理父子关系
|
// 处理父子关系
|
||||||
treeNodeMap.values().stream()
|
treeNodeMap.values().stream()
|
||||||
.filter(node -> !node.getPid().equals(ProductCategoryConstants.PID_ROOT))
|
.filter(node -> !node.getPid().equals(ProductCategoryConstants.PID_ROOT))
|
||||||
.forEach((childNode) -> {
|
.forEach((childNode) -> {
|
||||||
// 获得父节点
|
// 获得父节点
|
||||||
AdminProductCategoryTreeNodeVO parentNode = treeNodeMap.get(childNode.getPid());
|
AdminsProductCategoryTreeNodeVO parentNode = treeNodeMap.get(childNode.getPid());
|
||||||
if (parentNode.getChildren() == null) { // 初始化 children 数组
|
if (parentNode.getChildren() == null) { // 初始化 children 数组
|
||||||
parentNode.setChildren(new ArrayList<>());
|
parentNode.setChildren(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
@ -50,9 +50,9 @@ public class AdminsProductCategoryController {
|
||||||
parentNode.getChildren().add(childNode);
|
parentNode.getChildren().add(childNode);
|
||||||
});
|
});
|
||||||
// 获得到所有的根节点
|
// 获得到所有的根节点
|
||||||
List<AdminProductCategoryTreeNodeVO> rootNodes = treeNodeMap.values().stream()
|
List<AdminsProductCategoryTreeNodeVO> rootNodes = treeNodeMap.values().stream()
|
||||||
.filter(node -> node.getPid().equals(ProductCategoryConstants.PID_ROOT))
|
.filter(node -> node.getPid().equals(ProductCategoryConstants.PID_ROOT))
|
||||||
.sorted(Comparator.comparing(AdminProductCategoryTreeNodeVO::getSort))
|
.sorted(Comparator.comparing(AdminsProductCategoryTreeNodeVO::getSort))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
return CommonResult.success(rootNodes);
|
return CommonResult.success(rootNodes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ import com.alibaba.dubbo.config.annotation.Reference;
|
||||||
import com.fasterxml.jackson.databind.JavaType;
|
import com.fasterxml.jackson.databind.JavaType;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiImplicitParams;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
@ -35,6 +37,16 @@ public class AdminsProductSpuController {
|
||||||
|
|
||||||
@PostMapping("/spu/add")
|
@PostMapping("/spu/add")
|
||||||
@ApiOperation("创建商品")
|
@ApiOperation("创建商品")
|
||||||
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "name", value = "SPU 名字", required = true, example = "厮大牛逼"),
|
||||||
|
@ApiImplicitParam(name = "sellPoint", value = "卖点", required = true, example = "各种 MQ 骚操作"),
|
||||||
|
@ApiImplicitParam(name = "description", value = "描述", required = true, example = "你就说强不强 MQ 骚操作"),
|
||||||
|
@ApiImplicitParam(name = "cid", value = "分类编号", required = true, example = "反正我是信了"),
|
||||||
|
@ApiImplicitParam(name = "picUrls", value = "商品主图地址的数组", required = true, example = "http://www.iocoder.cn"),
|
||||||
|
@ApiImplicitParam(name = "visible", value = "是否上架商品(是否可见)", required = true, example = "true"),
|
||||||
|
@ApiImplicitParam(name = "skuStr", value = "SKU 字符串", required = true, example = "[{\"attrs\": [1,3 ], \"price\": 1, \"quantity\": 100, \"picUrl\": \"http://www.iocoder.cn\"}]"),
|
||||||
|
|
||||||
|
})
|
||||||
public CommonResult<AdminsProductSpuDetailVO> add(@RequestParam("name") String name,
|
public CommonResult<AdminsProductSpuDetailVO> add(@RequestParam("name") String name,
|
||||||
@RequestParam("sellPoint") String sellPoint,
|
@RequestParam("sellPoint") String sellPoint,
|
||||||
@RequestParam("description") String description,
|
@RequestParam("description") String description,
|
||||||
|
@ -54,6 +66,17 @@ public class AdminsProductSpuController {
|
||||||
|
|
||||||
@PostMapping("/spu/update")
|
@PostMapping("/spu/update")
|
||||||
@ApiOperation("更新商品")
|
@ApiOperation("更新商品")
|
||||||
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "id", value = "SPU 编号", required = true, example = "100"),
|
||||||
|
@ApiImplicitParam(name = "name", value = "SPU 名字", required = true, example = "厮大牛逼"),
|
||||||
|
@ApiImplicitParam(name = "sellPoint", value = "卖点", required = true, example = "各种 MQ 骚操作"),
|
||||||
|
@ApiImplicitParam(name = "description", value = "描述", required = true, example = "你就说强不强 MQ 骚操作"),
|
||||||
|
@ApiImplicitParam(name = "cid", value = "分类编号", required = true, example = "反正我是信了"),
|
||||||
|
@ApiImplicitParam(name = "picUrls", value = "商品主图地址的数组", required = true, example = "http://www.iocoder.cn"),
|
||||||
|
@ApiImplicitParam(name = "visible", value = "是否上架商品(是否可见)", required = true, example = "true"),
|
||||||
|
@ApiImplicitParam(name = "skuStr", value = "SKU 字符串", required = true, example = "[{\"attrs\": [1,3 ], \"price\": 1, \"quantity\": 100, \"picUrl\": \"http://www.iocoder.cn\"}]"),
|
||||||
|
|
||||||
|
})
|
||||||
public CommonResult<Boolean> update(@RequestParam("id") Integer id,
|
public CommonResult<Boolean> update(@RequestParam("id") Integer id,
|
||||||
@RequestParam("name") String name,
|
@RequestParam("name") String name,
|
||||||
@RequestParam("sellPoint") String sellPoint,
|
@RequestParam("sellPoint") String sellPoint,
|
||||||
|
|
|
@ -3,7 +3,7 @@ package cn.iocoder.mall.product.application.convert;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
|
import cn.iocoder.mall.product.api.bo.ProductCategoryBO;
|
||||||
import cn.iocoder.mall.product.application.vo.users.UsersProductCategoryVO;
|
import cn.iocoder.mall.product.application.vo.users.UsersProductCategoryVO;
|
||||||
import cn.iocoder.mall.product.application.vo.admins.AdminProductCategoryTreeNodeVO;
|
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryTreeNodeVO;
|
||||||
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryVO;
|
import cn.iocoder.mall.product.application.vo.admins.AdminsProductCategoryVO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.Mappings;
|
import org.mapstruct.Mappings;
|
||||||
|
@ -21,7 +21,7 @@ public interface ProductCategoryConvert {
|
||||||
|
|
||||||
List<UsersProductCategoryVO> convertToVO(List<ProductCategoryBO> categoryList);
|
List<UsersProductCategoryVO> convertToVO(List<ProductCategoryBO> categoryList);
|
||||||
|
|
||||||
AdminProductCategoryTreeNodeVO convert(ProductCategoryBO category);
|
AdminsProductCategoryTreeNodeVO convert(ProductCategoryBO category);
|
||||||
|
|
||||||
CommonResult<AdminsProductCategoryVO> convert(CommonResult<ProductCategoryBO> result);
|
CommonResult<AdminsProductCategoryVO> convert(CommonResult<ProductCategoryBO> result);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package cn.iocoder.mall.product.application.vo.admins;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
@ApiModel(value = "商品规格 VO")
|
||||||
|
public class AdminsProductAttrDetailVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "规格编号", required = true, example = "1")
|
||||||
|
private Integer attrId;
|
||||||
|
@ApiModelProperty(value = "规格名", required = true, example = "颜色")
|
||||||
|
private String attrName;
|
||||||
|
@ApiModelProperty(value = "规格值", required = true, example = "10")
|
||||||
|
private Integer attrValueId;
|
||||||
|
@ApiModelProperty(value = "规格值名", required = true, example = "红色")
|
||||||
|
private String attrValueName;
|
||||||
|
|
||||||
|
public Integer getAttrId() {
|
||||||
|
return attrId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductAttrDetailVO setAttrId(Integer attrId) {
|
||||||
|
this.attrId = attrId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttrName() {
|
||||||
|
return attrName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductAttrDetailVO setAttrName(String attrName) {
|
||||||
|
this.attrName = attrName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAttrValueId() {
|
||||||
|
return attrValueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductAttrDetailVO setAttrValueId(Integer attrValueId) {
|
||||||
|
this.attrValueId = attrValueId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttrValueName() {
|
||||||
|
return attrValueName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductAttrDetailVO setAttrValueName(String attrValueName) {
|
||||||
|
this.attrValueName = attrValueName;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ApiModel("产品分类树节点 VO")
|
@ApiModel("产品分类树节点 VO")
|
||||||
public class AdminProductCategoryTreeNodeVO {
|
public class AdminsProductCategoryTreeNodeVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "分类编号", required = true, example = "1")
|
@ApiModelProperty(value = "分类编号", required = true, example = "1")
|
||||||
private Integer id;
|
private Integer id;
|
||||||
|
@ -26,13 +26,13 @@ public class AdminProductCategoryTreeNodeVO {
|
||||||
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳")
|
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳")
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
@ApiModelProperty(value = "子节点数组")
|
@ApiModelProperty(value = "子节点数组")
|
||||||
private List<AdminProductCategoryTreeNodeVO> children;
|
private List<AdminsProductCategoryTreeNodeVO> children;
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setId(Integer id) {
|
public AdminsProductCategoryTreeNodeVO setId(Integer id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ public class AdminProductCategoryTreeNodeVO {
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setPid(Integer pid) {
|
public AdminsProductCategoryTreeNodeVO setPid(Integer pid) {
|
||||||
this.pid = pid;
|
this.pid = pid;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ public class AdminProductCategoryTreeNodeVO {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setName(String name) {
|
public AdminsProductCategoryTreeNodeVO setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ public class AdminProductCategoryTreeNodeVO {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setDescription(String description) {
|
public AdminsProductCategoryTreeNodeVO setDescription(String description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ public class AdminProductCategoryTreeNodeVO {
|
||||||
return picUrl;
|
return picUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setPicUrl(String picUrl) {
|
public AdminsProductCategoryTreeNodeVO setPicUrl(String picUrl) {
|
||||||
this.picUrl = picUrl;
|
this.picUrl = picUrl;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ public class AdminProductCategoryTreeNodeVO {
|
||||||
return sort;
|
return sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setSort(Integer sort) {
|
public AdminsProductCategoryTreeNodeVO setSort(Integer sort) {
|
||||||
this.sort = sort;
|
this.sort = sort;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ public class AdminProductCategoryTreeNodeVO {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setStatus(Integer status) {
|
public AdminsProductCategoryTreeNodeVO setStatus(Integer status) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -95,16 +95,16 @@ public class AdminProductCategoryTreeNodeVO {
|
||||||
return createTime;
|
return createTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setCreateTime(Date createTime) {
|
public AdminsProductCategoryTreeNodeVO setCreateTime(Date createTime) {
|
||||||
this.createTime = createTime;
|
this.createTime = createTime;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AdminProductCategoryTreeNodeVO> getChildren() {
|
public List<AdminsProductCategoryTreeNodeVO> getChildren() {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AdminProductCategoryTreeNodeVO setChildren(List<AdminProductCategoryTreeNodeVO> children) {
|
public AdminsProductCategoryTreeNodeVO setChildren(List<AdminsProductCategoryTreeNodeVO> children) {
|
||||||
this.children = children;
|
this.children = children;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
package cn.iocoder.mall.product.application.vo.admins;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品 Sku 明细 BO
|
||||||
|
*/
|
||||||
|
public class AdminsProductSkuDetailVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "sku 编号", required = true, example = "1")
|
||||||
|
private Integer id;
|
||||||
|
@ApiModelProperty(value = "SPU 编号", required = true, example = "1")
|
||||||
|
private Integer spuId;
|
||||||
|
@ApiModelProperty(value = "图片地址", required = true, example = "http://www.iocoder.cn")
|
||||||
|
private String picURL;
|
||||||
|
@ApiModelProperty(value = "规格值数组", required = true)
|
||||||
|
private List<AdminsProductAttrDetailVO> attrs;
|
||||||
|
@ApiModelProperty(value = "价格,单位:分", required = true, example = "100")
|
||||||
|
private Integer price;
|
||||||
|
@ApiModelProperty(value = "库存数量", required = true, example = "100")
|
||||||
|
private Integer quantity;
|
||||||
|
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSkuDetailVO setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSpuId() {
|
||||||
|
return spuId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSkuDetailVO setSpuId(Integer spuId) {
|
||||||
|
this.spuId = spuId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPicURL() {
|
||||||
|
return picURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSkuDetailVO setPicURL(String picURL) {
|
||||||
|
this.picURL = picURL;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSkuDetailVO setPrice(Integer price) {
|
||||||
|
this.price = price;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getQuantity() {
|
||||||
|
return quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSkuDetailVO setQuantity(Integer quantity) {
|
||||||
|
this.quantity = quantity;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AdminsProductAttrDetailVO> getAttrs() {
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSkuDetailVO setAttrs(List<AdminsProductAttrDetailVO> attrs) {
|
||||||
|
this.attrs = attrs;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,120 @@
|
||||||
package cn.iocoder.mall.product.application.vo.admins;
|
package cn.iocoder.mall.product.application.vo.admins;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@ApiModel(value = "商品 SPU 详细 VO", description = "包括 SKU 信息 VO")
|
@ApiModel(value = "商品 SPU 详细 VO", description = "包括 SKU 信息 VO")
|
||||||
public class AdminsProductSpuDetailVO {
|
public class AdminsProductSpuDetailVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "SPU 编号", required = true, example = "1")
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
// ========== 基本信息 =========
|
||||||
|
@ApiModelProperty(value = "SPU 名字", required = true, example = "厮大牛逼")
|
||||||
|
private String name;
|
||||||
|
@ApiModelProperty(value = "卖点", required = true, example = "各种 MQ 骚操作")
|
||||||
|
private String sellPoint;
|
||||||
|
@ApiModelProperty(value = "描述", required = true, example = "你就说强不强")
|
||||||
|
private String description;
|
||||||
|
@ApiModelProperty(value = "分类编号", required = true, example = "反正我是信了")
|
||||||
|
private Integer cid;
|
||||||
|
@ApiModelProperty(value = "商品主图地址的数组", required = true, example = "http://www.iocoder.cn")
|
||||||
|
private List<String> picUrls;
|
||||||
|
|
||||||
|
// ========== 其他信息 =========
|
||||||
|
@ApiModelProperty(value = "是否上架商品(是否可见)", required = true, example = "true")
|
||||||
|
private Boolean visible;
|
||||||
|
@ApiModelProperty(value = "排序字段", required = true, example = "10")
|
||||||
|
private Integer sort;
|
||||||
|
|
||||||
|
// ========== SKU =========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SKU 数组
|
||||||
|
*/
|
||||||
|
private List<AdminsProductSkuDetailVO> skus;
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSellPoint() {
|
||||||
|
return sellPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setSellPoint(String sellPoint) {
|
||||||
|
this.sellPoint = sellPoint;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCid() {
|
||||||
|
return cid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setCid(Integer cid) {
|
||||||
|
this.cid = cid;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPicUrls() {
|
||||||
|
return picUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setPicUrls(List<String> picUrls) {
|
||||||
|
this.picUrls = picUrls;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getVisible() {
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setVisible(Boolean visible) {
|
||||||
|
this.visible = visible;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSort() {
|
||||||
|
return sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setSort(Integer sort) {
|
||||||
|
this.sort = sort;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AdminsProductSkuDetailVO> getSkus() {
|
||||||
|
return skus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdminsProductSpuDetailVO setSkus(List<AdminsProductSkuDetailVO> skus) {
|
||||||
|
this.skus = skus;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
package cn.iocoder.mall.product.api.bo;
|
package cn.iocoder.mall.product.api.bo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 商品规格 BO
|
* 商品规格明细 BO
|
||||||
*/
|
*/
|
||||||
public class ProductAttrBO {
|
public class ProductAttrDetailBO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格编号
|
* 规格编号
|
||||||
|
@ -26,7 +26,7 @@ public class ProductAttrBO {
|
||||||
return attrId;
|
return attrId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductAttrBO setAttrId(Integer attrId) {
|
public ProductAttrDetailBO setAttrId(Integer attrId) {
|
||||||
this.attrId = attrId;
|
this.attrId = attrId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ public class ProductAttrBO {
|
||||||
return attrName;
|
return attrName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductAttrBO setAttrName(String attrName) {
|
public ProductAttrDetailBO setAttrName(String attrName) {
|
||||||
this.attrName = attrName;
|
this.attrName = attrName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ public class ProductAttrBO {
|
||||||
return attrValueId;
|
return attrValueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductAttrBO setAttrValueId(Integer attrValueId) {
|
public ProductAttrDetailBO setAttrValueId(Integer attrValueId) {
|
||||||
this.attrValueId = attrValueId;
|
this.attrValueId = attrValueId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public class ProductAttrBO {
|
||||||
return attrValueName;
|
return attrValueName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductAttrBO setAttrValueName(String attrValueName) {
|
public ProductAttrDetailBO setAttrValueName(String attrValueName) {
|
||||||
this.attrValueName = attrValueName;
|
this.attrValueName = attrValueName;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
|
@ -14,17 +14,7 @@ public class ProductSkuDetailBO {
|
||||||
/**
|
/**
|
||||||
* 商品编号
|
* 商品编号
|
||||||
*/
|
*/
|
||||||
private Integer itemId;
|
private Integer spuId;
|
||||||
|
|
||||||
// TODO 店铺编号
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 状态
|
|
||||||
*
|
|
||||||
* 1-正常
|
|
||||||
* 2-禁用
|
|
||||||
*/
|
|
||||||
private Integer status;
|
|
||||||
/**
|
/**
|
||||||
* 图片地址
|
* 图片地址
|
||||||
*/
|
*/
|
||||||
|
@ -32,7 +22,7 @@ public class ProductSkuDetailBO {
|
||||||
/**
|
/**
|
||||||
* 规格值数组
|
* 规格值数组
|
||||||
*/
|
*/
|
||||||
private List<ProductAttrBO> attrs;
|
private List<ProductAttrDetailBO> attrs;
|
||||||
/**
|
/**
|
||||||
* 价格,单位:分
|
* 价格,单位:分
|
||||||
*/
|
*/
|
||||||
|
@ -42,4 +32,59 @@ public class ProductSkuDetailBO {
|
||||||
*/
|
*/
|
||||||
private Integer quantity;
|
private Integer quantity;
|
||||||
|
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDetailBO setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSpuId() {
|
||||||
|
return spuId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDetailBO setSpuId(Integer spuId) {
|
||||||
|
this.spuId = spuId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPicURL() {
|
||||||
|
return picURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDetailBO setPicURL(String picURL) {
|
||||||
|
this.picURL = picURL;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ProductAttrDetailBO> getAttrs() {
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDetailBO setAttrs(List<ProductAttrDetailBO> attrs) {
|
||||||
|
this.attrs = attrs;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDetailBO setPrice(Integer price) {
|
||||||
|
this.price = price;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getQuantity() {
|
||||||
|
return quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDetailBO setQuantity(Integer quantity) {
|
||||||
|
this.quantity = quantity;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
package cn.iocoder.mall.product.api.bo;
|
package cn.iocoder.mall.product.api.bo;
|
||||||
|
|
||||||
import cn.iocoder.mall.product.api.dto.ProductSkuAddDTO;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,15 +49,94 @@ public class ProductSpuDetailBO {
|
||||||
/**
|
/**
|
||||||
* 排序字段
|
* 排序字段
|
||||||
*/
|
*/
|
||||||
private Integer order;
|
private Integer sort;
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
// ========== SKU =========
|
// ========== SKU =========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SKU 数组
|
* SKU 数组
|
||||||
*/
|
*/
|
||||||
private List<ProductSkuAddDTO> skus;
|
private List<ProductSkuDetailBO> skus;
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSellPoint() {
|
||||||
|
return sellPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setSellPoint(String sellPoint) {
|
||||||
|
this.sellPoint = sellPoint;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCid() {
|
||||||
|
return cid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setCid(Integer cid) {
|
||||||
|
this.cid = cid;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPicUrls() {
|
||||||
|
return picUrls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setPicUrls(List<String> picUrls) {
|
||||||
|
this.picUrls = picUrls;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getVisible() {
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setVisible(Boolean visible) {
|
||||||
|
this.visible = visible;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSort() {
|
||||||
|
return sort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setSort(Integer sort) {
|
||||||
|
this.sort = sort;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ProductSkuDetailBO> getSkus() {
|
||||||
|
return skus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSpuDetailBO setSkus(List<ProductSkuDetailBO> skus) {
|
||||||
|
this.skus = skus;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package cn.iocoder.mall.product.api.constant;
|
||||||
|
|
||||||
|
public class ProductAttrConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ATTR 状态 - 开启
|
||||||
|
*/
|
||||||
|
public static final Integer ATTR_STATUS_ENABLE = 1;
|
||||||
|
/**
|
||||||
|
* ATTR 状态 - 关闭
|
||||||
|
*/
|
||||||
|
public static final Integer ATTR_STATUS_DISABLE = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ATTR_VALUE 状态 - 开启
|
||||||
|
*/
|
||||||
|
public static final Integer ATTR_VALUE_STATUS_ENABLE = 1;
|
||||||
|
/**
|
||||||
|
* ATTR_VALUE 状态 - 关闭
|
||||||
|
*/
|
||||||
|
public static final Integer ATTR_VALUE_STATUS_DISABLE = 2;
|
||||||
|
|
||||||
|
}
|
|
@ -11,8 +11,20 @@ public enum ProductErrorCodeEnum {
|
||||||
PRODUCT_CATEGORY_PARENT_NOT_EXISTS(1003001000, "父分类不存在"),
|
PRODUCT_CATEGORY_PARENT_NOT_EXISTS(1003001000, "父分类不存在"),
|
||||||
PRODUCT_CATEGORY_NOT_EXISTS(1003001001, "商品分类不存在"),
|
PRODUCT_CATEGORY_NOT_EXISTS(1003001001, "商品分类不存在"),
|
||||||
PRODUCT_CATEGORY_PARENT_NOT_SELF(1003001002, "不能设置自己为父分类"),
|
PRODUCT_CATEGORY_PARENT_NOT_SELF(1003001002, "不能设置自己为父分类"),
|
||||||
PRODUCT_CATEGORY_STATUS_EQUALS(1002002003, "商品分类已经是该状态"),
|
PRODUCT_CATEGORY_STATUS_EQUALS(1002001003, "商品分类已经是该状态"),
|
||||||
PRODUCT_CATEGORY_DELETE_ONLY_DISABLE(1002002004, "只有关闭的商品分类才可以删除"),
|
PRODUCT_CATEGORY_DELETE_ONLY_DISABLE(1002001004, "只有关闭的商品分类才可以删除"),
|
||||||
|
PRODUCT_CATEGORY_MUST_ENABLE(1002001005, "只有开启的商品分类,才可以使用"),
|
||||||
|
|
||||||
|
// ========== PRODUCT SPU + SKU 模块 ==========
|
||||||
|
PRODUCT_SKU_ATTR_CANT_NOT_DUPLICATE(1003002000, "一个 Sku 下,不能有重复的规格"),
|
||||||
|
PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS(1003002001, "一个 Spu 下的每个 Sku ,其规格数必须一致"),
|
||||||
|
PRODUCT_SPU_SKU__NOT_DUPLICATE(1003002002, "一个 Spu 下的每个 Sku ,必须不重复"),
|
||||||
|
|
||||||
|
|
||||||
|
// ========== PRODUCT ATTR + ATTR_VALUE 模块 ==========
|
||||||
|
PRODUCT_ATTR_VALUE_NOT_EXIST(1003003000, "商品属性值不存在"),
|
||||||
|
|
||||||
|
PRODUCT_ATTR_NOT_EXIST(1003003001, "商品属性值不存在"),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package cn.iocoder.mall.product.api.constant;
|
||||||
|
|
||||||
|
public class ProductSpuConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态 - 开启
|
||||||
|
*/
|
||||||
|
public static final Integer SKU_STATUS_ENABLE = 1;
|
||||||
|
/**
|
||||||
|
* 状态 - 关闭
|
||||||
|
*/
|
||||||
|
public static final Integer SKU_STATUS_DISABLE = 2;
|
||||||
|
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ public class ProductSpuAddDTO {
|
||||||
/**
|
/**
|
||||||
* 分类编号
|
* 分类编号
|
||||||
*/
|
*/
|
||||||
@NotEmpty(message = "分类不能为空")
|
@NotNull(message = "分类不能为空")
|
||||||
private Integer cid;
|
private Integer cid;
|
||||||
/**
|
/**
|
||||||
* 商品主图地址
|
* 商品主图地址
|
||||||
|
|
|
@ -1,11 +1,26 @@
|
||||||
package cn.iocoder.mall.product.convert;
|
package cn.iocoder.mall.product.convert;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.util.StringUtil;
|
||||||
|
import cn.iocoder.mall.product.api.bo.ProductAttrDetailBO;
|
||||||
|
import cn.iocoder.mall.product.api.bo.ProductSkuDetailBO;
|
||||||
import cn.iocoder.mall.product.api.bo.ProductSpuBO;
|
import cn.iocoder.mall.product.api.bo.ProductSpuBO;
|
||||||
|
import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO;
|
||||||
|
import cn.iocoder.mall.product.api.dto.ProductSkuAddDTO;
|
||||||
|
import cn.iocoder.mall.product.api.dto.ProductSkuUpdateDTO;
|
||||||
|
import cn.iocoder.mall.product.api.dto.ProductSpuAddDTO;
|
||||||
|
import cn.iocoder.mall.product.api.dto.ProductSpuUpdateDTO;
|
||||||
|
import cn.iocoder.mall.product.dataobject.ProductSkuDO;
|
||||||
import cn.iocoder.mall.product.dataobject.ProductSpuDO;
|
import cn.iocoder.mall.product.dataobject.ProductSpuDO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mapping;
|
||||||
import org.mapstruct.Mappings;
|
import org.mapstruct.Mappings;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface ProductSpuConvert {
|
public interface ProductSpuConvert {
|
||||||
|
|
||||||
|
@ -14,4 +29,60 @@ public interface ProductSpuConvert {
|
||||||
@Mappings({})
|
@Mappings({})
|
||||||
ProductSpuBO convert(ProductSpuDO spu);
|
ProductSpuBO convert(ProductSpuDO spu);
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(source = "picUrls", target = "picUrls", ignore = true)
|
||||||
|
})
|
||||||
|
ProductSpuDO convert(ProductSpuAddDTO productSpuAddDTO);
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(source = "attrs", target = "attrs", ignore = true)
|
||||||
|
})
|
||||||
|
ProductSkuDO convert(ProductSkuAddDTO productSkuAddDTO);
|
||||||
|
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(source = "picUrls", target = "picUrls", ignore = true)
|
||||||
|
})
|
||||||
|
ProductSpuDO convert(ProductSpuUpdateDTO productSpuUpdateDTO);
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(source = "attrs", target = "attrs", ignore = true)
|
||||||
|
})
|
||||||
|
ProductSkuDO convert(ProductSkuUpdateDTO productSkuUpdateDTO);
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
ProductSpuDetailBO convert(ProductSpuBO spu);
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(source = "picUrls", target = "picUrls", ignore = true)
|
||||||
|
})
|
||||||
|
ProductSpuDetailBO convert2(ProductSpuDO spu);
|
||||||
|
|
||||||
|
@Mappings({
|
||||||
|
@Mapping(source = "attrs", target = "attrs", ignore = true)
|
||||||
|
})
|
||||||
|
ProductSkuDetailBO convert2(ProductSkuDO sku);
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
default ProductSpuDetailBO convert2(ProductSpuDO spu, List<ProductSkuDO> skus, List<ProductAttrDetailBO> productAttrDetailBOs) {
|
||||||
|
// 创建并转换 ProductSpuDetailBO 对象
|
||||||
|
ProductSpuDetailBO spuDetail = this.convert2(spu).setPicUrls(StringUtil.split(spu.getPicUrls(), ","));
|
||||||
|
// 创建 ProductAttrDetailBO 的映射。其中,KEY 为 ProductAttrDetailBO.attrValueId ,即规格值的编号
|
||||||
|
Map<Integer, ProductAttrDetailBO> productAttrDetailBOMap = productAttrDetailBOs.stream().collect(
|
||||||
|
Collectors.toMap(ProductAttrDetailBO::getAttrValueId, productAttrDetailBO -> productAttrDetailBO));
|
||||||
|
// 创建并转换 ProductSpuDetailBO 数组
|
||||||
|
spuDetail.setSkus(new ArrayList<>());
|
||||||
|
skus.forEach(sku -> {
|
||||||
|
// 创建 ProductSpuDetailBO 对象
|
||||||
|
ProductSkuDetailBO skuDetail = ProductSpuConvert.this.convert2(sku)
|
||||||
|
.setAttrs(new ArrayList<>());
|
||||||
|
spuDetail.getSkus().add(skuDetail);
|
||||||
|
// 设置 ProductSpuDetailBO 的 attrs 规格属性
|
||||||
|
List<String> attrs = StringUtil.split(sku.getAttrs(), ",");
|
||||||
|
attrs.forEach(attr -> skuDetail.getAttrs().add(productAttrDetailBOMap.get(Integer.valueOf(attr))));
|
||||||
|
});
|
||||||
|
// 返回
|
||||||
|
return spuDetail;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package cn.iocoder.mall.product.dao;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.product.dataobject.ProductAttrDO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ProductAttrMapper {
|
||||||
|
|
||||||
|
ProductAttrDO selectById(@Param("id") Integer id);
|
||||||
|
|
||||||
|
List<ProductAttrDO> selectListByIds(@Param("ids") Collection<Integer> ids);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package cn.iocoder.mall.product.dao;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.product.dataobject.ProductAttrValueDO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ProductAttrValueMapper {
|
||||||
|
|
||||||
|
ProductAttrValueDO selectById(@Param("id") Integer id);
|
||||||
|
|
||||||
|
List<ProductAttrValueDO> selectListByIds(@Param("ids") Collection<Integer> ids);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package cn.iocoder.mall.product.dao;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.product.dataobject.ProductSkuDO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface ProductSkuMapper {
|
||||||
|
|
||||||
|
ProductSkuDO selectById(Integer id);
|
||||||
|
|
||||||
|
void insertList(@Param("productSkuDOs") List<ProductSkuDO> productSkuDOs);
|
||||||
|
|
||||||
|
}
|
|
@ -8,4 +8,8 @@ public interface ProductSpuMapper {
|
||||||
|
|
||||||
ProductSpuDO selectById(Integer id);
|
ProductSpuDO selectById(Integer id);
|
||||||
|
|
||||||
|
void insert(ProductSpuDO productSpuDO);
|
||||||
|
|
||||||
|
void update(ProductSpuDO productSpuDO);
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package cn.iocoder.mall.product.dataobject;
|
package cn.iocoder.mall.product.dataobject;
|
||||||
|
|
||||||
import java.util.Date;
|
import cn.iocoder.common.framework.dataobject.BaseDO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Product 规格
|
* Product 规格
|
||||||
*/
|
*/
|
||||||
public class ProductAttrDO {
|
public class ProductAttrDO extends BaseDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格编号
|
* 规格编号
|
||||||
|
@ -15,20 +15,39 @@ public class ProductAttrDO {
|
||||||
* 名称
|
* 名称
|
||||||
*/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
private Date createTime;
|
|
||||||
/**
|
|
||||||
* 最后更新时间
|
|
||||||
*/
|
|
||||||
private Date updateTime;
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
*
|
*
|
||||||
* 1-正常
|
* 1-开启
|
||||||
* 2-删除
|
* 2-禁用
|
||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductAttrDO setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductAttrDO setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductAttrDO setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package cn.iocoder.mall.product.dataobject;
|
package cn.iocoder.mall.product.dataobject;
|
||||||
|
|
||||||
import java.util.Date;
|
import cn.iocoder.common.framework.dataobject.BaseDO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Product 规格值
|
* Product 规格值
|
||||||
*/
|
*/
|
||||||
public class ProductAttrValueDO {
|
public class ProductAttrValueDO extends BaseDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 规格值编号
|
* 规格值编号
|
||||||
|
@ -19,20 +19,48 @@ public class ProductAttrValueDO {
|
||||||
* 规格值
|
* 规格值
|
||||||
*/
|
*/
|
||||||
private String name;
|
private String name;
|
||||||
/**
|
|
||||||
* 创建时间
|
|
||||||
*/
|
|
||||||
private Date createTime;
|
|
||||||
/**
|
|
||||||
* 最后更新时间
|
|
||||||
*/
|
|
||||||
private Date updateTime;
|
|
||||||
/**
|
/**
|
||||||
* 状态
|
* 状态
|
||||||
*
|
*
|
||||||
* 1-正常
|
* 1-正常
|
||||||
* 2-删除
|
* 2-禁用
|
||||||
*/
|
*/
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductAttrValueDO setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAttrId() {
|
||||||
|
return attrId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductAttrValueDO setAttrId(Integer attrId) {
|
||||||
|
this.attrId = attrId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductAttrValueDO setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductAttrValueDO setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -7,9 +7,6 @@ import cn.iocoder.common.framework.dataobject.BaseDO;
|
||||||
*/
|
*/
|
||||||
public class ProductCategoryDO extends BaseDO {
|
public class ProductCategoryDO extends BaseDO {
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static final Integer STATUS_ENABLE = 1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分类编号
|
* 分类编号
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,7 +14,7 @@ public class ProductSkuDO extends BaseDO {
|
||||||
/**
|
/**
|
||||||
* 商品编号
|
* 商品编号
|
||||||
*/
|
*/
|
||||||
private Integer itemId;
|
private Integer spuId;
|
||||||
|
|
||||||
// TODO 店铺编号
|
// TODO 店铺编号
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ public class ProductSkuDO extends BaseDO {
|
||||||
/**
|
/**
|
||||||
* 图片地址
|
* 图片地址
|
||||||
*/
|
*/
|
||||||
private String picURL;
|
private String picUrl;
|
||||||
/**
|
/**
|
||||||
* 规格值({@link ProductAttrDO})数组
|
* 规格值({@link ProductAttrDO})数组
|
||||||
*
|
*
|
||||||
|
@ -52,4 +52,68 @@ public class ProductSkuDO extends BaseDO {
|
||||||
// */
|
// */
|
||||||
// private Integer soldNum;
|
// private Integer soldNum;
|
||||||
|
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDO setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSpuId() {
|
||||||
|
return spuId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDO setSpuId(Integer spuId) {
|
||||||
|
this.spuId = spuId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDO setStatus(Integer status) {
|
||||||
|
this.status = status;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPicUrl() {
|
||||||
|
return picUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDO setPicUrl(String picUrl) {
|
||||||
|
this.picUrl = picUrl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttrs() {
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDO setAttrs(String attrs) {
|
||||||
|
this.attrs = attrs;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDO setPrice(Integer price) {
|
||||||
|
this.price = price;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getQuantity() {
|
||||||
|
return quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProductSkuDO setQuantity(Integer quantity) {
|
||||||
|
this.quantity = quantity;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -55,7 +55,7 @@ public class ProductSpuDO extends BaseDO {
|
||||||
/**
|
/**
|
||||||
* 排序字段
|
* 排序字段
|
||||||
*/
|
*/
|
||||||
private Integer order;
|
private Integer sort;
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -119,12 +119,15 @@ public class ProductSpuDO extends BaseDO {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getOrder() {
|
public Integer getSort() {
|
||||||
return order;
|
return sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductSpuDO setOrder(Integer order) {
|
public ProductSpuDO setSort(Integer sort) {
|
||||||
this.order = order;
|
this.sort = sort;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package cn.iocoder.mall.product.service;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
|
import cn.iocoder.mall.product.api.bo.ProductAttrDetailBO;
|
||||||
|
import cn.iocoder.mall.product.api.constant.ProductAttrConstants;
|
||||||
|
import cn.iocoder.mall.product.api.constant.ProductErrorCodeEnum;
|
||||||
|
import cn.iocoder.mall.product.dao.ProductAttrMapper;
|
||||||
|
import cn.iocoder.mall.product.dao.ProductAttrValueMapper;
|
||||||
|
import cn.iocoder.mall.product.dataobject.ProductAttrDO;
|
||||||
|
import cn.iocoder.mall.product.dataobject.ProductAttrValueDO;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品规格 Service 实现类
|
||||||
|
*
|
||||||
|
* @see cn.iocoder.mall.product.dataobject.ProductAttrDO
|
||||||
|
* @see cn.iocoder.mall.product.dataobject.ProductAttrValueDO
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class ProductAttrServiceImpl {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ProductAttrMapper productAttrMapper;
|
||||||
|
@Autowired
|
||||||
|
private ProductAttrValueMapper productValueMapper;
|
||||||
|
|
||||||
|
public CommonResult<List<ProductAttrDetailBO>> validProductAttrAndValue(Set<Integer> productAttrValueIds) {
|
||||||
|
// 首先,校验规格值
|
||||||
|
List<ProductAttrValueDO> attrValues = productValueMapper.selectListByIds(productAttrValueIds);
|
||||||
|
if (attrValues.size() != productAttrValueIds.size()) {
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_VALUE_NOT_EXIST.getCode());
|
||||||
|
}
|
||||||
|
for (ProductAttrValueDO attrValue : attrValues) { // 同时,校验下状态
|
||||||
|
if (ProductAttrConstants.ATTR_STATUS_DISABLE.equals(attrValue.getStatus())) {
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_VALUE_NOT_EXIST.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 然后,校验规格
|
||||||
|
Set<Integer> attrIds = attrValues.stream().map(ProductAttrValueDO::getAttrId).collect(Collectors.toSet());
|
||||||
|
List<ProductAttrDO> attrs = productAttrMapper.selectListByIds(attrIds);
|
||||||
|
if (attrs.size() != attrIds.size()) {
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_NOT_EXIST.getCode());
|
||||||
|
}
|
||||||
|
for (ProductAttrDO attr : attrs) { // 同时,校验下状态
|
||||||
|
if (ProductAttrConstants.ATTR_VALUE_STATUS_DISABLE.equals(attr.getStatus())) {
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_NOT_EXIST.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 返回成功
|
||||||
|
Map<Integer, ProductAttrDO> attrMap = attrs.stream().collect(Collectors.toMap(ProductAttrDO::getId, productAttrDO -> productAttrDO)); // ProductAttrDO 的映射,方便查找。
|
||||||
|
List<ProductAttrDetailBO> result = attrValues.stream().map(productAttrValueDO -> new ProductAttrDetailBO()
|
||||||
|
.setAttrId(productAttrValueDO.getAttrId()).setAttrName(attrMap.get(productAttrValueDO.getAttrId()).getName())
|
||||||
|
.setAttrValueId(productAttrValueDO.getId()).setAttrValueName(productAttrValueDO.getName())).collect(Collectors.toList());
|
||||||
|
return CommonResult.success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProductCategoryBO> getListByPid(Integer pid) {
|
public List<ProductCategoryBO> getListByPid(Integer pid) {
|
||||||
List<ProductCategoryDO> categoryList = productCategoryMapper.selectListByPidAndStatusOrderBySort(pid, ProductCategoryDO.STATUS_ENABLE);
|
List<ProductCategoryDO> categoryList = productCategoryMapper.selectListByPidAndStatusOrderBySort(pid, ProductCategoryConstants.STATUS_ENABLE);
|
||||||
return ProductCategoryConvert.INSTANCE.convertToBO(categoryList);
|
return ProductCategoryConvert.INSTANCE.convertToBO(categoryList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
|
||||||
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_DELETE_ONLY_DISABLE.getCode());
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_DELETE_ONLY_DISABLE.getCode());
|
||||||
}
|
}
|
||||||
// TODO 芋艿:考虑下,是否需要判断下该分类下是否有商品
|
// TODO 芋艿:考虑下,是否需要判断下该分类下是否有商品
|
||||||
|
// TODO 芋艿,需要补充下,还有子分类
|
||||||
// 标记删除商品分类
|
// 标记删除商品分类
|
||||||
ProductCategoryDO updateProductCategory = new ProductCategoryDO().setId(productCategoryId);
|
ProductCategoryDO updateProductCategory = new ProductCategoryDO().setId(productCategoryId);
|
||||||
updateProductCategory.setDeleted(BaseDO.DELETED_YES);
|
updateProductCategory.setDeleted(BaseDO.DELETED_YES);
|
||||||
|
@ -119,6 +120,20 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
|
||||||
return CommonResult.success(true);
|
return CommonResult.success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommonResult<ProductCategoryDO> validProductCategory(Integer productCategoryId) {
|
||||||
|
// 校验分类是否存在
|
||||||
|
ProductCategoryDO productCategory = productCategoryMapper.selectById(productCategoryId);
|
||||||
|
if (productCategory == null) {
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode());
|
||||||
|
}
|
||||||
|
// 只有禁用的商品分类才可以删除
|
||||||
|
if (ProductCategoryConstants.STATUS_DISABLE.equals(productCategory.getStatus())) {
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_CATEGORY_MUST_ENABLE.getCode());
|
||||||
|
}
|
||||||
|
// 返回结果
|
||||||
|
return CommonResult.success(productCategory);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isValidStatus(Integer status) {
|
private boolean isValidStatus(Integer status) {
|
||||||
return ProductCategoryConstants.STATUS_ENABLE.equals(status)
|
return ProductCategoryConstants.STATUS_ENABLE.equals(status)
|
||||||
|| ProductCategoryConstants.STATUS_DISABLE.equals(status);
|
|| ProductCategoryConstants.STATUS_DISABLE.equals(status);
|
||||||
|
|
|
@ -1,39 +1,143 @@
|
||||||
package cn.iocoder.mall.product.service;
|
package cn.iocoder.mall.product.service;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.dataobject.BaseDO;
|
||||||
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
|
import cn.iocoder.common.framework.util.StringUtil;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
import cn.iocoder.mall.product.api.ProductSpuService;
|
import cn.iocoder.mall.product.api.ProductSpuService;
|
||||||
|
import cn.iocoder.mall.product.api.bo.ProductAttrDetailBO;
|
||||||
import cn.iocoder.mall.product.api.bo.ProductSpuBO;
|
import cn.iocoder.mall.product.api.bo.ProductSpuBO;
|
||||||
import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO;
|
import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO;
|
||||||
|
import cn.iocoder.mall.product.api.constant.ProductErrorCodeEnum;
|
||||||
|
import cn.iocoder.mall.product.api.constant.ProductSpuConstants;
|
||||||
|
import cn.iocoder.mall.product.api.dto.ProductSkuAddDTO;
|
||||||
import cn.iocoder.mall.product.api.dto.ProductSpuAddDTO;
|
import cn.iocoder.mall.product.api.dto.ProductSpuAddDTO;
|
||||||
import cn.iocoder.mall.product.api.dto.ProductSpuUpdateDTO;
|
import cn.iocoder.mall.product.api.dto.ProductSpuUpdateDTO;
|
||||||
import cn.iocoder.mall.product.convert.ProductSpuConvert;
|
import cn.iocoder.mall.product.convert.ProductSpuConvert;
|
||||||
|
import cn.iocoder.mall.product.dao.ProductSkuMapper;
|
||||||
import cn.iocoder.mall.product.dao.ProductSpuMapper;
|
import cn.iocoder.mall.product.dao.ProductSpuMapper;
|
||||||
|
import cn.iocoder.mall.product.dataobject.ProductCategoryDO;
|
||||||
|
import cn.iocoder.mall.product.dataobject.ProductSkuDO;
|
||||||
import cn.iocoder.mall.product.dataobject.ProductSpuDO;
|
import cn.iocoder.mall.product.dataobject.ProductSpuDO;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示
|
@Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示
|
||||||
@com.alibaba.dubbo.config.annotation.Service
|
@com.alibaba.dubbo.config.annotation.Service(validation = "true")
|
||||||
public class ProductSpuServiceImpl implements ProductSpuService {
|
public class ProductSpuServiceImpl implements ProductSpuService {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProductSpuMapper productSpuDAO;
|
private ProductSpuMapper productSpuMapper;
|
||||||
|
@Autowired
|
||||||
|
private ProductSkuMapper productSkuMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ProductCategoryServiceImpl productCategoryService;
|
||||||
|
@Autowired
|
||||||
|
private ProductAttrServiceImpl productAttrService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProductSpuBO getProductSpu(Integer id) {
|
public ProductSpuBO getProductSpu(Integer id) {
|
||||||
ProductSpuDO productSpuDO = productSpuDAO.selectById(id);
|
ProductSpuDO productSpuDO = productSpuMapper.selectById(id);
|
||||||
// 转换成 BO
|
// 转换成 BO
|
||||||
return ProductSpuConvert.INSTANCE.convert(productSpuDO);
|
return ProductSpuConvert.INSTANCE.convert(productSpuDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public CommonResult<ProductSpuDetailBO> addProductSpu(Integer adminId, ProductSpuAddDTO productSpuAddDTO) {
|
public CommonResult<ProductSpuDetailBO> addProductSpu(Integer adminId, ProductSpuAddDTO productSpuAddDTO) {
|
||||||
return null;
|
// 校验商品分类分类存在
|
||||||
|
CommonResult<ProductCategoryDO> validCategoryResult = productCategoryService.validProductCategory(productSpuAddDTO.getCid());
|
||||||
|
if (validCategoryResult.isError()) {
|
||||||
|
return CommonResult.error(validCategoryResult);
|
||||||
|
}
|
||||||
|
// 校验规格是否存在
|
||||||
|
Set<Integer> productAttrValueIds = new HashSet<>();
|
||||||
|
productSpuAddDTO.getSkus().forEach(productSkuAddDTO -> productAttrValueIds.addAll(productSkuAddDTO.getAttrs()));
|
||||||
|
CommonResult<List<ProductAttrDetailBO>> validAttrResult = productAttrService.validProductAttrAndValue(productAttrValueIds);
|
||||||
|
if (validAttrResult.isError()) {
|
||||||
|
return CommonResult.error(validAttrResult);
|
||||||
|
}
|
||||||
|
// 保存 Spu
|
||||||
|
ProductSpuDO spu = ProductSpuConvert.INSTANCE.convert(productSpuAddDTO)
|
||||||
|
.setPicUrls(StringUtil.join(productSpuAddDTO.getPicUrls(), ","))
|
||||||
|
.setSort(0); // 排序为 0
|
||||||
|
spu.setCreateTime(new Date()).setDeleted(BaseDO.DELETED_NO);
|
||||||
|
productSpuMapper.insert(spu);
|
||||||
|
// 保存 Sku
|
||||||
|
List<ProductSkuDO> skus = productSpuAddDTO.getSkus().stream().map(productSkuAddDTO -> {
|
||||||
|
ProductSkuDO sku = ProductSpuConvert.INSTANCE.convert(productSkuAddDTO)
|
||||||
|
.setSpuId(spu.getId())
|
||||||
|
.setStatus(ProductSpuConstants.SKU_STATUS_ENABLE)
|
||||||
|
.setAttrs(StringUtil.join(productSkuAddDTO.getAttrs(), ","));
|
||||||
|
sku.setCreateTime(new Date()).setDeleted(BaseDO.DELETED_NO);
|
||||||
|
return sku;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
// 校验 Sku 规格
|
||||||
|
CommonResult<Boolean> validProductSkuResult = validProductSku(productSpuAddDTO.getSkus(), validAttrResult.getData());
|
||||||
|
if (validProductSkuResult.isError()) {
|
||||||
|
return CommonResult.error(validProductSkuResult);
|
||||||
|
}
|
||||||
|
productSkuMapper.insertList(skus);
|
||||||
|
// 返回成功
|
||||||
|
return CommonResult.success(ProductSpuConvert.INSTANCE.convert2(spu, skus, validAttrResult.getData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<Boolean> updateProductSpu(Integer adminId, ProductSpuUpdateDTO productSpuUpdateDTO) {
|
public CommonResult<Boolean> updateProductSpu(Integer adminId, ProductSpuUpdateDTO productSpuUpdateDTO) {
|
||||||
return null;
|
// 校验商品分类分类存在
|
||||||
|
CommonResult<ProductCategoryDO> validCategoryResult = productCategoryService.validProductCategory(productSpuUpdateDTO.getCid());
|
||||||
|
if (validCategoryResult.isError()) {
|
||||||
|
return CommonResult.error(validCategoryResult);
|
||||||
|
}
|
||||||
|
// 校验规格是否存在
|
||||||
|
Set<Integer> productAttrValueIds = new HashSet<>();
|
||||||
|
productSpuUpdateDTO.getSkus().forEach(productSkuAddDTO -> productAttrValueIds.addAll(productSkuAddDTO.getAttrs()));
|
||||||
|
CommonResult<List<ProductAttrDetailBO>> validAttrResult = productAttrService.validProductAttrAndValue(productAttrValueIds);
|
||||||
|
if (validAttrResult.isError()) {
|
||||||
|
return CommonResult.error(validAttrResult);
|
||||||
|
}
|
||||||
|
// 更新 Spu
|
||||||
|
ProductSpuDO updateSpu = ProductSpuConvert.INSTANCE.convert(productSpuUpdateDTO)
|
||||||
|
.setPicUrls(StringUtil.join(productSpuUpdateDTO.getPicUrls(), ","));
|
||||||
|
productSpuMapper.update(updateSpu);
|
||||||
|
// 校验 Sku 规格
|
||||||
|
return CommonResult.success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CommonResult<Boolean> validProductSku(List<ProductSkuAddDTO> productSkuAddDTOs, List<ProductAttrDetailBO> productAttrDetailBOs) {
|
||||||
|
// 创建 ProductAttrDetailBO 的映射。其中,KEY 为 ProductAttrDetailBO.attrValueId ,即规格值的编号
|
||||||
|
Map<Integer, ProductAttrDetailBO> productAttrDetailBOMap = productAttrDetailBOs.stream().collect(
|
||||||
|
Collectors.toMap(ProductAttrDetailBO::getAttrValueId, productAttrDetailBO -> productAttrDetailBO));
|
||||||
|
// 1. 先校验,一个 Sku 下,没有重复的规格。校验方式是,遍历每个 Sku ,看看是否有重复的规格 attrId
|
||||||
|
for (ProductSkuAddDTO sku : productSkuAddDTOs) {
|
||||||
|
Set<Integer> attrIds = sku.getAttrs().stream().map(attrValueId -> productAttrDetailBOMap.get(attrValueId).getAttrId()).collect(Collectors.toSet());
|
||||||
|
if (attrIds.size() != sku.getAttrs().size()) {
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_SKU_ATTR_CANT_NOT_DUPLICATE.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2. 再校验,每个 Sku 的规格值的数量,是一致的。
|
||||||
|
int attrSize = productSkuAddDTOs.get(0).getAttrs().size();
|
||||||
|
for (int i = 1; i < productSkuAddDTOs.size(); i++) {
|
||||||
|
if (attrSize != productSkuAddDTOs.get(i).getAttrs().size()) {
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_SPU_ATTR_NUMBERS_MUST_BE_EQUALS.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3. 最后校验,每个 Sku 之间不是重复的
|
||||||
|
Set<Set<Integer>> skuAttrValues = new HashSet<>(); // 每个元素,都是一个 Sku 的 attrValueId 集合。这样,通过最外层的 Set ,判断是否有重复的.
|
||||||
|
for (ProductSkuAddDTO sku : productSkuAddDTOs) {
|
||||||
|
if (!skuAttrValues.add(new HashSet<>(sku.getAttrs()))) { // 添加失败,说明重复
|
||||||
|
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_SPU_SKU__NOT_DUPLICATE.getCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 校验通过
|
||||||
|
return CommonResult.success(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="cn.iocoder.mall.product.dao.ProductAttrMapper">
|
||||||
|
|
||||||
|
<sql id="FIELDS">
|
||||||
|
id, name, status, create_time
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!--<select id="selectList" resultType="ProductCategoryDO">-->
|
||||||
|
<!--SELECT-->
|
||||||
|
<!--<include refid="FIELDS" />-->
|
||||||
|
<!--FROM product_category-->
|
||||||
|
<!--WHERE deleted = 0-->
|
||||||
|
<!--</select>-->
|
||||||
|
|
||||||
|
<select id="selectById" parameterType="Integer" resultType="ProductAttrDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS" />
|
||||||
|
FROM product_attr
|
||||||
|
WHERE id = #{id}
|
||||||
|
AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!--<insert id="insert" parameterType="ProductCategoryDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">-->
|
||||||
|
<!--INSERT INTO product_category (-->
|
||||||
|
<!--pid, name, description, pic_url, sort,-->
|
||||||
|
<!--status, create_time, deleted-->
|
||||||
|
<!--) VALUES (-->
|
||||||
|
<!--#{pid}, #{name}, #{description}, #{picUrl}, #{sort},-->
|
||||||
|
<!--#{status}, #{createTime}, #{deleted}-->
|
||||||
|
<!--)-->
|
||||||
|
<!--</insert>-->
|
||||||
|
|
||||||
|
<!--<update id="update" parameterType="ProductCategoryDO">-->
|
||||||
|
<!--UPDATE product_category-->
|
||||||
|
<!--<set>-->
|
||||||
|
<!--<if test="pid != null">-->
|
||||||
|
<!--pid = #{pid},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="name != null">-->
|
||||||
|
<!--name = #{name},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="description != null">-->
|
||||||
|
<!--description = #{description},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="picUrl != null">-->
|
||||||
|
<!--pic_url = #{picUrl},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="sort != null">-->
|
||||||
|
<!--sort = #{sort},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="status != null">-->
|
||||||
|
<!--status = #{status},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="deleted != null">-->
|
||||||
|
<!--deleted = #{deleted}-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--</set>-->
|
||||||
|
<!--WHERE id = #{id}-->
|
||||||
|
<!--</update>-->
|
||||||
|
|
||||||
|
<select id="selectListByIds" resultType="ProductAttrDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS" />
|
||||||
|
FROM product_attr
|
||||||
|
WHERE id IN
|
||||||
|
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="cn.iocoder.mall.product.dao.ProductAttrValueMapper">
|
||||||
|
|
||||||
|
<sql id="FIELDS">
|
||||||
|
id, attr_id, name, status, create_time
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!--<select id="selectList" resultType="ProductCategoryDO">-->
|
||||||
|
<!--SELECT-->
|
||||||
|
<!--<include refid="FIELDS" />-->
|
||||||
|
<!--FROM product_category-->
|
||||||
|
<!--WHERE deleted = 0-->
|
||||||
|
<!--</select>-->
|
||||||
|
|
||||||
|
<select id="selectById" parameterType="Integer" resultType="ProductAttrValueDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS" />
|
||||||
|
FROM product_attr_value
|
||||||
|
WHERE id = #{id}
|
||||||
|
AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!--<insert id="insert" parameterType="ProductCategoryDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">-->
|
||||||
|
<!--INSERT INTO product_category (-->
|
||||||
|
<!--pid, name, description, pic_url, sort,-->
|
||||||
|
<!--status, create_time, deleted-->
|
||||||
|
<!--) VALUES (-->
|
||||||
|
<!--#{pid}, #{name}, #{description}, #{picUrl}, #{sort},-->
|
||||||
|
<!--#{status}, #{createTime}, #{deleted}-->
|
||||||
|
<!--)-->
|
||||||
|
<!--</insert>-->
|
||||||
|
|
||||||
|
<!--<update id="update" parameterType="ProductCategoryDO">-->
|
||||||
|
<!--UPDATE product_category-->
|
||||||
|
<!--<set>-->
|
||||||
|
<!--<if test="pid != null">-->
|
||||||
|
<!--pid = #{pid},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="name != null">-->
|
||||||
|
<!--name = #{name},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="description != null">-->
|
||||||
|
<!--description = #{description},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="picUrl != null">-->
|
||||||
|
<!--pic_url = #{picUrl},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="sort != null">-->
|
||||||
|
<!--sort = #{sort},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="status != null">-->
|
||||||
|
<!--status = #{status},-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--<if test="deleted != null">-->
|
||||||
|
<!--deleted = #{deleted}-->
|
||||||
|
<!--</if>-->
|
||||||
|
<!--</set>-->
|
||||||
|
<!--WHERE id = #{id}-->
|
||||||
|
<!--</update>-->
|
||||||
|
|
||||||
|
<select id="selectListByIds" resultType="ProductAttrValueDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS" />
|
||||||
|
FROM product_attr_value
|
||||||
|
WHERE id IN
|
||||||
|
<foreach item="id" collection="ids" separator="," open="(" close=")" index="">
|
||||||
|
#{id}
|
||||||
|
</foreach>
|
||||||
|
AND deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
|
@ -1,12 +1,24 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="cn.iocoder.mall.product.dao.ProductSpuMapper">
|
<mapper namespace="cn.iocoder.mall.product.dao.ProductSkuMapper">
|
||||||
|
|
||||||
<select id="selectById" parameterType="Integer" resultType="ProductSpuDO">
|
<select id="selectById" parameterType="Integer" resultType="ProductSkuDO">
|
||||||
SELECT
|
SELECT
|
||||||
id
|
id
|
||||||
FROM product_spu
|
FROM product_sku
|
||||||
WHERE id = #{id}
|
WHERE id = #{id}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<insert id="insertList" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
||||||
|
INSERT INTO product_sku (
|
||||||
|
spu_id, status, pic_url, attrs, price,
|
||||||
|
quantity, deleted, create_time
|
||||||
|
) VALUES
|
||||||
|
<foreach collection="productSkuDOs" item="productSkuDO" separator=",">
|
||||||
|
(#{productSkuDO.spuId}, #{productSkuDO.status}, #{productSkuDO.picUrl}, #{productSkuDO.attrs}, #{productSkuDO.price},
|
||||||
|
#{productSkuDO.quantity}, #{productSkuDO.deleted}, #{productSkuDO.createTime}
|
||||||
|
)
|
||||||
|
</foreach>
|
||||||
|
</insert>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="cn.iocoder.mall.product.dao.ProductSpuMapper">
|
||||||
|
|
||||||
|
<select id="selectById" parameterType="Integer" resultType="ProductSpuDO">
|
||||||
|
SELECT
|
||||||
|
id
|
||||||
|
FROM product_spu
|
||||||
|
WHERE id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insert" parameterType="ProductSpuDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
||||||
|
INSERT INTO product_spu (
|
||||||
|
name, sell_point, description, cid, pic_urls,
|
||||||
|
visible, sort, deleted, create_time
|
||||||
|
) VALUES (
|
||||||
|
#{name}, #{sellPoint}, #{description}, #{cid}, #{picUrls},
|
||||||
|
#{visible}, #{sort}, #{deleted}, #{createTime}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="update">
|
||||||
|
|
||||||
|
</update>
|
||||||
|
|
||||||
|
</mapper>
|
Loading…
Reference in New Issue