diff --git a/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/report/BankloanreportListPlugin.java b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/report/BankloanreportListPlugin.java new file mode 100644 index 0000000..67eb392 --- /dev/null +++ b/sys/shkd-sys-sys/src/main/java/shkd/sys/sys/plugin/report/BankloanreportListPlugin.java @@ -0,0 +1,374 @@ +package shkd.sys.sys.plugin.report; + +import kd.bos.algo.*; +import kd.bos.algo.input.CollectionInput; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.dataentity.metadata.clr.DataEntityPropertyCollection; +import kd.bos.db.DB; +import kd.bos.db.DBRoute; +import kd.bos.entity.MainEntityType; +import kd.bos.entity.report.AbstractReportListDataPlugin; +import kd.bos.entity.report.FastFilter; +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.portal.util.DateUtils; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.MetadataServiceHelper; +import kd.bos.servicehelper.QueryServiceHelper; +import kd.bos.util.CollectionUtils; +import kd.ssc.task.util.DateUtil; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 报表取数插件 + */ +public class BankloanreportListPlugin extends AbstractReportListDataPlugin { + private static Log log = LogFactory.getLog(BankloanreportListPlugin.class); + + /** + * 以银行账户为主表取查询。 + * 显示所选的核算组织下的所有银行账户的流水 + * + * @param reportQueryParam + * @param o + * @return + * @throws Throwable + */ + @Override + public DataSet query(ReportQueryParam reportQueryParam, Object o) throws Throwable { + HashMap listQFilter = getListQFilter(reportQueryParam); + + //1、查询借款合同基础数据(主数据) + MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType("cfm_loancontractbill"); + String mainDbRouteKey = dataEntityType.getDBRouteKey(); + String selectLoanContarctSql = + "id as loancontractbillid," + + "org.shkd_comcode shkd_comcode," + + "org.shkd_comname shkd_comname," + + "contractno shkd_contractno," + + "org.number shkd_orgnum," + + "org.name shkd_orgname," + + "bizdate shkd_bizdate,"+ + "CASE \n" + + " WHEN finproduct.number = 'RZPZ-0002' OR finproduct.number = 'RZPZ-0019' THEN 'F01'\n" + + " WHEN finproduct.number = 'RZPZ-0036' THEN 'F02'\n" + + " WHEN finproduct.number = 'RZPZ-0026' THEN 'F03'\n" + + " ELSE 'F04'\n" + + "END AS shkd_loankind,"+ + "CASE \n" + + " WHEN guarantee = ',2,' THEN 'C'\n" + + " WHEN guarantee = ',4,' THEN 'B'\n" + + " WHEN guarantee = ',5,' THEN 'A'\n" + + " WHEN guarantee = ',6,' THEN 'Z'\n" + + " WHEN guarantee = ',7,' THEN 'D'\n" + + " ELSE 'E'\n" + + "END AS shkd_guarantee,"+ + "creditortype," + + "loantype," + //借款类型 + "billno as loanContarctBillNo," + + "textcreditor"; + DataSet loanContractBills = QueryServiceHelper.queryDataSet(this.getClass().getSimpleName(), "cfm_loancontractbill", selectLoanContarctSql, new QFilter[0], null); + + //2、查询合作金融机构的数据(基础资料) + String selectFinOrgInfoSql = "id as finorginfoid,number as finorginfonum,name as finorginfoname,finorgtype.number as finorgtypenum"; + DataSet finorginfos = QueryServiceHelper.queryDataSet(this.getClass().getSimpleName(), "bd_finorginfo", selectFinOrgInfoSql, new QFilter[0], null); + + //3、左连接主数据和基础资料数据 + DataSet leftjoinOne = loanContractBills.join(finorginfos, JoinType.LEFT).on("textcreditor", "finorginfoname") + .select("loancontractbillid", "shkd_comcode", "shkd_comname", "shkd_contractno", "shkd_orgnum", "shkd_orgname", "shkd_bizdate", + "shkd_loankind", "shkd_guarantee", "creditortype", "textcreditor","loanContarctBillNo","finorgtypenum","finorginfonum","finorginfoname").finish(); + + //4、添加shkd_internalloan的字段 + DataSet addFieldOne = leftjoinOne.addField("CASE \n" + + " WHEN (creditortype = 'finorg' and finorgtypenum = 'FI-031') or creditortype = 'innerunit' THEN 'T00'\n" + + " ELSE 'T01' END", "shkd_internalloan"); + + //5、查询提款处理单数据(主数据的提款单分录数据) + String selectCfmLoanBillSql = + "id as loanbillid," + + "loancontractbill.number as loanbillContractno," + + "creditortype as loanbillCDtype," + + "textcreditor as shkd_textcreditorname," + + "billno as loanbillBillno," + + "currency.sign as shkd_currency," + + "drawamount as shkd_drawamount," + + "bizdate as shkd_syncdrawdate," + + "term as shkd_syncterm," + + "referencerate.number as referenceratenumber," + //参考利率 + "rateadjustdate," + //首次利率确定日 + "rateadjustcycletype," + //利率重置周期 + "rateadjustcycle," + //利率重置周期值 + "ratesign," + //利率浮动基点(BP) + "ratefloatpoint," + //利率浮动基点 + "startloanrate," + //起息日利率 + "interesttype," + //利率类型 + "convertrate"; //折合同币种汇率 + DataSet loanbills = QueryServiceHelper.queryDataSet(this.getClass().getSimpleName(), "cfm_loanbill", selectCfmLoanBillSql, new QFilter[0], null); + + //6、左连接主数据和提款处理单数据 + RowMeta rowMeta1 = addFieldOne.getRowMeta(); + RowMeta rowMeta2 = loanbills.getRowMeta(); + String[] fieldNames1 = rowMeta1.getFieldNames(); + String[] fieldNames2 = rowMeta2.getFieldNames(); + List selects1 = new ArrayList<>(Arrays.asList(fieldNames1)); + List selects2 = new ArrayList<>(Arrays.asList(fieldNames2)); + selects1.addAll(selects2); + DataSet leftjoin2 = addFieldOne.join(loanbills, JoinType.LEFT).on("shkd_contractno", "loanbillContractno") + .select(selects1.toArray(new String[0])).finish(); + + //7、查找各种可能的债权人(主体关联在提款单) + //a、业务单元 + String selectBosOrgSql = "id as bosorgid,number as bosorgnNum,name as bosorgName,country.name as basorgCountryName"; + DataSet entry_basorgs = QueryServiceHelper.queryDataSet(this.getClass().getSimpleName(), "bos_org", selectBosOrgSql, new QFilter[0], null); + //b、内部金融组织 + String selectFinorginfoSql = "id as finorginfoid,number as finorginfoNum,name as finorginfoName,parent.name finorginfoParentName,country.name as finorginfoCountryName"; + DataSet entry_finorginfos = QueryServiceHelper.queryDataSet(this.getClass().getSimpleName(), "bd_finorginfo", selectFinorginfoSql, new QFilter[0], null); + //c、商务伙伴 + String selectBizpartnerSql = "id as bizpartnerid,number as bizpartnerNum,name as bizpartnerName,country.name as bizpartnerCountryName"; + DataSet entry_bizpartners = QueryServiceHelper.queryDataSet(this.getClass().getSimpleName(), "bd_bizpartner", selectBizpartnerSql, new QFilter[0], null); + + //8、左连接主数据和各种可能的债权人(关联在提款单上) + RowMeta rowMeta3 = leftjoin2.getRowMeta(); + RowMeta rowMeta4 = entry_basorgs.getRowMeta(); + RowMeta rowMeta5 = entry_finorginfos.getRowMeta(); + RowMeta rowMeta6 = entry_bizpartners.getRowMeta(); + String[] fieldNames3 = rowMeta3.getFieldNames(); + String[] fieldNames4 = rowMeta4.getFieldNames(); + String[] fieldNames5 = rowMeta5.getFieldNames(); + String[] fieldNames6 = rowMeta6.getFieldNames(); + List selects3 = new ArrayList<>(Arrays.asList(fieldNames3)); + List selects4 = new ArrayList<>(Arrays.asList(fieldNames4)); + List selects5 = new ArrayList<>(Arrays.asList(fieldNames5)); + List selects6 = new ArrayList<>(Arrays.asList(fieldNames6)); + selects3.addAll(selects4); + DataSet leftjoin3 = leftjoin2.join(entry_basorgs, JoinType.LEFT).on("shkd_textcreditorname", "bosorgName") + .select(selects3.toArray(new String[0])).finish(); + selects3.addAll(selects5); + DataSet leftjoin4 = leftjoin3.join(entry_finorginfos, JoinType.LEFT).on("shkd_textcreditorname", "finorginfoName") + .select(selects3.toArray(new String[0])).finish(); + selects3.addAll(selects6); + DataSet leftjoin5 = leftjoin4.join(entry_bizpartners, JoinType.LEFT).on("shkd_textcreditorname", "bizpartnerName") + .select(selects3.toArray(new String[0])).finish(); + + //9、赋值债权人编码、总行字段,国家 + DataSet addField2 = leftjoin5 + .addField("CASE \n" + + " WHEN loanbillCDtype = 'innerunit' THEN bosorgnNum\n" + + " WHEN (loanbillCDtype = 'finorg' or loanbillCDtype = 'bank' or loanbillCDtype = 'settlecenter') THEN finorginfoNum\n" + + " WHEN loanbillCDtype = 'custom' THEN bizpartnerNum\n" + + " ELSE '' END", "shkd_textcreditornum") + .addField("CASE \n" + + " WHEN loanbillCDtype = 'innerunit' THEN bosorgName\n" + + " WHEN (loanbillCDtype = 'finorg' or loanbillCDtype = 'bank' or loanbillCDtype = 'settlecenter') THEN finorginfoParentName\n" + + " WHEN loanbillCDtype = 'custom' THEN bizpartnerName\n" + + " ELSE '' END", "shkd_textcreditortrc") + .addField("CASE \n" + + " WHEN loanbillCDtype = 'innerunit' THEN basorgCountryName\n" + + " WHEN (loanbillCDtype = 'finorg' or loanbillCDtype = 'bank' or loanbillCDtype = 'settlecenter') THEN finorginfoCountryName\n" + + " WHEN loanbillCDtype = 'custom' THEN bizpartnerCountryName\n" + + " ELSE '' END", "shkd_country") + .addField("null", "shkd_loanrate")//利率水平 + .addField("null", "shkd_amountoricur")//贷款余额(原币) + .addField("null", "shkd_amountbencur");//贷款余额(本币) + + //10、赋值利率水平、贷款余额(原币)、贷款余额(本币) + DynamicObjectCollection plainDynamicObjectCollection = ORM.create().toPlainDynamicObjectCollection(addField2); + Date shkdSelectdate = (Date)listQFilter.get("shkd_selectdate"); + if(shkdSelectdate == null) shkdSelectdate = new Date(); + for (DynamicObject dataRow : plainDynamicObjectCollection) { + String referenceratenumber = dataRow.getString("referenceratenumber");//参考利率 + Date rateadjustdate = dataRow.getDate("rateadjustdate");//首次利率确定日 + BigDecimal shkdDrawamount = dataRow.getBigDecimal("shkd_drawamount");//提款金额 + String loanbillBillno = dataRow.getString("loanbillBillno");//提款单编码 + String rateadjustcycletype = dataRow.getString("rateadjustcycletype");//利率重置周期 + Integer rateadjustcycle = dataRow.getInt("rateadjustcycle");//利率重置周期值 + String ratesign = dataRow.getString("ratesign");//利率浮动基点(BP) + BigDecimal ratefloatpoint = dataRow.getBigDecimal("ratefloatpoint");//利率浮动基点 + BigDecimal startloanrate = dataRow.getBigDecimal("startloanrate");//起息日利率 + String interesttype = dataRow.getString("interesttype");//利率类型 + BigDecimal convertrate = dataRow.getBigDecimal("convertrate");//折合同币种汇率 + + //赋值利率 + if ("fixed".equals(interesttype)){ + //固定利率 直接赋值startloanrate + dataRow.set("shkd_loanrate", startloanrate); + }else if ("float".equals(interesttype)){ + //浮动利率 + //计算利率周期 + Calendar calendar = Calendar.getInstance(); + calendar.setTime(rateadjustdate); + switch (rateadjustcycletype){ + case "D": calendar.add(Calendar.DAY_OF_MONTH, rateadjustcycle); + break; + case "W": calendar.add(Calendar.DAY_OF_MONTH, rateadjustcycle * 7); + break; + case "M": calendar.add(Calendar.MONTH, rateadjustcycle); + break; + case "S": calendar.add(Calendar.MONTH, rateadjustcycle * 3); + break; + case "H": calendar.add(Calendar.MONTH, rateadjustcycle * 6); + break; + case "Y": calendar.add(Calendar.YEAR, rateadjustcycle); + break; + default: break; + } + Date enddate = calendar.getTime(); + + // 比较 shkdSelectdate 和 enddate + DynamicObject dateRate = new DynamicObject(); + if (shkdSelectdate != null) { + int comparison = shkdSelectdate.compareTo(enddate); + if (comparison > 0) { + // shkdSelectdate 在 enddate 之后 + QFilter qFilter = new QFilter("referrate.number","=",referenceratenumber); + DynamicObject[] cfm_loanbill_bond = BusinessDataServiceHelper.load("md_datarate","endprice",qFilter.toArray(), "bizdate DESC"); + if (cfm_loanbill_bond.length > 0) { + dateRate = cfm_loanbill_bond[0]; + } + } else { + // shkdSelectdate 在 enddate 之前 或者 shkdSelectdate 与 enddate 相等 + QFilter qFilter = new QFilter("referrate.number","=",referenceratenumber); + qFilter.and("bizdate","<=",shkdSelectdate); + DynamicObject[] cfm_loanbill_bond = BusinessDataServiceHelper.load("md_datarate","endprice",qFilter.toArray(), "bizdate DESC"); + if (cfm_loanbill_bond.length > 0) { + dateRate = cfm_loanbill_bond[0]; + } + } + } + + //计算利率 + BigDecimal endprice = dateRate.getBigDecimal("endprice"); + BigDecimal shkd_loanrate = BigDecimal.ZERO; + if (endprice == null){ + endprice = BigDecimal.ZERO; + } + if ("add".equals(ratesign)){ + shkd_loanrate = endprice.add(ratefloatpoint.multiply(BigDecimal.valueOf(0.01))); + }else if ("subtract".equals(ratesign)){ + shkd_loanrate = endprice.subtract(ratefloatpoint.multiply(BigDecimal.valueOf(0.01))); + } + dataRow.set("shkd_loanrate", shkd_loanrate); + } + + //赋值贷款余额(原币)、贷款余额(本币) + BigDecimal totalAmount = BigDecimal.ZERO; + DynamicObjectCollection repaymentbill = QueryServiceHelper.query("cfm_repaymentbill", "billno,amount", new QFilter("loans.e_loanbill.number", "=", loanbillBillno).and("bizdate","<=",shkdSelectdate).and("billstatus","=","C").toArray()); + if (repaymentbill != null && repaymentbill.size() > 0) { + // 按 billno 分组,取每组第一条记录 + Map groupedRepayments = new LinkedHashMap<>(); + for (DynamicObject repayment : repaymentbill) { + String billno = repayment.getString("billno"); + // 如果该 billno 还未添加到 map 中,则添加(这样保证取的是第一条记录) + if (!groupedRepayments.containsKey(billno)) { + groupedRepayments.put(billno, repayment); + } + } + // 计算所有分组的 amount 合计 + for (DynamicObject repayment : groupedRepayments.values()) { + BigDecimal amount = repayment.getBigDecimal("amount"); + if (amount != null) { + totalAmount = totalAmount.add(amount); + } + } + } + BigDecimal shkd_amountoricur = shkdDrawamount.subtract(totalAmount); + dataRow.set("shkd_amountoricur", shkd_amountoricur); + dataRow.set("shkd_amountbencur", shkd_amountoricur.multiply(convertrate)); + } + + //根据已结清标识符过滤数据 + Boolean shkd_beensettled = (Boolean)listQFilter.get("shkd_beensettled"); + if (Boolean.FALSE.equals(shkd_beensettled) || shkd_beensettled == null) { + // 执行过滤已结清数据的逻辑 + Iterator iterator = plainDynamicObjectCollection.iterator(); + while (iterator.hasNext()) { + DynamicObject dataRow = iterator.next(); + BigDecimal shkd_amountoricur = dataRow.getBigDecimal("shkd_amountoricur"); + if (shkd_amountoricur == null || (shkd_amountoricur != null && shkd_amountoricur.compareTo(BigDecimal.ZERO) <= 0)) { + iterator.remove(); // 移除已结清的数据 + } + } + } + + // 创建一个空的DataSet 将DynamicObjectCollection转化为DataSet + Collection coll = new ArrayList<>();//报表展示数据 + // 遍历修改后的数据的所有字段 + List displayFields = new ArrayList<>();//列标识 + DynamicObject object = plainDynamicObjectCollection.get(0); + DataEntityPropertyCollection properties = object.getDataEntityType().getProperties(); + // 获取所有字段 + properties.forEach(property -> displayFields.add(property.getName())); + log.info("displayFields列标识:{}", displayFields); + for (DynamicObject dataRow : plainDynamicObjectCollection) { + // 将数据放入数组 + Object[] objects = new Object[displayFields.size()]; + for (int i = 0; i < displayFields.size(); i++) { + objects[i] = dataRow.get(displayFields.get(i)); + } + coll.add(objects); + } + + // 创建一个空的DataSet 将DynamicObjectCollection转化为DataSet + DataType stringType = DataType.StringType; + DataType dateType = DataType.DateType; + DataType bigDecimalType = DataType.BigDecimalType; +// DataType integerType = DataType.IntegerType; + List dataTypes = new ArrayList<>();//列标识 + + for (String field : displayFields) { + if (field.contains("shkd_syncdrawdate") || field.contains("shkd_bizdate")) { + dataTypes.add(dateType); + } else if (field.contains("shkd_drawamount") || field.contains("shkd_loanrate") || "shkd_amountoricur".equals(field) || "shkd_amountbencur".equals(field)) { + dataTypes.add(bigDecimalType); + } else { + dataTypes.add(stringType); + } + } + log.info("dataTypes数据类型:{}", dataTypes); + + + RowMeta rowMeta = RowMetaFactory.createRowMeta(displayFields.toArray(new String[0]), dataTypes.toArray(new DataType[0])); + CollectionInput inputs = new CollectionInput(rowMeta, coll); + + try { + addField2 = Algo.create(this.getClass().getName()).createDataSet(inputs); + } catch (Exception e) { + log.error("数据集创建失败:{}", e.getMessage()); + } + + return addField2; + } + + + /** + * 获取报表所有过滤条件 + * + * @param reportQueryParam + * @return + */ + public HashMap getListQFilter(ReportQueryParam reportQueryParam) { + //过滤条件数组 + HashMap filterMaps = new HashMap<>(); + //初始化过滤数据 + List filterItems = reportQueryParam.getFilter().getFilterItems(); + if (CollectionUtils.isNotEmpty(filterItems)) { + for (FilterItemInfo info : filterItems) { + filterMaps.put(info.getPropName(),info.getValue()); + } + } + return filterMaps; + } + + +} \ No newline at end of file