diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java index 3b123c3..42906f2 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java @@ -74,21 +74,52 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu BigDecimal sumProvisionEarnings =BigDecimal.ZERO;//收益计提汇总 BigDecimal sumMonthEarnings =BigDecimal.ZERO;//本月收益汇总 BigDecimal sumYearEarnings =BigDecimal.ZERO;//本年收益汇总 + BigDecimal sumActualEarnings =BigDecimal.ZERO;//实际收益汇总 + while (iterator.hasNext()) { DynamicObject row = iterator.next(); - // 基础字段获取(添加null检查) + //1.金额(千元)设置 BigDecimal amount = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[4]); // 原始金额(元) BigDecimal buyAmount = amount.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);//购买金额(千元) row.set(REPORT_FIELDS[4],buyAmount); + Date buyDate = row.getDate(REPORT_FIELDS[7]); // 购买日 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]); // 预计业绩比较基准(%) 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]); - 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 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]); // 购买份额 - // 1. 设置计提日 - row.set(DYNAMICS_FIELDS[1], accrualDate); - // 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); + // 12. 收益计提 = (持有份额 *月末单位净值 - 购买份额*购买时单位净值) / 1000 + BigDecimal revenueAmt = countRevenueAmt(valueDate,expireDate2, accrualDate,buyCopies, monthNetWorth, netWorth, row,startBuyCopies); sumProvisionEarnings=sumProvisionEarnings.add(revenueAmt); + // 本月收益计算累计 - //BigDecimal monthRevenue = countMonthRevenue(monthNetWorth, netWorth, buyCopies, valueDate, accrualDate, expireDate, row); BigDecimal monthRevenue = ReportUtils.getBigDecimalValue(row, DYNAMICS_FIELDS[4]); 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]); sumYearEarnings=sumYearEarnings.add(yearRevenue); //实际总收益率=实际收益/金额 BigDecimal actualEarnings = ReportUtils.getBigDecimalValue(row, DYNAMICS_FIELDS[8]); row.set(DYNAMICS_FIELDS[9],actualEarnings.divide(buyAmount,2, RoundingMode.HALF_UP)); - + sumActualEarnings=sumActualEarnings.add(actualEarnings); //小计行合计 // 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.removeRowData(rowData,REPORT_FIELDS[9],DYNAMICS_FIELDS[1]); //添加合计 // 需要配置求和的字段映射(目标字段,来源字段) List 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[4], DYNAMICS_FIELDS[4]}); // shjh_monthrevenueamt 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); @@ -161,10 +184,13 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu * 获取估值分录数据 * @param accrualDate 计提日 * @param buyDate 购买日期 + * @param expireDate 到期日 * @param buyAmount 购买金额 + * @param days 天数(计提日-计息日) + * @param basisDays 计息基准天数 * @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 monthIop = BigDecimal.ZERO; @@ -173,7 +199,6 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu BigDecimal monthAnnualizedRate = BigDecimal.ZERO; BigDecimal yearAmount = BigDecimal.ZERO; BigDecimal yearAnnualizedRate = BigDecimal.ZERO; - BigDecimal yearStartAmount = buyAmount; DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(id, "cim_finsubscribe"); if (dynamicObject != null) { @@ -187,60 +212,95 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu DynamicObject yearStartRecord = null; long minDiff = Long.MAX_VALUE; - // 获取日期信息 + // 获取计提日期相关信息 Calendar accrualCal = Calendar.getInstance(); accrualCal.setTime(accrualDate); int accrualYear = accrualCal.get(Calendar.YEAR); int accrualMonth = accrualCal.get(Calendar.MONTH); + //与年初相隔天数 + int daysFromJan1 = accrualCal.get(Calendar.DAY_OF_YEAR) - 1; + //获取购买日相关信息 Calendar buyCal = Calendar.getInstance(); buyCal.setTime(buyDate); int buyYear = buyCal.get(Calendar.YEAR); int buyMonth = buyCal.get(Calendar.MONTH); + // 遍历估值记录 for (DynamicObject object : dynamicObjectCollection) { - Date valuationdate = object.getDate("e_valuationdate"); - if (valuationdate == null) continue; + Date valuationDate = object.getDate("e_valuationdate"); + if (valuationDate == null) continue; + Date redeemDate = object.getDate("shjh_shrq"); // 获取赎回日期 Calendar valCal = Calendar.getInstance(); - valCal.setTime(valuationdate); + valCal.setTime(valuationDate); int valYear = valCal.get(Calendar.YEAR); int valMonth = valCal.get(Calendar.MONTH); - // 1. 寻找离计提日最近的份额记录 - long diff = Math.abs(valuationdate.getTime() - accrualDate.getTime()); + // 1. 寻找离计提日最近的份额记录(相同日期取赎回日期最大的) + long diff = Math.abs(valuationDate.getTime() - accrualDate.getTime()); if (diff < minDiff) { minDiff = diff; closestRecord = object; - } - - // 2. 寻找本月最后一次估值记录 - if (!valuationdate.after(accrualDate)) { - if (latestIopRecord == null || valuationdate.after(latestIopRecord.getDate("e_valuationdate"))) { - latestIopRecord = object; + } else if (diff == minDiff && closestRecord != null) { + // 相同估值日期时,比较赎回日期 + Date currentRedeemDate = closestRecord.getDate("shjh_shrq"); + if (redeemDate != null && (currentRedeemDate == null || redeemDate.after(currentRedeemDate))) { + closestRecord = object; } } - // 3. 寻找上月最后一次估值记录 + // 2. 寻找本月最后一次估值记录(相同日期取赎回日期最大的) + if (!valuationDate.after(accrualDate)) { + 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; + } + } + } + + // 3. 寻找上月最后一次估值记录(相同日期取赎回日期最大的) if ((valYear == accrualYear && valMonth == accrualMonth - 1) || (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; + } } } - // 4. 寻找上一年最后一次估值记录 + // 4. 寻找上一年最后一次估值记录(相同日期取赎回日期最大的) 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; + } } } - // 5. 寻找本年第一个估值记录 + // 5. 寻找本年第一个估值记录(相同日期取赎回日期最大的) if (valYear == accrualYear) { - if (yearStartRecord == null || valuationdate.before(yearStartRecord.getDate("e_valuationdate"))) { + if (yearStartRecord == null) { 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,31 +317,55 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu } // 计算本月收益 + // 计提日期向上最近一次市值-上月最后一次的市值(表体若没有,置0) + // 新增逻辑:计息日<计提日<=到期日所在月月底才计算本月收益和收益率 if (latestIopRecord != null) { BigDecimal currentMarketValue = latestIopRecord.getBigDecimal("e_iopv").multiply(buyCopies); - // 只有当上月记录存在时才计算本月收益 - if (lastMonthRecord != null) { - BigDecimal lastMonthMarketValue = lastMonthRecord.getBigDecimal("e_iopv") - .multiply(lastMonthRecord.getBigDecimal("e_surpcopies")); - monthAmount = currentMarketValue.subtract(lastMonthMarketValue) - .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); + // 新增:检查计息日<计提日<=到期日所在月月底 + 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(); - // 计算当月年化收益率 - if (lastMonthMarketValue.compareTo(BigDecimal.ZERO) != 0) { + // 验证计息日 < 计提日 <= 到期日所在月月底 + isValidPeriod = (valueDate.before(accrualDate) || valueDate.equals(accrualDate)) + && (accrualDate.before(monthEndDate) || accrualDate.equals(monthEndDate)); + } - monthAnnualizedRate = monthAmount.divide(buyAmount).multiply(new BigDecimal(1200)).setScale(2, RoundingMode.HALF_UP); - } - } else if (accrualYear == buyYear && accrualMonth == buyMonth) { - // 特殊处理:计提月与购买月相同时,使用购买金额作为上月市值 - BigDecimal lastMonthMarketValue = buyAmount; - monthAmount = currentMarketValue.subtract(lastMonthMarketValue.multiply(new BigDecimal(1000))) - .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); + if (isValidPeriod) { + // 只有当上月记录存在时才计算本月收益 + // ①计提日期若与购买日期不同月,取不到上月最后一次,单元格为0 + if (lastMonthRecord != null) { + BigDecimal lastMonthMarketValue = lastMonthRecord.getBigDecimal("e_iopv") + .multiply(lastMonthRecord.getBigDecimal("e_surpcopies")); + monthAmount = currentMarketValue.subtract(lastMonthMarketValue) + .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); - if (lastMonthMarketValue.compareTo(BigDecimal.ZERO) != 0) { - - monthAnnualizedRate = monthAmount.divide(buyAmount).multiply(new BigDecimal(1200)).setScale(2, RoundingMode.HALF_UP); + // 计算当月年化收益率 + // 本月收益/购买金额*100*12 + if (lastMonthMarketValue.compareTo(BigDecimal.ZERO) != 0) { + monthAnnualizedRate = monthAmount + .divide(buyAmount, 6, RoundingMode.HALF_UP) + .multiply(new BigDecimal(1200)) + .setScale(2, RoundingMode.HALF_UP); + } + } else if (accrualYear == buyYear && accrualMonth == buyMonth) { + // 特殊处理:计提月与购买月相同时,使用购买金额作为上月市值 + // ②如果计提日期和购买日同月,"上月最后一次的市值行"取购买金额 + monthAmount = currentMarketValue.subtract(buyAmount.multiply(new BigDecimal(1000))) + .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); + if (buyAmount.compareTo(BigDecimal.ZERO) != 0) { + //本月收益/购买金额*100*12 + monthAnnualizedRate = monthAmount + .divide(buyAmount, 6, RoundingMode.HALF_UP) + .multiply(new BigDecimal(1200)) + .setScale(2, RoundingMode.HALF_UP); + } } } } @@ -294,42 +378,33 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu if (lastYearRecord != null) { BigDecimal lastYearMarketValue = lastYearRecord.getBigDecimal("e_iopv") .multiply(lastYearRecord.getBigDecimal("e_surpcopies")); + yearAmount = currentMarketValue.subtract(lastYearMarketValue) .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); -// // 计算本年累计年化收益率 -// if (yearStartRecord != null) { -// yearStartAmount = yearStartRecord.getBigDecimal("e_iopv") -// .multiply(yearStartRecord.getBigDecimal("e_surpcopies")); -// } - - 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)) + //本年累计年化收益率=(本年累计总收益额/金额)/(计提日期到-年初日期)*计息基准天数 + if (buyAmount.compareTo(BigDecimal.ZERO) != 0 && BigDecimal.valueOf(daysFromJan1).compareTo(BigDecimal.ZERO) != 0 ) { + yearAnnualizedRate = yearAmount + .divide(buyAmount, 6, RoundingMode.HALF_UP) + .divide(BigDecimal.valueOf(daysFromJan1), 6, RoundingMode.HALF_UP) + .multiply(basisDays) .setScale(2, RoundingMode.HALF_UP); } } else if (accrualYear == buyYear) { - // 特殊处理:计提年与购买年相同时,使用购买金额作为上年市值 - BigDecimal lastYearMarketValue = buyAmount; + // 特殊处理:计提年与购买年相同时:本年累计年化收益率=(本年累计总收益额/金额)/天数*计息基准天数 + // 天数:(计提日期到-计息日) - if (lastYearMarketValue.compareTo(BigDecimal.ZERO) != 0) { - yearAmount = currentMarketValue.subtract(lastYearMarketValue.multiply(new BigDecimal(1000))) + if (buyAmount.compareTo(BigDecimal.ZERO) != 0 ) { + yearAmount = currentMarketValue.subtract(buyAmount.multiply(new BigDecimal(1000))) .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); - int monthCount = accrualMonth -buyMonth; - if (monthCount==0){ - monthCount = 1; + if (days.compareTo(BigDecimal.ZERO) !=0 ){ + yearAnnualizedRate = yearAmount + .divide(buyAmount, 6, RoundingMode.HALF_UP) + .divide(days, 6, RoundingMode.HALF_UP) + .multiply(basisDays) + .setScale(2, RoundingMode.HALF_UP); } - yearAnnualizedRate = yearAmount - .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); } } } @@ -347,18 +422,51 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu } /** - * 计算天数 = 计提日 - 计息日 + * 计算天数规则: + * 1. 计提日 <= 到期日:天数 = 计提日 - 计息日 + * 2. 计提日 > 到期日:天数 = 到期日 - 计息日 * @param valueDate 计息日 + * @param expireDate 到期日 * @param accrualDate 计提日 - * @param row 表格 + * @param row 表格行数据 + * @return 计算得到的天数 */ - private void countDays(Date valueDate,Date accrualDate,DynamicObject row){ - if (valueDate != null) { - long days = (accrualDate.getTime() - valueDate.getTime()) / (1000 * 60 * 60 * 24); - row.set(DYNAMICS_FIELDS[2], new BigDecimal(days)); - } else { + private BigDecimal countDays(Date valueDate, Date expireDate, Date accrualDate, DynamicObject row) { + if (expireDate==null){ + expireDate=accrualDate; + } + 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); } + + + return days; } private String countProductTerm(Date valueDate, Date expireDate, Date accrualDate, DynamicObject row) { @@ -419,6 +527,14 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu return day; } + private BigDecimal computeBasisDays(String basis){ + BigDecimal basisDay= BigDecimal.valueOf(365); + if (basis.contains("360")){ + basisDay=BigDecimal.valueOf(360); + } + return basisDay; + } + /** * 预计收益 = 产品期限 * 金额(千元) * 预计业绩比较基准 / 365 * @param expectedRate 预计业绩比较基准(%) @@ -426,11 +542,8 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu * @param amount 投资金额 * @param row 表格 */ - private BigDecimal countProRevenue(BigDecimal expectedRate,String day,BigDecimal amount,DynamicObject row,String basis) { - BigDecimal basisDay= BigDecimal.valueOf(365); - if (basis.contains("360")){ - basisDay=BigDecimal.valueOf(360); - } + private BigDecimal countProRevenue(BigDecimal expectedRate,String day,BigDecimal amount,DynamicObject row,BigDecimal basisDay) { + BigDecimal projectRevenue = BigDecimal.ZERO; if (expectedRate != null) { 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 购买份额(初始份额) * @return 计算后的收益金额(保留2位小数) */ - private BigDecimal countRevenueAmt( + private BigDecimal countRevenueAmt(Date valueDate, Date expireDate, Date accrualDate, BigDecimal buyCopies, BigDecimal monthNetWorth, BigDecimal netWorth, DynamicObject row, BigDecimal startBuyCopies ) { + if (expireDate==null){ + expireDate=accrualDate; + } BigDecimal revenue = BigDecimal.ZERO; + // 检查所有参数是否非空 if (buyCopies != null && monthNetWorth != null && netWorth != null && startBuyCopies != null) { // 计算:(持有份额 * 月末单位净值 - 购买份额 * 购买时单位净值) / 1000 @@ -467,12 +584,26 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu .divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); // 设置到表格行 - row.set(DYNAMICS_FIELDS[3], revenue); + boolean isValidPeriod = !valueDate.after(accrualDate) && !accrualDate.after(expireDate); + if (isValidPeriod){ + row.set(DYNAMICS_FIELDS[3], revenue); + }else { + row.set(DYNAMICS_FIELDS[3], BigDecimal.ZERO); + return BigDecimal.ZERO; + } + } 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 月末单位净值 diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialListReport.java b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialListReport.java index 6c8fd3e..8cfea23 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialListReport.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialListReport.java @@ -2,6 +2,7 @@ package shjh.jhzj7.fi.fi.plugin.report; import kd.bos.algo.DataSet; import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; import kd.bos.entity.report.AbstractReportColumn; import kd.bos.entity.report.AbstractReportListDataPlugin; import kd.bos.entity.report.FilterItemInfo; @@ -67,6 +68,16 @@ public class FinancialListReport extends AbstractReportListDataPlugin implements 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. 查询理财收益预提数据 // DataSet addDataSet = QueryServiceHelper.queryDataSet( // this.getClass().getName() + "1", @@ -86,23 +97,18 @@ public class FinancialListReport extends AbstractReportListDataPlugin implements */ private List buildFilters(List filterItems) { List filters = new ArrayList<>(); - + List bankNameIds =new ArrayList<>(); + List productTypeIds =new ArrayList<>(); for (FilterItemInfo filterItem : filterItems) { Object value = filterItem.getValue(); Date date = filterItem.getDate(); switch (filterItem.getPropName()) { case FILTER_BANK_NAME: // 银行筛选 - if (value != null) { - Long bankId = (Long) ((DynamicObject) value).getPkValue(); - filters.add(new QFilter("finorginfo", QCP.equals, bankId)); - } + this.getMultipleFilter(filterItem, bankNameIds); break; case FILTER_PRODUCT_NAME: // 产品筛选 - if (value != null) { - Long productId = (Long) ((DynamicObject) value).getPkValue(); - filters.add(new QFilter("product", QCP.equals, productId)); - } + this.getMultipleFilter(filterItem, productTypeIds); break; case FILTER_BUY_DATE: // 购买日筛选 if (date != null) { @@ -120,6 +126,13 @@ public class FinancialListReport extends AbstractReportListDataPlugin implements } 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; } @@ -173,6 +186,22 @@ public class FinancialListReport extends AbstractReportListDataPlugin implements } } + /** + * 获取报表多选基础资料过滤数据 + * @param filterItem + * @param bankNameIds + * @return + */ + private List getMultipleFilter(FilterItemInfo filterItem,List 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; + } } diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/report/util/ReportUtils.java b/main/java/shjh/jhzj7/fi/fi/plugin/report/util/ReportUtils.java index bb2b9c9..dfc2840 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/report/util/ReportUtils.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/report/util/ReportUtils.java @@ -77,7 +77,7 @@ public class ReportUtils { 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 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) { Calendar cal = Calendar.getInstance();