diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/form/RecBillChangeListExtendPlugin.java b/main/java/shjh/jhzj7/fi/fi/plugin/form/RecBillChangeListExtendPlugin.java index 3a0f6ec..f2ef39f 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/form/RecBillChangeListExtendPlugin.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/form/RecBillChangeListExtendPlugin.java @@ -80,8 +80,8 @@ public class RecBillChangeListExtendPlugin extends AbstractListPlugin implements } // 收款类型校验 - if (!Arrays.asList("103", "109", "100").contains(typeNumber)) { - this.getView().showTipNotification("所选单据不满足变更条件,只有收款类型=“预付款退回/员工还款/销售回款”的收款单才允许变更。"); + if (Arrays.asList("103", "109", "100").contains(typeNumber)) { + this.getView().showTipNotification("所选单据不满足变更条件,收款类型=“预付款退回/员工还款/销售回款”的收款单不允许变更。"); evt.setCancel(true); return; } diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java new file mode 100644 index 0000000..ea8913c --- /dev/null +++ b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java @@ -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 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; + } + +} \ No newline at end of file diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialListReport.java b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialListReport.java new file mode 100644 index 0000000..58609d2 --- /dev/null +++ b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialListReport.java @@ -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 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 buildFilters(List filterItems) { + List 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(","); + } + } + } + +} + + diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/report/RegularListReport.java b/main/java/shjh/jhzj7/fi/fi/plugin/report/RegularListReport.java index 8ec157f..611e419 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/report/RegularListReport.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/report/RegularListReport.java @@ -102,6 +102,7 @@ public class RegularListReport extends AbstractReportListDataPlugin implements P logger.error(e.getMessage()); } // 按组织名称排序,这样,底部的合计数据,就会与上面的组织名称排在一起 + assert unionDataSet != null; return unionDataSet.orderBy(new String[]{FIELDS[0]}); } 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 new file mode 100644 index 0000000..f84a1d7 --- /dev/null +++ b/main/java/shjh/jhzj7/fi/fi/plugin/report/util/ReportUtils.java @@ -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); + } + +}