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/controller/DataLinkUpController.class b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/classes/java/main/com/awspaas/user/apps/bnbm/datalinkup/controller/DataLinkUpController.class index feba41d..6f23994 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/controller/DataLinkUpController.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/controller/DataLinkUpController.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 969766f..8230fc6 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/SaleDataSummaryServiceImpl.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/SaleDataSummaryServiceImpl.class index 0f9a62d..765cef5 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/SaleDataSummaryServiceImpl.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/SaleDataSummaryServiceImpl.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 e852e24..6148b16 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 63795d0..4d05e4b 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/controller/DataLinkUpController.java b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/controller/DataLinkUpController.java index 335192f..dec2aa0 100644 --- a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/controller/DataLinkUpController.java +++ b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/controller/DataLinkUpController.java @@ -18,6 +18,7 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; @@ -193,8 +194,10 @@ public class DataLinkUpController { } if (tablename.equals("应收表")){ LOGGER.info("开始执行应收的明细汇总"); - syncService.querySourceDataYS(ccId, tableName, timeField, startDate, endDate, partitionField, - fieldMappings, targetTable, jezd); + if ((!bkgs.equals("北新防水")) || (!bkgs.equals("北新涂料"))) { + syncService.querySourceDataYS(ccId, tableName, timeField, startDate, endDate, partitionField, + fieldMappings, targetTable, jezd); + } }else { syncService.querySourceData(ccId, tableName, timeField, startDate, endDate, partitionField, fieldMappings, targetTable, jezd); @@ -266,7 +269,10 @@ public class DataLinkUpController { }else if ("采购".equals(ssyw)){ summaryService = new PurchaseDataSummaryServiceImpl(); LOGGER.info("采购业务检测到,创建summaryService实例"); - }else { + } else if ("运营".equals(ssyw)) { +// summaryService = new ProductionDataSyncServiceImpl(); + LOGGER.info("运营业务检测到,创建summaryService实例"); + } else { LOGGER.error("{}没有汇总类",ssyw); } @@ -283,7 +289,7 @@ public class DataLinkUpController { summaryService.calculateSummary(dateRange, bo); LOGGER.info("完成一体化-销售数据汇总计算,BKGS: {}", bo.get("BKGS")); - saleCountDimension = new SaleCountDimensionImpl(); +// saleCountDimension = new SaleCountDimensionImpl(); LOGGER.info("开始执行销售数据多维度汇总计算,BKGS: {}", bo.get("BKGS")); saleCountDimension.calculateSummary(dateRange, bo); LOGGER.info("完成销售数据多维度汇总计算,BKGS: {}", bo.get("BKGS")); @@ -343,7 +349,10 @@ public class DataLinkUpController { LocalDate date = LocalDate.parse(formattedDate, dateFormatter); LocalDateTime startDateTime = date.atStartOfDay(); // 当天00:00:00 Date startDate = Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()); - LOGGER.info("时间范围:{}-{}",startDate,endDate); + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String startDateStr = simpleDateFormat.format(startDate)+" 00:00:00"; + String endDateStr = simpleDateFormat.format(endDate)+" 23:59:59"; + LOGGER.info("时间范围:{}-{}",startDateStr,endDateStr); JSONArray configArray = new JSONArray(dataStr); // 2. 转换为BO对象列表 @@ -370,12 +379,6 @@ public class DataLinkUpController { hzb = "BO_EU_BNBM_DATALINKUP_XS_YSL"; } LOGGER.info("汇总板块数据——销售的接口"); - } else if ("运营".equals(ssyw)) { - dataSyncService = new ProductionDataSyncServiceImpl(); - if ("原材料".equals(tablename)){ - hzb = "BO_EU_DWS_ORDER_YCLXH_HZ"; - } - LOGGER.info("汇总板块数据——运营的接口"); } else if ("采购".equals(ssyw)){ dataSyncService = new PurchaseDataSyncServiceImpl(); if ("采购单".equals(tablename)){ @@ -388,11 +391,23 @@ public class DataLinkUpController { hzb = "BO_EU_CG_WLD_HZ"; } else if ("入库单".equals(tablename)){ hzb = "BO_EU_DWD_ORDER_RKD_HZ"; - }else { + } else { LOGGER.error("当前表没有汇总表"); + continue; } LOGGER.info("汇总板块数据——采购的接口"); - }else { + } else if ("运营".equals(ssyw)) { + dataSyncService = new ProductionDataSyncServiceImpl(); + if ("生产入库".equals(tablename)) { + hzb = "BO_EU_BNBM_SCRK_HZ"; + } else if ("生产出库".equals(tablename)) { + hzb = "BO_EU_BNBM_SCCK_HZ"; + }else { + LOGGER.error("当前表没有汇总表"); + continue; + } + LOGGER.info("汇总板块数据——运营的接口"); + } else { LOGGER.error("{}当前表没有汇总表",ssyw); return ro.err(ssyw+"当前表没有汇总表"); } @@ -420,7 +435,7 @@ public class DataLinkUpController { String deleteSql = "DELETE FROM "+hzb+" WHERE BKGS = '"+bkgs+"'"; int deletedCount = DBSql.update(deleteSql); LOGGER.info("已删除目标表["+hzb+"]中{}条数据(时间范围: {} - {}),耗时:{}ms", - deletedCount, startDate, endDate, System.currentTimeMillis() - deleteStartTime); + deletedCount, startDateStr, endDateStr, System.currentTimeMillis() - deleteStartTime); } // 根据时间范围增加数据分页查询数据存储到BO_EU_BNBM_DATALINKUP_XS_XSL_HZ // 全量分页迁移数据到汇总表 @@ -440,10 +455,11 @@ public class DataLinkUpController { // 按时间范围删除 for (String bkgs : bkgsArr) { String deleteSql = "DELETE FROM " + hzb + - " WHERE BKGS = '"+bkgs+"' AND " + targetTimeField + " BETWEEN ? AND ?"; - int deletedCount = DBSql.update(deleteSql, new Object[]{startDate, endDate}); + " WHERE BKGS = '"+bkgs+"' AND " + targetTimeField + " >= ? "; + LOGGER.info("deleteSql:{}",deleteSql); + int deletedCount = DBSql.update(deleteSql, new Object[]{startDateStr}); LOGGER.info("已删除目标表["+hzb+"]中{}条数据(时间范围: {} - {})", - deletedCount, startDate, endDate); + deletedCount, startDateStr, endDateStr); } // 根据时间范围增加数据分页查询数据存储到BO_EU_BNBM_DATALINKUP_XS_XSL_HZ // 按时间范围分页迁移数据到汇总表 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 a9283e8..19aaa06 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 @@ -22,7 +22,7 @@ import java.util.*; /** * @ClassName: WaterproofPaintAccountsReceivableJob - * @Description: 防水涂料计算应收单 - 多线程版本 + * @Description: 防水涂料计算应收单 - 每月最大日期版本(月末按昨天查询) * @date: 2025/8/29 16:38 * @Blog: https:// */ @@ -34,8 +34,6 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { 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 THREAD_POOL_SIZE = 2; // 线程池大小,根据需求调整 - // 板块配置 @Override public void execute(JobExecutionContext job) throws JobExecutionException { @@ -52,6 +50,7 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { startDate = nowDate.minusYears(1).withDayOfYear(1); } LOGGER.info("开始执行防水涂料应收单计算任务,时间范围:{} 到 {}", startDate, nowDate); + // 依次处理防水和涂料两个板块 boolean allSuccess = true; for (Section section : Section.values()) { @@ -64,13 +63,14 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { if (!allSuccess) { throw new JobExecutionException("部分板块处理失败"); } - LOGGER.info("防水涂料应收单计算任务完成,共处理 {} 天数据", nowDate.toEpochDay() - startDate.toEpochDay() + 1); + LOGGER.info("防水涂料应收单计算任务完成"); } catch (Exception e) { LOGGER.error("执行防水涂料应收单计算任务时发生错误", e); throw new JobExecutionException("任务执行失败", e); } } + /** * 处理单个板块的数据 * @param section 板块配置 @@ -82,24 +82,17 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { String sectionName = section.getName(); LOGGER.info("开始处理{}板块数据,时间范围:{} 到 {}", sectionName, startDate, nowDate); - // 每个板块使用独立的缓存 - Map> historicalBalanceCache = new HashMap<>(); - // 新增缓存用于存储每日的累计值 - Map previousLjxsCache = new HashMap<>(); // 缓存前一天的累计销售 - Map previousLjhkCache = new HashMap<>(); // 缓存前一天的累计还款 - Map qcyeCache = new HashMap<>(); // 缓存期初余额(每个客户只需计算一次) - try { // 开始清理开始时间到结束时间的数据后再进行计算更新数据 - String startDateFormat = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); - String nowDateFormat = nowDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + 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 BETWEEN '" + startDateFormat + "' AND '" + nowDateFormat + "'"); - LOGGER.info("已删除目标表[{}]中{}条数据(时间范围: {} - {})", - section.getTargetTable(), delete, startDateFormat, nowDateFormat); + " WHERE RQ >= '" + startDateFormat + "' "); + LOGGER.info("已删除目标表[{}]中{}条数据(时间范围: {} )", + section.getTargetTable(), delete, startDateFormat); // 查询销售组织和客户分组信息 - List maps = DBSql.getMaps("SELECT QYGS, FCUSTNAME, SQ AS FPROVINCE,CS AS FCITY FROM " + + 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"); if (maps == null || maps.isEmpty()) { @@ -113,80 +106,60 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { List batchData = new ArrayList<>(); int processedCount = 0; - // 遍历日期范围 - for (LocalDate currentDate = startDate; !currentDate.isAfter(nowDate); currentDate = currentDate.plusDays(1)) { - LOGGER.debug("{}板块正在处理日期: {}", sectionName, currentDate); + // 获取每个月的最大日期(月末日期) + List monthEndDates = getMonthEndDates(startDate, nowDate); + LOGGER.info("{}板块将处理 {} 个月末日期", sectionName, monthEndDates.size()); + // 遍历每个月末日期 + for (LocalDate monthEndDate : monthEndDates) { + LOGGER.info("{}板块正在处理月末日期: {}", sectionName, monthEndDate); + + // 计算该月的日期范围(月初到月末或昨天) + LocalDate monthStartDate = monthEndDate.withDayOfMonth(1); + LocalDate monthEnd = monthEndDate; + int i =0; // 遍历每个销售组织-客户组合 for (RowMap row : maps) { + if (i==1){ + break; + } + i++; 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"):"": ""; - String cacheKey = saleOrgUnit + "_" + custName; + // 计算期初余额(上一年度) + LocalDate previousYearStart = monthStartDate.minusYears(1).withDayOfYear(1); + LocalDate previousYearEnd = monthStartDate.minusYears(1).withDayOfYear(365); + BigDecimal qcye = calculateInitialBalance(section, saleOrgUnit, custName, previousYearStart, previousYearEnd); - // 计算期初余额(上一年度)- 每个客户只需计算一次 - BigDecimal qcye; - if (currentDate.equals(startDate)) { - LocalDate previousYearStart = currentDate.minusYears(1).withDayOfYear(1); - LocalDate previousYearEnd = currentDate.minusYears(1).withDayOfYear(365); - qcye = calculateInitialBalance(section, saleOrgUnit, custName, previousYearStart, previousYearEnd); - qcyeCache.put(cacheKey, qcye); - } else { - qcye = qcyeCache.get(cacheKey); - if (qcye == null) { - // 如果缓存中没有,说明之前没有计算过,则计算并缓存 - LocalDate previousYearStart = currentDate.minusYears(1).withDayOfYear(1); - LocalDate previousYearEnd = currentDate.minusYears(1).withDayOfYear(365); - qcye = calculateInitialBalance(section, saleOrgUnit, custName, previousYearStart, previousYearEnd); - qcyeCache.put(cacheKey, qcye); - } - } + // 计算累计销售(本年年初到查询截止日期) + LocalDate yearStart = monthStartDate.withDayOfYear(1); + BigDecimal ljxs = calculateTotalSales(section, saleOrgUnit, custName, monthEndDate, monthEnd); - // 计算当日销售 - BigDecimal dailySales = calculateTotalSales(section, saleOrgUnit, custName, currentDate, currentDate); - // 计算当日还款 - BigDecimal dailyRepayment = calculateTotalRepayment(section, saleOrgUnit, custName, currentDate, currentDate); - - // 计算累计销售(本年年初到当前日期)- 使用增量方式 - BigDecimal ljxs; - if (currentDate.equals(startDate)) { - // 第一天直接使用当日销售 - ljxs = dailySales; - } else { - // 后续天数:前一天的累计销售 + 当日销售 - BigDecimal previousLjxs = previousLjxsCache.getOrDefault(cacheKey, BigDecimal.ZERO); - ljxs = previousLjxs.add(dailySales); - } - previousLjxsCache.put(cacheKey, ljxs); - - // 计算累计还款(本年年初到当前日期)- 使用增量方式 - BigDecimal ljhk; - if (currentDate.equals(startDate)) { - // 第一天直接使用当日还款 - ljhk = dailyRepayment; - } else { - // 后续天数:前一天的累计还款 + 当日还款 - BigDecimal previousLjhk = previousLjhkCache.getOrDefault(cacheKey, BigDecimal.ZERO); - ljhk = previousLjhk.add(dailyRepayment); - } - previousLjhkCache.put(cacheKey, ljhk); + // 计算累计还款(本年年初到查询截止日期) + BigDecimal ljhk = calculateTotalRepayment(section, saleOrgUnit, custName, monthEndDate, monthEnd); // 计算应收余额 BigDecimal ysye = qcye.add(ljxs).subtract(ljhk); +// LOGGER.info("计算应收余额={}",ysye.doubleValue()); - // 计算账龄分析 - Map zlfx = calculateAgingAnalysis(historicalBalanceCache, saleOrgUnit, custName, currentDate, ysye); + // 计算账龄分析(需要查询历史数据) + 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, currentDate, custName, + section, manageRegionName, saleOrgUnit, monthEndDate, custName, province, city, district, qcye, ljxs, ljhk, ysye, zlfx ); @@ -198,9 +171,6 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { batchData.clear(); } - // 更新历史余额缓存,用于后续账龄分析 - updateHistoricalBalanceCache(historicalBalanceCache, saleOrgUnit, custName, currentDate, ysye); - // 更新处理计数 processedCount++; if (processedCount % 1000 == 0) { @@ -208,8 +178,8 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { } } catch (Exception e) { - LOGGER.error("{}板块处理销售组织 {} 客户 {} 日期 {} 时发生错误", - sectionName, row.getString("FSaleOrgUnit"), row.getString("FCustName"), currentDate, e); + LOGGER.error("{}板块处理销售组织 {} 客户 {} 月末日期 {} 时发生错误", + sectionName, row.getString("XSZZ"), row.getString("FCUSTNAME"), monthEndDate, e); } } } @@ -228,18 +198,65 @@ 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 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); + } + } + // 如果当前月份与endDate是同年同月 + else { + LocalDate dayBeforeEnd = endDate.minusDays(1); + // 确保前一天在时间范围内 + if (!dayBeforeEnd.isBefore(startDate)) { + monthEndDates.add(dayBeforeEnd); + } + break; // 遇到同年同月后就可以结束循环了 + } + 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 BETWEEN ? AND ?", - saleOrgUnit, custName, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate) + " 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; @@ -247,9 +264,11 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { // 查询收款单总额 RowMap skResult = DBSql.getMap( "SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSkdTable() + - " WHERE FSALEORGUNIT = ? AND FCUSTNAME = ? AND FBILLDATE BETWEEN ? AND ?", - saleOrgUnit, custName, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate) + " 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; @@ -257,13 +276,16 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { // 查询收款退款单总额 RowMap sktkResult = DBSql.getMap( "SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSktkdTable() + - " WHERE FSALEORGUNIT = ? AND FCUSTNAME = ? AND FBILLDATE BETWEEN ? AND ?", - saleOrgUnit, custName, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate) + " 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); @@ -278,13 +300,19 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { */ 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 BETWEEN ? AND ?", - saleOrgUnit, custName, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate) + " 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+""); +// 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; @@ -299,13 +327,17 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { */ 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"; try { // 查询收款单总额 RowMap skResult = DBSql.getMap( "SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSkdTable() + - " WHERE FSALEORGUNIT = ? AND FCUSTNAME = ? AND FBILLDATE BETWEEN ? AND ?", - saleOrgUnit, custName, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate) + " 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+""); BigDecimal skTotal = skResult != null && skResult.get("total") != null ? new BigDecimal(skResult.get("total").toString()) : BigDecimal.ZERO; @@ -313,13 +345,15 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { // 查询收款退款单总额 RowMap sktkResult = DBSql.getMap( "SELECT SUM(FSALEAMOUNTRMB) as total FROM " + section.getSktkdTable() + - " WHERE FSALEORGUNIT = ? AND FCUSTNAME = ? AND FBILLDATE BETWEEN ? AND ?", - saleOrgUnit, custName, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate) + " 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+""); 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); @@ -330,17 +364,13 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { } /** - * 计算账龄分析 + * 计算月度账龄分析 */ - private Map calculateAgingAnalysis(Map> historicalBalanceCache, - String saleOrgUnit, String custName, - LocalDate currentDate, BigDecimal currentBalance) { + private Map calculateMonthlyAgingAnalysis(Section section, String saleOrgUnit, String custName, + LocalDate currentDate, BigDecimal currentBalance) { Map result = new HashMap<>(); try { - String key = saleOrgUnit + "_" + custName; - Map customerHistory = historicalBalanceCache.getOrDefault(key, new HashMap<>()); - // 计算各个时间点的应收余额 LocalDate date60DaysAgo = currentDate.minusDays(60); LocalDate date1YearAgo = currentDate.minusYears(1); @@ -349,21 +379,22 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { LocalDate date4YearsAgo = currentDate.minusYears(4); LocalDate date5YearsAgo = currentDate.minusYears(5); - BigDecimal balance60DaysAgo = findClosestBalance(customerHistory, date60DaysAgo); - BigDecimal balance1YearAgo = findClosestBalance(customerHistory, date1YearAgo); - BigDecimal balance2YearsAgo = findClosestBalance(customerHistory, date2YearsAgo); - BigDecimal balance3YearsAgo = findClosestBalance(customerHistory, date3YearsAgo); - BigDecimal balance4YearsAgo = findClosestBalance(customerHistory, date4YearsAgo); - BigDecimal balance5YearsAgo = findClosestBalance(customerHistory, date5YearsAgo); + // 查询历史月末的应收余额 + 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); // 计算各账龄段金额 - result.put("ZLFX0_60", currentBalance.subtract(balance60DaysAgo)); - result.put("ZLFX60_1", balance60DaysAgo.subtract(balance1YearAgo)); - result.put("ZLFX1_2", balance1YearAgo.subtract(balance2YearsAgo)); - result.put("ZLFX2_3", balance2YearsAgo.subtract(balance3YearsAgo)); - result.put("ZLFX3_4", balance3YearsAgo.subtract(balance4YearsAgo)); - result.put("ZLFX4_5", balance4YearsAgo.subtract(balance5YearsAgo)); - result.put("ZLFX5", balance5YearsAgo); + 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)); } catch (Exception e) { LOGGER.error("计算账龄分析时发生错误,销售组织: {}, 客户: {}", saleOrgUnit, custName, e); @@ -381,27 +412,29 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { } /** - * 查找最接近日期的应收余额 + * 查找指定月末的应收余额 */ - private BigDecimal findClosestBalance(Map history, LocalDate targetDate) { - if (history.isEmpty()) { + private BigDecimal findMonthlyBalance(Section section, String saleOrgUnit, String custName, LocalDate targetDate) { + // 调整为目标月份的月末日期 + LocalDate monthEndDate = targetDate.withDayOfMonth(targetDate.lengthOfMonth()); + String dateStr = monthEndDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 23:59:59"; + + try { + // 查询目标表中该月末的应收余额 + RowMap result = DBSql.getMap( + "SELECT YSYE FROM " + section.getTargetTable() + + " WHERE XSZZ = ? AND KH = ? AND RQ = ?", + saleOrgUnit, custName, dateStr + ); + + 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; } - - // 首先尝试精确匹配 - if (history.containsKey(targetDate)) { - return history.get(targetDate); - } - - // 如果没有精确匹配,查找最接近的日期 - LocalDate closestDate = null; - for (LocalDate date : history.keySet()) { - if (date.isBefore(targetDate) && (closestDate == null || date.isAfter(closestDate))) { - closestDate = date; - } - } - - return closestDate != null ? history.get(closestDate) : BigDecimal.ZERO; } /** @@ -451,16 +484,4 @@ public class WaterproofPaintAccountsReceivableJob implements IJob { LOGGER.error("批量插入{}板块数据到表{}时发生错误", section.getName(), section.getTargetTable(), e); } } - - /** - * 更新历史余额缓存 - */ - private void updateHistoricalBalanceCache(Map> historicalBalanceCache, - String saleOrgUnit, String custName, - LocalDate date, BigDecimal balance) { - String key = saleOrgUnit + "_" + custName; - historicalBalanceCache - .computeIfAbsent(key, k -> new HashMap<>()) - .put(date, balance); - } } \ No newline at end of file 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/ProductionDataSyncServiceImpl.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/ProductionDataSyncServiceImpl.java index c334a61..4ab0fe8 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/ProductionDataSyncServiceImpl.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/ProductionDataSyncServiceImpl.java @@ -698,8 +698,10 @@ public class ProductionDataSyncServiceImpl implements DataSyncService { String tablename = mainConfig.getString("TABLENAME");//同步表名 String hzb = ""; try { - if ("原材料".equals(tablename)){ - hzb = "BO_EU_DWS_ORDER_YCLXH_HZ"; + if ("生产入库".equals(tablename)) { + hzb = "BO_EU_BNBM_SCRK_HZ"; + } else if ("生产出库".equals(tablename)) { + hzb = "BO_EU_BNBM_SCCK_HZ"; }else { continue; } 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 6c82f53..2dda400 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 @@ -409,6 +409,19 @@ public class SaleCountDimensionImpl implements DataSummaryService { ), (existing, replacement) -> existing )); + // 获取公司简称 + List gsjcList = DBSql.getMaps("SELECT GSMC,JC FROM BO_EU_BNBM_ZZWHB"); + Map gsjcMap = gsjcList.stream() + .filter(row -> { + String gsmc = row.getString("GSMC"); + String jc = row.getString("JC"); + return gsmc != null && jc != null; + }) + .collect(Collectors.toMap( + row -> row.getString("GSMC"), + row -> row.getString("JC"), + (existing, replacement) -> existing // 处理重复key + )); String querySql = "SELECT DZRQ,QYGS, KCZZ, " + " CASE " + @@ -492,6 +505,9 @@ public class SaleCountDimensionImpl implements DataSummaryService { bo.set("ISOEM", gzjzStrings[4]);//是否OEM板 // bo.set("SNTQXE", map.getString("sntqxe")); bo.set("BHSYYSR", ssjermb); + if (gsjcMap.containsKey(gc)) { + bo.set("GCJC", gsjcMap.get(gc)); + } bos.add(bo); } 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 596bc43..f33ddb5 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 @@ -11,6 +11,7 @@ import com.actionsoft.sdk.local.SDK; import com.actionsoft.sdk.local.api.cc.RDSAPI; import com.awspaas.user.apps.bnbm.datalinkup.entity.DateRange; import com.awspaas.user.apps.bnbm.datalinkup.service.DataSyncService; +import com.awspaas.user.apps.bnbm.datalinkup.util.SaleUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -140,13 +141,13 @@ public class SaleDataSyncServiceImpl implements DataSyncService { // 按时间范围删除 deleteTargetData(targetTable, targetTimeField, startDate, endDate); } - // 查询源表数据(跨库查询) - querySourceData(ccId, tableName, timeField, startDate, endDate, partitionField, - fieldMappings, targetTable,jezd); + // 查询源表数据(跨库查询) if (tablename.equals("应收表")){ LOGGER.info("开始执行应收的明细汇总"); - querySourceDataYS(ccId, tableName, timeField, startDate, endDate, partitionField, - fieldMappings, targetTable, jezd); + if ((!bkgs.equals("北新防水")) || (!bkgs.equals("北新涂料"))) { + querySourceDataYS(ccId, tableName, timeField, startDate, endDate, partitionField, + fieldMappings, targetTable, jezd); + } }else { querySourceData(ccId, tableName, timeField, startDate, endDate, partitionField, fieldMappings, targetTable, jezd); @@ -560,6 +561,7 @@ public class SaleDataSyncServiceImpl implements DataSyncService { */ public int processAndInsertData(List sourceData, List mappings, String targetTable) { + List gzjzList = SDK.getBOAPI().query("BO_EU_DATALINKUP_CPJZGZJCMC").desc().list(); String bkgs = ""; Set bkgsSet = null; if (sourceData.isEmpty()) { @@ -578,8 +580,20 @@ public class SaleDataSyncServiceImpl implements DataSyncService { try { // 字段映射转换 BO targetData = convertFields(record, mappings); + // 匹配公装家装类别,如果未匹配到,则默认未其他 + if ("BO_EU_BNBM_DATALINKUP_XS_XSL_JBL,BO_EU_BNBM_DATALINKUP_XS_XSL,BO_EU_TL_SALESDATA_SKD,BO_EU_SALESDATA_SKD,BO_EU_BNBM_DATALINKUP_XS_XSL_TS".contains(targetTable)) { + String[] gzjzStrings = SaleUtil.matchSingleField(targetData.getString("BKGS"), targetData.getString("LB_1"), + targetData.getString("LB_2"), targetData.getString("LB_3"), gzjzList, "其他", "其他", "其他"); + targetData.set("MC_JC", gzjzStrings[1]);//面材/基材 + targetData.set("JZ_GZ", gzjzStrings[0]);//家装/工装 + targetData.set("PROD_CAT", gzjzStrings[2]);//产品类型 + targetData.set("PBGNB", gzjzStrings[3]);//普板/功能板 + targetData.set("ISOEM", gzjzStrings[4]);//是否OEM板 +// bo.set("SNTQXE", map.getString("sntqxe")); + } batchList.add(targetData); + // 批量插入条件:达到批处理大小或最后一条 if (batchList.size() >= PAGE_SIZE || i == totalCount - 1) { // 使用管理员权限批量插入 @@ -593,7 +607,7 @@ public class SaleDataSyncServiceImpl implements DataSyncService { } } // 增加详细日志输出:共处理多少条,成功同步多少条 - bkgs = Arrays.toString(bkgsSet.toArray()); + bkgs = bkgsSet.stream().collect(Collectors.joining(", ")); LOGGER.info("同步板块为:{};落地表为:{},本次处理{}条数据,成功同步{}条数据到表[{}]", bkgs,targetTable,processedCount, successCount, targetTable); return successCount;