10. Credits (CR):
- $97 on liability payables
(we will pay the merchant)
- $3 Credit on P&L interchange
(our profit)
- $100 on off-balance
asset current-limit
EXAMPLE: A purchase of $100
Debits (DR):
- $100 on asset settled
(we will receive
it from the customer)
- $100 on off-balance
liability current-limit-cp
11. EXAMPLE: A payment of $100
Debits (DR):
- $100 on asset cash
(we received it
from the customer)
- $100 on off-balance
asset current-limit
Credits (CR):
- $100 on asset settled
(we paid the purchase)
- $100 on off balance
liability current-limit-cp
12. DOUBLE ENTRY ACCOUNTING
EVENTS TRIGGERING MOVEMENTS
• purchases
• payments
• bills
IMMUTABLE
• append-only
• entry log
• can fix past by compensating
INVARIANTS
• movements sums to zero
• a book-account balance is sum of credits
and debits
13. 1 MOVEMENT => N ENTRIES
(s/defschema Entry {:entry/id s/Uuid
:entry/amount PositiveAmount
:entry/debit-account BookAccount
:entry/credit-account BookAccount
:entry/post-date LocalDate
:entry/movement Movement})
So by design,
(ns double-entry.models.entry
(:require [schema.core :as s]))
14. 1 BUSINESS EVENT => 1 MOVEMENT + META
e.g new-purchase, new-payment, new-bill
(s/defschema Movement {:movement/id s/Uuid
:movement/flow-id String
:movement/topic Topic
:movement/owner-account Account
:movement/produced-at LocalDateTime
:movement/consumed-at LocalDateTime
:movement/user String})
(s/defschema Meta {:meta/id s/Uuid
:meta/movement Movement
:meta/entity (s/either Payment Purchase Bill ...)})
20. Cumulative cache
(balance sheet)
Event
(log)
2 LOGS AND A CACHE
ACTUAL TIME
audit trail / Datomic log
“when did we know”day 0 day 30 day 90
SYSTEM OF RECORD TIME
official version of events
uses business-relevant “post dates”
can correct after the fact
day 90
day 0day 0
day 30
21. SANITY CHECKS / BUSINESS INVARIANTS
• Balances must be always positive or always negative
• Cannot have a “late” balance there is a “prepaid” balance
• A purchase should “move” exactly the purchase amount on
assets and on current limit
24. 1. Business events generate idempotent Kafka
messages
2. For each event, apply functions to convert the
event data into a movement with 1+ entries
• Movements balance by design
• Movements associate provenance metadata
3. Pre-check guarantees invariants against db value
4. Eagerly cache resulting balances
debit-account credit-account amount
a/max-limit
a/current-limit
l/max-limit-cp
l/current-limit-cp
initial-limit
15000.00
15000.00
CARD ISSUED
31. DETECTING OPERATIONAL MISTAKES
USE CASES
MANAGEMENT ACCOUNTING
• delinquency tables by cohort and aging
• receivables (domestic, foreign, financed)
• revenue per customer (interchange, interest, fx spread)
REPORTING
• covenants
• regulatory
FINANCIAL ACCOUNTING
• consolidate to ERP
32. Declarative rules are extensible for additional financial products
(e.g., already extending to rewards, debt financing)
Financial analysis applies at a micro level (negative balances,
weird ratios, operational problems)
Business-specific invariants provide safety (declare mutually
exclusive and impossible states,alert unexpected situations)
Generative testing finds real bugs
Service is shardable by customer account (no interactions
between accounts)
WHAT DO WE LIKE?
33. 33
IF YOU ARE ENTRUSTED WITH A CUSTOMER’S
FINANCIAL RELATIONSHIP, CONSIDER BUILDING A
DOUBLE-ENTRY SYSTEM FOR YOUR DOMAIN