Executive Summary
As CONA expands to serve SaaS businesses with subscription billing (Paddle, Stripe, Chargebee), we need proper accrual accounting for prepaid revenue. This RFC proposes a deferred revenue recognition system that: Key Goals:- Correctly recognize revenue over the service period (not when payment received)
- Comply with German HGB (§252 Abs. 1 Nr. 5) and IFRS 15 requirements
- Provide clear visibility into deferred revenue liabilities
- Handle cancellations and refunds gracefully
- Automate monthly revenue recognition via Temporal workflows
- 🎯 Document-based: Integrations populate
deferred_revenue_start_date,deferred_revenue_end_date,deferred_revenue_periodon invoices - ⚙️ Posting Matrix Interception: System intercepts posting matrix execution for prepaid invoices and redirects revenue → PRAP account
- 📅 Schedule-based: One schedule per invoice, generates monthly recognition entries
- 🔄 Automated: Monthly Temporal workflow recognizes revenue without manual intervention
- Revenue recognition for usage-based billing (separate feature)
- Multi-element arrangements (split between services)
- Contract modifications mid-period (v2 feature)
How It Works: End-to-End Flow
Problem Statement
Current State
CONA currently records subscription payments as immediate revenue:- HGB §252 (1) Nr. 5: Realization principle - revenue only when earned
- IFRS 15: Revenue from contracts with customers over performance period
- Matching Principle: Revenue must match period when service delivered
German Accounting Requirements
Rechnungsabgrenzungsposten (ARAP) - Required by German law:- Passive RAP (2610): Prepayments received for future services = Liability
- Must be amortized over service period (monthly for subscriptions)
- SKR03/SKR04: Account 2610 “Passive Rechnungsabgrenzungsposten”
Business Impact
Current Problems:- Inflated Revenue: Annual subscriptions show 12x revenue in month 1
- Incorrect P&L: January shows €100k revenue, Feb-Dec show €0
- Missing Liabilities: Balance sheet doesn’t show obligation to deliver services
- Tax Issues: Advance VAT recognition without service delivery
- Cancellation Chaos: No clear way to handle mid-year cancellations
Proposed Solution
Architecture Overview
Data Model
1. Extend Documents Table
Add new columns for deferred revenue configuration and schedule link:- ✅ Type-safe ENUM: Prevents typos and invalid values at compile time
- ✅ Deferred revenue data on document: Integration sets it once during import
- ✅ Account-based trigger: Posting to deferred revenue account automatically creates schedule
- ✅ Flexible: Works for any integration (Paddle, Stripe, Chargebee, manual invoices)
- ✅ Fallback-friendly: If fields empty, can use document date + default duration
- ✅ Proration built-in: First/last periods automatically prorated by days
2. Deferred Revenue Tool Configuration
Use the existingtools table to store deferred revenue configuration:
- Integrations must set
deferred_revenue_start_dateanddeferred_revenue_end_date - These come from the subscription billing period (always available from Paddle/Stripe/Chargebee)
- If missing, system will reject the document (not silently fallback)
- Only
deferred_revenue_periodcan use fallback (defaults to MONTHLY)
- Monthly Temporal workflow automatically processes all active schedules
- Schedule status controls whether revenue is recognized:
active→ Recognized automatically by workflowcompleted→ All revenue already recognizedcancelled→ No further recognition (e.g., customer refunded)suspended→ Temporarily paused (e.g., payment issues)
- Revenue is always recognized at the end of each period
- MONTHLY: Last day of month (Jan 31, Feb 28/29, Mar 31, etc.)
- WEEKLY: Last day of ISO week (Sunday)
- DAILY: Each day
- QUARTERLY: Last day of quarter (Mar 31, Jun 30, Sep 30, Dec 31)
- YEARLY: Last day of year (Dec 31)
3. New Table: deferred_revenue_schedules
deferred_revenue_account_id: The liability account (2610) - used as debit account for monthly recognition GL entriestarget_revenue_account_id: The revenue account (8401) - captured from posting matrix at interception, used as credit account for monthly recognition GL entriescancellation_document_id: Links to credit note document
- GL entries are created directly and attached to the source sales invoice (
document_idongeneral_ledger= source invoice) - No new document type; recognition entries link to
general_ledgerfor audit trail - Accounts come from the schedule:
deferred_revenue_account_id(DR) andtarget_revenue_account_id(CR)
Implementation Details
1. Transaction Import Flow (Paddle)
Step 1: Integration populates deferred revenue fields on document2. Monthly Revenue Recognition Workflow
Creates general ledger entries attached to the sales invoice3. Accounting Logic for Recognition
GL entries use accounts from the schedule:- Debit:
deferred_revenue_account_id(PRAP, e.g. 2610) from the schedule - Credit:
target_revenue_account_id(e.g. 8401) from the schedule — stored when the posting matrix intercepts the original invoice
4. Cancellation Handling
UI/UX Implementation
1. Chart of Accounts Configuration
Setup page:/setup/chart-of-accounts
2. Sales Invoice Document View
Activity Log Display
When viewing the invoice, users will see an activity log entry:2. Deferred Revenue Card Component
3. Deferred Revenue Schedule Detail Page
German Accounting Compliance
Chart of Accounts (SKR03)
Example Bookings
Initial Payment (Jan 1, 2024):Temporal Workflow Schedule
Monthly Revenue Recognition
Migration Plan
Phase 1: Foundation (Week 1)
- Create database tables
- Add core functions for schedule management
- Implement
shouldDeferRevenue()logic
Phase 2: Integration (Week 2)
- Update Paddle transaction processing
- Test with sandbox transactions
- Add custom properties to documents
Phase 3: Recognition (Week 3)
- Implement monthly workflow
- Test recognition entries
- Schedule Temporal workflow
Phase 4: UI (Week 4)
- Build DeferredRevenueCard component
- Create schedule detail page
- Add to document view
Phase 5: Cancellations (Week 5)
- Implement cancellation handler
- Test refund scenarios
- Webhook integration
Testing Strategy
Unit Tests
- Schedule creation logic
- Amount calculation (monthly, daily)
- Rounding edge cases
- Cancellation scenarios
Integration Tests
- Full Paddle transaction → schedule → recognition flow
- Cancellation with refund
- Multiple subscriptions per customer
E2E Tests
- Import annual subscription
- Verify deferred revenue booking
- Trigger monthly workflow
- Check GL entries created
- Cancel and verify credit note
Proration Implementation ✅
Decision: Automatic Proration for Partial Periods
Status: IMPLEMENTED in CONA-740 All partial periods (first/last months, weeks, etc.) are automatically prorated by days to ensure accurate revenue recognition.MONTHLY Proration Example
Scenario: €120 for 12-month subscription starting Jan 15, 2024WEEKLY Proration Example (ISO Weeks)
Scenario: €52 for 52-week subscription starting Wednesday (mid-week)Proration Formula
Rounding Strategy
Last period gets the remainder to prevent floating-point drift:Benefits
✅ IFRS 15 Compliant - Revenue proportional to performance obligation ✅ Accurate - Matches service delivery exactly ✅ Handles Edge Cases - Leap years, varying month lengths, partial weeks ✅ No Manual Adjustment - Fully automated ✅ Exact Totals - No rounding errors (last period correction)Implementation Status
- ✅ CONA-740: Database schema with
DEFERRED_REVENUE_PERIODenum - 🔲 Future: Schedule creation with proration calculation
- 🔲 Future: Monthly recognition workflow
/apps/internal-docs/implementation-notes/deferred-revenue-proration.md
Open Questions
-
Partial Periods: How to handle subscriptions starting mid-month?✅ RESOLVED- Decision: Auto-prorate first and last periods by days (implemented in CONA-740)
-
Upgrades/Downgrades: How to handle plan changes mid-period?
- Proposal: Phase 2 feature - create new schedule, prorate old
-
Multiple Currencies: How to handle FX changes over recognition period?
- Proposal: Lock FX rate at transaction date (IFRS approach)
-
Daily vs Monthly: Should we support daily recognition?✅ RESOLVED- Decision: Support DAILY, WEEKLY, MONTHLY, QUARTERLY, YEARLY via enum (implemented in CONA-740)
-
Manual Adjustments: Can accountants manually adjust schedules?
- Proposal: Yes, with audit trail and approval workflow
Risks & Mitigation
Success Metrics
- Correctness: 100% of deferred revenue schedules match expected recognition
- Compliance: Pass external audit review for HGB/IFRS compliance
- Performance: Process 10,000+ schedules in <5 minutes
- Reliability: 99.9% success rate for monthly recognition runs
- User Experience: <2 seconds to load schedule detail page