mall + trade:review 商品管理

This commit is contained in:
YunaiV 2023-06-03 22:59:34 +08:00
parent e72f741d02
commit dd93215139
12 changed files with 40 additions and 75 deletions

View File

@ -1,7 +1,7 @@
package cn.iocoder.yudao.module.product.enums;
/**
* Product 常量 TODO 把使用到的常量收拢到一块定义替换魔法值
* Product 常量
*
* @author HUIHUI
*/
@ -12,13 +12,4 @@ public interface ProductConstants {
*/
int ALERT_STOCK = 10;
/**
* 默认商品销量 TODO 默认商品销量为零
*/
Integer SALES_COUNT = 0;
/**
* 默认善品浏览量 TODO 默认浏览量为零
*/
Integer BROWSE_COUNT = 0;
}

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.controller.app.spu;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppProductSpuDetailRespVO;
@ -67,7 +66,7 @@ public class AppProductSpuController {
}
// 查询商品 SKU
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuIdAndStatus(spu.getId());
List<ProductSkuDO> skus = productSkuService.getSkuListBySpuId(spu.getId());
// 查询商品属性
List<ProductPropertyValueDetailRespBO> propertyValues = productPropertyValueService
.getPropertyValueDetailList(ProductSkuConvert.INSTANCE.convertPropertyValueIds(skus));

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuRespVO;
import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
@ -23,9 +22,6 @@ import org.mapstruct.factory.Mappers;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
@ -65,8 +61,6 @@ public interface ProductSpuConvert {
return StrUtil.toString(list);
}
// TODO @puhui999部分属性可以通过 mapstruct @Mapping(source = , target = , ) 映射转换可以查下文档 fix:哈哈 这样确实丝滑哈
@Mapping(source = "sliderPicUrls", target = "sliderPicUrls", qualifiedByName = "convertListToString")
@Mapping(source = "giveCouponTemplateIds", target = "giveCouponTemplateIds", qualifiedByName = "convertListToString")
@Mapping(source = "activityOrders", target = "activityOrders", qualifiedByName = "convertListToString")

View File

@ -14,11 +14,6 @@ import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
/**
* 商品 SKU Mapper
*
* @author 芋道源码
*/
@Mapper
public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> {
@ -26,11 +21,6 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> {
return selectList(ProductSkuDO::getSpuId, spuId);
}
default List<ProductSkuDO> selectListBySpuIdAndStatus(Long spuId) {
return selectList(new LambdaQueryWrapperX<ProductSkuDO>()
.eq(ProductSkuDO::getSpuId, spuId));
}
default List<ProductSkuDO> selectListBySpuId(Collection<Long> spuIds) {
return selectList(ProductSkuDO::getSpuId, spuIds);
}
@ -73,6 +63,7 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> {
return selectList(new QueryWrapper<ProductSkuDO>().apply("stock <= warn_stock"));
}
// TODO @puhui999貌似 IN 不出来数据哈直接全部查询出来处理就好列
/**
* 更新 sku 属性值时使用的分页查询
*

View File

@ -96,6 +96,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
}
}
// TODO @puhui999不用抽方法因为不太会复用这个方法哈
private void validateProductCategoryIsHaveBindSpu(Long id) {
Long count = productSpuService.getSpuCountByCategoryId(id);
if (0 != count) {
@ -126,9 +127,9 @@ public class ProductCategoryServiceImpl implements ProductCategoryService {
}
int level = 1;
// for 的原因是因为避免脏数据导致可能的死循环一般不会超过 100 层哈
for (int i = 0; i < 100; i++) {
ProductCategoryDO category = productCategoryMapper.selectById(id);
for (int i = 0; i < Byte.MAX_VALUE; i++) {
// 如果没有父节点break 结束
ProductCategoryDO category = productCategoryMapper.selectById(id);
if (category == null
|| Objects.equals(category.getParentId(), PARENT_ID_NULL)) {
break;

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.product.service.property;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyCreateReqVO;
@ -72,7 +71,7 @@ public class ProductPropertyServiceImpl implements ProductPropertyService {
// 更新
ProductPropertyDO updateObj = ProductPropertyConvert.INSTANCE.convert(updateReqVO);
productPropertyMapper.updateById(updateObj);
// TODO 芋艿更新时需要看看 sku fix
// TODO @puhui是不是只要传递变量不传递整个 updateObj 变量哈
productSkuService.updateSkuProperty(updateObj);
}

View File

@ -73,7 +73,9 @@ public class ProductPropertyValueServiceImpl implements ProductPropertyValueServ
// 更新
ProductPropertyValueDO updateObj = ProductPropertyValueConvert.INSTANCE.convert(updateReqVO);
productPropertyValueMapper.updateById(updateObj);
// TODO 芋艿更新时需要看看 sku fix
// TODO @puhui是不是只要传递变量不传递整个 updateObj 变量哈
productSkuService.updateSkuPropertyValue(updateObj);
}

View File

@ -5,7 +5,6 @@ import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateO
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyDO;
import cn.iocoder.yudao.module.product.dal.dataobject.property.ProductPropertyValueDO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import org.springframework.lang.Nullable;
import java.util.Collection;
import java.util.List;
@ -87,14 +86,6 @@ public interface ProductSkuService {
*/
List<ProductSkuDO> getSkuListBySpuId(Long spuId);
/**
* 基于 SPU 编号和状态获得商品 SKU 集合
*
* @param spuId SPU 编号
* @return 商品 SKU 集合
*/
List<ProductSkuDO> getSkuListBySpuIdAndStatus(Long spuId);
/**
* 获得 spu 对应的 SKU 集合
*

View File

@ -140,11 +140,6 @@ public class ProductSkuServiceImpl implements ProductSkuService {
return productSkuMapper.selectListBySpuId(spuId);
}
@Override
public List<ProductSkuDO> getSkuListBySpuIdAndStatus(Long spuId) {
return productSkuMapper.selectListBySpuIdAndStatus(spuId);
}
@Override
public List<ProductSkuDO> getSkuListBySpuId(List<Long> spuIds) {
return productSkuMapper.selectListBySpuId(spuIds);
@ -163,9 +158,10 @@ public class ProductSkuServiceImpl implements ProductSkuService {
@Override
public int updateSkuProperty(ProductPropertyDO updateObj) {
// TODO 看了一下数据库有关于 json 字符串的处理怕数据库出现兼容问题这里还是用数据库常规操作来实现
// TODO @puhui999直接全部查询处理批量处理就好列一般项目的商品不会超过几十万的哈
Long count = productSkuMapper.selectCountByPropertyNotNull();
int currentPage = 1;
List<ProductSkuDO> skuDOs = new ArrayList<>();
List<ProductSkuDO> updateSkus = new ArrayList<>();
if (count == 0) {
return 0;
}
@ -178,25 +174,25 @@ public class ProductSkuServiceImpl implements ProductSkuService {
if (CollUtil.isEmpty(records)) {
break;
}
records.stream()
.filter(sku -> sku.getProperties() != null)
records.stream().filter(sku -> sku.getProperties() != null)
.forEach(sku -> sku.getProperties().forEach(property -> {
if (property.getPropertyId().equals(updateObj.getId())) {
property.setPropertyName(updateObj.getName());
skuDOs.add(sku);
updateSkus.add(sku);
}
}));
}
if (CollUtil.isEmpty(skuDOs)) {
if (CollUtil.isEmpty(updateSkus)) {
return 0;
}
// TODO @puhui999貌似 updateBatch 自己会拆分批次这里不用再拆分了
// 每批处理的大小
int batchSize = 1000;
for (int i = 0; i < skuDOs.size(); i += batchSize) {
List<ProductSkuDO> batchSkuDOs = skuDOs.subList(i, Math.min(i + batchSize, skuDOs.size()));
for (int i = 0; i < updateSkus.size(); i += batchSize) {
List<ProductSkuDO> batchSkuDOs = updateSkus.subList(i, Math.min(i + batchSize, updateSkus.size()));
productSkuMapper.updateBatch(batchSkuDOs, batchSize);
}
return skuDOs.size();
return updateSkus.size();
}
@Override
@ -204,7 +200,7 @@ public class ProductSkuServiceImpl implements ProductSkuService {
// TODO 看了一下数据库有关于 json 字符串的处理怕数据库出现兼容问题这里还是用数据库常规操作来实现
Long count = productSkuMapper.selectCountByPropertyNotNull();
int currentPage = 1;
List<ProductSkuDO> skuDOs = new ArrayList<>();
List<ProductSkuDO> updateSkus = new ArrayList<>();
if (count == 0) {
return 0;
}
@ -222,20 +218,20 @@ public class ProductSkuServiceImpl implements ProductSkuService {
.forEach(sku -> sku.getProperties().forEach(property -> {
if (property.getValueId().equals(updateObj.getId())) {
property.setValueName(updateObj.getName());
skuDOs.add(sku);
updateSkus.add(sku);
}
}));
}
if (CollUtil.isEmpty(skuDOs)) {
if (CollUtil.isEmpty(updateSkus)) {
return 0;
}
// 每批处理的大小
int batchSize = 1000;
for (int i = 0; i < skuDOs.size(); i += batchSize) {
List<ProductSkuDO> batchSkuDOs = skuDOs.subList(i, Math.min(i + batchSize, skuDOs.size()));
for (int i = 0; i < updateSkus.size(); i += batchSize) {
List<ProductSkuDO> batchSkuDOs = updateSkus.subList(i, Math.min(i + batchSize, updateSkus.size()));
productSkuMapper.updateBatch(batchSkuDOs, batchSize);
}
return skuDOs.size();
return updateSkus.size();
}
@Override

View File

@ -13,7 +13,6 @@ import cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
import cn.iocoder.yudao.module.product.enums.ProductConstants;
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
import cn.iocoder.yudao.module.product.service.brand.ProductBrandService;
import cn.iocoder.yudao.module.product.service.category.ProductCategoryService;
@ -27,6 +26,7 @@ import javax.annotation.Resource;
import java.util.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getMinValue;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue;
import static cn.iocoder.yudao.module.product.dal.dataobject.category.ProductCategoryDO.CATEGORY_LEVEL;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
@ -101,13 +101,13 @@ public class ProductSpuServiceImpl implements ProductSpuService {
*/
private void initSpuFromSkus(ProductSpuDO spu, List<ProductSkuCreateOrUpdateReqVO> skus) {
// sku 单价最低的商品的价格
spu.setPrice(CollectionUtils.getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice));
spu.setPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getPrice));
// sku 单价最低的商品的市场价格
spu.setMarketPrice(CollectionUtils.getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
spu.setMarketPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
// sku单价最低的商品的成本价格
spu.setCostPrice(CollectionUtils.getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getCostPrice));
spu.setCostPrice(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getCostPrice));
// sku单价最低的商品的条形码
spu.setBarCode(CollectionUtils.getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getBarCode));
spu.setBarCode(getMinValue(skus, ProductSkuCreateOrUpdateReqVO::getBarCode));
// skus 库存总数
spu.setStock(getSumValue(skus, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
// 若是 spu 已有状态则不处理
@ -115,9 +115,9 @@ public class ProductSpuServiceImpl implements ProductSpuService {
// 默认状态为上架
spu.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
// 默认商品销量
spu.setSalesCount(ProductConstants.SALES_COUNT);
spu.setSalesCount(0);
// 默认商品浏览量
spu.setBrowseCount(ProductConstants.BROWSE_COUNT);
spu.setBrowseCount(0);
}
}
@ -159,6 +159,7 @@ public class ProductSpuServiceImpl implements ProductSpuService {
*
* @param id id
*/
// TODO puhui999感觉不用独立出来一个方法直接在 deleteSpu 方法中校验即可
private void validateSpuStatus(Long id) {
ProductSpuDO spuDO = productSpuMapper.selectById(id);
// 判断 SPU 状态是否为回收站

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.module.trade.controller.admin.delivery;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.expresstemplate.*;
@ -71,6 +70,7 @@ public class DeliveryExpressTemplateController {
return success(DeliveryExpressTemplateConvert.INSTANCE.convertList(list));
}
// TODO @puhui999DeliveryExpressTemplateRespVO 搞个 simple 的哈
@GetMapping("/list-all-simple")
@Operation(summary = "获取快递模版精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<DeliveryExpressTemplateRespVO>> getSimpleTemplateList() {

View File

@ -27,13 +27,13 @@ public class DefaultController {
"[微信公众号 yudao-module-mp - 已禁用][参考 https://doc.iocoder.cn/mp/build/ 开启]");
}
@RequestMapping(value = {"/admin-api/product/**", // 商品中心
"/admin-api/trade/**", // 交易中心
"/admin-api/promotion/**"}) // 营销中心
public CommonResult<Boolean> mall404() {
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
}
// @RequestMapping(value = {"/admin-api/product/**", // 商品中心
// "/admin-api/trade/**", // 交易中心
// "/admin-api/promotion/**"}) // 营销中心
// public CommonResult<Boolean> mall404() {
// return CommonResult.error(NOT_IMPLEMENTED.getCode(),
// "[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]");
// }
@RequestMapping(value = {"/admin-api/report/**"})
public CommonResult<Boolean> report404() {