diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/tmp/compileJava/previous-compilation-data.bin b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/tmp/compileJava/previous-compilation-data.bin index 4c61c25..0cd27be 100644 Binary files a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/tmp/compileJava/previous-compilation-data.bin and b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/job/WaterproofPaintAccountsReceivableJob.java b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/job/WaterproofPaintAccountsReceivableJob.java index 47e9b0e..f3a85af 100644 --- a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/job/WaterproofPaintAccountsReceivableJob.java +++ b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/job/WaterproofPaintAccountsReceivableJob.java @@ -96,17 +96,17 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { // sql += " AND F_SFNBJY ='否'"; // } sql += " GROUP BY FCUSTNAME,XSZZ"; - List customerMaps = DBSql.getMaps(sql); -// List customerMaps = new ArrayList<>(); -// HashMap hashMap = new HashMap<>(); -// hashMap.put("QYGS","北方区域公司"); -// hashMap.put("FCUSTNAME","大连红太阳防水保温工程有限公司"); -// hashMap.put("FPROVINCE","辽宁省"); -// hashMap.put("FCITY","大连市"); -// hashMap.put("FDISTRICT",""); -// hashMap.put("XSZZ","北新禹王防水科技集团有限公司"); -// RowMap map = new RowMap(hashMap); -// customerMaps.add(map); +// List customerMaps = DBSql.getMaps(sql); + List customerMaps = new ArrayList<>(); + HashMap hashMap = new HashMap<>(); + hashMap.put("QYGS","北方区域公司"); + hashMap.put("FCUSTNAME","大连红太阳防水保温工程有限公司"); + hashMap.put("FPROVINCE","辽宁省"); + hashMap.put("FCITY","大连市"); + hashMap.put("FDISTRICT",""); + hashMap.put("XSZZ","北新禹王防水科技集团有限公司"); + RowMap map = new RowMap(hashMap); + customerMaps.add(map); if (customerMaps == null || customerMaps.isEmpty()) { LOGGER.warn("{}板块未查询到销售组织和客户数据", sectionName); @@ -117,6 +117,9 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { // 分批次处理客户数据 int totalCustomers = customerMaps.size(); + // 预加载所有客户的历史余额数据 + Map> historicalBalanceData = preloadAllHistoricalBalanceData(customerMaps); + LOGGER.info("成功预加载 {} 个客户的历史余额数据", historicalBalanceData.size()); for (int i = 0; i < totalCustomers; i += CUSTOMER_BATCH_SIZE) { int endIndex = Math.min(i + CUSTOMER_BATCH_SIZE, totalCustomers); List batchCustomers = customerMaps.subList(i, endIndex); @@ -124,7 +127,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { LOGGER.info("{}板块正在处理第 {} 批客户,进度: {}/{}", 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) { LOGGER.error("{}板块第 {} 批客户处理失败", sectionName, (i / CUSTOMER_BATCH_SIZE) + 1); return false; @@ -140,11 +143,154 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { } } + /** + * 预加载所有客户的历史余额数据 + */ + private Map> preloadAllHistoricalBalanceData(List customerMaps) { + Map> historicalBalanceData = new HashMap<>(); + + try { + // 提取所有销售组织和客户名称 + List saleOrgUnits = customerMaps.stream() + .map(row -> row.getString("XSZZ")) + .distinct() + .collect(Collectors.toList()); + + List custNames = customerMaps.stream() + .map(row -> row.getString("FCUSTNAME")) + .distinct() + .collect(Collectors.toList()); + + // 批量查询所有客户的历史余额数据 + List 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> historicalBalanceData, + List 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 balanceMap = historicalBalanceData.get(key); + for (String period : periods) { + balanceMap.putIfAbsent(period, 0.0); + } + } + } + + /** + * 批量查询所有客户的历史余额数据 + */ + private List batchQueryAllHistoricalBalanceData(List saleOrgUnits, List 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 customerBatch, - LocalDate startDate, LocalDate endDate) { + LocalDate startDate, LocalDate endDate,Map> historicalBalanceData) { try { // 提取销售组织和客户名称列表 List saleOrgUnits = customerBatch.stream() @@ -164,7 +310,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { // 批量预加载所有需要的数据 Map preloadedResults = preloadAllData( - section, saleOrgUnits, custNames, monthEndDates); + section, saleOrgUnits, custNames, monthEndDates, historicalBalanceData); // 批量处理数据 List allRecords = new ArrayList<>(); @@ -191,7 +337,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { Map zlfx = new HashMap<>(); 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); - zlfx.put(zlfxKey, value); + zlfx.put(zlfxKey, value.subtract(qcye)); } // 创建记录 @@ -242,7 +388,8 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { * 预加载所有需要的数据 */ private Map preloadAllData(Section section, - List saleOrgUnits, List custNames, List monthEndDates) { + List saleOrgUnits, List custNames, + List monthEndDates,Map> historicalBalanceData) { LOGGER.info("预加载数据开始"); Map results = new HashMap<>(); @@ -261,9 +408,9 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { // 批量查询收款退款单数据 Map sktkData = batchQuerySKTKDData(section, saleOrgUnits, custNames, extendedMonthEndDates); // 批量查询历史余额数据 - Map historyData = batchQueryHistoryBalance(section, saleOrgUnits, custNames, extendedMonthEndDates); +// Map 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) { LOGGER.error("预加载数据时发生错误", e); } @@ -453,7 +600,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { */ private Map batchQueryHistoryBalance(Section section, List saleOrgUnits, List custNames, List monthEndDates) { - + List arrayList = new ArrayList<>(); Map result = new HashMap<>(); try { @@ -490,7 +637,8 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { */ private void calculateAllMetrics(Map results, Map ysData, Map skData, - Map sktkData, Map historyData, + Map sktkData, + Map> historicalBalanceData, // 新增参数 List saleOrgUnits, List custNames, List monthEndDates, List extendedMonthEndDates) { @@ -521,7 +669,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { BigDecimal ysye = qcye.add(ljxs).subtract(ljhk); // 计算账龄分析 - Map zlfx = calculateAgingAnalysis(historyData, saleOrgUnit, custName, monthEndDate, ysye); + Map zlfx = calculateAgingAnalysis(historicalBalanceData, saleOrgUnit, custName, 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 + "LJHK_" + monthEndDate, ljhk); // LOGGER.info("计算{}:{}",keyPrefix + "YSYE_" + monthEndDate, ysye); - for (Map.Entry entry : zlfx.entrySet()) { results.put(keyPrefix + entry.getKey() + "_" + monthEndDate, entry.getValue()); + LOGGER.info("KEY:{},value:{}",keyPrefix + entry.getKey() + "_" + monthEndDate,entry.getValue()); } } catch (Exception e) { LOGGER.error("计算指标时发生错误,销售组织: {}, 客户: {}, 日期: {}", @@ -589,37 +737,38 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { /** * 计算账龄分析 */ - private Map calculateAgingAnalysis(Map historyData, - String saleOrgUnit, String custName, LocalDate currentDate, BigDecimal currentBalance) { + private Map calculateAgingAnalysis(Map> historicalBalanceData, + String saleOrgUnit, String custName, LocalDate currentDate, BigDecimal openingBalance) { Map result = new HashMap<>(); - String keyPrefix = saleOrgUnit + "_" + custName + "_"; + String key = saleOrgUnit + "_" + custName; try { - // 计算各个时间点的历史余额 - LocalDate date60DaysAgo = currentDate.minusDays(60); - LocalDate date1YearAgo = currentDate.minusYears(1); - LocalDate date2YearsAgo = currentDate.minusYears(2); - LocalDate date3YearsAgo = currentDate.minusYears(3); - LocalDate date4YearsAgo = currentDate.minusYears(4); - LocalDate date5YearsAgo = currentDate.minusYears(5); + // 从预加载的历史余额数据中获取该客户的数据 + Map balanceMap = historicalBalanceData.get(key); + + if (balanceMap == null) { + LOGGER.warn("未找到客户 {} 的历史余额数据", key); + balanceMap = new HashMap<>(); + } // 查找历史余额 - BigDecimal balance60DaysAgo = findHistoricalBalance(historyData, keyPrefix, date60DaysAgo); - BigDecimal balance1YearAgo = findHistoricalBalance(historyData, keyPrefix, date1YearAgo); - BigDecimal balance2YearsAgo = findHistoricalBalance(historyData, keyPrefix, date2YearsAgo); - BigDecimal balance3YearsAgo = findHistoricalBalance(historyData, keyPrefix, date3YearsAgo); - BigDecimal balance4YearsAgo = findHistoricalBalance(historyData, keyPrefix, date4YearsAgo); - BigDecimal balance5YearsAgo = findHistoricalBalance(historyData, keyPrefix, date5YearsAgo); + BigDecimal balance60DaysAgo = BigDecimal.valueOf(balanceMap.get("60天")); + BigDecimal balance1YearAgo = BigDecimal.valueOf(balanceMap.get("1年")); + BigDecimal balance2YearsAgo = BigDecimal.valueOf(balanceMap.get("2年")); + BigDecimal balance3YearsAgo = BigDecimal.valueOf(balanceMap.get("3年")); + BigDecimal balance4YearsAgo = BigDecimal.valueOf(balanceMap.get("4年")); + 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("ZLFX60_1", balance60DaysAgo.subtract(balance1YearAgo.max(BigDecimal.ZERO))); - result.put("ZLFX1_2", balance1YearAgo.subtract(balance2YearsAgo.max(BigDecimal.ZERO))); - result.put("ZLFX2_3", balance2YearsAgo.subtract(balance3YearsAgo.max(BigDecimal.ZERO))); - result.put("ZLFX3_4", balance3YearsAgo.subtract(balance4YearsAgo.max(BigDecimal.ZERO))); - result.put("ZLFX4_5", balance4YearsAgo.subtract(balance5YearsAgo.max(BigDecimal.ZERO))); - result.put("ZLFX5", balance5YearsAgo.max(BigDecimal.ZERO)); + result.put("ZLFX0_60", balance60DaysAgo.subtract(openingBalance)); + result.put("ZLFX60_1", balance1YearAgo.subtract(balance60DaysAgo).subtract(openingBalance)); + result.put("ZLFX1_2", balance2YearsAgo.subtract(balance1YearAgo).subtract(openingBalance)); + result.put("ZLFX2_3", balance3YearsAgo.subtract(balance2YearsAgo).subtract(openingBalance)); + result.put("ZLFX3_4", balance4YearsAgo.subtract(balance3YearsAgo).subtract(openingBalance)); + result.put("ZLFX4_5", balance5YearsAgo.subtract(balance4YearsAgo).subtract(openingBalance)); + result.put("ZLFX5", balance5YearsLastAgo); } catch (Exception e) { LOGGER.error("计算账龄分析时发生错误,销售组织: {}, 客户: {}", saleOrgUnit, custName, e); @@ -636,18 +785,6 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { return result; } - /** - * 查找历史余额 - */ - private BigDecimal findHistoricalBalance(Map 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查询条件 */