浏览代码

feat(product): 添加产品描述字段和优化产品属性管理

- 移除收藏功能中的favoritesId条件以支持更灵活的产品收藏
- 新增产品描述字段到ProductBaseBo和ProductBaseVo中
- 在ProductBaseServiceImpl中实现产品描述的数据映射和更新逻辑
- 为产品属性添加唯一性校验,防止同一分类下重复属性名称
- 修改价格区间查询逻辑,统一使用字符串类型进行比较
- 修复ProductPhotos中imageUrl的字段映射错误
- 为PT方案功能添加产品选择和数据存储功能
- 增加服务异常处理和数据验证逻辑
- 更新PPT方案列表排序方式为降序排列
肖路 1 月之前
父节点
当前提交
8299444f5d

+ 0 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/controller/pc/MyProductController.java

@@ -157,7 +157,6 @@ public class MyProductController {
         productCollectService.remove(Wrappers.lambdaQuery(ProductCollect.class)
             .eq(ProductCollect::getUserId, LoginHelper.getUserId())
             .eq(ProductCollect::getProductId, bo.getProductId())
-            .eq(ProductCollect::getFavoritesId, bo.getFavoritesId())
         );
         return R.ok();
     }

+ 10 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/ProuctPptScheme.java

@@ -154,5 +154,15 @@ public class ProuctPptScheme extends TenantEntity {
      */
     private String remark;
 
+    /**
+    * 商品数据(json)
+    * */
+    private String productData;
+    /**
+    * 商品数量
+    * */
+    private Integer productNum;
+
+
 
 }

+ 5 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProductBaseBo.java

@@ -374,6 +374,11 @@ public class ProductBaseBo extends BaseEntity {
      */
     private Long minOrderQuantity;
 
+    /**
+    * 产品描述
+    * */
+    private String productDescription;
+
     /**
      * 是否可定制
      */

+ 11 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/bo/ProuctPptSchemeBo.java

@@ -181,5 +181,16 @@ public class ProuctPptSchemeBo extends BaseEntity {
     * */
     private List<Long> userIds;
 
+    private List<Long> productIds;
+
+    /**
+     * 商品数据(json)
+     * */
+    private String productData;
+    /**
+     * 商品数量
+     * */
+    private Integer productNum;
+
 
 }

+ 5 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProductBaseVo.java

@@ -440,6 +440,11 @@ public class ProductBaseVo implements Serializable {
      * */
     private Long virtualInventory;
 
+    /**
+     * 产品描述
+     * */
+    private String productDescription;
+
 
     /**
      * 定制说明

+ 9 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/domain/vo/ProuctPptSchemeVo.java

@@ -204,5 +204,14 @@ public class ProuctPptSchemeVo implements Serializable {
     @ExcelProperty(value = "备注")
     private String remark;
 
+    /**
+     * 商品数据(json)
+     * */
+    private String productData;
+    /**
+     * 商品数量
+     * */
+    private Integer productNum;
+
 
 }

+ 16 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductAttributesServiceImpl.java

@@ -2,6 +2,7 @@ package org.dromara.product.service.impl;
 
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -124,7 +125,21 @@ public class ProductAttributesServiceImpl  extends ServiceImpl<ProductAttributes
      * 保存前的数据校验
      */
     private void validEntityBeforeSave(ProductAttributes entity){
-        //TODO 做一些数据校验,如唯一约束
+        // 校验同一分类下是否存在相同属性名称的属性
+        if (entity.getCategoryId() != null && entity.getProductAttributesName() != null) {
+            LambdaQueryWrapper<ProductAttributes> lqw = Wrappers.lambdaQuery();
+            lqw.ne(ObjectUtil.isNotEmpty(entity.getId()), ProductAttributes::getId, entity.getId());
+            lqw.eq(ProductAttributes::getCategoryId, entity.getCategoryId());
+            lqw.eq(ProductAttributes::getProductAttributesName, entity.getProductAttributesName());
+            // 编辑时排除当前记录
+            if (entity.getId() != null) {
+                lqw.ne(ProductAttributes::getId, entity.getId());
+            }
+            long count = baseMapper.selectCount(lqw);
+            if (count > 0) {
+                throw new ServiceException("同一分类下请不要添加相同属性");
+            }
+        }
     }
 
     /**

+ 1 - 0
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBaseAuditServiceImpl.java

@@ -193,6 +193,7 @@ public class ProductBaseAuditServiceImpl extends ServiceImpl<ProductBaseAuditMap
     public Boolean insertByBo(ProductBaseAuditBo bo) {
         ProductBaseAudit add = MapstructUtils.convert(bo, ProductBaseAudit.class);
         LoginUser loginUser = LoginHelper.getLoginUser();
+        add.setId(null);
         if(ObjectUtil.isNotEmpty(loginUser.getSupplierId())){
             add.setCreateById(loginUser.getSupplierId());
             add.setCreateByType(1);

+ 22 - 10
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProductBaseServiceImpl.java

@@ -39,6 +39,7 @@ import org.dromara.product.domain.ProductClassification;
 import org.dromara.product.domain.ProductCustomization;
 import org.dromara.product.service.IProductBaseService;
 
+import java.math.RoundingMode;
 import java.util.*;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -265,6 +266,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             vo.setProductNature(extend.getPurchaseManagerNo());
             vo.setPurchasingPersonnel(extend.getPurchaseNo());
             vo.setSupplierNo(extend.getSupplierNo());
+            vo.setProductDescription(extend.getProductDescription());
         }
 
         // 3. 查询并填充价格库存信息(product_price_inventory表)
@@ -511,16 +513,16 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             //价格区间 1:1-100 2:100-500 3:500-1000 4:1000以上
             switch (bo.getPriceRange()) {
                 case "1":
-                    wrapper.between(ProductBaseVo::getMemberPrice, 1, 100);
+                    wrapper.between(ProductBaseVo::getMemberPrice, "1", "100");
                     break;
                 case "2":
-                    wrapper.between(ProductBaseVo::getMemberPrice, 100, 500);
+                    wrapper.between(ProductBaseVo::getMemberPrice, "100", "500");
                     break;
                 case "3":
-                    wrapper.between(ProductBaseVo::getMemberPrice, 500, 1000);
+                    wrapper.between(ProductBaseVo::getMemberPrice, "500", "1000");
                     break;
                 case "4":
-                    wrapper.ge(ProductBaseVo::getMemberPrice, 1000);
+                    wrapper.ge(ProductBaseVo::getMemberPrice, "1000");
                     break;
             }
         }
@@ -647,7 +649,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
     private void saveProductDetail(ProductBaseBo bo, Long productId) {
         ProductPhotos productPhotos= new ProductPhotos();
         productPhotos.setProductId(productId);
-        productPhotos.setImageUrl(bo.getProductImage());
+        productPhotos.setImageUrl(bo.getImageUrl());
         productPhotos.setProductDetailsPc(bo.getPcDetail());
         productPhotos.setProductDetailsApp(bo.getMobileDetail());
         photosMapper.insert(productPhotos);
@@ -788,6 +790,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         extend.setShelfComments(bo.getShelfComments());
         extend.setPurchaseManagerNo(bo.getProductNature());
         extend.setPurchaseNo(bo.getPurchasingPersonnel());
+        extend.setProductDescription(bo.getProductDescription());
         extendMapper.insert(extend);
     }
 
@@ -871,6 +874,7 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             if (bo.getProductNature() != null) existing.setPurchaseManagerNo(bo.getProductNature());
             if (bo.getPurchasingPersonnel() != null) existing.setPurchaseNo(bo.getPurchasingPersonnel());
             if (bo.getSupplierNo() != null) existing.setSupplierNo(bo.getSupplierNo());
+            if (bo.getProductDescription() != null) existing.setProductDescription(bo.getProductDescription());
             extendMapper.updateById(existing);
         } else {
             // 不存在则新增
@@ -1519,13 +1523,13 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
             //价格区间 1:1-100 2:100-500 3:500-1000 4:1000以上
             switch (bo.getPriceRange()) {
                 case "1":
-                    lqw.between("b.market_price", 1, 100);
+                    lqw.between("p.market_price", 1, 100);
                 case "2":
-                    lqw.between("b.market_price", 100, 500);
+                    lqw.between("p.market_price", 100, 500);
                 case "3":
-                    lqw.between("b.market_price", 500, 1000);
+                    lqw.between("p.market_price", 500, 1000);
                 case "4":
-                    lqw.ge("b.market_price", 1000);
+                    lqw.ge("p.market_price", 1000);
             }
         }
         if(bo.getSortField() != null && bo.getSortOrder() != null){
@@ -1542,7 +1546,6 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
                 }
             }
         }
-        lqw.select("b.id","b.product_image","p.market_price","p.member_price","p.min_selling_price","p.min_order_quantity","b.item_name","u.unit_name");
 
         // 使用ES分页查询
         try {
@@ -1571,6 +1574,15 @@ public class ProductBaseServiceImpl extends ServiceImpl<ProductBaseMapper, Produ
         return TableDataInfo.build();
     }
 
+    public static void main(String[] args) {
+        Date oldPlanStartAt = DateUtil.parse("2026-03-18 00:00:00");
+        Date oldPlanEndAt = DateUtil.parse("2026-04-18 00:00:00");
+        BigDecimal time = BigDecimal.valueOf(DateUtil.betweenDay(oldPlanStartAt, oldPlanEndAt, true) + 1);
+        BigDecimal priceAvgLease = BigDecimal.valueOf(549.90).divide(time, 2, RoundingMode.HALF_UP);
+
+        System.out.println(priceAvgLease);
+    }
+
     /**
      * PC端商品浏览记录
      *

+ 17 - 1
ruoyi-modules/ruoyi-product/src/main/java/org/dromara/product/service/impl/ProuctPptSchemeServiceImpl.java

@@ -3,6 +3,7 @@ package org.dromara.product.service.impl;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.dubbo.config.annotation.DubboReference;
 import org.dromara.common.core.exception.ServiceException;
@@ -16,6 +17,10 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.satoken.utils.LoginHelper;
+import org.dromara.product.domain.ProductBase;
+import org.dromara.product.domain.vo.ProductBaseVo;
+import org.dromara.product.mapper.ProductBaseMapper;
+import org.dromara.product.service.IProductBaseService;
 import org.dromara.system.api.RemoteUserService;
 import org.dromara.system.api.domain.vo.RemoteUserVo;
 import org.springframework.stereotype.Service;
@@ -44,6 +49,7 @@ public class ProuctPptSchemeServiceImpl  extends ServiceImpl<ProuctPptSchemeMapp
 
     private final ProuctPptSchemeMapper baseMapper;
 
+    private final IProductBaseService productBaseService;
     @DubboReference
     private RemoteUserService remoteUserService;
 
@@ -88,7 +94,7 @@ public class ProuctPptSchemeServiceImpl  extends ServiceImpl<ProuctPptSchemeMapp
     private LambdaQueryWrapper<ProuctPptScheme> buildQueryWrapper(ProuctPptSchemeBo bo) {
         Map<String, Object> params = bo.getParams();
         LambdaQueryWrapper<ProuctPptScheme> lqw = Wrappers.lambdaQuery();
-        lqw.orderByAsc(ProuctPptScheme::getId);
+        lqw.orderByDesc(ProuctPptScheme::getId);
         lqw.like(StringUtils.isNotBlank(bo.getName()), ProuctPptScheme::getName, bo.getName());
         lqw.eq(bo.getTemplateId() != null, ProuctPptScheme::getTemplateId, bo.getTemplateId());
         lqw.like(StringUtils.isNotBlank(bo.getTplName()), ProuctPptScheme::getTplName, bo.getTplName());
@@ -127,6 +133,11 @@ public class ProuctPptSchemeServiceImpl  extends ServiceImpl<ProuctPptSchemeMapp
     @Override
     public Boolean insertByBo(ProuctPptSchemeBo bo) {
         ProuctPptScheme add = MapstructUtils.convert(bo, ProuctPptScheme.class);
+        if (ObjectUtil.isEmpty(bo.getProductIds())) {
+            throw new ServiceException("请选择产品");
+        }
+        List<ProductBaseVo> productBaseVos = bo.getProductIds().stream().map(productBaseService::queryById).collect(Collectors.toList());
+        add.setProductData(JSONUtil.toJsonStr(productBaseVos));
         validEntityBeforeSave(add);
         add.setOwnerId(LoginHelper.getUserId());
         boolean flag = baseMapper.insert(add) > 0;
@@ -146,6 +157,11 @@ public class ProuctPptSchemeServiceImpl  extends ServiceImpl<ProuctPptSchemeMapp
     public Boolean updateByBo(ProuctPptSchemeBo bo) {
         ProuctPptScheme update = MapstructUtils.convert(bo, ProuctPptScheme.class);
         validEntityBeforeSave(update);
+        if (ObjectUtil.isEmpty(bo.getProductIds())) {
+            throw new ServiceException("请选择产品");
+        }
+        List<ProductBaseVo> productBaseVos = bo.getProductIds().stream().map(productBaseService::queryById).collect(Collectors.toList());
+        update.setProductData(JSONUtil.toJsonStr(productBaseVos));
         return baseMapper.updateById(update) > 0;
     }