共富接口修改
This commit is contained in:
1 parent
8647444e10
commit
0db2942043
12 files changed
+264
-244
No files matched your search
+11
-4
@@ -56,14 +56,12 @@ public interface RemoteMallProductService {
|
||||
/**
|
||||
* 购物车校验库存
|
||||
*
|
||||
* @param productId 商品ID(多SKU模式传SKU ID,单SPU模式传SPU ID)
|
||||
* @param productType 商品类型(1=SKU, 2=SPU)
|
||||
* @param skuId SKU ID
|
||||
* @param incrCount 扣减数量(正数或负数)
|
||||
* @return 库存是否充足
|
||||
*/
|
||||
@GetMapping("/mallProduct/checkStock")
|
||||
R<Boolean> checkStock(@RequestParam("productId") Long productId,
|
||||
@RequestParam("productType") Integer productType,
|
||||
R<Boolean> checkStock(@RequestParam("skuId") Long skuId,
|
||||
@RequestParam("incrCount") Double incrCount);
|
||||
|
||||
/**
|
||||
@@ -129,5 +127,14 @@ public interface RemoteMallProductService {
|
||||
*/
|
||||
@GetMapping("/mallProduct/listByIds")
|
||||
R<List<MallProductEntity>> getListByIds(@RequestParam("ids") List<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据SKU ID列表批量查询SKU和SPU信息
|
||||
*
|
||||
* @param skuIds SKU ID列表
|
||||
* @return SKU和SPU详情列表
|
||||
*/
|
||||
@GetMapping("/mallProduct/getSkusWithSpu")
|
||||
R<List<MallProductDetailAppVo>> getSkusWithSpuBySkuIds(@RequestParam("skuIds") List<Long> skuIds);
|
||||
}
|
||||
|
||||
+2
-5
@@ -27,16 +27,13 @@ public class MallProductStockChangeDTO {
|
||||
@Schema(description = "库存变更明细")
|
||||
public static class Item {
|
||||
|
||||
@NotNull(message = "商品ID不能为空(SPU或SKU ID)")
|
||||
@Schema(description = "商品ID(多SKU模式传SKU ID,单SPU模式传SPU ID)")
|
||||
@NotNull(message = "SKU ID不能为空")
|
||||
@Schema(description = "SKU ID")
|
||||
private Long id;
|
||||
|
||||
@NotNull(message = "库存变化数量不能为空")
|
||||
@Schema(description = "库存变化数量(正数增加,负数扣减)")
|
||||
private Double incrCount;
|
||||
|
||||
@Schema(description = "商品类型(1=SKU, 2=SPU)")
|
||||
private Integer productType;
|
||||
}
|
||||
}
|
||||
|
||||
-12
@@ -64,18 +64,6 @@ public class MallProductDetailAppVo {
|
||||
@Schema(description = "轮播图")
|
||||
private String carouselImages;
|
||||
|
||||
/**
|
||||
* 定价方式(1多SKU 2单价SPU)
|
||||
*/
|
||||
@Schema(description = "定价方式")
|
||||
private Integer priceType;
|
||||
|
||||
/**
|
||||
* SPU售价(单位:分)
|
||||
*/
|
||||
@Schema(description = "SPU售价(单位:分)")
|
||||
private Integer spuPrice;
|
||||
|
||||
/**
|
||||
* 划线价(单位:分)
|
||||
*/
|
||||
|
||||
+3
-21
@@ -43,12 +43,6 @@ public class MallProductListAppVo {
|
||||
@Schema(description = "副标题")
|
||||
private String subTitle;
|
||||
|
||||
/**
|
||||
* 品牌
|
||||
*/
|
||||
@Schema(description = "品牌")
|
||||
private String brand;
|
||||
|
||||
/**
|
||||
* 主图
|
||||
*/
|
||||
@@ -61,18 +55,6 @@ public class MallProductListAppVo {
|
||||
@Schema(description = "轮播图")
|
||||
private String carouselImages;
|
||||
|
||||
/**
|
||||
* 定价方式(1多SKU 2单价SPU)
|
||||
*/
|
||||
@Schema(description = "定价方式")
|
||||
private Integer priceType;
|
||||
|
||||
/**
|
||||
* SPU售价(单位:分)
|
||||
*/
|
||||
@Schema(description = "SPU售价(单位:分)")
|
||||
private Integer spuPrice;
|
||||
|
||||
/**
|
||||
* 划线价(单位:分)
|
||||
*/
|
||||
@@ -98,9 +80,9 @@ public class MallProductListAppVo {
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 最低价格(从SKU中计算,单位:分)
|
||||
* 零售价(从SKU中取最低价,单位:分)
|
||||
*/
|
||||
@Schema(description = "最低价格(单位:分)")
|
||||
private Integer minPrice;
|
||||
@Schema(description = "零售价")
|
||||
private Integer retailPrice;
|
||||
}
|
||||
|
||||
+110
-89
@@ -214,8 +214,9 @@ public class MallProductController {
|
||||
|
||||
/**
|
||||
* 批量扣减/增加库存(正数增加,负数扣减)
|
||||
* 统一通过SKU ID进行库存变更
|
||||
*/
|
||||
@Operation(summary = "批量扣减/增加库存", description = "批量扣减/增加库存")
|
||||
@Operation(summary = "批量扣减/增加库存", description = "批量扣减/增加库存(基于SKU ID)")
|
||||
@PostMapping("/deductStock")
|
||||
public R<Boolean> deductStock(@Valid @RequestBody MallProductStockChangeDTO changes) {
|
||||
try {
|
||||
@@ -224,43 +225,22 @@ public class MallProductController {
|
||||
}
|
||||
|
||||
for (MallProductStockChangeDTO.Item item : changes.getItems()) {
|
||||
if (item.getProductType() == null) {
|
||||
return R.failed("商品类型不能为空");
|
||||
// 统一使用SKU ID进行库存变更
|
||||
MallProductSkuEntity sku = mallProductSkuService.getById(item.getId());
|
||||
if (sku == null) {
|
||||
return R.failed("SKU不存在:" + item.getId());
|
||||
}
|
||||
|
||||
if (item.getProductType() == 1) {
|
||||
// SKU 模式:更新 SKU 库存
|
||||
MallProductSkuEntity sku = mallProductSkuService.getById(item.getId());
|
||||
if (sku == null) {
|
||||
return R.failed("SKU不存在:" + item.getId());
|
||||
}
|
||||
|
||||
Double newStock = (sku.getStock() != null ? sku.getStock() : 0D) + item.getIncrCount();
|
||||
if (newStock < 0) {
|
||||
return R.failed("SKU库存不足:" + sku.getSkuName());
|
||||
}
|
||||
|
||||
sku.setStock(newStock);
|
||||
mallProductSkuService.updateById(sku);
|
||||
|
||||
// 更新 SPU 总库存
|
||||
updateSpuTotalStock(sku.getProductId());
|
||||
|
||||
} else if (item.getProductType() == 2) {
|
||||
// SPU 模式:直接更新 SPU 总库存
|
||||
MallProductEntity product = mallProductService.getById(item.getId());
|
||||
if (product == null) {
|
||||
return R.failed("商品不存在:" + item.getId());
|
||||
}
|
||||
|
||||
Double newStock = (product.getTotalStock() != null ? product.getTotalStock() : 0D) + item.getIncrCount();
|
||||
if (newStock < 0) {
|
||||
return R.failed("商品库存不足:" + product.getTitle());
|
||||
}
|
||||
|
||||
product.setTotalStock(newStock);
|
||||
mallProductService.updateById(product);
|
||||
Double newStock = (sku.getStock() != null ? sku.getStock() : 0D) + item.getIncrCount();
|
||||
if (newStock < 0) {
|
||||
return R.failed("SKU库存不足:" + sku.getSkuName());
|
||||
}
|
||||
|
||||
sku.setStock(newStock);
|
||||
mallProductSkuService.updateById(sku);
|
||||
|
||||
// 更新 SPU 总库存
|
||||
updateSpuTotalStock(sku.getProductId());
|
||||
}
|
||||
|
||||
return R.ok(true);
|
||||
@@ -270,36 +250,20 @@ public class MallProductController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 购物车校验库存
|
||||
* 购物车校验库存(基于SKU ID)
|
||||
*/
|
||||
@Operation(summary = "购物车校验库存", description = "购物车校验库存")
|
||||
@Operation(summary = "购物车校验库存", description = "购物车校验库存(基于SKU ID)")
|
||||
@GetMapping("/checkStock")
|
||||
public R<Boolean> checkStock(@RequestParam("productId") Long productId,
|
||||
@RequestParam("productType") Integer productType,
|
||||
public R<Boolean> checkStock(@RequestParam("skuId") Long skuId,
|
||||
@RequestParam("incrCount") Double incrCount) {
|
||||
try {
|
||||
if (productType == 1) {
|
||||
// SKU 模式
|
||||
MallProductSkuEntity sku = mallProductSkuService.getById(productId);
|
||||
if (sku == null) {
|
||||
return R.ok(false);
|
||||
}
|
||||
|
||||
Double currentStock = sku.getStock() != null ? sku.getStock() : 0D;
|
||||
return R.ok(currentStock + incrCount >= 0);
|
||||
|
||||
} else if (productType == 2) {
|
||||
// SPU 模式
|
||||
MallProductEntity product = mallProductService.getById(productId);
|
||||
if (product == null) {
|
||||
return R.ok(false);
|
||||
}
|
||||
|
||||
Double currentStock = product.getTotalStock() != null ? product.getTotalStock() : 0D;
|
||||
return R.ok(currentStock + incrCount >= 0);
|
||||
MallProductSkuEntity sku = mallProductSkuService.getById(skuId);
|
||||
if (sku == null) {
|
||||
return R.ok(false);
|
||||
}
|
||||
|
||||
return R.failed("无效的商品类型");
|
||||
Double currentStock = sku.getStock() != null ? sku.getStock() : 0D;
|
||||
return R.ok(currentStock + incrCount >= 0);
|
||||
} catch (Exception e) {
|
||||
return R.failed("校验库存失败:" + e.getMessage());
|
||||
}
|
||||
@@ -363,6 +327,75 @@ public class MallProductController {
|
||||
return R.ok(mallProductService.listByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据SKU ID列表批量查询SKU和SPU信息
|
||||
*/
|
||||
@Operation(summary = "根据SKU ID列表批量查询SKU和SPU信息", description = "根据SKU ID列表批量查询SKU和SPU信息(包含完整SPU详情)")
|
||||
@GetMapping("/getSkusWithSpu")
|
||||
public R<List<MallProductDetailAppVo>> getSkusWithSpuBySkuIds(@RequestParam("skuIds") List<Long> skuIds) {
|
||||
try {
|
||||
if (CollUtil.isEmpty(skuIds)) {
|
||||
return R.ok(new java.util.ArrayList<>());
|
||||
}
|
||||
|
||||
// 1. 查询所有SKU
|
||||
List<MallProductSkuEntity> skuList = mallProductSkuService.listByIds(skuIds);
|
||||
if (CollUtil.isEmpty(skuList)) {
|
||||
return R.ok(new java.util.ArrayList<>());
|
||||
}
|
||||
|
||||
// 2. 获取所有关联的商品ID
|
||||
List<Long> productIds = skuList.stream()
|
||||
.map(MallProductSkuEntity::getProductId)
|
||||
.distinct()
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
// 3. 查询所有商品
|
||||
List<MallProductEntity> products = mallProductService.listByIds(productIds);
|
||||
|
||||
// 4. 按商品ID分组SKU
|
||||
java.util.Map<Long, List<MallProductSkuEntity>> skuMap = skuList.stream()
|
||||
.collect(java.util.stream.Collectors.groupingBy(MallProductSkuEntity::getProductId));
|
||||
|
||||
// 5. 组装结果(每个商品只包含查询的SKU,不是全部SKU)
|
||||
List<MallProductDetailAppVo> voList = products.stream()
|
||||
.map(product -> {
|
||||
MallProductDetailAppVo vo = new MallProductDetailAppVo();
|
||||
vo.setId(product.getId());
|
||||
vo.setMerchantId(product.getMerchantId());
|
||||
vo.setCategoryId(product.getCategoryId());
|
||||
vo.setTitle(product.getTitle());
|
||||
vo.setSubTitle(product.getSubTitle());
|
||||
vo.setBrand(product.getBrand());
|
||||
vo.setCoverImage(product.getCoverImage());
|
||||
vo.setCarouselImages(product.getCarouselImages());
|
||||
vo.setOriginalPrice(product.getOriginalPrice());
|
||||
vo.setTotalStock(product.getTotalStock());
|
||||
vo.setProductNature(product.getProductNature());
|
||||
vo.setStatus(product.getStatus());
|
||||
vo.setSaleStartTime(product.getSaleStartTime());
|
||||
vo.setSaleEndTime(product.getSaleEndTime());
|
||||
vo.setDescription(product.getDescription());
|
||||
|
||||
// 只包含请求的SKU
|
||||
List<MallProductSkuEntity> productSkus = skuMap.get(product.getId());
|
||||
if (CollUtil.isNotEmpty(productSkus)) {
|
||||
List<MallProductSkuAppVo> skuVoList = productSkus.stream()
|
||||
.map(this::convertToSkuVo)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
vo.setSkuList(skuVoList);
|
||||
}
|
||||
|
||||
return vo;
|
||||
})
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
return R.ok(voList);
|
||||
} catch (Exception e) {
|
||||
return R.failed("根据SKU ID查询商品失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 私有辅助方法 ====================
|
||||
|
||||
/**
|
||||
@@ -394,30 +427,22 @@ public class MallProductController {
|
||||
vo.setCategoryId(product.getCategoryId());
|
||||
vo.setTitle(product.getTitle());
|
||||
vo.setSubTitle(product.getSubTitle());
|
||||
vo.setBrand(product.getBrand());
|
||||
vo.setCoverImage(product.getCoverImage());
|
||||
vo.setCarouselImages(product.getCarouselImages());
|
||||
vo.setPriceType(product.getPriceType());
|
||||
vo.setSpuPrice(product.getSpuPrice());
|
||||
vo.setOriginalPrice(product.getOriginalPrice());
|
||||
vo.setTotalStock(product.getTotalStock());
|
||||
vo.setProductNature(product.getProductNature());
|
||||
vo.setStatus(product.getStatus());
|
||||
|
||||
// 如果是多SKU模式,计算最低价格
|
||||
if (product.getPriceType() != null && product.getPriceType() == 1) {
|
||||
List<MallProductSkuEntity> skuList = mallProductSkuService.list(
|
||||
Wrappers.<MallProductSkuEntity>lambdaQuery()
|
||||
.eq(MallProductSkuEntity::getProductId, product.getId())
|
||||
.orderByAsc(MallProductSkuEntity::getPrice)
|
||||
);
|
||||
|
||||
if (CollUtil.isNotEmpty(skuList)) {
|
||||
vo.setMinPrice(skuList.get(0).getPrice());
|
||||
}
|
||||
} else {
|
||||
// 单SPU模式,最低价格就是SPU价格
|
||||
vo.setMinPrice(product.getSpuPrice());
|
||||
// 查询SKU列表,获取零售价(取最低价格的SKU)
|
||||
List<MallProductSkuEntity> skuList = mallProductSkuService.list(
|
||||
Wrappers.<MallProductSkuEntity>lambdaQuery()
|
||||
.eq(MallProductSkuEntity::getProductId, product.getId())
|
||||
.orderByAsc(MallProductSkuEntity::getPrice)
|
||||
);
|
||||
|
||||
if (CollUtil.isNotEmpty(skuList)) {
|
||||
vo.setRetailPrice(skuList.get(0).getPrice());
|
||||
}
|
||||
|
||||
return vo;
|
||||
@@ -436,8 +461,6 @@ public class MallProductController {
|
||||
vo.setBrand(product.getBrand());
|
||||
vo.setCoverImage(product.getCoverImage());
|
||||
vo.setCarouselImages(product.getCarouselImages());
|
||||
vo.setPriceType(product.getPriceType());
|
||||
vo.setSpuPrice(product.getSpuPrice());
|
||||
vo.setOriginalPrice(product.getOriginalPrice());
|
||||
vo.setTotalStock(product.getTotalStock());
|
||||
vo.setProductNature(product.getProductNature());
|
||||
@@ -446,18 +469,16 @@ public class MallProductController {
|
||||
vo.setSaleEndTime(product.getSaleEndTime());
|
||||
vo.setDescription(product.getDescription());
|
||||
|
||||
// 如果是多SKU模式,查询SKU列表
|
||||
if (product.getPriceType() != null && product.getPriceType() == 1) {
|
||||
List<MallProductSkuEntity> skuList = mallProductSkuService.list(
|
||||
Wrappers.<MallProductSkuEntity>lambdaQuery()
|
||||
.eq(MallProductSkuEntity::getProductId, product.getId())
|
||||
);
|
||||
// 查询SKU列表
|
||||
List<MallProductSkuEntity> skuList = mallProductSkuService.list(
|
||||
Wrappers.<MallProductSkuEntity>lambdaQuery()
|
||||
.eq(MallProductSkuEntity::getProductId, product.getId())
|
||||
);
|
||||
|
||||
List<MallProductSkuAppVo> skuVoList = skuList.stream()
|
||||
.map(this::convertToSkuVo)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
vo.setSkuList(skuVoList);
|
||||
}
|
||||
List<MallProductSkuAppVo> skuVoList = skuList.stream()
|
||||
.map(this::convertToSkuVo)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
vo.setSkuList(skuVoList);
|
||||
|
||||
return vo;
|
||||
}
|
||||
|
||||
+22
-4
@@ -12,6 +12,7 @@ import com.bsd.pjcloud.common.excel.annotation.RequestExcel;
|
||||
import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
|
||||
import com.bsd.pjcloud.common.log.annotation.SysLog;
|
||||
import com.bsd.pjcloud.common.security.util.SecurityUtils;
|
||||
import com.bsd.pjcloud.supermarket.dto.StockWarnQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuAppQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockByCodeReqDTO;
|
||||
@@ -222,17 +223,34 @@ public class SmErpSpuController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* 分页查询库存预警
|
||||
* @param page 分页对象
|
||||
* @param supermarketSpu 商品spu
|
||||
* @param queryDTO 查询条件
|
||||
* @return
|
||||
*/
|
||||
@Operation(summary = "分页查询库存预警" , description = "分页查询库存预警" )
|
||||
@GetMapping("/warnStock/page" )
|
||||
@PreAuthorize("@pms.hasPermission('supermarket_supermarketSpu_view')" )
|
||||
public R getWarnStockPage(@ParameterObject Page page, @ParameterObject SmErpSpuEntity supermarketSpu) {
|
||||
public R getWarnStockPage(@ParameterObject Page page, @ParameterObject StockWarnQueryDTO queryDTO) {
|
||||
// 调试日志:打印查询参数
|
||||
System.out.println("========== 库存预警查询参数 ==========");
|
||||
System.out.println("分页参数 - current: " + page.getCurrent() + ", size: " + page.getSize());
|
||||
if (queryDTO != null) {
|
||||
System.out.println("warnType: " + queryDTO.getWarnType() + " (类型: " + (queryDTO.getWarnType() != null ? queryDTO.getWarnType().getClass().getName() : "null") + ")");
|
||||
System.out.println("warnType.equals(\"1\"): " + (queryDTO.getWarnType() != null && queryDTO.getWarnType().equals("1")));
|
||||
System.out.println("warnType == \"1\": " + (queryDTO.getWarnType() != null && queryDTO.getWarnType() == "1"));
|
||||
System.out.println("barcode: " + queryDTO.getBarcode());
|
||||
System.out.println("productCode: " + queryDTO.getProductCode());
|
||||
System.out.println("productName: " + queryDTO.getProductName());
|
||||
System.out.println("categoryId: " + queryDTO.getCategoryId());
|
||||
} else {
|
||||
System.out.println("queryDTO is NULL!");
|
||||
}
|
||||
System.out.println("======================================");
|
||||
|
||||
IPage iPage = smErpStockService.selectWarnStockWithSpu(page, supermarketSpu);
|
||||
IPage iPage = smErpStockService.selectWarnStockWithSpu(page, queryDTO);
|
||||
|
||||
System.out.println("查询结果数量: " + iPage.getRecords().size() + " / 总数: " + iPage.getTotal());
|
||||
|
||||
return R.ok(iPage);
|
||||
|
||||
|
||||
+4
-17
@@ -72,19 +72,6 @@ public class MallProductCreateDTO {
|
||||
@Schema(description = "SPU轮播图URL(逗号分隔,按顺序)")
|
||||
private String carouselImages;
|
||||
|
||||
/**
|
||||
* 定价方式(1多SKU 2单价SPU)
|
||||
*/
|
||||
@NotNull(message = "定价方式不能为空")
|
||||
@Schema(description = "定价方式(1多SKU 2单价SPU)")
|
||||
private Integer priceType;
|
||||
|
||||
/**
|
||||
* SPU售价(当price_type=2有效)
|
||||
*/
|
||||
@Schema(description = "SPU售价(当price_type=2有效)")
|
||||
private Integer spuPrice;
|
||||
|
||||
/**
|
||||
* 划线价
|
||||
*/
|
||||
@@ -92,13 +79,13 @@ public class MallProductCreateDTO {
|
||||
private Integer originalPrice;
|
||||
|
||||
/**
|
||||
* 总库存(冗余)
|
||||
* 总库存(冗余,由SKU汇总计算)
|
||||
*/
|
||||
@Schema(description = "总库存(冗余)")
|
||||
@Schema(description = "总库存(冗余,由SKU汇总计算)")
|
||||
private Double totalStock;
|
||||
|
||||
/**
|
||||
* 计量单位
|
||||
* 商品性质
|
||||
*/
|
||||
@Schema(description = "商品性质")
|
||||
private String productNature;
|
||||
@@ -130,7 +117,7 @@ public class MallProductCreateDTO {
|
||||
|
||||
|
||||
/**
|
||||
* SKU列表(当priceType=1时必填)
|
||||
* SKU列表(可选,单个商品一条SKU,多规格商品多条SKU)
|
||||
*/
|
||||
@Valid
|
||||
@Schema(description = "SKU列表")
|
||||
|
||||
+3
-4
@@ -3,11 +3,10 @@ package com.bsd.pjcloud.supermarket.mapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
|
||||
import com.bsd.pjcloud.supermarket.dto.inventoryrecords.UpdateStockDTO;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSpuEntity;
|
||||
import com.bsd.pjcloud.supermarket.dto.StockWarnQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpStockEntity;
|
||||
import com.bsd.pjcloud.supermarket.vo.stockwarn.StockWarnVO;
|
||||
import com.github.houbb.heaven.annotation.reflect.Param;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
@@ -16,7 +15,7 @@ import java.util.List;
|
||||
public interface SmErpStockMapper extends PjcloudBaseMapper<SmErpStockEntity> {
|
||||
|
||||
|
||||
IPage<StockWarnVO> selectWarnStockWithSpu(Page<SmErpStockEntity> page, @Param("param") SmErpSpuEntity param);
|
||||
IPage<StockWarnVO> selectWarnStockWithSpu(Page<SmErpStockEntity> page, @Param("query") StockWarnQueryDTO query);
|
||||
|
||||
|
||||
}
|
||||
+2
-2
@@ -3,8 +3,8 @@ package com.bsd.pjcloud.supermarket.service;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.bsd.pjcloud.supermarket.dto.StockWarnQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.inventoryrecords.UpdateStockDTO;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSpuEntity;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpStockEntity;
|
||||
import com.bsd.pjcloud.supermarket.vo.stockwarn.StockWarnVO;
|
||||
import com.github.houbb.heaven.annotation.reflect.Param;
|
||||
@@ -15,7 +15,7 @@ public interface SmErpStockService extends IService<SmErpStockEntity> {
|
||||
|
||||
|
||||
|
||||
IPage<StockWarnVO> selectWarnStockWithSpu(Page<SmErpStockEntity> page,SmErpSpuEntity param);
|
||||
IPage<StockWarnVO> selectWarnStockWithSpu(Page<SmErpStockEntity> page, StockWarnQueryDTO queryDTO);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+32
-69
@@ -38,6 +38,7 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
public boolean createProductWithSkus(MallProductCreateDTO productCreateDTO) {
|
||||
// 业务验证
|
||||
validateProductData(productCreateDTO);
|
||||
|
||||
// 1. 创建SPU
|
||||
MallProductEntity product = new MallProductEntity();
|
||||
product.setMerchantId(productCreateDTO.getMerchantId());
|
||||
@@ -47,8 +48,6 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
product.setBrand(productCreateDTO.getBrand());
|
||||
product.setCoverImage(productCreateDTO.getCoverImage());
|
||||
product.setCarouselImages(productCreateDTO.getCarouselImages());
|
||||
product.setPriceType(productCreateDTO.getPriceType());
|
||||
product.setSpuPrice(productCreateDTO.getSpuPrice());
|
||||
product.setOriginalPrice(productCreateDTO.getOriginalPrice());
|
||||
product.setProductNature(productCreateDTO.getProductNature());
|
||||
product.setStatus(productCreateDTO.getStatus());
|
||||
@@ -62,9 +61,8 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
throw new RuntimeException("保存商品SPU失败");
|
||||
}
|
||||
|
||||
// 3. 处理SKU
|
||||
if (productCreateDTO.getPriceType() == 1 && CollUtil.isNotEmpty(productCreateDTO.getSkuList())) {
|
||||
// 多SKU模式,保存SKU列表
|
||||
// 3. 处理SKU(如果有)
|
||||
if (CollUtil.isNotEmpty(productCreateDTO.getSkuList())) {
|
||||
List<MallProductSkuEntity> skuList = productCreateDTO.getSkuList().stream()
|
||||
.map(skuDTO -> {
|
||||
MallProductSkuEntity sku = new MallProductSkuEntity();
|
||||
@@ -93,21 +91,9 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
.sum();
|
||||
product.setTotalStock(totalStock);
|
||||
this.updateById(product);
|
||||
} else if (productCreateDTO.getPriceType() == 2) {
|
||||
// 单价SPU模式,使用前端传入的totalStock
|
||||
Double totalStock = productCreateDTO.getTotalStock();
|
||||
if (totalStock == null) {
|
||||
totalStock = 0D; // 如果没有传入,默认为0
|
||||
}
|
||||
product.setTotalStock(totalStock);
|
||||
this.updateById(product);
|
||||
} else {
|
||||
// 没有SKU信息,使用前端传入的totalStock或默认为0
|
||||
Double totalStock = productCreateDTO.getTotalStock();
|
||||
if (totalStock == null) {
|
||||
totalStock = 0D;
|
||||
}
|
||||
product.setTotalStock(totalStock);
|
||||
// 没有SKU,总库存为0
|
||||
product.setTotalStock(0D);
|
||||
this.updateById(product);
|
||||
}
|
||||
|
||||
@@ -134,8 +120,6 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
product.setBrand(productCreateDTO.getBrand());
|
||||
product.setCoverImage(productCreateDTO.getCoverImage());
|
||||
product.setCarouselImages(productCreateDTO.getCarouselImages());
|
||||
product.setPriceType(productCreateDTO.getPriceType());
|
||||
product.setSpuPrice(productCreateDTO.getSpuPrice());
|
||||
product.setOriginalPrice(productCreateDTO.getOriginalPrice());
|
||||
product.setProductNature(productCreateDTO.getProductNature());
|
||||
product.setStatus(productCreateDTO.getStatus());
|
||||
@@ -149,9 +133,8 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
throw new RuntimeException("更新商品SPU失败");
|
||||
}
|
||||
|
||||
// 3. 处理SKU
|
||||
if (productCreateDTO.getPriceType() == 1 && CollUtil.isNotEmpty(productCreateDTO.getSkuList())) {
|
||||
// 多SKU模式,精确处理SKU的增删改
|
||||
// 3. 处理SKU(精确处理SKU的增删改)
|
||||
if (CollUtil.isNotEmpty(productCreateDTO.getSkuList())) {
|
||||
updateSkusForProduct(product.getId(), productCreateDTO.getSkuList());
|
||||
|
||||
// 计算总库存
|
||||
@@ -165,17 +148,12 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
product.setTotalStock(totalStock);
|
||||
this.updateById(product);
|
||||
} else {
|
||||
// 单价SPU模式或没有SKU信息,删除所有SKU
|
||||
// 没有SKU信息,删除所有SKU
|
||||
LambdaQueryWrapper<MallProductSkuEntity> deleteWrapper = Wrappers.lambdaQuery();
|
||||
deleteWrapper.eq(MallProductSkuEntity::getProductId, product.getId());
|
||||
mallProductSkuService.remove(deleteWrapper);
|
||||
|
||||
// 使用前端传入的totalStock
|
||||
Double totalStock = productCreateDTO.getTotalStock();
|
||||
if (totalStock == null) {
|
||||
totalStock = 0D; // 如果没有传入,默认为0
|
||||
}
|
||||
product.setTotalStock(totalStock);
|
||||
product.setTotalStock(0D);
|
||||
this.updateById(product);
|
||||
}
|
||||
|
||||
@@ -293,8 +271,6 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
dto.setBrand(product.getBrand());
|
||||
dto.setCoverImage(product.getCoverImage());
|
||||
dto.setCarouselImages(product.getCarouselImages());
|
||||
dto.setPriceType(product.getPriceType());
|
||||
dto.setSpuPrice(product.getSpuPrice());
|
||||
dto.setOriginalPrice(product.getOriginalPrice());
|
||||
dto.setTotalStock(product.getTotalStock());
|
||||
dto.setProductNature(product.getProductNature());
|
||||
@@ -304,29 +280,27 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
dto.setDescription(product.getDescription());
|
||||
|
||||
// 3. 获取SKU信息
|
||||
if (product.getPriceType() == 1) {
|
||||
LambdaQueryWrapper<MallProductSkuEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(MallProductSkuEntity::getProductId, id);
|
||||
List<MallProductSkuEntity> skuList = mallProductSkuService.list(wrapper);
|
||||
|
||||
List<MallProductSkuCreateDTO> skuDTOList = skuList.stream()
|
||||
.map(sku -> {
|
||||
MallProductSkuCreateDTO skuDTO = new MallProductSkuCreateDTO();
|
||||
skuDTO.setSkuCode(sku.getSkuCode());
|
||||
skuDTO.setSkuName(sku.getSkuName());
|
||||
skuDTO.setPrice(sku.getPrice());
|
||||
skuDTO.setCostPrice(sku.getCostPrice());
|
||||
skuDTO.setStock(sku.getStock());
|
||||
skuDTO.setBarcode(sku.getBarcode());
|
||||
skuDTO.setWeightG(sku.getWeightG());
|
||||
skuDTO.setVolumeCm3(sku.getVolumeCm3());
|
||||
skuDTO.setStatus(sku.getStatus());
|
||||
return skuDTO;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
dto.setSkuList(skuDTOList);
|
||||
}
|
||||
LambdaQueryWrapper<MallProductSkuEntity> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(MallProductSkuEntity::getProductId, id);
|
||||
List<MallProductSkuEntity> skuList = mallProductSkuService.list(wrapper);
|
||||
|
||||
List<MallProductSkuCreateDTO> skuDTOList = skuList.stream()
|
||||
.map(sku -> {
|
||||
MallProductSkuCreateDTO skuDTO = new MallProductSkuCreateDTO();
|
||||
skuDTO.setSkuCode(sku.getSkuCode());
|
||||
skuDTO.setSkuName(sku.getSkuName());
|
||||
skuDTO.setPrice(sku.getPrice());
|
||||
skuDTO.setCostPrice(sku.getCostPrice());
|
||||
skuDTO.setStock(sku.getStock());
|
||||
skuDTO.setBarcode(sku.getBarcode());
|
||||
skuDTO.setWeightG(sku.getWeightG());
|
||||
skuDTO.setVolumeCm3(sku.getVolumeCm3());
|
||||
skuDTO.setStatus(sku.getStatus());
|
||||
return skuDTO;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
dto.setSkuList(skuDTOList);
|
||||
|
||||
return dto;
|
||||
}
|
||||
@@ -336,12 +310,8 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
* @param productCreateDTO 商品创建DTO
|
||||
*/
|
||||
private void validateProductData(MallProductCreateDTO productCreateDTO) {
|
||||
// 多SKU模式验证
|
||||
if (productCreateDTO.getPriceType() == 1) {
|
||||
if (CollUtil.isEmpty(productCreateDTO.getSkuList())) {
|
||||
throw new RuntimeException("多SKU模式下必须提供SKU列表");
|
||||
}
|
||||
|
||||
// 如果有SKU,验证SKU数据
|
||||
if (CollUtil.isNotEmpty(productCreateDTO.getSkuList())) {
|
||||
// 验证SKU编码在当前请求中的唯一性
|
||||
long distinctSkuCodes = productCreateDTO.getSkuList().stream()
|
||||
.map(MallProductSkuCreateDTO::getSkuCode)
|
||||
@@ -368,12 +338,5 @@ public class MallProductServiceImpl extends ServiceImpl<MallProductMapper, MallP
|
||||
throw new RuntimeException("SKU编码已存在,请使用不同的编码");
|
||||
}
|
||||
}
|
||||
|
||||
// 单价SPU模式验证
|
||||
if (productCreateDTO.getPriceType() == 2) {
|
||||
if (productCreateDTO.getSpuPrice() == null || productCreateDTO.getSpuPrice() <= 0) {
|
||||
throw new RuntimeException("单价SPU模式下必须设置有效的SPU价格");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
-3
@@ -4,9 +4,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bsd.pjcloud.supermarket.dto.StockWarnQueryDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.inventoryrecords.InventoryRecordSaveItemDTO;
|
||||
import com.bsd.pjcloud.supermarket.dto.inventoryrecords.UpdateStockDTO;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpSpuEntity;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpStockEntity;
|
||||
import com.bsd.pjcloud.supermarket.entity.SmErpUnitEntity;
|
||||
import com.bsd.pjcloud.supermarket.mapper.SmErpSpuMapper;
|
||||
@@ -39,8 +39,50 @@ public class SmErpStockServiceImpl extends ServiceImpl<SmErpStockMapper, SmErpSt
|
||||
|
||||
|
||||
@Override
|
||||
public IPage<StockWarnVO> selectWarnStockWithSpu(Page<SmErpStockEntity> page, SmErpSpuEntity param) {
|
||||
return baseMapper.selectWarnStockWithSpu(page, param);
|
||||
public IPage<StockWarnVO> selectWarnStockWithSpu(Page<SmErpStockEntity> page, StockWarnQueryDTO queryDTO) {
|
||||
// 如果有 warnType 参数,需要特殊处理分页
|
||||
if (queryDTO != null && queryDTO.getWarnType() != null && !queryDTO.getWarnType().isEmpty()) {
|
||||
String targetWarnType = queryDTO.getWarnType();
|
||||
|
||||
// 创建一个临时的查询对象,不带 warnType(查询所有预警数据)
|
||||
StockWarnQueryDTO tempQuery = new StockWarnQueryDTO();
|
||||
tempQuery.setProductCode(queryDTO.getProductCode());
|
||||
tempQuery.setBarcode(queryDTO.getBarcode());
|
||||
tempQuery.setProductName(queryDTO.getProductName());
|
||||
tempQuery.setCategoryId(queryDTO.getCategoryId());
|
||||
tempQuery.setWarnType(null); // 设为 null,查询所有预警
|
||||
|
||||
// 查询所有预警数据(不分页,用大分页)
|
||||
Page<SmErpStockEntity> bigPage = new Page<>(1, 100000);
|
||||
IPage<StockWarnVO> allResult = baseMapper.selectWarnStockWithSpu(bigPage, tempQuery);
|
||||
|
||||
// 在内存中筛选指定的 warnType
|
||||
List<StockWarnVO> filteredList = allResult.getRecords().stream()
|
||||
.filter(vo -> targetWarnType.equals(vo.getWarnType()))
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
System.out.println("所有预警数量: " + allResult.getRecords().size() +
|
||||
", warnType=" + targetWarnType + " 的数量: " + filteredList.size());
|
||||
|
||||
// 手动分页
|
||||
int total = filteredList.size();
|
||||
int pageSize = (int) page.getSize();
|
||||
int current = (int) page.getCurrent();
|
||||
int fromIndex = (current - 1) * pageSize;
|
||||
int toIndex = Math.min(fromIndex + pageSize, total);
|
||||
|
||||
List<StockWarnVO> pagedList = (fromIndex < total)
|
||||
? filteredList.subList(fromIndex, toIndex)
|
||||
: new java.util.ArrayList<>();
|
||||
|
||||
Page<StockWarnVO> resultPage = new Page<>(current, pageSize, total);
|
||||
resultPage.setRecords(pagedList);
|
||||
|
||||
return resultPage;
|
||||
} else {
|
||||
// 没有 warnType 参数,直接查询所有预警
|
||||
return baseMapper.selectWarnStockWithSpu(page, queryDTO);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+30
-14
@@ -23,6 +23,7 @@
|
||||
<id column="id" property="id"/>
|
||||
<result column="inventory_upper_limit" property="inventoryUpperLimit"/>
|
||||
<result column="inventory_lower_limit" property="inventoryLowerLimit"/>
|
||||
<result column="stock" property="stock"/>
|
||||
|
||||
<!-- 预警类型计算字段 -->
|
||||
<result column="warn_type" property="warnType"/>
|
||||
@@ -30,17 +31,24 @@
|
||||
<!-- SPU表关联字段 -->
|
||||
<result column="product_code" property="productCode"/>
|
||||
<result column="product_name" property="productName"/>
|
||||
<result column="barcode" property="barcode"/>
|
||||
<result column="spec" property="spec"/>
|
||||
<result column="unit" property="unit"/>
|
||||
<result column="package_num" property="packageNum"/>
|
||||
<result column="pic_url" property="picUrl"/>
|
||||
<result column="category_id" property="categoryId"/>
|
||||
|
||||
<!-- 包装单位表关联字段 -->
|
||||
<result column="barcode" property="barCode"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectWarnStockWithSpu" resultMap="stockWarnResultMap">
|
||||
SELECT
|
||||
SELECT DISTINCT
|
||||
stock.inventory_upper_limit,
|
||||
stock.inventory_lower_limit,
|
||||
stock.current_stock as stock,
|
||||
spu.product_code,
|
||||
spu.product_name,
|
||||
spu.bar_code,
|
||||
(SELECT bar_code FROM sm_erp_unit WHERE spu_id = spu.id AND is_base = 1 LIMIT 1) as barcode,
|
||||
spu.spec,
|
||||
spu.unit,
|
||||
spu.package_num,
|
||||
@@ -48,23 +56,31 @@
|
||||
spu.category_id,
|
||||
spu.id,
|
||||
CASE
|
||||
WHEN (stock.current_stock) > stock.inventory_upper_limit THEN '2'
|
||||
ELSE '1'
|
||||
WHEN stock.current_stock < stock.inventory_lower_limit THEN '1'
|
||||
WHEN stock.current_stock > stock.inventory_upper_limit THEN '2'
|
||||
ELSE NULL
|
||||
END AS warn_type
|
||||
FROM sm_erp_stock stock
|
||||
LEFT JOIN sm_erp_spu spu ON stock.erp_spu_id = spu.id
|
||||
<where>
|
||||
<!-- 库存预警条件 -->
|
||||
(stock.current_stock) < stock.inventory_lower_limit or ( stock.current_stock) > stock.inventory_upper_limit
|
||||
|
||||
<if test="param.productCode != null and param.productCode != ''">
|
||||
AND spu.product_code = #{param.productCode}
|
||||
(stock.current_stock < stock.inventory_lower_limit OR stock.current_stock > stock.inventory_upper_limit)
|
||||
|
||||
<if test="query != null and query.productCode != null and query.productCode != ''">
|
||||
AND spu.product_code LIKE CONCAT('%', #{query.productCode}, '%')
|
||||
</if>
|
||||
<if test="param.barcode != null and param.barcode != ''">
|
||||
AND spu.bar_code = #{param.barCode}
|
||||
<if test="query != null and query.barcode != null and query.barcode != ''">
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM sm_erp_unit u
|
||||
WHERE u.spu_id = spu.id
|
||||
AND u.is_base = 1
|
||||
AND u.bar_code = #{query.barcode}
|
||||
)
|
||||
</if>
|
||||
<if test="param.productName != null and param.productName != ''">
|
||||
AND spu.product_name LIKE CONCAT('%', #{param.productName}, '%')
|
||||
<if test="query != null and query.productName != null and query.productName != ''">
|
||||
AND spu.product_name LIKE CONCAT('%', #{query.productName}, '%')
|
||||
</if>
|
||||
<if test="query != null and query.categoryId != null">
|
||||
AND spu.category_id = #{query.categoryId}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY stock.id DESC
|
||||
|
||||
Reference in new issue
Block a user