Featured image of post 账务是怎样运行的

账务是怎样运行的

本次从宏观到微观,关注一个核心系统的账务应该如何运行。希望可以准确的考虑账务的总流程和细节。放款、还款、计提、转列、拨备、批扣、流水同步。每个场景下的细节和事务控制等尽量详细。

账务是怎样运行的

对于业务主流程可以看我的这篇文章

本次尽量在把所有的操作分成多个阶段,每个阶段都会对已知信息做出总结。(个人绘制,配图)

基础信息说明

在开启业务之前,需要同步的几个重要信息。下面列举的信息为目的,本文中列举的所有业务场景,只是为了达到下面几个目的所使用的手段。类似于本地强事务中:AID和C的关系。

账户信息

一个客户对应一个账户,一个账户对应一笔借据,每次账务操作都需对账户上锁

字段说明枚举
客户号
借据号
产品ID
减值标识当前账户是否已减值
账户余额贷款余额
上日账户余额上次贷款余额
上次交易会计日期标定当前账户已计提日期
上日正常本金
上日逾期本金
上日减值本金
上日计提利息上次利息计提余额
账户状态标识当前账户是否有效,如果借据结清,就销户正常
销户
放款冲正
预开户
处理状态锁位处理中
已处理
预锁定无锁定
预锁定
加锁流水号只有上锁的流水号才能实现解锁

锁定账户:哪条流水(连接/线程)进行的加锁(开启事务/获取资源)操作,有且只有这条流水去进行解锁,而且必须保证解锁的逻辑能够执行。

借据信息

借据维度的详细信息

字段说明枚举
借据号
账户号
客户号
还款方式与下文中产品信息中的还款方式相同
四级分类核心自己的账户登记正常
逾期
呆滞
呆账
五级分类银行贷款角度的五级分类正常、关注、次级、可疑、损失
借据金额放款本金
正常本金
逾期本金
减值本金
减值标识表内外标识
是否停息本借据是否仍然计提
停息日期
借据余额
应收应计利息所有未结清期供计提的累计(已结清期供应计利息置0)
催收应计利息与上同理,借据减值后,会从应收转催收
应收欠息已到期的未收利息累计
催收欠息非应计状态下的欠息
应收应计罚息与利息同理
催收应计罚息
应收罚息正常情况下罚息计提后立刻转应收,但部分结息规则不同,可能导致转应收不及时
催收应收罚息
应计复息
复息
核销标识是否已核销
核销利息只表示核销时共核销的金额,不代表核销后的余额
核销罚息只表示核销时共核销的金额,不代表核销后的余额
核销复息只表示核销时共核销的金额,不代表核销后的余额
总期数
本期期数当前贷款处于哪一期
上次还款日上一次还款的日期
下次还款日通常为借据所处当前期次的到期时间
计提日期上次计提的日期
结息日期上次结息的日期

借据的详细信息表:从账务角度出发,主要包含应计(已计提)应收(未还)、已还(累计已还)三种金额。以及当前借据所处的状态等(4级分类、5级分类、表内外标识等)

利率表

理论上相同产品的利率相同,但在金融领域,利率是由风控来抉择的,使用相同产品的不同人,可能出现不同的利率。

每笔借据对应的利率

字段说明枚举
客户号
借据号
账户号
正常利率
罚息利率
复利利率
折后利率使用优惠后会出现
费用利率试算费用时使用的利率
基准利率LPR或人行基准利率
贴息利率针对贴息场景使用的贴息率

贷款期供表

还款计划,核心账务运行的基础组件,所有贷款都是由不同各种各样的还款计划来构成一个完整的贷款。

字段说明枚举
客户号
借据号
账户号
本期期数
起始日期当期开始的时间
到期日期当前期次的到期日,一般就是下一期的开始日期当期结束的日期
上日还款日期
下次还款日期一般为到期日
初始本金放款时预生成的值
初始利息
初始费用
剩余余额剩余本金
剩余本金
应收应计利息已计提的未还总额
催收应计利息减值已计提未还总额
应收欠息剩余欠息
催收欠息减值剩余欠息
应收应计罚息
催收应计罚息
应收罚息
催收罚息
应计复息
复息
费用
计提日期最后一次计提的日期
利息调整正数调整
罚息调整
复息调整
费用调整
利息抵扣金额还款时优惠的金额(延展期、优惠券等会用到)
本期状态当期期供的状态正常
逾期
呆滞
呆账
结清
减值表示
破期表示当前借据是否为整期,破期需特殊计提
宽限期宽限期

期供信息和借据信息类似,换一种说法,借据信息就是由期供信息组成的。

上面提到的所有表,都是终态表,我们的目的是为了操作上面的表。但如何科学的操作终态表,就需要有流水表来记录。下面列举重要的流水表。

交易主流水

所有都会记录的主要流水,用来同步本次交易的状态

字段说明枚举
客户号
交易日期
交易流水号(重要)主流水,账户上锁,解锁,放款,其他表都需要记录本流水。有且只有相同的流水才能操作相同的记录。
交易类型无论那种类型的交易都需要在主流水表来同步状态,这样设计可以方便流水同步放贷
收贷
核销
核销冲正
核销回收
利息调整
提现(虚账户)
放款冲正
交易金额
交易状态(重要)本次交易状态的标志(所有交易都以本状态为准)初始化
记账成功
记账失败
冲正中
已冲正
未知(超时)
待处理(还款批量)
处理次数本交易尝试的次数(一般在批扣时常用)
扣款类型当前还款使用的方式联机
批量
人工代扣
对公还款
批扣零金额还款

贷款交易流水

对客的交易流水,可以变相的理解为超全的paylog,包含放还款等(没有利息计提)每条记录一般都是要向客户展示的。

字段说明枚举
会计日期账务时间
交易日期交易日期只本流水成功的时间(可能会跨日)
交易流水号同主流水表流水号
交易类型放款
还款
核销
核销冲正
利息调整
虚账户提现
放款冲正
客户号
账户号
借据号
还款状态提前还款
正常还款
逾期还款
期供还款(正常)
期供还款(逾期)
还款期数当前还款对应的期数提前还款时取最早的一期
还款金额总金额,用来调用支付
提前还款本金
提前还款利息
提前还款方式提前还N
提前结清
提前部分结清
提前还当期
提前还本
提前部分还款
正常本金还款前的本金金额
应还本金交易后金额
本金发生额本次交易发生的本金(一般表示当前还款扣减的本金)
逾期本金还款前的逾期金额
逾期本金发生额本次交易的本金
应还逾期本金交易后金额
减值本金
减值本金发生额
应还减值本金
已减值本金转正常转列金额
已减值利息转正常
应收应计利息发生额本次计提的利息
应收应计利息本次交易后应计利息
催收应计利息本次交易后的减值利息
催收应计利息发生额本次计提的减值利息
应收欠息发生额本次还款的利息
催收欠息发生额本次还款的减值利息
应收欠息欠息余额
催收欠息
应收应计罚息发生额本次计提罚息
应收应计罚息交易后罚息
催收应计罚息交易后减值罚息
催收应计罚息发生额本次计提的减值罚息
应收罚息发生额本次还款的罚息
催收罚息发生额本次还款的减值罚息
四级分类正常、逾期、呆滞、呆账
五级分类正常、关注、次级、可疑、损失
减值标识
核销标识
交易状态当前交易流水的状态初始化(处理中)
记账成功
记账失败
冲正中
已冲正
未知(超时)
待处理(批量还款)

一笔借据绝大多数交易都会在这里展示,对于账务相关字段,大致可分为下面几种

  1. 应收应计金额:本次交易后的金额
  2. 应收应计发生额:本次交易需补计提的金额
  3. 欠息金额:本次交易后去,欠息余额
  4. 欠息发生额:本次还款实际发生的金额
  • 为什么会有一个总金额?

因为支付只会用对应的金额去请求对应账户,并不关心这些钱中包含哪些内容。(由哪些金额组成)核心作为事务控制的基准,需有统一管控。

支付交易流水

登记与支付操作相关的流水,支付系统不care资金有哪些内容组成,支付只care本次交易的状态,总额等。

字段说明枚举
会计日期
交易日期可能不同
交易流水号主流水
支付流水号与资方(银行)交易的流水号
支付渠道
客户号
贷款账号
借据号
付款账号
收款账号
交易金额
交易状态(重点)初始化(处理中)
记账成功
记账失败
已冲正
未知(超时)
对账状态是否以对账(可能出现跨日对账)

支付账号中存在大量补充校验信息,本文只介绍账务,固不赘述

利息计提流水

按日计提的流水单独记录,此部分流水一般不向用户展示

字段说明枚举
客户号
交易日期
交易流水号
借据号
本金调整本金一般不涉及调整
利息调整存在正向和反向调整
罚息调整反向调整为减免
复息调整

此流水不存在交易状态,因为一旦登记就是成功。(只有成功才会登记流水)

期供交易流水表

与期供表相同,增加了本次交易的流水号,记录每次流水交易后,期供的变化情况。

可以用此表来实现回滚。(如需)

这里不再赘述(只是在期供表上增加了流水号)

放款

放款只资金从银行到客户的提现过程。

客户角度只能看到一笔借据生成了,一笔钱到账了。

但在银行(核心)角度生意才刚刚开始,本次只列举账务,如开户行,支付用的账号等不再列举范围内。

只列举核心维系一笔账务运行的关键信息

额度等暂不放入其中,只会偶尔提到,但不深入。

放款前的准备

如果想要开始一笔贷款,必须提前准备的信息

产品信息

每笔借据都必须对应产品,不同产品可能会有各自不同的规则。

产品的目的是尽量让贷款分类,在有限的种类下给客户不同的选择

属性解释枚举
计提周期借据以什么样的周期来做计提,常见的为按日计提
贷款类型与账务无关,贷款的补充信息:信用类、
抵押类、
质押类、
担保类、
保证类
还款方式(重要)可以理解成放款阶段最重要的几个字段之一,
本字段直接决定了期供应该如何生成,且每期对应的本金、利息如何分配。
放款阶段的试算器,完全就是为了不同的还款方式而定制化的。
利随本清(随借随还)
先息后本
等额本息
等额本金
按月复息定期还本
等额本息气球贷
等额本金气球贷
按月付息定期还本气球贷
还息周期定义按什么样的维度来还款利息
(周期性还本还息时使用)
还本周期与上同理
还款顺序指表内的还款顺序(罚利本)
减值还款顺序表外的还款顺序(本利罚)
宽限期借据到期后,可以宽限的天数
固定还款日有些产品还款日固定(为了方便计算)
末期和首期是否同日防止出现破期(让每期期供计息天数相同)

放款基础信息

在放款前置操作时准备好的字段,放款前置大部分为渠道、风险等

属性解释枚举
客户号本身不属于账务必须,
但整个核心系统的事务都是基于账户来设计的
一个客户对应一个账户,
一个账务同一时间只能进行一个操作
产品id查询产品信息的依据
还款方式重要字段,这里不再赘述
总期数共生成几期还款计划
正常利率(重要)借据正常状态下的利率
逾期利率可能存在逾期下与正常利率不同情况
折扣率如果放款时有优惠,需使用折扣率
放款日期借据的起始日期
  • 折扣率

折扣率不一定会直接提供,大部分场景下需要计算得出

固定利率:有些折扣会直接让利率固定,此场景不需要再考虑折扣率(利率已是折扣后的)

其他情况:需通过折扣率/正常利率,算出折扣率(后面为了得出优惠情况)

放款试算

所谓放款试算,只预生成借据和期供信息,相当于预放款,给客户一个完整的展示。后续实际贷款流程也会重新调用放款试算。试算更适合单独的展示账务是如何生成的。

放款全程没有事务,不涉及加锁,不涉及入库。

  • 为什么不入库或加锁?

放款试算只提现如何生成借据和期供,不一定只有在预放款时调用,可能在延展期,提前部分还款等场景下都会调用。且调用频率较高,如果每次试算都入库,会生成大量无效的数据。

据了解,有些支持预放款的机构(如数禾:借呗),会把放款试算的结果保存在数据库中,来增加放款的响应速度。但放款场景下,试算是非常耗时的一环吗??

前期准备杂项介绍

  • 试算时入参

入参大部分为放款前准备阶段的已知数据,下面列举一些账务较为重要的字段

字段备注
借据金额
还款方式(重要)不同的还款方式会生成不同的期供
总期数生成的期供共有多少期
正常利率
还款日
首次还款日可能出现首期破期
  • 试算时出参

目标字段

字段备注
本息总额总金额:本金+利息(客户必还的钱)
本金总额
利息总额
到期日期
还款日
年利率
起始日期借据开始的日期(可以理解成起息日)
下次还款日支付系统可能调用
还款计划<开始>还款计划是一个集合,下面展示集合中单个元素包含的信息
开始日期当期开始日期
到期日当期结束日期
当前期数
还款总额当前期数需还款总金额
归还本金当期应还本金
归还利息当期应还利息
剩余总本金到当期为止的剩余总本金(用来计算利息)
费用等字段暂不列出
还款计划<结束>

后面会详细列出上表中每个字段的生成逻辑

根据不同的还款方式使用不同的放款试算器

等额本金试算器

最简单的贷款生成逻辑,只根据剩余本金、计息天数、日利率来计算

  1. 预生成还款计算,并把本金分配到每期上

为什么要拆分本金?如果自定义还本周期,会出现多个不存在应还本金的还款计划,所以本金不一定是会拆分到每一起上的。

总期数:会生成多少期还款计划在产品配置时就已经定义。

哪些期数会被分配本金:还本周期/还息周期,后续每次增加 还本周期/还息周期

1
for(int i=还本周期/还息周期;i<总期数;i+=还本周期/还息周期)

如还本周期为2,还息周期为1,生成的还款计划就是1(只还息)2(还本还息)3(只还息)4(还本还息)…

字段组成逻辑
还款计划<开始>还款计划是一个集合,下面展示集合中单个元素包含的信息
开始日期
到期日
当前期数当期的期数
还款总额
归还本金借据总金额/还本周期=每期应还款金额(除不尽的余额补在最后一期)
归还利息
剩余总本金
费用等字段暂不列出
还款计划<结束>
  1. 利息计算

计算每期的利息,对于首期有特殊计算逻辑

字段组成逻辑
还款计划<开始>还款计划是一个集合,下面展示集合中单个元素包含的信息
开始日期第一期为:借据放款时提供的起息日
其他期数:为上一期的到期日
到期日第一期:放款时传入
其他期数:开始日期向后增加一个月
当期计息天数(内部使用)破期(首期):
1、按实际天数算
2、按整期算(30天)
3、满一个月部分按照30计算,超出部分按照实际天数
其他期数:统一按照30天计算
当前期数当期的期数
还款总额当期本金+当期利息
归还本金借据总金额/还本周期=每期应还款金额(除不尽的余额补在最后一期)
归还利息年利率/360*计息天数 *剩余本金
剩余总本金截止目前为止的剩余总本金(包括当期)计算利息使用
费用等字段暂不列出
还款计划<结束>

还款计划生成完成!

  1. 借据字段补全
字段逻辑
本息总额总金额:本金+利息(客户必还的钱)
本金总额放款时提供
利息总额计算还款计划时生成的利息和
到期日期最后一期的到期日期
还款日首次还款日
年利率放款时提供
起始日期借据开始的日期(可以理解成起息日)
下次还款日首期到期日
还款计划<开始>还款计划是一个集合,下面展示集合中单个元素包含的信息
开始日期第一期为:借据放款时提供的起息日
其他期数:为上一期的到期日
到期日第一期:放款时传入
其他期数:开始日期向后增加一个月
当期计息天数(内部使用)破期(首期):
1、按实际天数算
2、按整期算(30天)
3、满一个月部分按照30计算,超出部分按照实际天数
其他期数:统一按照30天计算
当前期数当期的期数
还款总额当期本金+当期利息
归还本金借据总金额/还本周期=每期应还款金额(除不尽的余额补在最后一期)
归还利息年利率/360*计息天数 *剩余本金
剩余总本金截止目前为止的剩余总本金(包括当期)计算利息使用
费用等字段暂不列出
还款计划<结束>

等额本金为最简单的贷款生成方式,后续其他还款方式的生成思想与等额本金相同

等额本息试算器

等额本金要提前拆分本金,等额本息由于每期还款总金额相同,所以需预拆分每期还款总额

  • 如何计算每期还款总额

1767581897215.png

字段备注
本息总额总金额:本金+利息(客户必还的钱)
本金总额放款时提供
利息总额计算还款计划时生成的利息和
到期日期最后一期的到期日期
还款日首次还款日
年利率放款时提供
起始日期借据开始的日期(可以理解成起息日)
下次还款日首期到期日
还款计划<开始>还款计划是一个集合,下面展示集合中单个元素包含的信息
开始日期第一期为:借据放款时提供的起息日
其他期数:为上一期的到期日
到期日第一期:放款时传入
其他期数:开始日期向后增加一个月
当期计息天数(内部使用)破期(首期):
1、按实际天数算
2、按整期算(30天)
3、满一个月部分按照30计算,超出部分按照实际天数
其他期数:统一按照30天计算
当前期数当期的期数
还款总额等额本息计算根据上面列出公式得出
归还本金根据本期还款总额-当期归还利息
归还利息年利率/360*计息天数 *剩余本金
剩余总本金截止目前为止的剩余总本金(包括当期)计算利息使用
费用等字段暂不列出
还款计划<结束>

等额本息计算顺序有所改变:1、算出每期还款总额,2、算出当期应还利息,3、根据当期还款总额-当期应还利息=当期应还本金。

放款try

放款主要涉及三个服务联通,额度占用,借据期供生成,调用支付。(三个全部成功后才能提交)

主要介绍事务控制,单个小事务和整体分布式事务是如何结合的。

所有分布式事务,都需要考虑三个问题:幂等性,空回滚,悬挂问题,下文中会解释每个场景下问题是如何处理的。

放款账务部分有两个独立本地事务组成

流水登记(事务1)

登记三大流水

交易主流水、贷款交易流水、支付交易流水。

  • 为什么使用独立事务登记流水?

事务回滚触发条件存在两种情况:

  1. 流水重复入库失败:当前流水已经入库被处理,不再重复处理。(幂等性

  2. 代码出现异常,导致事务回滚:独立事务只做流水入库处理,如果和试算开户等计算逻辑放到同一个事务中,如果代码出现异常,登记的流水也会丢失。

    虽然下次相同的流水应该也会执行相同的回滚逻辑,但给系统增加了负担,所以让代码异常和流水登记分开。

开户、放款试算信息落库(事务2)

开户时生成账户信息,默认生成的账户信息为上锁状态,上锁流水为当前放款请求流水。(防止没有放款成功,此借据被其他线程消费)

给当前客户创建客户信息,走放款试算逻辑生成借据、期供。

  • 落库借据
  1. 落库账户信息
  2. 借据信息
  3. 利率信息
  4. 期供信息

上述表除账户信息中存在锁状态,其他表无状态

当前阶段并没有特殊逻辑,如果本阶段出现异常回滚,说明流水中存在错误参数,无法放款。之前登记的流水也要提交,遇到相同流水无需重复试算。

放款confirm

资源占用成功,支付返回成功后,就会提交占用的资源。

由于借据相关信息已在占用阶段生成,所谓提交阶段只需提交流水信息。(把流水状态改成成功)

更新三大流水表状态为成功:交易主流水、贷款交易流水、支付交易流水。

最后阶段解锁账户

放款取消Cancel

支付返回失败,放款冲正。

取消阶段和提交阶段相同,为了保证事务/锁/资源一定可以释放,所有提交取消都是轻量级原子操作。不附加额外逻辑。

  1. 更新三大流水表为失败:交易主流水、贷款交易流水、支付交易流水。

  2. 最后更新账户状态为放款冲正。(失败)

try阶段落库的借据信息、期供信息等不做处理。

放款总结答疑

  • 为什么只修改流水,不修改借据信息,或者是为什么不在借据信息上也增加类似账户的状态字段?

只修改流水,是为了保证提交和取消操作一定可以被执行。

只有账户信息上存在状态,其他所有非流水表都不在事务执行状态字段,是为了保证状态修改的原子性,避免死锁。

如果借据信息上存在类似账户的事务执行状态字段:加锁操作就不在是原子性的:

两个线程同时上锁:A线程线对账户加锁,后执行对借据加锁。B线程对借据加锁,后执行账户加锁。产生死锁

  • 幂等性

try阶段两个独立事务,事务一登记流水,流水一旦登记,就不能再重复登记。

confirm:只按流水更新流水状态为成功,重复成功where条件中不存在当前流水号且状态为处理中的流水。

cancel:同提交操作,只更新流水。

  • 空回滚

在try阶段之前,就执行了cancel逻辑。

cancel只会更新流水,由于try阶段还未执行,三大流水表中不存在流水信息,cancel逻辑只会空跑。

  • 悬挂问题

额度占用成功,但借据生成执行超时,导致事务管理器已经发起了取消请求后,借据生成执行又成功了。

现有逻辑中没有考虑悬挂问题,对于这种超时后又提示占用成功的流水,会由后面的流水同步任务来让此流水走向终态。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计