1、销售拉明细增加家装面材产品类型等
2、销售bi汇总销量销额增加工厂简称,维护经纬度 3、修改计算判断 4、修改防水涂料应收
This commit is contained in:
parent
9b3a659a6e
commit
d612cf8311
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
||||
// 按时间范围分页迁移数据到汇总表
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user