1、票据管理:开票/收票登记、开票申请,票据类型根据单据发布应用决定票据类型过滤、默认票据类型BUG处理
2、开票登记触发下推计息单,下推反写开票登记、费用明细 3、计息单删除校验及删除上游两表关联记录
This commit is contained in:
parent
4af45886af
commit
b5c75191ee
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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<String> 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<String, Object> 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<Object> 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<IOperateInfo> 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<String,Object> 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<HashMap<String, Date>> dateList = genJXEntry(issueDate, draftbillexpireDate);
|
||||
int monthCount = dateList.size();
|
||||
int seq = entries.size();
|
||||
for (HashMap<String, Date> 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<HashMap<String,Date>> genJXEntry(Date start, Date end) {
|
||||
ArrayList<HashMap<String,Date>> 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<String, Date> 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<Object> 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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Long> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue