Skip to main content

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
Architecture Highlights:
  • 🎯 Document-based: Integrations populate deferred_revenue_start_date, deferred_revenue_end_date, deferred_revenue_period on 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
Not Goals:
  • 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:
This violates:
  • 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:
  1. Inflated Revenue: Annual subscriptions show 12x revenue in month 1
  2. Incorrect P&L: January shows €100k revenue, Feb-Dec show €0
  3. Missing Liabilities: Balance sheet doesn’t show obligation to deliver services
  4. Tax Issues: Advance VAT recognition without service delivery
  5. 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:
Document Example:
Why this design?
  • 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 existing tools table to store deferred revenue configuration:
Deferred Revenue Tool Record:
Integration requirements:
  • Integrations must set deferred_revenue_start_date and deferred_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_period can use fallback (defaults to MONTHLY)
Revenue recognition:
  • Monthly Temporal workflow automatically processes all active schedules
  • Schedule status controls whether revenue is recognized:
    • active → Recognized automatically by workflow
    • completed → All revenue already recognized
    • cancelled → No further recognition (e.g., customer refunded)
    • suspended → Temporarily paused (e.g., payment issues)
Recognition timing:
  • 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)
This is standard accounting practice and matches regulatory requirements.

3. New Table: deferred_revenue_schedules

Key Fields:
  • deferred_revenue_account_id: The liability account (2610) - used as debit account for monthly recognition GL entries
  • target_revenue_account_id: The revenue account (8401) - captured from posting matrix at interception, used as credit account for monthly recognition GL entries
  • cancellation_document_id: Links to credit note document
Key Design:
  • GL entries are created directly and attached to the source sales invoice (document_id on general_ledger = source invoice)
  • No new document type; recognition entries link to general_ledger for audit trail
  • Accounts come from the schedule: deferred_revenue_account_id (DR) and target_revenue_account_id (CR)

Implementation Details

1. Transaction Import Flow (Paddle)

Step 1: Integration populates deferred revenue fields on document
Step 2: System intercepts posting matrix for prepaid invoices

2. Monthly Revenue Recognition Workflow

Creates general ledger entries attached to the sales invoice

3. 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
No posting matrix is used for recognition; accounts are determined at schedule creation time from the intercepted invoice’s posting matrix result.

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):
Monthly Recognition (Jan 31, 2024):
Cancellation with Refund (Apr 15, 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, 2024

WEEKLY 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_PERIOD enum
  • 🔲 Future: Schedule creation with proration calculation
  • 🔲 Future: Monthly recognition workflow
See: /apps/internal-docs/implementation-notes/deferred-revenue-proration.md

Open Questions

  1. Partial Periods: How to handle subscriptions starting mid-month?RESOLVED
    • Decision: Auto-prorate first and last periods by days (implemented in CONA-740)
  2. Upgrades/Downgrades: How to handle plan changes mid-period?
    • Proposal: Phase 2 feature - create new schedule, prorate old
  3. Multiple Currencies: How to handle FX changes over recognition period?
    • Proposal: Lock FX rate at transaction date (IFRS approach)
  4. Daily vs Monthly: Should we support daily recognition?RESOLVED
    • Decision: Support DAILY, WEEKLY, MONTHLY, QUARTERLY, YEARLY via enum (implemented in CONA-740)
  5. 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

Appendix: Example Scenarios

Scenario 1: Annual Subscription

Scenario 2: Quarterly Subscription

Scenario 3: Cancellation After 3 Months


References