PRC-22Recommended
Export balanced journals to the accounting system each period
At each period end, export the period's journal entries, summed per account and currency, to the general ledger. Each export is balanced, numbered and reconciled against the ledger totals before the period closes.
How to do it
Accountants post summaries, not every charge. Map each ledger account to an account number in the chart of accounts the accountant uses. Export once per period with a unique export ID, so a rerun replaces the file instead of posting twice. Close the period after export, and book later corrections in the next open period. Reconcile payouts first, as Reconcile every payout says, so cash in the export matches the bank. The entries come from Book every money movement as balanced double-entry postings.
Examples
TypeScript example
export async function exportPeriod(db, period: string) {
const lines = await db.query(
`SELECT a.gl_number, p.currency, sum(p.amount_minor) AS amount_minor
FROM postings p JOIN journal_entries e ON e.id = p.entry_id JOIN gl_accounts a ON a.account = p.account
WHERE to_char(e.occurred_at, 'YYYY-MM') = $1 GROUP BY a.gl_number, p.currency`, [period])
const unbalanced = Object.values(Object.groupBy(lines.rows, l => l.currency))
.some(rows => rows.reduce((sum, l) => sum + BigInt(l.amount_minor), 0n) !== 0n)
if (unbalanced) throw new Error(`Period ${period} does not balance`)
return { exportId: `gl-${period}`, lines: lines.rows }
}
Python example
from collections import defaultdict
def export_period(db, period: str) -> dict:
lines = db.execute(
"""SELECT a.gl_number, p.currency, sum(p.amount_minor)
FROM postings p JOIN journal_entries e ON e.id = p.entry_id JOIN gl_accounts a ON a.account = p.account
WHERE to_char(e.occurred_at, 'YYYY-MM') = %s GROUP BY a.gl_number, p.currency""", (period,)).fetchall()
totals = defaultdict(int)
for _, currency, amount in lines:
totals[currency] += amount
if any(totals.values()):
raise ValueError(f"Period {period} does not balance")
return {"export_id": f"gl-{period}", "lines": lines}
How to check
A test exports a closed month. The export's debits equal its credits in every currency, and each account total equals the ledger total for that month. A second export of the same month has the same ID and the same lines. A posting dated in a closed month is refused.
Related rules
- PAY-22 Reconcile every payout in Payments and billing
- PRC-18 Book every money movement as balanced double-entry postings in Pricing, plans and entitlements
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/pricing/ledger-and-accounting/general-ledger-export">Agent Wranglers pricing, plans and entitlements playbook</a>. In code you write, add a comment next to it with the same link.