|
...
|
...
|
@@ -49,10 +49,13 @@ import java.math.BigDecimal; |
|
49
|
49
|
import java.math.RoundingMode;
|
|
50
|
50
|
import java.time.LocalDate;
|
|
51
|
51
|
import java.time.LocalDateTime;
|
|
|
52
|
+import java.time.YearMonth;
|
|
52
|
53
|
import java.time.temporal.ChronoUnit;
|
|
53
|
54
|
import java.time.temporal.TemporalAdjusters;
|
|
54
|
55
|
import java.util.*;
|
|
55
|
56
|
import java.util.function.Function;
|
|
|
57
|
+import java.util.regex.Matcher;
|
|
|
58
|
+import java.util.regex.Pattern;
|
|
56
|
59
|
import java.util.stream.Collectors;
|
|
57
|
60
|
|
|
58
|
61
|
|
|
...
|
...
|
@@ -495,13 +498,17 @@ public class ReceiptLedgerInfoServiceImpl extends BaseMpServiceImpl<ReceiptLedge |
|
495
|
498
|
return result;
|
|
496
|
499
|
}
|
|
497
|
500
|
List<String> shortNames = dataList.stream().map(ReceiptLedgerReportBo::getCustomerShortName).distinct().collect(Collectors.toList());
|
|
|
501
|
+ // 根据简称获取台账明细数据
|
|
|
502
|
+ Map<String, List<ReceiptLedgerInfo>> agreementDataMap = getLedgerInfoByShortName(shortNames, Boolean.FALSE);
|
|
|
503
|
+ Map<String, List<ReceiptLedgerInfo>> overdueDataMap = getLedgerInfoByShortName(shortNames, Boolean.TRUE);
|
|
498
|
504
|
// 只统计约定内、一次、二次协调、清欠阶段
|
|
499
|
505
|
List<String> debtStatusList = new ArrayList<>();
|
|
500
|
506
|
debtStatusList.add("AGREEMENT");
|
|
501
|
507
|
debtStatusList.add("FIRST_COORDINATE");
|
|
502
|
508
|
debtStatusList.add("SECOND_COORDINATE");
|
|
503
|
509
|
debtStatusList.add("CLEAR_DEBTS");
|
|
504
|
|
- List<Map<String, Object>> debtAmountList = getBaseMapper().statisticsDeptByShortName(shortNames, debtStatusList);
|
|
|
510
|
+ debtStatusList.add("DEPOSIT");
|
|
|
511
|
+ List<Map<String, Object>> debtAmountList = getBaseMapper().statisticsDebtByShortName(shortNames, debtStatusList, "INSIDE");
|
|
505
|
512
|
if (CollectionUtils.isEmpty(debtAmountList)) {
|
|
506
|
513
|
return result;
|
|
507
|
514
|
}
|
|
...
|
...
|
@@ -525,12 +532,8 @@ public class ReceiptLedgerInfoServiceImpl extends BaseMpServiceImpl<ReceiptLedge |
|
525
|
532
|
if (CollectionUtils.isEmpty(list)) {
|
|
526
|
533
|
continue;
|
|
527
|
534
|
}
|
|
528
|
|
- BigDecimal debtTotal = BigDecimal.ZERO;
|
|
529
|
|
- BigDecimal agreementTotal = BigDecimal.ZERO;
|
|
530
|
|
- BigDecimal firstCoordinateTotal = BigDecimal.ZERO;
|
|
531
|
|
- BigDecimal secondCoordinateTotal = BigDecimal.ZERO;
|
|
532
|
|
- BigDecimal clearDebtTotal = BigDecimal.ZERO;
|
|
533
|
535
|
long waitDeliveredOrderTotal = 0;
|
|
|
536
|
+ List<String> creditStatusList = new ArrayList<>();
|
|
534
|
537
|
List<String> debtStates = new ArrayList<>();
|
|
535
|
538
|
Map<String, ReceiptLedgerReportDetail> reportDetailMap = new LinkedHashMap<>();
|
|
536
|
539
|
for (Map<String, Object> map : list) {
|
|
...
|
...
|
@@ -545,24 +548,31 @@ public class ReceiptLedgerInfoServiceImpl extends BaseMpServiceImpl<ReceiptLedge |
|
545
|
548
|
}
|
|
546
|
549
|
reportDetail.setCustomerName(customerName);
|
|
547
|
550
|
reportDetail.setCreditStatus(debtStatus);
|
|
548
|
|
- if ("AGREEMENT".equals(debtStatus)) {
|
|
549
|
|
- reportDetail.setAgreement(valueConvert(debtAmount));
|
|
550
|
|
- agreementTotal = agreementTotal.add(debtAmount);
|
|
|
551
|
+ if ("AGREEMENT".equals(debtStatus) || "DEPOSIT".equals(debtStatus)) {
|
|
|
552
|
+ BigDecimal agreement = reportDetail.getAgreement();
|
|
|
553
|
+ if (agreement == null) {
|
|
|
554
|
+ agreement = debtAmount;
|
|
|
555
|
+ } else {
|
|
|
556
|
+ agreement = agreement.add(debtAmount);
|
|
|
557
|
+ }
|
|
|
558
|
+ reportDetail.setAgreement(valueConvert(agreement));
|
|
551
|
559
|
reportDetail.setCreditStatus("约定内");
|
|
552
|
560
|
} else if ("FIRST_COORDINATE".equals(debtStatus)) {
|
|
553
|
561
|
reportDetail.setFirstCoordinate(valueConvert(debtAmount));
|
|
554
|
|
- firstCoordinateTotal = firstCoordinateTotal.add(debtAmount);
|
|
555
|
562
|
reportDetail.setCreditStatus("超期1");
|
|
556
|
563
|
} else if ("SECOND_COORDINATE".equals(debtStatus)) {
|
|
557
|
564
|
reportDetail.setSecondCoordinate(valueConvert(debtAmount));
|
|
558
|
|
- secondCoordinateTotal = secondCoordinateTotal.add(debtAmount);
|
|
559
|
565
|
reportDetail.setCreditStatus("超期2");
|
|
560
|
566
|
} else if ("CLEAR_DEBTS".equals(debtStatus)) {
|
|
561
|
567
|
reportDetail.setClearDebt(valueConvert(debtAmount));
|
|
562
|
|
- clearDebtTotal = clearDebtTotal.add(debtAmount);
|
|
563
|
568
|
reportDetail.setCreditStatus("超期3");
|
|
564
|
569
|
}
|
|
565
|
|
- debtTotal = debtTotal.add(debtAmount);
|
|
|
570
|
+ // 计算超额数据(授信状态)
|
|
|
571
|
+ String creditStatus = calculateExcess(debtAmount, report.getQuota());
|
|
|
572
|
+ if (StringUtils.isNotBlank(creditStatus)) {
|
|
|
573
|
+ report.setCreditStatus(creditStatus);
|
|
|
574
|
+ creditStatusList.add(creditStatus);
|
|
|
575
|
+ }
|
|
566
|
576
|
// 统计待交付订单数
|
|
567
|
577
|
Long count = orderCountMap.get(customerName);
|
|
568
|
578
|
if (count != null) {
|
|
...
|
...
|
@@ -575,14 +585,15 @@ public class ReceiptLedgerInfoServiceImpl extends BaseMpServiceImpl<ReceiptLedge |
|
575
|
585
|
List<ReceiptLedgerReportDetail> details = new ArrayList<>(reportDetailMap.values());
|
|
576
|
586
|
report.setDetailList(details);
|
|
577
|
587
|
|
|
578
|
|
- report.setDebtTotal(valueConvert(debtTotal));
|
|
579
|
|
- report.setAgreementTotal(valueConvert(agreementTotal));
|
|
580
|
|
- report.setFirstCoordinateTotal(valueConvert(firstCoordinateTotal));
|
|
581
|
|
- report.setSecondCoordinateTotal(valueConvert(secondCoordinateTotal));
|
|
582
|
|
- report.setClearDebtTotal(valueConvert(clearDebtTotal));
|
|
583
|
|
- report.setCreditStatus(getHighestPriorityStatus(debtStates));
|
|
584
|
|
- // 处理超额逻辑
|
|
|
588
|
+ // 处理约定内、一次协调、二次协调、清欠小计数据
|
|
|
589
|
+ handleSubtotal(agreementDataMap, overdueDataMap, report);
|
|
|
590
|
+ // 授时状态
|
|
|
591
|
+ report.setTimingStatus(getHighestPriorityStatus(debtStates));
|
|
|
592
|
+ // 授信状态
|
|
|
593
|
+ report.setCreditStatus(findMaxPercentageString(creditStatusList));
|
|
585
|
594
|
report.setWaitDeliveredOrderTotal(waitDeliveredOrderTotal);
|
|
|
595
|
+ BigDecimal debtTotal = report.getDebtTotal();
|
|
|
596
|
+ report.setDebtTotal(valueConvert(debtTotal));
|
|
586
|
597
|
}
|
|
587
|
598
|
return result;
|
|
588
|
599
|
}
|
|
...
|
...
|
@@ -852,6 +863,36 @@ public class ReceiptLedgerInfoServiceImpl extends BaseMpServiceImpl<ReceiptLedge |
|
852
|
863
|
shipmentsPlanDetailService.delByOrderIds(needFreezeOrderIds);
|
|
853
|
864
|
}
|
|
854
|
865
|
|
|
|
866
|
+ @Override
|
|
|
867
|
+ public void autoUpdateDebtStatus() {
|
|
|
868
|
+ // 获取当月所有台账明细数据
|
|
|
869
|
+ QueryReceiptLedgerInfoVo ledgerInfoVo = new QueryReceiptLedgerInfoVo();
|
|
|
870
|
+ LocalDateTime startTime = YearMonth.now()
|
|
|
871
|
+ .atDay(1)
|
|
|
872
|
+ .atStartOfDay();
|
|
|
873
|
+ LocalDateTime endTime = YearMonth.now()
|
|
|
874
|
+ .atEndOfMonth()
|
|
|
875
|
+ .atTime(23, 59, 59);
|
|
|
876
|
+ ledgerInfoVo.setCreateTimeStart(startTime.toString());
|
|
|
877
|
+ ledgerInfoVo.setCreateTimeEnd(endTime.toString());
|
|
|
878
|
+ List<ReceiptLedgerInfo> ledgerInfoList = getBaseMapper().query(ledgerInfoVo);
|
|
|
879
|
+ if (CollectionUtils.isEmpty(ledgerInfoList)) {
|
|
|
880
|
+ return;
|
|
|
881
|
+ }
|
|
|
882
|
+ for (ReceiptLedgerInfo info : ledgerInfoList) {
|
|
|
883
|
+ BigDecimal endAccountReceivable = info.getEndAccountReceivable();
|
|
|
884
|
+ LocalDate processedDate = info.getProcessedDate();
|
|
|
885
|
+ if (processedDate != null) {
|
|
|
886
|
+ // 更新欠款状态
|
|
|
887
|
+ String debtStatus = getSettlementStatus(endAccountReceivable, processedDate);
|
|
|
888
|
+ LambdaUpdateWrapper<ReceiptLedgerInfo> updateWrapper = Wrappers.lambdaUpdate(ReceiptLedgerInfo.class);
|
|
|
889
|
+ updateWrapper.set(ReceiptLedgerInfo::getDebtStatus, debtStatus)
|
|
|
890
|
+ .eq(ReceiptLedgerInfo::getId, info.getId());
|
|
|
891
|
+ getBaseMapper().update(updateWrapper);
|
|
|
892
|
+ }
|
|
|
893
|
+ }
|
|
|
894
|
+ }
|
|
|
895
|
+
|
|
855
|
896
|
|
|
856
|
897
|
/**
|
|
857
|
898
|
* 从多个状态中获取最高优先级的状态
|
|
...
|
...
|
@@ -911,4 +952,96 @@ public class ReceiptLedgerInfoServiceImpl extends BaseMpServiceImpl<ReceiptLedge |
|
911
|
952
|
OpLogUtil.setVariable("id", data.getId());
|
|
912
|
953
|
OpLogUtil.setExtra(vo);
|
|
913
|
954
|
}
|
|
|
955
|
+
|
|
|
956
|
+
|
|
|
957
|
+ /**
|
|
|
958
|
+ * 计算超额比例
|
|
|
959
|
+ *
|
|
|
960
|
+ * @param amount 欠款金额
|
|
|
961
|
+ * @param quota 额度
|
|
|
962
|
+ * @return String
|
|
|
963
|
+ */
|
|
|
964
|
+ private String calculateExcess(BigDecimal amount, BigDecimal quota) {
|
|
|
965
|
+ if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0
|
|
|
966
|
+ || quota == null || quota.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
967
|
+ return null;
|
|
|
968
|
+ }
|
|
|
969
|
+ // 万元转换成元
|
|
|
970
|
+ quota = quota.multiply(new BigDecimal(10000));
|
|
|
971
|
+ if (amount.compareTo(quota) <= 0) {
|
|
|
972
|
+ return null;
|
|
|
973
|
+ }
|
|
|
974
|
+ BigDecimal result = amount.subtract(quota)
|
|
|
975
|
+ .divide(quota, 2, RoundingMode.HALF_UP)
|
|
|
976
|
+ .multiply(new BigDecimal(100))
|
|
|
977
|
+ .divide(new BigDecimal("5"), 0, RoundingMode.CEILING)
|
|
|
978
|
+ .multiply(new BigDecimal("5"));
|
|
|
979
|
+
|
|
|
980
|
+ return "超额" + result + "%";
|
|
|
981
|
+ }
|
|
|
982
|
+
|
|
|
983
|
+
|
|
|
984
|
+ /**
|
|
|
985
|
+ * 获取最大值对应的完整字符串
|
|
|
986
|
+ */
|
|
|
987
|
+ public static String findMaxPercentageString(List<String> dataList) {
|
|
|
988
|
+ if (CollectionUtils.isEmpty(dataList)) {
|
|
|
989
|
+ return null;
|
|
|
990
|
+ }
|
|
|
991
|
+ String maxString = null;
|
|
|
992
|
+ int maxValue = 0;
|
|
|
993
|
+ for (String str : dataList) {
|
|
|
994
|
+ // 提取数字
|
|
|
995
|
+ Pattern pattern = Pattern.compile("(\\d+)%");
|
|
|
996
|
+ Matcher matcher = pattern.matcher(str);
|
|
|
997
|
+ if (matcher.find()) {
|
|
|
998
|
+ int value = Integer.parseInt(matcher.group(1));
|
|
|
999
|
+ if (value > maxValue) {
|
|
|
1000
|
+ maxValue = value;
|
|
|
1001
|
+ maxString = str;
|
|
|
1002
|
+ }
|
|
|
1003
|
+ }
|
|
|
1004
|
+ }
|
|
|
1005
|
+ return maxString;
|
|
|
1006
|
+ }
|
|
|
1007
|
+
|
|
|
1008
|
+
|
|
|
1009
|
+ /**
|
|
|
1010
|
+ * 处理“小计”数据
|
|
|
1011
|
+ *
|
|
|
1012
|
+ * @param agreementDataMap 约定内数据集合
|
|
|
1013
|
+ * @param overdueDataMap 逾期数据集合
|
|
|
1014
|
+ * @param report 报表数据
|
|
|
1015
|
+ */
|
|
|
1016
|
+ private void handleSubtotal(Map<String, List<ReceiptLedgerInfo>> agreementDataMap, Map<String, List<ReceiptLedgerInfo>> overdueDataMap
|
|
|
1017
|
+ , ReceiptLedgerReportBo report) {
|
|
|
1018
|
+ String customerShortName = report.getCustomerShortName();
|
|
|
1019
|
+ }
|
|
|
1020
|
+
|
|
|
1021
|
+
|
|
|
1022
|
+ /**
|
|
|
1023
|
+ * 获取台账明细数据
|
|
|
1024
|
+ * 根据客户简称、状态分组
|
|
|
1025
|
+ *
|
|
|
1026
|
+ * @param shortNames 客户简称集合
|
|
|
1027
|
+ * @param overdue 是否逾期
|
|
|
1028
|
+ * @return Map<String, List<ReceiptLedgerInfo>>
|
|
|
1029
|
+ */
|
|
|
1030
|
+ private Map<String, List<ReceiptLedgerInfo>> getLedgerInfoByShortName(List<String> shortNames, Boolean overdue) {
|
|
|
1031
|
+ // 根据简称获取台账明细
|
|
|
1032
|
+ List<ReceiptLedgerInfo> ledgerInfoList = getBaseMapper().queryByShortName(shortNames, "INSIDE", overdue);
|
|
|
1033
|
+ if (CollectionUtils.isEmpty(ledgerInfoList)) {
|
|
|
1034
|
+ return Collections.emptyMap();
|
|
|
1035
|
+ }
|
|
|
1036
|
+ // 根据欠款状态分组
|
|
|
1037
|
+ Map<String, List<ReceiptLedgerInfo>> ledgerInfoMap = new HashMap<>();
|
|
|
1038
|
+ for (ReceiptLedgerInfo ledgerInfo : ledgerInfoList) {
|
|
|
1039
|
+ String debtStatus = ledgerInfo.getDebtStatus();
|
|
|
1040
|
+ String shortName = ledgerInfo.getCustomerShortName();
|
|
|
1041
|
+ String key = shortName + "_" + debtStatus;
|
|
|
1042
|
+ List<ReceiptLedgerInfo> list = ledgerInfoMap.computeIfAbsent(key, k -> new ArrayList<>());
|
|
|
1043
|
+ list.add(ledgerInfo);
|
|
|
1044
|
+ }
|
|
|
1045
|
+ return ledgerInfoMap;
|
|
|
1046
|
+ }
|
|
914
|
1047
|
} |
...
|
...
|
|