Ir al contenido principal
Petanque Life

Subscription Management

F08.11 90 funcionalidades Planificado

En resumen

Subscription Management runs the recurring-revenue lifecycle for tenant platform fees: Stripe Checkout and Swish QR checkout, automatic invoicing on renewal with per-line VAT, ECB-quarterly-fixed multi-currency billing across EUR, SEK, NOK, DKK, GBP, USD and CHF, the formal Price-Lock Guarantee that pins each Subscription to its original pricing_version, automatic revenue distribution into per-recipient RevenueEntry rows and outstanding-debt enforcement against club transfers and licence renewals.

Cómo funciona

Each Subscription document carries a pricing_version (ISO date) identifying the exact price list in force when the contract was signed; this value is preserved across renewals so a customer never sees an unannounced price hike — the Price-Lock Guarantee published at petanque.life/price-lock-guarantee in four languages. CRUD covers create, renew, terminate and upgrade. Automatic renewal triggers the invoicing pipeline: an Invoice is generated with per-line tax_rate and tax_amount derived from the tenant VAT config (F08.09.02), tax_total is summed and the total is set; auto-generation flows are /invoices/auto-generate/license-renewal (accepts fee_components with name, amount, recipient type) and /invoices/auto-generate/affiliation.

Local-currency invoicing follows the ECB quarterly fixing policy: rates are pinned the first banking day of January, April, July and October; supported currencies are EUR, SEK, NOK, DKK, GBP, USD and CHF; each invoice persists ecb_fixing_rate and ecb_fixing_date for historical reproducibility — published at petanque.life/currency-policy. Settlement runs through two checkout flows. Stripe Checkout: POST /checkout/ with gateway=stripe returns the Stripe URL, the user pays in Stripe, the platform listens on POST /webhooks/stripe for checkout.session.completed (creates Payment, updates Invoice, generates receipt, distributes revenue), checkout.session.expired (marks expired) and payment_intent.payment_failed (flags failure).

Swish: POST /checkout/ with gateway=swish returns base64 QR data, the Swish app posts back to /webhooks/swish, same pipeline. Revenue distribution executes on every confirmed payment: the system fetches the RevenueDistributionRule for the fee category, splits the amount per configured percentages and writes RevenueEntry rows per recipient (federation, district, external); without a rule, 100 percent goes to the federation. Outstanding invoices in status sent, overdue or partially_paid block club transfer (PL-301) at creation and licence renewal at approval.

Per-tenant gateway configuration lives at /payment-gateways/, with credentials as Azure Key Vault references — Sweden uses Stripe plus Swish, France uses Stripe.

Capacidades clave

  • Subscription document carrying pricing_version preserved across renewals (Price-Lock Guarantee)
  • Stripe Checkout and Swish QR checkout with webhook-driven Payment creation
  • Auto-generated renewal invoices with per-line VAT and tenant default template
  • ECB quarterly fixing for local-currency billing across EUR, SEK, NOK, DKK, GBP, USD and CHF
  • Automatic revenue distribution via RevenueDistributionRule writing per-recipient RevenueEntry rows
  • Outstanding-debt enforcement that blocks transfer and licence renewal until invoices clear
  • Per-tenant gateway configuration with Azure Key Vault-backed credentials

En la práctica

A federation signs up on the v2026.01 catalog at the Self-Service M tier in EUR. Twelve months later renewal triggers: the system pulls the still-valid pricing_version v2026.01 (Price-Lock holds even though v2026.04 is now published), generates an invoice in EUR using the Q2 ECB fixing for any non-EUR cross-rate audit, applies 25 percent MOMS per the tenant VAT config and emails the treasurer a Swish QR link. He scans, the Swish callback hits /webhooks/swish, the platform creates a Payment, marks the Invoice paid, generates the receipt and runs revenue distribution writing the platform-fee RevenueEntry.

Three months in, the federation initiates a club transfer; /debts/check returns clear and the transfer proceeds. A neighbouring federation lets the renewal invoice slip past due — /debts/check returns blocked and their next licence renewal is refused until the invoice settles or a credit note clears it.

Funcionalidades de este subsistema

90
ID Status Funcionalidades
F08.11.01 Entregado 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 Entregado 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 Entregado 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 Entregado 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 Entregado 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 Entregado 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 Entregado 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 Entregado 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 Entregado 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 Entregado /license-fee-configs/, /license-fee-overrides/, /license-fees/calculate ✅ PL-204
F08.01.02 Entregado /fee-schedules/ (fee_category=club_affiliation, med affiliation_tiers) ✅ PL-801
F08.01.03 Entregado /fee-schedules/ (fee_category=competition_entry) ✅ PL-801
F08.01.04 Entregado /fee-management/copy-season (säsongskopiering), /fee-management/by-season/{id} (konsoliderad vy) ✅ PL-F0801a
F08.01.05 Entregado /fee-surcharge-rules/ (CRUD), /fee-surcharges/calculate (early bird/late fee) ✅ PL-F0801a
F08.01.07 Entregado /revenue-distribution-rules/ + automatisk distribution vid betalning ✅ PL-801
F08.01.09 Entregado /fee-schedules/ (fee_category=sanction) ✅ PL-801
F08.02.01 Entregado /payments/ (registrera, spåra, återbetala) ✅ PL-801
F08.03.01 Entregado /invoices/ (skapa, rader, summor) ✅ PL-801
F08.03.02 Entregado Automatisk faktura vid licensgodkännande ✅ PL-801
F08.03.06 Entregado Fakturastatus: draft → sent → paid/overdue/cancelled ✅ PL-801
F08.03.07 Entregado /invoices/{id}/send-reminder ✅ PL-801
F08.03.08 Entregado /debts/check/{debtor_id} — blockerar transfer och licensförnyelse ✅ PL-801
F08.08.01 Entregado /financial-reports/revenue, /financial-reports/revenue/by-org-node ✅ PL-801
F08.02.02 Entregado /checkout/ (Stripe Checkout Session), /webhooks/stripe ✅ PL-802
F08.02.02 Entregado /checkout/ (Swish QR-betalning), /webhooks/swish ✅ PL-802
F08.02.04 Entregado /receipts/, /receipts/{id}/pdf (kvittogenerering) ✅ PL-802
F08.02.06 Entregado Automatisk avstämning via Stripe/Swish webhooks ✅ PL-802
F08.02.07 Entregado /payments/{id}/gateway-refund (återbetalning via gateway) ✅ PL-802
F08.02.10 Entregado Betalningsspårning: /payment-history/{debtor_id} ✅ PL-802
F08.03.01 Entregado /invoices/ utökad med tax_rate per rad, tax_amount, tax_total ✅ PL-F0803a
F08.03.02 Entregado /invoices/auto-generate/license-renewal, /invoices/auto-generate/affiliation ✅ PL-F0803a
F08.03.03 Entregado /invoice-templates/ (CRUD, per-federation, default-hantering) ✅ PL-F0803a
F08.03.04 Entregado /invoices/{id}/pdf (PDF-nedladdning), /invoices/{id}/deliver (e-postleverans) ✅ PL-F0803a
F08.03.05 Entregado /credit-notes/ (CRUD, issue, apply, void — kreditnotor mot fakturor) ✅ PL-F0803b
F08.03.06 Entregado /invoices/{id}/status-history, /invoices/mark-overdue (statusspårning med historik) ✅ PL-F0803b
F08.03.07 Entregado /reminder-configs/, /invoices/reminder-queue, /invoices/send-due-reminders (påminnelseautomatik) ✅ PL-F0803b
F08.03.08 Entregado /debt-collection/ (CRUD, escalate, resolve — inkassoworkflow) ✅ PL-F0803b
F08.05.01 Entregado /sponsors/ (CRUD med kontaktinfo, nivå, sponsrade entiteter) ✅ PL-F0805
F08.05.02 Entregado /sponsors/{id}/contracts (kontraktshantering med belopp, period, villkor) ✅ PL-F0805
F08.05.03 Entregado /sponsors/{id}/exposure (exponeringsregistrering och sammanfattning) ✅ PL-F0805
F08.05.04 Entregado /grants/ (ansökan: draft → submitted → approved/rejected → reporting) ✅ PL-F0805
F08.05.05 Entregado /grants/{id}/reports (bidragsrapportering efter godkännande) ✅ PL-F0805
F08.05.06 Entregado /sponsor-allocations/ (intäktsallokering per OrgNode med procentsatser) ✅ PL-F0805
F08.04.01 Entregado /budgets/ (CRUD med inkomst-/utgiftskategorier per OrgNode), /budgets/copy (kopiera med inflationsjustering) ✅ PL-F0804
F08.04.02 Entregado BudgetCategory med type: income/expense, kopplad till kontoplan ✅ PL-F0804
F08.04.03 Entregado /budgets/{id}/actualize + /budgets/{id}/variance (budget vs. faktisk) ✅ PL-F0804
F08.04.04 Entregado draft → proposed → approved → closed (godkännandeflöde med audit log) ✅ PL-F0804
F08.04.05 Entregado /accounting-reports/income-statement (årsvis + kvartalsvis med quarter-param), /accounting-reports/budget-tracking, /accounting-reports/balance-sheet ✅ PL-F0804
F08.04.06 Entregado /accounting-entries/ (verifikationer med kontoplan), /accounting-export/sie + /fec + /json ✅ PL-F0804
F08.01.04 Entregado /fee-management/copy-season (kopiera avgiftsdata), /fee-management/by-season/{id} ✅ PL-F0801a
F08.01.05 Entregado /fee-surcharge-rules/ (CRUD), /fee-surcharges/calculate (beräkning) ✅ PL-F0801a
F08.01.06 Entregado /fee-waiver-rules/ (CRUD), /fee-waivers/calculate (beräkning med ålder/familj/scoping) ✅ PL-F0801b
F08.01.07 Entregado /fee-splitting/calculate (fördelningsberäkning), /fee-splitting/execute (skapar RevenueEntry) ✅ PL-F0801b
F08.01.08 Entregado /fee-audit/ (lista), /fee-audit/{id} (detalj), /fee-audit/entity/{type}/{id} (per entitet) ✅ PL-F0801b
F08.01.09 Entregado /sanction-fee-configs/ (CRUD), /sanction-fee-configs/calculate/{season_id} (beräkning) ✅ PL-F0801b
F08.01.10 Entregado /suspension-fee-configs/ (CRUD), /suspension-fee-configs/calculate/{season_id} (beräkning) ✅ PL-F0801b
F08.01.06 Entregado /fee-waiver-rules/ (CRUD), /fee-waivers/calculate ✅ PL-F0801b
F08.01.07 Entregado /fee-splitting/calculate, /fee-splitting/execute ✅ PL-F0801b
F08.01.08 Entregado /fee-audit/, /fee-audit/{id}, /fee-audit/entity/{type}/{id} ✅ PL-F0801b
F08.01.09 Entregado /sanction-fee-configs/ (CRUD), /sanction-fee-configs/calculate/{season_id} ✅ PL-F0801b
F08.01.10 Entregado /suspension-fee-configs/ (CRUD), /suspension-fee-configs/calculate/{season_id} ✅ PL-F0801b
F08.07.01 Entregado /expense-claims/ (CRUD med specificerade utgiftsposter, kvitto-URL, käll-referens) ✅ PL-F0807
F08.07.02 Entregado /expenses/travel/calculate (km-ersättning + traktamente), embedded TravelExpense i claims ✅ PL-F0807
F08.07.03 Entregado /expense-claims/{id}/submit, /expense-claims/{id}/approve, /expense-claims/{id}/reject ✅ PL-F0807
F08.07.04 Entregado /expense-claims/{id}/pay (utbetalning med valfri betalningsmetod och referens) ✅ PL-F0807
F08.07.05 Entregado /expense-reports/by-category, /expense-reports/by-org-node (rapporter med filter) ✅ PL-F0807
F08.06.01 Entregado /prize-pools/ (CRUD, per tävling, med sponsor-koppling) ✅ PL-F0806
F08.06.02 Entregado /prize-pools/{id}/recalculate-distribution (procentbaserad omfördelning), /prize-pools/{id}/generate-payouts (auto från resultat) ✅ PL-F0806
F08.06.03 Entregado /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 Entregado /prize-payouts/calculate-tax (förhandsberäkning), /prize-payouts/tax-report (aggregerad skatterapport per land) ✅ PL-F0806
F08.06.05 Entregado /trophy-inventories/ (CRUD), /trophy-awards/ (CRUD), /prize-pools/{id}/generate-awards (auto från resultat) ✅ PL-F0806
F08.09.01 Entregado /license-fee-revisions/ (CRUD, approve, apply — årlig revision av licensavgifter) ✅ PL-F0809a
F08.09.02 Entregado /tenant-vat-configs/ (CRUD), /tenant-vat-configs/active, /tenant-vat-configs/resolve-rate ✅ PL-F0809a
F08.09.03 Entregado /invoice-number-series/ (CRUD), /invoice-number-series/preview ✅ PL-F0809a
F08.09.04 Entregado /payment-term-rules/ (CRUD), /payment-term-rules/resolve ✅ PL-F0809a
F08.09.05 Entregado /sepa-mandates/ (CRUD, activate, cancel), /sepa-direct-debits/ (CRUD, submit, settle, reject) ✅ PL-F0809a
F08.08.01 Entregado /financial-reporting/revenue-summary (intäkter per källa: licenser, tävlingar, sponsring, bidrag) ✅ PL-F0808
F08.08.02 Entregado /financial-reporting/expense-summary (kostnader per kategori: utlägg + bokföringsposter) ✅ PL-F0808
F08.08.03 Entregado /financial-reporting/federation-summary (hierarkisk sammanställning per OrgNode-nivå + budget) ✅ PL-F0808
F08.08.04 Entregado /financial-reporting/club-health (hälsoindikatorer: betalningsgrad, kostnadskvot, förfallna fakturor) ✅ PL-F0808
F08.08.05 Entregado /financial-reporting/trend-analysis (flerårsanalys med tillväxttakt, max 10 år) ✅ PL-F0808
F08.08.06 Entregado /financial-reporting/export/csv (UTF-8 BOM), /financial-reporting/export/saft (SAF-T XML, OECD) ✅ PL-F0808
F08.10.01 Entregado GET /accounting-export/fortnox (semikolonseparerad CSV, svenskt decimalformat, per-tenant kontoplansmappning) ✅ PL-F0810a
F08.10.02 Entregado GET /accounting-export/xero (kommaseparerad CSV, internationellt decimalformat, per-tenant kontoplansmappning) ✅ PL-F0810a
F08.10.03 Entregado GET /accounting-export/visma (tabbseparerad textfil, svenskt decimalformat, API-synk via integrationsconfig) ✅ PL-F0810a
F08.10.04 Entregado /chart-of-accounts-mappings/ (CRUD, per provider per tenant, duplikatskydd 409) ✅ PL-F0810a
F08.10.05 Entregado GET /accounting-export/sie4 (utökad SIE4 med #KTYP, #IB, #UB, #RES, CP437) ✅ PL-F0810b
F08.10.06 Entregado /financial-statements/ (CRUD, generering bokslut med resultat-/balansögonblicksbild, finalisering) ✅ PL-F0810b
F08.10.07 Entregado /period-locks/ (CRUD, check, unlock, blockerar entry create/post/void inom låst period) ✅ PL-F0810b
F08.10.08 Entregado /accounting-reports/consolidated-income-statement, /consolidated-balance-sheet (per OrgNode, kvartal) ✅ PL-F0810b