diff --git a/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/CdmInterestAccrualPlugin.java b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/CdmInterestAccrualPlugin.java index bb91782..57d94d4 100644 --- a/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/CdmInterestAccrualPlugin.java +++ b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/CdmInterestAccrualPlugin.java @@ -13,7 +13,6 @@ import kd.bos.entity.plugin.args.BeforeOperationArgs; import kd.bos.orm.query.QCP; import kd.bos.orm.query.QFilter; import kd.bos.servicehelper.BusinessDataServiceHelper; -import kd.bos.servicehelper.QueryServiceHelper; import kd.bos.servicehelper.operation.OperationServiceHelper; import kd.bos.servicehelper.operation.SaveServiceHelper; import kd.sdk.plugin.Plugin; @@ -71,11 +70,13 @@ public class CdmInterestAccrualPlugin extends AbstractOperationServicePlugIn imp HashMap dataMap = new HashMap<>(); dataMap.put("issueDate",issueDate); dataMap.put("draftbillexpireDate",draftbillexpireDate); + dataMap.put("billNo",billNo); QFilter filter = new QFilter("entry.srcbillno", QCP.equals, billNo); filter.and("feetype.number",QCP.in, feeTypeNumSet).and("kdsz_pushjx",QCP.not_equals,"B"); //费用明细所需字段 - String FeeBillSelectField = "id,billno,org,feetype,currency,amountrate,payamt,kdsz_pushjx"; + String FeeBillSelectField = "id,billno,org,feetype,currency,amountrate,payamt,oppunittype," + + "oppunit,oppacctbank,oppbebank,kdsz_pushjx"; DynamicObject[] feeBills = BusinessDataServiceHelper.load(FeeBill_KEY, FeeBillSelectField, new QFilter[]{filter}); if (feeBills == null || feeBills.length == 0){ logger.info("应付票据:" + billNo + "没有费用明细需要下推!"); @@ -132,6 +133,7 @@ public class CdmInterestAccrualPlugin extends AbstractOperationServicePlugIn imp DynamicObjectCollection JXBills = new DynamicObjectCollection(); Date issueDate = (Date)dataMap.get("issueDate"); Date draftbillexpireDate = (Date)dataMap.get("draftbillexpireDate"); + String originBillNo = (String)dataMap.get("billNo"); for (DynamicObject feeBill : feeBills) { DynamicObject JXBill = BusinessDataServiceHelper.newDynamicObject(INTERESTACCRUAL_KEY); //参数组装 @@ -140,6 +142,10 @@ public class CdmInterestAccrualPlugin extends AbstractOperationServicePlugIn imp DynamicObject currency = feeBill.getDynamicObject("currency");//币种 BigDecimal amountRate = feeBill.getBigDecimal("amountrate");//费率 BigDecimal feeAmt = feeBill.getBigDecimal("payamt");//费用金额 + String oppUnitType = feeBill.getString("oppunittype");//对方单位类型 + DynamicObject oppUnit = feeBill.getDynamicObject("oppunit");//对方单位 + String oppAcctBank = feeBill.getString("oppacctbank");//对方银行账号 + DynamicObject oppBeBank = feeBill.getDynamicObject("oppbebank");//对方开户行 // 将 Date 转换为 LocalDate(忽略时间部分) LocalDate localIssueDate = issueDate.toInstant() .atZone(ZoneId.systemDefault()) @@ -153,6 +159,7 @@ public class CdmInterestAccrualPlugin extends AbstractOperationServicePlugIn imp BigDecimal payAmt = feeAmt.multiply(new BigDecimal(term)).multiply(amountRate) .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);//付息金额 + JXBill.set("kdsz_originbillno", originBillNo);//票据单号 JXBill.set("billstatus","A"); JXBill.set("org", org);//业务组织 JXBill.set("kdsz_valuedate", issueDate);//计息开始日 @@ -161,6 +168,10 @@ public class CdmInterestAccrualPlugin extends AbstractOperationServicePlugIn imp JXBill.set("kdsz_currency", currency);//付息币别 JXBill.set("kdsz_feerate", amountRate);//费率 JXBill.set("kdsz_totalamount", payAmt);//付息金额 + JXBill.set("kdsz_oppunittype", oppUnitType);//对方单位类型 + JXBill.set("kdsz_oppunit", oppUnit);//对方单位名称 + JXBill.set("kdsz_oppbankacc", oppAcctBank);//对方银行账号 + JXBill.set("kdsz_oppbebank", oppBeBank);//对方开户行 JXBill.set("kdsz_srcentity",FeeBill_KEY);//源单类型 JXBill.set("kdsz_srcbillno",feeBill.getString("billno"));//源单编号 JXBill.set("kdsz_srcbillid",feeBill.getPkValue());//源单id @@ -182,6 +193,7 @@ public class CdmInterestAccrualPlugin extends AbstractOperationServicePlugIn imp //关联费用明细 DynamicObjectCollection billheadLk = JXBill.getDynamicObjectCollection("billhead_lk"); DynamicObject lk = billheadLk.addNew(); + lk.set("seq",1); lk.set("billhead_lk_stableid",FeeBill_TableID); lk.set("billhead_lk_sbillid",feeBill.getPkValue()); lk.set("billhead_lk_sid",feeBill.getPkValue()); diff --git a/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/InterestAccrualGenPaymentOperationPlugin.java b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/InterestAccrualGenPaymentOperationPlugin.java new file mode 100644 index 0000000..48bf913 --- /dev/null +++ b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/InterestAccrualGenPaymentOperationPlugin.java @@ -0,0 +1,274 @@ +package kdsz.zyf25.tmc.cfm.plugin.operate; + +import kd.bos.dataentity.OperateOption; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.EntityMetadataCache; +import kd.bos.entity.ExtendedDataEntity; +import kd.bos.entity.botp.runtime.TableDefine; +import kd.bos.entity.operate.result.IOperateInfo; +import kd.bos.entity.operate.result.OperationResult; +import kd.bos.entity.plugin.AbstractOperationServicePlugIn; +import kd.bos.entity.plugin.AddValidatorsEventArgs; +import kd.bos.entity.plugin.args.BeforeOperationArgs; +import kd.bos.entity.validate.AbstractValidator; +import kd.bos.i18n.mservice.I18nServiceHelper; +import kd.bos.i18n.mservice.utils.AmountConvertResult; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.operation.OperationServiceHelper; +import kd.bos.servicehelper.operation.SaveServiceHelper; +import kd.sdk.plugin.Plugin; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.Date; +import java.util.List; + +/** + * 单据操作插件 + */ +public class InterestAccrualGenPaymentOperationPlugin extends AbstractOperationServicePlugIn implements Plugin { + private static final Logger logger = LoggerFactory.getLogger(InterestAccrualGenPaymentOperationPlugin.class); + private static DynamicObject payBillType = null;//付款单单据类型 + private static DynamicObject payType = null;//付款类型 + private static DynamicObject settleType = null;//结算方式 + private static Long JxBill_TableID = 0L; + static { + TableDefine tableDefine = EntityMetadataCache.loadTableDefine("kdsz_interestaccrual", "kdsz_interestaccrual"); + JxBill_TableID = tableDefine.getTableId(); + payType = BusinessDataServiceHelper.loadSingle("cas_paymentbilltype" + , new QFilter[]{new QFilter("number", QCP.equals, "999")}); + payBillType = BusinessDataServiceHelper.loadSingle("bos_billtype" + , new QFilter[]{new QFilter("number", QCP.equals, "cas_paybill_other_BT_S")}); + settleType = BusinessDataServiceHelper.loadSingle("bd_settlementtype" + , new QFilter[]{new QFilter("number", QCP.equals, "JSFS05")}); + if (payType == null){ + logger.error("未找到编码为【999】的付款类型【其他费用】"); + throw new RuntimeException("未找到编码为【999】的付款类型【其他费用】"); + } + if (payBillType == null){ + logger.error("未找到编码为【cas_paybill_other_BT_S】的付款单类型【其他付款】"); + throw new RuntimeException("未找到编码为【cas_paybill_other_BT_S】的付款单类型【其他付款】"); + } + if (settleType == null){ + logger.error("未找到编码为【JSFS04】的结算方式【电汇(财资)】"); + throw new RuntimeException("未找到编码为【JSFS04】的结算方式【电汇(财资)】"); + } + } + @Override + public void onAddValidators(AddValidatorsEventArgs e) { + e.addValidator(new AbstractValidator() { + @Override + public void validate() { + ExtendedDataEntity[] extBills = this.getDataEntities(); + StringBuilder logInfo = new StringBuilder(); + for (ExtendedDataEntity extBill : extBills) { + DynamicObject bill = extBill.getDataEntity(); + if (!"C".equals(bill.getString("billstatus"))){ + addErrorMessage(extBill, "计息单:"+extBill.getBillNo()+"未审核,不允许下推。\n"); + logInfo.append("计息单:").append(extBill.getBillNo()).append("未审核,不允许下推。\n"); + continue; + } + String selectRowsStr = this.getOption().getVariableValue(bill.getString("id")); + if (selectRowsStr == null || selectRowsStr.length() == 0){ + addErrorMessage(extBill, "计息单:"+extBill.getBillNo()+"请选择要下推的行。\n"); + logInfo.append("计息单:").append(extBill.getBillNo()).append("请选择要下推的行。\n"); + continue; + } + selectRowsStr = StringUtils.deleteWhitespace(selectRowsStr); + selectRowsStr = selectRowsStr.substring(1, selectRowsStr.length() - 1); + String[] selectRowsArray = selectRowsStr.split(","); + int[] selectRows = new int[selectRowsArray.length]; + for (int i = 0; i < selectRows.length; i++) { + selectRows[i] = Integer.parseInt(selectRowsArray[i]); + } + DynamicObjectCollection entries = bill.getDynamicObjectCollection("entryentity"); + for (int selectRow : selectRows) { + DynamicObject entry = entries.get(selectRow); + DynamicObject payBill = entry.getDynamicObject("kdsz_e_paybill"); + if (payBill != null){ + addErrorMessage(extBill, "计息单:"+extBill.getBillNo()+"已生成付款单,不允许下推。\n"); + logInfo.append("计息单:").append(extBill.getBillNo()).append("已生成付款单,不允许下推。\n"); + } + } + } + if (logInfo.length() > 0){ + logger.error(logInfo.toString()); + } + } + }); + } + @Override + public void beforeExecuteOperationTransaction(BeforeOperationArgs e) { + super.beforeExecuteOperationTransaction(e); + DynamicObject[] bills = e.getDataEntities(); + for (DynamicObject bill : bills) { + String billNo = bill.getString("billno"); + String selectRowsStr = this.getOption().getVariableValue(bill.getString("id")); + selectRowsStr = StringUtils.deleteWhitespace(selectRowsStr); + selectRowsStr = selectRowsStr.substring(1, selectRowsStr.length() - 1); + String[] selectRowsArray = selectRowsStr.split(","); + int[] selectRows = new int[selectRowsArray.length]; + for (int i = 0; i < selectRows.length; i++) { + selectRows[i] = Integer.parseInt(selectRowsArray[i]); + } + //生成付款单 + OperationResult result = generatePaymentBill(bill,selectRows); + if (result.isSuccess()){ + logger.info("------计息单:"+billNo+"生成付款单成功"); + writeLkInfo(bill,selectRows,result.getSuccessPkIds().get(0)); + }else { + StringBuilder str = new StringBuilder(); + str.append("生成付款单失败。"); + List allErrorOrValidateInfo = result.getAllErrorOrValidateInfo(); + if (allErrorOrValidateInfo != null){ + str.append("message:\n"); + for (IOperateInfo iOperateInfo : allErrorOrValidateInfo) { + str.append(iOperateInfo.getMessage()).append("\n"); + } + } + logger.error(str.toString()); + e.setCancel( true); + e.setCancelMessage(str.toString()); + } + } + } + + //生成付款单 + private OperationResult generatePaymentBill(DynamicObject JxBill,int[] selectRows){ + DynamicObjectCollection jxEntities = JxBill.getDynamicObjectCollection("entryentity"); + BigDecimal totalAmt = BigDecimal.ZERO; + DynamicObject currency = JxBill.getDynamicObject("kdsz_currency");//付息币种 + DynamicObject payBank = JxBill.getDynamicObject("kdsz_paybank");//付息开户行 + DynamicObject payBankAcc = JxBill.getDynamicObject("kdsz_bankaccnum");//付息银行账号 + DynamicObject oppBeBank = JxBill.getDynamicObject("kdsz_oppbebank");//对方开户银行 + String oppBankAcc = JxBill.getString("kdsz_oppbankacc");//对方银行账号 +// String oppUnitType = JxBill.getString("kdsz_oppunittype");//对方单位类型 + DynamicObject oppUnit = JxBill.getDynamicObject("kdsz_oppunit");//对方单位 + //当前日期 + Date currentDate = Date.from( + LocalDate.now().atStartOfDay() // ① 将LocalDate转换为当天的LocalDateTime (00:00:00) + .atZone(ZoneId.systemDefault()) // ② 添加系统默认时区,得到ZonedDateTime + .toInstant() // ③ 转换为Instant (时间戳) + ); + //创建付款单对象 + DynamicObject payBill = BusinessDataServiceHelper.newDynamicObject("cas_paybill"); + payBill.set("org",JxBill.getDynamicObject("org"));//付款人 + payBill.set("billstatus","A");//单据状态 + payBill.set("currency",currency);//付款币种 + payBill.set("payerbank",payBank);//付款银行 + payBill.set("payeracctbank",payBankAcc);//付款银行账号 + if (oppBeBank != null){ + payBill.set("payeebank",oppBeBank);//收款银行 + payBill.set("payeebankname",oppBeBank.getString("name"));//收款银行名称 + payBill.set("kdsz_textfield2",oppBeBank.getString("name"));//收款银行账户名称 + } + payBill.set("paymenttype",payType);//付款类型 + payBill.set("billtype",payBillType);//单据类型 + payBill.set("payeetype","other");//收款人类型;默认其它 + if (oppUnit != null){ + payBill.set("payeename",oppUnit.getString("name"));//收款人名称 +// payBill.set("payee",supplier.getPkValue());//收款人id + payBill.set("recaccbankname",oppUnit.getString("name"));//收款人实名 + } + payBill.set("payeebanknum",oppBankAcc);//收款账号 + payBill.set("sourcebilltype",JxBill.getDataEntityType().getName());//源单类型 + payBill.set("sourcebillnumber",JxBill.getString("billno"));//源单编号 + payBill.set("sourcebillid",JxBill.getPkValue());//源单id + payBill.set("exchangerate",BigDecimal.ONE);//付款汇率 + payBill.set("priority","public");//紧急程度 默认普通 + payBill.set("paymentchannel","counter");//支付渠道:柜台(默认) + payBill.set("bizdate", currentDate);//业务日期 + payBill.set("settletype",settleType);//结算方式 + payBill.set("kdsz_czpaystatue","1");//财资付款状态 默认无需推送 + DynamicObjectCollection entries = payBill.getDynamicObjectCollection("entry");//付款明细 + for (int i = 0; i < selectRows.length; i++) { + DynamicObject jxEntry = jxEntities.get(selectRows[i]); + BigDecimal principal = jxEntry.getBigDecimal("kdsz_e_principal");//付息本金 + totalAmt = totalAmt.add(principal);//用于表头金额 + DynamicObject entry = entries.addNew(); + entry.set("seq",i + 1); + entry.set("e_payableamt",principal);//应付金额 + entry.set("e_sourcebillid",JxBill.getPkValue());//源单id + entry.set("e_sourcebillentryid",jxEntry.getPkValue());//源单分录id +// entry.set("e_payablelocamt",principal);//应付折本币 +// entry.set("e_actamt",principal);//实付金额 +// entry.set("e_localamt",principal);//实付折本币 +// entry.set("e_unlockamt",principal);//未锁定金额 +// entry.set("e_unsettledamt",principal);//未结算金额 +// entry.set("e_unsettledlocalamt",principal);//未结算金额折本币 + //关联关系 + DynamicObjectCollection entryLks = entry.getDynamicObjectCollection("entry_lk"); + DynamicObject entryLk = entryLks.addNew(); + entryLk.set("seq",1); + entryLk.set("entry_lk_stableid",JxBill_TableID); + entryLk.set("entry_lk_sbillid",JxBill.getPkValue()); + entryLk.set("entry_lk_sid",jxEntry.getPkValue()); + } + payBill.set("actpayamt",totalAmt);//付款金额 +// payBill.set("unsettleamount",totalAmt);//未结算金额 +// payBill.set("unsettleamountbase",totalAmt);//未结算金额(本币) + //金额大写 + String amtStr = totalAmt.toString(); + int index = amtStr.indexOf("."); + if (amtStr.length() > index + 2 ) { + String amt = amtStr.substring(0, index + 3); + //金额大写接口 + AmountConvertResult zhAmtResult = I18nServiceHelper.amountConvertUppercase("ZH", currency.getString("number"), amt, "false"); + if (zhAmtResult.isSuccess()){ + String zhAmt = zhAmtResult.getResult(); + payBill.set("kdsz_daxiejine1",zhAmt); + }else { + logger.error("金额大写转换失败!\n"+zhAmtResult.getErrorMsg()); + throw new RuntimeException("金额大写转换失败!\n"+zhAmtResult.getErrorMsg()); + } + } + return OperationServiceHelper.executeOperate("save","cas_paybill", new DynamicObject[]{payBill}, OperateOption.create()); + } + //反写关联信息 + + private void writeLkInfo(DynamicObject JxBill,int[] selectRows, Object successPkId){ + DynamicObject payBill = BusinessDataServiceHelper.loadSingle(successPkId, "cas_paybill"); + //反写计息单 + DynamicObjectCollection jxEntries = JxBill.getDynamicObjectCollection("entryentity"); + for (int selectRow : selectRows) { + jxEntries.get(selectRow).set("kdsz_e_paybill",payBill); + } + SaveServiceHelper.update(JxBill); + //反写计息的源单 + // TODO: 2025/12/11 暂定为开票登记 +// String payableBillSelectStr = "kdsz_payentry.kdsz_interestbillid,kdsz_payentry.kdsz_paylinkentry," + +// "kdsz_payentry.kdsz_paylinkentry.kdsz_paymentbill,kdsz_payentry.kdsz_paylinkentry.seq," + +// "kdsz_payentry.kdsz_paylinkentry.kdsz_paybillid,kdsz_payentry.kdsz_paylinkentry.kdsz_paybillno," + +// "kdsz_payentry.kdsz_paylinkentry.kdsz_netinterestpaid"; +// DynamicObject[] payableBills = BusinessDataServiceHelper.load("cdm_payablebill", payableBillSelectStr, +// new QFilter[]{new QFilter("kdsz_payentry.kdsz_interestbillid", QCP.equals, JxBill.getPkValue())}); + DynamicObject[] payableBills = BusinessDataServiceHelper.load("cdm_payablebill", "id", + new QFilter[]{new QFilter("kdsz_payentry.kdsz_interestbillid", QCP.equals, JxBill.getPkValue())}); + for (int i = 0; i < payableBills.length; i++) { + payableBills[i] = BusinessDataServiceHelper.loadSingle(payableBills[i].getPkValue(), "cdm_payablebill"); + DynamicObjectCollection payEntries = payableBills[i].getDynamicObjectCollection("kdsz_payentry"); + for (DynamicObject payEntry : payEntries) { + long lk_jxBillId = payEntry.getLong("kdsz_interestbillid"); + long JxId = JxBill.getLong("id"); + if (lk_jxBillId == JxId){ + DynamicObjectCollection payLkEntries = payEntry.getDynamicObjectCollection("kdsz_paylinkentry"); + int size = payLkEntries.size(); + DynamicObject newLkEntry = payLkEntries.addNew(); + newLkEntry.set("seq",size); + newLkEntry.set("kdsz_paymentbill",payBill); + newLkEntry.set("kdsz_paybillno",payBill.getString("billno")); + newLkEntry.set("kdsz_paybillid",payBill.getPkValue()); + newLkEntry.set("kdsz_netinterestpaid",payBill.getBigDecimal("actpayamt")); + } + } + } + SaveServiceHelper.save(payableBills); + } +} \ No newline at end of file