使用 Beancount 制作和追踪发票
一个纯文本模板、一个可重复的工作流程和一个简单的查询,即可解答“还有谁欠我钱?”
开票工作有时感觉像是一件苦差事,卡在您已完成的工作和您正在等待的付款之间。 但是,良好的开票流程是健康现金流的支柱。 它具有双重作用:清晰地告知您的客户他们欠款多少以及何时付款,并为您的会计系统提供其所需的可靠事实。
虽然专用的 SaaS 应用程序可以发送流畅的自动化 PDF 文件,但它们通常需要按月付费,并将您的数据锁定在专有孤岛中。 使用 Beancount 的轻量级纯文本方法提供了一个强大的替代方案。 您可以将每张发票转换为一组清晰的会计分录,从而获得版本控制、强大的元数据和即时查询的所有好处,而无需订阅。
最小可行发票(您永远不应该跳过的字段)
在接触您的账本之前,您需要一张专业的发票。 格式可以很简单,但内容必须精确。 这些借鉴久经考验的小企业实践的字段是不可协商的。
- **卖方详细信息:**您的公司名称和实际地址。
- **客户详细信息:**您的客户的名称和(理想情况下)他们的地址。
- **发票编号:**一个唯一的、连续的 ID,永不重复使用。
INV-045
紧随INV-044
之后。 - **开票日期和到期日期:**清楚地说明发票的开具日期和预期付款日期。
- **项目明细:**对服务或产品的清晰描述,以及数量、单价和项目总计。
- **小计、税金和总计:**显示计算过程,以便客户可以轻松理解。
- **可选注释:**用于感谢、汇款指示或客户提供的采购订单号。
为了帮助您入门,我们创建了一组可立即编辑的模板,其中包含所有这些字段。 电子表格版本甚至会为您预先计算总计。
在此获取我们的模板:beancount.io/invoice‑templates (提供 Google Docs、Word、Sheets、Excel 和 PDF 格式)
在您的账本中记录发票
将发票 PDF 发送给客户后,您必须将其记录在 Beancount 中。 这是一个至关重要的步骤,它在收入产生时确认收入,而不仅仅是在收到付款时。 该过程涉及两个不同的交易。
1. 开具发票时:
您创建一个交易,将总金额从您的 Income
账户转移到 Assets:AccountsReceivable
。 这会在您的账簿中创建一个数字借据。
; 2025‑07‑21 发票 #045 为 Acme Corp. 进行的网页设计冲刺
2025-07-21 * "Acme Corp" "INV-045 网页设计冲刺"
Assets:AccountsReceivable 3500.00 USD ; due:2025-08-04
Income:Design:Web
invoice_id: "INV-045"
contact_email: "ap@acme.example"
link: "docs/invoices/2025-07-21_Acme_INV-045.pdf"
在这里,您借记 AccountsReceivable
并贷记您的 Income
账户。 请注意丰富的元数据:到期日期、唯一的 invoice_id
,甚至直接指向您发送的 PDF 的 link:
。
2. 客户付款时:
当现金存入您的银行账户时,您记录第二个交易以“结清”借据。 这会将余额从 AccountsReceivable
转移到您的支票账户。
2025-08-01 * "Acme Corp" "INV-045 付款"
Assets:Bank:Checking 3500.00 USD
Assets:AccountsReceivable
invoice_id: "INV-045"
Assets:AccountsReceivable
中 INV-045
的余额现在为零,您的账簿完全平衡。
附加 PDF:
link:
元数据键与 Fava(Beancount 的 Web 界面)一起使用时尤其强大。 Fava 将直接在交易视图中呈现可点击的链接,因此只需点击一下即可访问源文档。 此工作流程早在 2016 年就在一项功能请求中设想 (GitHub)。
一个查询即可列出所有未结发票
那么,还有谁欠您钱? 使用此系统,您无需在电子邮件或电子表格中查找。 您只需要一个简单的查询。
将以下内容保存为名为 open-invoices.sql
的文件:
SELECT
meta('invoice_id') AS id,
payee,
narration,
date,
number(balance) AS outstanding
WHERE
account = "Assets:AccountsReceivable"
AND balance != 0
ORDER BY
date;
现在,从您的命令行运行它:
bean-query books.beancount open-invoices.sql
几秒钟内,您将获得一份清晰的、最新的所有未结发票的账龄报告,其中显示发票 ID、客户、开票日期和欠款金额。 无需额外的软件。
自动化繁琐的工作
纯文本的优点在于可编写脚本。 您可以自动化此工作流程中繁琐的部分。
- **模板 + Pandoc = PDF:**以 Markdown 格式维护您的发票模板。 一个小型 Python 脚本可以填充变量(客户名称、项目明细、发票编号),命令行工具 Pandoc 可以立即将其转换为专业的 PDF。
- **Git 预提交钩子:**如果您将账本存储在 Git 中,一个简单的预提交钩子可以在您保存工作之前运行检查。 它可以验证每个新的
invoice_id
是否唯一,交易过账是否平衡为零,以及link:
元数据中引用的文件是否实际 存在。 - **Cron 作业:**设置计划任务(cron 作业)以每晚运行您的
open-invoices.sql
查询并通过电子邮件向您发送摘要。 您将每天开始工作时确切地知道谁需要友好的提醒。
现实的警告
Beancount 是一个会计工具,而不是开票_服务_。 它不会自动向您的客户发送付款提醒或处理他们的信用卡付款。 工作流程是:您使用您选择的方法(例如上面的模板)创建并发送发票,然后在您的账本中记录会计分录。
对于大多数自由职业者和小商店来说,这个手动步骤对于一个完全拥有和控制的、防弹的、可审计的免费会计系统来说是一个很小的代价 (beancount.io)。
后续步骤
准备好控制您的开票了吗? 以下是开始的方法。
- 下载模板并使用它创建您的下一个真实发票,确保使用连续的发票编号。
- 将您发送的 PDF存储在专用文件夹中,例如
docs/invoices/
,并在您的 Beancount 交易中使用link:
元数据键来引用它们。 - 保存
open-invoices.sql
查询并将其作为您每周财务审查的一部分运行。
纯文本会计并不意味着放弃完善或控制——它只是意味着数据库是可 grep
的。 使用简单的模板和上面的代码片段,您将更快地获得付款_并 且_保持您的账簿整洁。