refactor(goods): 优化商品 SKU 处理逻辑

- 新增 SkuBo 主键字段,用于更新操作
- 优化商品保存逻辑,支持新增和更新 SKU
- 新增 SKU 获取接口,按商品 ID 查询
-调整商品查询结果,使用别名区分 SKU 字段
This commit is contained in:
huk 2025-09-19 14:53:58 +08:00
parent 1a859a9337
commit 1ee5c31022
6 changed files with 83 additions and 22 deletions

View File

@ -6,6 +6,7 @@ import com.wzj.soopin.goods.domain.bo.ProductCategoryBo;
import com.wzj.soopin.goods.domain.entity.ProductCategory;
import com.wzj.soopin.goods.domain.vo.ProductCategoryVO;
import com.wzj.soopin.goods.service.impl.ProductCategoryServiceImpl;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
@ -16,7 +17,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Tag(name ="商品分类接口列表")
@Tag(name ="商品分类")
@RestController
@RequestMapping("/app/product/category")
@RequiredArgsConstructor
@ -26,13 +27,13 @@ public class AppProductCategoryController {
private final ProductCategoryServiceImpl service;
private final ProductCategoryConvert convert;
@Tag(name ="查询商品分类列表")
@Operation(summary = "查询商品分类列表")
@PostMapping("page")
public R<Page<ProductCategoryVO>> page(@RequestBody ProductCategoryBo query, Page<ProductCategory> page) {
Page<ProductCategory> productCategoryPage = service.page(page,query.toWrapper());
return R.ok(convert.toVO(productCategoryPage));
}
@Tag(name = "查询列表")
@Operation(summary = "查询列表")
@PostMapping("/tree")
public R<List<ProductCategoryVO>> tree(@RequestBody ProductCategoryBo bo ) {
List<ProductCategoryVO> articleList = service.tree( bo.toWrapper());

View File

@ -1,12 +1,12 @@
package com.wzj.soopin.goods.business;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wzj.soopin.goods.convert.ProductConvert;
import com.wzj.soopin.goods.convert.SkuConvert;
import com.wzj.soopin.goods.domain.bo.ProductBo;
import com.wzj.soopin.goods.domain.bo.SkuBo;
import com.wzj.soopin.goods.domain.entity.Product;
import com.wzj.soopin.goods.domain.entity.Sku;
import com.wzj.soopin.goods.domain.vo.ProductVO;
@ -20,6 +20,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
@ -59,11 +60,34 @@ public class ProductBusinessImpl extends BusinessImpl<ProductService, ProductCon
product.setSales("0");
product.setTenantId(TenantHelper.getTenantId());
boolean result = productService.saveOrUpdate(product);
//清理掉旧的SKU
skuService.remove(new LambdaQueryWrapper<Sku>().eq(Sku::getProductId, product.getId()));
// 2. 保存SKU列表
if (CollectionUtils.isNotEmpty(bo.getSkuList())) {
List<Sku> skus = bo.getSkuList().stream()
// 新增则直接保存sku信息
if (bo.getId() == null) {
List<Sku> skus = bo.getSkuList().stream().map(skuBO -> {
Sku sku = skuConvert.toPo(skuBO);
sku.setProductId(product.getId());
sku.setTenantId(TenantHelper.getTenantId());
return sku;
}).collect(Collectors.toList());
result = skuService.saveBatch(skus);
} else {
// 更新需按照新sku信息和旧sku信息对比id一致的数据更新新sku信息中id缺失的要删除没有id的要新增
List<SkuBo> skuList = bo.getSkuList();
List<Sku> oldSkus = skuService.getByProductId(bo.getId());
// 分离需要更新新增和删除的SKU
List<Sku> skusToUpdate = skuList.stream()
.filter(skuBo -> skuBo.getId() != null)
.map(skuBO -> {
Sku sku = skuConvert.toPo(skuBO);
sku.setId(skuBO.getId());
sku.setProductId(product.getId());
sku.setTenantId(TenantHelper.getTenantId());
return sku;
})
.collect(Collectors.toList());
List<Sku> skusToSave = skuList.stream()
.filter(skuBo -> skuBo.getId() == null)
.map(skuBO -> {
Sku sku = skuConvert.toPo(skuBO);
sku.setProductId(product.getId());
@ -71,9 +95,36 @@ public class ProductBusinessImpl extends BusinessImpl<ProductService, ProductCon
return sku;
})
.collect(Collectors.toList());
result = skuService.saveBatch(skus);
}
// 获取旧SKU ID列表和当前提交的SKU ID列表
List<Long> oldSkuIds = oldSkus.stream()
.map(Sku::getId)
.collect(Collectors.toList());
List<Long> currentSkuIds = skuList.stream()
.map(SkuBo::getId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
// 找出需要删除的SKU ID在旧列表中但不在当前列表中的
List<Long> skusToDelete = oldSkuIds.stream()
.filter(id -> !currentSkuIds.contains(id))
.collect(Collectors.toList());
// 执行更新操作
if (CollectionUtils.isNotEmpty(skusToUpdate)) {
result = skuService.updateBatchById(skusToUpdate) && result;
}
// 执行新增操作
if (CollectionUtils.isNotEmpty(skusToSave)) {
result = skuService.saveBatch(skusToSave) && result;
}
// 执行删除操作
if (CollectionUtils.isNotEmpty(skusToDelete)) {
result = skuService.removeByIds(skusToDelete) && result;
}
}
return result;
}

View File

@ -12,6 +12,9 @@ import java.math.BigDecimal;
@Schema(description = "SKU信息 查询 对象")
public class SkuBo {
@Schema(description = "主键")
private Long id;
@Schema(description = "PRODUCT_ID 精确匹配")
private Long productId;

View File

@ -3,7 +3,11 @@ package com.wzj.soopin.goods.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.wzj.soopin.goods.domain.entity.Sku;
import java.util.List;
public interface SkuService extends IService<Sku> {
void add(Sku sku);
List<Sku> getByProductId(Long productId);
}

View File

@ -2,21 +2,23 @@ package com.wzj.soopin.goods.service.impl;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.goods.domain.bo.SkuBo;
import com.wzj.soopin.goods.domain.entity.Product;
import com.wzj.soopin.goods.domain.entity.Sku;
import com.wzj.soopin.goods.domain.vo.SkuVO;
import com.wzj.soopin.goods.domain.vo.SkuVO;
import com.wzj.soopin.goods.mapper.ProductMapper;
import com.wzj.soopin.goods.mapper.SkuMapper;
import com.wzj.soopin.goods.service.SkuService;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.tenant.helper.TenantHelper;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* sku信息Service业务层处理
@ -49,4 +51,9 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements SkuSe
sku.setTenantId(product.getTenantId());
skuMapper.insert(sku);
}
@Override
public List<Sku> getByProductId(Long productId) {
return skuMapper.selectList(Wrappers.lambdaQuery(Sku.class).eq(Sku::getProductId, productId));
}
}

View File

@ -63,8 +63,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
p.*,
s.id AS sku_id,
s.out_sku_id,
s.price,
s.pic,
s.price as skuPrice,
s.pic as skuPic,
s.stock,
s.sp_data
FROM
@ -89,9 +89,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="query.nameLike != null and query.nameLike != ''">
AND p.name LIKE CONCAT('%', #{query.nameLike}, '%')
</if>
<!-- <if test="query.categoryId != null">-->
<!-- AND p.category_id = #{query.categoryId}-->
<!-- </if>-->
<if test="query.categoryIds != null and query.categoryIds.size() > 0">
AND p.category_id IN
<foreach collection="query.categoryIds" item="categoryId" open="(" separator="," close=")">
@ -104,13 +101,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<resultMap id="ProductWithSkusResultMap" type="ProductVO">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="status" column="status"/>
<collection property="skuList" ofType="SkuVO">
<id property="id" column="sku_id"/>
<result property="outSkuId" column="out_sku_id"/>
<result property="price" column="price"/>
<result property="pic" column="pic"/>
<result property="price" column="skuPrice"/>
<result property="pic" column="skuPic"/>
<result property="stock" column="stock"/>
<result property="spData" column="sp_data"/>
</collection>