1、防水涂料应收方法

This commit is contained in:
llllon 2025-10-31 09:26:00 +08:00
parent d298fbbdf5
commit 933c7f83d4
2 changed files with 194 additions and 57 deletions

View File

@ -96,17 +96,17 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
// sql += " AND F_SFNBJY ='否'"; // sql += " AND F_SFNBJY ='否'";
// } // }
sql += " GROUP BY FCUSTNAME,XSZZ"; sql += " GROUP BY FCUSTNAME,XSZZ";
List<RowMap> customerMaps = DBSql.getMaps(sql); // List<RowMap> customerMaps = DBSql.getMaps(sql);
// List<RowMap> customerMaps = new ArrayList<>(); List<RowMap> customerMaps = new ArrayList<>();
// HashMap<String, Object> hashMap = new HashMap<>(); HashMap<String, Object> hashMap = new HashMap<>();
// hashMap.put("QYGS","北方区域公司"); hashMap.put("QYGS","北方区域公司");
// hashMap.put("FCUSTNAME","大连红太阳防水保温工程有限公司"); hashMap.put("FCUSTNAME","大连红太阳防水保温工程有限公司");
// hashMap.put("FPROVINCE","辽宁省"); hashMap.put("FPROVINCE","辽宁省");
// hashMap.put("FCITY","大连市"); hashMap.put("FCITY","大连市");
// hashMap.put("FDISTRICT",""); hashMap.put("FDISTRICT","");
// hashMap.put("XSZZ","北新禹王防水科技集团有限公司"); hashMap.put("XSZZ","北新禹王防水科技集团有限公司");
// RowMap map = new RowMap(hashMap); RowMap map = new RowMap(hashMap);
// customerMaps.add(map); customerMaps.add(map);
if (customerMaps == null || customerMaps.isEmpty()) { if (customerMaps == null || customerMaps.isEmpty()) {
LOGGER.warn("{}板块未查询到销售组织和客户数据", sectionName); LOGGER.warn("{}板块未查询到销售组织和客户数据", sectionName);
@ -117,6 +117,9 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
// 分批次处理客户数据 // 分批次处理客户数据
int totalCustomers = customerMaps.size(); int totalCustomers = customerMaps.size();
// 预加载所有客户的历史余额数据
Map<String, Map<String, Double>> historicalBalanceData = preloadAllHistoricalBalanceData(customerMaps);
LOGGER.info("成功预加载 {} 个客户的历史余额数据", historicalBalanceData.size());
for (int i = 0; i < totalCustomers; i += CUSTOMER_BATCH_SIZE) { for (int i = 0; i < totalCustomers; i += CUSTOMER_BATCH_SIZE) {
int endIndex = Math.min(i + CUSTOMER_BATCH_SIZE, totalCustomers); int endIndex = Math.min(i + CUSTOMER_BATCH_SIZE, totalCustomers);
List<RowMap> batchCustomers = customerMaps.subList(i, endIndex); List<RowMap> batchCustomers = customerMaps.subList(i, endIndex);
@ -124,7 +127,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
LOGGER.info("{}板块正在处理第 {} 批客户,进度: {}/{}", LOGGER.info("{}板块正在处理第 {} 批客户,进度: {}/{}",
sectionName, (i / CUSTOMER_BATCH_SIZE) + 1, endIndex, totalCustomers); sectionName, (i / CUSTOMER_BATCH_SIZE) + 1, endIndex, totalCustomers);
boolean batchSuccess = processCustomerBatch(section, batchCustomers, startDate, endDate); boolean batchSuccess = processCustomerBatch(section, batchCustomers, startDate, endDate, historicalBalanceData);
if (!batchSuccess) { if (!batchSuccess) {
LOGGER.error("{}板块第 {} 批客户处理失败", sectionName, (i / CUSTOMER_BATCH_SIZE) + 1); LOGGER.error("{}板块第 {} 批客户处理失败", sectionName, (i / CUSTOMER_BATCH_SIZE) + 1);
return false; return false;
@ -140,11 +143,154 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
} }
} }
/**
* 预加载所有客户的历史余额数据
*/
private Map<String, Map<String, Double>> preloadAllHistoricalBalanceData(List<RowMap> customerMaps) {
Map<String, Map<String, Double>> historicalBalanceData = new HashMap<>();
try {
// 提取所有销售组织和客户名称
List<String> saleOrgUnits = customerMaps.stream()
.map(row -> row.getString("XSZZ"))
.distinct()
.collect(Collectors.toList());
List<String> custNames = customerMaps.stream()
.map(row -> row.getString("FCUSTNAME"))
.distinct()
.collect(Collectors.toList());
// 批量查询所有客户的历史余额数据
List<RowMap> allBalanceData = batchQueryAllHistoricalBalanceData(saleOrgUnits, custNames);
// 按销售组织和客户名称组织数据
for (RowMap row : allBalanceData) {
String saleOrgUnit = row.getString("XSZZ");
String custName = row.getString("FCUSTNAME");
String period = row.getString("period");
String key = saleOrgUnit + "_" + custName;
if (!historicalBalanceData.containsKey(key)) {
historicalBalanceData.put(key, new HashMap<>());
}
BigDecimal totalYsAmount = BigDecimal.ZERO;
BigDecimal totalSkAmount = BigDecimal.ZERO;
BigDecimal totalSktkAmount = BigDecimal.ZERO;
String ysamount = StringUtils.isNotBlank(row.getString("ys")) ? row.getString("ys") : "0.00";
String skamount = StringUtils.isNotBlank(row.getString("sk")) ? row.getString("sk") : "0.00";
String tkamount = StringUtils.isNotBlank(row.getString("tk")) ? row.getString("tk") : "0.00";
totalYsAmount = new BigDecimal(ysamount);
totalSkAmount = new BigDecimal(skamount);
totalSktkAmount = new BigDecimal(tkamount);
// 计算公式累计应收金额 - (累计收款金额 - 累计收款退款金额)
BigDecimal balance = totalYsAmount.subtract(totalSkAmount.subtract(totalSktkAmount));
LOGGER.info("totalYsAmount:{},totalSkAmount:{},totalSktkAmount:{},balance:{}",totalYsAmount,totalSkAmount,totalSktkAmount,balance);
historicalBalanceData.get(key).put(period, balance.doubleValue());
}
// 确保所有客户的所有期间都有值
ensureAllCustomersHaveAllPeriods(historicalBalanceData, customerMaps);
} catch (Exception e) {
LOGGER.error("预加载所有客户历史余额数据时发生错误", e);
}
return historicalBalanceData;
}
/**
* 确保所有客户的所有期间都有值
*/
private void ensureAllCustomersHaveAllPeriods(Map<String, Map<String, Double>> historicalBalanceData,
List<RowMap> customerMaps) {
String[] periods = {"60天", "1年", "2年", "3年", "4年", "5年", "5年以上"};
for (RowMap customer : customerMaps) {
String saleOrgUnit = customer.getString("XSZZ");
String custName = customer.getString("FCUSTNAME");
String key = saleOrgUnit + "_" + custName;
if (!historicalBalanceData.containsKey(key)) {
historicalBalanceData.put(key, new HashMap<>());
}
Map<String, Double> balanceMap = historicalBalanceData.get(key);
for (String period : periods) {
balanceMap.putIfAbsent(period, 0.0);
}
}
}
/**
* 批量查询所有客户的历史余额数据
*/
private List<RowMap> batchQueryAllHistoricalBalanceData(List<String> saleOrgUnits, List<String> custNames) {
try {
String inSaleOrgs = buildInCondition(saleOrgUnits);
String inCustNames = buildInCondition(custNames);
String sql = "SELECT XSZZ, FCUSTNAME, period, SUM(ys) AS ys, SUM(sk) AS sk, SUM(tk) AS tk\n" +
" FROM ( SELECT XSZZ, FCUSTNAME,\n" +
" CASE\n" +
" WHEN DZRQ >= DATE_SUB(NOW(), INTERVAL 60 DAY) THEN '60天'\n" +
" WHEN DZRQ >= DATE_SUB(NOW(), INTERVAL 1 YEAR) THEN '1年'\n" +
" WHEN DZRQ >= DATE_SUB(NOW(), INTERVAL 2 YEAR) THEN '2年'\n" +
" WHEN DZRQ >= DATE_SUB(NOW(), INTERVAL 3 YEAR) THEN '3年'\n" +
" WHEN DZRQ >= DATE_SUB(NOW(), INTERVAL 4 YEAR) THEN '4年'\n" +
" WHEN DZRQ >= DATE_SUB(NOW(), INTERVAL 5 YEAR) THEN '5年'\n" +
" ELSE '5年以上'\n" +
" END AS period, SSJERMB AS ys, 0 AS sk, 0 AS tk\n" +
" FROM BO_EU_SALESDATA_SKD\n" +
" WHERE FCUSTNAME IS NOT NULL AND FCUSTNAME != '' AND XSZZ IS NOT NULL\n" +
" AND XSZZ IN (" + inSaleOrgs + ") AND FCUSTNAME IN (" + inCustNames + ")\n" +
" UNION ALL\n" +
" SELECT FSALEORGUNIT AS XSZZ, FCUSTNAME,\n" +
" CASE\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 60 DAY) THEN '60天'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 1 YEAR) THEN '1年'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 2 YEAR) THEN '2年'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 3 YEAR) THEN '3年'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 4 YEAR) THEN '4年'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 5 YEAR) THEN '5年'\n" +
" ELSE '5年以上'\n" +
" END AS period, 0 AS ys, FSALEAMOUNTRMB AS sk, 0 AS tk\n" +
" FROM BO_EU_FS_SALESDATA_SKD\n" +
" WHERE FCUSTNAME IS NOT NULL AND FCUSTNAME != '' AND FSALEORGUNIT IS NOT NULL\n" +
" AND FSALEORGUNIT IN (" + inSaleOrgs + ") AND FCUSTNAME IN (" + inCustNames + ")\n" +
" UNION ALL\n" +
" SELECT FSALEORGUNIT AS XSZZ, FCUSTNAME,\n" +
" CASE\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 60 DAY) THEN '60天'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 1 YEAR) THEN '1年'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 2 YEAR) THEN '2年'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 3 YEAR) THEN '3年'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 4 YEAR) THEN '4年'\n" +
" WHEN FBILLDATE >= DATE_SUB(NOW(), INTERVAL 5 YEAR) THEN '5年'\n" +
" ELSE '5年以上'\n" +
" END AS period, 0 AS ys, 0 AS sk, FSALEAMOUNTRMB AS tk\n" +
" FROM BO_EU_SALESDATA_SKTKD\n" +
" WHERE FCUSTNAME IS NOT NULL AND FCUSTNAME != '' AND FSALEORGUNIT IS NOT NULL\n" +
" AND FSALEORGUNIT IN (" + inSaleOrgs + ") AND FCUSTNAME IN (" + inCustNames + ")\n" +
" ) AS combined_data\n" +
" GROUP BY XSZZ, FCUSTNAME, period\n" +
" ORDER BY XSZZ, FCUSTNAME,\n" +
" CASE period\n" +
" WHEN '60天' THEN 1\n" +
" WHEN '1年' THEN 2\n" +
" WHEN '2年' THEN 3\n" +
" WHEN '3年' THEN 4\n" +
" WHEN '4年' THEN 5\n" +
" WHEN '5年' THEN 6\n" +
" WHEN '5年以上' THEN 7\n" +
" END";
return DBSql.getMaps(sql);
} catch (Exception e) {
LOGGER.error("批量查询所有客户历史余额数据时发生错误", e);
return new ArrayList<>();
}
}
/** /**
* 处理一批客户数据 * 处理一批客户数据
*/ */
private boolean processCustomerBatch(Section section, List<RowMap> customerBatch, private boolean processCustomerBatch(Section section, List<RowMap> customerBatch,
LocalDate startDate, LocalDate endDate) { LocalDate startDate, LocalDate endDate,Map<String, Map<String, Double>> historicalBalanceData) {
try { try {
// 提取销售组织和客户名称列表 // 提取销售组织和客户名称列表
List<String> saleOrgUnits = customerBatch.stream() List<String> saleOrgUnits = customerBatch.stream()
@ -164,7 +310,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
// 批量预加载所有需要的数据 // 批量预加载所有需要的数据
Map<String, BigDecimal> preloadedResults = preloadAllData( Map<String, BigDecimal> preloadedResults = preloadAllData(
section, saleOrgUnits, custNames, monthEndDates); section, saleOrgUnits, custNames, monthEndDates, historicalBalanceData);
// 批量处理数据 // 批量处理数据
List<BO> allRecords = new ArrayList<>(); List<BO> allRecords = new ArrayList<>();
@ -191,7 +337,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
Map<String, BigDecimal> zlfx = new HashMap<>(); Map<String, BigDecimal> zlfx = new HashMap<>();
for (String zlfxKey : Arrays.asList("ZLFX0_60", "ZLFX60_1", "ZLFX1_2", "ZLFX2_3", "ZLFX3_4", "ZLFX4_5", "ZLFX5")) { for (String zlfxKey : Arrays.asList("ZLFX0_60", "ZLFX60_1", "ZLFX1_2", "ZLFX2_3", "ZLFX3_4", "ZLFX4_5", "ZLFX5")) {
BigDecimal value = getPreloadedValue(preloadedResults, keyPrefix + zlfxKey + "_" + monthEndDate); BigDecimal value = getPreloadedValue(preloadedResults, keyPrefix + zlfxKey + "_" + monthEndDate);
zlfx.put(zlfxKey, value); zlfx.put(zlfxKey, value.subtract(qcye));
} }
// 创建记录 // 创建记录
@ -242,7 +388,8 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
* 预加载所有需要的数据 * 预加载所有需要的数据
*/ */
private Map<String, BigDecimal> preloadAllData(Section section, private Map<String, BigDecimal> preloadAllData(Section section,
List<String> saleOrgUnits, List<String> custNames, List<LocalDate> monthEndDates) { List<String> saleOrgUnits, List<String> custNames,
List<LocalDate> monthEndDates,Map<String, Map<String, Double>> historicalBalanceData) {
LOGGER.info("预加载数据开始"); LOGGER.info("预加载数据开始");
Map<String, BigDecimal> results = new HashMap<>(); Map<String, BigDecimal> results = new HashMap<>();
@ -261,9 +408,9 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
// 批量查询收款退款单数据 // 批量查询收款退款单数据
Map<String, BigDecimal> sktkData = batchQuerySKTKDData(section, saleOrgUnits, custNames, extendedMonthEndDates); Map<String, BigDecimal> sktkData = batchQuerySKTKDData(section, saleOrgUnits, custNames, extendedMonthEndDates);
// 批量查询历史余额数据 // 批量查询历史余额数据
Map<String, BigDecimal> historyData = batchQueryHistoryBalance(section, saleOrgUnits, custNames, extendedMonthEndDates); // Map<String, BigDecimal> historyData = batchQueryHistoryBalance(section, saleOrgUnits, custNames, extendedMonthEndDates);
// 计算所有需要的指标 // 计算所有需要的指标
calculateAllMetrics(results, ysData, skData, sktkData, historyData, saleOrgUnits, custNames, monthEndDates,extendedMonthEndDates); calculateAllMetrics(results, ysData, skData, sktkData, historicalBalanceData, saleOrgUnits, custNames, monthEndDates,extendedMonthEndDates);
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("预加载数据时发生错误", e); LOGGER.error("预加载数据时发生错误", e);
} }
@ -453,7 +600,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
*/ */
private Map<String, BigDecimal> batchQueryHistoryBalance(Section section, List<String> saleOrgUnits, private Map<String, BigDecimal> batchQueryHistoryBalance(Section section, List<String> saleOrgUnits,
List<String> custNames, List<LocalDate> monthEndDates) { List<String> custNames, List<LocalDate> monthEndDates) {
List<String> arrayList = new ArrayList<>();
Map<String, BigDecimal> result = new HashMap<>(); Map<String, BigDecimal> result = new HashMap<>();
try { try {
@ -490,7 +637,8 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
*/ */
private void calculateAllMetrics(Map<String, BigDecimal> results, private void calculateAllMetrics(Map<String, BigDecimal> results,
Map<String, BigDecimal> ysData, Map<String, BigDecimal> skData, Map<String, BigDecimal> ysData, Map<String, BigDecimal> skData,
Map<String, BigDecimal> sktkData, Map<String, BigDecimal> historyData, Map<String, BigDecimal> sktkData,
Map<String, Map<String, Double>> historicalBalanceData, // 新增参数
List<String> saleOrgUnits, List<String> custNames, List<LocalDate> monthEndDates, List<String> saleOrgUnits, List<String> custNames, List<LocalDate> monthEndDates,
List<LocalDate> extendedMonthEndDates) { List<LocalDate> extendedMonthEndDates) {
@ -521,7 +669,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
BigDecimal ysye = qcye.add(ljxs).subtract(ljhk); BigDecimal ysye = qcye.add(ljxs).subtract(ljhk);
// 计算账龄分析 // 计算账龄分析
Map<String, BigDecimal> zlfx = calculateAgingAnalysis(historyData, saleOrgUnit, custName, monthEndDate, ysye); Map<String, BigDecimal> zlfx = calculateAgingAnalysis(historicalBalanceData, saleOrgUnit, custName, monthEndDate, qcye);
// 存储计算结果 // 存储计算结果
results.put(keyPrefix + "QCYE_" + monthEndDate, qcye); results.put(keyPrefix + "QCYE_" + monthEndDate, qcye);
@ -532,9 +680,9 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
// LOGGER.info("计算{}{}",keyPrefix + "LJXS_" + monthEndDate, ljxs); // LOGGER.info("计算{}{}",keyPrefix + "LJXS_" + monthEndDate, ljxs);
// LOGGER.info("计算{}{}",keyPrefix + "LJHK_" + monthEndDate, ljhk); // LOGGER.info("计算{}{}",keyPrefix + "LJHK_" + monthEndDate, ljhk);
// LOGGER.info("计算{}{}",keyPrefix + "YSYE_" + monthEndDate, ysye); // LOGGER.info("计算{}{}",keyPrefix + "YSYE_" + monthEndDate, ysye);
for (Map.Entry<String, BigDecimal> entry : zlfx.entrySet()) { for (Map.Entry<String, BigDecimal> entry : zlfx.entrySet()) {
results.put(keyPrefix + entry.getKey() + "_" + monthEndDate, entry.getValue()); results.put(keyPrefix + entry.getKey() + "_" + monthEndDate, entry.getValue());
LOGGER.info("KEY:{},value:{}",keyPrefix + entry.getKey() + "_" + monthEndDate,entry.getValue());
} }
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("计算指标时发生错误,销售组织: {}, 客户: {}, 日期: {}", LOGGER.error("计算指标时发生错误,销售组织: {}, 客户: {}, 日期: {}",
@ -589,37 +737,38 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
/** /**
* 计算账龄分析 * 计算账龄分析
*/ */
private Map<String, BigDecimal> calculateAgingAnalysis(Map<String, BigDecimal> historyData, private Map<String, BigDecimal> calculateAgingAnalysis(Map<String, Map<String, Double>> historicalBalanceData,
String saleOrgUnit, String custName, LocalDate currentDate, BigDecimal currentBalance) { String saleOrgUnit, String custName, LocalDate currentDate, BigDecimal openingBalance) {
Map<String, BigDecimal> result = new HashMap<>(); Map<String, BigDecimal> result = new HashMap<>();
String keyPrefix = saleOrgUnit + "_" + custName + "_"; String key = saleOrgUnit + "_" + custName;
try { try {
// 计算各个时间点的历史余额 // 从预加载的历史余额数据中获取该客户的数据
LocalDate date60DaysAgo = currentDate.minusDays(60); Map<String, Double> balanceMap = historicalBalanceData.get(key);
LocalDate date1YearAgo = currentDate.minusYears(1);
LocalDate date2YearsAgo = currentDate.minusYears(2); if (balanceMap == null) {
LocalDate date3YearsAgo = currentDate.minusYears(3); LOGGER.warn("未找到客户 {} 的历史余额数据", key);
LocalDate date4YearsAgo = currentDate.minusYears(4); balanceMap = new HashMap<>();
LocalDate date5YearsAgo = currentDate.minusYears(5); }
// 查找历史余额 // 查找历史余额
BigDecimal balance60DaysAgo = findHistoricalBalance(historyData, keyPrefix, date60DaysAgo); BigDecimal balance60DaysAgo = BigDecimal.valueOf(balanceMap.get("60天"));
BigDecimal balance1YearAgo = findHistoricalBalance(historyData, keyPrefix, date1YearAgo); BigDecimal balance1YearAgo = BigDecimal.valueOf(balanceMap.get("1年"));
BigDecimal balance2YearsAgo = findHistoricalBalance(historyData, keyPrefix, date2YearsAgo); BigDecimal balance2YearsAgo = BigDecimal.valueOf(balanceMap.get("2年"));
BigDecimal balance3YearsAgo = findHistoricalBalance(historyData, keyPrefix, date3YearsAgo); BigDecimal balance3YearsAgo = BigDecimal.valueOf(balanceMap.get("3年"));
BigDecimal balance4YearsAgo = findHistoricalBalance(historyData, keyPrefix, date4YearsAgo); BigDecimal balance4YearsAgo = BigDecimal.valueOf(balanceMap.get("4年"));
BigDecimal balance5YearsAgo = findHistoricalBalance(historyData, keyPrefix, date5YearsAgo); BigDecimal balance5YearsAgo = BigDecimal.valueOf(balanceMap.get("5年"));
BigDecimal balance5YearsLastAgo = BigDecimal.valueOf(balanceMap.get("5年以上"));
// 计算各账龄段金额 // 计算各账龄段金额
result.put("ZLFX0_60", currentBalance.subtract(balance60DaysAgo.max(BigDecimal.ZERO))); result.put("ZLFX0_60", balance60DaysAgo.subtract(openingBalance));
result.put("ZLFX60_1", balance60DaysAgo.subtract(balance1YearAgo.max(BigDecimal.ZERO))); result.put("ZLFX60_1", balance1YearAgo.subtract(balance60DaysAgo).subtract(openingBalance));
result.put("ZLFX1_2", balance1YearAgo.subtract(balance2YearsAgo.max(BigDecimal.ZERO))); result.put("ZLFX1_2", balance2YearsAgo.subtract(balance1YearAgo).subtract(openingBalance));
result.put("ZLFX2_3", balance2YearsAgo.subtract(balance3YearsAgo.max(BigDecimal.ZERO))); result.put("ZLFX2_3", balance3YearsAgo.subtract(balance2YearsAgo).subtract(openingBalance));
result.put("ZLFX3_4", balance3YearsAgo.subtract(balance4YearsAgo.max(BigDecimal.ZERO))); result.put("ZLFX3_4", balance4YearsAgo.subtract(balance3YearsAgo).subtract(openingBalance));
result.put("ZLFX4_5", balance4YearsAgo.subtract(balance5YearsAgo.max(BigDecimal.ZERO))); result.put("ZLFX4_5", balance5YearsAgo.subtract(balance4YearsAgo).subtract(openingBalance));
result.put("ZLFX5", balance5YearsAgo.max(BigDecimal.ZERO)); result.put("ZLFX5", balance5YearsLastAgo);
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("计算账龄分析时发生错误,销售组织: {}, 客户: {}", saleOrgUnit, custName, e); LOGGER.error("计算账龄分析时发生错误,销售组织: {}, 客户: {}", saleOrgUnit, custName, e);
@ -636,18 +785,6 @@ public class WaterproofPaintAccountsReceivableJob implements IJob {
return result; return result;
} }
/**
* 查找历史余额
*/
private BigDecimal findHistoricalBalance(Map<String, BigDecimal> historyData, String keyPrefix, LocalDate targetDate) {
// 调整为目标月份的月末日期
LocalDate monthEndDate = targetDate.withDayOfMonth(targetDate.lengthOfMonth());
String dateKey = monthEndDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String fullKey = keyPrefix + dateKey;
return historyData.getOrDefault(fullKey, BigDecimal.ZERO);
}
/** /**
* 构建IN查询条件 * 构建IN查询条件
*/ */