Financial Overview¶
Craft Easy ships with a full-stack financial system: payments, invoicing, subscriptions, claims, payment plans, revenue splits, settlements, and double-entry bookkeeping. Every piece is opt-in — a plain CRUD API can ignore all of them — but if you turn on even one, the rest are designed to slot in cleanly alongside it.
This section documents each subsystem as a user would approach it: what it does, how to configure it, which endpoints to call, and how it connects to the rest. This page is the orientation map.
The money flow¶
A Craft Easy deployment has three financial actors:
┌──────────────────┐
│ System Owner │ the platform vendor
│ (you) │
└────────┬─────────┘
│ service fees, self-billing
│ revenue share
▼
┌──────────────────┐
│ Tenant │ a customer organization
│ (your customer) │
└────────┬─────────┘
│ customer charges
│ claim recovery
▼
┌──────────────────┐
│ Customer │ the tenant's end-user
│ (their customer) │
└──────────────────┘
Money moves in both directions:
- Customer → Tenant — the tenant's revenue. Usually captured through a payment provider (Stripe, Klarna, Swish) and tracked as a
Payment. If the payment fails, the debt becomes aClaimthat can be recovered over time. - Tenant → System Owner — service fees and revenue share. Settled at the end of each billing period as a
Settlement, with the system owner withholding its cut before paying the tenant. - System Owner → Tenant — payouts (the tenant's share of customer revenue) and credit notes. Paid out as a
PayoutBatch, posted against the tenant's payout account.
Every arrow in that diagram is recorded twice: once as a business object (a payment, an invoice, a settlement) and once as a pair of ledger entries in the double-entry books. The business objects drive workflow; the ledger entries drive reporting and external accounting exports.
The subsystems at a glance¶
| Subsystem | Purpose | Core service | Models |
|---|---|---|---|
| Payments | Customer-facing payment capture, refunds, payouts | PaymentService |
Payment, PayoutBatch, PaymentAccount |
| Payment Providers | Pluggable Stripe, Klarna, Swish, custom | PaymentProviderRegistry |
TenantProviderConfig |
| Invoicing | Service-fee, customer-charge, self-billing, credit notes | InvoiceService |
Invoice, InvoiceLineItem |
| Billing & Subscriptions | Recurring plans with retry schedules | BillingService |
RecurringBillingPlan, Subscription |
| Claims | Interest accrual, dispute and escalation | ClaimService |
Claim, CollectionFlow |
| Payment Plans | Installment plans attached to claims | PaymentPlanService |
PaymentPlan, Installment |
| Revenue Splits | Date-based percentage, fixed, tiered splits | RevenueSplitService |
RevenueSplitRule, RevenueSplitRecord |
| Settlements & Payouts | Period payout, auto-approval, allocation | SettlementService, AllocationService |
Settlement, SettlementOrder |
| Bookkeeping | Double-entry ledger, BAS chart of accounts, SIE4 export | BookkeepingService |
LedgerEntry, Account |
| Client Funds | Segregated client money accounts | — | ClientFundAccount, ClientFundTransaction |
Multi-currency¶
Every amount in the financial system is a Decimal — there are no float values anywhere in the code, because float arithmetic loses pennies. Currencies are represented by their ISO 4217 code, and craft_easy.core.money.CURRENCIES tracks how many decimal places each one uses:
| Currency | Decimal places |
|---|---|
| SEK, NOK, DKK, EUR, USD, GBP, CHF, PLN | 2 |
| ISK, JPY | 0 |
The MoneyAmount value object wraps an amount and its currency together, and refuses to add two amounts in different currencies. Every service method that takes money values takes amount + currency so cross-currency mistakes surface immediately.
A tenant declares its default currency on the Tenant document, plus an optional list of allowed currencies. When a payment is created without specifying a currency, the default is used. Attempting to create a payment in a currency that is not in enabled_currencies fails at the service layer before any provider is called.
Enabling the financial stack¶
There is no "turn on the financial system" switch — each subsystem has its own:
class Settings(CraftEasySettings):
PAYMENTS_ENABLED: bool = False
DEFAULT_CURRENCY: str = "SEK"
DEFAULT_VAT_RATE: Decimal = Decimal("0.25")
SEED_DEFAULT_ACCOUNTS: bool = True # seeds BAS chart of accounts on first boot
# plus provider-specific keys — STRIPE_*, KLARNA_*, SWISH_* — documented per page
Typical rollout order, from easiest to most demanding:
- Bookkeeping — immediate, no external dependencies. Post ledger entries from day one, even if you have no payments yet.
- Invoicing — no payment provider required. Useful on its own for systems that bill by bank transfer.
- Payments + one provider — turn on
PAYMENTS_ENABLED, register one provider (Stripe is usually the fastest to onboard), set up webhooks. - Settlements — once payments are flowing, configure each tenant's
SettlementOrderand turn on the settlement runner. - Billing — add recurring plans once one-time payments work.
- Claims, payment plans, collection flow — add these when you need to recover failed or unpaid receivables.
- Revenue splits — once you have a partner model and need to share revenue with third parties.
Every subsystem is tenant-scoped, so you can enable them per tenant via their agreement — a tenant without the invoicing feature simply cannot reach the invoice routes.
Where to go next¶
If you are starting fresh, read Payments and Payment Providers first — they cover the core capture loop.
If you are adding recurring billing, jump to Billing & Subscriptions.
If you are implementing debt recovery, start at Claims, then Payment Plans.
If you need accounting-grade books, read Bookkeeping — it has the SIE4 example and the chart of accounts.
If you care about how money leaves the system, read Settlements & Payouts — that is where the tenant actually gets paid.