diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/form/RedeemBillExtendEditPlugin.java b/main/java/shjh/jhzj7/fi/fi/plugin/form/RedeemBillExtendEditPlugin.java index b5a7b5a..9e865a2 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/form/RedeemBillExtendEditPlugin.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/form/RedeemBillExtendEditPlugin.java @@ -86,6 +86,13 @@ public class RedeemBillExtendEditPlugin extends RedeemBillEdit { BigDecimal copies = (BigDecimal)this.getModel().getValue("copies"); BigDecimal iopv = finBill.getBigDecimal("iopv"); BigDecimal realRevenue = redeemAmount.subtract(iopv.multiply(copies)); + String value = (String) this.getModel().getValue("shjh_xjglcp"); + //非现金管理类:计提日期前所有赎回单上的实际收益 + //赎回单实际收益:赎回份数*(赎回日净值-购买时净值) + if ("0".equals(value)) { + BigDecimal shrjz = (BigDecimal) this.getModel().getValue("shjh_shrjz"); + realRevenue=copies.multiply(shrjz.subtract(iopv)); + } TmcViewInputHelper.setValWithoutDataChanged(this.getModel(), "realrevenue", realRevenue); } diff --git a/main/java/shjh/jhzj7/fi/fi/plugin/form/RedeemFormPlugin.java b/main/java/shjh/jhzj7/fi/fi/plugin/form/RedeemFormPlugin.java index 840acc5..61c5bf2 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/form/RedeemFormPlugin.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/form/RedeemFormPlugin.java @@ -4,11 +4,15 @@ import kd.bos.dataentity.entity.DynamicObject; import kd.bos.dataentity.entity.DynamicObjectCollection; import kd.bos.entity.datamodel.events.PropertyChangedArgs; import kd.bos.form.plugin.AbstractFormPlugin; +import kd.bos.logging.Log; +import kd.bos.logging.LogFactory; import kd.bos.orm.query.QCP; import kd.bos.orm.query.QFilter; import kd.bos.servicehelper.BusinessDataServiceHelper; +import shjh.jhzj7.fi.fi.plugin.report.FinancialFormReport; import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.Date; import java.util.EventObject; @@ -19,17 +23,20 @@ import java.util.EventObject; */ public class RedeemFormPlugin extends AbstractFormPlugin { + private final static Log logger = LogFactory.getLog(RedeemFormPlugin.class); + + @Override public void propertyChanged(PropertyChangedArgs e) { super.propertyChanged(e); String name = e.getProperty().getName(); if ("redeemdate".equals(name)) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); - Date redeemdate = (Date)this.getView().getModel().getValue(name);//赎回日期 + Date redeemdate = (Date) this.getView().getModel().getValue(name);//赎回日期 if (null != redeemdate) { String format1 = format.format(redeemdate); // 修改【赎回日期】后,校验理财申购单估值表体是否存在该日期,若不存在报错:“该日期不存在估值信息,请前往理财申购列表进行估值。” - DynamicObject finbillno = (DynamicObject)this.getView().getModel().getValue("finbillno");//产品编号 + DynamicObject finbillno = (DynamicObject) this.getView().getModel().getValue("finbillno");//产品编号 if (null != finbillno) { // 理财申购单 QFilter qFilter = new QFilter("id", QCP.equals, finbillno.getLong("id")); @@ -51,30 +58,40 @@ public class RedeemFormPlugin extends AbstractFormPlugin { break; } } - boolean renewal =(boolean)this.getModel().getValue("isrenewal"); + boolean renewal = (boolean) this.getModel().getValue("isrenewal"); if (!isExist && !renewal) { this.getView().showErrorNotification("该日期不存在估值信息,请前往理财申购列表进行估值。"); - this.getView().getModel().setValue("redeemdate",null); + this.getView().getModel().setValue("redeemdate", null); this.getView().updateView("redeemdate"); - }else { - this.getView().getModel().setValue("shjh_shrjz",shrjz); + } else { + this.getView().getModel().setValue("shjh_shrjz", shrjz); this.getView().updateView("shjh_shrjz"); - this.getView().getModel().setValue("shjh_shrsyfe",shrsyfe); + this.getView().getModel().setValue("shjh_shrsyfe", shrsyfe); this.getView().updateView("shjh_shrsyfe"); } } + updateRevenue(cimFinsubscribe); } } } - }else if ("copies".equals(name)) { + } else if ("copies".equals(name)) { //表头【剩余份数】=【赎回日剩余份数】—【赎回份数】(大于等于0); - BigDecimal copies = (BigDecimal)this.getView().getModel().getValue(name);//赎回份数 - BigDecimal shjh_shrsyfe = (BigDecimal)this.getView().getModel().getValue("shjh_shrsyfe");//赎回日剩余份额 + BigDecimal copies = (BigDecimal) this.getView().getModel().getValue(name);//赎回份数 + BigDecimal shjh_shrsyfe = (BigDecimal) this.getView().getModel().getValue("shjh_shrsyfe");//赎回日剩余份额 // 判断赎回份数是否大于赎回日剩余份额 if (copies.compareTo(shjh_shrsyfe) > 0) { this.getView().showErrorNotification("【赎回日剩余份数】—【赎回份数】(大于等于0)"); - this.getView().getModel().setValue("copies",BigDecimal.ZERO); + this.getView().getModel().setValue("copies", BigDecimal.ZERO); this.getView().updateView("copies"); + } else { + //获取申购单 + DynamicObject finSubscribeF7 = (DynamicObject) this.getModel().getValue("finbillno"); + if (finSubscribeF7 != null) { + DynamicObject finSubscribe = BusinessDataServiceHelper.loadSingle(finSubscribeF7.getPkValue(), "cim_finsubscribe"); + if (finSubscribe != null) { + updateRevenue(finSubscribe); + } + } } } } @@ -82,20 +99,117 @@ public class RedeemFormPlugin extends AbstractFormPlugin { @Override public void afterBindData(EventObject e) { super.afterBindData(e); - if ("A".equals((String)this.getModel().getValue("billstatus"))){ + if ("A".equals((String) this.getModel().getValue("billstatus"))) { //新增不可编辑字段【是否现金管理类】:根据理财申购单表头字段带出 - DynamicObject finbillno = (DynamicObject)this.getView().getModel().getValue("finbillno");//产品编号 + DynamicObject finbillno = (DynamicObject) this.getView().getModel().getValue("finbillno");//产品编号 if (null != finbillno) { // 理财申购单 QFilter qFilter = new QFilter("id", QCP.equals, finbillno.getLong("id")); - DynamicObject cimFinsubscribe = BusinessDataServiceHelper.loadSingle("cim_finsubscribe", qFilter.toArray()); - if (null != cimFinsubscribe) { - this.getView().getModel().setValue("shjh_xjglcp",cimFinsubscribe.getString("shjh_xjglcp")); + DynamicObject finSubscribe = BusinessDataServiceHelper.loadSingle("cim_finsubscribe", qFilter.toArray()); + if (null != finSubscribe) { + this.getView().getModel().setValue("shjh_xjglcp", finSubscribe.getString("shjh_xjglcp")); this.getView().updateView("shjh_xjglcp"); //字段【赎回份数】默认为赎回日期剩余份额,可手工修改。 - this.getView().getModel().setValue("copies",cimFinsubscribe.getBigDecimal("surpluscopies")); + this.getView().getModel().setValue("copies", finSubscribe.getBigDecimal("surpluscopies")); } } } } + + private void updateRevenue(DynamicObject finSubscribe) { + BigDecimal copies = (BigDecimal) this.getView().getModel().getValue("copies");//赎回份数 + BigDecimal shrsyfe = (BigDecimal) this.getView().getModel().getValue("copies");//赎回日剩余份数 + + DynamicObjectCollection collection = finSubscribe.getDynamicObjectCollection("valuationentry"); + if (collection != null && collection.size() != 0) { + //判断现金管理类 + String value = (String) this.getModel().getValue("shjh_xjglcp"); + //现金管理类:计提日期前所有赎回单的现金管理类收益 + //赎回单理财实际收益:赎回金额一购买金额*(赎回比之积) + if ("1".equals(value)) { + Date redeemDate = (Date) this.getModel().getValue("redeemdate"); + if (redeemDate != null) { + //自身比 + BigDecimal selfRat = copies.divide(shrsyfe,10, RoundingMode.HALF_UP); + //赎回比之积 + BigDecimal redProductAmount = this.getRedProductAmount(collection, redeemDate); + BigDecimal amount = (BigDecimal) this.getModel().getValue("amount"); + this.getModel().setValue("shjh_realrevenue2", amount.subtract(finSubscribe.getBigDecimal("amount").multiply(redProductAmount).multiply(selfRat))); + this.getView().updateView("shjh_realrevenue2"); + } + } + } + + } + + /** + * 计提日最近估值记录获取——(赎回份额/赎回日剩余份额)* 所有赎回单 + * + * @param entry 输入数据集合 + * @param date 目标日期 + * @return 所有符合条件的赎回单的(赎回份额 / 剩余份额)的乘积 + */ + private BigDecimal getRedProductAmount(DynamicObjectCollection entry, Date date) { + // 1. 按估值日期和赎回日期排序 + DynamicObjectCollection sortedEntries = new DynamicObjectCollection(); + sortedEntries.addAll(entry); + + sortedEntries.sort((o1, o2) -> { + // 优先按估值日期排序(从小到大) + Date valDate1 = o1.getDate("e_valuationdate"); + Date valDate2 = o2.getDate("e_valuationdate"); + int compareValDate = valDate1.compareTo(valDate2); + if (compareValDate != 0) { + return compareValDate; + } + + // 估值日期相同时,按赎回日期排序 + Date redDate1 = o1.getDate("shjh_shrq"); + Date redDate2 = o2.getDate("shjh_shrq"); + if (redDate1 == null && redDate2 == null) return 0; + if (redDate1 == null) return -1; // null视为较小值 + if (redDate2 == null) return 1; + return redDate1.compareTo(redDate2); + }); + + // 2. 累乘符合条件的差额,初始值设为1 + BigDecimal product = BigDecimal.ONE; + + for (DynamicObject item : sortedEntries) { + try { + // 检查是否为赎回单(跳过非赎回条目) + DynamicObject shdh = item.getDynamicObject("shjh_shdh"); + if (shdh == null) { + continue; + } + + // 检查估值日期是否 ≤ 目标日期 + Date valDate = item.getDate("e_valuationdate"); + if (valDate == null || valDate.compareTo(date) > 0) { + continue; + } + + Object pkValue = shdh.getPkValue(); + DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(pkValue, "cim_redeem"); + + // 安全获取数值字段 + BigDecimal copies = dynamicObject.getBigDecimal("copies"); // 赎回份额 + BigDecimal remainderCopies = dynamicObject.getBigDecimal("shjh_shrsyfe"); // 赎回日剩余份额 + + if (copies == null || remainderCopies == null || remainderCopies.compareTo(BigDecimal.ZERO) == 0) { + continue; // 跳过无效数据 + } + + // 计算 (赎回份额/剩余日份额) + BigDecimal ratio = copies.divide(remainderCopies, 10, RoundingMode.HALF_UP); + // 累乘 + product = product.multiply(ratio).setScale(10, RoundingMode.HALF_UP); + + } catch (Exception e) { + // 记录错误并跳过当前条目 + logger.error("处理赎回单数据出错: " + e.getMessage(), e); + } + } + return product; + } } 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 390cafc..bcdfb1c 100644 --- a/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java +++ b/main/java/shjh/jhzj7/fi/fi/plugin/report/FinancialFormReport.java @@ -32,13 +32,13 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu "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", "shjh_id","shjh_status", - "shjh_basis","shjh_startbuycopies" + "shjh_basis","shjh_startbuycopies","shjh_nowamount" }; private static final String[] DYNAMICS_FIELDS = { "shjh_projectrevenueamt","shjh_date","shjh_days","shjh_revenueamt", "shjh_monthrevenueamt","shjh_monthrate","shjh_yearrevenueamt", - "shjh_yearrate","shjh_actualearnings","shjh_actualrate","shjh_expire","shjh_nowamount" + "shjh_yearrate","shjh_actualearnings","shjh_actualrate","shjh_expire" }; @Override @@ -56,7 +56,7 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[8], "实际收益", ReportColumn.TYPE_DECIMAL , String.valueOf(8)})); reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[9], "实际总收益率(%)", ReportColumn.TYPE_DECIMAL , String.valueOf(8)})); reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[10], "是否已到期", ReportColumn.TYPE_TEXT })); - reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[11], "金额(千元)", ReportColumn.TYPE_DECIMAL , String.valueOf(8)})); + //reportList.getColumns().add(ReportUtils.createReportColumn(new String [] { DYNAMICS_FIELDS[11], "金额(千元)", ReportColumn.TYPE_DECIMAL , String.valueOf(8)})); } @@ -166,7 +166,7 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu //过滤 ReportUtils.removeRowData(rowData,REPORT_FIELDS[9],DYNAMICS_FIELDS[1]); //排序 - //ReportUtils.sortByDate(rowData,REPORT_FIELDS[9],false); + ReportUtils.sortByDate(rowData,REPORT_FIELDS[7],false); //添加合计 // 需要配置求和的字段映射(目标字段,来源字段) List sumConfig = new ArrayList<>(); @@ -178,6 +178,7 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu 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 + sumConfig.add(new String[]{REPORT_FIELDS[17], REPORT_FIELDS[17]}); // shjh_actualearnings ReportUtils.addTotalRowData(rowData,REPORT_FIELDS[0],"小计","合计",sumConfig); @@ -205,7 +206,7 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu BigDecimal monthAnnualizedRate = BigDecimal.ZERO; BigDecimal yearAmount = BigDecimal.ZERO; BigDecimal yearAnnualizedRate = BigDecimal.ZERO; - //计提日期之前赎回金额之和(用于实际收益计算) + //计提日期之前实际收益、现金管理类收益之和(用于实际收益计算) BigDecimal allRedAmount = BigDecimal.ZERO; //计提日期之前赎回金额之和(用于收益计提计算) BigDecimal allRedProductAmount = BigDecimal.ZERO; @@ -234,7 +235,17 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu int accrualYear = accrualCal.get(Calendar.YEAR); int accrualMonth = accrualCal.get(Calendar.MONTH); //与年初相隔天数 - int daysFromJan1 = accrualCal.get(Calendar.DAY_OF_YEAR) - 1; + //与年初相隔天数 + int daysFromJan1; + if (expireDate != null && accrualDate.after(expireDate)) { + // 当计提日期大于到期日时,计算到期日到年初的天数 + Calendar expireCal = Calendar.getInstance(); + expireCal.setTime(expireDate); + daysFromJan1 = expireCal.get(Calendar.DAY_OF_YEAR) - 1; + } else { + // 正常情况计算计提日到年初的天数 + daysFromJan1 = accrualCal.get(Calendar.DAY_OF_YEAR) - 1; + } //获取购买日相关信息 Calendar buyCal = Calendar.getInstance(); @@ -330,12 +341,12 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu buyCopies = closestRecord.getBigDecimal("e_surpcopies"); //计提日最近估值记录获取——(赎回金额+实际收益)* 所有赎回单 - allRedAmount=this.getRedAmount(dynamicObjectCollection,closestRecord.getDate("e_valuationdate")); - + allRedAmount=this.getRealRevenueAmount(dynamicObjectCollection,closestRecord.getDate("e_valuationdate")); + row.set(DYNAMICS_FIELDS[8], allRedAmount); // 实际收益 //计提日最近估值记录获取——(1-赎回份额/赎回日剩余份额)* 所有赎回单 allRedProductAmount=this.getRedProductAmount(dynamicObjectCollection,closestRecord.getDate("e_valuationdate")); //计算金额(千元) - row.set(DYNAMICS_FIELDS[11],allRedProductAmount.multiply(buyAmount).setScale(8, RoundingMode.HALF_UP)); + row.set(REPORT_FIELDS[17],allRedProductAmount.multiply(buyAmount).setScale(8, RoundingMode.HALF_UP)); } // 设置月末单位净值 @@ -452,7 +463,7 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu } //计算实际收益 - countActRevenueAmt(buyCopies, monthIop, netWorth, row,startBuyCopies,allRedAmount); + //countActRevenueAmt(buyCopies, monthIop, netWorth, row,startBuyCopies,allRedAmount); // 设置结果 row.set(REPORT_FIELDS[5], buyCopies); row.set(REPORT_FIELDS[11], monthIop); @@ -521,6 +532,59 @@ public class FinancialFormReport extends AbstractReportFormPlugin implements Plu return sum; } + /** + * 获取实际收益 + * @param entry 估值分录 + * @param date 填入日期 + * @return + */ + private BigDecimal getRealRevenueAmount(DynamicObjectCollection entry, Date date) { + // 1. 按估值日期和赎回日期排序 + DynamicObjectCollection sortedEntries = new DynamicObjectCollection(); + sortedEntries.addAll(entry); + + sortedEntries.sort((o1, o2) -> { + // 优先按估值日期排序(从小到大) + Date valDate1 = o1.getDate("e_valuationdate"); + Date valDate2 = o2.getDate("e_valuationdate"); + int compareValDate = valDate1.compareTo(valDate2); + if (compareValDate != 0) { + return compareValDate; + } + + // 估值日期相同时,按赎回日期排序 + Date redDate1 = o1.getDate("shjh_shrq"); + Date redDate2 = o2.getDate("shjh_shrq"); + if (redDate1 == null && redDate2 == null) return 0; + if (redDate1 == null) return -1; // null视为较小值 + if (redDate2 == null) return 1; + return redDate1.compareTo(redDate2); + }); + + // 2. 累加符合条件的赎回金额 + BigDecimal sum = BigDecimal.ZERO; + for (DynamicObject item : sortedEntries) { + // 检查是否为赎回单(跳过非赎回条目) + DynamicObject shdh = item.getDynamicObject("shjh_shdh"); + if (shdh == null) { + continue; + } + + // 检查估值日期是否 ≤ 目标日期 + Date valDate = item.getDate("e_valuationdate"); + if (valDate != null && valDate.compareTo(date) <= 0) { + Object pkValue = shdh.getPkValue(); + DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(pkValue, "cim_redeem"); + BigDecimal amount = dynamicObject.getBigDecimal("shjh_realrevenue2"); // 现金管理类收益 + BigDecimal realrevenue = dynamicObject.getBigDecimal("realrevenue"); // 实际收益字段名 + if (amount != null) { + sum = sum.add(amount).add(realrevenue); + } + } + } + + return sum; + } /** * 计提日最近估值记录获取——(1-赎回份额/赎回日剩余份额)* 所有赎回单