理财报表优化3.0

This commit is contained in:
李贵强 2025-06-19 18:12:20 +08:00
parent f1ff3dff9b
commit f54bb8c5b8
3 changed files with 312 additions and 108 deletions

View File

@ -74,21 +74,52 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
BigDecimal sumProvisionEarnings =BigDecimal.ZERO;//收益计提汇总 BigDecimal sumProvisionEarnings =BigDecimal.ZERO;//收益计提汇总
BigDecimal sumMonthEarnings =BigDecimal.ZERO;//本月收益汇总 BigDecimal sumMonthEarnings =BigDecimal.ZERO;//本月收益汇总
BigDecimal sumYearEarnings =BigDecimal.ZERO;//本年收益汇总 BigDecimal sumYearEarnings =BigDecimal.ZERO;//本年收益汇总
BigDecimal sumActualEarnings =BigDecimal.ZERO;//实际收益汇总
while (iterator.hasNext()) { while (iterator.hasNext()) {
DynamicObject row = iterator.next(); DynamicObject row = iterator.next();
// 基础字段获取添加null检查 //1.金额千元设置
BigDecimal amount = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[4]); // 原始金额 BigDecimal amount = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[4]); // 原始金额
BigDecimal buyAmount = amount.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);//购买金额千元 BigDecimal buyAmount = amount.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);//购买金额千元
row.set(REPORT_FIELDS[4],buyAmount); row.set(REPORT_FIELDS[4],buyAmount);
Date buyDate = row.getDate(REPORT_FIELDS[7]); // 购买日 Date buyDate = row.getDate(REPORT_FIELDS[7]); // 购买日
Date valueDate = row.getDate(REPORT_FIELDS[8]); // 计息日 Date valueDate = row.getDate(REPORT_FIELDS[8]); // 计息日
Date expireDate = row.getDate(REPORT_FIELDS[9]); // 到期日 Date expireDate = row.getDate(REPORT_FIELDS[9]); // 到期日-初始值
BigDecimal expectedRate = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[10]); // 预计业绩比较基准% BigDecimal expectedRate = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[10]); // 预计业绩比较基准%
String basis = row.getString(REPORT_FIELDS[15]);//计息基准 String basis = row.getString(REPORT_FIELDS[15]);//计息基准
//理财申购单估值分录处理
// 2. 设置计提日
row.set(DYNAMICS_FIELDS[1], accrualDate);
// 3. 计算产品期限总天数=到期日-计息日
String term = countProductTerm(valueDate, expireDate, accrualDate, row);
// 4. 计算天数 = 计提日 - 计息日
// 计提日<=到期日计提日 - 计息日
// 计提日>到期日到期日 - 计息日
Date expireDate2 = row.getDate(REPORT_FIELDS[9]);//到期日-改动值
BigDecimal days = countDays(valueDate,expireDate2, accrualDate, row);
// 5.计息基准天数
BigDecimal basisDays = computeBasisDays(basis);
// 6. 预计收益 = 产品期限 * 金额(千元) * 预计业绩比较基准 / 365
BigDecimal proRevenue = countProRevenue(expectedRate, term, amount, row,basisDays);
sumProjectedEarnings=sumProjectedEarnings.add(proRevenue);
// 理财申购单估值分录相关数据处理
// 7. 持有份额 = 计提日期向上最近持有份额
// 8. 月末单位净值 = 计提日期向上最近一次的净值
// 9. 月末净值报告日 = 计提日期向上最近一次的估值日期
// 10. 本月收益千元当月年化收益率%
// 11. 本年累计收益千元本年累计年化收益率
Long id = row.getLong(REPORT_FIELDS[13]); Long id = row.getLong(REPORT_FIELDS[13]);
valuationEntry(accrualDate,buyDate,buyAmount,id,row); valuationEntry(accrualDate,buyDate,expireDate2,valueDate,buyAmount,days,basisDays,id,row);
BigDecimal buyCopies = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[5]); // 持有份额 BigDecimal buyCopies = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[5]); // 持有份额
BigDecimal netWorth = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[6]); // 购买时单位净值 BigDecimal netWorth = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[6]); // 购买时单位净值
@ -96,33 +127,22 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
BigDecimal startBuyCopies = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[16]); // 购买份额 BigDecimal startBuyCopies = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[16]); // 购买份额
// 1. 设置计提日 // 12. 收益计提 = (持有份额 *月末单位净值 - 购买份额*购买时单位净值) / 1000
row.set(DYNAMICS_FIELDS[1], accrualDate); BigDecimal revenueAmt = countRevenueAmt(valueDate,expireDate2, accrualDate,buyCopies, monthNetWorth, netWorth, row,startBuyCopies);
// 2. 计算天数 = 计提日 - 计息日
countDays(valueDate,accrualDate,row);
// 3. 计算产品期限总天数=到期日-计息日
String day = countProductTerm(valueDate, expireDate, accrualDate, row);
// 4. 预计收益 = 产品期限 * 金额(千元) * 预计业绩比较基准 / 365
BigDecimal proRevenue = countProRevenue(expectedRate, day, amount, row,basis);
sumProjectedEarnings=sumProjectedEarnings.add(proRevenue);
// 5. 收益计提 = (持有份额 *月末单位净值 - 购买份额*购买时单位净值) / 1000
BigDecimal revenueAmt = countRevenueAmt(buyCopies, monthNetWorth, netWorth, row,startBuyCopies);
sumProvisionEarnings=sumProvisionEarnings.add(revenueAmt); sumProvisionEarnings=sumProvisionEarnings.add(revenueAmt);
// 本月收益计算累计 // 本月收益计算累计
//BigDecimal monthRevenue = countMonthRevenue(monthNetWorth, netWorth, buyCopies, valueDate, accrualDate, expireDate, row);
BigDecimal monthRevenue = ReportUtils.getBigDecimalValue(row, DYNAMICS_FIELDS[4]); BigDecimal monthRevenue = ReportUtils.getBigDecimalValue(row, DYNAMICS_FIELDS[4]);
sumMonthEarnings=sumMonthEarnings.add(monthRevenue); sumMonthEarnings=sumMonthEarnings.add(monthRevenue);
// 7. 当月收益率 = 本月收益 / 金额(千元) * 100 * 12
//countMonthRate(amount,monthRevenue,row);
// 本年收益累计 // 本年收益累计
//BigDecimal yearRevenue = countYearRevenue(monthNetWorth, netWorth, buyCopies, valueDate, accrualDate, expireDate, row);
BigDecimal yearRevenue = ReportUtils.getBigDecimalValue(row, DYNAMICS_FIELDS[6]); BigDecimal yearRevenue = ReportUtils.getBigDecimalValue(row, DYNAMICS_FIELDS[6]);
sumYearEarnings=sumYearEarnings.add(yearRevenue); sumYearEarnings=sumYearEarnings.add(yearRevenue);
//实际总收益率=实际收益/金额 //实际总收益率=实际收益/金额
BigDecimal actualEarnings = ReportUtils.getBigDecimalValue(row, DYNAMICS_FIELDS[8]); BigDecimal actualEarnings = ReportUtils.getBigDecimalValue(row, DYNAMICS_FIELDS[8]);
row.set(DYNAMICS_FIELDS[9],actualEarnings.divide(buyAmount,2, RoundingMode.HALF_UP)); row.set(DYNAMICS_FIELDS[9],actualEarnings.divide(buyAmount,2, RoundingMode.HALF_UP));
sumActualEarnings=sumActualEarnings.add(actualEarnings);
//小计行合计 //小计行合计
// if (row.getString(REPORT_FIELDS[0]).contains("-小计")){ // if (row.getString(REPORT_FIELDS[0]).contains("-小计")){
@ -141,6 +161,8 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
//小计行处理 //小计行处理
//ReportUtils.changeRowData(rowData,REPORT_FIELDS[0]); //ReportUtils.changeRowData(rowData,REPORT_FIELDS[0]);
//过滤
ReportUtils.removeRowData(rowData,REPORT_FIELDS[9],DYNAMICS_FIELDS[1]);
//添加合计 //添加合计
// 需要配置求和的字段映射目标字段来源字段 // 需要配置求和的字段映射目标字段来源字段
List<String[]> sumConfig = new ArrayList<>(); List<String[]> sumConfig = new ArrayList<>();
@ -151,6 +173,7 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
sumConfig.add(new String[]{DYNAMICS_FIELDS[3], DYNAMICS_FIELDS[3]}); // shjh_revenueamt sumConfig.add(new String[]{DYNAMICS_FIELDS[3], DYNAMICS_FIELDS[3]}); // shjh_revenueamt
sumConfig.add(new String[]{DYNAMICS_FIELDS[4], DYNAMICS_FIELDS[4]}); // shjh_monthrevenueamt sumConfig.add(new String[]{DYNAMICS_FIELDS[4], DYNAMICS_FIELDS[4]}); // shjh_monthrevenueamt
sumConfig.add(new String[]{DYNAMICS_FIELDS[6], DYNAMICS_FIELDS[6]}); // shjh_yearrevenueamt sumConfig.add(new String[]{DYNAMICS_FIELDS[6], DYNAMICS_FIELDS[6]}); // shjh_yearrevenueamt
sumConfig.add(new String[]{DYNAMICS_FIELDS[8], DYNAMICS_FIELDS[8]}); // shjh_actualearnings
ReportUtils.addTotalRowData(rowData,REPORT_FIELDS[0],"小计","合计",sumConfig); ReportUtils.addTotalRowData(rowData,REPORT_FIELDS[0],"小计","合计",sumConfig);
@ -161,10 +184,13 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
* 获取估值分录数据 * 获取估值分录数据
* @param accrualDate 计提日 * @param accrualDate 计提日
* @param buyDate 购买日期 * @param buyDate 购买日期
* @param expireDate 到期日
* @param buyAmount 购买金额 * @param buyAmount 购买金额
* @param days 天数(计提日-计息日)
* @param basisDays 计息基准天数
* @param id 表单id * @param id 表单id
*/ */
private void valuationEntry(Date accrualDate, Date buyDate, BigDecimal buyAmount, Long id, DynamicObject row) { private void valuationEntry(Date accrualDate, Date buyDate,Date expireDate,Date valueDate, BigDecimal buyAmount,BigDecimal days,BigDecimal basisDays, Long id, DynamicObject row) {
// 初始化所有变量 // 初始化所有变量
BigDecimal buyCopies = BigDecimal.ZERO; BigDecimal buyCopies = BigDecimal.ZERO;
BigDecimal monthIop = BigDecimal.ZERO; BigDecimal monthIop = BigDecimal.ZERO;
@ -173,7 +199,6 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
BigDecimal monthAnnualizedRate = BigDecimal.ZERO; BigDecimal monthAnnualizedRate = BigDecimal.ZERO;
BigDecimal yearAmount = BigDecimal.ZERO; BigDecimal yearAmount = BigDecimal.ZERO;
BigDecimal yearAnnualizedRate = BigDecimal.ZERO; BigDecimal yearAnnualizedRate = BigDecimal.ZERO;
BigDecimal yearStartAmount = buyAmount;
DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(id, "cim_finsubscribe"); DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(id, "cim_finsubscribe");
if (dynamicObject != null) { if (dynamicObject != null) {
@ -187,60 +212,95 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
DynamicObject yearStartRecord = null; DynamicObject yearStartRecord = null;
long minDiff = Long.MAX_VALUE; long minDiff = Long.MAX_VALUE;
// 获取日期信息 // 获取计提日期相关信息
Calendar accrualCal = Calendar.getInstance(); Calendar accrualCal = Calendar.getInstance();
accrualCal.setTime(accrualDate); accrualCal.setTime(accrualDate);
int accrualYear = accrualCal.get(Calendar.YEAR); int accrualYear = accrualCal.get(Calendar.YEAR);
int accrualMonth = accrualCal.get(Calendar.MONTH); int accrualMonth = accrualCal.get(Calendar.MONTH);
//与年初相隔天数
int daysFromJan1 = accrualCal.get(Calendar.DAY_OF_YEAR) - 1;
//获取购买日相关信息
Calendar buyCal = Calendar.getInstance(); Calendar buyCal = Calendar.getInstance();
buyCal.setTime(buyDate); buyCal.setTime(buyDate);
int buyYear = buyCal.get(Calendar.YEAR); int buyYear = buyCal.get(Calendar.YEAR);
int buyMonth = buyCal.get(Calendar.MONTH); int buyMonth = buyCal.get(Calendar.MONTH);
// 遍历估值记录 // 遍历估值记录
for (DynamicObject object : dynamicObjectCollection) { for (DynamicObject object : dynamicObjectCollection) {
Date valuationdate = object.getDate("e_valuationdate"); Date valuationDate = object.getDate("e_valuationdate");
if (valuationdate == null) continue; if (valuationDate == null) continue;
Date redeemDate = object.getDate("shjh_shrq"); // 获取赎回日期
Calendar valCal = Calendar.getInstance(); Calendar valCal = Calendar.getInstance();
valCal.setTime(valuationdate); valCal.setTime(valuationDate);
int valYear = valCal.get(Calendar.YEAR); int valYear = valCal.get(Calendar.YEAR);
int valMonth = valCal.get(Calendar.MONTH); int valMonth = valCal.get(Calendar.MONTH);
// 1. 寻找离计提日最近的份额记录 // 1. 寻找离计提日最近的份额记录相同日期取赎回日期最大的
long diff = Math.abs(valuationdate.getTime() - accrualDate.getTime()); long diff = Math.abs(valuationDate.getTime() - accrualDate.getTime());
if (diff < minDiff) { if (diff < minDiff) {
minDiff = diff; minDiff = diff;
closestRecord = object; closestRecord = object;
} else if (diff == minDiff && closestRecord != null) {
// 相同估值日期时比较赎回日期
Date currentRedeemDate = closestRecord.getDate("shjh_shrq");
if (redeemDate != null && (currentRedeemDate == null || redeemDate.after(currentRedeemDate))) {
closestRecord = object;
}
} }
// 2. 寻找本月最后一次估值记录 // 2. 寻找本月最后一次估值记录相同日期取赎回日期最大的
if (!valuationdate.after(accrualDate)) { if (!valuationDate.after(accrualDate)) {
if (latestIopRecord == null || valuationdate.after(latestIopRecord.getDate("e_valuationdate"))) { if (latestIopRecord == null) {
latestIopRecord = object;
} else {
int dateCompare = valuationDate.compareTo(latestIopRecord.getDate("e_valuationdate"));
if (dateCompare > 0 ||
(dateCompare == 0 && isRedeemDateLater(redeemDate, latestIopRecord.getDate("shjh_shrq")))) {
latestIopRecord = object; latestIopRecord = object;
} }
} }
}
// 3. 寻找上月最后一次估值记录 // 3. 寻找上月最后一次估值记录相同日期取赎回日期最大的
if ((valYear == accrualYear && valMonth == accrualMonth - 1) || if ((valYear == accrualYear && valMonth == accrualMonth - 1) ||
(accrualMonth == 0 && valYear == accrualYear - 1 && valMonth == 11)) { (accrualMonth == 0 && valYear == accrualYear - 1 && valMonth == 11)) {
if (lastMonthRecord == null || valuationdate.after(lastMonthRecord.getDate("e_valuationdate"))) { if (lastMonthRecord == null) {
lastMonthRecord = object;
} else {
int dateCompare = valuationDate.compareTo(lastMonthRecord.getDate("e_valuationdate"));
if (dateCompare > 0 ||
(dateCompare == 0 && isRedeemDateLater(redeemDate, lastMonthRecord.getDate("shjh_shrq")))) {
lastMonthRecord = object; lastMonthRecord = object;
} }
} }
}
// 4. 寻找上一年最后一次估值记录 // 4. 寻找上一年最后一次估值记录相同日期取赎回日期最大的
if (valYear == accrualYear - 1) { if (valYear == accrualYear - 1) {
if (lastYearRecord == null || valuationdate.after(lastYearRecord.getDate("e_valuationdate"))) { if (lastYearRecord == null) {
lastYearRecord = object;
} else {
int dateCompare = valuationDate.compareTo(lastYearRecord.getDate("e_valuationdate"));
if (dateCompare > 0 ||
(dateCompare == 0 && isRedeemDateLater(redeemDate, lastYearRecord.getDate("shjh_shrq")))) {
lastYearRecord = object; lastYearRecord = object;
} }
} }
}
// 5. 寻找本年第一个估值记录 // 5. 寻找本年第一个估值记录相同日期取赎回日期最大的
if (valYear == accrualYear) { if (valYear == accrualYear) {
if (yearStartRecord == null || valuationdate.before(yearStartRecord.getDate("e_valuationdate"))) { if (yearStartRecord == null) {
yearStartRecord = object; yearStartRecord = object;
} else {
int dateCompare = valuationDate.compareTo(yearStartRecord.getDate("e_valuationdate"));
if (dateCompare < 0 ||
(dateCompare == 0 && isRedeemDateLater(redeemDate, yearStartRecord.getDate("shjh_shrq")))) {
yearStartRecord = object;
}
} }
} }
} }
@ -257,10 +317,28 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
} }
// 计算本月收益 // 计算本月收益
// 计提日期向上最近一次市值-上月最后一次的市值表体若没有置0
// 新增逻辑计息日<计提日<=到期日所在月月底才计算本月收益和收益率
if (latestIopRecord != null) { if (latestIopRecord != null) {
BigDecimal currentMarketValue = latestIopRecord.getBigDecimal("e_iopv").multiply(buyCopies); BigDecimal currentMarketValue = latestIopRecord.getBigDecimal("e_iopv").multiply(buyCopies);
// 新增检查计息日<计提日<=到期日所在月月底
boolean isValidPeriod = true;
if (expireDate != null) {
// 获取到期日所在月的最后一天
Calendar expireCal = Calendar.getInstance();
expireCal.setTime(expireDate);
expireCal.set(Calendar.DAY_OF_MONTH, expireCal.getActualMaximum(Calendar.DAY_OF_MONTH));
Date monthEndDate = expireCal.getTime();
// 验证计息日 < 计提日 <= 到期日所在月月底
isValidPeriod = (valueDate.before(accrualDate) || valueDate.equals(accrualDate))
&& (accrualDate.before(monthEndDate) || accrualDate.equals(monthEndDate));
}
if (isValidPeriod) {
// 只有当上月记录存在时才计算本月收益 // 只有当上月记录存在时才计算本月收益
// 计提日期若与购买日期不同月取不到上月最后一次单元格为0
if (lastMonthRecord != null) { if (lastMonthRecord != null) {
BigDecimal lastMonthMarketValue = lastMonthRecord.getBigDecimal("e_iopv") BigDecimal lastMonthMarketValue = lastMonthRecord.getBigDecimal("e_iopv")
.multiply(lastMonthRecord.getBigDecimal("e_surpcopies")); .multiply(lastMonthRecord.getBigDecimal("e_surpcopies"));
@ -268,20 +346,26 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
// 计算当月年化收益率 // 计算当月年化收益率
// 本月收益/购买金额*100*12
if (lastMonthMarketValue.compareTo(BigDecimal.ZERO) != 0) { if (lastMonthMarketValue.compareTo(BigDecimal.ZERO) != 0) {
monthAnnualizedRate = monthAmount
monthAnnualizedRate = monthAmount.divide(buyAmount).multiply(new BigDecimal(1200)).setScale(2, RoundingMode.HALF_UP); .divide(buyAmount, 6, RoundingMode.HALF_UP)
.multiply(new BigDecimal(1200))
.setScale(2, RoundingMode.HALF_UP);
} }
} else if (accrualYear == buyYear && accrualMonth == buyMonth) { } else if (accrualYear == buyYear && accrualMonth == buyMonth) {
// 特殊处理计提月与购买月相同时使用购买金额作为上月市值 // 特殊处理计提月与购买月相同时使用购买金额作为上月市值
BigDecimal lastMonthMarketValue = buyAmount; // 如果计提日期和购买日同月"上月最后一次的市值行"取购买金额
monthAmount = currentMarketValue.subtract(lastMonthMarketValue.multiply(new BigDecimal(1000))) monthAmount = currentMarketValue.subtract(buyAmount.multiply(new BigDecimal(1000)))
.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
if (lastMonthMarketValue.compareTo(BigDecimal.ZERO) != 0) { if (buyAmount.compareTo(BigDecimal.ZERO) != 0) {
//本月收益/购买金额*100*12
monthAnnualizedRate = monthAmount.divide(buyAmount).multiply(new BigDecimal(1200)).setScale(2, RoundingMode.HALF_UP); monthAnnualizedRate = monthAmount
.divide(buyAmount, 6, RoundingMode.HALF_UP)
.multiply(new BigDecimal(1200))
.setScale(2, RoundingMode.HALF_UP);
}
} }
} }
} }
@ -294,47 +378,38 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
if (lastYearRecord != null) { if (lastYearRecord != null) {
BigDecimal lastYearMarketValue = lastYearRecord.getBigDecimal("e_iopv") BigDecimal lastYearMarketValue = lastYearRecord.getBigDecimal("e_iopv")
.multiply(lastYearRecord.getBigDecimal("e_surpcopies")); .multiply(lastYearRecord.getBigDecimal("e_surpcopies"));
yearAmount = currentMarketValue.subtract(lastYearMarketValue) yearAmount = currentMarketValue.subtract(lastYearMarketValue)
.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
// // 计算本年累计年化收益率 //本年累计年化收益率=本年累计总收益额/金额/(计提日期到-年初日期*计息基准天数
// if (yearStartRecord != null) { if (buyAmount.compareTo(BigDecimal.ZERO) != 0 && BigDecimal.valueOf(daysFromJan1).compareTo(BigDecimal.ZERO) != 0 ) {
// yearStartAmount = yearStartRecord.getBigDecimal("e_iopv") yearAnnualizedRate = yearAmount
// .multiply(yearStartRecord.getBigDecimal("e_surpcopies")); .divide(buyAmount, 6, RoundingMode.HALF_UP)
// } .divide(BigDecimal.valueOf(daysFromJan1), 6, RoundingMode.HALF_UP)
.multiply(basisDays)
if (lastYearMarketValue.compareTo(BigDecimal.ZERO) != 0) {
int monthCount = accrualMonth + 1;
yearAnnualizedRate = yearAmount.multiply(new BigDecimal(1000))
.divide(lastYearMarketValue, 6, RoundingMode.HALF_UP)
.divide(new BigDecimal(monthCount), 6, RoundingMode.HALF_UP)
.multiply(new BigDecimal(12))
.multiply(new BigDecimal(100))
.setScale(2, RoundingMode.HALF_UP); .setScale(2, RoundingMode.HALF_UP);
} }
} else if (accrualYear == buyYear) { } else if (accrualYear == buyYear) {
// 特殊处理计提年与购买年相同时使用购买金额作为上年市值 // 特殊处理计提年与购买年相同时:本年累计年化收益率=本年累计总收益额/金额/天数*计息基准天数
BigDecimal lastYearMarketValue = buyAmount; // 天数(计提日期到-计息日
if (lastYearMarketValue.compareTo(BigDecimal.ZERO) != 0) { if (buyAmount.compareTo(BigDecimal.ZERO) != 0 ) {
yearAmount = currentMarketValue.subtract(lastYearMarketValue.multiply(new BigDecimal(1000))) yearAmount = currentMarketValue.subtract(buyAmount.multiply(new BigDecimal(1000)))
.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
int monthCount = accrualMonth -buyMonth; if (days.compareTo(BigDecimal.ZERO) !=0 ){
if (monthCount==0){
monthCount = 1;
}
yearAnnualizedRate = yearAmount yearAnnualizedRate = yearAmount
.divide(lastYearMarketValue, 6, RoundingMode.HALF_UP) .divide(buyAmount, 6, RoundingMode.HALF_UP)
.divide(new BigDecimal(monthCount), 6, RoundingMode.HALF_UP) .divide(days, 6, RoundingMode.HALF_UP)
.multiply(new BigDecimal(12)) .multiply(basisDays)
.multiply(new BigDecimal(100))
.setScale(2, RoundingMode.HALF_UP); .setScale(2, RoundingMode.HALF_UP);
} }
} }
} }
} }
} }
}
// 设置结果 // 设置结果
row.set(REPORT_FIELDS[5], buyCopies); row.set(REPORT_FIELDS[5], buyCopies);
@ -347,18 +422,51 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
} }
/** /**
* 计算天数 = 计提日 - 计息日 * 计算天数规则
* 1. 计提日 <= 到期日天数 = 计提日 - 计息日
* 2. 计提日 > 到期日天数 = 到期日 - 计息日
* @param valueDate 计息日 * @param valueDate 计息日
* @param expireDate 到期日
* @param accrualDate 计提日 * @param accrualDate 计提日
* @param row 表格 * @param row 表格行数据
* @return 计算得到的天数
*/ */
private void countDays(Date valueDate,Date accrualDate,DynamicObject row){ private BigDecimal countDays(Date valueDate, Date expireDate, Date accrualDate, DynamicObject row) {
if (valueDate != null) { if (expireDate==null){
long days = (accrualDate.getTime() - valueDate.getTime()) / (1000 * 60 * 60 * 24); expireDate=accrualDate;
row.set(DYNAMICS_FIELDS[2], new BigDecimal(days)); }
} else { BigDecimal days;
// 检查必要参数是否为空
if (valueDate == null || accrualDate == null) {
row.set(DYNAMICS_FIELDS[2], BigDecimal.ZERO);
return BigDecimal.ZERO;
}
// 确定结束日期比较计提日和到期日
Date endDate = accrualDate;
if (accrualDate.after(expireDate) || expireDate==accrualDate) {
endDate = expireDate;
}
// 计算天数差毫秒转换为天
long diffMillis = endDate.getTime() - valueDate.getTime();
long diffDays = diffMillis / (1000 * 60 * 60 * 24);
// 确保天数不为负
diffDays = Math.max(diffDays, 0);
days = new BigDecimal(diffDays);
// 验证计息日 <= 计提日 <= 到期日
boolean isValidPeriod = !valueDate.after(accrualDate) && !accrualDate.after(expireDate);
if (isValidPeriod){
row.set(DYNAMICS_FIELDS[2], days);
}else {
row.set(DYNAMICS_FIELDS[2], BigDecimal.ZERO); row.set(DYNAMICS_FIELDS[2], BigDecimal.ZERO);
} }
return days;
} }
private String countProductTerm(Date valueDate, Date expireDate, Date accrualDate, DynamicObject row) { private String countProductTerm(Date valueDate, Date expireDate, Date accrualDate, DynamicObject row) {
@ -419,6 +527,14 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
return day; return day;
} }
private BigDecimal computeBasisDays(String basis){
BigDecimal basisDay= BigDecimal.valueOf(365);
if (basis.contains("360")){
basisDay=BigDecimal.valueOf(360);
}
return basisDay;
}
/** /**
* 预计收益 = 产品期限 * 金额(千元) * 预计业绩比较基准 / 365 * 预计收益 = 产品期限 * 金额(千元) * 预计业绩比较基准 / 365
* @param expectedRate 预计业绩比较基准% * @param expectedRate 预计业绩比较基准%
@ -426,11 +542,8 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
* @param amount 投资金额 * @param amount 投资金额
* @param row 表格 * @param row 表格
*/ */
private BigDecimal countProRevenue(BigDecimal expectedRate,String day,BigDecimal amount,DynamicObject row,String basis) { private BigDecimal countProRevenue(BigDecimal expectedRate,String day,BigDecimal amount,DynamicObject row,BigDecimal basisDay) {
BigDecimal basisDay= BigDecimal.valueOf(365);
if (basis.contains("360")){
basisDay=BigDecimal.valueOf(360);
}
BigDecimal projectRevenue = BigDecimal.ZERO; BigDecimal projectRevenue = BigDecimal.ZERO;
if (expectedRate != null) { if (expectedRate != null) {
projectRevenue = new BigDecimal(day).multiply(amount.divide(new BigDecimal(1000), 10, RoundingMode.HALF_UP)) projectRevenue = new BigDecimal(day).multiply(amount.divide(new BigDecimal(1000), 10, RoundingMode.HALF_UP))
@ -450,15 +563,19 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
* @param startBuyCopies 购买份额初始份额 * @param startBuyCopies 购买份额初始份额
* @return 计算后的收益金额保留2位小数 * @return 计算后的收益金额保留2位小数
*/ */
private BigDecimal countRevenueAmt( private BigDecimal countRevenueAmt(Date valueDate, Date expireDate, Date accrualDate,
BigDecimal buyCopies, BigDecimal buyCopies,
BigDecimal monthNetWorth, BigDecimal monthNetWorth,
BigDecimal netWorth, BigDecimal netWorth,
DynamicObject row, DynamicObject row,
BigDecimal startBuyCopies BigDecimal startBuyCopies
) { ) {
if (expireDate==null){
expireDate=accrualDate;
}
BigDecimal revenue = BigDecimal.ZERO; BigDecimal revenue = BigDecimal.ZERO;
// 检查所有参数是否非空 // 检查所有参数是否非空
if (buyCopies != null && monthNetWorth != null && netWorth != null && startBuyCopies != null) { if (buyCopies != null && monthNetWorth != null && netWorth != null && startBuyCopies != null) {
// 计算(持有份额 * 月末单位净值 - 购买份额 * 购买时单位净值) / 1000 // 计算(持有份额 * 月末单位净值 - 购买份额 * 购买时单位净值) / 1000
@ -467,12 +584,26 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu
.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
// 设置到表格行 // 设置到表格行
boolean isValidPeriod = !valueDate.after(accrualDate) && !accrualDate.after(expireDate);
if (isValidPeriod){
row.set(DYNAMICS_FIELDS[3], revenue); row.set(DYNAMICS_FIELDS[3], revenue);
}else {
row.set(DYNAMICS_FIELDS[3], BigDecimal.ZERO);
return BigDecimal.ZERO;
}
} }
return revenue; return revenue;
} }
// 辅助方法比较赎回日期
private boolean isRedeemDateLater(Date newRedeemDate, Date existingRedeemDate) {
if (newRedeemDate == null) return false;
if (existingRedeemDate == null) return true;
return newRedeemDate.after(existingRedeemDate);
}
/** /**
* 本月收益计算严格按生效期间计算 * 本月收益计算严格按生效期间计算
* @param monthNetWorth 月末单位净值 * @param monthNetWorth 月末单位净值

View File

@ -2,6 +2,7 @@ package shjh.jhzj7.fi.fi.plugin.report;
import kd.bos.algo.DataSet; import kd.bos.algo.DataSet;
import kd.bos.dataentity.entity.DynamicObject; import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.entity.report.AbstractReportColumn; import kd.bos.entity.report.AbstractReportColumn;
import kd.bos.entity.report.AbstractReportListDataPlugin; import kd.bos.entity.report.AbstractReportListDataPlugin;
import kd.bos.entity.report.FilterItemInfo; import kd.bos.entity.report.FilterItemInfo;
@ -67,6 +68,16 @@ public class FinancialListReport extends AbstractReportListDataPlugin implements
null null
); );
// 3. 获取过滤日期并提取年份
Date filterDate = param.getFilter().getDate("shjh_filterdate");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
String filterYear = sdf.format(filterDate);
// 4. 应用过滤条件
mainDataSet = mainDataSet.filter(
"shjh_expiredate IS NULL OR " + // 保留到期日为空的记录
"year(shjh_expiredate) >= " + filterYear // 计提日年份 <= 到期日年份
);
// 3. 查询理财收益预提数据 // 3. 查询理财收益预提数据
// DataSet addDataSet = QueryServiceHelper.queryDataSet( // DataSet addDataSet = QueryServiceHelper.queryDataSet(
// this.getClass().getName() + "1", // this.getClass().getName() + "1",
@ -86,23 +97,18 @@ public class FinancialListReport extends AbstractReportListDataPlugin implements
*/ */
private List<QFilter> buildFilters(List<FilterItemInfo> filterItems) { private List<QFilter> buildFilters(List<FilterItemInfo> filterItems) {
List<QFilter> filters = new ArrayList<>(); List<QFilter> filters = new ArrayList<>();
List<Long> bankNameIds =new ArrayList<>();
List<Long> productTypeIds =new ArrayList<>();
for (FilterItemInfo filterItem : filterItems) { for (FilterItemInfo filterItem : filterItems) {
Object value = filterItem.getValue(); Object value = filterItem.getValue();
Date date = filterItem.getDate(); Date date = filterItem.getDate();
switch (filterItem.getPropName()) { switch (filterItem.getPropName()) {
case FILTER_BANK_NAME: // 银行筛选 case FILTER_BANK_NAME: // 银行筛选
if (value != null) { this.getMultipleFilter(filterItem, bankNameIds);
Long bankId = (Long) ((DynamicObject) value).getPkValue();
filters.add(new QFilter("finorginfo", QCP.equals, bankId));
}
break; break;
case FILTER_PRODUCT_NAME: // 产品筛选 case FILTER_PRODUCT_NAME: // 产品筛选
if (value != null) { this.getMultipleFilter(filterItem, productTypeIds);
Long productId = (Long) ((DynamicObject) value).getPkValue();
filters.add(new QFilter("product", QCP.equals, productId));
}
break; break;
case FILTER_BUY_DATE: // 购买日筛选 case FILTER_BUY_DATE: // 购买日筛选
if (date != null) { if (date != null) {
@ -120,6 +126,13 @@ public class FinancialListReport extends AbstractReportListDataPlugin implements
} }
break; break;
} }
if (bankNameIds.size()!=0){
filters.add(new QFilter("finorginfo", QCP.in,bankNameIds));
}
if (bankNameIds.size()!=0){
filters.add(new QFilter("investvarieties", QCP.in,productTypeIds));
}
} }
return filters; return filters;
} }
@ -173,6 +186,22 @@ public class FinancialListReport extends AbstractReportListDataPlugin implements
} }
} }
/**
* 获取报表多选基础资料过滤数据
* @param filterItem
* @param bankNameIds
* @return
*/
private List<Long> getMultipleFilter(FilterItemInfo filterItem,List<Long> bankNameIds){
DynamicObjectCollection value = (DynamicObjectCollection) filterItem.getValue();
if (value!=null && value.size()!=0){
for (DynamicObject dynamicObject : value) {
Long pkValue = (Long) dynamicObject.getPkValue();
bankNameIds.add(pkValue);
}
}
return bankNameIds;
}
} }

View File

@ -77,7 +77,7 @@ public class ReportUtils {
totalRow.set(targetField, totals[i]); totalRow.set(targetField, totals[i]);
} }
rowData.add(totalRow); rowData.add(0,totalRow);
} }
/** /**
@ -122,6 +122,50 @@ public class ReportUtils {
} }
} }
/**
* 对往年过期数据处理相对计提日期而言
* 列表插件已有该过滤-该方法针对提前已结清修改了到期日的数据
* @param rowData 数据集合
* @param keyWord1 到期日
* @param keyWord2 计提日
*/
public static void removeRowData(DynamicObjectCollection rowData,String keyWord1,String keyWord2) {
List<DynamicObject> rowsToRemove = new ArrayList<>();
Calendar cal = Calendar.getInstance();
for (DynamicObject row : rowData) {
Date expireDate = row.getDate(keyWord1); // 到期日
Date accrualDate = row.getDate(keyWord2); // 计提日
// 条件1到期日为null
if (expireDate == null) {
rowsToRemove.add(row);
continue;
}
// 条件2计提日不为null且到期日所在年 < 计提日所在年
if (accrualDate != null) {
cal.setTime(expireDate);
int expireYear = cal.get(Calendar.YEAR);
cal.setTime(accrualDate);
int accrualYear = cal.get(Calendar.YEAR);
if (expireYear < accrualYear) {
rowsToRemove.add(row);
}
}
}
// 移除重复的小计行
if (!rowsToRemove.isEmpty()) {
rowData.removeAll(rowsToRemove);
}
}
// 辅助方法获取某个月的第一天 // 辅助方法获取某个月的第一天
public static Date getFirstDayOfMonth(Date date) { public static Date getFirstDayOfMonth(Date date) {
Calendar cal = Calendar.getInstance(); Calendar cal = Calendar.getInstance();