NC6 关于凭证接口的坑

昨天开始,帮一个老客户处理通过接口保存的凭证,凭证号会出现重复的问题。追了很深的代码,从ws实体转换,到凭证号生成和断号处理。有两个问题一定要处理完善,不然接口有问题。
1.生成凭证号。如果凭证号字段为空,调用系统凭证保存组件时,系统会使用独立事务,自动生成凭证号,逻辑就是根据账簿,类型,期间在库里存有当前最大号,然后+1。为了防止并发时查询值的时候重复,系统做法是,在同一个事务中,先执行一句update进行锁表,然后查询,补号,设值,跟新最大值,事务提交后,解锁。期间如果有线程访问,由于表被锁,在执行update时,会阻塞,所以每个线程查询的最大值不会重复。如果发生异常,远程调用会调用回滚方法(VoucherNoFetch.addRollbackHook(voucher);),回滚最大凭证号。
2.断号储存。如果凭证号字段不为空,且大于最大值,那么它与最大值之间的数字,会存入断号表,用于补号。
3.断号问题。由于是接口调用,发生异常不会回滚,最大值已经加大,而生成的凭证号也没保存为断号,所以就会出现断号问题。如果接口发生异常,我们将生成凭证号保存为断号,貌似可以解决断号问题,但是又会出现重复问题。
4.重复问题。假设发生凭证号重复异常,凭证没有保存,基于上面的处理,会将这个重复的凭证号保存为断号。我们知道,在生成凭证号时,会优先补号,那么这个重复的凭证号就会通过补号,变成重复的凭证号。
由于以上的原因,防止凭证号断号,重复,在catch里加一个判断,如果初始凭证号为空(默认是int.min)并且异常时凭证号大于0时,将此凭证号保存为断号。最好最合理的方法是凭证号全由NC生成。

顺便说一句,接口调用的时候也可以加动态锁,也是在事务提交后会自动解锁。

猜你喜欢

转载自blog.csdn.net/guaizang/article/details/106309687
nc