Browse Source

feat: 供应商费率配置;

hanchaolong 1 month ago
parent
commit
9cb550663d

+ 4 - 4
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/controller/SysDeptRateController.java

@@ -22,7 +22,7 @@ import com.ruoyi.common.core.utils.poi.ExcelUtil;
 import com.ruoyi.common.core.web.page.TableDataInfo;
 
 /**
- * 供应商费率配置Controller
+ * PC-供应商费率配置
  * 
  * @author RuiJing
  * @date 2026-03-17
@@ -41,7 +41,7 @@ public class SysDeptRateController extends BaseController
     @GetMapping("/list")
     public TableDataInfo list(SysDeptRate sysDeptRate)
     {
-        startPage();
+//        startPage();
         List<SysDeptRate> list = sysDeptRateService.selectSysDeptRateList(sysDeptRate);
         return getDataTable(list);
     }
@@ -75,9 +75,9 @@ public class SysDeptRateController extends BaseController
     @RequiresPermissions("logistics:rate:add")
     @Log(title = "供应商费率配置", businessType = BusinessType.INSERT)
     @PostMapping
-    public AjaxResult add(@RequestBody SysDeptRate sysDeptRate)
+    public AjaxResult add(@RequestBody List<SysDeptRate> sysDeptRates)
     {
-        return toAjax(sysDeptRateService.insertSysDeptRate(sysDeptRate));
+        return toAjax(sysDeptRateService.insertSysDeptRate(sysDeptRates));
     }
 
     /**

+ 2 - 2
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/ISysDeptRateService.java

@@ -30,10 +30,10 @@ public interface ISysDeptRateService
     /**
      * 新增供应商费率配置
      * 
-     * @param sysDeptRate 供应商费率配置
+     * @param sysDeptRates 供应商费率配置
      * @return 结果
      */
-    public int insertSysDeptRate(SysDeptRate sysDeptRate);
+    public int insertSysDeptRate(List<SysDeptRate> sysDeptRates);
 
     /**
      * 修改供应商费率配置

+ 148 - 6
jd-logistics-modules/jd-logistics-system/src/main/java/com/ruoyi/logistics/service/impl/SysDeptRateServiceImpl.java

@@ -1,7 +1,12 @@
 package com.ruoyi.logistics.service.impl;
 
-import java.util.List;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import com.ruoyi.common.core.exception.ServiceException;
 import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.security.utils.SecurityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.ruoyi.logistics.mapper.SysDeptRateMapper;
@@ -41,20 +46,62 @@ public class SysDeptRateServiceImpl implements ISysDeptRateService
     @Override
     public List<SysDeptRate> selectSysDeptRateList(SysDeptRate sysDeptRate)
     {
-        return sysDeptRateMapper.selectSysDeptRateList(sysDeptRate);
+        List<SysDeptRate> sysDeptRates = sysDeptRateMapper.selectSysDeptRateList(sysDeptRate);
+            
+        // 根据 companyType 和 productType 分组后,再根据 intervalBegins 正序排列
+        return sysDeptRates.stream()
+            .sorted(
+                Comparator.comparing(SysDeptRate::getCompanyType)
+                    .thenComparing(SysDeptRate::getProductType)
+                    .thenComparing(SysDeptRate::getIntervalBegins)
+            )
+            .collect(Collectors.toList());
     }
 
     /**
      * 新增供应商费率配置
      * 
-     * @param sysDeptRate 供应商费率配置
+     * @param sysDeptRates 供应商费率配置
      * @return 结果
      */
     @Override
-    public int insertSysDeptRate(SysDeptRate sysDeptRate)
+    public int insertSysDeptRate(List<SysDeptRate> sysDeptRates)
     {
-        sysDeptRate.setCreateTime(DateUtils.getNowDate());
-        return sysDeptRateMapper.insertSysDeptRate(sysDeptRate);
+        if (sysDeptRates == null || sysDeptRates.isEmpty()) {
+            throw new ServiceException("批量插入的费率配置列表不能为空");
+        }
+
+        // 按 companyType + productType 分组校验区间重叠
+        Map<String, List<SysDeptRate>> groupedRates = new HashMap<>();
+
+        for (SysDeptRate rate : sysDeptRates) {
+            // 构建分组 key: companyType_productType
+            String groupKey = rate.getCompanyType() + "_" + rate.getProductType();
+            groupedRates.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(rate);
+        }
+
+        // 对每个分组进行区间重叠校验
+        for (Map.Entry<String, List<SysDeptRate>> entry : groupedRates.entrySet()) {
+            List<SysDeptRate> rates = entry.getValue();
+            validateIntervalOverlap(rates);
+        }
+
+        // 设置创建时间并批量插入
+        for (SysDeptRate rate : sysDeptRates) {
+            if (null == rate.getRateId()) {
+                rate.setCreateTime(DateUtils.getNowDate());
+                rate.setCreateBy(SecurityUtils.getUsername());
+                rate.setUserId(SecurityUtils.getUserId());
+                sysDeptRateMapper.insertSysDeptRate(rate);
+            } else {
+                rate.setUpdateTime(DateUtils.getNowDate());
+                rate.setUpdateBy(SecurityUtils.getUsername());
+                rate.setUserId(SecurityUtils.getUserId());
+                sysDeptRateMapper.updateSysDeptRate(rate);
+            }
+        }
+
+        return sysDeptRates.size();
     }
 
     /**
@@ -93,4 +140,99 @@ public class SysDeptRateServiceImpl implements ISysDeptRateService
     {
         return sysDeptRateMapper.deleteSysDeptRateByRateId(rateId);
     }
+    
+    /**
+     * 校验同一物流公司和产品类型的区间是否重叠
+     * 区间规则:(intervalBegins, intervalEnds] 左开右闭
+     * 
+     * @param rates 费率配置列表
+     * @throws ServiceException 如果存在区间重叠
+     */
+    private static void validateIntervalOverlap(List<SysDeptRate> rates) {
+        if (rates.size() <= 1) {
+            return; // 单个或空列表无需校验
+        }
+        
+        // 两两比较所有区间
+        for (int i = 0; i < rates.size(); i++) {
+            for (int j = i + 1; j < rates.size(); j++) {
+                SysDeptRate rate1 = rates.get(i);
+                SysDeptRate rate2 = rates.get(j);
+                
+                Long begins1 = rate1.getIntervalBegins();
+                Long ends1 = rate1.getIntervalEnds();
+                Long begins2 = rate2.getIntervalBegins();
+                Long ends2 = rate2.getIntervalEnds();
+                
+                // 检查区间有效性
+                if (begins1 == null || ends1 == null || begins2 == null || ends2 == null) {
+                    throw new ServiceException("区间开始和结束值不能为空");
+                }
+                
+                if (begins1 >= ends1) {
+                    throw new ServiceException(String.format(
+                        "第%d条配置的区间开始值必须小于结束值", i + 1));
+                }
+                
+                if (begins2 >= ends2) {
+                    throw new ServiceException(String.format(
+                        "第%d条配置的区间开始值必须小于结束值", j + 1));
+                }
+                
+                // 判断两个区间是否重叠
+                // 区间 1: (begins1, ends1]
+                // 区间 2: (begins2, ends2]
+                // 不重叠的条件:ends1 <= begins2 或 ends2 <= begins1
+                // 重叠的条件:!(ends1 <= begins2 || ends2 <= begins1)
+                boolean isOverlap = !(ends1 <= begins2 || ends2 <= begins1);
+                
+                if (isOverlap) {
+                    throw new ServiceException(String.format(
+                        "物流公司%s、产品类型%s的区间配置存在重叠:区间%d(%d,%d] 与区间%d(%d,%d]",
+                        rates.get(i).getCompanyType(),
+                        rates.get(i).getProductType(),
+                        i + 1, begins1, ends1,
+                        j + 1, begins2, ends2));
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        List<SysDeptRate> rates = new ArrayList<>();
+        SysDeptRate a = new SysDeptRate();
+        SysDeptRate b = new SysDeptRate();
+        SysDeptRate c = new SysDeptRate();
+
+        a.setCompanyType("JD");
+        a.setProductType("ed-m-0001");
+        a.setIntervalBegins(0L);
+        a.setIntervalEnds(100L);
+        a.setRate(new BigDecimal("0.1"));
+
+        b.setCompanyType("JD");
+        b.setProductType("ed-m-0001");
+        b.setIntervalBegins(100L);
+        b.setIntervalEnds(200L);
+        b.setRate(new BigDecimal("0.2"));
+
+        c.setCompanyType("JD");
+        c.setProductType("ed-m-0002");
+        c.setIntervalBegins(200L);
+        c.setIntervalEnds(300L);
+        c.setRate(new BigDecimal("0.3"));
+
+        rates.add(c);
+        rates.add(b);
+        rates.add(a);
+
+        List<SysDeptRate> collect = rates.stream()
+                .sorted(
+                        Comparator.comparing(SysDeptRate::getCompanyType)
+                                .thenComparing(SysDeptRate::getProductType)
+                                .thenComparing(SysDeptRate::getIntervalBegins)
+                )
+                .collect(Collectors.toList());
+        System.out.println(1);
+    }
 }