Finance & Billing
246 features · 20 subsystems
Financial management across all federation levels. Leverages Craft-Easy's financial primitives (payments, invoicing, billing, bookkeeping) extended with petanque-specific financial workflows.
Fee Management
F08.01- F08.01.01 Shipped
Composite license fee configuration — license fee = sum of configurable components set at different OrgNode levels. Example France: part fédérale (set by FFPJP) + part ligue (set by ligue régionale) + part comité (set by comité départemental) + assurance. Each component configurable per license type, age, category. Supports regional price variation (France, Spain).
✅ PL-F0801a - F08.01.02 Shipped
Club affiliation fee configuration (flat or per-member)
✅ PL-F0801a - F08.01.03 Shipped
Competition entry fee management
✅ PL-F0801a - F08.01.04 Shipped
Fee schedules per season/year
✅ PL-F0801a - F08.01.05 Shipped
Early bird / late fee surcharges
✅ PL-F0801a - F08.01.06 Shipped
Fee waivers and discounts (youth, veteran, disabled, family) — configurable per tenant (e.g., Sweden: no sanction fee for youth classes)
✅ PL-F0801b - F08.01.07 Shipped
Fee splitting with automatic distribution — when a license is purchased, the system automatically splits the payment to the correct recipients (federation account, regional account, district account, insurance). Configurable split ratios per OrgNode level.
✅ PL-F0801b - F08.01.08 Shipped
Fee history and audit trail
✅ PL-F0801b - F08.01.09 Shipped
Sanction fee per competition class — configurable per tenant (e.g., Sweden: 300 SEK per class, paid to district where competition is held). Supports different fee rules per competition level.
✅ PL-F0801b - F08.01.10 Shipped
License suspension administrative fee — configurable per tenant (e.g., Sweden: 2× senior license fee, charged to the club requesting suspension)
✅ PL-F0801b
Payment Processing
F08.02- F08.02.01 Shipped
✅ Payment recording and status tracking
- F08.02.02 Planned
✅ Online payment gateway integration (Stripe, PayPal, local providers)
- F08.02.03 Planned
✅ Bank transfer payment matching
- F08.02.04 Shipped
✅ Payment receipt generation
- F08.02.05 Planned
✅ Installment payment plans (split license fee over months)
- F08.02.06 Shipped
✅ Payment reconciliation
- F08.02.07 Planned
✅ Refund processing
- F08.02.08 Planned
✅ Club bulk payment (club pays all member licenses)
- F08.02.09 Planned
✅ Multi-currency support (international competitions)
- F08.02.10 Shipped
✅ Payment audit trail
- F08.02.11 Shipped
✅ Affiliate hybrid signup med Stripe Payment Link — gated av sys_support-godkännande, 14 d expiry, valuta klassificeras per land (SE→SEK, NO→NOK, DK→DKK, GB→GBP, CH→CHF, övriga→EUR), webhook driver provisionering via PL-T003
✅ PL-T302
Invoicing
F08.03- F08.03.01 Shipped
Invoice generation (line items, tax, totals)
✅ PL-F0803a - F08.03.02 Shipped
Automatic invoice generation (license renewal, affiliation)
✅ PL-F0803a - F08.03.03 Shipped
Invoice templates per federation
✅ PL-F0803a - F08.03.04 Shipped
Invoice delivery (email, download)
✅ PL-F0803a - F08.03.05 Planned
✅ Credit note management
- F08.03.06 Shipped
✅ Invoice status tracking (draft, sent, paid, overdue)
- F08.03.07 Planned
✅ Payment reminder automation
- F08.03.08 Shipped
✅ Debt collection workflow — involuntary dunning lifecycle: banner → 6 months read-only → +12 months data deletion
✅ PL-T047 - F08.03.09 Shipped
Multi-issuer invoicing — Invoice.issuer_type ∈ {platform, tenant, org_node} + issuer_tenant_id/issuer_org_node_id separerar utställare från gäldenär; cross-tenant-fakturor möjliga (FIPJP → nationsförbund); validatorer enforcerar konsistens; backfill-skript sätter historiska fakturor till platform-utställda.
✅ PL-T091 - F08.03.10 Shipped
Multi-language invoicing + ECB reference rate — Invoice.language (ISO-639-1) + per-språk PDF-templates (templates/invoice/{template_name}/{lang}.html) med en.html-fallback + structlog-warning; plattformsfakturor låsta till engelska; ECB-referenskurs fångad per faktura vid utfärdande (ecb_reference_rate + ecb_reference_date) för audit-spårbarhet i cross-currency-scenarier.
✅ PL-T091
Dunning & Payment Enforcement
F08.09**Status:** PL-T047 implemented
How it works- F08.09.01 Shipped
Involuntary dunning lifecycle: banner_only → final_warning → read_only → pre_deletion → deleted
✅ PL-T047 - F08.09.02 Shipped
Persistent payment-overdue banner visible to all tenant users (not just admins)
✅ PL-T047 - F08.09.03 Shipped
Email cascade to all tenant admins at each dunning stage transition
✅ PL-T047 - F08.09.04 Shipped
Stripe webhook integration: invoice.payment_failed opens case, invoice.paid closes (if ≤ final_warning)
✅ PL-T047 - F08.09.05 Shipped
Contract billing integration: 30-day overdue triggers dunning case
✅ PL-T047 - F08.09.06 Shipped
Platform-admin manual waive with mandatory reason + governance audit log
✅ PL-T047 - F08.09.07 Shipped
Anti-scope: no auto-reactivation after read_only — manual waive required
✅ PL-T047 - F08.09.08 Shipped
Voluntary cancellation during active dunning case closes dunning cleanly
✅ PL-T047
Federation Budgeting
F08.04- F08.04.01 Shipped
Annual budget creation per federation
✅ PL-F0804 - F08.04.02 Shipped
Budget categories (competitions, administration, development, travel, etc.)
✅ PL-F0804 - F08.04.03 Shipped
Budget vs. actual tracking
✅ PL-F0804 - F08.04.04 Shipped
Budget approval workflow
✅ PL-F0804 - F08.04.05 Shipped
Financial report generation (annual, quarterly)
✅ PL-F0804 - F08.04.06 Shipped
Bookkeeping / ledger entries
✅ PL-F0804
Sponsorship & Grants
F08.05- F08.05.01 Shipped
Sponsor registry (company, contact, contract period, amount)
✅ PL-F0805 - F08.05.02 Shipped
Sponsorship contract management
✅ PL-F0805 - F08.05.03 Shipped
Sponsor exposure tracking (logo placement, mentions)
✅ PL-F0805 - F08.05.04 Shipped
Grant application tracking (government, sports council)
✅ PL-F0805 - F08.05.05 Shipped
Grant reporting and accountability
✅ PL-F0805 - F08.05.06 Shipped
Sponsorship revenue allocation (competition, federation, club)
✅ PL-F0805 - F08.05.07 Shipped
Grant application workflow — MinistryGrantApplication med 8-state-machine (draft → submitted → under_review → awarded → in_progress → reporting_due → closed; rejected som terminal-gren)
✅ PL-T223 - F08.05.08 Shipped
Multi-stage status — capability-gated transitions via submit/record_decision/mark_in_progress/close med immutabel audit-trail
✅ PL-T223 - F08.05.09 Shipped
Reporting-due reminder — daglig cron-trigg 30/14/7 dagar före closes_at, deduplicerad per bucket, status promoveras till reporting_due vid minsta bucket
✅ PL-T223
Prize Money & Awards
F08.06- F08.06.01 Planned
✅ Prize pool configuration per competition
- F08.06.02 Planned
✅ Prize money distribution rules
- F08.06.03 Planned
✅ Winner payment processing
- F08.06.04 Planned
✅ Tax reporting for prize money
- F08.06.05 Planned
✅ Trophy and medal inventory tracking
Expense Management
F08.07- F08.07.01 Shipped
Expense claim submission (umpires, officials, delegates)
✅ PL-F0807 - F08.07.02 Shipped
Travel expense calculation (distance, per diem)
✅ PL-F0807 - F08.07.03 Shipped
Expense approval workflow
✅ PL-F0807 - F08.07.04 Shipped
Expense reimbursement processing
✅ PL-F0807 - F08.07.05 Shipped
Expense category reporting
✅ PL-F0807
Financial Reporting
F08.08- F08.08.01 Shipped
Revenue reports (by source: licenses, competitions, sponsorship)
- F08.08.02 Shipped
Expense reports (by category)
- F08.08.03 Planned
Federation financial summary (upward reporting)
- F08.08.04 Planned
Club financial health indicators
- F08.08.05 Planned
Multi-year trend analysis
- F08.08.06 Planned
Export to accounting software (CSV, SAFT, SIE)
Bokföring och redovisning
F08.10- F08.10.01 Shipped
Sverige - Fortnox-export — semikolonseparerad CSV med VER/Serie/Vernr/Datum/Text/Konto/Debet/Kredit. Svenskt decimalformat (komma). Exporterar endast bokförda verifikationer. Använder per-tenant kontoplansmappning.
✅ PL-F0810a - F08.10.02 Shipped
International - Xero-export — kommaseparerad CSV med *Date/*Description/*AccountCode/*Debit/*Credit/TaxType/Reference. Internationellt decimalformat (punkt). Per-tenant kontoplansmappning.
✅ PL-F0810a - F08.10.03 Shipped
Sverige - Visma eEkonomi-export — tabbseparerad textfil med VER/Serie/Vernr/Datum/Text/Konto/Debet/Kredit/Projekt/Resultatenhet. Svenskt decimalformat. Stödjer API-synkronisering via integrationsconfig.
✅ PL-F0810a - F08.10.04 Shipped
Per-tenant chart of accounts mapping — ChartOfAccountsMapping-samling tenant-scopad. Översätter interna BAS-konton till externa leverantörskonton. En aktiv mappning per provider per tenant. CRUD med duplikatskydd (409).
✅ PL-F0810a - F08.10.05 Shipped
SIE4-export med IB/UB/RES — utökad SIE4-export (GET /accounting-export/sie4) med #KTYP kontotyper, #IB ingående balanser, #UB utgående balanser, #RES resultaträkningskonton. CP437-encoding, fiscal_year/company_name/org_number-parametrar.
✅ PL-F0810b - F08.10.06 Shipped
Bokslut per säsong — generering av bokslut (financial statements) med resultaträkning- och balansräkningsögonblicksbilder. Status draft→finalized livscykel. Valfri periodlåsning vid finalisering. CRUD /financial-statements/.
✅ PL-F0810b - F08.10.07 Shipped
Revisionsspår och låsning av perioder — periodlåsning förhindrar skapande/bokföring/makulering av verifikationer inom låst datumintervall. CRUD + check + unlock /period-locks/. Överlappande lås avvisas. Komplett audit trail via FinancialAuditLog.
✅ PL-F0810b - F08.10.08 Shipped
Resultaträkning och balansräkning per OrgNode — konsoliderade rapporter per kostnadställe. GET /accounting-reports/consolidated-income-statement och /consolidated-balance-sheet med org_node_id-nedbrytning. Kvartalsfilter.
✅ PL-F0810b - F08.10.09 Shipped
Bokio SIE4-export — Bokio-specifik SIE4-variant med UTF-8 BOM, CRLF-radslut, BAS-2024-validering (1000–8999), obligatoriskt #ORGNR. GET /accounting/bokio/export/sie4.
✅ PL-T078 - F08.10.10 Shipped
Bokio direkt-API — OAuth2-onboarding + synkron/batch-POST av verifikationer till Bokio REST API med idempotency-nycklar. Token-refresh 5 min före expiry. Error-hantering: 401 retry, 409 ignore, 422 fail, 429 backoff.
✅ PL-T078 - F08.10.11 Shipped
Bokio sync-jobb — batch-sync var 15 min (eller on-demand), plockar entries med synced_to_bokio_at is None, POST till Bokio per entry, markerar synced med external_refs.bokio. Max 3 retries med exponentiell backoff.
✅ PL-T078 - F08.10.12 Shipped
Bokio onboarding-flow — POST /accounting/bokio/configure (company_id, sync_mode api/sie4_only), OAuth-URL för API-läge, test-connection via get_fiscal_years(). Admin-vy med provider-kort, Sync Now-knapp, SIE4-nedladdning.
✅ PL-T078
Per-nationell ekonomi och avgifter
F08.09- F08.09.01 Shipped
Per-tenant license fee with annual revision
✅ PL-F0809a - F08.09.02 Shipped
Per-tenant VAT/MOMS/TVA/IVA configuration
✅ PL-F0809a - F08.09.03 Shipped
Per-tenant invoice number series
✅ PL-F0809a - F08.09.04 Shipped
Per-tenant payment term rules (30/60/90 days)
✅ PL-F0809a - F08.09.05 Shipped
France SEPA Direct Debit for club fees
✅ PL-F0809a - F08.09.06 Shipped
Sverige - Swish som default-betalsätt — per-debtor-type betalningspolicy med min/max-belopp, Swish som default för spelare
✅ PL-F0809b - F08.09.07 Shipped
Deutschland - SEPA-Lastschrift — Basislastschrift (CORE) och Firmenlastschrift (B2B) via SEPA-mandathantering
✅ PL-F0809b - F08.09.08 Shipped
Espana - Bizum för spelare-betalningar — Bizum med beloppstak (max 1 000 EUR), fallback till kort vid överskridande
✅ PL-F0809b - F08.09.09 Shipped
Per-tenant valutahantering — basvaluta, stödda valutor, decimalplatser, avrundningsläge, visningsformat
✅ PL-F0809b - F08.09.10 Shipped
Multi-currency rapportering för FIPJP/CEP — konsoliderade flervaualtarapporter med växelkursupplösning, kategoribrytning, finalisering
✅ PL-F0809b
Pricing Catalog
F08.10- F08.10.01 Shipped
14-SKU pricing catalog data model — TenantBillingType (14 enums), BillingMode (self_service/contract), PricingCatalogVersion (versioned, immutable), PricingTier (per-version, per-billing-type, Decimal EUR price, i18n display/description/includes).
✅ PL-T011 - F08.10.02 Shipped
Seed data v2026.01 — Idempotent seed script skapar initial katalog med exakta priser från market-analysis.md A2. 7 self-service + 7 contract tiers. i18n för en/fr/es/sv.
✅ PL-T011 - F08.10.03 Shipped
Admin pricing catalog API — GET /admin/pricing-catalog/current (14 tiers), /versions (historik), /versions/{id}, /tiers/{billing_type}. Platform-admin auth.
✅ PL-T011 - F08.10.04 Shipped
Public pricing API — GET /public/pricing (7 self-service tiers, no auth, Cache-Control max-age=300).
✅ PL-T011 - F08.10.05 Shipped
Admin pricing catalog UI — Read-only list- och detaljvy i admin under Platform > Pricing Catalog. 14 tiers i tabell, detaljvy med i18n-fält, Stripe-ID:n, license-range.
✅ PL-T011 - F08.10.06 Shipped
National tier auto-classification — resolve_national_tier_from_license_count: 0–999→XS, 1000–2999→S, 3000–9999→M, ≥10000→L.
✅ PL-T011 - F08.10.07 Shipped
Publicera ny version (write-UI i admin)
✅ PL-F0810b - F08.10.08 Shipped
Prishistorik per kund (koppling via Subscription)
✅ PL-F0810b - F08.10.09 Shipped
Tenant-typ-bryggad pricing-katalog (PL-T226) — PricingTier utökas med tenant_type (broad till TenantType) + denormaliserade domain_count / subsystem_count / feature_count från TENANT_TIER_MATRIX. TENANT_TYPE_FOR_BILLING_TYPE ger reverse-lookup för Stripe-webhook + drift-job. Migration tools/migrations/pl-t226-tenant-type-pricing.py är idempotent.
✅ PL-T226 - F08.10.10 Shipped
Public detail-endpoint för tier-jämförelser (PL-T226) — GET /public/pricing-tiers (full 14-rad-katalog med ?include_legacy=true för 15) + GET /public/pricing-tiers/{tenant_type} (deep-link med included_subsystems / excluded_subsystems från matrisen). 5 min cache. Service tier_for_tenant_type() routar FEDERATION mot national_* via license-count.
✅ PL-T226 - F08.10.11 Shipped
Pricing tier sync-check job (PL-T226) — nattlig jämförelse av PricingTier-tabellen mot www/src/data/tenant-tiers.ts. SEV2 platform-event vid divergens.
✅ PL-T226
Subscription Management
F08.11## Implementation Status
How it works- F08.11.01 Shipped
Subscription datamodell med pricing_version — varje Subscription kopplas till en pricing_version (ISO-datum) som identifierar den prislista som gällde vid avtalstillfället. Oförändrat vid förnyelse. Indexerat för rapportqueries.
✅ PL-T042 - F08.11.02 Shipped
Price-Lock Guarantee — formell policy: priset som pricing_version anger gäller så länge Subscription:en är aktiv. Inga automatiska prishöjningar vid förnyelse. Publicerad på petanque.life/price-lock-guarantee (4 språk).
✅ PL-T042 - F08.11.03 Shipped
Subscription CRUD-livscykel (PL-T285) — PUT /subscriptions/{id} uppgraderar tier inom låst pricing_version (downgrades blockas 422). POST /subscriptions/{id}/cancel med immediate=False (default) eller True (sys_finance + fresh-auth). POST /subscriptions/{id}/renew är idempotent på (subscription_id, period_start, period_end). DELETE /subscriptions/{id} soft-deletar (sys_finance + fresh-auth) — blockeras vid obetalda fakturor. Audit via write_finance_audit.
✅ PL-T285 - F08.11.04 Shipped
Pricing-version-rapport (PL-T285) — GET /sys/billing/subscription-report/by-pricing-version?include_cancelled=<bool> aggregerar antal aktiva subscriptions och låst årsintäkt per pricing_version, plus tenant-typ-fördelning. Cache 5 min via Redis. Sys-konsol-vy sys/app/(dashboard)/billing/subscription-report.tsx med trendgraf och tabell.
✅ PL-T285 - F08.11.05 Shipped
Auto-renewal-jobb (PL-T285) — subscription_auto_renewal_job körs varje timme via craft-easy-jobs, plockar auto_renew=True AND status=ACTIVE AND next_renewal_at <= now, skapar Invoice via existerande pipeline med oförändrat pricing_version. Retry 1h/2h/4h, sedan dunning (PL-T047). Drift-detektion subscription_renewal_drift (SEV2) när jobbet inte körts >25h. Audit subscription.auto_renewed / subscription.auto_renewal_failed.
✅ PL-T285 - F08.11.06 Shipped
ECB-kvartalsfixing för lokal valuta — formell policy: fakturering i lokal valuta sker enligt ECB:s kvartalsfixade referensväxelkurser. Fixing första bankdagen i januari, april, juli, oktober. Stödda valutor: EUR, SEK, NOK, DKK, GBP, USD, CHF. Varje faktura sparar ecb_fixing_rate och ecb_fixing_date för historisk reproducerbarhet. Publicerad på petanque.life/currency-policy (4 språk).
✅ PL-T043 - F08.11.07 Shipped
Tenant-typ-tier-byte via Stripe Subscription Schedule (PL-T226) — POST /sys/billing/{tenant_id}/change-tier (sys_finance + fresh-auth) byter TenantConfig.tenant_type, repointar TenantSubscription mot ny TenantBillingType, skapar Stripe Subscription Schedule prorated, invaliderar TenantTierResolver-cachen och skriver tenant.tier.billing_changed + tenant.tier.synced_from_stripe-audit. Companion-endpoint …/change-tier/quote är read-only förhandsbesked. Downgrades från federation-grade SKU blockas (422 tier_downgrade_blocked).
✅ PL-T226 - F08.11.08 Shipped
Tenant-facing upgrade-quote + ROI-räknare (PL-T226) — POST /admin/billing/upgrade-quote returnerar prorated belopp + pre-fylld contact-sales/?topic=tier-upgrade-URL. Admin-vyn views/billing/SubscriptionView.tsx läser GET /me/tenant-tier, listar inkluderade delsystem och låter kunden simulera tier-byte. Faktiska byten ligger hos sys-operator.
✅ PL-T226 - F08.11.09 Shipped
Stripe webhook tenant_type-sync + drift-job (PL-T226) — customer.subscription.updated läser metadata.tenant_type, applicerar om det driftat, skriver tenant.tier.synced_from_stripe-audit + bustar tier-resolver-cachen. Job stripe_subscription_drift_check (varje timme) fångar oöverensstämmelser → billing_health=warning + SEV2 platform-event.
✅ PL-T226 - F08.01.01 Shipped
/license-fee-configs/, /license-fee-overrides/, /license-fees/calculate
✅ PL-204 - F08.01.02 Shipped
/fee-schedules/ (fee_category=club_affiliation, med affiliation_tiers)
✅ PL-801 - F08.01.03 Shipped
/fee-schedules/ (fee_category=competition_entry)
✅ PL-801 - F08.01.04 Shipped
/fee-management/copy-season (säsongskopiering), /fee-management/by-season/{id} (konsoliderad vy)
✅ PL-F0801a - F08.01.05 Shipped
/fee-surcharge-rules/ (CRUD), /fee-surcharges/calculate (early bird/late fee)
✅ PL-F0801a - F08.01.07 Shipped
/revenue-distribution-rules/ + automatisk distribution vid betalning
✅ PL-801 - F08.01.09 Shipped
/fee-schedules/ (fee_category=sanction)
✅ PL-801 - F08.02.01 Shipped
/payments/ (registrera, spåra, återbetala)
✅ PL-801 - F08.03.01 Shipped
/invoices/ (skapa, rader, summor)
✅ PL-801 - F08.03.02 Shipped
Automatisk faktura vid licensgodkännande
✅ PL-801 - F08.03.06 Shipped
Fakturastatus: draft → sent → paid/overdue/cancelled
✅ PL-801 - F08.03.07 Shipped
/invoices/{id}/send-reminder
✅ PL-801 - F08.03.08 Shipped
/debts/check/{debtor_id} — blockerar transfer och licensförnyelse
✅ PL-801 - F08.08.01 Shipped
/financial-reports/revenue, /financial-reports/revenue/by-org-node
✅ PL-801 - F08.02.02 Shipped
/checkout/ (Stripe Checkout Session), /webhooks/stripe
✅ PL-802 - F08.02.02 Shipped
/checkout/ (Swish QR-betalning), /webhooks/swish
✅ PL-802 - F08.02.04 Shipped
/receipts/, /receipts/{id}/pdf (kvittogenerering)
✅ PL-802 - F08.02.06 Shipped
Automatisk avstämning via Stripe/Swish webhooks
✅ PL-802 - F08.02.07 Shipped
/payments/{id}/gateway-refund (återbetalning via gateway)
✅ PL-802 - F08.02.10 Shipped
Betalningsspårning: /payment-history/{debtor_id}
✅ PL-802 - F08.03.01 Shipped
/invoices/ utökad med tax_rate per rad, tax_amount, tax_total
✅ PL-F0803a - F08.03.02 Shipped
/invoices/auto-generate/license-renewal, /invoices/auto-generate/affiliation
✅ PL-F0803a - F08.03.03 Shipped
/invoice-templates/ (CRUD, per-federation, default-hantering)
✅ PL-F0803a - F08.03.04 Shipped
/invoices/{id}/pdf (PDF-nedladdning), /invoices/{id}/deliver (e-postleverans)
✅ PL-F0803a - F08.03.05 Shipped
/credit-notes/ (CRUD, issue, apply, void — kreditnotor mot fakturor)
✅ PL-F0803b - F08.03.06 Shipped
/invoices/{id}/status-history, /invoices/mark-overdue (statusspårning med historik)
✅ PL-F0803b - F08.03.07 Shipped
/reminder-configs/, /invoices/reminder-queue, /invoices/send-due-reminders (påminnelseautomatik)
✅ PL-F0803b - F08.03.08 Shipped
/debt-collection/ (CRUD, escalate, resolve — inkassoworkflow)
✅ PL-F0803b - F08.05.01 Shipped
/sponsors/ (CRUD med kontaktinfo, nivå, sponsrade entiteter)
✅ PL-F0805 - F08.05.02 Shipped
/sponsors/{id}/contracts (kontraktshantering med belopp, period, villkor)
✅ PL-F0805 - F08.05.03 Shipped
/sponsors/{id}/exposure (exponeringsregistrering och sammanfattning)
✅ PL-F0805 - F08.05.04 Shipped
/grants/ (ansökan: draft → submitted → approved/rejected → reporting)
✅ PL-F0805 - F08.05.05 Shipped
/grants/{id}/reports (bidragsrapportering efter godkännande)
✅ PL-F0805 - F08.05.06 Shipped
/sponsor-allocations/ (intäktsallokering per OrgNode med procentsatser)
✅ PL-F0805 - F08.04.01 Shipped
/budgets/ (CRUD med inkomst-/utgiftskategorier per OrgNode), /budgets/copy (kopiera med inflationsjustering)
✅ PL-F0804 - F08.04.02 Shipped
BudgetCategory med type: income/expense, kopplad till kontoplan
✅ PL-F0804 - F08.04.03 Shipped
/budgets/{id}/actualize + /budgets/{id}/variance (budget vs. faktisk)
✅ PL-F0804 - F08.04.04 Shipped
draft → proposed → approved → closed (godkännandeflöde med audit log)
✅ PL-F0804 - F08.04.05 Shipped
/accounting-reports/income-statement (årsvis + kvartalsvis med quarter-param), /accounting-reports/budget-tracking, /accounting-reports/balance-sheet
✅ PL-F0804 - F08.04.06 Shipped
/accounting-entries/ (verifikationer med kontoplan), /accounting-export/sie + /fec + /json
✅ PL-F0804 - F08.01.04 Shipped
/fee-management/copy-season (kopiera avgiftsdata), /fee-management/by-season/{id}
✅ PL-F0801a - F08.01.05 Shipped
/fee-surcharge-rules/ (CRUD), /fee-surcharges/calculate (beräkning)
✅ PL-F0801a - F08.01.06 Shipped
/fee-waiver-rules/ (CRUD), /fee-waivers/calculate (beräkning med ålder/familj/scoping)
✅ PL-F0801b - F08.01.07 Shipped
/fee-splitting/calculate (fördelningsberäkning), /fee-splitting/execute (skapar RevenueEntry)
✅ PL-F0801b - F08.01.08 Shipped
/fee-audit/ (lista), /fee-audit/{id} (detalj), /fee-audit/entity/{type}/{id} (per entitet)
✅ PL-F0801b - F08.01.09 Shipped
/sanction-fee-configs/ (CRUD), /sanction-fee-configs/calculate/{season_id} (beräkning)
✅ PL-F0801b - F08.01.10 Shipped
/suspension-fee-configs/ (CRUD), /suspension-fee-configs/calculate/{season_id} (beräkning)
✅ PL-F0801b - F08.01.06 Shipped
/fee-waiver-rules/ (CRUD), /fee-waivers/calculate
✅ PL-F0801b - F08.01.07 Shipped
/fee-splitting/calculate, /fee-splitting/execute
✅ PL-F0801b - F08.01.08 Shipped
/fee-audit/, /fee-audit/{id}, /fee-audit/entity/{type}/{id}
✅ PL-F0801b - F08.01.09 Shipped
/sanction-fee-configs/ (CRUD), /sanction-fee-configs/calculate/{season_id}
✅ PL-F0801b - F08.01.10 Shipped
/suspension-fee-configs/ (CRUD), /suspension-fee-configs/calculate/{season_id}
✅ PL-F0801b - F08.07.01 Shipped
/expense-claims/ (CRUD med specificerade utgiftsposter, kvitto-URL, käll-referens)
✅ PL-F0807 - F08.07.02 Shipped
/expenses/travel/calculate (km-ersättning + traktamente), embedded TravelExpense i claims
✅ PL-F0807 - F08.07.03 Shipped
/expense-claims/{id}/submit, /expense-claims/{id}/approve, /expense-claims/{id}/reject
✅ PL-F0807 - F08.07.04 Shipped
/expense-claims/{id}/pay (utbetalning med valfri betalningsmetod och referens)
✅ PL-F0807 - F08.07.05 Shipped
/expense-reports/by-category, /expense-reports/by-org-node (rapporter med filter)
✅ PL-F0807 - F08.06.01 Shipped
/prize-pools/ (CRUD, per tävling, med sponsor-koppling)
✅ PL-F0806 - F08.06.02 Shipped
/prize-pools/{id}/recalculate-distribution (procentbaserad omfördelning), /prize-pools/{id}/generate-payouts (auto från resultat)
✅ PL-F0806 - F08.06.03 Shipped
/prize-payouts/{id}/approve (godkänn med skatteberäkning), /prize-payouts/{id}/process-payment (koppla betalning), /prize-payouts/batch-approve (batchgodkännande)
✅ PL-F0806 - F08.06.04 Shipped
/prize-payouts/calculate-tax (förhandsberäkning), /prize-payouts/tax-report (aggregerad skatterapport per land)
✅ PL-F0806 - F08.06.05 Shipped
/trophy-inventories/ (CRUD), /trophy-awards/ (CRUD), /prize-pools/{id}/generate-awards (auto från resultat)
✅ PL-F0806 - F08.09.01 Shipped
/license-fee-revisions/ (CRUD, approve, apply — årlig revision av licensavgifter)
✅ PL-F0809a - F08.09.02 Shipped
/tenant-vat-configs/ (CRUD), /tenant-vat-configs/active, /tenant-vat-configs/resolve-rate
✅ PL-F0809a - F08.09.03 Shipped
/invoice-number-series/ (CRUD), /invoice-number-series/preview
✅ PL-F0809a - F08.09.04 Shipped
/payment-term-rules/ (CRUD), /payment-term-rules/resolve
✅ PL-F0809a - F08.09.05 Shipped
/sepa-mandates/ (CRUD, activate, cancel), /sepa-direct-debits/ (CRUD, submit, settle, reject)
✅ PL-F0809a - F08.08.01 Shipped
/financial-reporting/revenue-summary (intäkter per källa: licenser, tävlingar, sponsring, bidrag)
✅ PL-F0808 - F08.08.02 Shipped
/financial-reporting/expense-summary (kostnader per kategori: utlägg + bokföringsposter)
✅ PL-F0808 - F08.08.03 Shipped
/financial-reporting/federation-summary (hierarkisk sammanställning per OrgNode-nivå + budget)
✅ PL-F0808 - F08.08.04 Shipped
/financial-reporting/club-health (hälsoindikatorer: betalningsgrad, kostnadskvot, förfallna fakturor)
✅ PL-F0808 - F08.08.05 Shipped
/financial-reporting/trend-analysis (flerårsanalys med tillväxttakt, max 10 år)
✅ PL-F0808 - F08.08.06 Shipped
/financial-reporting/export/csv (UTF-8 BOM), /financial-reporting/export/saft (SAF-T XML, OECD)
✅ PL-F0808 - F08.10.01 Shipped
GET /accounting-export/fortnox (semikolonseparerad CSV, svenskt decimalformat, per-tenant kontoplansmappning)
✅ PL-F0810a - F08.10.02 Shipped
GET /accounting-export/xero (kommaseparerad CSV, internationellt decimalformat, per-tenant kontoplansmappning)
✅ PL-F0810a - F08.10.03 Shipped
GET /accounting-export/visma (tabbseparerad textfil, svenskt decimalformat, API-synk via integrationsconfig)
✅ PL-F0810a - F08.10.04 Shipped
/chart-of-accounts-mappings/ (CRUD, per provider per tenant, duplikatskydd 409)
✅ PL-F0810a - F08.10.05 Shipped
GET /accounting-export/sie4 (utökad SIE4 med #KTYP, #IB, #UB, #RES, CP437)
✅ PL-F0810b - F08.10.06 Shipped
/financial-statements/ (CRUD, generering bokslut med resultat-/balansögonblicksbild, finalisering)
✅ PL-F0810b - F08.10.07 Shipped
/period-locks/ (CRUD, check, unlock, blockerar entry create/post/void inom låst period)
✅ PL-F0810b - F08.10.08 Shipped
/accounting-reports/consolidated-income-statement, /consolidated-balance-sheet (per OrgNode, kvartal)
✅ PL-F0810b
Bank Reconciliation
F08.12_PL-T076 — import av kontoutdrag, regelbaserad auto-matchning, manuell inbox, AccountingEntry-generering, lock-flöde._
How it works- F08.12.01 Shipped
Import av kontoutdrag — stöd för CAMT.053 (ISO 20022), CSV (generisk + bankspecifik: Nordea, SEB, Handelsbanken, Swedbank, BNP Paribas, Crédit Agricole), OFX, SIE4. Formatdetektering automatisk. SHA-256-deduplicering.
✅ PL-T076 - F08.12.02 Shipped
Regelbaserad auto-matchning — klubbkassörens egna regler (motpartsnamn-regex, beloppsintervall, OCR-prefix). Prioritetsordning. Stöder book_to_account, match_to_invoice_by_ocr och ignore.
✅ PL-T076 - F08.12.03 Shipped
Heuristisk matchning — referens/OCR-matchning mot Payment (1.0 conf), fuzzy namn+belopp+datum ±3d (Jaro-Winkler ≥ 0.85). Under 0.6 → unmatched.
✅ PL-T076 - F08.12.04 Shipped
Manuell inbox — obematchade rader med färgkodning (grön/gul/röd). Tre-knapps-flöde: matcha mot faktura, bokför som ny post, ignorera. Split-matchning stöds.
✅ PL-T076 - F08.12.05 Shipped
AccountingEntry-generering — automatisk dubbelbokning vid matchning: debet bank/kredit kundfordran (incoming), debet leverantörsskuld/kredit bank (outgoing), debet bank/kredit intäktskonto (new).
✅ PL-T076 - F08.12.06 Shipped
Saldo-avstämning och lock — closing_balance == opening_balance + sum(lines) OCH alla lines matchade ⇒ status=locked. Balance-check-endpoint returnerar expected/actual/diff.
✅ PL-T076
Tenant Billing Profile
F08.13_PL-T092 — tenant-scoped singleton som styr språk, betalningstid, påminnelsekadens, ton, dröjsmålspolicy och utställar-identitet._
How it works- F08.13.01 Shipped
BillingProfile-modell — tenant-scoped singleton med språk/valuta/betalningstid/ton/dunning-stages/dröjsmålsavgift/issuer-identitet. Fyra pydantic-validatorer (språk, dröjsmåls-policy→fält, dunning-kadens sortering/unika, payment-terms-ton).
✅ PL-T092 - F08.13.02 Shipped
Konfigurerbar dunning-kadens — DunningStageConfig med offset_days (0–720), stage_name, template_id, channel (email/letter/both). Stigande sortering + unika offsets/namn enforced.
✅ PL-T092 - F08.13.03 Shipped
Dröjsmålsavgifts-policy — none/fixed/percentage/interest_rate med matchande fält-kravsvalidering och legal_reference för nationell lagstiftning (Code de commerce L. 441-6, BGB § 288 Abs. 2, Inkassolagen 1974:182 § 6).
✅ PL-T092 - F08.13.04 Shipped
Profil-cache — in-process TTL 60 s per tenant; invalidate_billing_profile_cache(tenant_id) vid alla mutationer. ≤ 50 ms p95 på cold read, ≪ 1 ms på cache hit.
✅ PL-T092 - F08.13.05 Shipped
Platform defaults fallback — get_platform_defaults() returnerar hårdkodad konfig (Easy Software System In Europe AB, engelska, EUR, 30d, 14/30/60 dunning). resolve_profile_or_defaults fallback-loggar strukturerad varning (billing_profile.fallback_to_defaults).
✅ PL-T092 - F08.13.06 Shipped
API — GET/PUT /tenants/{id}/billing-profile (tenant-admin RBAC via _assert_tenant_access), POST /tenants/{id}/billing-profile/dunning-stages/preview för dry-run av kadensändringar (antal fakturor + total_outstanding per stadium idag).
✅ PL-T092 - F08.13.07 Shipped
Onboarding-seed — create_default_billing_profile(tenant_id, issuer_*, ...) skapar profilen vid tenant-onboarding; avvisar dubbel-skapelse på service-nivå (singleton-invariant ägd av servicen, ej DB-constraint).
✅ PL-T092
Pro Services Billing
F08.11_PL-T036 — timbaserad fakturering för konsultengagemang (€150/h)._
How it works- F08.11.01 Shipped
ProServiceEngagement — scoped consulting assignment per tenant med låst timpris (€150/h), estimerat timantal och faktureringskontakt
✅ PL-T036 - F08.11.02 Shipped
TimeEntry med kvartstimme-precision — DRAFT→SUBMITTED→INVOICED/VOIDED livscykel; max 24h per konsult per dag
✅ PL-T036 - F08.11.03 Shipped
Månadsvis faktureringsjobb — idempotent jobb skapar ProServiceInvoice per tenant 1:a varje månad; markerar TimeEntries INVOICED
✅ PL-T036 - F08.11.04 Shipped
Finansiell separation — revenue_category = "pro_services_consulting" på alla dokument; aldrig inkluderad i subscription ARR
✅ PL-T036 - F08.11.05 Shipped
Kund-rapport — kunden ser egna SUBMITTED/INVOICED poster; consultant_user_id dold; DRAFT aldrig exponerat
✅ PL-T036 - F08.11.06 Shipped
Faktura-förhandsgranskning — admin kan se nästa månads fakturor innan jobbet körs
✅ PL-T036 - F08.11.07 Shipped
Pro Services revenue-rapport — månadsvis/årsvis rapport separerad från subscription ARR
✅ PL-T036
Bot Protection
F08.14_PL-T072 — Cloudflare Turnstile + honeypot + rate-limit + audit på alla publika POST-endpoints._
How it works- F08.14.01 Shipped
Turnstile-widget — Cloudflare Turnstile på alla publika POST-endpoints (auth, contract-requests, newsletter, contact, feedback, klubbansökan); osynlig 95 % av tiden; GDPR-vänlig (ingen cookie); fail-open med 5 s timeout.
✅ PL-T072 - F08.14.02 Shipped
Honeypot-fält — dolda formulärfält som botar fyller i; serverside-validering avvisar 422 om satta. Kompletterar Turnstile för enklaste botar.
✅ PL-T072 - F08.14.03 Shipped
Rate-limit-stack — IP-baserad rate-limit per endpoint (Redis-counter); 429 efter tröskel; dynamiska gränser per endpoint-känslighet.
✅ PL-T072 - F08.14.04 Shipped
Audit + alert — strukturerad logg på Turnstile-fail/honeypot-trigger/rate-limit-block; Prometheus-counter; alert vid spike (>10× baseline).
✅ PL-T072
Swedbank Bankgirot BGI-inläsning
F08.15_PL-T095 — SFTP-dragen auto-matchning av inkommande Bankgirot-betalningar mot `Invoice.ocr_reference`. Kärnpipelinen (Luhn + parser + matchare + admin-kö + job) är klar; riktig SFTP-hämtning och Azure Key Vault-credentials landar i en uppföljning._
How it works- F08.15.01 Shipped
Luhn mod-10-hjälpare — verify_luhn/generate_luhn_checksum/build_ocr_reference med testvektorer (Wikipedia, MasterCard). Strippar icke-siffror, zero-pad till ≥3, trim till ≤24, sist checksum.
✅ PL-T095 - F08.15.02 Shipped
BGMax-parser (legacy fixed-length) — record 01 (valuta pos 25–27), 05 (OCR pos 3–27, belopp pos 28–45 som öre, datum pos 46–53 YYYYMMDD, motpart pos 54–80). Okända record-typer hoppas över utan krasch.
✅ PL-T095 - F08.15.03 Shipped
ISO 20022 pain.002-parser — namespace-strippad iteration av TxInfAndSts-noder; stödjer pain.002.001.10–.12.
✅ PL-T095 - F08.15.04 Shipped
Auto-detect parser — auto_detect_and_parse väljer XML vs legacy på första non-whitespace-bytet.
✅ PL-T095 - F08.15.05 Shipped
Invoice.ocr_reference — nytt fält (4–25 siffror) + Pydantic-validator som auto-genererar från invoice_number om det saknas; index på (tenant_id, ocr_reference).
✅ PL-T095 - F08.15.06 Shipped
BankImportRun-modell — platform-scoped audit per fil med SHA-256 source_hash för idempotens, filename, fetched_at, format, rows-räknare, status (success/partial/failed).
✅ PL-T095 - F08.15.07 Shipped
UnmatchedBankTransfer-modell — platform-scoped kö med reason (no_ocr/invalid_ocr_checksum/no_matching_invoice/amount_overpaid) och resolution-fält (matched_invoice_id, ignored).
✅ PL-T095 - F08.15.08 Shipped
Matcher — cross-tenant lookup mot aktiva fakturor (sent/overdue/partially_paid), skapar Payment (method bank_transfer, status completed) + BankTransferMatch (status matched, confidence exact), uppdaterar invoice.paid_amount och status.
✅ PL-T095 - F08.15.09 Shipped
Övermatchning — när beloppet överstiger utestående skapas både payment och amount_overpaid unmatched-rad så admin kan hantera återbetalning.
✅ PL-T095 - F08.15.10 Shipped
SHA-256-idempotens — process_file_content returnerar befintlig BankImportRun vid återleverans; inga dubblerade betalningar.
✅ PL-T095 - F08.15.11 Shipped
Craft-easy-jobregistrering — bank-reconciliation-import med injicerbar fetcher: () -> Iterable[(filename, content)]; default-fetcher returnerar []. Tester byter fetcher på modulnivå.
✅ PL-T095 - F08.15.12 Shipped
Admin-kö — GET /admin/bank/unmatched, POST /admin/bank/unmatched/{id}/match?invoice_id=, POST /admin/bank/unmatched/{id}/ignore, GET /admin/bank/import-runs. Alla platform_admin-skyddade.
✅ PL-T095 - F08.15.13 Shipped
SFTP-hämtare — asyncssh-baserad fetcher mot Swedbanks SFTP-inbox med credentials från Azure Key Vault.
✅ PL-T095 - F08.15.14 Shipped
Move-on-processed — flytta fil till processed/ resp. failed/ efter varje försök så idempotens-hashet bara försvarar mot genuina dubletter.
✅ PL-T095 - F08.15.15 Shipped
Tenant-admin-kö — låt federationer hantera sina egna unmatched-rader (nuvarande surface är platform_admin-only eftersom inboxen är platform-vid).
✅ PL-T095 - F08.15.16 Shipped
Parse-failure-alert — Slack/email-notifiering när en BGI-fil misslyckas parsa.
✅ PL-T095
Tenant-admin UI för fakturering
F08.16_PL-T096 — sex vyer i admin-appen under nytt sidomenysektion "Fakturering": tenant-scopade (fakturaprofil, fakturor, fakturadetalj, betalningar) och platform-admin-only (omatchade transfers, batch-jobb)._
How it works- F08.16.01 Shipped
Central API-klient — admin/src/lib/billing-api.ts centraliserar alla anrop mot /tenants/{id}/billing-profile, /invoices, /payments, /admin/bank/* och craft-easy-/jobs/*; exponerar typer (BillingProfile, Invoice, Payment, UnmatchedTransfer, JobRun), hjälpfunktioner (formatMoney, invoiceStatusLabel, INVOICE_STATUSES), multi-status fan-out för listfiltret, och ApiError-genomsläpp.
✅ PL-T096 - F08.16.02 Shipped
BillingProfileView — editerar tenantens singleton-profil via GET/PUT /tenants/{id}/billing-profile. Dunning-stegar som editerbar tabell (add/remove/reorder, auto-sortering på save), språk som chip multi-select (default låst i supported-listan), villkorliga dröjsmålsfält per policy, POST .../dunning-stages/preview för dry-run. Client-side validering speglar backend-pydantic.
✅ PL-T096 - F08.16.03 Shipped
InvoiceList — GET /invoices/?status=... med multi-status-chip-filter (parallel fan-out + de-dup per id när flera valts), "Ladda fler 50"-paginering, sorterbara kolumner (Nummer, Debitor, Utfärdad, Förfaller, Summa, Status), statusfärgade pill-badges.
✅ PL-T096 - F08.16.04 Shipped
InvoiceDetail — full faktura-detalj: header med status-badge, info-kort (issuer, debitor, ECB-referenskurs, OCR), rader, betalningslista (parallell GET /payments/?invoice_id=), status_history-tidslinje, villkorliga actions (PATCH /send, POST /send-reminder, PATCH /cancel), PDF-länk via Linking.openURL.
✅ PL-T096 - F08.16.05 Shipped
PaymentList — GET /payments/?status= med radiofilter (alla/avslutade/pågående/misslyckade/återbetalda/avbrutna), paginering, row-click öppnar faktura. Kolumner: Betald, Belopp, Metod, Referens, Faktura (last-8), Status.
✅ PL-T096 - F08.16.06 Shipped
UnmatchedTransfersView (platform-admin) — GET /admin/bank/unmatched, include-resolved-toggle, row-actions via modal (Matcha via faktura-ID + POST .../match?invoice_id=...; Ignorera med motivering + POST .../ignore). Status-badges OLÖST/MATCHAD/IGNORERAD.
✅ PL-T096 - F08.16.07 Shipped
JobsAdmin (platform-admin) — kort-grid med alla /jobs/registry-jobb (Historik-filter + Kör nu), body-table med senaste 100 /jobs/runs-poster (manuellt-triggad-markör, tid i sekunder, status-färgad badge, felmeddelande 2 rader). POST /jobs/run/{name} med tom parameter-body.
✅ PL-T096 - F08.16.08 Shipped
Navigation — ny sidomenysektion "Fakturering" mellan Ekonomi och Innehåll med 5 länkar (3 tenant-scopade, 2 platform-admin-gatade via nytt requiresPlatformAdmin-flag i NavItem). Filtret appliceras både i visibleSectionsFor() och i ⌘K command palette.
✅ PL-T096 - F08.16.09 Shipped
requirePlatformAdmin-HOC — admin/src/auth/platform-admin.tsx: hämtar GET /session/me, tillåter scope === "platform_admin", role === "platform_admin" eller is_system_user, renderar annars 403-panel. Används av /billing/unmatched-transfers och /platform/jobs. Bara kosmetisk — backend enforceras oberoende.
✅ PL-T096 - F08.16.10 Shipped
usePlatformAdmin-hook — hook-variant för icke-blockerande villkorlig UI (sidomenyns dolda länkar, command palette-index). Läser samma /session/me-resultat.
✅ PL-T096
Multi-currency Foundation (PL-T224)
F08.17`MoneyAmount` value object + manual `FXRate`-table + `FXService.convert`. Hedging hooks och real-time FX-feeds är **explicit out-of-scope** — se docs/business/finance/multi-currency-foundation.md.
- F08.17.01 Shipped
MoneyAmount value object — Pydantic-modell med currency: ISO4217 + amount: Decimal. Wire-format: amount serialiserad som string för float-säker JS-transport. Negativa belopp tillåts (refunds). Likhet currency-aware. Konsumeras av PracticeExam.fee och MentorAssignment.hourly_rate.
✅ PL-T224 - F08.17.02 Shipped
FXRate manual entry + lookup — Beanie-document med (base_currency, quote_currency, rate, as_of, source, is_active). POST /finance/fx/rates (capability finance.fx.manage) skriver manuella rates; GET /finance/fx/rates?base="e=&as_of= hämtar senaste matchande. Source-värdena ecb-daily och stripe-fx reserverade för framtida automation.
✅ PL-T224 - F08.17.03 Shipped
FXService.convert — POST /finance/fx/convert med {amount, currency, target_currency, as_of?}. base==quote returnerar input oförändrat utan DB-hit. Saknad rate ger 422 fx_rate_unavailable. Conversion runda till 0.01 ROUND_HALF_EVEN. Returnerar rate_used för audit-spårning.
✅ PL-T224
No features match your filters.