1、销售拉明细增加家装面材产品类型等

2、销售bi汇总销量销额增加工厂简称,维护经纬度
3、修改计算判断
4、修改防水涂料应收
This commit is contained in:
llllon 2025-09-25 10:23:36 +08:00
parent 9b3a659a6e
commit d612cf8311
10 changed files with 232 additions and 163 deletions

View File

@ -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
// 按时间范围分页迁移数据到汇总表

View File

@ -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<String, Map<LocalDate, BigDecimal>> historicalBalanceCache = new HashMap<>();
// 新增缓存用于存储每日的累计值
Map<String, BigDecimal> previousLjxsCache = new HashMap<>(); // 缓存前一天的累计销售
Map<String, BigDecimal> previousLjhkCache = new HashMap<>(); // 缓存前一天的累计还款
Map<String, BigDecimal> 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<RowMap> maps = DBSql.getMaps("SELECT QYGS, FCUSTNAME, SQ AS FPROVINCE,CS AS FCITY FROM " +
List<RowMap> 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<BO> batchData = new ArrayList<>();
int processedCount = 0;
// 遍历日期范围
for (LocalDate currentDate = startDate; !currentDate.isAfter(nowDate); currentDate = currentDate.plusDays(1)) {
LOGGER.debug("{}板块正在处理日期: {}", sectionName, currentDate);
// 获取每个月的最大日期月末日期
List<LocalDate> 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<String, BigDecimal> zlfx = calculateAgingAnalysis(historicalBalanceCache, saleOrgUnit, custName, currentDate, ysye);
// 计算账龄分析需要查询历史数据
Map<String, BigDecimal> 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<LocalDate> getMonthEndDates(LocalDate startDate, LocalDate endDate) {
List<LocalDate> 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<String, BigDecimal> calculateAgingAnalysis(Map<String, Map<LocalDate, BigDecimal>> historicalBalanceCache,
String saleOrgUnit, String custName,
LocalDate currentDate, BigDecimal currentBalance) {
private Map<String, BigDecimal> calculateMonthlyAgingAnalysis(Section section, String saleOrgUnit, String custName,
LocalDate currentDate, BigDecimal currentBalance) {
Map<String, BigDecimal> result = new HashMap<>();
try {
String key = saleOrgUnit + "_" + custName;
Map<LocalDate, BigDecimal> 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<LocalDate, BigDecimal> 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<String, Map<LocalDate, BigDecimal>> historicalBalanceCache,
String saleOrgUnit, String custName,
LocalDate date, BigDecimal balance) {
String key = saleOrgUnit + "_" + custName;
historicalBalanceCache
.computeIfAbsent(key, k -> new HashMap<>())
.put(date, balance);
}
}

View File

@ -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;
}

View File

@ -409,6 +409,19 @@ public class SaleCountDimensionImpl implements DataSummaryService {
),
(existing, replacement) -> existing
));
// 获取公司简称
List<RowMap> gsjcList = DBSql.getMaps("SELECT GSMC,JC FROM BO_EU_BNBM_ZZWHB");
Map<String, String> 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);
}

View File

@ -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<RowMap> sourceData,
List<BO> mappings, String targetTable) {
List<BO> gzjzList = SDK.getBOAPI().query("BO_EU_DATALINKUP_CPJZGZJCMC").desc().list();
String bkgs = "";
Set<String> 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;