理财收益计提报表
This commit is contained in:
parent
4c4e67cdd3
commit
986d9ac682
|
|
@ -80,8 +80,8 @@ public class RecBillChangeListExtendPlugin extends AbstractListPlugin implements
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收款类型校验
|
// 收款类型校验
|
||||||
if (!Arrays.asList("103", "109", "100").contains(typeNumber)) {
|
if (Arrays.asList("103", "109", "100").contains(typeNumber)) {
|
||||||
this.getView().showTipNotification("所选单据不满足变更条件,只有收款类型=“预付款退回/员工还款/销售回款”的收款单才允许变更。");
|
this.getView().showTipNotification("所选单据不满足变更条件,收款类型=“预付款退回/员工还款/销售回款”的收款单不允许变更。");
|
||||||
evt.setCancel(true);
|
evt.setCancel(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,314 @@
|
||||||
|
package shjh.jhzj7.fi.fi.plugin.report;
|
||||||
|
|
||||||
|
import kd.bos.dataentity.entity.DynamicObject;
|
||||||
|
import kd.bos.dataentity.entity.DynamicObjectCollection;
|
||||||
|
import kd.bos.entity.report.FilterItemInfo;
|
||||||
|
import kd.bos.entity.report.ReportColumn;
|
||||||
|
import kd.bos.entity.report.ReportQueryParam;
|
||||||
|
import kd.bos.logging.Log;
|
||||||
|
import kd.bos.logging.LogFactory;
|
||||||
|
import kd.bos.report.ReportList;
|
||||||
|
import kd.bos.report.plugin.AbstractReportFormPlugin;
|
||||||
|
import kd.sdk.plugin.Plugin;
|
||||||
|
import shjh.jhzj7.fi.fi.plugin.report.util.ReportUtils;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报表界面插件
|
||||||
|
* 理财收益计提报表界面插件
|
||||||
|
*/
|
||||||
|
public class FinancialFormReport extends AbstractReportFormPlugin implements Plugin {
|
||||||
|
|
||||||
|
private final static Log logger = LogFactory.getLog(FinancialFormReport.class);
|
||||||
|
|
||||||
|
private static final String FILTER_DATE = "shjh_filterdate";
|
||||||
|
|
||||||
|
private static final String[] REPORT_FIELDS = {
|
||||||
|
"shjh_bankname", "shjh_productname", "shjh_producttype", "shjh_productterm",
|
||||||
|
"shjh_amount", "shjh_buycopies", "shjh_iopv", "shjh_buydate", "shjh_valuedate",
|
||||||
|
"shjh_expiredate", "shjh_planrevenue", "shjh_monthiopv", "shjh_monthiopvdate"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final String[] DYNAMICS_FIELDS = {
|
||||||
|
"shjh_projectrevenueamt","shjh_date","shjh_days","shjh_revenueamt",
|
||||||
|
"shjh_monthrevenueamt","shjh_monthrate","shjh_yearrevenueamt"
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeQuery(ReportQueryParam queryParam) {
|
||||||
|
super.beforeQuery(queryParam);
|
||||||
|
ReportList reportList = getControl("reportlistap");
|
||||||
|
reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[0], "预计收益(千元)", ReportColumn.TYPE_DECIMAL , String.valueOf(2)}));
|
||||||
|
reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[1], "计提日", ReportColumn.TYPE_DATE }));
|
||||||
|
reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[2], "天数", ReportColumn.TYPE_BIGINT }));
|
||||||
|
reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[3], "收益计提(千元)", ReportColumn.TYPE_DECIMAL , String.valueOf(2)}));
|
||||||
|
reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[4], "本月收益(千元)", ReportColumn.TYPE_DECIMAL , String.valueOf(2)}));
|
||||||
|
reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[5], "当月收益率(%)", ReportColumn.TYPE_DECIMAL , String.valueOf(2)}));
|
||||||
|
reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[6], "本年累计收益(千元)", ReportColumn.TYPE_DECIMAL , String.valueOf(2)}));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void processRowData(String gridPK, DynamicObjectCollection rowData, ReportQueryParam queryParam) {
|
||||||
|
super.processRowData(gridPK, rowData, queryParam);
|
||||||
|
|
||||||
|
// 获取筛选条件中的计提日
|
||||||
|
Date accrualDate = queryParam.getFilter().getDate(FILTER_DATE);
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(accrualDate);
|
||||||
|
|
||||||
|
// 遍历每一行数据
|
||||||
|
Iterator<DynamicObject> iterator = rowData.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
DynamicObject row = iterator.next();
|
||||||
|
//跳过小计行
|
||||||
|
if (row.getString(REPORT_FIELDS[0]).contains("-小计")){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 基础字段获取(添加null检查)
|
||||||
|
BigDecimal amount = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[4]); // 原始金额(元)
|
||||||
|
row.set(REPORT_FIELDS[4],amount.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP));
|
||||||
|
|
||||||
|
BigDecimal buyCopies = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[5]); // 持有份额
|
||||||
|
BigDecimal netWorth = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[6]); // 购买时单位净值
|
||||||
|
Date buyDate = row.getDate(REPORT_FIELDS[7]); // 购买日
|
||||||
|
Date valueDate = row.getDate(REPORT_FIELDS[8]); // 计息日
|
||||||
|
Date expireDate = row.getDate(REPORT_FIELDS[9]); // 到期日
|
||||||
|
BigDecimal expectedRate = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[10]); // 预计业绩比较基准(%)
|
||||||
|
BigDecimal monthNetWorth = ReportUtils.getBigDecimalValue(row, REPORT_FIELDS[11]); // 月末单位净值
|
||||||
|
|
||||||
|
// 1. 设置计提日
|
||||||
|
row.set(DYNAMICS_FIELDS[1], accrualDate);
|
||||||
|
// 2. 计算天数 = 计提日 - 计息日
|
||||||
|
countDays(valueDate,accrualDate,row);
|
||||||
|
// 3. 计算产品期限(总天数)=到期日-购买日,若到期日为空则用计提日-购买日
|
||||||
|
String day = countProductTerm(buyDate, expireDate, accrualDate, row);
|
||||||
|
// 4. 预计收益 = 产品期限 * 金额(千元) * 预计业绩比较基准 / 365
|
||||||
|
BigDecimal proRevenue = countProRevenue(expectedRate, day, amount, row);
|
||||||
|
// 5. 收益计提 = 持有份额 * (月末单位净值 - 购买时单位净值) / 1000
|
||||||
|
BigDecimal revenueAmt = countRevenueAmt(buyCopies, monthNetWorth, netWorth, row);
|
||||||
|
// 6. 本月收益计算(严格按生效期间计算)
|
||||||
|
BigDecimal monthRevenue = countMonthRevenue(monthNetWorth, netWorth, buyCopies, valueDate, accrualDate, expireDate, row);
|
||||||
|
// 7. 当月收益率 = 本月收益 / 金额(千元) * 100 * 12
|
||||||
|
countMonthRate(amount,monthRevenue,row);
|
||||||
|
// 8. 本年累计收益 = 当年各月收益之和(按实际持有天数比例计算)
|
||||||
|
BigDecimal yearRevenue = countYearRevenue(monthNetWorth, netWorth, buyCopies, valueDate, accrualDate, expireDate, row);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算天数 = 计提日 - 计息日
|
||||||
|
* @param valueDate 计息日
|
||||||
|
* @param accrualDate 计提日
|
||||||
|
* @param row 表格
|
||||||
|
*/
|
||||||
|
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 {
|
||||||
|
row.set(DYNAMICS_FIELDS[2], BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算产品期限(总天数)=到期日-购买日,若到期日为空则用计提日-购买日
|
||||||
|
* @param buyDate 购买日
|
||||||
|
* @param expireDate 到期日
|
||||||
|
* @param accrualDate 计提日
|
||||||
|
* @param row 表格
|
||||||
|
* @return 总天数
|
||||||
|
*/
|
||||||
|
private String countProductTerm(Date buyDate,Date expireDate,Date accrualDate,DynamicObject row){
|
||||||
|
String day = "0"; // 默认值设为0
|
||||||
|
if (buyDate != null) {
|
||||||
|
Date endDate = (expireDate != null) ? expireDate : accrualDate;
|
||||||
|
// 检查计提日/到期日是否早于购买日
|
||||||
|
if (endDate.getTime() >= buyDate.getTime()) {
|
||||||
|
long termDays = (endDate.getTime() - buyDate.getTime()) / (1000 * 60 * 60 * 24);
|
||||||
|
day = String.valueOf(termDays);
|
||||||
|
}
|
||||||
|
// 如果endDate早于buyDate,保持day=0
|
||||||
|
}
|
||||||
|
row.set(REPORT_FIELDS[3], day);
|
||||||
|
return day;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预计收益 = 产品期限 * 金额(千元) * 预计业绩比较基准 / 365
|
||||||
|
* @param expectedRate 预计业绩比较基准(%)
|
||||||
|
* @param day 总天数
|
||||||
|
* @param amount 投资金额
|
||||||
|
* @param row 表格
|
||||||
|
*/
|
||||||
|
private BigDecimal countProRevenue(BigDecimal expectedRate,String day,BigDecimal amount,DynamicObject row) {
|
||||||
|
BigDecimal projectRevenue = BigDecimal.ZERO;
|
||||||
|
if (expectedRate != null) {
|
||||||
|
projectRevenue = new BigDecimal(day).multiply(amount.divide(new BigDecimal(1000), 10, RoundingMode.HALF_UP))
|
||||||
|
.multiply(expectedRate.divide(new BigDecimal(100), 10, RoundingMode.HALF_UP))
|
||||||
|
.divide(new BigDecimal(365), 2, RoundingMode.HALF_UP);
|
||||||
|
row.set(DYNAMICS_FIELDS[0], projectRevenue);
|
||||||
|
}
|
||||||
|
return projectRevenue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收益计提 = 持有份额 * (月末单位净值 - 购买时单位净值) / 1000
|
||||||
|
* @param buyCopies 持有份额
|
||||||
|
* @param monthNetWorth 月末单位净值
|
||||||
|
* @param netWorth 购买时单位净值
|
||||||
|
* @param row 表格
|
||||||
|
*/
|
||||||
|
private BigDecimal countRevenueAmt(BigDecimal buyCopies,BigDecimal monthNetWorth,BigDecimal netWorth,DynamicObject row){
|
||||||
|
BigDecimal revenue=BigDecimal.ZERO;
|
||||||
|
if (buyCopies != null && monthNetWorth != null && netWorth != null) {
|
||||||
|
revenue = buyCopies.multiply(monthNetWorth.subtract(netWorth))
|
||||||
|
.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
|
||||||
|
row.set(DYNAMICS_FIELDS[3], revenue);
|
||||||
|
}
|
||||||
|
return revenue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本月收益计算(严格按生效期间计算)
|
||||||
|
* @param monthNetWorth 月末单位净值
|
||||||
|
* @param netWorth 单位净值
|
||||||
|
* @param buyCopies 持有份额
|
||||||
|
* @param valueDate 计息日
|
||||||
|
* @param accrualDate 计提日
|
||||||
|
* @param expireDate 到期日
|
||||||
|
* @param row 表格
|
||||||
|
* @return 本月收益金额
|
||||||
|
*/
|
||||||
|
private BigDecimal countMonthRevenue(BigDecimal monthNetWorth,BigDecimal netWorth,BigDecimal buyCopies,Date valueDate,Date accrualDate,Date expireDate,DynamicObject row){
|
||||||
|
BigDecimal monthRevenue = BigDecimal.ZERO;
|
||||||
|
if (monthNetWorth != null && netWorth != null && buyCopies != null && valueDate != null) {
|
||||||
|
|
||||||
|
// 关键判断:计提日必须在计息日之后(产品已生效)
|
||||||
|
if (!accrualDate.before(valueDate)) {
|
||||||
|
|
||||||
|
// 获取当月第一天(月初)
|
||||||
|
Date monthFirstDay = ReportUtils.getFirstDayOfMonth(accrualDate);
|
||||||
|
|
||||||
|
// 情况1:产品已过期
|
||||||
|
if (expireDate != null && expireDate.before(accrualDate)) {
|
||||||
|
// 仅在过期当月计算
|
||||||
|
if (ReportUtils.isSameMonth(expireDate, accrualDate)) {
|
||||||
|
Date periodStart = valueDate.after(monthFirstDay) ? valueDate : monthFirstDay;
|
||||||
|
long effectiveDays = ReportUtils.getDaysBetween(periodStart, expireDate);
|
||||||
|
BigDecimal totalRevenue = buyCopies.multiply(monthNetWorth.subtract(netWorth));
|
||||||
|
monthRevenue = ReportUtils.calculateProportionalRevenue(
|
||||||
|
totalRevenue,
|
||||||
|
ReportUtils.getDaysBetween(valueDate, expireDate),
|
||||||
|
effectiveDays
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 情况2:产品未过期
|
||||||
|
else {
|
||||||
|
Date periodStart = valueDate.after(monthFirstDay) ? valueDate : monthFirstDay;
|
||||||
|
long effectiveDays = ReportUtils.getDaysBetween(periodStart, accrualDate);
|
||||||
|
BigDecimal totalRevenue = buyCopies.multiply(monthNetWorth.subtract(netWorth));
|
||||||
|
monthRevenue = ReportUtils.calculateProportionalRevenue(
|
||||||
|
totalRevenue,
|
||||||
|
ReportUtils.getDaysBetween(valueDate, expireDate != null ? expireDate : accrualDate),
|
||||||
|
effectiveDays
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 计提日在计息日之前(产品未生效)则monthRevenue保持为0
|
||||||
|
}
|
||||||
|
row.set(DYNAMICS_FIELDS[4], monthRevenue.setScale(2, RoundingMode.HALF_UP));
|
||||||
|
return monthRevenue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当月收益率 = 本月收益 / 金额(千元) * 100 * 12
|
||||||
|
* @param amount 投资金额
|
||||||
|
* @param monthRevenue 本月收益
|
||||||
|
* @param row 表格
|
||||||
|
*/
|
||||||
|
private void countMonthRate(BigDecimal amount,BigDecimal monthRevenue,DynamicObject row){
|
||||||
|
if (amount.compareTo(BigDecimal.ZERO) != 0) {
|
||||||
|
BigDecimal monthRate = monthRevenue
|
||||||
|
.divide(amount, 10, RoundingMode.HALF_UP) // 先计算 (月收入/金额)
|
||||||
|
.multiply(new BigDecimal(1200)) // 再 ×1200(假设业务需要)
|
||||||
|
.setScale(2, RoundingMode.HALF_UP); // 最终保留2位小数
|
||||||
|
|
||||||
|
row.set(DYNAMICS_FIELDS[5], monthRate);
|
||||||
|
} else {
|
||||||
|
row.set(DYNAMICS_FIELDS[5], BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本年累计收益 = 当年各月收益之和(按实际持有天数比例计算)
|
||||||
|
* @param monthNetWorth 月末单位净值
|
||||||
|
* @param netWorth 单位净值
|
||||||
|
* @param buyCopies 持有份额
|
||||||
|
* @param valueDate 计息日
|
||||||
|
* @param accrualDate 计提日
|
||||||
|
* @param expireDate 到期日
|
||||||
|
* @param row 表格
|
||||||
|
*/
|
||||||
|
private BigDecimal countYearRevenue(BigDecimal monthNetWorth,BigDecimal netWorth,BigDecimal buyCopies,Date valueDate,Date accrualDate,Date expireDate,DynamicObject row){
|
||||||
|
BigDecimal yearRevenue = BigDecimal.ZERO;
|
||||||
|
if (monthNetWorth != null && netWorth != null && buyCopies != null && valueDate != null) {
|
||||||
|
|
||||||
|
// 获取计提日所在年份的起止时间
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(accrualDate);
|
||||||
|
cal.set(Calendar.MONTH, Calendar.JANUARY);
|
||||||
|
cal.set(Calendar.DAY_OF_MONTH, 1);
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
cal.set(Calendar.MINUTE, 0);
|
||||||
|
cal.set(Calendar.SECOND, 0);
|
||||||
|
cal.set(Calendar.MILLISECOND, 0);
|
||||||
|
Date yearStart = cal.getTime();
|
||||||
|
|
||||||
|
cal.set(Calendar.MONTH, Calendar.DECEMBER);
|
||||||
|
cal.set(Calendar.DAY_OF_MONTH, 31);
|
||||||
|
Date yearEnd = cal.getTime();
|
||||||
|
|
||||||
|
// 核心判断:产品在当年有存续期(满足任意一条即可)
|
||||||
|
// 1. 计息日 <= 年末 且 到期日 >= 年初(跨年产品)
|
||||||
|
// 2. 到期日为null且计息日 <= 年末(未到期产品)
|
||||||
|
boolean isEffectiveThisYear =
|
||||||
|
(valueDate.before(yearEnd) || ReportUtils.isSameYear(valueDate, yearStart)) &&
|
||||||
|
(expireDate == null || expireDate.after(yearStart)) ||
|
||||||
|
(expireDate == null && (valueDate.before(yearEnd) || ReportUtils.isSameYear(valueDate, yearStart)));
|
||||||
|
|
||||||
|
if (isEffectiveThisYear) {
|
||||||
|
// 计算实际生效时间段
|
||||||
|
Date effectiveStart = valueDate.after(yearStart) ? valueDate : yearStart;
|
||||||
|
Date effectiveEnd = (expireDate == null || expireDate.after(yearEnd)) ? yearEnd : expireDate;
|
||||||
|
|
||||||
|
// 计算本年有效天数
|
||||||
|
long effectiveDays = ReportUtils.getDaysBetween(effectiveStart, effectiveEnd);
|
||||||
|
|
||||||
|
// 计算总存续天数
|
||||||
|
long totalDays = ReportUtils.getDaysBetween(valueDate,
|
||||||
|
expireDate != null ? expireDate : accrualDate);
|
||||||
|
|
||||||
|
// 计算总收益
|
||||||
|
BigDecimal totalRevenue = buyCopies.multiply(monthNetWorth.subtract(netWorth));
|
||||||
|
|
||||||
|
// 按比例计算本年收益
|
||||||
|
yearRevenue = ReportUtils.calculateProportionalRevenue(
|
||||||
|
totalRevenue,
|
||||||
|
totalDays,
|
||||||
|
effectiveDays
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row.set(DYNAMICS_FIELDS[6], yearRevenue.setScale(2, RoundingMode.HALF_UP));
|
||||||
|
return yearRevenue;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
package shjh.jhzj7.fi.fi.plugin.report;
|
||||||
|
|
||||||
|
import kd.bos.algo.DataSet;
|
||||||
|
import kd.bos.dataentity.entity.DynamicObject;
|
||||||
|
import kd.bos.entity.report.AbstractReportColumn;
|
||||||
|
import kd.bos.entity.report.AbstractReportListDataPlugin;
|
||||||
|
import kd.bos.entity.report.FilterItemInfo;
|
||||||
|
import kd.bos.entity.report.ReportQueryParam;
|
||||||
|
import kd.bos.logging.Log;
|
||||||
|
import kd.bos.logging.LogFactory;
|
||||||
|
import kd.bos.orm.ORM;
|
||||||
|
import kd.bos.orm.query.QCP;
|
||||||
|
import kd.bos.orm.query.QFilter;
|
||||||
|
import kd.bos.servicehelper.QueryServiceHelper;
|
||||||
|
import kd.sdk.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报表取数插件
|
||||||
|
* 理财收益计提报表取数
|
||||||
|
*/
|
||||||
|
public class FinancialListReport extends AbstractReportListDataPlugin implements Plugin {
|
||||||
|
private static final Log logger = LogFactory.getLog(FinancialListReport.class);
|
||||||
|
|
||||||
|
// 理财申购单字段
|
||||||
|
private static final String[] FINANCIAL_FIELDS = {
|
||||||
|
"finorginfo.name", "productname", "revenuetype", "term", "amount",
|
||||||
|
"buycopies", "iopv", "purchasedate", "valuedate", "expiredate", "planrevenue"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 报表输出字段
|
||||||
|
private static final String[] REPORT_FIELDS = {
|
||||||
|
"shjh_bankname", "shjh_productname", "shjh_producttype", "shjh_productterm",
|
||||||
|
"shjh_amount", "shjh_buycopies", "shjh_iopv", "shjh_buydate", "shjh_valuedate",
|
||||||
|
"shjh_expiredate", "shjh_planrevenue", "shjh_monthiopv", "shjh_monthiopvdate"
|
||||||
|
};
|
||||||
|
|
||||||
|
// 筛选条件字段名
|
||||||
|
private static final String FILTER_BANK_NAME = "shjh_filtername";
|
||||||
|
private static final String FILTER_PRODUCT_NAME = "shjh_filterproduct";
|
||||||
|
private static final String FILTER_BUY_DATE = "shjh_filterbuydate";
|
||||||
|
private static final String FILTER_START_DATE = "shjh_startdate";
|
||||||
|
private static final String FILTER_END_DATE = "shjh_enddate";
|
||||||
|
|
||||||
|
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSet query(ReportQueryParam param, Object context) throws Throwable {
|
||||||
|
// 1. 构建查询条件
|
||||||
|
List<QFilter> filters = buildFilters(param.getFilter().getFilterItems());
|
||||||
|
filters.add(new QFilter("billstatus", QCP.equals, "C")); // 只查询已审核单据
|
||||||
|
|
||||||
|
// 2. 查询理财申购单数据
|
||||||
|
StringBuilder selectFields = new StringBuilder();
|
||||||
|
assembleSQL(selectFields);
|
||||||
|
selectFields.append(",").append("billno");
|
||||||
|
DataSet mainDataSet = QueryServiceHelper.queryDataSet(
|
||||||
|
this.getClass().getName(),
|
||||||
|
"cim_finsubscribe",
|
||||||
|
String.valueOf(selectFields),
|
||||||
|
filters.toArray(new QFilter[0]),
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. 查询理财收益预提数据
|
||||||
|
DataSet addDataSet = QueryServiceHelper.queryDataSet(
|
||||||
|
this.getClass().getName() + "1",
|
||||||
|
"cim_intbill_batch",
|
||||||
|
"entry.finbillno, entry.shjh_nowamount AS shjh_monthiopv, preintdate AS shjh_monthiopvdate",
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4. 合并数据并返回结果
|
||||||
|
return processAndMergeDatasets(mainDataSet, addDataSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据界面筛选条件构建QFilter列表
|
||||||
|
*/
|
||||||
|
private List<QFilter> buildFilters(List<FilterItemInfo> filterItems) {
|
||||||
|
List<QFilter> filters = 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));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FILTER_PRODUCT_NAME: // 产品筛选
|
||||||
|
if (value != null) {
|
||||||
|
Long productId = (Long) ((DynamicObject) value).getPkValue();
|
||||||
|
filters.add(new QFilter("product", QCP.equals, productId));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FILTER_BUY_DATE: // 购买日筛选
|
||||||
|
if (date != null) {
|
||||||
|
filters.add(new QFilter("purchasedate", QCP.equals, DATE_FORMAT.format(date)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FILTER_START_DATE: // 计息日筛选
|
||||||
|
if (date != null) {
|
||||||
|
filters.add(new QFilter("valuedate", QCP.equals, DATE_FORMAT.format(date)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FILTER_END_DATE: // 到期日筛选
|
||||||
|
if (date != null) {
|
||||||
|
filters.add(new QFilter("expiredate", QCP.equals, DATE_FORMAT.format(date)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理并合并数据集
|
||||||
|
*/
|
||||||
|
private DataSet processAndMergeDatasets(DataSet mainDataSet, DataSet addDataSet) {
|
||||||
|
// 关联两个数据集
|
||||||
|
DataSet joinedDataSet = mainDataSet.join(addDataSet)
|
||||||
|
.on("billno", "entry.finbillno")
|
||||||
|
.select(REPORT_FIELDS)
|
||||||
|
.finish();
|
||||||
|
|
||||||
|
// 生成按银行分组的小计行
|
||||||
|
DataSet summaryDataSet = joinedDataSet.groupBy(new String[]{REPORT_FIELDS[0]})
|
||||||
|
.sum(REPORT_FIELDS[4]) // 对金额字段求和
|
||||||
|
.finish()
|
||||||
|
.addField("'-'", REPORT_FIELDS[1]) // 产品名称
|
||||||
|
.addField("'-'", REPORT_FIELDS[2]) // 产品类型
|
||||||
|
.addField("'-'", REPORT_FIELDS[3]) // 产品期限
|
||||||
|
.addField("0L", REPORT_FIELDS[5]) // 持有份数
|
||||||
|
.addField("0L", REPORT_FIELDS[6]) // 单位净值
|
||||||
|
.addField("NULL", REPORT_FIELDS[7]) // 购买日
|
||||||
|
.addField("NULL", REPORT_FIELDS[8]) // 计息日
|
||||||
|
.addField("NULL", REPORT_FIELDS[9]) // 到期日
|
||||||
|
.addField("0L", REPORT_FIELDS[10]) // 预计收益
|
||||||
|
.addField("0L", REPORT_FIELDS[11]) // 月末净值
|
||||||
|
.addField("NULL", REPORT_FIELDS[12]) // 净值报告日
|
||||||
|
.select("concat(shjh_bankname+'-小计') as " + String.join(",", REPORT_FIELDS))
|
||||||
|
.select(String.join(",", REPORT_FIELDS));
|
||||||
|
|
||||||
|
// 合并明细数据和小计数据,并按银行名称排序
|
||||||
|
return joinedDataSet.union(summaryDataSet)
|
||||||
|
.orderBy(new String[]{REPORT_FIELDS[0]});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装SQL
|
||||||
|
*
|
||||||
|
* @param selectFields
|
||||||
|
*/
|
||||||
|
private void assembleSQL(StringBuilder selectFields) {
|
||||||
|
for (int i = 0; i < FINANCIAL_FIELDS.length; i++) {
|
||||||
|
if (i == FINANCIAL_FIELDS.length-1) {
|
||||||
|
selectFields.append(FINANCIAL_FIELDS[i]).append(" as ").append(REPORT_FIELDS[i]);
|
||||||
|
}else {
|
||||||
|
selectFields.append(FINANCIAL_FIELDS[i]).append(" as ").append(REPORT_FIELDS[i]).append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -102,6 +102,7 @@ public class RegularListReport extends AbstractReportListDataPlugin implements P
|
||||||
logger.error(e.getMessage());
|
logger.error(e.getMessage());
|
||||||
}
|
}
|
||||||
// 按组织名称排序,这样,底部的合计数据,就会与上面的组织名称排在一起
|
// 按组织名称排序,这样,底部的合计数据,就会与上面的组织名称排在一起
|
||||||
|
assert unionDataSet != null;
|
||||||
return unionDataSet.orderBy(new String[]{FIELDS[0]});
|
return unionDataSet.orderBy(new String[]{FIELDS[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
package shjh.jhzj7.fi.fi.plugin.report.util;
|
||||||
|
|
||||||
|
import kd.bos.dataentity.entity.DynamicObject;
|
||||||
|
import kd.bos.dataentity.entity.LocaleString;
|
||||||
|
import kd.bos.entity.report.ReportColumn;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class ReportUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态创建报表列表字段列
|
||||||
|
* @param columnInfo
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ReportColumn createReportColumn(String [] columnInfo) {
|
||||||
|
ReportColumn reportColumn = new ReportColumn();
|
||||||
|
// 设置报表列字段的标识
|
||||||
|
reportColumn.setFieldKey(columnInfo[0]);
|
||||||
|
// 设置报表列字段的标识
|
||||||
|
reportColumn.setCaption(new LocaleString(columnInfo[1]));
|
||||||
|
// 设置报表列字段的类型
|
||||||
|
reportColumn.setFieldType(columnInfo[2]);
|
||||||
|
// 设置报表列字段的精度
|
||||||
|
if (columnInfo.length>3){
|
||||||
|
reportColumn.setScale(Integer.parseInt(columnInfo[3]));
|
||||||
|
}
|
||||||
|
return reportColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:获取某个月的第一天
|
||||||
|
public static Date getFirstDayOfMonth(Date date) {
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.set(Calendar.DAY_OF_MONTH, 1);
|
||||||
|
return cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 安全获取BigDecimal值
|
||||||
|
public static BigDecimal getBigDecimalValue(DynamicObject row, String fieldName) {
|
||||||
|
Object value = row.get(fieldName);
|
||||||
|
if (value instanceof BigDecimal) {
|
||||||
|
return (BigDecimal) value;
|
||||||
|
} else if (value instanceof Number) {
|
||||||
|
return BigDecimal.valueOf(((Number) value).doubleValue());
|
||||||
|
}
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:按比例计算收益
|
||||||
|
public static BigDecimal calculateProportionalRevenue(BigDecimal totalRevenue, long totalDays, long effectiveDays) {
|
||||||
|
if (totalDays <= 0 || effectiveDays <= 0) {
|
||||||
|
return BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
return totalRevenue
|
||||||
|
.divide(new BigDecimal(totalDays), 10, RoundingMode.HALF_UP)
|
||||||
|
.multiply(new BigDecimal(effectiveDays))
|
||||||
|
.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP); // 转换为千元单位
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:计算两个日期之间的天数
|
||||||
|
public static long getDaysBetween(Date start, Date end) {
|
||||||
|
if (start == null || end == null) return 0;
|
||||||
|
return (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:判断是否同月
|
||||||
|
public static boolean isSameMonth(Date date1, Date date2) {
|
||||||
|
Calendar cal1 = Calendar.getInstance();
|
||||||
|
cal1.setTime(date1);
|
||||||
|
Calendar cal2 = Calendar.getInstance();
|
||||||
|
cal2.setTime(date2);
|
||||||
|
return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
|
||||||
|
&& cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:判断是否同年
|
||||||
|
public static boolean isSameYear(Date date1, Date date2) {
|
||||||
|
Calendar cal1 = Calendar.getInstance();
|
||||||
|
cal1.setTime(date1);
|
||||||
|
Calendar cal2 = Calendar.getInstance();
|
||||||
|
cal2.setTime(date2);
|
||||||
|
return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue