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