增加 user 端的商品分类接口

增加 user 端的商品 spu 接口
pull/1/head
YunaiV 2019-03-07 19:36:59 +08:00
parent 335c19e62d
commit 03f6b2b82c
27 changed files with 767 additions and 73 deletions

View File

@ -6,15 +6,18 @@ import cn.iocoder.mall.product.api.ProductAttrService;
import cn.iocoder.mall.product.api.bo.ProductAttrBO; import cn.iocoder.mall.product.api.bo.ProductAttrBO;
import cn.iocoder.mall.product.api.bo.ProductAttrPageBO; import cn.iocoder.mall.product.api.bo.ProductAttrPageBO;
import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO; import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO;
import cn.iocoder.mall.product.api.dto.ProductAttrAddDTO; import cn.iocoder.mall.product.api.bo.ProductAttrValueBO;
import cn.iocoder.mall.product.api.dto.ProductAttrPageDTO; import cn.iocoder.mall.product.api.dto.*;
import cn.iocoder.mall.product.api.dto.ProductAttrUpdateDTO;
import cn.iocoder.mall.product.application.convert.ProductAttrConvert; import cn.iocoder.mall.product.application.convert.ProductAttrConvert;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrPageVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrPageVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrSimpleVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrSimpleVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrValueVO;
import com.alibaba.dubbo.config.annotation.Reference; import com.alibaba.dubbo.config.annotation.Reference;
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 org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@ -28,6 +31,7 @@ public class AdminsProductAttrController {
private ProductAttrService productAttrService; private ProductAttrService productAttrService;
@GetMapping("/attr/page") @GetMapping("/attr/page")
@ApiOperation("获得规格分页")
public CommonResult<AdminsProductAttrPageVO> attrPage(@RequestParam(value = "name", required = false) String name, public CommonResult<AdminsProductAttrPageVO> attrPage(@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo, @RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) { @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
@ -40,6 +44,7 @@ public class AdminsProductAttrController {
} }
@GetMapping("/attr/tree") @GetMapping("/attr/tree")
@ApiOperation(value = "获得规格树结构", notes = "该接口返回的信息更为精简。一般用于前端缓存数据字典到本地。")
public CommonResult<List<AdminsProductAttrSimpleVO>> tree() { public CommonResult<List<AdminsProductAttrSimpleVO>> tree() {
// 查询全列表 // 查询全列表
CommonResult<List<ProductAttrSimpleBO>> result = productAttrService.getProductAttrList(); CommonResult<List<ProductAttrSimpleBO>> result = productAttrService.getProductAttrList();
@ -48,6 +53,10 @@ public class AdminsProductAttrController {
} }
@PostMapping("/attr/add") @PostMapping("/attr/add")
@ApiOperation(value = "创建商品规格")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "规格名", required = true, example = "颜色")
})
public CommonResult<AdminsProductAttrVO> addAttr(@RequestParam("name") String name) { public CommonResult<AdminsProductAttrVO> addAttr(@RequestParam("name") String name) {
// 创建 ProductAttrAddDTO 对象 // 创建 ProductAttrAddDTO 对象
ProductAttrAddDTO productAttrAddDTO = new ProductAttrAddDTO().setName(name); ProductAttrAddDTO productAttrAddDTO = new ProductAttrAddDTO().setName(name);
@ -58,6 +67,11 @@ public class AdminsProductAttrController {
} }
@PostMapping("/attr/update") @PostMapping("/attr/update")
@ApiOperation(value = "修改商品规格")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "规格编号", required = true, example = "1"),
@ApiImplicitParam(name = "name", value = "规格名", required = true, example = "颜色")
})
public CommonResult<Boolean> updateAttr(@RequestParam("id") Integer id, public CommonResult<Boolean> updateAttr(@RequestParam("id") Integer id,
@RequestParam("name") String name) { @RequestParam("name") String name) {
// 创建 ProductAttrUpdateDTO 对象 // 创建 ProductAttrUpdateDTO 对象
@ -67,6 +81,11 @@ public class AdminsProductAttrController {
} }
@PostMapping("/attr/update_status") @PostMapping("/attr/update_status")
@ApiOperation(value = "修改商品规格状态")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "规格编号", required = true, example = "100"),
@ApiImplicitParam(name = "status", value = "状态", required = true, example = "1")
})
public CommonResult<Boolean> updateAttrStatus(@RequestParam("id") Integer id, public CommonResult<Boolean> updateAttrStatus(@RequestParam("id") Integer id,
@RequestParam("status") Integer status) { @RequestParam("status") Integer status) {
return productAttrService.updateProductAttrStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status); return productAttrService.updateProductAttrStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status);
@ -75,18 +94,43 @@ public class AdminsProductAttrController {
// TODO 芋艿 暂时不考虑 delete Attr 。因为关联逻辑比较多 // TODO 芋艿 暂时不考虑 delete Attr 。因为关联逻辑比较多
@PostMapping("/attr_value/add") @PostMapping("/attr_value/add")
public CommonResult addAttrValue() { @ApiOperation(value = "创建商品规格值")
return null; @ApiImplicitParams({
@ApiImplicitParam(name = "attrId", value = "规格编号", required = true, example = "100"),
@ApiImplicitParam(name = "name", value = "规格值", required = true, example = "蓝色")
})
public CommonResult<AdminsProductAttrValueVO> addAttrValue(@RequestParam("attrId") Integer attrId,
@RequestParam("name") String name) {
// 创建 ProductAttrValueAddDTO 对象
ProductAttrValueAddDTO productAttrValueAddDTO = new ProductAttrValueAddDTO().setAttrId(attrId).setName(name);
// 添加
CommonResult<ProductAttrValueBO> result = productAttrService.addProductAttrValue(AdminSecurityContextHolder.getContext().getAdminId(), productAttrValueAddDTO);
// 返回结果
return ProductAttrConvert.INSTANCE.convert4(result);
} }
@PostMapping("/attr_value/update") @PostMapping("/attr_value/update")
public CommonResult<Boolean> updateAttrValue() { @ApiOperation(value = "修改商品规格值")
return null; @ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "规格值编号", required = true, example = "100"),
@ApiImplicitParam(name = "name", value = "规格值", required = true, example = "蓝色")
})
public CommonResult<Boolean> updateAttrValue(@RequestParam("id") Integer id,
@RequestParam("name") String name) {
// 创建 ProductAttrValueUpdateDTO 对象
ProductAttrValueUpdateDTO productAttrValueUpdateDTO = new ProductAttrValueUpdateDTO().setId(id).setName(name);
// 更新
return productAttrService.updateProductAttrValue(AdminSecurityContextHolder.getContext().getAdminId(), productAttrValueUpdateDTO);
} }
@PostMapping("/attr_value/update_status") @PostMapping("/attr_value/update_status")
public CommonResult<Boolean> updateAttrValueStatus() { @ApiImplicitParams({
return null; @ApiImplicitParam(name = "id", value = "规格编号", required = true, example = "100"),
@ApiImplicitParam(name = "status", value = "状态", required = true, example = "1")
})
public CommonResult<Boolean> updateAttrValueStatus(@RequestParam("id") Integer id,
@RequestParam("status") Integer status) {
return productAttrService.updateProductAttrValueStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status);
} }
// TODO 芋艿 暂时不考虑 delete Attr Value 。因为关联逻辑比较多 // TODO 芋艿 暂时不考虑 delete Attr Value 。因为关联逻辑比较多

View File

@ -1,32 +0,0 @@
package cn.iocoder.mall.product.application.controller.users;
import cn.iocoder.mall.product.api.ProductSpuService;
import cn.iocoder.mall.product.api.bo.ProductSpuBO;
import cn.iocoder.mall.product.application.vo.ProductSpuListVO;
import com.alibaba.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("user/product/spu")
public class ProductSpuController {
@Reference(validation = "true")
private ProductSpuService productSpuService;
// TODO 详情
@GetMapping("/info")
public ProductSpuBO info(@RequestParam("id") Integer id) {
// return productSpuService.getProductSpu(id);
return null;
}
// TODO 分页
@GetMapping("/list")
public ProductSpuListVO list() {
return null;
}
}

View File

@ -18,7 +18,7 @@ import java.util.List;
@RestController("productCategoryController_users") @RestController("productCategoryController_users")
@RequestMapping("users/product/category") @RequestMapping("users/product/category")
@Api("商品分类") @Api("商品分类")
public class ProductCategoryController { public class UsersProductCategoryController {
@Reference(validation = "true") @Reference(validation = "true")
private ProductCategoryService productCategoryService; private ProductCategoryService productCategoryService;

View File

@ -0,0 +1,54 @@
package cn.iocoder.mall.product.application.controller.users;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.product.api.ProductSpuService;
import cn.iocoder.mall.product.api.bo.ProductSpuPageBO;
import cn.iocoder.mall.product.api.dto.ProductSpuPageDTO;
import cn.iocoder.mall.product.application.convert.ProductSpuConvert;
import cn.iocoder.mall.product.application.vo.users.UsersProductSpuDetailVO;
import cn.iocoder.mall.product.application.vo.users.UsersProductSpuPageVO;
import com.alibaba.dubbo.config.annotation.Reference;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("users/spu")
@Api("商品 SPU + SKU")
public class UsersProductSpuController {
@Reference(validation = "true")
private ProductSpuService productSpuService;
@GetMapping("/info")
@ApiOperation("商品 SPU 明细")
@ApiImplicitParam(name = "id", value = "SPU 编号", required = true, example = "100")
public CommonResult<UsersProductSpuDetailVO> info(@RequestParam("id") Integer id) {
return ProductSpuConvert.INSTANCE.convert4(productSpuService.getProductSpu(id));
}
@GetMapping("/page")
@ApiOperation("商品 SPU 分页列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "cid", value = "分类编号", example = "1"),
@ApiImplicitParam(name = "pageNo", value = "页码,从 0 开始", example = "0"),
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
})
public CommonResult<UsersProductSpuPageVO> page(@RequestParam(value = "cid", required = false) Integer cid,
@RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
// 创建 ProductSpuPageDTO 对象
ProductSpuPageDTO productSpuPageDTO = new ProductSpuPageDTO().setCid(cid).setVisible(true)
.setPageNo(pageNo).setPageSize(pageSize);
// 查询分页
CommonResult<ProductSpuPageBO> result = productSpuService.getProductSpuPage(productSpuPageDTO);
// 返回结果
return ProductSpuConvert.INSTANCE.convert3(result);
}
}

View File

@ -4,9 +4,11 @@ import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.product.api.bo.ProductAttrBO; import cn.iocoder.mall.product.api.bo.ProductAttrBO;
import cn.iocoder.mall.product.api.bo.ProductAttrPageBO; import cn.iocoder.mall.product.api.bo.ProductAttrPageBO;
import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO; import cn.iocoder.mall.product.api.bo.ProductAttrSimpleBO;
import cn.iocoder.mall.product.api.bo.ProductAttrValueBO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrPageVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrPageVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrSimpleVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrSimpleVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductAttrValueVO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -30,4 +32,7 @@ public interface ProductAttrConvert {
@Mappings({}) @Mappings({})
CommonResult<AdminsProductAttrVO> convert3(CommonResult<ProductAttrBO> productAttrBO); CommonResult<AdminsProductAttrVO> convert3(CommonResult<ProductAttrBO> productAttrBO);
@Mappings({})
CommonResult<AdminsProductAttrValueVO> convert4(CommonResult<ProductAttrValueBO> productAttrValueBO);
} }

View File

@ -5,6 +5,8 @@ import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO;
import cn.iocoder.mall.product.api.bo.ProductSpuPageBO; import cn.iocoder.mall.product.api.bo.ProductSpuPageBO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuDetailVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuDetailVO;
import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuPageVO; import cn.iocoder.mall.product.application.vo.admins.AdminsProductSpuPageVO;
import cn.iocoder.mall.product.application.vo.users.UsersProductSpuDetailVO;
import cn.iocoder.mall.product.application.vo.users.UsersProductSpuPageVO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
import org.mapstruct.Mappings; import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
@ -23,4 +25,10 @@ public interface ProductSpuConvert {
@Mappings({}) @Mappings({})
CommonResult<AdminsProductSpuPageVO> convert2(CommonResult<ProductSpuPageBO> result); CommonResult<AdminsProductSpuPageVO> convert2(CommonResult<ProductSpuPageBO> result);
@Mappings({})
CommonResult<UsersProductSpuPageVO> convert3(CommonResult<ProductSpuPageBO> result);
@Mappings({})
CommonResult<UsersProductSpuDetailVO> convert4(CommonResult<ProductSpuDetailBO> result);
} }

View File

@ -1,16 +0,0 @@
package cn.iocoder.mall.product.application.vo;
import java.util.List;
public class ProductSpuListVO {
/**
* SPU
*/
private List<ProductSpuVO> list;
/**
*
*/
private Boolean hasNext;
}

View File

@ -1,4 +0,0 @@
package cn.iocoder.mall.product.application.vo;
public class ProductSpuVO {
}

View File

@ -0,0 +1,67 @@
package cn.iocoder.mall.product.application.vo.admins;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.Date;
@ApiModel(value = "商品规格值 VO")
public class AdminsProductAttrValueVO {
@ApiModelProperty(value = "规格值编号", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "规格编号", required = true, example = "1")
private Integer attrId;
@ApiModelProperty(value = "规格名", required = true, example = "颜色")
private String name;
@ApiModelProperty(value = "状态", required = true, example = "1")
private Integer status;
@ApiModelProperty(value = "创建时间", required = true, example = "时间戳")
private Date createTime;
public Integer getId() {
return id;
}
public AdminsProductAttrValueVO setId(Integer id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public AdminsProductAttrValueVO setName(String name) {
this.name = name;
return this;
}
public Integer getStatus() {
return status;
}
public AdminsProductAttrValueVO setStatus(Integer status) {
this.status = status;
return this;
}
public Date getCreateTime() {
return createTime;
}
public AdminsProductAttrValueVO setCreateTime(Date createTime) {
this.createTime = createTime;
return this;
}
public Integer getAttrId() {
return attrId;
}
public AdminsProductAttrValueVO setAttrId(Integer attrId) {
this.attrId = attrId;
return this;
}
}

View File

@ -22,7 +22,6 @@ public class AdminsProductSkuDetailVO {
@ApiModelProperty(value = "库存数量", required = true, example = "100") @ApiModelProperty(value = "库存数量", required = true, example = "100")
private Integer quantity; private Integer quantity;
public Integer getId() { public Integer getId() {
return id; return id;
} }

View File

@ -0,0 +1,54 @@
package cn.iocoder.mall.product.application.vo.users;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel(value = "商品规格属性和值对 VO")
public class UsersProductAttrAndValuePairVO {
@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 UsersProductAttrAndValuePairVO setAttrId(Integer attrId) {
this.attrId = attrId;
return this;
}
public String getAttrName() {
return attrName;
}
public UsersProductAttrAndValuePairVO setAttrName(String attrName) {
this.attrName = attrName;
return this;
}
public Integer getAttrValueId() {
return attrValueId;
}
public UsersProductAttrAndValuePairVO setAttrValueId(Integer attrValueId) {
this.attrValueId = attrValueId;
return this;
}
public String getAttrValueName() {
return attrValueName;
}
public UsersProductAttrAndValuePairVO setAttrValueName(String attrValueName) {
this.attrValueName = attrValueName;
return this;
}
}

View File

@ -0,0 +1,79 @@
package cn.iocoder.mall.product.application.vo.users;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
* Sku BO
*/
public class UsersProductSkuDetailVO {
@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<UsersProductAttrAndValuePairVO> 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 UsersProductSkuDetailVO setId(Integer id) {
this.id = id;
return this;
}
public Integer getSpuId() {
return spuId;
}
public UsersProductSkuDetailVO setSpuId(Integer spuId) {
this.spuId = spuId;
return this;
}
public String getPicURL() {
return picURL;
}
public UsersProductSkuDetailVO setPicURL(String picURL) {
this.picURL = picURL;
return this;
}
public Integer getPrice() {
return price;
}
public UsersProductSkuDetailVO setPrice(Integer price) {
this.price = price;
return this;
}
public Integer getQuantity() {
return quantity;
}
public UsersProductSkuDetailVO setQuantity(Integer quantity) {
this.quantity = quantity;
return this;
}
public List<UsersProductAttrAndValuePairVO> getAttrs() {
return attrs;
}
public UsersProductSkuDetailVO setAttrs(List<UsersProductAttrAndValuePairVO> attrs) {
this.attrs = attrs;
return this;
}
}

View File

@ -0,0 +1,95 @@
package cn.iocoder.mall.product.application.vo.users;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
@ApiModel(value = "商品 SPU 详细 VO", description = "包括 SKU 信息 VO")
public class UsersProductSpuDetailVO {
@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;
// ========== SKU =========
/**
* SKU
*/
private List<UsersProductSkuDetailVO> skus;
public Integer getId() {
return id;
}
public UsersProductSpuDetailVO setId(Integer id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public UsersProductSpuDetailVO setName(String name) {
this.name = name;
return this;
}
public String getSellPoint() {
return sellPoint;
}
public UsersProductSpuDetailVO setSellPoint(String sellPoint) {
this.sellPoint = sellPoint;
return this;
}
public String getDescription() {
return description;
}
public UsersProductSpuDetailVO setDescription(String description) {
this.description = description;
return this;
}
public Integer getCid() {
return cid;
}
public UsersProductSpuDetailVO setCid(Integer cid) {
this.cid = cid;
return this;
}
public List<String> getPicUrls() {
return picUrls;
}
public UsersProductSpuDetailVO setPicUrls(List<String> picUrls) {
this.picUrls = picUrls;
return this;
}
public List<UsersProductSkuDetailVO> getSkus() {
return skus;
}
public UsersProductSpuDetailVO setSkus(List<UsersProductSkuDetailVO> skus) {
this.skus = skus;
return this;
}
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.mall.product.application.vo.users;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
@ApiModel("商品 SPU 分页 VO")
public class UsersProductSpuPageVO {
@ApiModelProperty(value = "spu 数组", required = true)
private List<UsersProductSpuVO> spus;
@ApiModelProperty(value = "总数", required = true)
private Integer count;
public List<UsersProductSpuVO> getSpus() {
return spus;
}
public UsersProductSpuPageVO setSpus(List<UsersProductSpuVO> spus) {
this.spus = spus;
return this;
}
public Integer getCount() {
return count;
}
public UsersProductSpuPageVO setCount(Integer count) {
this.count = count;
return this;
}
}

View File

@ -0,0 +1,85 @@
package cn.iocoder.mall.product.application.vo.users;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
@ApiModel(value = "商品 SPU VO", description = "不包括 SKU 信息 VO")
public class UsersProductSpuVO {
@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 Integer cid;
@ApiModelProperty(value = "商品主图地址的数组", required = true, example = "http://www.iocoder.cn")
private List<String> picUrls;
// ========== Sku 相关字段 =========
/**
*
*
* Sku
*/
private Integer price;
public Integer getId() {
return id;
}
public UsersProductSpuVO setId(Integer id) {
this.id = id;
return this;
}
public String getName() {
return name;
}
public UsersProductSpuVO setName(String name) {
this.name = name;
return this;
}
public String getSellPoint() {
return sellPoint;
}
public UsersProductSpuVO setSellPoint(String sellPoint) {
this.sellPoint = sellPoint;
return this;
}
public Integer getCid() {
return cid;
}
public UsersProductSpuVO setCid(Integer cid) {
this.cid = cid;
return this;
}
public List<String> getPicUrls() {
return picUrls;
}
public UsersProductSpuVO setPicUrls(List<String> picUrls) {
this.picUrls = picUrls;
return this;
}
public Integer getPrice() {
return price;
}
public UsersProductSpuVO setPrice(Integer price) {
this.price = price;
return this;
}
}

View File

@ -11,6 +11,10 @@ public class ProductAttrValueBO {
* *
*/ */
private Integer id; private Integer id;
/**
*
*/
private Integer attrId;
/** /**
* *
*/ */
@ -59,4 +63,13 @@ public class ProductAttrValueBO {
this.createTime = createTime; this.createTime = createTime;
return this; return this;
} }
public Integer getAttrId() {
return attrId;
}
public ProductAttrValueBO setAttrId(Integer attrId) {
this.attrId = attrId;
return this;
}
} }

View File

@ -48,6 +48,14 @@ public class ProductSpuBO {
*/ */
private Integer sort; private Integer sort;
// ========== Sku 相关字段 =========
/**
*
*
* Sku
*/
private Integer price;
public Integer getId() { public Integer getId() {
return id; return id;
} }
@ -120,4 +128,13 @@ public class ProductSpuBO {
return this; return this;
} }
public Integer getPrice() {
return price;
}
public ProductSpuBO setPrice(Integer price) {
this.price = price;
return this;
}
} }

View File

@ -26,7 +26,8 @@ public enum ProductErrorCodeEnum {
PRODUCT_ATTR_NOT_EXIST(1003003001, "商品属性值不存在"), PRODUCT_ATTR_NOT_EXIST(1003003001, "商品属性值不存在"),
PRODUCT_ATTR_EXISTS(1003003002, "商品规格已经存在"), PRODUCT_ATTR_EXISTS(1003003002, "商品规格已经存在"),
PRODUCT_ATTR_STATUS_EQUALS(1003003003, "商品规格已经是该状态"), PRODUCT_ATTR_STATUS_EQUALS(1003003003, "商品规格已经是该状态"),
PRODUCT_ATTR_VALUE_EXISTS(1003003004, "商品规格值已经存在"),
PRODUCT_ATTR_VALUE_STATUS_EQUALS(1003003005, "商品规格值已经是该状态"),
; ;
private final int code; private final int code;

View File

@ -7,7 +7,20 @@ import javax.validation.constraints.NotNull;
*/ */
public class ProductSpuPageDTO { public class ProductSpuPageDTO {
/**
*
*
*
*/
private String name; private String name;
/**
*
*/
private Integer cid;
/**
*
*/
private Boolean visible;
@NotNull(message = "页码不能为空") @NotNull(message = "页码不能为空")
private Integer pageNo; private Integer pageNo;
@ -41,4 +54,22 @@ public class ProductSpuPageDTO {
return this; return this;
} }
public Integer getCid() {
return cid;
}
public ProductSpuPageDTO setCid(Integer cid) {
this.cid = cid;
return this;
}
public Boolean getVisible() {
return visible;
}
public ProductSpuPageDTO setVisible(Boolean visible) {
this.visible = visible;
return this;
}
} }

View File

@ -3,6 +3,8 @@ package cn.iocoder.mall.product.convert;
import cn.iocoder.mall.product.api.bo.*; import cn.iocoder.mall.product.api.bo.*;
import cn.iocoder.mall.product.api.dto.ProductAttrAddDTO; import cn.iocoder.mall.product.api.dto.ProductAttrAddDTO;
import cn.iocoder.mall.product.api.dto.ProductAttrUpdateDTO; import cn.iocoder.mall.product.api.dto.ProductAttrUpdateDTO;
import cn.iocoder.mall.product.api.dto.ProductAttrValueAddDTO;
import cn.iocoder.mall.product.api.dto.ProductAttrValueUpdateDTO;
import cn.iocoder.mall.product.dataobject.ProductAttrDO; import cn.iocoder.mall.product.dataobject.ProductAttrDO;
import cn.iocoder.mall.product.dataobject.ProductAttrValueDO; import cn.iocoder.mall.product.dataobject.ProductAttrValueDO;
import org.mapstruct.Mapper; import org.mapstruct.Mapper;
@ -40,10 +42,17 @@ public interface ProductAttrConvert {
@Mappings({}) @Mappings({})
ProductAttrDO convert(ProductAttrUpdateDTO productAttrUpdateDTO); ProductAttrDO convert(ProductAttrUpdateDTO productAttrUpdateDTO);
@Mappings({})
ProductAttrValueDO convert(ProductAttrValueAddDTO productAttrValueAddDTO);
@Mappings({})
ProductAttrValueDO convert(ProductAttrValueUpdateDTO productAttrValueUpdateDTO);
@Mappings({}) @Mappings({})
ProductAttrBO convert(ProductAttrDO productAttrDO); ProductAttrBO convert(ProductAttrDO productAttrDO);
@Mappings({}) @Mappings({})
ProductAttrValueBO convert2(ProductAttrValueDO productAttrValueDO); ProductAttrValueBO convert2(ProductAttrValueDO productAttrValueDO);
} }

View File

@ -18,4 +18,12 @@ public interface ProductAttrValueMapper {
List<ProductAttrValueDO> selectListByAttrIds(@Param("attrIds") Collection<Integer> attrIds); List<ProductAttrValueDO> selectListByAttrIds(@Param("attrIds") Collection<Integer> attrIds);
ProductAttrValueDO selectByAttrIdAndName(@Param("attrId") Integer attrId,
@Param("name") String name);
void insert(ProductAttrValueDO productAttrValueDO);
void update(ProductAttrValueDO productAttrValueDO);
} }

View File

@ -15,10 +15,15 @@ public interface ProductSpuMapper {
void update(ProductSpuDO productSpuDO); void update(ProductSpuDO productSpuDO);
// TODO 芋艿,需要捉摸下,怎么优化下。参数有点多
List<ProductSpuDO> selectListByNameLikeOrderBySortAsc(@Param("name") String name, List<ProductSpuDO> selectListByNameLikeOrderBySortAsc(@Param("name") String name,
@Param("cid") Integer cid,
@Param("visible") Boolean visible,
@Param("offset") Integer offset, @Param("offset") Integer offset,
@Param("limit") Integer limit); @Param("limit") Integer limit);
Integer selectCountByNameLike(@Param("name") String name); Integer selectCountByNameLike(@Param("name") String name,
@Param("cid") Integer cid,
@Param("visible") Boolean visible);
} }

View File

@ -57,6 +57,20 @@ public class ProductSpuDO extends BaseDO {
*/ */
private Integer sort; private Integer sort;
// ========== Sku 相关字段 =========
/**
*
*
* Sku
*/
private Integer price;
/**
*
*
* Sku
*/
private Integer quantity;
public Integer getId() { public Integer getId() {
return id; return id;
} }
@ -128,4 +142,23 @@ public class ProductSpuDO extends BaseDO {
this.sort = sort; this.sort = sort;
return this; return this;
} }
public Integer getPrice() {
return price;
}
public ProductSpuDO setPrice(Integer price) {
this.price = price;
return this;
}
public Integer getQuantity() {
return quantity;
}
public ProductSpuDO setQuantity(Integer quantity) {
this.quantity = quantity;
return this;
}
} }

View File

@ -167,17 +167,58 @@ public class ProductAttrServiceImpl implements ProductAttrService {
@Override @Override
public CommonResult<ProductAttrValueBO> addProductAttrValue(Integer adminId, ProductAttrValueAddDTO productAttrValueAddDTO) { public CommonResult<ProductAttrValueBO> addProductAttrValue(Integer adminId, ProductAttrValueAddDTO productAttrValueAddDTO) {
return null; // 校验规格名不重复
if (productAttrValueMapper.selectByAttrIdAndName(productAttrValueAddDTO.getAttrId(), productAttrValueAddDTO.getName()) != null) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_VALUE_EXISTS.getCode());
}
// 插入到数据库
ProductAttrValueDO productAttrValueDO = ProductAttrConvert.INSTANCE.convert(productAttrValueAddDTO)
.setStatus(ProductAttrConstants.ATTR_VALUE_STATUS_ENABLE);
productAttrValueDO.setCreateTime(new Date()).setDeleted(BaseDO.DELETED_NO);
productAttrValueMapper.insert(productAttrValueDO);
// 返回成功
return CommonResult.success(ProductAttrConvert.INSTANCE.convert2(productAttrValueDO));
} }
@Override @Override
public CommonResult<Boolean> updateProductAttrValue(Integer adminId, ProductAttrValueUpdateDTO productAttrValueUpdateDTO) { public CommonResult<Boolean> updateProductAttrValue(Integer adminId, ProductAttrValueUpdateDTO productAttrValueUpdateDTO) {
return null; // 校验存在
ProductAttrValueDO productAttrValueDO = productAttrValueMapper.selectById(productAttrValueUpdateDTO.getId());
if (productAttrValueDO == null) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_VALUE_NOT_EXIST.getCode());
}
// 校验规格名不重复
ProductAttrValueDO existsAttrDO = productAttrValueMapper.selectByAttrIdAndName(productAttrValueDO.getAttrId(), productAttrValueUpdateDTO.getName());
if (existsAttrDO != null && !existsAttrDO.getId().equals(productAttrValueUpdateDTO.getId())) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_VALUE_EXISTS.getCode());
}
// 更新到数据库
ProductAttrValueDO updateProductValue = ProductAttrConvert.INSTANCE.convert(productAttrValueUpdateDTO);
productAttrValueMapper.update(updateProductValue);
// 返回成功
return CommonResult.success(true);
} }
@Override @Override
public CommonResult<Boolean> updateProductAttrValueStatus(Integer adminId, Integer productAttrValueId, Integer status) { public CommonResult<Boolean> updateProductAttrValueStatus(Integer adminId, Integer productAttrValueId, Integer status) {
return null; // 校验参数
if (!isValidAttrValueStatus(status)) {
return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "变更状态必须是开启1或关闭2"); // TODO 有点搓
}
// 校验存在
ProductAttrValueDO productAttrValueDO = productAttrValueMapper.selectById(productAttrValueId);
if (productAttrValueDO == null) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_VALUE_NOT_EXIST.getCode());
}
// 校验状态
if (productAttrValueDO.getStatus().equals(status)) {
return ServiceExceptionUtil.error(ProductErrorCodeEnum.PRODUCT_ATTR_VALUE_STATUS_EQUALS.getCode());
}
// 更新到数据库
ProductAttrValueDO updateProductAttrValue = new ProductAttrValueDO().setId(productAttrValueId).setStatus(status);
productAttrValueMapper.update(updateProductAttrValue);
// 返回成功
return CommonResult.success(true);
} }
private boolean isValidAttrStatus(Integer status) { private boolean isValidAttrStatus(Integer status) {

View File

@ -92,6 +92,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
.setPicUrls(StringUtil.join(productSpuAddDTO.getPicUrls(), ",")) .setPicUrls(StringUtil.join(productSpuAddDTO.getPicUrls(), ","))
.setSort(0); // 排序为 0 .setSort(0); // 排序为 0
spu.setCreateTime(new Date()).setDeleted(BaseDO.DELETED_NO); spu.setCreateTime(new Date()).setDeleted(BaseDO.DELETED_NO);
initSpuFromSkus(spu, productSpuAddDTO.getSkus()); // 初始化 sku 相关信息到 spu 中
productSpuMapper.insert(spu); productSpuMapper.insert(spu);
// 保存 Sku // 保存 Sku
List<ProductSkuDO> skus = productSpuAddDTO.getSkus().stream().map(productSkuAddDTO -> { List<ProductSkuDO> skus = productSpuAddDTO.getSkus().stream().map(productSkuAddDTO -> {
@ -141,6 +142,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
// 更新 Spu // 更新 Spu
ProductSpuDO updateSpu = ProductSpuConvert.INSTANCE.convert(productSpuUpdateDTO) ProductSpuDO updateSpu = ProductSpuConvert.INSTANCE.convert(productSpuUpdateDTO)
.setPicUrls(StringUtil.join(productSpuUpdateDTO.getPicUrls(), ",")); .setPicUrls(StringUtil.join(productSpuUpdateDTO.getPicUrls(), ","));
initSpuFromSkus(updateSpu, productSpuUpdateDTO.getSkus()); // 初始化 sku 相关信息到 spu 中
productSpuMapper.update(updateSpu); productSpuMapper.update(updateSpu);
// 修改 Sku // 修改 Sku
List<ProductSkuDO> existsSkus = productSkuMapper.selectListBySpuIdAndStatus(productSpuUpdateDTO.getId(), ProductSpuConstants.SKU_STATUS_ENABLE); List<ProductSkuDO> existsSkus = productSkuMapper.selectListBySpuIdAndStatus(productSpuUpdateDTO.getId(), ProductSpuConstants.SKU_STATUS_ENABLE);
@ -198,10 +200,11 @@ public class ProductSpuServiceImpl implements ProductSpuService {
ProductSpuPageBO productSpuPage = new ProductSpuPageBO(); ProductSpuPageBO productSpuPage = new ProductSpuPageBO();
// 查询分页数据 // 查询分页数据
int offset = productSpuPageDTO.getPageNo() * productSpuPageDTO.getPageSize(); int offset = productSpuPageDTO.getPageNo() * productSpuPageDTO.getPageSize();
productSpuPage.setSpus(ProductSpuConvert.INSTANCE.convert(productSpuMapper.selectListByNameLikeOrderBySortAsc(productSpuPageDTO.getName(), productSpuPage.setSpus(ProductSpuConvert.INSTANCE.convert(productSpuMapper.selectListByNameLikeOrderBySortAsc(
productSpuPageDTO.getName(), productSpuPageDTO.getCid(), productSpuPageDTO.getVisible(),
offset, productSpuPageDTO.getPageSize()))); offset, productSpuPageDTO.getPageSize())));
// 查询分页总数 // 查询分页总数
productSpuPage.setCount(productSpuMapper.selectCountByNameLike(productSpuPageDTO.getName())); productSpuPage.setCount(productSpuMapper.selectCountByNameLike(productSpuPageDTO.getName(), productSpuPageDTO.getCid(), productSpuPageDTO.getVisible()));
// 返回结果 // 返回结果
return CommonResult.success(productSpuPage); return CommonResult.success(productSpuPage);
} }
@ -250,4 +253,10 @@ public class ProductSpuServiceImpl implements ProductSpuService {
return null; return null;
} }
private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuAddOrUpdateDTO> skus) {
assert skus.size() > 0; // 写个断言,避免下面警告
spu.setPrice(skus.stream().min(Comparator.comparing(ProductSkuAddOrUpdateDTO::getPrice)).get().getPrice()); // 求最小价格
spu.setQuantity(skus.stream().mapToInt(ProductSkuAddOrUpdateDTO::getQuantity).sum()); // 求库存之和
}
} }

View File

@ -93,4 +93,38 @@
</where> </where>
</select> </select>
<select id="selectByAttrIdAndName" resultType="ProductAttrValueDO">
SELECT
<include refid="FIELDS" />
FROM product_attr_value
WHERE name = #{name}
AND deleted = 0
LIMIT 1
</select>
<insert id="insert" parameterType="ProductAttrValueDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO product_attr_value (
attr_id, name, status, create_time, deleted
) VALUES (
#{attrId}, #{name}, #{status}, #{createTime}, #{deleted}
)
</insert>
<update id="update" parameterType="ProductAttrValueDO">
UPDATE product_attr_value
<set>
<if test="name != null">
name = #{name},
</if>
<if test="status != null">
status = #{status},
</if>
<if test="deleted != null">
deleted = #{deleted}
</if>
</set>
WHERE id = #{id}
</update>
</mapper> </mapper>

View File

@ -4,7 +4,8 @@
<sql id="FIELDS"> <sql id="FIELDS">
id, name, sell_point, description, cid, id, name, sell_point, description, cid,
pic_urls, visible, sort, create_time pic_urls, visible, sort, price, quantity,
create_time
</sql> </sql>
<select id="selectById" parameterType="Integer" resultType="ProductSpuDO"> <select id="selectById" parameterType="Integer" resultType="ProductSpuDO">
@ -18,10 +19,12 @@
<insert id="insert" parameterType="ProductSpuDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id"> <insert id="insert" parameterType="ProductSpuDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO product_spu ( INSERT INTO product_spu (
name, sell_point, description, cid, pic_urls, name, sell_point, description, cid, pic_urls,
visible, sort, deleted, create_time visible, sort, price, quantity,
deleted, create_time
) VALUES ( ) VALUES (
#{name}, #{sellPoint}, #{description}, #{cid}, #{picUrls}, #{name}, #{sellPoint}, #{description}, #{cid}, #{picUrls},
#{visible}, #{sort}, #{deleted}, #{createTime} #{visible}, #{sort}, #{price}, #{quantity},
#{deleted}, #{createTime}
) )
</insert> </insert>
@ -46,6 +49,12 @@
<if test="visible != null"> <if test="visible != null">
visible = #{visible}, visible = #{visible},
</if> </if>
<if test="price != null">
price = #{price},
</if>
<if test="quantity != null">
quantity = #{quantity},
</if>
<if test="sort != null"> <if test="sort != null">
sort = #{sort}, sort = #{sort},
</if> </if>
@ -64,6 +73,12 @@
<if test="name != null"> <if test="name != null">
name LIKE "%"#{name}"%" name LIKE "%"#{name}"%"
</if> </if>
<if test="cid != null">
AND cid = #{cid}
</if>
<if test="visible != null">
AND visible = #{visible}
</if>
AND deleted = 0 AND deleted = 0
</where> </where>
ORDER BY sort ASC ORDER BY sort ASC
@ -78,6 +93,12 @@
<if test="name != null"> <if test="name != null">
name LIKE "%"#{name}"%" name LIKE "%"#{name}"%"
</if> </if>
<if test="cid != null">
AND cid = #{cid}
</if>
<if test="visible != null">
AND visible = #{visible}
</if>
AND deleted = 0 AND deleted = 0
</where> </where>
</select> </select>