库存
This commit is contained in:
@@ -10,6 +10,7 @@ import com.tashow.cloud.productapi.enums.ApiConstants;
|
|||||||
import jakarta.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿:fallbackFactory =
|
||||||
@@ -46,5 +47,20 @@ public interface ProdApi {
|
|||||||
@GetMapping(PREFIX + "/getProdPage")
|
@GetMapping(PREFIX + "/getProdPage")
|
||||||
PageResult<ProdListVO> getProdPage(ProdPageReqVO pageReqVO);
|
PageResult<ProdListVO> getProdPage(ProdPageReqVO pageReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扣减库存
|
||||||
|
* @param skuId 单品ID
|
||||||
|
* @param stocksNum 扣减数量
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/reduceStocks")
|
||||||
|
CommonResult<Boolean> reduceStocks(Long skuId, Integer stocksNum) ;
|
||||||
|
/**
|
||||||
|
* 增加库存
|
||||||
|
* @param skuId 单品ID
|
||||||
|
* @param stocksNum 增加数量
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/increaseStocks")
|
||||||
|
CommonResult<Boolean> increaseStocks(Long skuId, Integer stocksNum);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,4 +32,10 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode SKU_SERVICES_FORM_NOT_EXISTS = new ErrorCode(10021, "商品SKU扩展服务表单不存在");
|
ErrorCode SKU_SERVICES_FORM_NOT_EXISTS = new ErrorCode(10021, "商品SKU扩展服务表单不存在");
|
||||||
ErrorCode SKU_SERVICE_TRANSPORT_NOT_EXISTS = new ErrorCode(10022, "服务遗体运输不存在");
|
ErrorCode SKU_SERVICE_TRANSPORT_NOT_EXISTS = new ErrorCode(10022, "服务遗体运输不存在");
|
||||||
ErrorCode SKU_SERVICE_DETAILS_NOT_EXISTS = new ErrorCode(10023, "服务详情不存在");
|
ErrorCode SKU_SERVICE_DETAILS_NOT_EXISTS = new ErrorCode(10023, "服务详情不存在");
|
||||||
|
|
||||||
|
ErrorCode SKU_DOES_NOT_EXIST = new ErrorCode(10030, "商品不存在");
|
||||||
|
ErrorCode SKU_DELETE = new ErrorCode(10030, "商品已删除");
|
||||||
|
ErrorCode SKU_DISABLE = new ErrorCode(10031, "商品已禁用");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.tashow.cloud.product.api;
|
|||||||
import com.tashow.cloud.common.pojo.CommonResult;
|
import com.tashow.cloud.common.pojo.CommonResult;
|
||||||
import com.tashow.cloud.common.pojo.PageResult;
|
import com.tashow.cloud.common.pojo.PageResult;
|
||||||
import com.tashow.cloud.product.service.ProdService;
|
import com.tashow.cloud.product.service.ProdService;
|
||||||
|
import com.tashow.cloud.product.service.SkuService;
|
||||||
import com.tashow.cloud.productapi.api.product.ProdApi;
|
import com.tashow.cloud.productapi.api.product.ProdApi;
|
||||||
import com.tashow.cloud.productapi.api.product.dto.ProdDO;
|
import com.tashow.cloud.productapi.api.product.dto.ProdDO;
|
||||||
import com.tashow.cloud.productapi.api.product.vo.prod.ProdListVO;
|
import com.tashow.cloud.productapi.api.product.vo.prod.ProdListVO;
|
||||||
@@ -12,6 +13,8 @@ import jakarta.annotation.Resource;
|
|||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import static com.tashow.cloud.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||||
@Validated
|
@Validated
|
||||||
public class ProdImpl implements ProdApi {
|
public class ProdImpl implements ProdApi {
|
||||||
@@ -19,6 +22,9 @@ public class ProdImpl implements ProdApi {
|
|||||||
@Resource
|
@Resource
|
||||||
private ProdService prodService;
|
private ProdService prodService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SkuService skuService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<ProdDO> getProdInfo(Long id) {
|
public CommonResult<ProdDO> getProdInfo(Long id) {
|
||||||
return CommonResult.success(prodService.getProd(id));
|
return CommonResult.success(prodService.getProd(id));
|
||||||
@@ -34,4 +40,16 @@ public class ProdImpl implements ProdApi {
|
|||||||
return prodService.getProdPage(pageReqVO);
|
return prodService.getProdPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> reduceStocks(Long skuId, Integer stocksNum) {
|
||||||
|
skuService.reduceStocks(skuId, stocksNum);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> increaseStocks(Long skuId, Integer stocksNum) {
|
||||||
|
skuService.increaseStocks(skuId, stocksNum);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.tashow.cloud.common.pojo.CommonResult;
|
|||||||
import com.tashow.cloud.common.pojo.PageResult;
|
import com.tashow.cloud.common.pojo.PageResult;
|
||||||
import com.tashow.cloud.product.mapper.ProdMapper;
|
import com.tashow.cloud.product.mapper.ProdMapper;
|
||||||
import com.tashow.cloud.product.service.ProdService;
|
import com.tashow.cloud.product.service.ProdService;
|
||||||
|
import com.tashow.cloud.product.service.SkuService;
|
||||||
import com.tashow.cloud.productapi.api.product.dto.ProdDO;
|
import com.tashow.cloud.productapi.api.product.dto.ProdDO;
|
||||||
import com.tashow.cloud.productapi.api.product.vo.prod.*;
|
import com.tashow.cloud.productapi.api.product.vo.prod.*;
|
||||||
import com.tashow.cloud.productapi.enums.BaseEnum;
|
import com.tashow.cloud.productapi.enums.BaseEnum;
|
||||||
@@ -30,6 +31,8 @@ public class ProdController {
|
|||||||
@Resource
|
@Resource
|
||||||
private ProdService prodService;
|
private ProdService prodService;
|
||||||
@Resource
|
@Resource
|
||||||
|
private SkuService skuService;
|
||||||
|
@Resource
|
||||||
private ProdMapper prodMapper;
|
private ProdMapper prodMapper;
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@Operation(summary = "创建商品")
|
@Operation(summary = "创建商品")
|
||||||
@@ -154,4 +157,23 @@ public class ProdController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/reduceStocks")
|
||||||
|
@Operation(summary = "扣减库存")
|
||||||
|
@PermitAll
|
||||||
|
public CommonResult<Boolean> reduceStocks(@RequestParam("skuid") Long skuId,
|
||||||
|
@RequestParam("stocksNum") Integer stocksNum) {
|
||||||
|
skuService.reduceStocks(skuId, stocksNum);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/increaseStocks")
|
||||||
|
@Operation(summary = "增加库存")
|
||||||
|
@PermitAll
|
||||||
|
public CommonResult<Boolean> increaseStocks(@RequestParam("skuid") Long skuId,
|
||||||
|
@RequestParam("stocksNum") Integer stocksNum) {
|
||||||
|
skuService.increaseStocks(skuId, stocksNum);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.tashow.cloud.productapi.api.product.dto.SkuDO;
|
|||||||
import com.tashow.cloud.productapi.api.product.vo.sku.SkuRecycleBinVO;
|
import com.tashow.cloud.productapi.api.product.vo.sku.SkuRecycleBinVO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Update;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 单品SKU Mapper
|
* 单品SKU Mapper
|
||||||
@@ -44,4 +45,25 @@ public interface SkuMapper extends BaseMapperX<SkuDO> {
|
|||||||
|
|
||||||
// 查询商品下所有 SKU 的 is_shelf 状态(未删除)
|
// 查询商品下所有 SKU 的 is_shelf 状态(未删除)
|
||||||
List<Integer> selectShelfStatusByProdId(@Param("prodId") Long prodId);
|
List<Integer> selectShelfStatusByProdId(@Param("prodId") Long prodId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扣减库存(带乐观锁)
|
||||||
|
* @param skuId 单品ID
|
||||||
|
* @param stocksNum 扣减数量
|
||||||
|
* @param version 版本号
|
||||||
|
* @return 更新影响的行数
|
||||||
|
*/
|
||||||
|
@Update("UPDATE tz_sku SET stocks = stocks - #{stocksNum}, version = version + 1, update_time = NOW() " +
|
||||||
|
"WHERE sku_id = #{skuId} AND version = #{version} AND stocks >= #{stocksNum} AND deleted = 0")
|
||||||
|
int reduceStocks(@Param("skuId") Long skuId,
|
||||||
|
@Param("stocksNum") Integer stocksNum,
|
||||||
|
@Param("version") Integer version);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加库存
|
||||||
|
*/
|
||||||
|
@Update("UPDATE tz_sku SET stocks = stocks + #{stocksNum}, version = version + 1, update_time = NOW() " +
|
||||||
|
"WHERE sku_id = #{skuId} AND deleted = 0")
|
||||||
|
int increaseStocks(@Param("skuId") Long skuId,
|
||||||
|
@Param("stocksNum") Integer stocksNum);
|
||||||
}
|
}
|
||||||
@@ -175,5 +175,17 @@ public interface SkuService {
|
|||||||
* @param skuServiceDeliverList 更新信息
|
* @param skuServiceDeliverList 更新信息
|
||||||
*/
|
*/
|
||||||
void updateDeliver(List<SkuServiceDeliverDO> skuServiceDeliverList);
|
void updateDeliver(List<SkuServiceDeliverDO> skuServiceDeliverList);
|
||||||
|
/**
|
||||||
|
* 扣减库存
|
||||||
|
* @param skuId 单品ID
|
||||||
|
* @param stocksNum 扣减数量
|
||||||
|
*/
|
||||||
|
void reduceStocks(Long skuId, Integer stocksNum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加库存
|
||||||
|
* @param skuId 单品ID
|
||||||
|
* @param stocksNum 增加数量
|
||||||
|
*/
|
||||||
|
void increaseStocks(Long skuId, Integer stocksNum);
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@ import com.tashow.cloud.productapi.api.product.vo.sku.*;
|
|||||||
import com.tashow.cloud.productapi.enums.BaseEnum;
|
import com.tashow.cloud.productapi.enums.BaseEnum;
|
||||||
import com.tashow.cloud.productapi.enums.ErrorCodeConstants;
|
import com.tashow.cloud.productapi.enums.ErrorCodeConstants;
|
||||||
import com.tashow.cloud.productapi.enums.ServiceTypeEnum;
|
import com.tashow.cloud.productapi.enums.ServiceTypeEnum;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
@@ -41,6 +42,7 @@ import static com.tashow.cloud.common.exception.util.ServiceExceptionUtil.except
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@Validated
|
@Validated
|
||||||
|
@Slf4j
|
||||||
public class SkuServiceImpl implements SkuService {
|
public class SkuServiceImpl implements SkuService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@@ -967,6 +969,62 @@ public class SkuServiceImpl implements SkuService {
|
|||||||
skuServiceDeliverMapper.insertBatch(skuServiceDeliverList);
|
skuServiceDeliverMapper.insertBatch(skuServiceDeliverList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void reduceStocks(Long skuId, Integer stocksNum) {
|
||||||
|
if (stocksNum == null || stocksNum <= 0) {
|
||||||
|
stocksNum=1;
|
||||||
|
}
|
||||||
|
// 查询SKU信息
|
||||||
|
SkuDO sku = skuMapper.selectById(skuId);
|
||||||
|
if (sku == null) {
|
||||||
|
//商品不存在
|
||||||
|
throw exception(ErrorCodeConstants.SKU_DOES_NOT_EXIST);
|
||||||
|
}
|
||||||
|
if (sku.getDeleted() == 1) {
|
||||||
|
//商品已删除
|
||||||
|
throw exception(ErrorCodeConstants.SKU_DELETE);
|
||||||
|
}
|
||||||
|
if (sku.getStatus() == 0) {
|
||||||
|
//商品已禁用
|
||||||
|
throw exception(ErrorCodeConstants.SKU_DISABLE);
|
||||||
|
}
|
||||||
|
// 检查无限库存标志
|
||||||
|
if (sku.getStocksFlg() != null && sku.getStocksFlg() == 1) {
|
||||||
|
log.info("SKU {} 为无限库存,无需扣减", skuId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查库存是否充足
|
||||||
|
if (sku.getStocks() < stocksNum) {
|
||||||
|
throw new IllegalArgumentException("库存不足,当前库存:" + sku.getStocks() + ",需要:" + stocksNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扣减库存
|
||||||
|
int updateRows = skuMapper.reduceStocks(skuId, stocksNum, sku.getVersion());
|
||||||
|
|
||||||
|
if (updateRows == 0) {
|
||||||
|
// 可能是版本号冲突或库存不足
|
||||||
|
SkuDO currentSku = skuMapper.selectById(skuId);
|
||||||
|
if (currentSku.getStocks() < stocksNum) {
|
||||||
|
throw new IllegalArgumentException("库存不足,当前库存:" + sku.getStocks() + ",需要:" + stocksNum);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("扣减库存失败,请重试");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("扣减库存成功 - SKU: {}, 扣减数量: {}, 剩余库存: {}",skuId, stocksNum, sku.getStocks() - stocksNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void increaseStocks(Long skuId, Integer stocksNum) {
|
||||||
|
// 查询SKU信息
|
||||||
|
SkuDO sku = skuMapper.selectById(skuId);
|
||||||
|
// 检查无限库存标志
|
||||||
|
if (sku.getStocksFlg() != null && sku.getStocksFlg() == 1) {
|
||||||
|
log.info("SKU {} 为无限库存,无需增加", skuId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
skuMapper.increaseStocks(skuId, stocksNum);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user