This commit is contained in:
xuelijun
2025-10-31 15:16:15 +08:00
parent 261a8b4797
commit 720937581f
7 changed files with 154 additions and 0 deletions

View File

@@ -10,6 +10,7 @@ import com.tashow.cloud.productapi.enums.ApiConstants;
import jakarta.annotation.security.PermitAll;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = ApiConstants.NAME) // TODO 芋艿fallbackFactory =
@@ -46,5 +47,20 @@ public interface ProdApi {
@GetMapping(PREFIX + "/getProdPage")
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);
}

View File

@@ -32,4 +32,10 @@ public interface ErrorCodeConstants {
ErrorCode SKU_SERVICES_FORM_NOT_EXISTS = new ErrorCode(10021, "商品SKU扩展服务表单不存在");
ErrorCode SKU_SERVICE_TRANSPORT_NOT_EXISTS = new ErrorCode(10022, "服务遗体运输不存在");
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, "商品已禁用");
}

View File

@@ -3,6 +3,7 @@ package com.tashow.cloud.product.api;
import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult;
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.dto.ProdDO;
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.web.bind.annotation.RestController;
import static com.tashow.cloud.common.pojo.CommonResult.success;
@RestController // 提供 RESTful API 接口,给 Feign 调用
@Validated
public class ProdImpl implements ProdApi {
@@ -19,6 +22,9 @@ public class ProdImpl implements ProdApi {
@Resource
private ProdService prodService;
@Resource
private SkuService skuService;
@Override
public CommonResult<ProdDO> getProdInfo(Long id) {
return CommonResult.success(prodService.getProd(id));
@@ -34,4 +40,16 @@ public class ProdImpl implements ProdApi {
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);
}
}

View File

@@ -4,6 +4,7 @@ import com.tashow.cloud.common.pojo.CommonResult;
import com.tashow.cloud.common.pojo.PageResult;
import com.tashow.cloud.product.mapper.ProdMapper;
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.vo.prod.*;
import com.tashow.cloud.productapi.enums.BaseEnum;
@@ -30,6 +31,8 @@ public class ProdController {
@Resource
private ProdService prodService;
@Resource
private SkuService skuService;
@Resource
private ProdMapper prodMapper;
@PostMapping("/create")
@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);
}
}

View File

@@ -9,6 +9,7 @@ import com.tashow.cloud.productapi.api.product.dto.SkuDO;
import com.tashow.cloud.productapi.api.product.vo.sku.SkuRecycleBinVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
/**
* 单品SKU Mapper
@@ -44,4 +45,25 @@ public interface SkuMapper extends BaseMapperX<SkuDO> {
// 查询商品下所有 SKU 的 is_shelf 状态(未删除)
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);
}

View File

@@ -175,5 +175,17 @@ public interface SkuService {
* @param 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);
}

View File

@@ -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.ErrorCodeConstants;
import com.tashow.cloud.productapi.enums.ServiceTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
@@ -41,6 +42,7 @@ import static com.tashow.cloud.common.exception.util.ServiceExceptionUtil.except
*/
@Service
@Validated
@Slf4j
public class SkuServiceImpl implements SkuService {
@Resource
@@ -967,6 +969,62 @@ public class SkuServiceImpl implements SkuService {
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);
}
}