|
@@ -149,10 +149,28 @@ public class SysDeptRateServiceImpl implements ISysDeptRateService
|
|
|
* @throws ServiceException 如果存在区间重叠
|
|
* @throws ServiceException 如果存在区间重叠
|
|
|
*/
|
|
*/
|
|
|
private static void validateIntervalOverlap(List<SysDeptRate> rates) {
|
|
private static void validateIntervalOverlap(List<SysDeptRate> rates) {
|
|
|
- if (rates.size() <= 1) {
|
|
|
|
|
|
|
+ if (rates == null || rates.isEmpty()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 按起始金额排序,便于连续性校验
|
|
|
|
|
+ rates.sort(Comparator.comparing(SysDeptRate::getIntervalBegins));
|
|
|
|
|
+
|
|
|
|
|
+ String companyType = rates.get(0).getCompanyType();
|
|
|
|
|
+ String productType = rates.get(0).getProductType();
|
|
|
|
|
+ String companyName = getCompanyName(companyType);
|
|
|
|
|
+ String productName = getProductName(productType);
|
|
|
|
|
+
|
|
|
|
|
+ // 单个规则的校验
|
|
|
|
|
+ if (rates.size() == 1) {
|
|
|
SysDeptRate rate = rates.get(0);
|
|
SysDeptRate rate = rates.get(0);
|
|
|
Long begins = rate.getIntervalBegins();
|
|
Long begins = rate.getIntervalBegins();
|
|
|
Long ends = rate.getIntervalEnds();
|
|
Long ends = rate.getIntervalEnds();
|
|
|
|
|
+
|
|
|
|
|
+ if (begins == null || begins != 0) {
|
|
|
|
|
+ throw new ServiceException(String.format(
|
|
|
|
|
+ "%s、%s的第一条规则起始金额必须为0", companyName, productName));
|
|
|
|
|
+ }
|
|
|
// 检查区间有效性
|
|
// 检查区间有效性
|
|
|
if (begins == null || ends == null) {
|
|
if (begins == null || ends == null) {
|
|
|
throw new ServiceException("区间开始和结束值不能为空");
|
|
throw new ServiceException("区间开始和结束值不能为空");
|
|
@@ -160,73 +178,101 @@ public class SysDeptRateServiceImpl implements ISysDeptRateService
|
|
|
|
|
|
|
|
if (begins >= ends) {
|
|
if (begins >= ends) {
|
|
|
throw new ServiceException(String.format(
|
|
throw new ServiceException(String.format(
|
|
|
- "%s、%s配置的区间开始值必须小于结束值", getCompanyName(rate.getCompanyType()), getProductName(rate.getProductType())));
|
|
|
|
|
|
|
+ "%s、%s配置的区间开始值必须小于结束值", companyName, productName));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (rate.getRate() == null || rate.getRate().compareTo(new BigDecimal("0")) == 0) {
|
|
|
|
|
+ throw new ServiceException(String.format(
|
|
|
|
|
+ "%s、%s的费率不能为0", companyName, productName));
|
|
|
|
|
+ }
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 多条规则的校验
|
|
|
|
|
+ // 1. 第一条起始金额必须为0
|
|
|
|
|
+ SysDeptRate firstRate = rates.get(0);
|
|
|
|
|
+ if (firstRate.getIntervalBegins() == null || firstRate.getIntervalBegins() != 0) {
|
|
|
|
|
+ throw new ServiceException(String.format(
|
|
|
|
|
+ "%s、%s的第一条规则起始金额必须为0", companyName, productName));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 校验每条规则的有效性
|
|
|
|
|
+ for (int i = 0; i < rates.size(); i++) {
|
|
|
|
|
+ SysDeptRate rate = rates.get(i);
|
|
|
|
|
+ Long begins = rate.getIntervalBegins();
|
|
|
|
|
+ Long ends = rate.getIntervalEnds();
|
|
|
|
|
+
|
|
|
|
|
+ if (begins == null || ends == null) {
|
|
|
|
|
+ throw new ServiceException(String.format(
|
|
|
|
|
+ "%s、%s第%d条规则的区间开始和结束值不能为空", companyName, productName, i + 1));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (begins >= ends) {
|
|
|
|
|
+ throw new ServiceException(String.format(
|
|
|
|
|
+ "%s、%s第%d条规则的区间开始值必须小于结束值", companyName, productName, i + 1));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (rate.getRate().compareTo(new BigDecimal("0")) == 0) {
|
|
|
|
|
|
|
+ if (rate.getRate() == null || rate.getRate().compareTo(new BigDecimal("0")) == 0) {
|
|
|
throw new ServiceException(String.format(
|
|
throw new ServiceException(String.format(
|
|
|
- "%s、%s的费率不能为0", getCompanyName(rate.getCompanyType()), getProductName(rate.getProductType())));
|
|
|
|
|
|
|
+ "%s、%s第%d条规则的费率不能为0", companyName, productName, i + 1));
|
|
|
}
|
|
}
|
|
|
- return; // 单个或空列表无需校验
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 两两比较所有区间
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 校验连续性:当前行的起始金额必须等于上一行的结束金额
|
|
|
|
|
+ for (int i = 1; i < rates.size(); i++) {
|
|
|
|
|
+ SysDeptRate prevRate = rates.get(i - 1);
|
|
|
|
|
+ SysDeptRate currRate = rates.get(i);
|
|
|
|
|
+
|
|
|
|
|
+ if (!currRate.getIntervalBegins().equals(prevRate.getIntervalEnds())) {
|
|
|
|
|
+ throw new ServiceException(String.format(
|
|
|
|
|
+ "%s、%s的规则不连续:第%d条规则结束金额为%d,第%d条规则起始金额为%d,必须相等",
|
|
|
|
|
+ companyName, productName,
|
|
|
|
|
+ i, prevRate.getIntervalEnds(),
|
|
|
|
|
+ i + 1, currRate.getIntervalBegins()));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 校验区间重叠(虽然连续性校验已经保证了不重叠,但保留此校验作为双重保障)
|
|
|
for (int i = 0; i < rates.size(); i++) {
|
|
for (int i = 0; i < rates.size(); i++) {
|
|
|
for (int j = i + 1; j < rates.size(); j++) {
|
|
for (int j = i + 1; j < rates.size(); j++) {
|
|
|
SysDeptRate rate1 = rates.get(i);
|
|
SysDeptRate rate1 = rates.get(i);
|
|
|
SysDeptRate rate2 = rates.get(j);
|
|
SysDeptRate rate2 = rates.get(j);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
Long begins1 = rate1.getIntervalBegins();
|
|
Long begins1 = rate1.getIntervalBegins();
|
|
|
Long ends1 = rate1.getIntervalEnds();
|
|
Long ends1 = rate1.getIntervalEnds();
|
|
|
Long begins2 = rate2.getIntervalBegins();
|
|
Long begins2 = rate2.getIntervalBegins();
|
|
|
Long ends2 = rate2.getIntervalEnds();
|
|
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]
|
|
// 区间 1: (begins1, ends1]
|
|
|
// 区间 2: (begins2, ends2]
|
|
// 区间 2: (begins2, ends2]
|
|
|
// 不重叠的条件:ends1 <= begins2 或 ends2 <= begins1
|
|
// 不重叠的条件:ends1 <= begins2 或 ends2 <= begins1
|
|
|
// 重叠的条件:!(ends1 <= begins2 || ends2 <= begins1)
|
|
// 重叠的条件:!(ends1 <= begins2 || ends2 <= begins1)
|
|
|
boolean isOverlap = !(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]",
|
|
|
|
|
- getCompanyName(rates.get(i).getCompanyType()),
|
|
|
|
|
- getProductName(rates.get(i).getProductType()),
|
|
|
|
|
- i + 1, begins1, ends1,
|
|
|
|
|
- j + 1, begins2, ends2));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (rate1.getRate().compareTo(new BigDecimal("0")) == 0) {
|
|
|
|
|
- throw new ServiceException(String.format(
|
|
|
|
|
- "%s、%s的费率不能为0", getCompanyName(rate1.getCompanyType()), getProductName(rate1.getProductType())));
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- if (rate1.getRate().compareTo(rate2.getRate()) < 0) {
|
|
|
|
|
|
|
+ if (isOverlap) {
|
|
|
throw new ServiceException(String.format(
|
|
throw new ServiceException(String.format(
|
|
|
- "%s、%s的费率配置有误:区间%d(%d,%d] 与区间%d(%d,%d]",
|
|
|
|
|
- getCompanyName(rates.get(i).getCompanyType()),
|
|
|
|
|
- getProductName(rates.get(i).getProductType()),
|
|
|
|
|
|
|
+ "%s、%s的区间配置存在重叠:第%d条规则(%d,%d] 与第%d条规则(%d,%d]",
|
|
|
|
|
+ companyName, productName,
|
|
|
i + 1, begins1, ends1,
|
|
i + 1, begins1, ends1,
|
|
|
j + 1, begins2, ends2));
|
|
j + 1, begins2, ends2));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 校验费率递减:起始金额小的区间,费率应该更大或相等
|
|
|
|
|
+ for (int i = 0; i < rates.size() - 1; i++) {
|
|
|
|
|
+ SysDeptRate currentRate = rates.get(i);
|
|
|
|
|
+ SysDeptRate nextRate = rates.get(i + 1);
|
|
|
|
|
+
|
|
|
|
|
+ if (currentRate.getRate().compareTo(nextRate.getRate()) < 0) {
|
|
|
|
|
+ throw new ServiceException(String.format(
|
|
|
|
|
+ "%s、%s的费率配置有误:第%d条规则费率%.2f应大于等于第%d条规则费率%.2f",
|
|
|
|
|
+ companyName, productName,
|
|
|
|
|
+ i + 1, currentRate.getRate(),
|
|
|
|
|
+ i + 2, nextRate.getRate()));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static String getCompanyName(String companyType) {
|
|
private static String getCompanyName(String companyType) {
|