需求背景
业务代码在对下游单据进行处理时,常常需要找到源头的核心单据(例如订单),根据核心单据的数据状态等信息,决定业务逻辑。
核心单据和下游单据之间,经过了多次的单据转换(如A -> B -> C -> D ->…)。很不幸,在当前需要处理的下游单据上,并没有冗余字段记录源头核心单据的信息,无法通过本单上的字段值找到源单。
每次执行单据转换时,平台都会在后台自动记录单据之间的关联关系,并提供了相应的服务接口,查询各单之间的关系。上述需求,可以通过平台提供的服务接口实现。
说明:正因为平台会在后台自动记录单据之间的关联关系,在设计下游单据时,其实不需要考虑冗余太多字段,一层层携带、记录源头核心单据信息。
本章介绍如何使用平台提供的服务接口,搜索源单。
案例设计
假设源头核心单据是demo_botp1,当前处理的下游单据是demo_botp3:
demo_botp1 下推生成 demo_botp2;
demo_botp2 接着下推生成 demo_botp3;
当前正在审核demo_botp3,需要找到源头的demo_botp1;
相关知识点
BFTrackerServiceHelper:平台封装的单据关联关系追踪服务,可以搜索源单、搜索目标单、搜索分录行的关联追溯树;
示例代码
案例实现思路:
开发单据demo_botp3的审核操作插件,派生自AbstractOperationServicePlugIn;
重写beforeExecuteOperationTransaction方法,此方法在操作校验通过,开启事务保护前触发,可以在此事件中,检查、整理数据;
调用BFTrackerServiceHelper服务方法,传入本单主实体编码和单据内码,搜索本单的全部源单;从中获取需要查找的源单demo_botp1;
根据取到的源头demo_botp1单据内码,进行后续处理。
特别说明:
本示例使用的BFTrackerServiceHelper.findSourceBills只是整体搜索出所有源单,未区分各单直接的对应关系,这在批量处理时会有限制。如果需要准确区分各单对应关系,需要使用BFTrackerServiceHelper.loadLinkUpNodes获取行级追溯树,然后从其中寻找源单,详细过程,请参阅另外一个场景、示例。
package kd.bos.plugin.sample.bill.billconvert.bizcase; import java.util.HashSet; import java.util.Map; import java.util.Set; import kd.bos.entity.ExtendedDataEntity; import kd.bos.entity.plugin.AbstractOperationServicePlugIn; import kd.bos.entity.plugin.args.BeforeOperationArgs; import kd.bos.servicehelper.botp.BFTrackerServiceHelper; /** * 示例:在单据审核时,搜索源头单据 * * @author rd_johnnyding * */ public class FindSourceBillOpPlugin extends AbstractOperationServicePlugIn { /** * 开启事务保护前,触发本事件:对数据进行检查、整理 */ @Override public void beforeExecuteOperationTransaction(BeforeOperationArgs e) { if (e.getValidExtDataEntities().isEmpty()) { return; } // 获取当前单据(下游单据)的主实体编码、单据内码 String targetEntityNumber = this.billEntityType.getName(); Set<Object> billIds = new HashSet<>(); for(ExtendedDataEntity dataEntity : e.getValidExtDataEntities()) { billIds.add(dataEntity.getBillPkId()); } // 调用平台的服务,获取所有源单及其内码 Map<String, HashSet<Long>> sourceBillIds = BFTrackerServiceHelper.findSourceBills(targetEntityNumber, billIds.toArray(new Long[0])); // 从所有源单中寻找需要的demo_botpbill1 HashSet<Long> botpbill1_Ids = new HashSet<>(); String botpbill1_EntityNumber = "demo_botp1"; if (sourceBillIds.containsKey(botpbill1_EntityNumber)) { botpbill1_Ids = sourceBillIds.get(botpbill1_EntityNumber); } if (!botpbill1_Ids.isEmpty()) { // TODO 已经获取到了源头的demo_botpbill1单据内码,可以进行后续处理 } } }
推荐阅读