diff --git a/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/form/cdm/CdmBillTypeBillPlugin.java b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/form/cdm/CdmBillTypeBillPlugin.java index 20fdbf3..fb6b077 100644 --- a/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/form/cdm/CdmBillTypeBillPlugin.java +++ b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/form/cdm/CdmBillTypeBillPlugin.java @@ -38,15 +38,10 @@ public class CdmBillTypeBillPlugin extends AbstractBillPlugIn implements Plugin, String appId = showParameter.getAppId(); //信用证、供应链金融 票据类型赋默认值 String billTypeNum = ""; - switch (appId){ - //信用证 - case TYPE_XYZ: - billTypeNum = XZY_NUM; - break; - //供应链金融 - case TYPE_GYL: - billTypeNum = GYL_NUM; - break; + if (TYPE_XYZ.equals(appId)){ + billTypeNum = XZY_NUM; + } else if (TYPE_GYL.equals(appId)) { + billTypeNum = GYL_NUM; } if (StringUtils.isNotBlank(billTypeNum)){ DynamicObject billType = BusinessDataServiceHelper.loadSingle("cdm_billtype", "id", 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 new file mode 100644 index 0000000..6abaa79 --- /dev/null +++ b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/CdmInterestAccrualPlugin.java @@ -0,0 +1,247 @@ +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.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.PreparePropertysEventArgs; +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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.YearMonth; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; +import java.util.*; + +/** + * 票据管理计息 + */ +public class CdmInterestAccrualPlugin extends AbstractOperationServicePlugIn implements Plugin { + private static final Logger logger = LoggerFactory.getLogger(CdmInterestAccrualPlugin.class); + private static HashSet feeTypeNumSet = new HashSet<>(); + private static final String FeeBill_KEY = "cfm_feebill";//费用明细标识 + private static final String INTERESTACCRUAL_KEY = "kdsz_interestaccrual";//计息单标识 + private static Long FeeBill_TableID = 0L; + static { + feeTypeNumSet.add("FY_011"); + feeTypeNumSet.add("FY_012"); + feeTypeNumSet.add("FY_013"); + TableDefine tableDefine = EntityMetadataCache.loadTableDefine("cfm_feebill", "cfm_feebill"); + FeeBill_TableID = tableDefine.getTableId(); + } + @Override + public void onPreparePropertys(PreparePropertysEventArgs e) { + super.onPreparePropertys(e); + e.getFieldKeys().add("billno"); + e.getFieldKeys().add("issuedate"); + e.getFieldKeys().add("draftbillexpiredate"); + e.getFieldKeys().add("kdsz_payentry.kdsz_interestbill"); + e.getFieldKeys().add("kdsz_payentry.kdsz_interestbillno"); + e.getFieldKeys().add("kdsz_payentry.kdsz_interestbillid"); + e.getFieldKeys().add("kdsz_payentry.kdsz_interestbillstatus"); + e.getFieldKeys().add("kdsz_payentry.kdsz_valuedate"); + e.getFieldKeys().add("kdsz_payentry.kdsz_settledate"); + e.getFieldKeys().add("kdsz_payentry.kdsz_paydate"); + } + + @Override + public void beforeExecuteOperationTransaction(BeforeOperationArgs e) { + super.beforeExecuteOperationTransaction(e); + DynamicObject[] bills = e.getDataEntities(); + for (DynamicObject bill : bills) { + String billNo = bill.getString("billno"); + Date issueDate = bill.getDate("issuedate");//出票日 + Date draftbillexpireDate = bill.getDate("draftbillexpiredate");//票据到期日 + //生成计息单除费用明细外的参数 + HashMap dataMap = new HashMap<>(); + dataMap.put("issueDate",issueDate); + dataMap.put("draftbillexpireDate",draftbillexpireDate); + + 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"; + DynamicObject[] feeBills = BusinessDataServiceHelper.load(FeeBill_KEY, FeeBillSelectField, new QFilter[]{filter}); + if (feeBills == null || feeBills.length == 0){ + logger.info("应付票据:" + billNo + "没有费用明细无需下推!"); + continue; + } + OperationResult result = genJXBill(dataMap,feeBills); + if (result.isSuccess()){ + List successPkIds = result.getSuccessPkIds(); + if (successPkIds.size() == feeBills.length){ + logger.info("应付票据:" + billNo + "下推计息单成功!"); + DynamicObjectCollection payEntries = bill.getDynamicObjectCollection("kdsz_payentry"); + int size = payEntries.size(); + //开票登记(应付票据)记录下推信息 + for (Object successPkId : successPkIds) { + DynamicObject jxBill = BusinessDataServiceHelper.loadSingle(successPkId, INTERESTACCRUAL_KEY); + if (jxBill == null)continue; + DynamicObject payEntry = payEntries.addNew(); + payEntry.set("seq", ++size); + payEntry.set("kdsz_interestbill",successPkId); + payEntry.set("kdsz_interestbillno",jxBill.getString("billno")); + payEntry.set("kdsz_interestbillid",successPkId); +// payEntry.set("",); +// payEntry.set("",); +// payEntry.set("",); + } + SaveServiceHelper.save(new DynamicObject[]{bill}); + for (DynamicObject feeBill : feeBills) { + feeBill.set("kdsz_pushjx", "B"); + } + SaveServiceHelper.update(feeBills); + } +// else { +// //部分生成则删除 +// OperationResult deleteResult = deleteBills(successPkIds); +// if (!deleteResult.isSuccess()){ +// logger.info("应付票据:" + billNo + "下推计息单部分成功的单据删除失败!"); +// }else { +// logger.info("应付票据:" + billNo + "下推计息单部分成功的单据删除成功!"); +// } +// } + }else { + List errors = result.getAllErrorOrValidateInfo(); + StringBuilder errorStr = new StringBuilder(); + for (IOperateInfo error : errors) { + String message = error.getMessage(); + errorStr.append(message).append("\n"); + } + logger.error("应付票据:" + billNo + "下推计息单失败!\n" + errorStr); + } + } + } + + private OperationResult genJXBill(HashMap dataMap,DynamicObject[] feeBills) { + DynamicObjectCollection JXBills = new DynamicObjectCollection(); + Date issueDate = (Date)dataMap.get("issueDate"); + Date draftbillexpireDate = (Date)dataMap.get("draftbillexpireDate"); + for (DynamicObject feeBill : feeBills) { + DynamicObject JXBill = BusinessDataServiceHelper.newDynamicObject(INTERESTACCRUAL_KEY); + //参数组装 + DynamicObject org = feeBill.getDynamicObject("org");//组织 + DynamicObject feeType = feeBill.getDynamicObject("feetype");//费用类型 + DynamicObject currency = feeBill.getDynamicObject("currency");//币种 + BigDecimal amountRate = feeBill.getBigDecimal("amountrate");//费率 + BigDecimal feeAmt = feeBill.getBigDecimal("payamt");//费用金额 + // 将 Date 转换为 LocalDate(忽略时间部分) + LocalDate localIssueDate = issueDate.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + + LocalDate localExpireDate = draftbillexpireDate.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + // 计算天数差 + long term = Math.abs(ChronoUnit.DAYS.between(localIssueDate, localExpireDate)); + BigDecimal payAmt = feeAmt.multiply(new BigDecimal(term)).multiply(amountRate) + .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);//付息金额 + + JXBill.set("billstatus","A"); + JXBill.set("org", org);//业务组织 + JXBill.set("kdsz_valuedate", issueDate);//计息开始日 + JXBill.set("kdsz_maturitydate", draftbillexpireDate);//计息结束日 + JXBill.set("kdsz_feetype", feeType);//费用类型 + JXBill.set("kdsz_currency", currency);//付息币别 + JXBill.set("kdsz_feerate", amountRate);//费率 + JXBill.set("kdsz_totalamount", payAmt);//付息金额 + JXBill.set("kdsz_srcentity",FeeBill_KEY);//源单类型 + JXBill.set("kdsz_srcbillno",feeBill.getString("billno"));//源单编号 + JXBill.set("kdsz_srcbillid",feeBill.getPkValue());//源单id + //生成按月计息明细 + DynamicObjectCollection entries = JXBill.getDynamicObjectCollection("entryentity"); + ArrayList> dateList = genJXEntry(issueDate, draftbillexpireDate); + int monthCount = dateList.size(); + int seq = entries.size(); + for (HashMap map : dateList) { + Date startDate = map.get("start"); + Date endDate = map.get("end"); + DynamicObject entry = entries.addNew(); + entry.set("seq", ++seq); + entry.set("kdsz_e_valuedate",startDate); + entry.set("kdsz_e_maturitydate",endDate); + entry.set("kdsz_e_principal",payAmt.divide(new BigDecimal(monthCount),2, RoundingMode.HALF_UP)); + entry.set("kdsz_e_feerate",amountRate); + } + //关联费用明细 + DynamicObjectCollection billheadLk = JXBill.getDynamicObjectCollection("billhead_lk"); + DynamicObject lk = billheadLk.addNew(); + lk.set("billhead_lk_stableid",FeeBill_TableID); + lk.set("billhead_lk_sbillid",feeBill.getPkValue()); + lk.set("billhead_lk_sid",feeBill.getPkValue()); + JXBills.add(JXBill); + } + if (JXBills.size() > 0){ + DynamicObject[] JXBillArray = JXBills.toArray(new DynamicObject[0]); + return OperationServiceHelper.executeOperate("save", INTERESTACCRUAL_KEY, JXBillArray, OperateOption.create()); + } + OperationResult failResult = new OperationResult(); + failResult.setSuccess(false); + return failResult; + } + private ArrayList> genJXEntry(Date start, Date end) { + ArrayList> dateList = new ArrayList<>(); + LocalDate startDate = start.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + LocalDate endDate = end.toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDate(); + if (startDate == null || endDate == null || startDate.isAfter(endDate)) { + return dateList; + } + LocalDate currentStart = startDate; + while (currentStart.isBefore(endDate) || currentStart.isEqual(endDate)) { + HashMap map = new HashMap<>(); + // 获取当前月份的最后一天 + YearMonth currentMonth = YearMonth.from(currentStart); + LocalDate monthEnd = currentMonth.atEndOfMonth(); + // 如果月份结束日期大于结束日期,则使用结束日期 + LocalDate rangeEnd = monthEnd.isBefore(endDate) ? monthEnd : endDate; + map.put("start", Date.from(currentStart.atStartOfDay() + .atZone(ZoneId.systemDefault()) + .toInstant())); + map.put("end", Date.from(rangeEnd.atStartOfDay() + .atZone(ZoneId.systemDefault()) + .toInstant())); + dateList.add(map); + // 下一段从下个月的第一天开始 + currentStart = rangeEnd.plusDays(1); + // 如果已经到达结束日期,退出循环 + if (rangeEnd.isEqual(endDate)) { + break; + } + } + return dateList; + } + + private OperationResult deleteBills(List ids) { + OperationResult result = new OperationResult(); + if (ids == null || ids.size() == 0){ + result.setSuccess(false); + return result; + } + DynamicObject[] deleteBills = BusinessDataServiceHelper.load(INTERESTACCRUAL_KEY, "id", + new QFilter[]{new QFilter("id", QCP.in, ids)}); + for (int i = 0; i < deleteBills.length; i++) { + deleteBills[i] = BusinessDataServiceHelper.loadSingle(deleteBills[i].getPkValue(), INTERESTACCRUAL_KEY); + } + return OperationServiceHelper.executeOperate("delete", INTERESTACCRUAL_KEY, deleteBills, OperateOption.create()); + } +} \ No newline at end of file diff --git a/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/InterestAccrualDeletePlugin.java b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/InterestAccrualDeletePlugin.java new file mode 100644 index 0000000..9f1c549 --- /dev/null +++ b/code/tmc/kdsz-zyf25-tmc-cfm/src/main/java/kdsz/zyf25/tmc/cfm/plugin/operate/InterestAccrualDeletePlugin.java @@ -0,0 +1,88 @@ +package kdsz.zyf25.tmc.cfm.plugin.operate; + +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.entity.ExtendedDataEntity; +import kd.bos.entity.filter.QFilterDto; +import kd.bos.entity.plugin.AbstractOperationServicePlugIn; +import kd.bos.entity.plugin.AddValidatorsEventArgs; +import kd.bos.entity.plugin.PreparePropertysEventArgs; +import kd.bos.entity.plugin.args.AfterOperationArgs; +import kd.bos.entity.validate.AbstractValidator; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.operation.SaveServiceHelper; +import kd.sdk.plugin.Plugin; + +import java.util.HashSet; + +/** + * 计息单删除校验以及反写上游开票登记、费用明细下推状态 + */ +public class InterestAccrualDeletePlugin extends AbstractOperationServicePlugIn implements Plugin { + @Override + public void onPreparePropertys(PreparePropertysEventArgs e) { + super.onPreparePropertys(e); + e.getFieldKeys().add("kdsz_srcentity"); + e.getFieldKeys().add("kdsz_srcbillid"); + e.getFieldKeys().add("id"); + e.getFieldKeys().add("entryentity.kdsz_e_paybill"); + } + + @Override + public void onAddValidators(AddValidatorsEventArgs e) { + e.addValidator(new AbstractValidator() { + @Override + public void validate() { + ExtendedDataEntity[] extBills = this.getDataEntities(); + for (ExtendedDataEntity extBill : extBills) { + DynamicObject bill = extBill.getDataEntity(); + DynamicObjectCollection entries = bill.getDynamicObjectCollection("entryentity"); + for (DynamicObject entry : entries) { + DynamicObject payBill = entry.getDynamicObject("kdsz_e_paybill"); + if (payBill != null) { + addErrorMessage(extBill, "计息单:"+extBill.getBillNo()+"已生成付款单,不允许删除"); + } + } + } + } + }); + } + + @Override + public void afterExecuteOperationTransaction(AfterOperationArgs e) { + super.afterExecuteOperationTransaction(e); + DynamicObject[] bills = e.getDataEntities(); + for (DynamicObject bill : bills) { + String srcEntity = bill.getString("kdsz_srcentity"); + Object srcBillId = bill.get("kdsz_srcbillid"); + DynamicObject feeBill = BusinessDataServiceHelper.loadSingle(srcBillId, srcEntity); + if (feeBill != null) { + feeBill.set("kdsz_pushjx","A"); + SaveServiceHelper.update(feeBill); + DynamicObjectCollection feeEntries = feeBill.getDynamicObjectCollection("entry"); + HashSet srcBillIds = new HashSet<>(); + for (DynamicObject feeEntry : feeEntries) { + long pjId = feeEntry.getLong("srcbillid"); + srcBillIds.add(pjId); + } + QFilter filter = new QFilter("id", "in", srcBillIds); + // TODO: 2025/12/10 暂时定为开票登记 + DynamicObject[] srcBills = BusinessDataServiceHelper.load("cdm_payablebill", + "id,kdsz_payentry.kdsz_interestbillid", new QFilter[]{filter}); + for (DynamicObject srcBill : srcBills) { + DynamicObjectCollection srcPayEntries = srcBill.getDynamicObjectCollection("kdsz_payentry"); + for (int i = srcPayEntries.size() - 1; i > 0 ; i--) { + DynamicObject srcPayEntry = srcPayEntries.get(i); + long srcJXBillId = srcPayEntry.getLong("kdsz_interestbillid"); + long id = bill.getLong("id"); + if (srcJXBillId == id){ + srcPayEntries.remove( i); + } + } + } + SaveServiceHelper.save(srcBills); + } + } + } +} \ No newline at end of file