银行记账接口(续)

记账接口做什么?

1. 公共校验
这个没什么好说的,就是对上层应用传入的合约号,会计日期等参数以及是否允许透支等标志的合法校验,值得一提的是,合约的币种和交易币种需要保持一致,人民币账户不能记美元。结售汇转换应该放在应用来做。

2. 更新合约当前余额
最基本的功能,也没什么好说的。

3. 根据账户余额类型及发生额生成对应的合约分录

4. 根据账户余额类型、发生额及分录关系码生成合约分录
意思是,外围调用记账接口后,会自动触发一些账户余额,特别是统计类余额的变化。这些统计类余额本质上是由于合约余额动账产生的,比如某合约取现后,会联动触发累计取现金额这个余额类型产生变化。所以为了减少应用调用记账次数,会事先配置好分录关系码,记账时根据分录关系码生成多条分录。(对于理财应用,比如某贷方金额动账后,记账接口还需要对份额进行加减。)

5. 联动生成合约明细并自动开户
比方说A行部向B行部转账1000.00元,对于A行部,钱少了1000元,对于B行部,钱多了1000元。AB行部之间需要补一对特殊的合约(通存通兑),来保证A行部和B行部本身的平衡。再复杂一点,A行部是新成立的行部,发生交易时这个特殊合约还没开立,这时候记账接口需要进行开户操作。

6. 登记待更新日终余额表
对于采用日终余额法计息的合约,如果有动账则登记这张表,当晚日终余额加工批量程序会从这张表出发,对登记余额类型进行更新。这个日终余额表只起到了框定范围的作用。
补充:对公存款的个人活期支票户采用积数法计息,其他都采用日终余额法计息。

7. 人民币账户记外币
只有一个场景,即外币收手续费,某个跨国公司在我国内开立了分公司,并开立人民币账户。缴纳手续费时可能会转入外币。这个时候合约余额没法使用原有的合约,因为合约余额类型是没有币种信息的,默认都和原合约相同,人民币合约下所有的合约余额都是人民币的。这个场景下发生业务的合约是一个客户合约,并不是为了收取手续费的专用合约,ABC采用了一个新的数据模型,合约外币余额。

8. 入上日账
这个稍微复杂一点,入上日账只允许在批量模式下出现,通过记账掩码入上日账处理标识判断是否为入上日账处理(只允许在批量交易下入上日账),如果是,则获取上一日的会计日期,生成明细和更新余额时都按照上日会计日期进行判断处理。

  • 将合约明细上的入上日账处理标识赋值为‘1’,明细中的会计日期赋值为上日会计日期
  • 根据明细,更新当前合约余额
    • 明细中的会计日期 = 更新前余额表中的最后动账日期,说明切日之后没有发生当日动账交易。(与入当日账时的处理规则相同)更新最后动账日为明细中的会计日期,更新当前余额,次末动账日和次末动账日余额不变。(最简单的情况)
    • 明细中的会计日期 > 更新前余额表中的最后动账日期,此时说明入上日账前到上一日的日切(即整上一会计日),都没有发生动账交易。(因为如果但凡有一次动账,最后动账日期即被修改为上一会计日)更新次末动账日为最后动账日,更新次末动账日余额为当前余额,更新最后动账日期为明细中的会计日期,更新当前余额。(入上日账变成了上日第一次动账,与入当日账时的处理规则相同)
    • 明细中的会计日期 < 更新前余额表中的最后动账日期,说明入上日账前(切日之后)已经发生了当日动账交易,比如说半夜十二点多你做了一笔支付,余额表中的最后动账日期已经更新为当前会计日期,并且次末动账日期已经更新为上日,次末动账日余额已经更新为上日的日终余额。最后动账日不变,更新当前余额,更新次末动账日余额(与当前余额同加同减,处理逻辑类似冲账,当不允许透支时,更新后的次末动账日余额不能小于零),如果明细中的会计日期>次末动账日期,则需要将次末动账日期修改为明细中的会计日期(入上日账时的特殊处理规则)。

多说一句,日切通常是在晚上12点整开始,12点后开始批量处理上日账务,银行日切的时间通常很短,而遇到系统维护或主机升级,为了保证记账正确,日切通常会提前。比如说你在11:59分购买了某行的某理财产品,碰巧这天这个银行系统升级,日切提前到了11:58,这相当于你购买当天的利息被银行扣掉了。

9. 汇总入账
记账接口判断入账模式:实时更新,批量汇总更新;账户余额类型的属性是实时更新的,无视传入的状态位,否则以传入的为准。如果是批量汇总更新(即日终批量进行汇总入账),生成的分录上的更新处理状态为“批量更新”,不修改余额。对于主机系统造成压力比较大的交易一般会考虑以汇总入账的方式记账。

10. 抹账
获取需要抹掉交易的日志号,新生成的交易合约明细和原正交易的信息一样,只是新生成的合约明细账务处理状态为抹账,完成平衡校验后,根据日志号修改原合约明细账务处理状态为被抹,登记交易间关系表为“抹账关系”。
特殊情况是,抹账交易可能会触发其他正交易。目前只有两种场景:

  • 某对公账户,当余额大于100万时会自动触发资金归集,抹最后一笔余额大于100万的交易,被触发资金归集的交易不能抹。
  • 个人活期联机结息,正常情况下,个人结息交易是在批量程序处理的,但是如果批量结息失败,在下次联机动账时会检查结息时间,发现上次没结息就自动触发个人联机结息。这个时候如果要抹账的话,联机结息操作不能抹。

对于如上两种特殊情况,需要应用对已经发生的分录做部分抹账,做法是送记账接口的记账掩码为正常处理,然后根据输入的分录按照正交易逻辑进行余额更新处理。也就是说,特殊抹账是按照正交易来做的。功能很灵活,当然,也容易出错。

11. 冲正(错账调整)
要冲的错账应该小于当前会计日期,目前记账不支持记未来账(但也不是不能做,无非就是倒起息和预起息),如果合约是采用积数法计息,则计算调整积数并更新(复杂);如果是余额法计息,则根据规则计算日终余额调整金额并更新日终余额调整表,结息由专门的结息程序来计算。

  1. 余额法计息,以当前会计日期和错账日期为区间,查询日终余额调整表,如果存在记录(说明当天已经调整过至少一次了),则累加记录中的调整金额,如果查询不到记录,则新增一条记录(当晚批量程序会找余额调整表和余额表,计算利息,这样设计使得日终余额表和余额调整表分别记录余额和需要调整的金额)。
  2. 积数法计息,贷方余额变动,比较生效日期和滚积数日期
    1. 生效日期(T1)大于上次滚积数日期(T2,即为合约余额表里积数的最后动账日期),则正常滚积数,积数发生额 = 当前贷方余额×(T1-T2)
    2. 生效日期(T1)等于上次滚积数日期(T2),不处理
    3. 生效日期(T1)小于上次滚积数日期(T2),则计算并更新调整积数,调整积数=合约余额变动金额×(T2-T1)

银行通过两种计息法保证用户的利息结算准确,一个是积数法计息,一个是余额法计息。积数法对于银行开销较小,余额法开销较大。积数法记录上次动账日到当前会计日的积数,结息后会清零;余额法会根据当前积数计算余额利息并记录余额调整表。对于活期而言,为了减小开销可以使用积数计息法,对于对公账户,为了提高精确性使用余额计息法。当然,两种结息算法得出的利息是完全一样的,只是计算成本不同。另外,计息账户发生动账时会触发动账结息。比如你有10000块钱,存了两天,虽然银行可能还没来得及结息,但是如果你想销户的话银行还是会自动为你按照活期利率给你这两天的利息。结息后本金和计提的利息一并记入本金。举个例子说明:
2016年6月1日,你在A银行存5万元一年定期,年利率2.5%,31天后取出1000元,此时取出的1000元会按照活期利率计算利息,剩余的49000元仍然按照定期计算利息。

关于定期/活期存款的结息日:活期的利息并非每天都结,央行规定按季度结息,而且不同银行有自己的结息日。

  1. 计算天数:即该余额保持不变的天数
  2. 计算积数:本金×时间
  3. 计算结息:积数×日利率

50000*32*0.025/360 = 111.11,算得5W元一个月的定期应付利息会从111.11变成107.64,假设A银行结息日为7月2日,正常情况下,结息后应付利息调整为107.64 + (50000-1000)*0.025/360 = 111.04。这个金额会累加到本金里(记贷方余额,不知道是什么东西的同学请翻上一篇)。如果这时发生冲账,要冲掉取现1000的交易,记账接口记日终余额调整表,贷方+1000。少记的利息会在下个季度的计息程序补足。如果这个时候销户的话也会进行结息。

12. 特殊动账,个人活期批量结息时,只更新最后动账日,不更新客户最后动账日。比如中石化(大客户)的对公账户,有自己的会计系统,如果账户未动账的时候我们发起了一笔结息(假设每个季度23号),然后更新了最后动账日期,中石化的财务肯定不会满意。

13. 借贷平衡校验
从明细全局内存中读取联机交易写入的所有合约明细数据,按照行部、币种将借方发生额和贷方发生额分别累加汇总后,判断总借方金额与总贷方金额是否相等,如不等,则报错。实际上,财会部为每组交易配置了会计模板(核算操作码),因此在一个交易下(核算场景下),还要对发生交易的多个行部发生的交易信息进行平衡校验。

银行记账接口

银行的记账和处理是个很复杂的过程,可以说从业务逻辑到技术实现都是很有技术含量的。2016年双十一农业银行(以下称ABC)全天交易量超过4亿笔,10号晚上只有一个人值班(啥事也没干)。据我所知没有任何一家互联网公司能做到。当然了,各家互联网公司的业务复杂程度和技术架构,解决方案与传统银行完全不一样,业务需求也不同,各家各有特点。

言归正传,在介绍记账之前,需要同学们先了解一些会计的基本概念。考虑到银行核心系统内部会有部分涉密的东西,我会尽量过滤掉这部分内容,只做一般化的讨论。

银行系统在处理上分为联机交易和批量交易两大部分,从字面意思上可以知道,联机就是实时处理,实时更新,比如活期账户取现。批量则是对当天处理的结果或者待入账信息等临时表进行汇总处理,具体包括清算、轧差等。记账接口在技术上是整个核心系统数据的来源,各个子应用(存款,贷款,理财等)通过记账接口完成对合约明细的写入。一般当天晚上,核心系统会从明细表出发进行一系列复杂的处理。换句话说,这个接口主要和合约明细这个表打交道。这个合约和我们所说的账户不一样,通常意义上的账户,比如说活期账户,是银行记账的维度,而为了明晰账簿,ABC采用的是以合约的形式记账,活期合约下,有活期合约余额类型和利息合约余额类型,通过合约的形式来逐户记账的方式叫做分户账。”账户”被分的更细了,这么做的意义在于,除了分户记账,我们还可以采取其他的维度去记账,比如按照一定的统计维度(网点、币种、产品、账户余额类型)来分门别类的统计。(分类账
举例说明:
某银行托管的基金合约下,客户持有的份额(余额类型一)是10000.00元
客户购买的暂存资金(余额类型二)是30000.00元
异常待处理应付客户资金(余额类型三)0.00元
同一个合约下不同的余额类型需要有各自不同的动账时间等属性。分类账用于账务核对,满足对可售产品(比如某定期,对于银行来讲就是一个可以卖给客户的产品)进行汇总的业务需求。上合约中,银行可以对客户购买的暂存资金进行冻结,交易金额封顶操作,等。
定义如下:
分户账:采用合约的形式来逐户设置,反应金融性交易的经济事项变动即时余额信息。
分类账:也称汇总账簿,按不同的维度分门别类的反应分户账汇总信息。
实际上,ABC还需要保留一个账簿叫做明细账,按照业务发生的时间顺序,逐日逐笔记录业务的账簿,这个保留的是最最原始的凭证信息。这个账簿以业务场景为出发点。

基本概念相关

合约:可以理解为客户和银行之间的一种契约。详细解释可以参考这里
合约分录
:合约分录是合约的资金或其他信息产生变化时产生的一条明细记录,按照是否有资金变动,合约分录可以分为金融性合约分录和非金融性合约分录,通过记账接口记录的均为金融性合约分录,即某账户余额类型的金额变动明细。也是我们记录的描述合约的最小单位。
合约明细:用来反映某一笔交易对某一个合约的影响,即当前合约的业务场景。一笔合约明细由一笔交易产生的、属于某一合约的全部合约分录组成。通过记账接口记录的都是金融性合约明细。即一笔交易中某一个合约下发生金额变动的账户余额类型的明细记录。
合约余额:反映一个合约下的某一账户余额类型的当前余额信息。
借贷平衡校验:按照借贷记账法,对一笔联机交易生成的所有合约明细数据,按照行部、币种将借方发生额和贷方发生额分别累加汇总后,利用“有借必有贷,借贷必相等”的记账规则来检验本交易记账是否正确。
抹账与冲正:对用户操作失误引起的错账进行调整,错账分为当日错账、隔日错账两种。对当日发生的账务差错,经高级主管审批,由原经办用户选择抹账交易,进行抹账处理。对非当日的其他账务差错,做冲正处理。多说一句,抹账和冲正都是对错误的补救。抹账相当于把原来发生的交易抹除,冲正相当于把原来发生的错误账务进行弥补,比如某天交易柜员需要转出100.00元到现金箱,但手抖多打了个0,转出了1000.00。第二天柜员发现前一天做错了,这个时候柜员可以采取两种措施:一种是从现金箱往回转9000.00,一种是把10000.00全部冲回去,重新转1000.00出来。往原交易方向的反向记叫冲正,记红字,正向冲叫补账,记蓝字。如果是涉及计息的合约,还需要对算错的利息进行调整(你也不希望银行平白无故多吃你的利息吧),这个待会再讨论。

假设储户以现金形式存入个人活期储蓄存款1000.00元,对于个人来说,钱(现金)减少了1000元,但是卡里的钱多了1000元,看起来平了。对于银行来说,钱存到了现金箱,然后进入了核心系统,看起来好像现金箱里多了1000元,然后核心系统的个人活期合约里也多了1000元,总共多了两千,好像哪里不对。 ^——^

实际上,会计上有这么一个公式:
资产=负债+所有者权益
任何交易发生,都需要根据“有必有借贷必相等”的记账规则对交易进行借贷平衡校验。这里的借和贷和我们通常意义上借给朋友十块钱的借不同,会计上的借贷表示记账符号,借表示账户的借方,贷表示账户的贷方。对于资产来说,借表示资产的增加(+),贷表示资产的减少(-)。对于负债或所有者权益来说,借表示负债、所有者权益、利润减少(-),贷表示负债、所有者权益、利润增加(+)。
什么意思呢?根据表示意义的不同,银行把合约号(会计上叫科目号)分为资产类、负债类、所有着权益类等,不同类的科目账户增加或减少对于银行来讲意义是不一样的。比如说,个人的活期账户,对于银行来讲属于负债类科目,因为这是银行欠客户的,而固定资产,短期贷款等,这是银行自有的或者别人欠银行的,属于资产类科目。一个金融性交易,必然会导致至少两个账户的动账,在处理业务和会计事项时,必须同时登记借方科目和贷方科目,不管一借多贷还是多借一贷甚至多借多贷,借贷双方的金额必须相等。这就是“有借必有贷,借贷必相等”。
那资产=负债+所有者权益呢?
刚才说了,个人的活期存款在银行是负债,所以记录的是负债类科目,而库存现金是银行的资产,所以上述提到的业务场景应记的会计分录为:
借:库存现金 1000.00元                           (资产)
贷:个人活期储蓄存款  1000.00元        (负债)
这样就平了。再举几个例子:
银行给企业发放短期贷款一笔,金额为1000000.00元,转入该企业存款账户:
借:短期贷款  1000000.00元                   (资产)
贷:单位活期存款  1000000.00元         (负债)
银行向中国人民银行解交回笼资金100000.00元
借:存放中央银行款项  100000.00元     (负债)
贷:库存现金  100000.00元                   (资产)
再说借贷,一般来说,一个账户的左方称为借方,右方称为贷方,在哪方登记增加数,在哪方登记减少数取决于账户本身的性质。资产与负债和所有者权益是同一个资金的两个对立面,他们之间应该保持这平衡关系,因此,这两类账户必须以相反的方向来登记其金额的减少和增加。

通常:资产类账户借方登记增加数,贷方登记减少数;负债类和所有者权益类贷方登记增加数,借方登记减少数。因此对于资产类账户,余额增加记入借方,对于负债类科目和所有者权益类科目,余额增加记贷方
对于资产类账户的余额和发生额关系表示为:
期末余额  =  期初余额  +  借方本期发生额  –  贷方本期发生额
(借方)      (借方)
负债类和所有者权益类账户余额和发生额关系表示为:
期末余额  =  期初余额  +  贷方本期发生额  –  借方本期发生额
(贷方)      (贷方)
对如上例子,发生额及余额试算如下:

账户名称 期初余额 本期发生额 期末余额
借方 贷方 借方 贷方 借方 贷方
库存现金 1000000 1000 100000 90100
个人活期存款 1000 1000
企业短期贷款 1000000 1000000
单位活期存款 1000000 1000000
存放中央银行款项 100000 100000

未完待续。