Browse Source

调整库存、商品属性和规格的逻辑。

cangku
delicacylee 3 years ago
parent
commit
dd28f0845d
No known key found for this signature in database GPG Key ID: 40CBD364B612268F
  1. 33
      hiver-core/src/main/java/cc/hiver/core/base/HiverBasePageQuery.java
  2. 10
      hiver-core/src/main/java/cc/hiver/core/common/constant/MallConstant.java
  3. 10
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AddressController.java
  4. 42
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/GoodsAttributeController.java
  5. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/GoodsCategoryController.java
  6. 61
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/GoodsController.java
  7. 78
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/GoodsStockController.java
  8. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsAttributeDao.java
  9. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsCategoryAttributeDao.java
  10. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsCategoryBrandDao.java
  11. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsDao.java
  12. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsStockDao.java
  13. 27
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsAttributeMapper.java
  14. 27
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsCategoryAttributeMapper.java
  15. 27
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsCategoryBrandMapper.java
  16. 40
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsMapper.java
  17. 35
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsStockMapper.java
  18. 66
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/dto/CheckPriceDTO.java
  19. 58
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/dto/GoodsStockDto.java
  20. 57
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/dto/LockStockDTO.java
  21. 54
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/form/GoodsCategoryAttributeForm.java
  22. 82
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/form/GoodsForm.java
  23. 40
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/GoodsPageQuery.java
  24. 84
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/GoodsDetailVO.java
  25. 89
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/GoodsPageVO.java
  26. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsAttributeService.java
  27. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsCategoryAttributeService.java
  28. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsCategoryBrandService.java
  29. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsService.java
  30. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsStockService.java
  31. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsAttributeService.java
  32. 9
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsCategoryAttributeService.java
  33. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsCategoryBrandService.java
  34. 69
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsService.java
  35. 66
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsStockService.java
  36. 23
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsAttributeServiceImpl.java
  37. 23
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsCategoryAttributeServiceImpl.java
  38. 23
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsCategoryBrandServiceImpl.java
  39. 23
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsServiceImpl.java
  40. 23
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsStockServiceImpl.java
  41. 11
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsAttributeServiceImpl.java
  42. 60
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsCategoryAttributeServiceImpl.java
  43. 11
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsCategoryBrandServiceImpl.java
  44. 64
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsServiceImpl.java
  45. 197
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsStockServiceImpl.java
  46. 66
      hiver-modules/hiver-mall/src/main/resources/mapper/GoodsMapper.xml
  47. 33
      hiver-modules/hiver-mall/src/main/resources/mapper/GoodsStockMapper.xml

33
hiver-core/src/main/java/cc/hiver/core/base/HiverBasePageQuery.java

@ -0,0 +1,33 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.core.base;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author Yazhi Li
*/
@Data
@ApiModel
public class HiverBasePageQuery {
@ApiModelProperty(value = "页码", example = "1")
private int pageNum = 1;
@ApiModelProperty(value = "每页记录数", example = "10")
private int pageSize = 10;
}

10
hiver-core/src/main/java/cc/hiver/core/common/constant/MallConstant.java

@ -25,4 +25,14 @@ public interface MallConstant {
* 销售单临时保存
*/
Integer SALES_ORDER_SAVED = 1;
/**
* 订单锁定的商品列表key前缀
*/
String ORDER_LOCKED_SKUS_PREFIX = "order:locked:goods:";
/**
* 商品分布式锁key前缀
*/
String SKU_LOCK_PREFIX = "product:stock:lock:";
}

10
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/AddressController.java

@ -41,20 +41,22 @@ public class AddressController {
@ApiOperation(value = "保存数据")
public Result addAddress(Address entity) {
boolean result = addressService.addAddress(entity);
if(result)
if(result) {
return ResultUtil.success("添加成功");
else
} else {
return ResultUtil.error("添加失败");
}
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
@ApiOperation(value = "更新数据")
public Result updateAddress(Address entity) {
boolean result = addressService.updateAddress(entity);
if(result)
if(result) {
return ResultUtil.success("更新成功");
else
} else {
return ResultUtil.error("更新失败");
}
}
@RequestMapping(value = "/delByIds", method = RequestMethod.POST)

42
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/GoodsAttributeController.java

@ -15,16 +15,24 @@ limitations under the License.
*/
package cc.hiver.mall.controller;
import cc.hiver.mall.service.GoodsAttributeService;
import cc.hiver.mall.service.GoodsCategoryAttributeService;
import cc.hiver.mall.service.GoodsCategoryBrandService;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.mall.entity.GoodsCategoryAttribute;
import cc.hiver.mall.pojo.form.GoodsCategoryAttributeForm;
import cc.hiver.mall.service.mybatis.GoodsCategoryAttributeService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author Yazhi Li
*/
@ -34,12 +42,30 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping(value = "/hiver/app/attribute/")
@Transactional
public class GoodsAttributeController {
@Autowired
private GoodsAttributeService goodsAttributeService;
@Autowired
private GoodsCategoryAttributeService goodsCategoryAttributeService;
@Autowired
private GoodsCategoryBrandService goodsCategoryBrandService;
@RequestMapping(value = "/list", method = RequestMethod.GET)
@ApiOperation(value = "属性列表")
public Result<List<GoodsCategoryAttribute>> listAttributes(
@ApiParam("商品分类ID") Long categoryId,
@ApiParam("类型(1:规格;2:属性)") Integer type
) {
List<GoodsCategoryAttribute> list = goodsCategoryAttributeService.list(new LambdaQueryWrapper<GoodsCategoryAttribute>()
.eq(categoryId != null, GoodsCategoryAttribute::getCategoryId, categoryId)
.eq(type != null, GoodsCategoryAttribute::getType, type)
);
return new ResultUtil<List<GoodsCategoryAttribute>>().setData(list);
}
@RequestMapping(value = "/batch", method = RequestMethod.POST)
@ApiOperation(value = "批量新增/修改")
public Result saveBatch(GoodsCategoryAttributeForm goodsCategoryAttributeForm) {
boolean result = goodsCategoryAttributeService.saveBatch(goodsCategoryAttributeForm);
if(result) {
return ResultUtil.success("批量处理成功");
} else {
return ResultUtil.error("批量处理失败");
}
}
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/GoodsCategoryController.java

@ -4,8 +4,11 @@ import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.core.vo.Option;
import cc.hiver.mall.entity.GoodsCategory;
import cc.hiver.mall.entity.GoodsCategoryAttribute;
import cc.hiver.mall.pojo.vo.GoodsCategoryVO;
import cc.hiver.mall.service.mybatis.GoodsCategoryAttributeService;
import cc.hiver.mall.service.mybatis.GoodsCategoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@ -26,6 +29,9 @@ public class GoodsCategoryController {
@Autowired
private GoodsCategoryService goodsCategoryService;
@Autowired
private GoodsCategoryAttributeService goodsCategoryAttributeService;
@RequestMapping(value = "/list", method = RequestMethod.GET)
@ApiOperation(value = "根据parentId获得商品分类列表")
public Result<List<GoodsCategoryVO>> list(@ApiParam("上级分类ID") String parentId) {
@ -73,6 +79,7 @@ public class GoodsCategoryController {
@CacheEvict(value = "mall", key = "'categoryList'")
public Result delByIds(@RequestParam String[] ids) {
for (String id : ids) {
goodsCategoryAttributeService.remove(new LambdaQueryWrapper<GoodsCategoryAttribute>().eq(GoodsCategoryAttribute::getCategoryId, id));
goodsCategoryService.removeById(id);
}
return ResultUtil.success("批量通过id删除数据成功");

61
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/GoodsController.java

@ -1,12 +1,20 @@
package cc.hiver.mall.controller;
import cc.hiver.mall.service.GoodsService;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.mall.pojo.form.GoodsForm;
import cc.hiver.mall.pojo.query.GoodsPageQuery;
import cc.hiver.mall.pojo.vo.GoodsDetailVO;
import cc.hiver.mall.pojo.vo.GoodsPageVO;
import cc.hiver.mall.service.mybatis.GoodsService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RestController
@ -16,4 +24,51 @@ import org.springframework.web.bind.annotation.RestController;
public class GoodsController {
@Autowired
private GoodsService goodsService;
@RequestMapping(value = "/getByCondition", method = RequestMethod.POST)
@ApiOperation(value = "商品分页列表")
public Result<IPage<GoodsPageVO>> listPmsSpuPages(GoodsPageQuery queryParams) {
IPage<GoodsPageVO> result = goodsService.listGoodsPages(queryParams);
return new ResultUtil<IPage<GoodsPageVO>>().setData(result);
}
@RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
@ApiOperation(value = "商品详情")
public Result<GoodsDetailVO> detail(@ApiParam("商品ID") @PathVariable String id) {
GoodsDetailVO goodsDetailVO = goodsService.getGoodsDetail(id);
return new ResultUtil<GoodsDetailVO>().setData(goodsDetailVO);
}
@RequestMapping(value = "/save", method = RequestMethod.POST)
@ApiOperation(value = "新增商品")
public Result addSpu(GoodsForm formData) {
boolean result = goodsService.addGoods(formData);
if(result) {
return ResultUtil.success("添加成功");
} else {
return ResultUtil.error("添加失败");
}
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
@ApiOperation(value = "修改商品")
public Result updateSpuById(GoodsForm formData) {
boolean result = goodsService.updateGoods(formData);
if(result) {
return ResultUtil.success("修改成功");
} else {
return ResultUtil.error("修改失败");
}
}
@RequestMapping(value = "/delByIds", method = RequestMethod.POST)
@ApiOperation(value = "删除商品")
public Result delete(@RequestParam String[] ids) {
boolean result = goodsService.removeByGoodsIds(ids);
if(result) {
return ResultUtil.success("删除成功");
} else {
return ResultUtil.error("删除失败");
}
}
}

78
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/GoodsStockController.java

@ -4,13 +4,16 @@ import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.mall.entity.GoodsInStock;
import cc.hiver.mall.entity.GoodsStock;
import cc.hiver.mall.pojo.dto.CheckPriceDTO;
import cc.hiver.mall.pojo.dto.LockStockDTO;
import cc.hiver.mall.service.GoodsInStockService;
import cc.hiver.mall.service.GoodsStockService;
import cc.hiver.mall.service.mybatis.GoodsStockService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@ -31,9 +34,78 @@ public class GoodsStockController {
@ApiOperation(value = "入库操作")
public Result save(GoodsInStock entity) {
goodsInStockService.save(entity);
GoodsStock goodsStock = goodsStockService.findById(entity.getGoodsStockId());
GoodsStock goodsStock = goodsStockService.getById(entity.getGoodsStockId());
goodsStock.setStock(goodsStock.getStock() + entity.getNum());
goodsStockService.update(goodsStock);
goodsStockService.updateStockNum(entity.getGoodsStockId(), goodsStock.getStock()+entity.getNum());
return ResultUtil.success();
}
@RequestMapping(value = "/detail/{id}", method = RequestMethod.GET)
@ApiOperation(value = "获得库存详细")
public Result<GoodsStock> getStockDetail(@PathVariable String id) {
GoodsStock goodsStock = goodsStockService.getById(id);
return new ResultUtil<GoodsStock>().setData(goodsStock);
}
@RequestMapping(value = "/{id}/stock_num", method = RequestMethod.GET)
@ApiOperation(value = "获得库存数量")
public Result<Integer> getStockNum(@PathVariable String id) {
Integer stockNum = goodsStockService.getStockNum(id);
return new ResultUtil<Integer>().setData(stockNum);
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
@ApiOperation(value = "修改库存信息")
public Result updateStock(GoodsStock goodsStock) {
boolean result = goodsStockService.updateById(goodsStock);
if(result) {
return ResultUtil.success("修改成功");
} else {
return ResultUtil.error("修改失败");
}
}
@RequestMapping(value = "/_lock", method = RequestMethod.POST)
@ApiOperation(value = "锁定库存")
public Result lockStock(LockStockDTO lockStockDTO) {
boolean result = goodsStockService.lockStock(lockStockDTO);
if(result) {
return ResultUtil.success("锁定库存成功");
} else {
return ResultUtil.error("锁定库存失败");
}
}
@RequestMapping(value = "/_unlock", method = RequestMethod.POST)
@ApiOperation(value = "解锁库存")
public Result<Boolean> unlockStock(String orderToken) {
boolean result = goodsStockService.unlockStock(orderToken);
if(result) {
return ResultUtil.success("解锁库存成功");
} else {
return ResultUtil.error("解锁库存失败");
}
}
@RequestMapping(value = "/_deduct", method = RequestMethod.POST)
@ApiOperation(value = "扣减库存")
public Result<Boolean> deductStock(String orderToken) {
boolean result = goodsStockService.deductStock(orderToken);
if(result) {
return ResultUtil.success("扣减库存成功");
} else {
return ResultUtil.error("扣减库存失败");
}
}
@RequestMapping(value = "/price/_check", method = RequestMethod.POST)
@ApiOperation(value = "商品验价")
public Result<Boolean> checkPrice(CheckPriceDTO checkPriceDTO) {
boolean result = goodsStockService.checkPrice(checkPriceDTO);
if(result) {
return ResultUtil.success("商品验价成功");
} else {
return ResultUtil.error("商品验价失败");
}
}
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsAttributeDao.java

@ -1,7 +0,0 @@
package cc.hiver.mall.dao;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.entity.GoodsAttribute;
public interface GoodsAttributeDao extends HiverBaseDao<GoodsAttribute, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsCategoryAttributeDao.java

@ -1,7 +0,0 @@
package cc.hiver.mall.dao;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.entity.GoodsCategoryAttribute;
public interface GoodsCategoryAttributeDao extends HiverBaseDao<GoodsCategoryAttribute, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsCategoryBrandDao.java

@ -1,7 +0,0 @@
package cc.hiver.mall.dao;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.entity.GoodsCategoryBrand;
public interface GoodsCategoryBrandDao extends HiverBaseDao<GoodsCategoryBrand, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsDao.java

@ -1,7 +0,0 @@
package cc.hiver.mall.dao;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.entity.Goods;
public interface GoodsDao extends HiverBaseDao<Goods, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/GoodsStockDao.java

@ -1,7 +0,0 @@
package cc.hiver.mall.dao;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.entity.GoodsStock;
public interface GoodsStockDao extends HiverBaseDao<GoodsStock, String> {
}

27
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsAttributeMapper.java

@ -0,0 +1,27 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.dao.mapper;
import cc.hiver.mall.entity.GoodsAttribute;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author Yazhi Li
*/
@Mapper
public interface GoodsAttributeMapper extends BaseMapper<GoodsAttribute> {
}

27
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsCategoryAttributeMapper.java

@ -0,0 +1,27 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.dao.mapper;
import cc.hiver.mall.entity.GoodsCategoryAttribute;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author Yazhi Li
*/
@Mapper
public interface GoodsCategoryAttributeMapper extends BaseMapper<GoodsCategoryAttribute> {
}

27
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsCategoryBrandMapper.java

@ -0,0 +1,27 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.dao.mapper;
import cc.hiver.mall.entity.GoodsCategoryBrand;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author Yazhi Li
*/
@Mapper
public interface GoodsCategoryBrandMapper extends BaseMapper<GoodsCategoryBrand> {
}

40
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsMapper.java

@ -0,0 +1,40 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.dao.mapper;
import cc.hiver.mall.entity.Goods;
import cc.hiver.mall.pojo.query.GoodsPageQuery;
import cc.hiver.mall.pojo.vo.GoodsPageVO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author Yazhi Li
*/
@Mapper
public interface GoodsMapper extends BaseMapper<Goods> {
/**
* 商品分页列表
*
* @param page
* @param queryParams
* @return
*/
List<GoodsPageVO> listGoodsPages(Page<GoodsPageVO> page, GoodsPageQuery queryParams);
}

35
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/GoodsStockMapper.java

@ -0,0 +1,35 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.dao.mapper;
import cc.hiver.mall.entity.GoodsStock;
import cc.hiver.mall.pojo.dto.GoodsStockDto;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* @author Yazhi Li
*/
@Mapper
public interface GoodsStockMapper extends BaseMapper<GoodsStock> {
/**
* 获取商品库存单元信息
*
* @param id
* @return
*/
GoodsStockDto getStockInfo(String id);
}

66
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/dto/CheckPriceDTO.java

@ -0,0 +1,66 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.math.BigDecimal;
import java.util.List;
/**
* @author Yazhi Li
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class CheckPriceDTO {
/**
* 订单编号
*/
private String orderSn;
/**
* 订单总金额
*/
private BigDecimal orderTotalAmount;
/**
* 订单商品明细
*/
private List<OrderSku> orderSkus;
/**
* 订单商品对象
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class OrderSku {
/**
* 商品ID
*/
private String goodsId;
/**
* 商品数量
*/
private Integer count;
}
}

58
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/dto/GoodsStockDto.java

@ -0,0 +1,58 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.pojo.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Column;
import java.math.BigDecimal;
/**
* @author Yazhi Li
*/
@Data
public class GoodsStockDto {
@ApiModelProperty(value = "序号")
private String id;
@ApiModelProperty(value = "库存编码")
private String sn;
@ApiModelProperty(value = "库存名称")
private String name;
@ApiModelProperty(value = "商品名称")
private String goodsName;
@ApiModelProperty(value = "采购价")
@Column(precision = 10, scale = 2)
private BigDecimal purchasePrice;
@ApiModelProperty(value = "市场价")
@Column(precision = 10, scale = 2)
private BigDecimal price;
@ApiModelProperty(value = "批发价")
@Column(precision = 10, scale = 2)
private BigDecimal wholesalePrice;
@ApiModelProperty(value = "库存数量")
private Integer stock = 0;
@ApiModelProperty(value = "商品图片")
private String picUrl;
}

57
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/dto/LockStockDTO.java

@ -0,0 +1,57 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.pojo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.List;
/**
* @author Yazhi Li
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class LockStockDTO {
/**
* 订单编号
*/
private String orderSn;
/**
* 锁定商品集合
*/
private List<LockedStock> lockedStocks;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class LockedStock {
/**
* 锁定商品ID
*/
private String goodsId;
/**
* 商品数量
*/
private Integer count;
}
}

54
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/form/GoodsCategoryAttributeForm.java

@ -0,0 +1,54 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.pojo.form;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* @author Yazhi Li
*/
@Data
@ApiModel("属性表单")
public class GoodsCategoryAttributeForm {
@ApiModelProperty("分类ID")
@NotNull
private String categoryId;
@ApiModelProperty("属性类型(1:规格;2:属性)")
@NotNull
private Integer type;
@ApiModelProperty("属性集合")
@NotEmpty
private List<Attribute> attributes;
@Data
public static class Attribute {
@ApiModelProperty("属性ID")
private String id;
@ApiModelProperty("属性名称")
@NotBlank
private String name;
}
}

82
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/form/GoodsForm.java

@ -0,0 +1,82 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.pojo.form;
import cc.hiver.mall.entity.GoodsAttribute;
import cc.hiver.mall.entity.GoodsStock;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Column;
import java.math.BigDecimal;
import java.util.List;
/**
* @author Yazhi Li
*/
@Data
public class GoodsForm {
@ApiModelProperty(value = "序号")
private String id;
@ApiModelProperty(value = "商品名称")
private String name;
@ApiModelProperty(value = "商品类型ID")
private String categoryId;
@ApiModelProperty(value = "商品品牌ID")
private String brandId;
@ApiModelProperty(value = "采购价")
@Column(precision = 10, scale = 2)
private BigDecimal purchasePrice;
@ApiModelProperty(value = "市场价")
@Column(precision = 10, scale = 2)
private BigDecimal price;
@ApiModelProperty(value = "批发价")
@Column(precision = 10, scale = 2)
private BigDecimal wholesalePrice;
@ApiModelProperty(value = "商品主图")
private String picUrl;
@ApiModelProperty("商品副图")
private String[] subPicUrls;
@ApiModelProperty(value = "视频地址")
private String videoUrl;
@ApiModelProperty(value = "商品简介")
private String description;
@ApiModelProperty(value = "商品详情")
private String detail;
@ApiModelProperty(value = "是否启用 0上架 -1下架")
private Integer status;
@ApiModelProperty(value = "属性列表")
private List<GoodsAttribute> attrList;
@ApiModelProperty(value = "规格列表")
private List<GoodsAttribute> specList;
@ApiModelProperty(value = "库存列表")
private List<GoodsStock> goodsStockList;
}

40
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/GoodsPageQuery.java

@ -0,0 +1,40 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.pojo.query;
import cc.hiver.core.base.HiverBasePageQuery;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author Yazhi Li
*/
@ApiModel("商品分页查询对象")
@Data
public class GoodsPageQuery extends HiverBasePageQuery {
@ApiModelProperty("关键字")
private String keywords;
@ApiModelProperty("商品分类ID")
private Long categoryId;
@ApiModelProperty("排序字段名")
private String sortField;
@ApiModelProperty("排序规则(asc:升序;desc:降序)")
private String sort;
}

84
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/GoodsDetailVO.java

@ -0,0 +1,84 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.pojo.vo;
import cc.hiver.mall.entity.GoodsAttribute;
import cc.hiver.mall.entity.GoodsStock;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Column;
import java.math.BigDecimal;
import java.util.List;
/**
* @author Yazhi Li
*/
@Data
@ApiModel("商品详情视图对象")
public class GoodsDetailVO {
@ApiModelProperty(value = "序号")
private String id;
@ApiModelProperty(value = "商品名称")
private String name;
@ApiModelProperty(value = "商品类型ID")
private String categoryId;
@ApiModelProperty(value = "商品品牌ID")
private String brandId;
@ApiModelProperty(value = "采购价")
@Column(precision = 10, scale = 2)
private BigDecimal purchasePrice;
@ApiModelProperty(value = "市场价")
@Column(precision = 10, scale = 2)
private BigDecimal price;
@ApiModelProperty(value = "批发价")
@Column(precision = 10, scale = 2)
private BigDecimal wholesalePrice;
@ApiModelProperty(value = "商品主图")
private String picUrl;
@ApiModelProperty("商品副图")
private String[] subPicUrls;
@ApiModelProperty(value = "视频地址")
private String videoUrl;
@ApiModelProperty(value = "商品简介")
private String description;
@ApiModelProperty(value = "商品详情")
private String detail;
@ApiModelProperty(value = "是否启用 0上架 -1下架")
private Integer status;
@ApiModelProperty(value = "属性列表")
private List<GoodsAttribute> attrList;
@ApiModelProperty(value = "规格列表")
private List<GoodsAttribute> specList;
@ApiModelProperty(value = "库存列表")
private List<GoodsStock> goodsStockList;
}

89
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/GoodsPageVO.java

@ -0,0 +1,89 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.pojo.vo;
import cc.hiver.mall.entity.GoodsStock;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import javax.persistence.Column;
import java.math.BigDecimal;
import java.util.List;
/**
* @author Yazhi Li
*/
@Data
@Accessors(chain = true)
public class GoodsPageVO {
@ApiModelProperty(value = "序号")
private String id;
@ApiModelProperty(value = "商品名称")
private String name;
@ApiModelProperty(value = "商品类型ID")
private String categoryId;
@ApiModelProperty(value = "商品品牌ID")
private String brandId;
@ApiModelProperty(value = "采购价")
@Column(precision = 10, scale = 2)
private BigDecimal purchasePrice;
@ApiModelProperty(value = "市场价")
@Column(precision = 10, scale = 2)
private BigDecimal price;
@ApiModelProperty(value = "批发价")
@Column(precision = 10, scale = 2)
private BigDecimal wholesalePrice;
@ApiModelProperty(value = "销量")
private Integer sales;
@ApiModelProperty(value = "商品主图")
private String picUrl;
@ApiModelProperty(value = "视频地址")
private String videoUrl;
@ApiModelProperty(value = "商品图册")
private String album;
@ApiModelProperty(value = "单位")
private String unit;
@ApiModelProperty(value = "商品简介")
private String description;
@ApiModelProperty(value = "商品详情")
private String detail;
@ApiModelProperty(value = "是否启用 0上架 -1下架")
private Integer status;
@ApiModelProperty(value = "分类名称")
private String categoryName;
@ApiModelProperty(value = "品牌名称")
private String brandName;
@ApiModelProperty(value = "库存列表")
private List<GoodsStock> goodsStockList;
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsAttributeService.java

@ -1,7 +0,0 @@
package cc.hiver.mall.service;
import cc.hiver.core.base.HiverBaseService;
import cc.hiver.mall.entity.GoodsAttribute;
public interface GoodsAttributeService extends HiverBaseService<GoodsAttribute, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsCategoryAttributeService.java

@ -1,7 +0,0 @@
package cc.hiver.mall.service;
import cc.hiver.core.base.HiverBaseService;
import cc.hiver.mall.entity.GoodsCategoryAttribute;
public interface GoodsCategoryAttributeService extends HiverBaseService<GoodsCategoryAttribute, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsCategoryBrandService.java

@ -1,7 +0,0 @@
package cc.hiver.mall.service;
import cc.hiver.core.base.HiverBaseService;
import cc.hiver.mall.entity.GoodsCategoryBrand;
public interface GoodsCategoryBrandService extends HiverBaseService<GoodsCategoryBrand, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsService.java

@ -1,7 +0,0 @@
package cc.hiver.mall.service;
import cc.hiver.core.base.HiverBaseService;
import cc.hiver.mall.entity.Goods;
public interface GoodsService extends HiverBaseService<Goods, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/GoodsStockService.java

@ -1,7 +0,0 @@
package cc.hiver.mall.service;
import cc.hiver.core.base.HiverBaseService;
import cc.hiver.mall.entity.GoodsStock;
public interface GoodsStockService extends HiverBaseService<GoodsStock, String> {
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsAttributeService.java

@ -0,0 +1,7 @@
package cc.hiver.mall.service.mybatis;
import cc.hiver.mall.entity.GoodsAttribute;
import com.baomidou.mybatisplus.extension.service.IService;
public interface GoodsAttributeService extends IService<GoodsAttribute> {
}

9
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsCategoryAttributeService.java

@ -0,0 +1,9 @@
package cc.hiver.mall.service.mybatis;
import cc.hiver.mall.entity.GoodsCategoryAttribute;
import cc.hiver.mall.pojo.form.GoodsCategoryAttributeForm;
import com.baomidou.mybatisplus.extension.service.IService;
public interface GoodsCategoryAttributeService extends IService<GoodsCategoryAttribute> {
boolean saveBatch(GoodsCategoryAttributeForm formData);
}

7
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsCategoryBrandService.java

@ -0,0 +1,7 @@
package cc.hiver.mall.service.mybatis;
import cc.hiver.mall.entity.GoodsCategoryBrand;
import com.baomidou.mybatisplus.extension.service.IService;
public interface GoodsCategoryBrandService extends IService<GoodsCategoryBrand> {
}

69
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsService.java

@ -0,0 +1,69 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.service.mybatis;
import cc.hiver.mall.entity.Goods;
import cc.hiver.mall.pojo.form.GoodsForm;
import cc.hiver.mall.pojo.query.GoodsPageQuery;
import cc.hiver.mall.pojo.vo.GoodsDetailVO;
import cc.hiver.mall.pojo.vo.GoodsPageVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author Yazhi Li
*/
public interface GoodsService extends IService<Goods> {
/**
* 管理端商品分页列表
*
* @param queryParams
* @return
*/
IPage<GoodsPageVO> listGoodsPages(GoodsPageQuery queryParams);
/**
* 管理端获取商品详情
*
* @param id
* @return
*/
GoodsDetailVO getGoodsDetail(String id);
/**
* 新增商品
*
* @param formData
* @return
*/
boolean addGoods(GoodsForm formData);
/**
* 修改商品
*
* @param formData
* @return
*/
boolean updateGoods(GoodsForm formData);
/**
* 删除商品
*
* @param ids 商品ID多个以英文逗号(,)分割
* @return
*/
boolean removeByGoodsIds(String[] ids);
}

66
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/GoodsStockService.java

@ -0,0 +1,66 @@
package cc.hiver.mall.service.mybatis;
import cc.hiver.mall.entity.GoodsStock;
import cc.hiver.mall.pojo.dto.CheckPriceDTO;
import cc.hiver.mall.pojo.dto.GoodsStockDto;
import cc.hiver.mall.pojo.dto.LockStockDTO;
import com.baomidou.mybatisplus.extension.service.IService;
public interface GoodsStockService extends IService<GoodsStock> {
/**
* 获取商品的库存数量
*
* @param id
* @return
*/
Integer getStockNum(String id);
/**
* 获取商品库存信息
*
* @param id
* @return
*/
GoodsStockDto getStockInfo(String id);
/**
* 锁定库存
*/
boolean lockStock(LockStockDTO lockStockDTO);
/**
* 解锁库存
*/
boolean unlockStock(String orderSn);
/**
* 扣减库存
*/
boolean deductStock(String orderSn);
/**
* 商品验价
*
* @param checkPriceDTO
* @return
*/
boolean checkPrice(CheckPriceDTO checkPriceDTO);
/**
* 修改商品库存数量
*
* @param id
* @param stockNum 商品库存数量
* @return
*/
boolean updateStockNum(String id, Integer stockNum);
/**
* 扣减商品库存
*
* @param id
* @param num 商品库存数量
* @return
*/
boolean deductStock(String id, Integer num);
}

23
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsAttributeServiceImpl.java

@ -1,23 +0,0 @@
package cc.hiver.mall.serviceimpl;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.dao.GoodsAttributeDao;
import cc.hiver.mall.entity.GoodsAttribute;
import cc.hiver.mall.service.GoodsAttributeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@Transactional
public class GoodsAttributeServiceImpl implements GoodsAttributeService {
@Autowired
private GoodsAttributeDao goodsAttributeDao;
@Override
public HiverBaseDao<GoodsAttribute, String> getRepository() {
return goodsAttributeDao;
}
}

23
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsCategoryAttributeServiceImpl.java

@ -1,23 +0,0 @@
package cc.hiver.mall.serviceimpl;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.dao.GoodsCategoryAttributeDao;
import cc.hiver.mall.entity.GoodsCategoryAttribute;
import cc.hiver.mall.service.GoodsCategoryAttributeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@Transactional
public class GoodsCategoryAttributeServiceImpl implements GoodsCategoryAttributeService {
@Autowired
private GoodsCategoryAttributeDao goodsCategoryAttributeDao;
@Override
public HiverBaseDao<GoodsCategoryAttribute, String> getRepository() {
return goodsCategoryAttributeDao;
}
}

23
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsCategoryBrandServiceImpl.java

@ -1,23 +0,0 @@
package cc.hiver.mall.serviceimpl;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.dao.GoodsCategoryBrandDao;
import cc.hiver.mall.entity.GoodsCategoryBrand;
import cc.hiver.mall.service.GoodsCategoryBrandService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@Transactional
public class GoodsCategoryBrandServiceImpl implements GoodsCategoryBrandService {
@Autowired
private GoodsCategoryBrandDao goodsCategoryBrandDao;
@Override
public HiverBaseDao<GoodsCategoryBrand, String> getRepository() {
return goodsCategoryBrandDao;
}
}

23
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsServiceImpl.java

@ -1,23 +0,0 @@
package cc.hiver.mall.serviceimpl;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.dao.GoodsDao;
import cc.hiver.mall.entity.Goods;
import cc.hiver.mall.service.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@Transactional
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsDao goodsDao;
@Override
public HiverBaseDao<Goods, String> getRepository() {
return goodsDao;
}
}

23
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/GoodsStockServiceImpl.java

@ -1,23 +0,0 @@
package cc.hiver.mall.serviceimpl;
import cc.hiver.core.base.HiverBaseDao;
import cc.hiver.mall.dao.GoodsStockDao;
import cc.hiver.mall.entity.GoodsStock;
import cc.hiver.mall.service.GoodsStockService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Service
@Transactional
public class GoodsStockServiceImpl implements GoodsStockService {
@Autowired
private GoodsStockDao goodsStockDao;
@Override
public HiverBaseDao<GoodsStock, String> getRepository() {
return goodsStockDao;
}
}

11
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsAttributeServiceImpl.java

@ -0,0 +1,11 @@
package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.mall.dao.mapper.GoodsAttributeMapper;
import cc.hiver.mall.entity.GoodsAttribute;
import cc.hiver.mall.service.mybatis.GoodsAttributeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class GoodsAttributeServiceImpl extends ServiceImpl<GoodsAttributeMapper, GoodsAttribute> implements GoodsAttributeService {
}

60
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsCategoryAttributeServiceImpl.java

@ -0,0 +1,60 @@
package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.mall.dao.mapper.GoodsCategoryAttributeMapper;
import cc.hiver.mall.entity.GoodsCategoryAttribute;
import cc.hiver.mall.pojo.form.GoodsCategoryAttributeForm;
import cc.hiver.mall.service.mybatis.GoodsCategoryAttributeService;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class GoodsCategoryAttributeServiceImpl extends ServiceImpl<GoodsCategoryAttributeMapper, GoodsCategoryAttribute> implements GoodsCategoryAttributeService {
@Override
public boolean saveBatch(GoodsCategoryAttributeForm formData) {
String categoryId = formData.getCategoryId();
Integer attributeType = formData.getType();
List<String> formIds = formData.getAttributes().stream()
.filter(item -> item.getId() != null)
.map(item -> item.getId())
.collect(Collectors.toList());
List<String> dbIds = this.list(new LambdaQueryWrapper<GoodsCategoryAttribute>()
.eq(GoodsCategoryAttribute::getCategoryId, categoryId)
.eq(GoodsCategoryAttribute::getType, attributeType)
.select(GoodsCategoryAttribute::getId)).stream()
.map(item -> item.getId())
.collect(Collectors.toList());
// 删除此次表单没有的属性ID
if (CollectionUtil.isNotEmpty(dbIds)) {
List<String> rmIds = dbIds.stream()
.filter(id -> CollectionUtil.isEmpty(formIds) || !formIds.contains(id))
.collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(rmIds)) {
this.removeByIds(rmIds);
}
}
// 新增/修改表单提交的属性
List<GoodsCategoryAttributeForm.Attribute> formAttributes = formData.getAttributes();
List<GoodsCategoryAttribute> attributeList = new ArrayList<>();
formAttributes.forEach(item -> {
GoodsCategoryAttribute attribute = new GoodsCategoryAttribute();
attribute.setCategoryId(categoryId);
attribute.setType(attributeType);
attribute.setName(item.getName());
attributeList.add(attribute);
});
boolean result = this.saveOrUpdateBatch(attributeList);
return result;
}
}

11
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsCategoryBrandServiceImpl.java

@ -0,0 +1,11 @@
package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.mall.dao.mapper.GoodsCategoryBrandMapper;
import cc.hiver.mall.entity.GoodsCategoryBrand;
import cc.hiver.mall.service.mybatis.GoodsCategoryBrandService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class GoodsCategoryBrandServiceImpl extends ServiceImpl<GoodsCategoryBrandMapper, GoodsCategoryBrand> implements GoodsCategoryBrandService {
}

64
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsServiceImpl.java

@ -0,0 +1,64 @@
/*
Copyright [2022] [https://hiver.cc]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.mall.dao.mapper.GoodsMapper;
import cc.hiver.mall.entity.Goods;
import cc.hiver.mall.pojo.form.GoodsForm;
import cc.hiver.mall.pojo.query.GoodsPageQuery;
import cc.hiver.mall.pojo.vo.GoodsDetailVO;
import cc.hiver.mall.pojo.vo.GoodsPageVO;
import cc.hiver.mall.service.mybatis.GoodsService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author Yazhi Li
*/
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {
@Override
public IPage<GoodsPageVO> listGoodsPages(GoodsPageQuery queryParams) {
Page<GoodsPageVO> page = new Page<>(queryParams.getPageNum(), queryParams.getPageSize());
List<GoodsPageVO> list = this.baseMapper.listGoodsPages(page, queryParams);
page.setRecords(list);
return page;
}
@Override
public GoodsDetailVO getGoodsDetail(String id) {
return null;
}
@Override
public boolean addGoods(GoodsForm formData) {
return false;
}
@Override
public boolean updateGoods(GoodsForm formData) {
return false;
}
@Override
public boolean removeByGoodsIds(String[] ids) {
return false;
}
}

197
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/GoodsStockServiceImpl.java

@ -0,0 +1,197 @@
package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.core.common.constant.MallConstant;
import cc.hiver.mall.dao.mapper.GoodsStockMapper;
import cc.hiver.mall.entity.GoodsStock;
import cc.hiver.mall.pojo.dto.CheckPriceDTO;
import cc.hiver.mall.pojo.dto.GoodsStockDto;
import cc.hiver.mall.pojo.dto.LockStockDTO;
import cc.hiver.mall.service.mybatis.GoodsStockService;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class GoodsStockServiceImpl extends ServiceImpl<GoodsStockMapper, GoodsStock> implements GoodsStockService {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RedissonClient redissonClient;
@Override
@Cacheable(cacheNames = "mall", key = "'stock_num:'+#id")
public Integer getStockNum(String id) {
GoodsStock goodsStock = this.getOne(new LambdaQueryWrapper<GoodsStock>().eq(GoodsStock::getId, id)
.select(GoodsStock::getStock));
Integer stockNum = goodsStock != null ? goodsStock.getStock() : 0;
return stockNum;
}
@Override
public GoodsStockDto getStockInfo(String id) {
GoodsStockDto goodsStockDto = this.baseMapper.getStockInfo(id);
return goodsStockDto;
}
@Override
@Transactional
public boolean lockStock(LockStockDTO lockStock) {
String orderSn = lockStock.getOrderSn();
log.info("创建订单【{}】锁定商品库存:{}", orderSn, lockStock);
List<LockStockDTO.LockedStock> lockedSkus = lockStock.getLockedStocks();
Assert.isTrue(CollectionUtil.isNotEmpty(lockedSkus), "锁定的商品为空");
// 循环遍历锁定商品
for (LockStockDTO.LockedStock lockedSku : lockedSkus) {
// 获取商品分布式锁
RLock lock = redissonClient.getLock(MallConstant.SKU_LOCK_PREFIX + lockedSku.getGoodsId());
// 加锁
lock.lock();
try {
boolean lockResult = this.update(new LambdaUpdateWrapper<GoodsStock>()
.setSql("locked_stock_num = locked_stock_num + " + lockedSku.getCount())
.eq(GoodsStock::getId, lockedSku.getGoodsId())
.apply("stock - locked_stock >= {0}", lockedSku.getCount())
);
Assert.isTrue(lockResult, "锁定商品 {} 失败", lockedSku.getGoodsId());
} finally {
// 释放锁
if (lock.isLocked()) {
lock.unlock();
}
}
}
redisTemplate.opsForValue().set(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn, lockedSkus);
return true;
}
@Override
public boolean unlockStock(String orderSn) {
log.info("订单取消:释放订单【{}】锁定的商品库存", orderSn);
List<LockStockDTO.LockedStock> lockedSkus = (List<LockStockDTO.LockedStock>) redisTemplate.opsForValue()
.get(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn);
// 遍历解锁商品
if (CollectionUtil.isNotEmpty(lockedSkus)) {
for (LockStockDTO.LockedStock lockedSku : lockedSkus) {
// 获取商品分布式锁
RLock lock = redissonClient.getLock(MallConstant.SKU_LOCK_PREFIX + lockedSku.getGoodsId());
// 加锁
lock.lock();
try {
this.update(new LambdaUpdateWrapper<GoodsStock>()
.eq(GoodsStock::getId, lockedSku.getGoodsId())
.setSql("locked_stock_num = locked_stock_num - " + lockedSku.getCount()));
} finally {
// 释放锁
if (lock.isLocked()) {
lock.unlock();
}
}
}
}
// 移除订单的商品信息缓存
redisTemplate.delete(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn);
return true;
}
@Override
public boolean deductStock(String orderSn) {
log.info("订单【{}】支付成功:扣减订单商品库存", orderSn);
// 获取订单提交时锁定的商品
List<LockStockDTO.LockedStock> lockedSkus = (List<LockStockDTO.LockedStock>) redisTemplate.opsForValue()
.get(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn);
if (CollectionUtil.isNotEmpty(lockedSkus)) {
for (LockStockDTO.LockedStock lockedSku : lockedSkus) {
// 获取商品分布式锁
RLock lock = redissonClient.getLock(MallConstant.SKU_LOCK_PREFIX + lockedSku.getGoodsId());
// 加锁
lock.lock();
try {
this.update(new LambdaUpdateWrapper<GoodsStock>()
.eq(GoodsStock::getId, lockedSku.getGoodsId())
.setSql("stock = stock_ - " + lockedSku.getCount())
.setSql("locked_stock = locked_stock - " + lockedSku.getCount())
);
} finally {
// 释放锁
if (lock.isLocked()) {
lock.unlock();
}
}
}
}
// 移除订单的商品缓存
redisTemplate.delete(MallConstant.ORDER_LOCKED_SKUS_PREFIX + orderSn);
return true;
}
@Override
public boolean checkPrice(CheckPriceDTO checkPrice) {
log.info("订单【{}】商品验价:{}", checkPrice);
// 订单总金额
BigDecimal orderTotalAmount = checkPrice.getOrderTotalAmount();
// 计算商品总金额
List<CheckPriceDTO.OrderSku> orderSkus = checkPrice.getOrderSkus();
if (orderTotalAmount == null || CollectionUtil.isEmpty(orderSkus)) {
log.warn("订单【{}】验价失败:订单总金额或订单商品为空,无法进行验价!");
return false;
}
// 订单商品ID集合
List<String> orderGoodsIds = orderSkus.stream().map(orderItem -> orderItem.getGoodsId())
.collect(Collectors.toList());
// 获取商品的实时价格
List<GoodsStock> goodsList = this.list(new LambdaQueryWrapper<GoodsStock>().in(GoodsStock::getId, orderGoodsIds)
.select(GoodsStock::getId, GoodsStock::getPrice)
);
if (CollectionUtil.isEmpty(goodsList)) {
log.warn("订单【{}】验价失败:订单商品库存不存在或已下架!");
return false;
}
// 计算商品实时总价
BigDecimal skuTotalAmount = goodsList.stream().map(sku -> {
// 获取订单中该商品数量
CheckPriceDTO.OrderSku matchOrderSku = orderSkus.stream()
.filter(orderSku -> sku.getId().equals(orderSku.getGoodsId()))
.findFirst().orElse(null);
// 单个商品实时总价 = 实时单价 * 订单该商品数量
return matchOrderSku != null ? sku.getPrice().multiply(new BigDecimal(matchOrderSku.getCount())) : BigDecimal.ZERO;
}).reduce(BigDecimal.ZERO, BigDecimal::add);
// 比较订单总价和商品实时总价
boolean checkPriceResult = orderTotalAmount.compareTo(skuTotalAmount) == 0;
return checkPriceResult;
}
@Override
@Transactional
public boolean updateStockNum(String id, Integer stockNum) {
boolean result = this.update(new LambdaUpdateWrapper<GoodsStock>()
.eq(GoodsStock::getId, id)
.set(GoodsStock::getStock, stockNum)
);
return result;
}
@Override
public boolean deductStock(String id, Integer num) {
boolean result = this.update(new LambdaUpdateWrapper<GoodsStock>()
.setSql("stock = stock - " + num)
.eq(GoodsStock::getId, id)
);
return result;
}
}

66
hiver-modules/hiver-mall/src/main/resources/mapper/GoodsMapper.xml

@ -0,0 +1,66 @@
<?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="cc.hiver.mall.dao.mapper.GoodsMapper">
<resultMap id="BaseResultMap" type="cc.hiver.mall.pojo.vo.GoodsPageVO">
<id property="id" column="id" jdbcType="VARCHAR"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="categoryId" column="category_id" jdbcType="BIGINT"/>
<result property="brandId" column="brand_id" jdbcType="BIGINT"/>
<result property="purchasePrice" column="purchase_price" jdbcType="BIGINT"/>
<result property="price" column="price" jdbcType="BIGINT"/>
<result property="wholesalePrice" column="wholesale_price" jdbcType="BIGINT"/>
<result property="sales" column="sales" jdbcType="INTEGER"/>
<result property="picUrl" column="pic_url" jdbcType="VARCHAR"/>
<result property="album" column="album" jdbcType="OTHER"/>
<result property="unit" column="unit" jdbcType="VARCHAR"/>
<result property="description" column="description" jdbcType="VARCHAR"/>
<result property="detail" column="detail" jdbcType="VARCHAR"/>
<result property="status" column="status" jdbcType="TINYINT"/>
<result property="categoryName" column="categoryName" jdbcType="VARCHAR"/>
<result property="brandName" column="brandName" jdbcType="VARCHAR"/>
<collection property="goodsStockList" column="id" select="cc.hiver.mall.dao.mapper.listGoodsByGoodsId">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="sn" column="sn" jdbcType="VARCHAR"/>
<result property="picUrl" column="pic_url" jdbcType="VARCHAR"/>
<result property="specIds" column="spec_ids" jdbcType="VARCHAR"/>
<result property="price" column="price" jdbcType="BIGINT"/>
<result property="stock" column="stock" jdbcType="INTEGER"/>
<result property="lockedStock" column="locked_stock" jdbcType="INTEGER"/>
</collection>
</resultMap>
<!--商品分页列表-->
<select id="listGoodsPages" resultMap="BaseResultMap">
SELECT
t1.id,
t1.name,
t1.pic_url,
t1.origin_price,
t1.price,
t1.sales,
t1.unit,
t1.detail,
t1.description,
t3.NAME categoryName,
t4.NAME brandName
FROM t_goods t1
LEFT JOIN t_goods_category t3 ON t1.category_id = t3.id
LEFT JOIN t_goods_brand t4 ON t1.brand_id = t4.id
<where>
<if test='queryParams.keywords!=null and queryParams.keywords.trim() neq ""'>
AND t1.name like concat('%',#{queryParams.keywords},'%')
</if>
<if test="queryParams.categoryId!=null">
AND t1.category_id =#{queryParams.categoryId}
</if>
</where>
ORDER BY
t1.update_time DESC,
t1.create_time DESC
</select>
</mapper>

33
hiver-modules/hiver-mall/src/main/resources/mapper/GoodsStockMapper.xml

@ -0,0 +1,33 @@
<?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="cc.hiver.mall.dao.mapper.GoodsStockMapper">
<!-- 根据商品ID获取商品库存单元列表 -->
<select id="listGoodsByGoodsId" resultType="cc.hiver.mall.entity.GoodsStock">
SELECT id ,
name ,
sn,
pic_url ,
spec_ids,
price ,
stock
FROM t_goods_stock
WHERE goods_id = #{id}
</select>
<!-- 获取商品库存单元信息 -->
<select id="getStockInfo" resultType="cc.hiver.mall.pojo.dto.GoodsStockDto">
select
t1.id,
t1.sn,
concat(t2.name,' ',t1.name) name,
t1.pic_url,
t1.price,
t1.stock,
t2.name as goodsName
from t_goods_stock t1
left join t_goods t2 on t1.goods_id = t2.id
where t1.id = #{id}
</select>
</mapper>
Loading…
Cancel
Save