凭证反写开发案例原创
金蝶云社区-陈来珍
陈来珍
9人赞赏了该文章 4,129次浏览 未经作者许可,禁止转载编辑于2021年11月29日 15:18:44
summary-icon摘要由AI智能服务提供

本文介绍了在业务单据(如采购申请单)生成凭证时,实时反写单据上“是否已生成凭证”及凭证号字段的实现方案。首先,通过编写一个反写插件,继承并实现相关方法以指定数据库路由、获取凭证启用/禁用状态及需反写的字段名。然后,注册该插件至系统配置中,使其与单据审核后的凭证生成操作关联。最后,扩展了插件的writeBack方法,以在生成或删除凭证时,将凭证状态及凭证号实时反写回采购申请单上,实现单据与凭证信息的同步更新。

一、需求背景

      在业务单据生成凭证的时候需要实时反写业务单据是否生成了凭证,这里以采购申请单生成凭证时实时反写采购申请单上的“是否已生成凭证号”字段为是;或者反写凭证号字段到单据上(采购申请单是业务无关的单据,仅仅是为了说明案例使用)

二、实现方案

31.png

1、编写反写插件

(1)反写插件继承 bos-ext-fi 下面的 kd.bos.ext.fi.ai.AbstractDapWriteBackImpl实现以下四个方法

public class DapconfigDemoPlugin extends AbstractDapWriteBackImpl {
    @Override
    protected DBRoute getDBRoute() {
       //用DBRoute对应具体的物理库,由mc的数据中心管理进行配置。
//secd是采购申请单物理表所在的库名,扩展开发库
       DBRoute DBR = DBRoute.of("secd");
       return DBR;
    }
    @Override//删除凭证写入的值这里是复选框- 布尔false
    protected Object getVchDisableStatus() {
       Boolean disRchValue=false;
       return disRchValue;
    }
    @Override//生成凭证时写入的值,这里是复选框- 布尔 true。
    protected Object getVchEnableStatus() {
       Boolean rchValue=true;
       return rchValue;
    }
    @Override//要反写的字段的字段名-是否已反写凭证
    protected String getVchStatusField() {
       String vchField="fk_sunp_ifvoucher";
       return vchField;
    }
}

(2mc分库标识

32.png

2、插件注册

开发平台搜索“dap配置”或者ai_dapconfig

33.png

配置上面二开实现的反写插件,关联操作audit指单据审核之后才能进行凭证生成的操作

34.png

3、扩展-凭证号反写:

        实现完上面1-2的操作之后,AbstractDapWriteBackImplwriteBack方法会被调用执行,而writeBack会调用到我们二开重写的方法getVchStatusField()getVchEnableStatus()DB.execute(getDBRoute(), "update "+mt.getAlias()+" set "+getVchStatusField()+" = ? where fid in ("+StringUtils.join(cache.toArray(), ',')+")", new Object[]{getVchEnableStatus()});

本案例二开重写的四个方法,只能实时反写修改采购申请单上面某个字段的值=某个常量,以此来判断采购申请单是否已生成了凭证,如果需要对应反写凭证号回采购申请单,可以重写writeBack方法:实现生成凭证时反写采购申请单上的凭证号字段,删除凭证时删除采购申请单上的凭证号

operation:执行的操作,生成凭证、删除凭证等

②billEntityNumber:执行生成凭证的单据的单据标识,这里是采购申请单的单据标识

③billToVch:单据编号和凭证号的映射信息

public void writeBack(VoucherOperation operation, String billEntityNumber, Map<Long, Voucher> billToVch)

    如果实现了凭证号反写,根据采购申请单上是否反写了凭证号就可以判断是否生成了凭证号,就没必要再在getVchStatusField()getVchEnableStatus()方法中设置反写是否已生成凭证号的字段了。(这里为了看效果,都实现了)

@Override
	public void writeBack(VoucherOperation operation, String billEntityNumber, Map<Long, Voucher> billToVch) {
		MainEntityType mt = EntityMetadataCache.getDataEntityType(billEntityNumber);
		Set<Long> keySet = billToVch.keySet();
		if (VoucherOperation.Create.equals(operation)) {
			//#开始执行生成凭证反写:"
			Object vchStatusField = getVchEnableStatus();
			List<Object[]> params = new ArrayList<>();
			for (Long me : keySet) {
				//#生成凭证的单据ID
				Voucher voucher=billToVch.get(me);//凭证
				String voucherNo = voucher.getVoucherNo();
				//这里处理的是一个单据只有一个凭证的时候,如果是多个凭证,可以先获取已经生成的凭证号,再拼接上字符串。
				Object[] param = new Object[] { vchStatusField,voucherNo, me };//
				params.add(param);
				if (params.size() >= 10000) {
					//#开始执行生成凭证反写SQL
					DB.executeBatch(getDBRoute(),
							"update " + mt.getAlias() + " set " + getVchStatusField() + " = ? , "+voucherNoFile+" = ? where fid = ?", params);
					//#结束执行生成凭证反写SQL
					params.clear();
				}
			}
			//#最后#开始执行生成凭证反写SQL
			if (params.size() > 0) {
				DB.executeBatch(getDBRoute(),
						"update " + mt.getAlias() + " set " + getVchStatusField() + " = ?  , "+voucherNoFile+" = ? where fid = ?", params);
			}
			//#最后#结束执行生成凭证反写SQL
		} else if (VoucherOperation.Delete.equals(operation)) {
			//#开始执行删除凭证反写
			Object vchDisableStatus = getVchDisableStatus();
			List<Object[]> params = new ArrayList<>();
			for (Long me : keySet) {
				log.info("AbstractDapWriteBackImpl#删除凭证的单据ID:" + me);
				//这里处理的是一个单据只有一个凭证的时候,如果是多个凭证,可以先获取已经生成的凭证号,再去掉本凭证之后的凭证号
				Object[] param = new Object[] {vchDisableStatus, "",me };// getVchDisableStatus
				params.add(param);
				if (params.size() >= 10000) {
					//#开始执行删除凭证反写SQL
					DB.executeBatch(getDBRoute(),
							"update " + mt.getAlias() + " set " + getVchStatusField() + " = ?  , "+voucherNoFile+" = ? where fid = ?", params);
					params.clear();
					//#结束执行删除凭证反写SQL
				}
			}
			//#最后#开始执行删除凭证反写SQL
			if (params.size() > 0) {
				DB.executeBatch(getDBRoute(),
						"update " + mt.getAlias() + " set " + getVchStatusField() + " = ? , "+voucherNoFile+" = ? where fid = ?", params);
			}
			//#最后#结束执行删除凭证反写SQL
		}
	}

三、实现效果

1、点击生成凭证,会弹出生成的凭证,退出凭证,刷新采购申请单,可以看到“是否已生成凭证已被反写修改为“是”;凭证号已被反写回采购申请单上。

35.png

36.png



赞 9