diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/job/SaleDataLinkUpJob.class b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/job/SaleDataLinkUpJob.class index 010f8f8..1c753de 100644 Binary files a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/job/SaleDataLinkUpJob.class and b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/job/SaleDataLinkUpJob.class differ diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleCountDimensionImpl.class b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleCountDimensionImpl.class index 2432cf1..cd04e0f 100644 Binary files a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleCountDimensionImpl.class and b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleCountDimensionImpl.class differ diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleDataSyncServiceImpl.class b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleDataSyncServiceImpl.class index 45c0c94..fda278a 100644 Binary files a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleDataSyncServiceImpl.class and b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleDataSyncServiceImpl.class differ 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 55c4f8a..f956245 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 c40e3a6..c1478f6 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 @@ -6,7 +6,6 @@ import com.actionsoft.bpms.schedule.IJob; import com.actionsoft.bpms.server.UserContext; import com.actionsoft.bpms.util.DBSql; import com.actionsoft.sdk.local.SDK; -import com.actionsoft.sdk.local.api.cc.RDSAPI; import com.awspaas.user.apps.bnbm.datalinkup.enums.Section; import org.apache.commons.lang3.StringUtils; import org.quartz.JobExecutionContext; @@ -19,27 +18,27 @@ import java.time.LocalDate; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.stream.Collectors; /** * @ClassName: WaterproofPaintAccountsReceivableJob - * @Description: 防水涂料计算应收单 - 每月最大日期版本(月末按昨天查询) + * @Description: 防水涂料计算应收单 - 优化版本(批量处理提升性能) * @date: 2025/8/29 16:38 - * @Blog: https:// */ public class WaterproofPaintAccountsReceivableJob implements IJob { private static final Logger LOGGER = LoggerFactory.getLogger(WaterproofPaintAccountsReceivableJob.class); // 定义常量 private static final String RDS_ID = "e19d738a-8eac-4c42-9c08-7fe93e75638d"; - private static final String DEFAULT_BKGS_FS = "北新防水"; - private static final String DEFAULT_BKGS_TL = "北新涂料"; private static final int BATCH_SIZE = 1000; + private static final int CUSTOMER_BATCH_SIZE = 500; // 客户分批大小 @Override public void execute(JobExecutionContext job) throws JobExecutionException { try { String param = SDK.getJobAPI().getJobParameter(job); - int timeRange = StringUtils.isNotBlank(param)?Integer.parseInt(param):0; + int timeRange = StringUtils.isNotBlank(param) ? Integer.parseInt(param) : 0; + // 获取当前时间 LocalDate nowDate = LocalDate.now(); LocalDate startDate; @@ -49,17 +48,19 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { // 默认计算去年第一天到现在的数据 startDate = nowDate.minusYears(1).withDayOfYear(1); } + LOGGER.info("开始执行防水涂料应收单计算任务,时间范围:{} 到 {}", startDate, nowDate); // 依次处理防水和涂料两个板块 boolean allSuccess = true; for (Section section : Section.values()) { - boolean success = processSection(section, startDate, nowDate); + boolean success = processSectionOptimized(section, startDate, nowDate); if (!success) { allSuccess = false; LOGGER.error("{}板块处理失败", section.getName()); } } + if (!allSuccess) { throw new JobExecutionException("部分板块处理失败"); } @@ -72,119 +73,48 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { } /** - * 处理单个板块的数据 - * @param section 板块配置 - * @param startDate 开始日期 - * @param nowDate 结束日期 - * @return 处理是否成功 + * 优化后的板块数据处理方法 */ - private boolean processSection(Section section, LocalDate startDate, LocalDate nowDate) { + private boolean processSectionOptimized(Section section, LocalDate startDate, LocalDate endDate) { String sectionName = section.getName(); - LOGGER.info("开始处理{}板块数据,时间范围:{} 到 {}", sectionName, startDate, nowDate); + LOGGER.info("开始处理{}板块数据,时间范围:{} 到 {}", sectionName, startDate, endDate); try { - // 开始清理开始时间到结束时间的数据后再进行计算更新数据 - String startDateFormat = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00"; - String nowDateFormat = nowDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 23:59:59"; - int delete = DBSql.update("DELETE FROM " + section.getTargetTable() + - " WHERE RQ >= '" + startDateFormat + "' "); - LOGGER.info("已删除目标表[{}]中{}条数据(时间范围: {} )", - section.getTargetTable(), delete, startDateFormat); + // 清理目标表数据 + String startDateFormat = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00:00:00"; + int deleteCount = DBSql.update("DELETE FROM " + section.getTargetTable() + " WHERE RQ >= ?", new String[]{startDateFormat}); + LOGGER.info("已删除目标表[{}]中{}条数据", section.getTargetTable(), deleteCount); - // 查询销售组织和客户分组信息 - List maps = DBSql.getMaps("SELECT QYGS, FCUSTNAME, SQ AS FPROVINCE,CS AS FCITY,QY AS FDISTRICT ,XSZZ FROM " + - section.getYsdTable() + " WHERE QYGS IS NOT NULL GROUP BY QYGS, FCUSTNAME, SQ,CS"); + // 获取所有销售组织-客户组合 + List customerMaps = DBSql.getMaps( + "SELECT DISTINCT QYGS, FCUSTNAME, SQ AS FPROVINCE, CS AS FCITY, QY AS FDISTRICT, XSZZ " + + "FROM " + section.getYsdTable() + " WHERE QYGS IS NOT NULL AND FCUSTNAME IS NOT NULL" + ); - if (maps == null || maps.isEmpty()) { + if (customerMaps == null || customerMaps.isEmpty()) { LOGGER.warn("{}板块未查询到销售组织和客户数据", sectionName); - return true; // 没有数据也算成功 + return true; } - LOGGER.info("{}板块共查询到 {} 个销售组织-客户组合", sectionName, maps.size()); + LOGGER.info("{}板块共查询到 {} 个销售组织-客户组合", sectionName, customerMaps.size()); - // 用于批量插入的数据列表 - List batchData = new ArrayList<>(); - int processedCount = 0; + // 分批次处理客户数据 + int totalCustomers = customerMaps.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); - // 获取每个月的最大日期(月末日期) - List monthEndDates = getMonthEndDates(startDate, nowDate); - LOGGER.info("{}板块将处理 {} 个月末日期", sectionName, monthEndDates.size()); + LOGGER.info("{}板块正在处理第 {} 批客户,进度: {}/{}", + sectionName, (i / CUSTOMER_BATCH_SIZE) + 1, endIndex, totalCustomers); - // 遍历每个月末日期 - for (LocalDate monthEndDate : monthEndDates) { - LOGGER.info("{}板块正在处理月末日期: {}", sectionName, monthEndDate); - - // 计算该月的日期范围(月初到月末或昨天) - LocalDate monthStartDate = monthEndDate.withDayOfMonth(1); - LocalDate monthEnd = monthEndDate; - // 遍历每个销售组织-客户组合 - for (RowMap row : maps) { - try { - String manageRegionName = row.getString("QYGS"); - String saleOrgUnit = row.getString("XSZZ"); - String custName = row.getString("FCUSTNAME"); -// LOGGER.info("manageRegionName:{};saleOrgUnit:{},custName:{}",manageRegionName,saleOrgUnit,custName); - - // 查询省市区信息 - String province = row != null ? row.getString("FPROVINCE") : ""; - String city = row != null ? row.getString("FCITY") : ""; - String district = row != null ? row.getString("FDISTRICT")!=null ? row.getString("FDISTRICT"):"": ""; - - // 计算期初余额(上一年度) - LocalDate previousYearStart = monthStartDate.minusYears(1).withDayOfYear(1); - LocalDate previousYearEnd = monthStartDate.minusYears(1).withDayOfYear(365); - BigDecimal qcye = calculateInitialBalance(section, saleOrgUnit, custName, previousYearStart, previousYearEnd); - - // 计算累计销售(本年年初到查询截止日期) - LocalDate yearStart = monthStartDate.withDayOfYear(1); - BigDecimal ljxs = calculateTotalSales(section, saleOrgUnit, custName, monthEndDate, monthEnd); - - // 计算累计还款(本年年初到查询截止日期) - BigDecimal ljhk = calculateTotalRepayment(section, saleOrgUnit, custName, monthEndDate, monthEnd); - - // 计算应收余额 - BigDecimal ysye = qcye.add(ljxs).subtract(ljhk); -// LOGGER.info("计算应收余额={}",ysye.doubleValue()); - - // 计算账龄分析(需要查询历史数据) - Map zlfx = calculateMonthlyAgingAnalysis(section, saleOrgUnit, custName, monthEndDate, ysye); -// for (String key: zlfx.keySet()){ -// LOGGER.info("账龄-{}={}",key,zlfx.get(key)); -// } - - // 创建数据记录(记录日期仍使用月末日期) - BO record = createRecord( - section, manageRegionName, saleOrgUnit, monthEndDate, custName, - province, city, district, qcye, ljxs, ljhk, ysye, zlfx - ); - - batchData.add(record); - - // 批量插入 - if (batchData.size() >= BATCH_SIZE) { - batchInsert(section, batchData); - batchData.clear(); - } - - // 更新处理计数 - processedCount++; - if (processedCount % 1000 == 0) { - LOGGER.info("{}板块已处理 {} 条记录", sectionName, processedCount); - } - - } catch (Exception e) { - LOGGER.error("{}板块处理销售组织 {} 客户 {} 月末日期 {} 时发生错误", - sectionName, row.getString("XSZZ"), row.getString("FCUSTNAME"), monthEndDate, e); - } + boolean batchSuccess = processCustomerBatch(section, batchCustomers, startDate, endDate); + if (!batchSuccess) { + LOGGER.error("{}板块第 {} 批客户处理失败", sectionName, (i / CUSTOMER_BATCH_SIZE) + 1); + return false; } } - // 插入剩余数据 - if (!batchData.isEmpty()) { - batchInsert(section, batchData); - } - - LOGGER.info("{}板块数据处理完成,共处理 {} 条记录", sectionName, processedCount); + LOGGER.info("{}板块数据处理完成,共处理 {} 个客户组合", sectionName, totalCustomers); return true; } catch (Exception e) { @@ -194,179 +124,403 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { } /** - * 判断是否为当前月月末 - * @param monthEndDate 月末日期 - * @param nowDate 当前日期 - * @return 是否为当前月月末 + * 处理一批客户数据 */ - private boolean isCurrentMonthEnd(LocalDate monthEndDate, LocalDate nowDate) { - // 判断是否为当前月的月末,并且月末日期大于或等于当前日期 - return monthEndDate.getMonth() == nowDate.getMonth() && - monthEndDate.getYear() == nowDate.getYear() && - monthEndDate.getDayOfMonth() == monthEndDate.lengthOfMonth() && - monthEndDate.isAfter(nowDate.minusDays(1)); // 确保是当前月月末 - } + private boolean processCustomerBatch(Section section, List customerBatch, + LocalDate startDate, LocalDate endDate) { + try { + // 提取销售组织和客户名称列表 + List saleOrgUnits = customerBatch.stream() + .map(row -> row.getString("XSZZ")) + .distinct() + .collect(Collectors.toList()); - /** - * 获取时间范围内的所有月末日期 - */ - private List getMonthEndDates(LocalDate startDate, LocalDate endDate) { - List monthEndDates = new ArrayList<>(); - LocalDate current = startDate.withDayOfMonth(1); - while (!current.isAfter(endDate)) { - // 如果当前月份与endDate不是同年同月 - if (current.getYear() != endDate.getYear() || current.getMonth() != endDate.getMonth()) { - LocalDate monthEnd = current.withDayOfMonth(current.lengthOfMonth()); - // 确保月末日期在时间范围内 - if (!monthEnd.isBefore(startDate) && !monthEnd.isAfter(endDate)) { - monthEndDates.add(monthEnd); + List custNames = customerBatch.stream() + .map(row -> row.getString("FCUSTNAME")) + .distinct() + .collect(Collectors.toList()); + + // 获取需要处理的所有月末日期 + List monthEndDates = getMonthEndDates(startDate, endDate); + + // 批量预加载所有需要的数据 + Map preloadedResults = preloadAllData( + section, saleOrgUnits, custNames, monthEndDates); + + // 批量处理数据 + List allRecords = new ArrayList<>(); + + for (LocalDate monthEndDate : monthEndDates) { + for (RowMap customer : customerBatch) { + String saleOrgUnit = customer.getString("XSZZ"); + String custName = customer.getString("FCUSTNAME"); + String keyPrefix = saleOrgUnit + "_" + custName + "_"; + + try { + // 从预加载数据中获取计算结果 + BigDecimal qcye = getPreloadedValue(preloadedResults, keyPrefix + "QCYE_" + monthEndDate); + BigDecimal ljxs = getPreloadedValue(preloadedResults, keyPrefix + "LJXS_" + monthEndDate); + BigDecimal ljhk = getPreloadedValue(preloadedResults, keyPrefix + "LJHK_" + monthEndDate); + BigDecimal ysye = qcye.add(ljxs).subtract(ljhk); + + // 从预加载数据中获取账龄分析 + 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); + } + + // 创建记录 + BO record = createRecord( + section, + customer.getString("QYGS"), + saleOrgUnit, + monthEndDate, + custName, + customer.getString("FPROVINCE"), + customer.getString("FCITY"), + customer.getString("FDISTRICT") != null ? customer.getString("FDISTRICT") : "", + qcye, ljxs, ljhk, ysye, zlfx + ); + + allRecords.add(record); + + } catch (Exception e) { + LOGGER.error("处理客户数据时发生错误,销售组织: {}, 客户: {}, 日期: {}", + saleOrgUnit, custName, monthEndDate, e); + } } } - // 如果当前月份与endDate是同年同月 - else { - LocalDate dayBeforeEnd = endDate.minusDays(1); - // 确保前一天在时间范围内 - if (!dayBeforeEnd.isBefore(startDate)) { - monthEndDates.add(dayBeforeEnd); - } - break; // 遇到同年同月后就可以结束循环了 + + // 分批插入数据 + for (int i = 0; i < allRecords.size(); i += BATCH_SIZE) { + int endIndex = Math.min(i + BATCH_SIZE, allRecords.size()); + List batchRecords = allRecords.subList(i, endIndex); + batchInsert(section, batchRecords); } - current = current.plusMonths(1); - } - return monthEndDates; - } - /** - * 计算期初余额 - */ - private BigDecimal calculateInitialBalance(Section section, String saleOrgUnit, String custName, - LocalDate startDate, LocalDate endDate) { - String startDateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00"; - String endDateStr = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 23:59:59"; - try { - // 查询应收单总额 - RowMap ysResult = DBSql.getMap( - "SELECT SUM(SSJERMB) as total FROM " + section.getYsdTable() + - " WHERE XSZZ = ? AND FCUSTNAME = ? AND DZRQ >= ? AND DZRQ< ?", - saleOrgUnit, custName, startDateStr, endDateStr - ); -// LOGGER.info("期初余额-应收单总额sql:SELECT SUM(SSJERMB) as total FROM " + section.getYsdTable() + -// " WHERE XSZZ = "+saleOrgUnit+" AND FCUSTNAME = "+custName+" AND DZRQ >= "+startDateStr+" AND DZRQ< "+endDateStr+""); - - BigDecimal ysTotal = ysResult != null && ysResult.get("total") != null ? - new BigDecimal(ysResult.get("total").toString()) : BigDecimal.ZERO; - - // 查询收款单总额 - RowMap skResult = DBSql.getMap( - "SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSkdTable() + - " WHERE FSALEORGUNIT = ? AND FCUSTNAME = ? AND FBILLDATE >= ? AND FBILLDATE < ?", - saleOrgUnit, custName, startDateStr, endDateStr - ); -// LOGGER.info("期初余额-收款单总额sql:SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSkdTable() + -// " WHERE FSALEORGUNIT = "+saleOrgUnit+" AND FCUSTNAME = "+custName+" AND FBILLDATE >= "+startDateStr+" AND FBILLDATE< "+endDateStr+""); - - BigDecimal skTotal = skResult != null && skResult.get("total") != null ? - new BigDecimal(skResult.get("total").toString()) : BigDecimal.ZERO; - - // 查询收款退款单总额 - RowMap sktkResult = DBSql.getMap( - "SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSktkdTable() + - " WHERE FSALEORGUNIT = ? AND FCUSTNAME = ? AND FBILLDATE >= ? AND FBILLDATE < ?", - saleOrgUnit, custName, startDateStr, endDateStr - ); -// LOGGER.info("期初余额-收款退款单总额sql:SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSktkdTable() + -// " WHERE FSALEORGUNIT = "+saleOrgUnit+" AND FCUSTNAME = "+custName+" AND FBILLDATE >= "+startDateStr+" AND FBILLDATE< "+endDateStr+""); - - BigDecimal sktkTotal = sktkResult != null && sktkResult.get("total") != null ? - new BigDecimal(sktkResult.get("total").toString()) : BigDecimal.ZERO; - -// LOGGER.info("期初余额:{}",sktkTotal.doubleValue()); - // 期初余额 = 应收单总额 - 收款单总额 + 收款退款单总额 - return ysTotal.subtract(skTotal).add(sktkTotal); + return true; } catch (Exception e) { - LOGGER.error("计算{}板块期初余额时发生错误,销售组织: {}, 客户: {}", section.getName(), saleOrgUnit, custName, e); - return BigDecimal.ZERO; + LOGGER.error("处理客户批次数据时发生错误", e); + return false; } } /** - * 计算累计销售 + * 安全获取预加载值 */ - private BigDecimal calculateTotalSales(Section section, String saleOrgUnit, String custName, - LocalDate startDate, LocalDate endDate) { - String startDateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00"; - String endDateStr = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 23:59:59"; - try { - RowMap result = DBSql.getMap( - "SELECT SUM(SSJERMB) as total FROM " + section.getYsdTable() + - " WHERE XSZZ = ? AND FCUSTNAME = ? AND DZRQ >= ? AND DZRQ < ?", - saleOrgUnit, custName, startDateStr, endDateStr - ); -// LOGGER.info("计算累计销售:SELECT SUM(SSJERMB) as total FROM " + section.getYsdTable() + -// " WHERE XSZZ = "+saleOrgUnit+" AND FCUSTNAME = "+custName+" AND DZRQ >= "+startDateStr+" AND DZRQ < "+endDateStr+""); + private BigDecimal getPreloadedValue(Map preloadedData, String key) { + return preloadedData.getOrDefault(key, BigDecimal.ZERO); + } -// LOGGER.info("累计销售={}",result != null && result.get("total") != null ? -// new BigDecimal(result.get("total").toString()) : BigDecimal.ZERO); - return result != null && result.get("total") != null ? - new BigDecimal(result.get("total").toString()) : BigDecimal.ZERO; + /** + * 预加载所有需要的数据 + */ + private Map preloadAllData(Section section, + List saleOrgUnits, List custNames, List monthEndDates) { + + Map results = new HashMap<>(); + + try { + // 批量查询应收单数据 + Map ysData = batchQueryYSDData(section, saleOrgUnits, custNames, monthEndDates); + + // 批量查询收款单数据 + Map skData = batchQuerySKDData(section, saleOrgUnits, custNames, monthEndDates); + + // 批量查询收款退款单数据 + Map sktkData = batchQuerySKTKDData(section, saleOrgUnits, custNames, monthEndDates); + + // 批量查询历史余额数据 + Map historyData = batchQueryHistoryBalance(section, saleOrgUnits, custNames, monthEndDates); + + // 计算所有需要的指标 + calculateAllMetrics(results, ysData, skData, sktkData, historyData, saleOrgUnits, custNames, monthEndDates); } catch (Exception e) { - LOGGER.error("计算{}板块累计销售时发生错误,销售组织: {}, 客户: {}", section.getName(), saleOrgUnit, custName, e); - return BigDecimal.ZERO; + LOGGER.error("预加载数据时发生错误", e); } + + return results; } /** - * 计算累计还款 + * 批量查询应收单数据 */ - private BigDecimal calculateTotalRepayment(Section section, String saleOrgUnit, String custName, - LocalDate startDate, LocalDate endDate) { - String startDateStr = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 00:00:00"; - String endDateStr = endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))+" 23:59:59"; + private Map batchQueryYSDData(Section section, List saleOrgUnits, + List custNames, List monthEndDates) { + + Map result = new HashMap<>(); + + if (saleOrgUnits.isEmpty() || custNames.isEmpty() || monthEndDates.isEmpty()) { + return result; + } + try { - // 查询收款单总额 - RowMap skResult = DBSql.getMap( - "SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSkdTable() + - " WHERE FSALEORGUNIT = ? AND FCUSTNAME = ? AND FBILLDATE >= ? AND FBILLDATE < ?", - saleOrgUnit, custName, startDateStr, endDateStr - ); -// LOGGER.info("计算累计还款:SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSkdTable() + -// " WHERE FSALEORGUNIT = "+saleOrgUnit+" AND FCUSTNAME = "+custName+" AND FBILLDATE >= "+startDateStr+" AND FBILLDATE < "+endDateStr+""); + String inSaleOrgs = buildInCondition(saleOrgUnits); + String inCustNames = buildInCondition(custNames); - BigDecimal skTotal = skResult != null && skResult.get("total") != null ? - new BigDecimal(skResult.get("total").toString()) : BigDecimal.ZERO; + // 构建日期条件 + StringBuilder dateCondition = new StringBuilder(); + for (LocalDate date : monthEndDates) { + LocalDate monthStart = date.withDayOfMonth(1); + if (dateCondition.length() > 0) { + dateCondition.append(" OR "); + } + dateCondition.append("(DZRQ >= '") + .append(monthStart.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) + .append(" 00:00:00' AND DZRQ <= '") + .append(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) + .append(" 23:59:59')"); + } - // 查询收款退款单总额 - RowMap sktkResult = DBSql.getMap( - "SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSktkdTable() + - " WHERE FSALEORGUNIT = ? AND FCUSTNAME = ? AND FBILLDATE >= ? AND FBILLDATE < ?", - saleOrgUnit, custName, startDateStr, endDateStr - ); -// LOGGER.info("计算累计还款:SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSktkdTable() + -// " WHERE FSALEORGUNIT = "+saleOrgUnit+" AND FCUSTNAME = "+custName+" AND FBILLDATE >= "+startDateStr+" AND FBILLDATE < "+endDateStr+""); + String sql = "SELECT XSZZ, FCUSTNAME, DATE_FORMAT(DZRQ, '%Y-%m-%d') as BILL_DATE, SUM(SSJERMB) as TOTAL " + + "FROM " + section.getYsdTable() + + " WHERE XSZZ IN (" + inSaleOrgs + ") " + + " AND FCUSTNAME IN (" + inCustNames + ") " + + " AND (" + dateCondition + ") " + + " GROUP BY XSZZ, FCUSTNAME, DATE_FORMAT(DZRQ, '%Y-%m-%d')"; - BigDecimal sktkTotal = sktkResult != null && sktkResult.get("total") != null ? - new BigDecimal(sktkResult.get("total").toString()) : BigDecimal.ZERO; -// LOGGER.info("累计还款={}",skTotal.subtract(sktkTotal).doubleValue()); - // 累计还款 = 收款单总额 - 收款退款单总额 - return skTotal.subtract(sktkTotal); + List queryResults = DBSql.getMaps(sql); + + for (RowMap row : queryResults) { + String key = row.getString("XSZZ") + "_" + row.getString("FCUSTNAME") + "_" + row.getString("BILL_DATE"); + BigDecimal value = row.get("TOTAL") != null ? new BigDecimal(row.get("TOTAL").toString()) : BigDecimal.ZERO; + result.put(key, value); + } } catch (Exception e) { - LOGGER.error("计算{}板块累计还款时发生错误,销售组织: {}, 客户: {}", section.getName(), saleOrgUnit, custName, e); - return BigDecimal.ZERO; + LOGGER.error("批量查询应收单数据时发生错误", e); } + + return result; } /** - * 计算月度账龄分析 + * 批量查询收款单数据 */ - private Map calculateMonthlyAgingAnalysis(Section section, String saleOrgUnit, String custName, - LocalDate currentDate, BigDecimal currentBalance) { + private Map batchQuerySKDData(Section section, List saleOrgUnits, + List custNames, List monthEndDates) { + Map result = new HashMap<>(); try { - // 计算各个时间点的应收余额 + String inSaleOrgs = buildInCondition(saleOrgUnits); + String inCustNames = buildInCondition(custNames); + + StringBuilder dateCondition = new StringBuilder(); + for (LocalDate date : monthEndDates) { + LocalDate monthStart = date.withDayOfMonth(1); + if (dateCondition.length() > 0) { + dateCondition.append(" OR "); + } + dateCondition.append("(FBILLDATE >= '") + .append(monthStart.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) + .append(" 00:00:00' AND FBILLDATE <= '") + .append(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) + .append(" 23:59:59')"); + } + + String sql = "SELECT FSALEORGUNIT, FCUSTNAME, DATE_FORMAT(FBILLDATE, '%Y-%m-%d') as BILL_DATE, SUM(FSALEAMOUNTRMB) as TOTAL " + + "FROM " + section.getSkdTable() + + " WHERE FSALEORGUNIT IN (" + inSaleOrgs + ") " + + " AND FCUSTNAME IN (" + inCustNames + ") " + + " AND (" + dateCondition + ") " + + " GROUP BY FSALEORGUNIT, FCUSTNAME, DATE_FORMAT(FBILLDATE, '%Y-%m-%d')"; + + List queryResults = DBSql.getMaps(sql); + + for (RowMap row : queryResults) { + String key = row.getString("FSALEORGUNIT") + "_" + row.getString("FCUSTNAME") + "_" + row.getString("BILL_DATE"); + BigDecimal value = row.get("TOTAL") != null ? new BigDecimal(row.get("TOTAL").toString()) : BigDecimal.ZERO; + result.put(key, value); + } + + } catch (Exception e) { + LOGGER.error("批量查询收款单数据时发生错误", e); + } + + return result; + } + + /** + * 批量查询收款退款单数据 + */ + private Map batchQuerySKTKDData(Section section, List saleOrgUnits, + List custNames, List monthEndDates) { + + Map result = new HashMap<>(); + + try { + String inSaleOrgs = buildInCondition(saleOrgUnits); + String inCustNames = buildInCondition(custNames); + + StringBuilder dateCondition = new StringBuilder(); + for (LocalDate date : monthEndDates) { + LocalDate monthStart = date.withDayOfMonth(1); + if (dateCondition.length() > 0) { + dateCondition.append(" OR "); + } + dateCondition.append("(FBILLDATE >= '") + .append(monthStart.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) + .append(" 00:00:00' AND FBILLDATE <= '") + .append(date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))) + .append(" 23:59:59')"); + } + + String sql = "SELECT FSALEORGUNIT, FCUSTNAME, DATE_FORMAT(FBILLDATE, '%Y-%m-%d') as BILL_DATE, SUM(FSALEAMOUNTRMB) as TOTAL " + + "FROM " + section.getSktkdTable() + + " WHERE FSALEORGUNIT IN (" + inSaleOrgs + ") " + + " AND FCUSTNAME IN (" + inCustNames + ") " + + " AND (" + dateCondition + ") " + + " GROUP BY FSALEORGUNIT, FCUSTNAME, DATE_FORMAT(FBILLDATE, '%Y-%m-%d')"; + + List queryResults = DBSql.getMaps(sql); + + for (RowMap row : queryResults) { + String key = row.getString("FSALEORGUNIT") + "_" + row.getString("FCUSTNAME") + "_" + row.getString("BILL_DATE"); + BigDecimal value = row.get("TOTAL") != null ? new BigDecimal(row.get("TOTAL").toString()) : BigDecimal.ZERO; + result.put(key, value); + } + + } catch (Exception e) { + LOGGER.error("批量查询收款退款单数据时发生错误", e); + } + + return result; + } + + /** + * 批量查询历史余额数据 + */ + private Map batchQueryHistoryBalance(Section section, List saleOrgUnits, + List custNames, List monthEndDates) { + + Map result = new HashMap<>(); + + try { + String inSaleOrgs = buildInCondition(saleOrgUnits); + String inCustNames = buildInCondition(custNames); + String inDates = monthEndDates.stream() + .map(date -> "'" + date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 23:59:59'") + .collect(Collectors.joining(",")); + + String sql = "SELECT XSZZ, KH, DATE_FORMAT(RQ, '%Y-%m-%d') as BALANCE_DATE, YSYE " + + "FROM " + section.getTargetTable() + + " WHERE XSZZ IN (" + inSaleOrgs + ") " + + " AND KH IN (" + inCustNames + ") " + + " AND RQ IN (" + inDates + ")"; + + List queryResults = DBSql.getMaps(sql); + + for (RowMap row : queryResults) { + String key = row.getString("XSZZ") + "_" + row.getString("KH") + "_" + row.getString("BALANCE_DATE"); + BigDecimal value = row.get("YSYE") != null ? new BigDecimal(row.get("YSYE").toString()) : BigDecimal.ZERO; + result.put(key, value); + } + + } catch (Exception e) { + LOGGER.error("批量查询历史余额数据时发生错误", e); + } + + return result; + } + + /** + * 计算所有指标 + */ + private void calculateAllMetrics(Map results, + Map ysData, Map skData, + Map sktkData, Map historyData, + List saleOrgUnits, List custNames, List monthEndDates) { + + // 计算每个客户每个月的指标 + for (String saleOrgUnit : saleOrgUnits) { + for (String custName : custNames) { + String keyPrefix = saleOrgUnit + "_" + custName + "_"; + + for (LocalDate monthEndDate : monthEndDates) { + String dateKey = monthEndDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + String fullKeyPrefix = keyPrefix + dateKey; + + // 计算期初余额(上一年度累计) + LocalDate previousYearStart = monthEndDate.minusYears(1).withDayOfYear(1); + LocalDate previousYearEnd = monthEndDate.minusYears(1).withDayOfYear(365); + BigDecimal qcye = calculatePeriodBalance(ysData, skData, sktkData, saleOrgUnit, custName, previousYearStart, previousYearEnd); + + // 计算累计销售(本年年初到当前月末) + LocalDate yearStart = monthEndDate.withDayOfYear(1); + BigDecimal ljxs = calculatePeriodBalance(ysData, null, null, saleOrgUnit, custName, yearStart, monthEndDate); + + // 计算累计还款(本年年初到当前月末) + BigDecimal ljhk = calculatePeriodBalance(null, skData, sktkData, saleOrgUnit, custName, yearStart, monthEndDate); + + // 计算应收余额 + BigDecimal ysye = qcye.add(ljxs).subtract(ljhk); + + // 计算账龄分析 + Map zlfx = calculateAgingAnalysis(historyData, saleOrgUnit, custName, monthEndDate, ysye); + + // 存储计算结果 + results.put(keyPrefix + "QCYE_" + monthEndDate, qcye); + results.put(keyPrefix + "LJXS_" + monthEndDate, ljxs); + results.put(keyPrefix + "LJHK_" + monthEndDate, ljhk); + results.put(keyPrefix + "YSYE_" + monthEndDate, ysye); + + for (Map.Entry entry : zlfx.entrySet()) { + results.put(keyPrefix + entry.getKey() + "_" + monthEndDate, entry.getValue()); + } + } + } + } + } + + /** + * 计算指定时间段的余额 + */ + private BigDecimal calculatePeriodBalance(Map ysData, Map skData, + Map sktkData, String saleOrgUnit, String custName, + LocalDate startDate, LocalDate endDate) { + + BigDecimal result = BigDecimal.ZERO; + String keyPrefix = saleOrgUnit + "_" + custName + "_"; + + // 累加指定时间段内的数据 + LocalDate current = startDate; + while (!current.isAfter(endDate)) { + String dateKey = current.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + String fullKey = keyPrefix + dateKey; + + if (ysData != null) { + result = result.add(ysData.getOrDefault(fullKey, BigDecimal.ZERO)); + } + + if (skData != null) { + result = result.subtract(skData.getOrDefault(fullKey, BigDecimal.ZERO)); + } + + if (sktkData != null) { + result = result.add(sktkData.getOrDefault(fullKey, BigDecimal.ZERO)); + } + + current = current.plusDays(1); + } + + return result; + } + + /** + * 计算账龄分析 + */ + private Map calculateAgingAnalysis(Map historyData, + String saleOrgUnit, String custName, LocalDate currentDate, BigDecimal currentBalance) { + + Map result = new HashMap<>(); + String keyPrefix = saleOrgUnit + "_" + custName + "_"; + + try { + // 计算各个时间点的历史余额 LocalDate date60DaysAgo = currentDate.minusDays(60); LocalDate date1YearAgo = currentDate.minusYears(1); LocalDate date2YearsAgo = currentDate.minusYears(2); @@ -374,13 +528,13 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { LocalDate date4YearsAgo = currentDate.minusYears(4); LocalDate date5YearsAgo = currentDate.minusYears(5); - // 查询历史月末的应收余额 - BigDecimal balance60DaysAgo = findMonthlyBalance(section, saleOrgUnit, custName, date60DaysAgo); - BigDecimal balance1YearAgo = findMonthlyBalance(section, saleOrgUnit, custName, date1YearAgo); - BigDecimal balance2YearsAgo = findMonthlyBalance(section, saleOrgUnit, custName, date2YearsAgo); - BigDecimal balance3YearsAgo = findMonthlyBalance(section, saleOrgUnit, custName, date3YearsAgo); - BigDecimal balance4YearsAgo = findMonthlyBalance(section, saleOrgUnit, custName, date4YearsAgo); - BigDecimal balance5YearsAgo = findMonthlyBalance(section, saleOrgUnit, custName, date5YearsAgo); + // 查找历史余额 + 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); // 计算各账龄段金额 result.put("ZLFX0_60", currentBalance.subtract(balance60DaysAgo.max(BigDecimal.ZERO))); @@ -393,7 +547,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { } catch (Exception e) { LOGGER.error("计算账龄分析时发生错误,销售组织: {}, 客户: {}", saleOrgUnit, custName, e); - // 发生错误时设置默认值 + // 设置默认值 result.put("ZLFX0_60", BigDecimal.ZERO); result.put("ZLFX60_1", BigDecimal.ZERO); result.put("ZLFX1_2", BigDecimal.ZERO); @@ -407,29 +561,55 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { } /** - * 查找指定月末的应收余额 + * 查找历史余额 */ - private BigDecimal findMonthlyBalance(Section section, String saleOrgUnit, String custName, LocalDate targetDate) { + private BigDecimal findHistoricalBalance(Map historyData, String keyPrefix, LocalDate targetDate) { // 调整为目标月份的月末日期 LocalDate monthEndDate = targetDate.withDayOfMonth(targetDate.lengthOfMonth()); - String dateStr = monthEndDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 23:59:59"; + String dateKey = monthEndDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + String fullKey = keyPrefix + dateKey; - try { - // 查询目标表中该月末的应收余额 - RowMap result = DBSql.getMap( - "SELECT YSYE FROM " + section.getTargetTable() + - " WHERE XSZZ = ? AND KH = ? AND RQ = ?", - saleOrgUnit, custName, dateStr - ); + return historyData.getOrDefault(fullKey, BigDecimal.ZERO); + } - return result != null && result.get("YSYE") != null ? - new BigDecimal(result.get("YSYE").toString()) : BigDecimal.ZERO; - - } catch (Exception e) { - LOGGER.debug("未找到{}板块销售组织 {} 客户 {} 日期 {} 的历史余额,使用默认值0", - section.getName(), saleOrgUnit, custName, monthEndDate); - return BigDecimal.ZERO; + /** + * 构建IN查询条件 + */ + private String buildInCondition(List values) { + if (values == null || values.isEmpty()) { + return "''"; } + return values.stream() + .map(value -> "'" + value.replace("'", "''") + "'") + .collect(Collectors.joining(",")); + } + + /** + * 获取时间范围内的所有月末日期(优化版) + */ + private List getMonthEndDates(LocalDate startDate, LocalDate endDate) { + List monthEndDates = new ArrayList<>(); + LocalDate current = startDate.withDayOfMonth(1); + + while (!current.isAfter(endDate)) { + if (current.getYear() == endDate.getYear() && current.getMonth() == endDate.getMonth()) { + // 当前月份与结束日期同年同月,使用结束日期前一天 + LocalDate dayBeforeEnd = endDate.minusDays(1); + if (!dayBeforeEnd.isBefore(startDate)) { + monthEndDates.add(dayBeforeEnd); + } + break; + } else { + // 其他月份使用月末日期 + LocalDate monthEnd = current.withDayOfMonth(current.lengthOfMonth()); + if (!monthEnd.isBefore(startDate) && !monthEnd.isAfter(endDate)) { + monthEndDates.add(monthEnd); + } + } + current = current.plusMonths(1); + } + + return monthEndDates; } /** @@ -456,13 +636,13 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { record.set("YSYE", ysye); // 账龄分析字段 - record.set("ZLFX0_60", zlfx.get("ZLFX0_60")); - record.set("ZLFX60_1", zlfx.get("ZLFX60_1")); - record.set("ZLFX1_2", zlfx.get("ZLFX1_2")); - record.set("ZLFX2_3", zlfx.get("ZLFX2_3")); - record.set("ZLFX3_4", zlfx.get("ZLFX3_4")); - record.set("ZLFX4_5", zlfx.get("ZLFX4_5")); - record.set("ZLFX5", zlfx.get("ZLFX5")); + record.set("ZLFX0_60", zlfx.getOrDefault("ZLFX0_60", BigDecimal.ZERO)); + record.set("ZLFX60_1", zlfx.getOrDefault("ZLFX60_1", BigDecimal.ZERO)); + record.set("ZLFX1_2", zlfx.getOrDefault("ZLFX1_2", BigDecimal.ZERO)); + record.set("ZLFX2_3", zlfx.getOrDefault("ZLFX2_3", BigDecimal.ZERO)); + record.set("ZLFX3_4", zlfx.getOrDefault("ZLFX3_4", BigDecimal.ZERO)); + record.set("ZLFX4_5", zlfx.getOrDefault("ZLFX4_5", BigDecimal.ZERO)); + record.set("ZLFX5", zlfx.getOrDefault("ZLFX5", BigDecimal.ZERO)); return record; } @@ -472,9 +652,8 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { */ private void batchInsert(Section section, List batchData) { try { - int[] dataBO = SDK.getBOAPI().createDataBO(section.getTargetTable(), batchData, UserContext.fromUID("admin")); - long result = Arrays.stream(dataBO).count(); - LOGGER.info("成功插入 {} 条数据到 {} 表", result, section.getTargetTable()); + int[] results = SDK.getBOAPI().createDataBO(section.getTargetTable(), batchData, UserContext.fromUID("admin")); + LOGGER.info("成功插入 {} 条数据到 {} 表", batchData.size(), section.getTargetTable()); } catch (Exception e) { LOGGER.error("批量插入{}板块数据到表{}时发生错误", section.getName(), section.getTargetTable(), e); } diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleCountDimensionImpl.java b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleCountDimensionImpl.java index f2a52c5..e27474f 100644 --- a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleCountDimensionImpl.java +++ b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleCountDimensionImpl.java @@ -501,7 +501,9 @@ public class SaleCountDimensionImpl implements DataSummaryService { bo.set("JD", location.getLongitude()); bo.set("WD", location.getLatitude()); } - if ("石膏板".equals(lb_1) || "高分子".equals(lb_1)){ + if ("石膏板".equals(lb_1) + || (bkgs.equals("北新防水") && ("高分子".equals(lb_1) || "卷材".equals(lb_1) || "涂料".equals(lb_1))) + || (bkgs.equals("北新涂料") && "涂料".equals(lb_1))){ bo.set("XL", map.getDouble("TSXL")); bo.set("SNTQXL", map.getString("sntqtsxl")); }else { diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleDataSyncServiceImpl.java b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleDataSyncServiceImpl.java index 8df30af..66826fc 100644 --- a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleDataSyncServiceImpl.java +++ b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/service/impl/SaleDataSyncServiceImpl.java @@ -97,13 +97,13 @@ public class SaleDataSyncServiceImpl implements DataSyncService { String targetTable = mainConfig.getString("LDB"); String ccId = mainConfig.getString("CC_ID"); String partitionField = mainConfig.getString("FQBZD"); - String bkgs = mainConfig.getString("BKGS"); + String bkgs = mainConfig.getString("SSBK"); String jezd = mainConfig.getString("JEZD"); String tablename = mainConfig.getString("TABLENAME"); DateRange dateRange = new DateRange(); - LOGGER.info("处理配置:BindID={}, 源表={}, 目标表={}, CC_ID={}, 时间字段={}, 分区字段配置={}", - bindId, tableName, targetTable, ccId,timeField,partitionField); + LOGGER.info("处理配置:BindID={}, 源表={}, 目标表={}, CC_ID={}, 时间字段={}, 分区字段配置={}, 板块={}", + bindId, tableName, targetTable, ccId,timeField,partitionField,bkgs); // 查询子表字段映射配置 List fieldMappings = SDK.getBOAPI() @@ -144,7 +144,7 @@ public class SaleDataSyncServiceImpl implements DataSyncService { // 查询源表数据(跨库查询) if (tablename.equals("应收表")){ LOGGER.info("开始执行应收的明细汇总"); - if ((!bkgs.equals("北新防水")) || (!bkgs.equals("北新涂料"))) { + if (!bkgs.equals("北新防水") || !bkgs.equals("北新涂料")) { querySourceDataYS(ccId, tableName, timeField, startDate, endDate, partitionField, fieldMappings, targetTable, jezd); } @@ -845,7 +845,7 @@ public class SaleDataSyncServiceImpl implements DataSyncService { if ("北新防水".equals(map.getString("BKGS")) && "否".equals(map.getString("F_SFNBJY")) && !map.getString("XSZZ").equals("北新防水工程(辽宁)有限公司") && !map.getString("XSZZ").equals("北新防水工程(四川)有限公司") - && StringUtils.isBlank(map.getString("F_SFNBJY"))){ + && StringUtils.isBlank(map.getString("QYGS").trim())){ continue; } // 复制所有字段(排除系统字段) @@ -997,7 +997,8 @@ public class SaleDataSyncServiceImpl implements DataSyncService { } if ("北新防水".equals(map.getString("BKGS")) && "否".equals(map.getString("F_SFNBJY")) && !map.getString("XSZZ").equals("北新防水工程(辽宁)有限公司") - && !map.getString("XSZZ").equals("北新防水工程(四川)有限公司")){ + && !map.getString("XSZZ").equals("北新防水工程(四川)有限公司") + && StringUtils.isBlank(map.getString("QYGS").trim())){ continue; } // 复制所有字段(排除系统字段) @@ -1118,12 +1119,26 @@ public class SaleDataSyncServiceImpl implements DataSyncService { " AND MONTH = " + firstDayOfLastYearMonth.getMonthValue()); LOGGER.info("先清空{}去年同期数{}",lastYearFirstDayStr,update1); // 构建插入SQL(注意:需确保字段匹配且处理可能的主键冲突) - String insertCurrentMonthLastYearSql = "INSERT INTO " + targetTable + - " SELECT * FROM " + targetTable + - " WHERE " + targetTimeField + " >= '" + lastYearFirstDayStr + - "' AND " + targetTimeField + " < '" + lastYearNextMonthFirstDayStr + "'"; + + String CurrentMonthLastYearSql = "SELECT * FROM " + targetTable + + " WHERE " +targetTimeField+">='"+lastYearFirstDayStr+"' AND "+ + targetTimeField+"<'"+lastYearNextMonthFirstDayStr+"'"; + ArrayList bos = new ArrayList<>(); + List maps = DBSql.getMaps(CurrentMonthLastYearSql); + for (RowMap map : maps) { + map.remove("ID"); + map.remove("ORGID"); + map.remove("CREATEDATE"); + map.remove("CREATEUSER"); + map.remove("UPDATEDATE"); + map.remove("UPDATEUSER"); + map.remove("ISEND"); + map.remove("BINDID"); + BO bo = new BO().setAll(map); + bos.add(bo); + } // 执行插入操作 - DBSql.update(insertCurrentMonthLastYearSql); + SDK.getBOAPI().createDataBO(hzb, bos, UserContext.fromUID("admin")); LOGGER.info("{}已新增当月去年同期数据",lastYearFirstDayStr); } catch (Exception e) { @@ -1329,23 +1344,75 @@ public class SaleDataSyncServiceImpl implements DataSyncService { String lastYearFirstDayStr = firstDayOfLastYearMonth.format(formatter); String lastYearNextMonthFirstDayStr = firstDayOfNextMonthLastYear.format(formatter); + //删除清空去年同期数据 int update1 = DBSql.update("DELETE FROM " + targetTable + " WHERE RQ = '" + lastYearNextMonthFirstDayStr+"'"); LOGGER.info("先清空{}去年同期数{}",lastYearFirstDayStr,update1); - // 构建插入SQL(注意:需确保字段匹配且处理可能的主键冲突) - String insertCurrentMonthLastYearSql = "INSERT INTO " + targetTable + - " SELECT * FROM " + targetTable + - " WHERE RQ >= '" + lastYearFirstDayStr + - "' AND RQ < '" + lastYearNextMonthFirstDayStr + "'"; - // 执行插入操作 - rdsapi.update(insertCurrentMonthLastYearSql); - LOGGER.info("{}已新增当月去年同期数据",lastYearFirstDayStr); + // 构建查询去年同期全部数据的SQL + String lastYearQuerySql; + List lastYearParams = new ArrayList<>(); + + // 根据不同的数据库类型构建查询语句 + if ("ORACLE".equalsIgnoreCase(DBname)) { + lastYearQuerySql = "SELECT * FROM " + tableName + + " WHERE TO_DATE(" + timeField + ", 'YYYY-MM-DD') BETWEEN TO_DATE(?, 'YYYY-MM-DD') AND TO_DATE(?, 'YYYY-MM-DD')"; + lastYearParams.add(lastYearFirstDayStr); + lastYearParams.add(lastYearNextMonthFirstDayStr); + } else if ("POSTGRESQL".equalsIgnoreCase(DBname) || "GAUSS".equalsIgnoreCase(DBname)) { + lastYearQuerySql = "SELECT * FROM " + tableName + + " WHERE " + timeField + "::DATE BETWEEN ?::DATE AND ?::DATE"; + lastYearParams.add(lastYearFirstDayStr); + lastYearParams.add(lastYearNextMonthFirstDayStr); + } else if ("SQLSERVER".equalsIgnoreCase(DBname)) { + lastYearQuerySql = "SELECT * FROM " + tableName + + " WHERE CONVERT(DATE, " + timeField + ") BETWEEN CONVERT(DATE, ?) AND CONVERT(DATE, ?)"; + lastYearParams.add(lastYearFirstDayStr); + lastYearParams.add(lastYearNextMonthFirstDayStr); + } else { + // 默认处理(如MySQL) + lastYearQuerySql = "SELECT * FROM " + tableName + + " WHERE STR_TO_DATE(" + timeField + ", '%Y-%m-%d') BETWEEN STR_TO_DATE(?, '%Y-%m-%d') AND STR_TO_DATE(?, '%Y-%m-%d')"; + lastYearParams.add(lastYearFirstDayStr); + lastYearParams.add(lastYearNextMonthFirstDayStr); + } + + // 添加分区条件(如果存在) + if (partitionField != null && !partitionField.isEmpty() && !maxPartition.isEmpty()) { + if ("ORACLE".equalsIgnoreCase(DBname)) { + lastYearQuerySql += " AND " + partitionField + " = '" + maxPartition + "'"; + } else { + lastYearQuerySql += " AND " + partitionField + " = '" + maxPartition + "'"; + } + } + + LOGGER.info("查询去年同期数据SQL: {}", lastYearQuerySql); + LOGGER.info("查询参数: 开始日期={}, 结束日期={}", lastYearFirstDayStr, lastYearNextMonthFirstDayStr); + + // 执行查询去年同期数据 + List lastYearData; + if (lastYearParams.isEmpty()) { + lastYearData = rdsapi.getMaps(lastYearQuerySql); + } else { + // 这里需要根据您的rdsapi接口调整参数传递方式 + lastYearData = rdsapi.getMaps(lastYearQuerySql, lastYearParams.toArray()); + } + + if (lastYearData != null && !lastYearData.isEmpty()) { + // 批量插入去年同期数据 + int lastYearSuccessCount = this.processAndInsertData(lastYearData, fieldMappings, targetTable); + LOGGER.info("成功插入去年同期数据{}条,时间范围: {}-{}", + lastYearSuccessCount, lastYearFirstDayStr, lastYearNextMonthFirstDayStr); + } else { + LOGGER.warn("未查询到去年同期数据,时间范围: {}-{}", + lastYearFirstDayStr, lastYearNextMonthFirstDayStr); + } } catch (Exception e) { LOGGER.error("每月1号任务执行失败: {}", e.getMessage(), e); } + // } LOGGER.info("从表[{}]共查询到{}条数据,成功同步{}条数据",