科目余额表中保存的是已过账凭证的余额数据,对于有需要同时包含未过账凭证数据的情况来说,就无法从科目余额表直接取数了,现行的方法是调用官方提供的虚拟过账方法,得到一个表结构和科目余额表一模一样的临时表,从这个临时表直接取数。这里提供另一种方案:即凭证保存时实时过账凭证。这种方法有个问题,就是当已过账凭证需要修改或删除时,不必须先反过账,造成操作上的不便。
过账反过账的方法如下所示:
/// <summary> /// 凭证过账反过账方法 /// </summary> /// <param name="ctx">上下文</param> /// <param name="postType">枚举类型,过账/反过账</param> /// <param name="lstVoucherIDs">待过账的凭证ID列表</param> /// <param name="lBookId">凭证所属账簿内码</param> /// <param name="iYear">凭证的年度</param> /// <param name="iPeriod">凭证的期间</param> /// <returns>过账结果信息</returns> private OperateResultCollection PostVoucher(Context ctx, Kingdee.K3.FIN.Core.PostType postType, List<long> lstVoucherIDs, long lBookId, int iYear, int iPeriod) { //操作结果 OperateResultCollection opResultPost = null; //过账参数 var postParam = new Kingdee.K3.FIN.Core.Parameters.VoucherPostParameters(); postParam.BookId=lBookId postParam.currentYear = iYear; postParam.currentPeriod = iPeriod; //过账方式为按明细过账 postParam.PostType = Kingdee.K3.FIN.Core.Parameters.GlVoucherPostType.Detail; //待过账的凭证ID postParam.VoucherIds = lstVoucherIDs.Distinct().ToArray(); //不检查凭证号连续性 postParam.IsCheckUncontinuity = false; postParam.IsContinueWhenError = true; //是否调整期凭证 postParam.IsAdjustPeriod = false; if (postType == Kingdee.K3.FIN.Core.PostType.Post) { //过账 opResultPost = Kingdee.K3.FIN.GL.ServiceHelper.VoucherPostServiceHelper.VoucherPost(ctx, postParam); } else { //反过账 opResultPost = Kingdee.K3.FIN.GL.ServiceHelper.VoucherPostServiceHelper.VoucherUnPost(ctx, postParam); } //返回过账结果信息 return opResultPost; }
将上面的代码封装好的方法,在凭证保存完成后调用即可完成自动过账。已知有凭证保存的地方主要涉及两处,一是总账的凭证保存,二是智能会计平台的凭证生成功能的凭证保存。
1, 总账的凭证保存调用凭证过账方式法:可以追加一个凭证保存插件,在插件的AfterExecuteOperationTransaction()方法中采用异步的方式执行凭证过账。插件编译好后,挂在凭证的保存操作的服务器插件列表的后面。具体代码示例如下:
/// <summary> /// 凭证保存后自动过账插件 /// </summary> [Description("凭证保存后自动过账插件")] public class VoucherPostOperationService : AbstractOperationServicePlugIn { /// <summary> /// 凭证保存事务完成后执行的事件 /// </summary> /// <param name="e"></param> public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e) { base.AfterExecuteOperationTransaction(e); //后期可以放在Task中处理的任务 new System.Threading.Tasks.Task(() => AfterOperationTransactionTaskWork(e)).Start(); } /// <summary> /// 在新的线程上处理与单据保存本身不直接相关的事务 /// </summary> /// <param name="e"></param> private void AfterOperationTransactionTaskWork(AfterExecuteOperationTransaction e) { try { //获得过账方法需要用到的参数值(略) var opResultPost = PostVoucher(this.Context, Kingdee.K3.FIN.Core.PostType.Post, lstVoucherIDs, lBookId, iYear, iPeriod); } catch (Exception ex) { Logger.Error(LogSubSystem.GL.ToString(), ex.Message, ex); } } }
2, 智能会计平台的凭证生成功能的凭证保存。如果系统中存在通过智能会计平台的凭证生成生成凭证的业务场景,则需要关注此方法,否则,可以略过。智能会计平台的凭证生成采用的不是标准操作,而是通过菜单的方法调用来实现的,无法直接干预方法执行的过程,只能在方法调用完成后,追加执行凭证过账。具体方法,可以在BOS设计器的凭证生成界面,新增一个【凭证生成】菜单项,同时隐藏原【凭证生成】菜单项,点击时执行二开插件中的凭证生成方法(COPY原凭证生成的代码,相关细节可以咨询智能会计平台),在获得该方法执行的结果后,根据结果再调用凭证过账的方法。
注意:要实现凭证实时过账,必须确保所在生成凭证的途径上都自动调用上面的凭证过账方法,否则将造成数据问题。以上两处为官方已知途径,如果二开发其它途径,也必须同时调用凭证过账方法。
推荐阅读