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 4035800..14e3e31 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 6f2e41a..f1f08ba 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 72a2f6a..f31f83d 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/libs/com.awspaas.user.apps.bnbm.datalinkup-1.0-SNAPSHOT.jar b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/libs/com.awspaas.user.apps.bnbm.datalinkup-1.0-SNAPSHOT.jar index 8f601c5..82f764f 100644 Binary files a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/libs/com.awspaas.user.apps.bnbm.datalinkup-1.0-SNAPSHOT.jar and b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/build/libs/com.awspaas.user.apps.bnbm.datalinkup-1.0-SNAPSHOT.jar 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 2a86a5b..52c33c3 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 7cbbf2b..f65c8bc 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 @@ -357,80 +357,6 @@ public class DataLinkUpController { LOGGER.info("【完成】数据计算汇总操作,总耗时:{}ms", methodEndTime - methodStartTime); return ro; } - // public ResponseObject calculateSummary(String dataStr, String sid, String formattedDate) { -// long methodStartTime = System.currentTimeMillis(); -// LOGGER.info("【开始】数据计算汇总操作,开始时间:{}", new Date(methodStartTime)); -// ResponseObject ro = ResponseObject.newOkResponse(); -// JSONArray configArray = new JSONArray(dataStr); -// -// Calendar cal = Calendar.getInstance(); -// cal.add(Calendar.DATE, -1); // 昨天 -// Date endDate = cal.getTime(); -// -// // 解析formattedDate为日期对象并计算时间范围 -// DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); -// LocalDate date = LocalDate.parse(formattedDate, dateFormatter); -// LocalDateTime startDateTime = date.atStartOfDay(); // 当天00:00:00 -// Date startDate = Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()); -// DataSummaryService summaryService = null; -// SaleCountDimensionImpl saleCountDimension = null; -// try { -// LOGGER.info("开始执行销售数据多维度汇总计算"); -// -// DateRange dateRange = new DateRange(); -// dateRange.setStartDate(startDate); -// dateRange.setEndDate(endDate); -// LOGGER.info("汇总计算开始时间为:{},结束时间为:{}",startDate,endDate); -// // 2. 执行汇总计算 -// for (int i = 0; i < configArray.length(); i++) { -// JSONObject config = configArray.getJSONObject(i); -// String timeField = config.getString("SJZD"); -// String ccId = config.getString("CC_ID"); -// String targetTable = config.getString("LDB"); -// String partitionField = config.getString("FQBZD"); -// String tableName = config.getString("TBB"); -// String bkgs = config.getString("SSBK"); -// String ssyw = config.getString("SSYW"); -// -// // 1. 创建数据汇总服务实例 -// if ("销售".equals(ssyw)) { -// summaryService = new SaleDataSummaryServiceImpl(); -// saleCountDimension = new SaleCountDimensionImpl(); -// LOGGER.info("销售销售的接口"); -// }else { -// summaryService = new PurchaseDataSummaryServiceImpl(); -// LOGGER.info("采购销售的接口"); -// } -// -// List bkgsMaps = DBSql.getMaps("SELECT BKGS FROM " + targetTable + " GROUP BY BKGS"); -// if (bkgsMaps!=null) { -// for (RowMap map : bkgsMaps) { -// BO bo = new BO(); -// bo.set("BKGS", map.getString("BKGS")); -//// summaryService.calculateSummary(dateRange, bo); -//// if (saleCountDimension!=null){ -//// //计算销售的维度 -//// LOGGER.info("======== 开始执行销售数据汇总计算 ========"); -// saleCountDimension.calculateSummary(dateRange, bo); -//// LOGGER.info("======== 销售数据汇总计算完成 ========"); -//// } -// } -// } -// } -// -// ro.put("success", true); -// ro.put("message", "数据汇总计算完成"); -// LOGGER.info("销售数据多维度汇总计算完成"); -// } catch (Exception e) { -// String errorMsg = "数据汇总计算失败: " + e.getMessage(); -// LOGGER.error(errorMsg, e); -// ro.put("success", false); -// ro.put("message", errorMsg); -// } -// long methodEndTime = System.currentTimeMillis(); -// LOGGER.info("【完成】数据计算汇总操作,总耗时:{}ms", methodEndTime - methodStartTime); -// return ro; -// } /** * 各板块数据汇总 diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/enums/Section.java b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/enums/Section.java new file mode 100644 index 0000000..21157c6 --- /dev/null +++ b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/enums/Section.java @@ -0,0 +1,46 @@ +package com.awspaas.user.apps.bnbm.datalinkup.enums; + +/** + * @ClassName: Section + * @Description: 防水涂料应收单枚举 + * @date: 2025/8/30 8:48 + * @Blog: https:// + */ +public enum Section { + + // 防水板块配置 + WATERPROOF("防水", "北新防水", + "BO_EU_XS_YSL_BXFS", + "T_FS_SalesData_YSD", + "T_FS_SalesData_SKD", + "T_FS_SalesData_SKTKD"), + // 涂料板块配置 + PAINT("涂料", "北新涂料", + "BO_EU_XS_YSL_BXTL", + "T_TL_SalesData_YSD", + "T_TL_SalesData_SKD", + "T_TL_SalesData_SKTKD"); + + private final String name; + private final String bkgs; + private final String targetTable; + private final String ysdTable; + private final String skdTable; + private final String sktkdTable; + + Section(String name, String bkgs, String targetTable, String ysdTable, String skdTable, String sktkdTable) { + this.name = name; + this.bkgs = bkgs; + this.targetTable = targetTable; + this.ysdTable = ysdTable; + this.skdTable = skdTable; + this.sktkdTable = sktkdTable; + } + + public String getName() { return name; } + public String getBkgs() { return bkgs; } + public String getTargetTable() { return targetTable; } + public String getYsdTable() { return ysdTable; } + public String getSkdTable() { return skdTable; } + public String getSktkdTable() { return sktkdTable; } +} 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 new file mode 100644 index 0000000..5ec94e9 --- /dev/null +++ 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 @@ -0,0 +1,447 @@ +package com.awspaas.user.apps.bnbm.datalinkup.job; + +import com.actionsoft.bpms.bo.engine.BO; +import com.actionsoft.bpms.commons.database.RowMap; +import com.actionsoft.bpms.schedule.IJob; +import com.actionsoft.bpms.server.UserContext; +import com.actionsoft.bpms.util.DBSql; +import com.actionsoft.bpms.util.UtilDate; +import com.actionsoft.sdk.local.SDK; +import com.actionsoft.sdk.local.api.cc.RDSAPI; +import com.awspaas.user.apps.bnbm.datalinkup.enums.Section; +import com.awspaas.user.apps.bnbm.datalinkup.service.impl.SaleDataSyncServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @ClassName: WaterproofPaintAccountsReceivableJob + * @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 THREAD_POOL_SIZE = 2; // 线程池大小,根据需求调整 + + // 板块配置 + + + @Override + public void execute(JobExecutionContext job) throws JobExecutionException { + try { + String param = SDK.getJobAPI().getJobParameter(job); + int timeRange = StringUtils.isNotBlank(param)?Integer.parseInt(param):0; + + // 获取当前时间 + LocalDate nowDate = LocalDate.now(); + LocalDate startDate; + + if (timeRange > 0) { + startDate = nowDate.minusDays(timeRange); + } else { + // 默认计算去年第一天到现在的数据 + startDate = nowDate.minusYears(1).withDayOfYear(1); + } + + LOGGER.info("开始执行防水涂料应收单计算任务,时间范围:{} 到 {}", startDate, nowDate); + + // 依次处理防水和涂料两个板块 + boolean allSuccess = true; + for (Section section : Section.values()) { + boolean success = processSection(section, startDate, nowDate); + if (!success) { + allSuccess = false; + LOGGER.error("{}板块处理失败", section.getName()); + } + } + + if (!allSuccess) { + throw new JobExecutionException("部分板块处理失败"); + } + + LOGGER.info("防水涂料应收单计算任务完成,共处理 {} 天数据", nowDate.toEpochDay() - startDate.toEpochDay() + 1); + + } catch (Exception e) { + LOGGER.error("执行防水涂料应收单计算任务时发生错误", e); + throw new JobExecutionException("任务执行失败", e); + } + } + /** + * 处理单个板块的数据 + * @param section 板块配置 + * @param startDate 开始日期 + * @param nowDate 结束日期 + * @return 处理是否成功 + */ + private boolean processSection(Section section, LocalDate startDate, LocalDate nowDate) { + String sectionName = section.getName(); + LOGGER.info("开始处理{}板块数据,时间范围:{} 到 {}", sectionName, startDate, nowDate); + + // 每个板块使用独立的缓存 + Map> historicalBalanceCache = new HashMap<>(); + + try { + // 开始清理开始时间到结束时间的数据后再进行计算更新数据 + String startDateFormat = startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + String nowDateFormat = nowDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + int delete = DBSql.update("DELETE FROM " + section.getTargetTable() + + " WHERE RQ BETWEEN '" + startDateFormat + "' AND '" + nowDateFormat + "'"); + LOGGER.info("已删除目标表[{}]中{}条数据(时间范围: {} - {})", + section.getTargetTable(), delete, startDateFormat, nowDateFormat); + + // 获取RDSAPI实例 + RDSAPI rdsapi = SDK.getCCAPI().getRDSAPI(RDS_ID); + + // 查询销售组织和客户分组信息 + List maps = rdsapi.getMaps("SELECT FManageRegionName, FSaleOrgUnit, FCustName FROM " + + section.getYsdTable() + " GROUP BY FManageRegionName, FSaleOrgUnit, FCustName"); + + if (maps == null || maps.isEmpty()) { + LOGGER.warn("{}板块未查询到销售组织和客户数据", sectionName); + return true; // 没有数据也算成功 + } + + LOGGER.info("{}板块共查询到 {} 个销售组织-客户组合", sectionName, maps.size()); + + // 用于批量插入的数据列表 + List batchData = new ArrayList<>(); + int processedCount = 0; + + // 遍历日期范围 + for (LocalDate currentDate = startDate; !currentDate.isAfter(nowDate); currentDate = currentDate.plusDays(1)) { + LOGGER.debug("{}板块正在处理日期: {}", sectionName, currentDate); + + // 遍历每个销售组织-客户组合 + for (RowMap row : maps) { + try { + String manageRegionName = row.getString("FManageRegionName"); + String saleOrgUnit = row.getString("FSaleOrgUnit"); + String custName = row.getString("FCustName"); + + // 查询省市区信息 + RowMap locationInfo = rdsapi.getMap( + "SELECT FProvince, FCity FROM " + section.getYsdTable() + + " WHERE FSaleOrgUnit = ? AND FCustName = ? ", + saleOrgUnit, custName + ); + + String province = locationInfo != null ? locationInfo.getString("FProvince") : ""; + String city = locationInfo != null ? locationInfo.getString("FCity") : ""; + String district = locationInfo != null ? locationInfo.getString("FDistrict") : ""; + + // 计算期初余额(上一年度) + LocalDate previousYearStart = currentDate.minusYears(1).withDayOfYear(1); + LocalDate previousYearEnd = currentDate.minusYears(1).withDayOfYear(365); + + BigDecimal qcye = calculateInitialBalance(rdsapi, section, saleOrgUnit, custName, previousYearStart, previousYearEnd); + + // 计算累计销售(本年年初到当前日期) + LocalDate currentYearStart = currentDate.withDayOfYear(1); + BigDecimal ljxs = calculateTotalSales(rdsapi, section, saleOrgUnit, custName, currentYearStart, currentDate); + + // 计算累计还款(本年年初到当前日期) + BigDecimal ljhk = calculateTotalRepayment(rdsapi, section, saleOrgUnit, custName, currentYearStart, currentDate); + + // 计算应收余额 + BigDecimal ysye = qcye.add(ljxs).subtract(ljhk); + + // 计算账龄分析 + Map zlfx = calculateAgingAnalysis(historicalBalanceCache, saleOrgUnit, custName, currentDate, ysye); + + // 创建数据记录 + BO record = createRecord( + section, manageRegionName, saleOrgUnit, currentDate, custName, + province, city, district, qcye, ljxs, ljhk, ysye, zlfx + ); + + batchData.add(record); + + // 批量插入 + if (batchData.size() >= BATCH_SIZE) { + batchInsert(section, batchData); + batchData.clear(); + } + + // 更新历史余额缓存,用于后续账龄分析 + updateHistoricalBalanceCache(historicalBalanceCache, saleOrgUnit, custName, currentDate, ysye); + + // 更新处理计数 + processedCount++; + if (processedCount % 1000 == 0) { + LOGGER.info("{}板块已处理 {} 条记录", sectionName, processedCount); + } + + } catch (Exception e) { + LOGGER.error("{}板块处理销售组织 {} 客户 {} 日期 {} 时发生错误", + sectionName, row.getString("FSaleOrgUnit"), row.getString("FCustName"), currentDate, e); + } + } + } + + // 插入剩余数据 + if (!batchData.isEmpty()) { + batchInsert(section, batchData); + } + + LOGGER.info("{}板块数据处理完成,共处理 {} 条记录", sectionName, processedCount); + return true; + + } catch (Exception e) { + LOGGER.error("处理{}板块数据时发生错误", sectionName, e); + return false; + } + } + + /** + * 计算期初余额 + */ + private BigDecimal calculateInitialBalance(RDSAPI rdsapi, Section section, String saleOrgUnit, String custName, + LocalDate startDate, LocalDate endDate) { + try { + // 查询应收单总额 + RowMap ysResult = rdsapi.getMap( + "SELECT SUM(FSaleAmountRMB) as total FROM " + section.getYsdTable() + + " WHERE FSaleOrgUnit = ? AND FCustName = ? AND FBillDate BETWEEN ? AND ?", + saleOrgUnit, custName, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate) + ); + + BigDecimal ysTotal = ysResult != null && ysResult.get("total") != null ? + new BigDecimal(ysResult.get("total").toString()) : BigDecimal.ZERO; + + // 查询收款单总额 + RowMap skResult = rdsapi.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) + ); + + BigDecimal skTotal = skResult != null && skResult.get("total") != null ? + new BigDecimal(skResult.get("total").toString()) : BigDecimal.ZERO; + + // 查询收款退款单总额 + RowMap sktkResult = rdsapi.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) + ); + + BigDecimal sktkTotal = sktkResult != null && sktkResult.get("total") != null ? + new BigDecimal(sktkResult.get("total").toString()) : BigDecimal.ZERO; + + // 期初余额 = 应收单总额 - 收款单总额 + 收款退款单总额 + return ysTotal.subtract(skTotal).add(sktkTotal); + + } catch (Exception e) { + LOGGER.error("计算{}板块期初余额时发生错误,销售组织: {}, 客户: {}", section.getName(), saleOrgUnit, custName, e); + return BigDecimal.ZERO; + } + } + + /** + * 计算累计销售 + */ + private BigDecimal calculateTotalSales(RDSAPI rdsapi, Section section, String saleOrgUnit, String custName, + LocalDate startDate, LocalDate endDate) { + try { + RowMap result = rdsapi.getMap( + "SELECT SUM(FSaleAmountRMB) as total FROM " + section.getYsdTable() + + " WHERE FSaleOrgUnit = ? AND FCustName = ? AND FBillDate BETWEEN ? AND ?", + saleOrgUnit, custName, java.sql.Date.valueOf(startDate), java.sql.Date.valueOf(endDate) + ); + + return result != null && result.get("total") != null ? + new BigDecimal(result.get("total").toString()) : BigDecimal.ZERO; + + } catch (Exception e) { + LOGGER.error("计算{}板块累计销售时发生错误,销售组织: {}, 客户: {}", section.getName(), saleOrgUnit, custName, e); + return BigDecimal.ZERO; + } + } + + /** + * 计算累计还款 + */ + private BigDecimal calculateTotalRepayment(RDSAPI rdsapi, Section section, String saleOrgUnit, String custName, + LocalDate startDate, LocalDate endDate) { + try { + // 查询收款单总额 + RowMap skResult = rdsapi.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) + ); + + BigDecimal skTotal = skResult != null && skResult.get("total") != null ? + new BigDecimal(skResult.get("total").toString()) : BigDecimal.ZERO; + + // 查询收款退款单总额 + RowMap sktkResult = rdsapi.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) + ); + + BigDecimal sktkTotal = sktkResult != null && sktkResult.get("total") != null ? + new BigDecimal(sktkResult.get("total").toString()) : BigDecimal.ZERO; + + // 累计还款 = 收款单总额 - 收款退款单总额 + return skTotal.subtract(sktkTotal); + + } catch (Exception e) { + LOGGER.error("计算{}板块累计还款时发生错误,销售组织: {}, 客户: {}", section.getName(), saleOrgUnit, custName, e); + return BigDecimal.ZERO; + } + } + + /** + * 计算账龄分析 + */ + private Map calculateAgingAnalysis(Map> historicalBalanceCache, + 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); + LocalDate date2YearsAgo = currentDate.minusYears(2); + LocalDate date3YearsAgo = currentDate.minusYears(3); + 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); + + // 计算各账龄段金额 + 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); + + } 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); + result.put("ZLFX2_3", BigDecimal.ZERO); + result.put("ZLFX3_4", BigDecimal.ZERO); + result.put("ZLFX4_5", BigDecimal.ZERO); + result.put("ZLFX5", BigDecimal.ZERO); + } + + return result; + } + + /** + * 查找最接近日期的应收余额 + */ + private BigDecimal findClosestBalance(Map history, LocalDate targetDate) { + if (history.isEmpty()) { + 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; + } + + /** + * 创建数据记录 + */ + private BO createRecord(Section section, String manageRegionName, String saleOrgUnit, LocalDate date, + String custName, String province, String city, String district, + BigDecimal qcye, BigDecimal ljxs, BigDecimal ljhk, BigDecimal ysye, + Map zlfx) { + BO record = new BO(); + + // 业务字段 + record.set("BKGS", section.getBkgs()); + record.set("QYGS", manageRegionName); + record.set("XSZZ", saleOrgUnit); + record.set("RQ", Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant())); + record.set("KH", custName); + record.set("SHENGQU", province); + record.set("SHIQU", city); + record.set("QX", district); + record.set("QCYE", qcye); + record.set("LJXS", ljxs); + record.set("LJHK", ljhk); + 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")); + + return record; + } + + /** + * 批量插入数据 + */ + 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()); + } catch (Exception e) { + 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/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 e9013bd..9805b91 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 @@ -462,7 +462,23 @@ public class SaleCountDimensionImpl implements DataSummaryService { Calendar cal = Calendar.getInstance(); cal.setTime(YEAR_MONTH_FORMAT.parse(yearMonth)); cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); - String lastDayOfMonth = DATE_FORMAT.format(cal.getTime()); + Date lastDayOfMonthDate = cal.getTime(); + String lastDayOfMonth = DATE_FORMAT.format(lastDayOfMonthDate); + + // 获取当前日期 + Calendar todayCal = Calendar.getInstance(); + todayCal.set(Calendar.HOUR_OF_DAY, 0); + todayCal.set(Calendar.MINUTE, 0); + todayCal.set(Calendar.SECOND, 0); + todayCal.set(Calendar.MILLISECOND, 0); + Date today = todayCal.getTime(); + + // 比较日期 否则保持不变 + if (lastDayOfMonthDate.after(today)) { + // 如果月末日期大于今天,使用今天日期 + lastDayOfMonth = DATE_FORMAT.format(today); + } + // 分页查询区域两金占比数据 int page = 0; @@ -471,15 +487,14 @@ public class SaleCountDimensionImpl implements DataSummaryService { int offset = page * PAGE_SIZE; // 第一个SQL:查询应收账款数据 - String receivableSql = "SELECT QYGS, XSZZ, SUM(YSYE) as YSZK " + + String receivableSql = "SELECT QYGS, BKGS, YSYE as YSZK " + "FROM " + RECEIVABLE_DETAIL_TABLE + " " + - "WHERE YEAR(RQ) = YEAR(?) AND MONTH(RQ) = MONTH(?) AND BKGS = ? " + + "WHERE RQ = ? AND BKGS = ? " + "GROUP BY QYGS, BKGS " + "LIMIT " + PAGE_SIZE + " OFFSET " + offset; LOGGER.info("应收账款数据查询第{}页,SQL: {}", page + 1, receivableSql); - List receivableMaps = DBSql.getMaps(conn, receivableSql, - lastDayOfMonth, lastDayOfMonth, bkgs); + List receivableMaps = DBSql.getMaps(conn, receivableSql, lastDayOfMonth, bkgs); if (receivableMaps.isEmpty()) { hasMore = false; @@ -524,11 +539,6 @@ public class SaleCountDimensionImpl implements DataSummaryService { String xszz = receivable.getString("XSZZ"); double yszk = receivable.getDouble("YSZK"); double kcje = inventoryMap.getOrDefault(xszz, 0.0); - double ljzb = 0.0; - - if ((yszk + kcje) > 0) { - ljzb = (yszk / (yszk + kcje)) * 100; - } BO bo = new BO(); bo.set("YEARMONTH", yearMonth); 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 7faf271..5eeea0d 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 @@ -682,6 +682,9 @@ public class SaleDataSyncServiceImpl implements DataSyncService { List bos = new ArrayList<>(); for (RowMap map : pageData) { BO bo = new BO(); + if ("梦牌".equals(map.getString("BKGS")) && "梦牌新材料(平邑)有限公司".equals(map.getString("XSZZ"))){ + continue; + } // 复制所有字段(排除系统字段) for (String key : map.keySet()) { if (!key.equalsIgnoreCase("ID") && diff --git a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/util/PurchaseUtil.java b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/util/PurchaseUtil.java index 539d02d..d2c4ce8 100644 --- a/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/util/PurchaseUtil.java +++ b/com.awspaas.user.apps.bnbm.datalinkup/com.awspaas.user.apps.bnbm.datalinkup/src/main/java/com/awspaas/user/apps/bnbm/datalinkup/util/PurchaseUtil.java @@ -40,9 +40,9 @@ public class PurchaseUtil { newWlmc = "护面纸"; } // 乳液 - else if ("北新嘉宝莉".equals(bkgs) && wlbm.contains("11M")){ + else if ("北新嘉宝莉".equals(bkgs) && wlbm.startsWith("11M")){ newWlmc = "乳液"; - } else if ("北新防水".equals(bkgs) && wlbm.contains("5070201")) { + } else if ("北新防水".equals(bkgs) && wlbm.startsWith("5070201")) { newWlmc = "乳液"; } else if ("北新涂料".equals(bkgs) && wlbm.contains("10114137")) { newWlmc = "乳液";