From 720937581f6fa3472896cfa62ca705afa5cd63cd Mon Sep 17 00:00:00 2001 From: xuelijun <977662702@qq.com> Date: Fri, 31 Oct 2025 15:16:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BA=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cloud/productapi/api/product/ProdApi.java | 16 +++++ .../productapi/enums/ErrorCodeConstants.java | 6 ++ .../tashow/cloud/product/api/ProdImpl.java | 18 ++++++ .../controller/admin/ProdController.java | 22 +++++++ .../cloud/product/mapper/SkuMapper.java | 22 +++++++ .../cloud/product/service/SkuService.java | 12 ++++ .../product/service/impl/SkuServiceImpl.java | 58 +++++++++++++++++++ 7 files changed, 154 insertions(+) diff --git a/tashow-feign/tashow-product-api/src/main/java/com/tashow/cloud/productapi/api/product/ProdApi.java b/tashow-feign/tashow-product-api/src/main/java/com/tashow/cloud/productapi/api/product/ProdApi.java index 6756d87..3969302 100644 --- a/tashow-feign/tashow-product-api/src/main/java/com/tashow/cloud/productapi/api/product/ProdApi.java +++ b/tashow-feign/tashow-product-api/src/main/java/com/tashow/cloud/productapi/api/product/ProdApi.java @@ -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 getProdPage(ProdPageReqVO pageReqVO); + /** + * 扣减库存 + * @param skuId 单品ID + * @param stocksNum 扣减数量 + */ + @GetMapping(PREFIX + "/reduceStocks") + CommonResult reduceStocks(Long skuId, Integer stocksNum) ; + /** + * 增加库存 + * @param skuId 单品ID + * @param stocksNum 增加数量 + */ + @GetMapping(PREFIX + "/increaseStocks") + CommonResult increaseStocks(Long skuId, Integer stocksNum); + } diff --git a/tashow-feign/tashow-product-api/src/main/java/com/tashow/cloud/productapi/enums/ErrorCodeConstants.java b/tashow-feign/tashow-product-api/src/main/java/com/tashow/cloud/productapi/enums/ErrorCodeConstants.java index 7f26c2e..bef3f11 100644 --- a/tashow-feign/tashow-product-api/src/main/java/com/tashow/cloud/productapi/enums/ErrorCodeConstants.java +++ b/tashow-feign/tashow-product-api/src/main/java/com/tashow/cloud/productapi/enums/ErrorCodeConstants.java @@ -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, "商品已禁用"); + + } diff --git a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/api/ProdImpl.java b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/api/ProdImpl.java index 9636a77..37cc5ba 100644 --- a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/api/ProdImpl.java +++ b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/api/ProdImpl.java @@ -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 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 reduceStocks(Long skuId, Integer stocksNum) { + skuService.reduceStocks(skuId, stocksNum); + return success(true); + } + + @Override + public CommonResult increaseStocks(Long skuId, Integer stocksNum) { + skuService.increaseStocks(skuId, stocksNum); + return success(true); + } + } diff --git a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/controller/admin/ProdController.java b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/controller/admin/ProdController.java index f68a7c4..6ce871d 100644 --- a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/controller/admin/ProdController.java +++ b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/controller/admin/ProdController.java @@ -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 reduceStocks(@RequestParam("skuid") Long skuId, + @RequestParam("stocksNum") Integer stocksNum) { + skuService.reduceStocks(skuId, stocksNum); + return success(true); + } + + @PostMapping("/increaseStocks") + @Operation(summary = "增加库存") + @PermitAll + public CommonResult increaseStocks(@RequestParam("skuid") Long skuId, + @RequestParam("stocksNum") Integer stocksNum) { + skuService.increaseStocks(skuId, stocksNum); + return success(true); + } + + } \ No newline at end of file diff --git a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/mapper/SkuMapper.java b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/mapper/SkuMapper.java index c5f8c97..05b1047 100644 --- a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/mapper/SkuMapper.java +++ b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/mapper/SkuMapper.java @@ -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 { // 查询商品下所有 SKU 的 is_shelf 状态(未删除) List 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); } \ No newline at end of file diff --git a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/service/SkuService.java b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/service/SkuService.java index ce7375f..791eba5 100644 --- a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/service/SkuService.java +++ b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/service/SkuService.java @@ -175,5 +175,17 @@ public interface SkuService { * @param skuServiceDeliverList 更新信息 */ void updateDeliver(List skuServiceDeliverList); + /** + * 扣减库存 + * @param skuId 单品ID + * @param stocksNum 扣减数量 + */ + void reduceStocks(Long skuId, Integer stocksNum); + /** + * 增加库存 + * @param skuId 单品ID + * @param stocksNum 增加数量 + */ + void increaseStocks(Long skuId, Integer stocksNum); } \ No newline at end of file diff --git a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/service/impl/SkuServiceImpl.java b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/service/impl/SkuServiceImpl.java index 29dc99d..7b6e4b9 100644 --- a/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/service/impl/SkuServiceImpl.java +++ b/tashow-module/tashow-module-product/src/main/java/com/tashow/cloud/product/service/impl/SkuServiceImpl.java @@ -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); + } } \ No newline at end of file