本文简化字版由OpenCC转换
上一篇文章介绍了为什么要复式记账,以及Beancount的基本特点。这篇言归正转,直接从实践开始。
账户类别
复式记账的最基本的特点就是以账户为核心,Beancount的系统整体上就是围绕账户来实现的。之前提到的会计恒等式中有资产、负债和权益三大部分,现在我们再增加两个类别,分别是收入和支出。Beancount系统中预定义了五个分类:
- Assets 资产
- Liabilities 负债
- Equity 权益(净资产)
- Expenses 支出
- Income 收入
这五类是Beancount的约定,除此了Equity之下一些特殊的账户外,没有任何预先定义的账户。用户可以定义各种各样的账户,Beancount对账户的组织是树形的,譬如我分别有这些资产账户:
Assets:Cash:JPY
Assets:Cash:USD
Assets:Bank:CH:UBS
Assets:Bank:CN:BoC
Assets:Bank:US:Chase:Checking
Assets:Bank:US:Chase:Saving
Assets:Bank:JP:SMBC:JPY
Assets:Bank:JP:SMBC:USD
Assets:Broker:US:IB
Assets:Points:Airline:JAL
Assets:Points:Airline:United
Beancount对这些账户的组织形式如下图:
接下来是声明账户的语法。Beancount要求每个使用的账户必须声明开户时间,格式是YYYY-mm-dd
。之后是关键词open
,表示在这个日期开户(或者开始记账)。接下来是账户名称,格式用:
隔开的树形语法,最后是(可以省略的)账户的货币种类。货币种类不需要事先定义,也没有系统内部的定义,一般来说我们使用三字母的货币代码,但其实可以用任何的名字(惟一的限制是大写字母和下划线)。我在这个例子中使用了USD
、JPY
、CNY
、CHF
四个货币,以及我自定义的P_JAL
和P_UA
表示不同航空公司的里程。
2019-01-01 open Assets:Cash:JPY JPY
2019-01-01 open Assets:Cash:USD USD
2019-01-01 open Assets:Bank:CH:UBS CHF
2019-01-01 open Assets:Bank:CN:BoC CNY
2019-01-01 open Assets:Bank:US:Chase:Checking USD
2019-01-01 open Assets:Bank:US:Chase:Saving USD
2019-01-01 open Assets:Bank:JP:SMBC:JPY JPY
2019-01-01 open Assets:Bank:JP:SMBC:USD USD
2019-01-01 open Assets:Broker:US:IB USD, JPY, CHF
2019-01-01 open Assets:Points:Airline:JAL P_JAL
2019-01-01 open Assets:Points:Airline:United P_UA
账户如何组织分类完全看个人需求和喜好,譬如我先分账户类型,再分国家,然后是金融机构名,最后是具体账户。分类的作用是可视化的时候,可以看某个非字节点下面所有账户的汇总。
接下来是负债类别的账户,最常见的就是信用卡,组织方式和使用方法和资产账户没有什么区别,譬如:
2019-01-01 open Liabilities:CreditCard:US:Discover USD
2019-01-01 open Liabilities:CreditCard:JP:Rakuten JPY
在开始记账之前,还差最后一步,就是收入和支出类别的定义。Beancount把收入支出的类别也想象成了一个账户,在语法上和资产、负债类账户没有区别。譬如下面例子:
2019-01-01 open Expenses:Clothing
2019-01-01 open Expenses:Food:Dinner
2019-01-01 open Expenses:Transport:Airline
2019-01-01 open Expenses:Transport:Railway
2019-01-01 open Income:Salary
2019-01-01 open Income:Rebate
基本借贷记账
有了以上定义的账户以后,我们终于可以开始实践记账了。复式记账又叫作「借贷记账」。之所以这么叫,是因为每一条记录都至少有一条借记(Debit)和一条贷记(Credit)。可以看下面这个例子:
2019-01-01 * "日本航空" "纽约-东京"
Expenses:Transport:Airline 1000 USD
Liabilities:CreditCard:US:Discover -1000 USD
这个例子表示我在日本航空购买了纽约-东京的机票,消费1000美元(贷记),付款的信用卡Discover扣款1000美元(借记)。
Beancount基本的语法如下所示:
YYYY-mm-dd * ["payee"] "description"
posting 1
posting 2
...
第一行要有日期,接下来是*
。收款者payee
是可选的,如果*
后面只有一个字符串,那就是省略了payee
。从第二行开始,每一行开头空两个缩进,然后是账户名以及金额、货币。这里有一个要点:要保证所有条目的总和是0,否则就会出现Transaction does not balance: (xxx USD)
这样的错误。这个要求很好理解,因为花出去的钱必须和账户上减少的钱一样,否则就是所谓的「账目不平」了。
Beancount语法的灵活性在于每个记账单元可以有任意多个条目(借记和贷记),只要保证它们的总和是0就可以。于是我们还可以这样记录:
2019-01-01 * "Walmart" "在超市买两件衣服和晚餐"
Expenses:Clothing 20 USD
Expenses:Clothing 10 USD
Expenses:Food:Dinner 10 USD
Liabilities:CreditCard:US:Discover -40 USD
更加复杂的例子可能是这样的:
2016-01-01 * "Google" "工资"
Assets:Bank:US:Chase:Checking 500 USD
Assets:Bank:US:Chase:Saving 1839.35 USD
Assets:Pension:US:401k:PreTax 419.23 USD
Assets:Pension:US:401k:PreTax 209.62 USD
Expenses:Health:Insurance:Dental 3.14 USD
Expenses:Finance:Insurance:TermLife 7.67 USD
Expenses:Health:Insurance:Vision 0.98 USD
Expenses:Tax:US:Federal 763.26 USD
Expenses:Tax:US:Medicare 60.84 USD
Expenses:Tax:US:SocialSecurity 260.15 USD
Expenses:Tax:US:State:NY 212.59 USD
Expenses:Tax:US:City:NYC 131.57 USD
Expenses:Tax:US:State:NYDisability 1.2 USD
Income:Salary:Regular -4192.31 USD
Income:Allowance:TermLife -7.67 USD
Income:Salary:401kMatch -209.62 USD
实际的记账中,一进一出的两个账户占了绝大多数。这个时候把正负的金额写两遍未免有点罗嗦了,所以Beancount还提供了金额插值的功能。简单说就是假设总和一定是0,在有N个账户的时候,只要求N-1个账户声明金额。于是最初的例子还可以写成:
2019-01-01 * "日本航空" "纽约-东京"
Expenses:Transport:Airline 1000 USD
Liabilities:CreditCard:US:Discover
在我的实践中,我只在正好是两个账户的时候才使用这个功能,因为可以避免重复的数字。但有多个账户的时候,把每个金额都写出来有助于避免错误,和「防御性编程」的理念一样。
在上面的例子中,我们还可以看出来,所有Expenses
类别的账户都是正数,所有Income
类别的账户都是负数。这是Beancount及类似工具使用负数来表示借记(Debit),正数表示贷记(Credit)的结果。简单来说,借记就是把账户上的资金移除,贷记就是增加账户的资金。同理,通常Assets
类是正数,Liabilities
类是负数。本质上每个账户的数值只有绝对值有意义,正负号并没有实际含义。
货币转换
如果在去国外旅游,免不了要进行货币转换。事实上Beancount本身没有定义任何货币,这也意味着你可以定义任何货币(或商品)。所以哪怕不出国,只要是记录了非主要货币类资产,譬如投资品,代金券,航空公司里程,那么就需要货币转换了。
在使用多个货币之前,需要先定义「工作货币」。工作货币可以不止一个,例如:
option "operating_currency" "JPY"
option "operating_currency" "USD"
定义了工作货币以后,在fava界面中可以看到工作货币单独列出的栏目。
Beancount货币转换的语法有两种,一种是使用@
记录单位货币的转换价格,例如:
2019-01-01 * "日本航空" "纽约-东京"
Expenses:Transport:Airline 1000 USD @ 110 JPY
Liabilities:CreditCard:JP:Rakuten -110000 JPY
另一种方式我更常用,使用@@
记录转换后的总额:
2019-01-01 * "日本航空" "纽约-东京"
Expenses:Transport:Airline 1000 USD @@ 110000 JPY
Liabilities:CreditCard:JP:Rakuten -110000 JPY
货币转换不一定只在一个账户上。下面的这个例子是以2.5日圆每点的价格,买了10000日本航空里程,但是付款的信用卡是以美元计价的,所以两遍都可以转换为25000日圆来平衡。
2019-01-01 * "日本航空" "购买里程"
Assets:Points:Airline:JAL 10000 P_JAL @ 2.5 JPY
Liabilities:CreditCard:US:Discover -220.0 USD @@ 25000 JPY
借贷管理
复式记账的强大之处是每个账户都有状态,而且每个操作都是原子的,这对复杂的资金进出记录非常有帮助。
生活中一个常见的例子是朋友之间的借钱和相互垫付,就拿我最近遇到一个例子来说吧,我和X、Y三人一起出游,从东京附近的横须贺坐船到猿岛,费用是每人1300日圆的船票和200日圆的登岛费,其中船票可以用信用卡支付,而登岛费只能付现金。我们一共需要付4500日圆,但是正好谁都没有这么多现金,于是决定我用信用卡付三人的船票,X用现金付三人的登岛费,最后再结算。
2019-05-25 * "猿岛" "渡轮"
Expenses:Transport:Ferry 1300 JPY ; 个人渡轮费用
Assets:Receivables:X 1300 JPY ; 对X应收账款
Assets:Receivables:Y 1300 JPY ; 对Y应收账款
Liabilities:CreditCard:JP:Rakuten -3900 JPY
2019-05-25 * "猿岛" "登岛费"
Expenses:Transport:Attraction 200 JPY ; 登岛费
Liabilities:Payable:X -200 JPY ; 欠X的钱
第二天,三人结算完毕,X付给我现金,Y转账给我。
2019-05-26 * "猿岛" "费用结算"
Assets:Receivables:X -1300 JPY ; X偿还债务
Liabilities:Payable:X 200 JPY ; 偿还对X的债务
Assets:Cash:JPY 1100 JPY ; X实际付给我的钱到账
Assets:Receivables:Y -1300 JPY ; Y偿还债务
Assets:Bank:JP:SMBC:JPY 1300 JPY ; Y实际付给我的钱到账
最终可以看出来,我在Expenses:Transport:Ferry
类别消费1300 JPY
,在Expenses:Transport:Attraction
类别消费200 JPY
,信用卡扣款3900 JPY
,收到了1100 JPY
的现金,Assets:Bank:JP:SMBC:JPY
收到了1300 JPY
的转账。
以上这种记账方法可以让资金的流动一目了然,类别和金额也准确无误。记录对他人的债权(应收账款)和欠他人的债务(应付账款),我分别使用了Assets:Receivables
和Liabilities:Payable
下面的账户。
应收账款和应付账款的另一个用途是区分付款和到货时间。一般来说交易是当场进行的,一个账户的借记和另一个账户的贷记同时发生,但是有些时候付款和到货并不是同时发生的,如果需要精确区分发生的时间的话,可以用这种方法把他们分成两笔记录。
下面这个例子是,用信用卡买日本航空里程,但是不知道为什么过了1个月才到账:
2019-01-01 * "日本航空" "购买里程"
Assets:Receivables:JAL 10000 P_JAL @@ 25000 JPY
Liabilities:CreditCard:US:Discover -220.0 USD @@ 25000 JPY
2019-02-01 * "日本航空" "里程到账"
Assets:Points:Airline:JAL 10000 P_JAL
Assets:Receivables:JAL
这篇文章到此为止,Beancount最基本的用法已经介绍完毕了。用这些简单的语法,我们已经可以满足大部分的记账需求了,但Beancount的强大之处远远不止于此。
下一篇我会继续介绍Beancount的更多用法,包括如何高效对账和资产折旧。同时欢迎加入Beancount中文讨论:t.me/beancount_zh。
上次修改时间 2019-05-27