Kulcare Docs
DeveloperBilling

Billing Reports, Commissions & Revenue Share Implementation Plan

Purpose: Comprehensive plan for implementing reports, commissions, and revenue share functionality in the new billing schema Based on: Legacy implementation in parts/billing and parts/clinic Target Schema: billing.* (with cross-domain dependencies on clinical.* and identity.*) Status: ✅ COMPLETED (Phases 1-5) | ⏳ PENDING (Phase 6: Specs)

Related: For how a facility's stakeholder payout is actually calculated — the P&L, the recognition bases, the carry-forward and the settlement gate — see stakeholder-payout-calculation.md. The end-user version of the same subject is ../../user/revenue-sharing-payouts.html. That model replaces the legacy parts/clinic stakeholder flow documented in 03-api-reference/stakeholders-revenue-apis.md.

Related: For who earns an invoice line (the line's doctor, else the encounter's participants), how rule and assignment dates are judged at the bill's issue date, and what Run now refuses, see commission-attribution.md.

Related: For vendor marketplace payments (multi-processor split-payment + commission collection on the Billing::Marketplace::* namespace), see ../marketplace/marketplace-multi-processor.md.

Related: For how a vendor sets up payouts, how a patient pays a vendor, every path that refunds a vendor order, refund requests, and the support runbooks, see vendor-payments-and-refunds.md.

Table of Contents

  1. Implementation Status
  2. Executive Summary
  3. Current System Analysis
  4. Proposed Schema Design
  5. Visual Schema Diagram
  6. Key Changes Explained
  7. Domain Structure
  8. API Endpoints
  9. Data Migration Strategy

Implementation Status

✅ Completed Phases (1-5)

PhaseStatusFiles CreatedNotes
Phase 1: Database Migration✅ Complete2 filesMain migration + commission assignments
Phase 2: Domain Foundation✅ Complete12 files11 models + routes updated
Phase 3: Commission API✅ Complete29 filesControllers, services, policies, blueprints
Phase 4: Revenue Share API✅ Complete15 filesControllers, services, policies, blueprints
Phase 5: Reports & Exports API✅ Complete18 filesControllers, services, policies, blueprints
Phase 6: Specs⏳ Pending0 filesSkipped per requirements

Migration Files Created

FileDescriptionTables
20260127100000_create_billing_reports_commissions_tables.rbMain migration with 9 tables + soft delete + CANCELLED statusAll billing reports/commissions tables
20260127110000_create_commission_assignments_table.rbCommission practitioner/staff assignmentsbilling.commission_assignments

Models Created (11 files)

ModelTableStatus
Billing::CommissionRulebilling.commission_rules✅ with soft delete columns
Billing::CommissionCalculationbilling.commission_calculations✅ with CANCELLED status
Billing::CommissionSettlementbilling.commission_settlements✅
Billing::CommissionWorkflowbilling.commission_workflows✅
Billing::CommissionAssignmentbilling.commission_assignments✅ BONUS - not in original plan
Billing::RevenueShareConfigbilling.revenue_share_configs✅ with inline stakeholders
Billing::RevenueShareStakeholderbilling.revenue_share_stakeholders✅ hierarchical support
Billing::RevenueShareCalculationbilling.revenue_share_calculations✅
Billing::RevenueShareDistributionbilling.revenue_share_distributions✅
Billing::RevenueDistributionQueuebilling.revenue_distribution_queues✅ BONUS - separate migration
Billing::ReportExportbilling.report_exports✅

Controllers Created (9 files)

ControllerEndpointsStatus
Billing::CommissionRulesControllerCRUD + activate/deactivate✅
Billing::CommissionCalculationsControllerIndex, show, update, bulk_update, export, approve✅
Billing::CommissionSettlementsControllerIndex, show, generate, approve, pay, cancel✅
Billing::CommissionWorkflowsControllerIndex, create, update, execute✅
Billing::CommissionDashboardControllerIndex, analytics✅
Billing::RevenueShareConfigsControllerCRUD with inline stakeholders✅
Billing::RevenueShareCalculationsControllerIndex, show, calculate, dashboard, approve✅
Billing::RevenueShareDistributionsControllerIndex, show, approve, pay✅
Billing::PremiumReportsControllerAll reports endpoints✅

Services Created (31 files)

Commission Services (13 files):

  • CommissionRulesService - Rule CRUD with assignee management
  • CommissionCalculationService - Percentage/fixed calculations
  • TieredCommissionCalculationService - Tiered calculations (REVENUE_GENERATED/SERVICES)
  • IndexService - Paginated listing with filters
  • UpdateStatusService - Individual status updates
  • BulkUpdateService - Bulk status operations
  • ApproveService - Approval workflow
  • SettlementService - Settlement generation
  • WorkflowExecuteService - Workflow execution
  • OverviewService - Dashboard metrics
  • AnalyticsService - Grouped analytics
  • CommissionWorkflowsService - Workflow management
  • CalculateService - Removed in PR #2511; it had no caller. CommissionCalculationService, run by a workflow, is the per-invoice path

Revenue Share Services (4 files):

  • RevenueShareConfigsService - Config CRUD with stakeholders
  • RevenueShare::CalculationService - Revenue share calculations
  • RevenueShare::DashboardService - Dashboard metrics

Report Services (8 files):

  • RevenueAnalysisService - Time-series revenue data
  • DashboardService - High-level KPIs
  • PeriodComparisonService - Period comparison
  • LocationComparisonService - Facility comparison
  • ConsolidatedService - Multi-facility overview
  • RevenueAnalysisExportService - Export revenue analysis
  • ComparativeExportService - Export comparative reports
  • ConsolidatedExportService - Export consolidated reports

Export Services (1 file):

  • Exports::CreateService - Async export creation

Blueprints Created (10 files)

BlueprintViewsStatus
CommissionRuleBlueprintnormal, detailed, fhir✅
CommissionCalculationBlueprintnormal, detailed✅
CommissionSettlementBlueprintnormal, detailed✅
CommissionWorkflowBlueprintnormal, detailed✅
CommissionAssignmentBlueprintnormal, detailed✅
RevenueShareConfigBlueprintnormal, detailed, with_stakeholders, fhir✅
RevenueShareCalculationBlueprintnormal, detailed, fhir✅
RevenueShareDistributionBlueprintnormal, detailed, fhir✅
ReportExportBlueprintnormal, detailed✅

Policies Created (10 files)

PolicyPermissionsStatus
CommissionRulePolicyview_practice_finance, manage_practice_finance✅
CommissionCalculationPolicyview_practice_finance, manage_practice_finance✅
CommissionSettlementPolicyview_practice_finance, manage_practice_finance✅
CommissionWorkflowPolicyview_practice_finance, manage_practice_finance✅
RevenueShareConfigPolicyview_practice_finance, manage_practice_finance✅
RevenueShareCalculationPolicyview_practice_finance, manage_practice_finance✅
RevenueShareDistributionPolicyview_practice_finance, manage_practice_finance✅
ReportExportPolicyview_practice_finance, manage_practice_finance✅

Background Jobs Created (2 files)

JobPurposeStatus
CommissionWorkflowJobExecute scheduled commission calculations✅
ReportExportJobAsync PDF/Excel/CSV generation✅

API Collections (.bru files) Created (74 files)

All API endpoints have corresponding Bruno HTTP client collections in kulcare-apis/Billing/:

  • Commission Rules (7 files)
  • Commission Calculations (5 files)
  • Commission Settlements (6 files)
  • Commission Workflows (8 files)
  • Commission Dashboard (2 files)
  • Revenue Share Configs (7 files)
  • Revenue Share Calculations (5 files)
  • Revenue Share Distributions (4 files)
  • Revenue Share Dashboard (1 file)
  • Reports (8 files)
  • Report Exports (4 files)

Executive Summary

What We Implemented

This plan covers the complete migration of three major functional areas to the new billing schema:

AreaDescriptionFiles Implemented
Financial ReportsRevenue analysis, dashboard, comparative & consolidated reports18 files
Commission SystemRules, calculations, workflows, settlements for practitioner compensation29 files
Revenue Share SystemConfiguration, calculations, distributions for stakeholder revenue sharing15 files
Report ExportsAsync report generation with PDF/Excel/CSV export6 files

Key Design Principles

PrincipleDescription
Domain-DrivenAll billing logic lives in billing.* schema
Tenant ScopedAll tables have tenant_id with RLS policies
UUIDv7 KeysPrimary keys use UUIDv7 for distributed compatibility
FHIR-AlignedReports follow FHIR financial resource patterns
Audit TrailFull audit trail via created_by, approved_by fields
Multi-CurrencySupport INR, USD, AED with proper exchange rates

Effort Estimate: COMPLETED

PhasePlannedActualStatus
Phase 1: Database Migration2-3 days2 days✅ Complete
Phase 2: Domain Foundation3-4 days3 days✅ Complete
Phase 3: Commission API5-7 days6 days✅ Complete
Phase 4: Revenue Share API4-5 days4 days✅ Complete
Phase 5: Reports API5-7 days5 days✅ Complete
Phase 6: Specs5-7 days-⏳ Skipped per requirements

Total: ~20 days of development (115+ files created)

Business Value

BenefitImpact
Unified SchemaAll billing-related logic consolidated in billing.* domain - no more scattered code across parts/billing and parts/clinic
Better Data ModelUUIDv7 primary keys provide sortable, time-ordered IDs ideal for distributed systems and audit trails
Explicit NamingSelf-documenting foreign keys (revenue_share_stakeholder_id vs generic stakeholder_id) improve code readability and reduce onboarding time
Enhanced MaintainabilityClear separation of concerns with domain-driven architecture - easier to locate, test, and modify billing logic
Multi-Tenant ScalabilityBuilt-in tenant isolation with RLS policies supports SaaS multi-tenancy from day one
FHIR AlignmentReports follow FHIR financial resource patterns for future healthcare interoperability
Comprehensive Audit TrailFull audit capability via created_by, approved_by, cancelled_by fields across all entities
Multi-Currency ReadyNative support for INR, USD, AED with proper exchange rate handling for international expansion
Soft Delete SupportCommission rules support soft delete with deleted, deleted_at, deleted_by columns
Enhanced Status WorkflowsCommission calculations now support CANCELLED status

What's Included

✅ All Business Logic Preserved from Legacy System:

Commission Types (all three):

  • Percentage commissions (% of gross amount)
  • Fixed commissions (fixed amount per service)
  • Tiered commissions (sliding scale with base + percentage)

Tiered Commission Approaches:

  • REVENUE_GENERATED: Based on ALL clinic billed services (management-level)
  • SERVICES: Based only on ASSIGNED practitioner services (individual/team performance)

Commission Assignments (BONUS FEATURE):

  • Practitioner and staff assignment to commission rules
  • Override percentages and fixed amounts per assignee
  • Active/inactive assignment tracking with effective dates
  • Support for hierarchical assignment structures

Revenue Sharing:

  • Hierarchical stakeholder support (parent → child relationships)
  • Multiple stakeholder types: Platform, Clinic Owner, Investor, Partner
  • Percentage-based or fixed-amount distribution methods
  • Configurable distribution rules via JSONB
  • Inline stakeholder creation/update with configs

Workflow Automation:

  • Scheduled execution (daily, weekly, monthly)
  • Automatic commission calculations based on invoice items
  • Configurable execution times per facility timezone
  • Background job execution via Sidekiq

Approval Workflows:

  • Calculations: CALCULATED → APPROVED → PAID → CANCELLED
  • Settlements: pending → approved → paid → cancelled
  • Revenue Share: calculated → approved → processed

Financial Reports:

  • Revenue Analysis (time-series data with trends)
  • Dashboard (high-level KPIs: monthly revenue, pending items)
  • Period Comparison (compare two time periods with growth %)
  • Location Comparison (compare facilities performance)
  • Consolidated (multi-facility overview with revenue, appointments, patients)

Report Exports:

  • Async PDF/Excel/CSV generation
  • Export types: COMMISSION_CALCULATIONS, REVENUE_ANALYSIS, REVENUE_SHARE, CONSOLIDATED_REPORT
  • Status tracking: PENDING → PROCESSING → COMPLETED/FAILED

✅ Enhanced Features:

  • Tenant isolation with Row Level Security (RLS) policies
  • Multi-currency support (INR, USD, AED) with exchange rate handling
  • Visual schema diagram for easy reference
  • Explicit foreign key naming convention
  • Comprehensive API documentation (40+ endpoints)
  • BONUS: Commission assignment tracking (not in original plan)
  • BONUS: Revenue distribution queue for post-commission revenue tracking
  • BONUS: Soft delete support for commission rules
  • BONUS: Cancelled status for commission calculations

Current System Analysis

1. Financial Reports

Current Location: parts/billing/controllers/premium_reports_controller.rb

Report TypeDescriptionKey MetricsOld Data Source
Revenue AnalysisTime-series revenue dataTotal, avg/day, patients, trendsclinic_patient_services.price
DashboardHigh-level KPIsMonthly revenue, pending itemsMultiple tables
Period ComparisonCompare two time periodsGrowth %, category breakdownclinic_patient_services
Location ComparisonCompare facilitiesPer-facility revenueclinic_patient_services
ConsolidatedMulti-facility overviewRevenue, appointments, patientsMultiple tables

2. Commission System

Current Locations:

  • Controllers: parts/billing/controllers/commission_*.rb, parts/clinic/controllers/commission_*.rb
  • Models: parts/billing/models/commission_*.rb, parts/clinic/models/commission_*.rb
ComponentDescriptionTables
RulesCommission rule definitionsclinic_commission_rules, commission_tiers
AssignmentsPractitioner/staff assignmentscommission_assignments
CalculationsPer-service calculationscommission_calculations
WorkflowsScheduled calculation jobscommission_workflows
SettlementsBatch payment settlementscommission_settlements
DashboardOverview & analyticsAggregated from above

Commission Types:

  • Percentage: % of gross amount
  • Fixed: Fixed amount per service
  • Tiered: Sliding scale based on revenue bands

3. Revenue Share System

Current Locations:

  • Controllers: parts/billing/controllers/revenue_share_*.rb, parts/clinic/controllers/revenue_share_*.rb
  • Models: parts/billing/models/revenue_share_*.rb, parts/clinic/models/revenue_share_*.rb
ComponentDescriptionTables
ConfigsRevenue share configurationsclinic_revenue_share_configs
StakeholdersStakeholder definitionsclinic_revenue_stakeholders
CalculationsCalculation batchesrevenue_share_calculations
DistributionsIndividual distributionsrevenue_share_distributions

Stakeholder Types: Platform, Clinic Owner, Investor, Partner

4. Report Exports

Current Location: parts/billing/models/report_export.rb

FieldTypeDescription
clinic_idFKReference to clinics
export_typeStringCOMMISSION_CALCULATIONS, COMMISSION_PAYOUT, REVENUE_ANALYSIS, etc.
file_formatStringPDF, EXCEL, CSV
statusStringPENDING, PROCESSING, COMPLETED, FAILED
parametersJSONBFilters and report parameters
file_urlStringS3 file location
error_messageTextError details if failed
created_by_idFKUser who triggered export
started_atDateTimeWhen processing started
completed_atDateTimeWhen processing completed

Proposed Schema Design

New Tables Overview

#TablePurposeOld Table
1billing.commission_rulesCommission rule definitionsclinic_commission_rules
2billing.commission_assignmentsPractitioner/staff assignmentscommission_assignments (BONUS)
3billing.commission_calculationsIndividual calculationscommission_calculations
4billing.commission_settlementsBatch settlementscommission_settlements
5billing.commission_workflowsScheduled jobscommission_workflows
6billing.revenue_share_configsRevenue share configsclinic_revenue_share_configs
7billing.revenue_share_stakeholdersStakeholder definitionsclinic_revenue_stakeholders
8billing.revenue_share_calculationsCalculation batchesrevenue_share_calculations
9billing.revenue_share_distributionsIndividual distributionsrevenue_share_distributions
10billing.revenue_distribution_queuesPost-commission revenueNEW (BONUS)
11billing.report_exportsAsync report exportsreport_exports

Table Definitions

1. Commission Rules

CREATE TABLE billing.commission_rules (
  -- Primary Key & Tenant
  id UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
  tenant_id UUID NOT NULL REFERENCES identity.tenants(id),
  facility_id UUID REFERENCES identity.facilities(id),  -- NULL = global rule

  -- Identification
  name VARCHAR(255) NOT NULL,
  description TEXT,
  rule_type VARCHAR(50) NOT NULL,  -- 'percentage', 'fixed', 'tiered'

  -- Commission Values
  commission_percentage DECIMAL(5,2),
  fixed_amount DECIMAL(12,2),
  tier_config JSONB,

  -- Applicability
  applies_to_all BOOLEAN DEFAULT false,
  practitioner_ids UUID[],
  service_type_ids UUID[],
  effective_from DATE NOT NULL,
  effective_to DATE,

  -- Status
  is_active BOOLEAN DEFAULT true,

  -- Soft Delete
  deleted BOOLEAN DEFAULT false NOT NULL,
  deleted_at TIMESTAMPTZ(6),
  deleted_by UUID REFERENCES identity.users(id),

  -- Audit
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  created_by UUID REFERENCES identity.users(id),

  CONSTRAINT chk_commission_values CHECK (
    (rule_type = 'percentage' AND commission_percentage IS NOT NULL)
    OR (rule_type = 'fixed' AND fixed_amount IS NOT NULL)
    OR (rule_type = 'tiered' AND tier_config IS NOT NULL)
  )
);

-- Indexes
CREATE INDEX idx_comm_rules_tenant_facility
  ON billing.commission_rules(tenant_id, facility_id);
CREATE INDEX idx_comm_rules_tenant_active
  ON billing.commission_rules(tenant_id, is_active)
  WHERE is_active = true;
CREATE INDEX idx_comm_rules_deleted
  ON billing.commission_rules(deleted);
CREATE INDEX idx_comm_rules_deleted_at
  ON billing.commission_rules(deleted_at);

Key Changes:

  • clinic_id → facility_id (references identity.facilities)
  • clinic_doctor_ids → practitioner_ids (references identity.practitioners)
  • basic_service_type_ids → service_type_ids (references invoice item types)
  • Added tenant_id for multi-tenancy
  • Added soft delete columns: deleted, deleted_at, deleted_by

2. Commission Calculations

CREATE TABLE billing.commission_calculations (
  -- Primary Key & Tenant
  id UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
  tenant_id UUID NOT NULL REFERENCES identity.tenants(id),
  facility_id UUID NOT NULL REFERENCES identity.facilities(id),

  -- Source References
  invoice_id UUID NOT NULL REFERENCES billing.invoices(id),
  invoice_item_id UUID REFERENCES billing.invoice_items(id),
  practitioner_id UUID NOT NULL REFERENCES identity.practitioners(id),
  commission_rule_id UUID REFERENCES billing.commission_rules(id),

  -- Calculation Details
  gross_amount DECIMAL(12,2) NOT NULL,
  commission_amount DECIMAL(12,2) NOT NULL,
  calculation_method VARCHAR(20) NOT NULL,

  -- Status Workflow
  status VARCHAR(20) NOT NULL DEFAULT 'CALCULATED',
  calculated_at TIMESTAMPTZ NOT NULL,
  approved_at TIMESTAMPTZ,
  approved_by UUID REFERENCES identity.users(id),
  paid_at TIMESTAMPTZ,
  cancelled_at TIMESTAMPTZ,
  cancelled_by UUID REFERENCES identity.users(id),

  -- Settlement Reference
  commission_settlement_id UUID REFERENCES billing.commission_settlements(id),

  -- Metadata
  notes TEXT,
  metadata JSONB DEFAULT '{}',

  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

Key Changes:

  • clinic_id → facility_id
  • clinic_patient_service_id → invoice_item_id
  • clinic_doctor_id → practitioner_id
  • Added CANCELLED status: cancelled_at, cancelled_by
  • Added tenant_id

3. Commission Settlements

CREATE TABLE billing.commission_settlements (
  -- Primary Key & Tenant
  id UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
  tenant_id UUID NOT NULL REFERENCES identity.tenants(id),
  facility_id UUID NOT NULL REFERENCES identity.facilities(id),
  practitioner_id UUID NOT NULL REFERENCES identity.practitioners(id),

  -- Settlement Period
  settlement_period VARCHAR(7) NOT NULL,
  period_start DATE NOT NULL,
  period_end DATE NOT NULL,

  -- Financial Summary
  total_commission DECIMAL(12,2) NOT NULL DEFAULT 0,
  total_deductions DECIMAL(12,2) NOT NULL DEFAULT 0,
  net_amount DECIMAL(12,2) NOT NULL,

  -- Status Workflow
  status VARCHAR(20) NOT NULL DEFAULT 'pending',
  approved_at TIMESTAMPTZ,
  approved_by UUID REFERENCES identity.users(id),
  paid_at TIMESTAMPTZ,
  payment_reference VARCHAR(255),
  cancelled_at TIMESTAMPTZ,
  cancelled_by UUID REFERENCES identity.users(id),
  cancellation_reason TEXT,

  -- Payment Transfer
  payment_transfer_id UUID,

  -- Metadata
  notes TEXT,

  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

  CONSTRAINT chk_settlement_amounts CHECK (
    net_amount >= 0 AND net_amount <= (total_commission - total_deductions)
  )
);

Key Changes:

  • clinic_id → facility_id
  • clinic_doctor_id → practitioner_id
  • Added tenant_id
  • Added cancellation support: cancelled_at, cancelled_by, cancellation_reason

Visual Schema Diagram

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                              BILLING SCHEMA - Reports & Commissions                    │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  ┌─────────────────────────── COMMISSION SYSTEM ───────────────────────────┐        │
│  │                                                                           │        │
│  │  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐      │        │
│  │  │ commission_rules │───>│commission_assignments│                    │      │        │
│  │  └────────┬────────┘    └─────────────────┘                            │      │        │
│  │           │                                                             │      │        │
│  │           │                                                            ▼      │        │
│  │           │                    ┌─────────────────────────────────┐    │      │        │
│  │           └───────────────────<│ commission_calculations          │    │      │        │
│  │                                │ • invoice_item_id ────────┐     │    │      │        │
│  │                                │ • practitioner_id           │     │    │      │        │
│  │                                │ • commission_rule_id        │     │    │      │        │
│  │                                └────────────────────────────┼─────┘    │      │        │
│  │                                                         │            │      │        │
│  │                                                         ▼            │      │        │
│  │                                ┌─────────────────────────────────┐  │      │        │
│  │                                │ commission_settlements           │  │      │        │
│  │                                │ • practitioner_id               │  │      │        │
│  │                                └─────────────────────────────────┘  │      │        │
│  │                                                                           │        │
│  └───────────────────────────────────────────────────────────────────────────┘        │
│                                                                                      │
│  ┌────────────────────────── REVENUE SHARE SYSTEM ──────────────────────────┐       │
│  │                                                                           │       │
│  │  ┌──────────────────────────┐                                            │       │
│  │  │ revenue_share_configs    │                                            │       │
│  │  └────────────┬─────────────┘                                            │       │
│  │               │                                                           │       │
│  │               ▼                                                           │       │
│  │  ┌────────────────────────────────────┐                                  │       │
│  │  │ revenue_share_stakeholders          │                                  │       │
│  │  │ • parent_revenue_share_stakeholder_id (self-ref)                      │       │
│  │  │   └── allows hierarchical stakeholder trees                           │       │
│  │  └────────────┬─────────────────────────┘                                  │       │
│  │               │                                                            │       │
│  │               ▼                                                            │       │
│  │  ┌────────────────────────────────────┐    ┌────────────────────────────┐  │       │
│  │  │ revenue_share_calculations          │───>│ revenue_share_distributions  │  │       │
│  │  └────────────────────────────────────┘    │ • revenue_share_stakeholder_id│  │       │
│  │                                              └────────────────────────────┘  │       │
│  │                                                                           │       │
│  └───────────────────────────────────────────────────────────────────────────┘       │
│                                                                                      │
│  ┌──────────────────────────   REPORTS & EXPORTS   ──────────────────────────┐       │
│  │                                                                           │       │
│  │  ┌─────────────────┐                                                       │       │
│  │  │ report_exports  │───> Generated Files (PDF/Excel/CSV)                   │       │
│  │  │                 │       • REVENUE_ANALYSIS                               │       │
│  │  │                 │       • COMMISSION_CALCULATIONS                        │       │
│  │  │                 │       • REVENUE_SHARE                                  │       │
│  │  │                 │       • CONSOLIDATED_REPORT                            │       │
│  │  └─────────────────┘                                                       │       │
│  │                                                                           │       │
│  └───────────────────────────────────────────────────────────────────────────┘       │
│                                                                                      │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                              CROSS-DOMAIN REFERENCES                                   │
├─────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                      │
│  IDENTITY FACILITIES ◄─────────────────────┐                                       │
│  └── facility_id (all tables)               │                                       │
│                                              │                                       │
│  IDENTITY PRACTITIONERS ◄───────────────────┤                                       │
│  └── practitioner_id (commission tables)     │                                       │
│                                              │                                       │
│  IDENTITY USERS ─────────────────────────────┤                                       │
│  └── created_by, approved_by, cancelled_by, deleted_by (audit fields)             │
│                                              │                                       │
│  BILLING INVOICES ───────────────────────────┤                                       │
│  └── invoice_id (commission_calculations)    │                                       │
│                                              │                                       │
│  BILLING INVOICE ITEMS ──────────────────────┤                                       │
│  └── invoice_item_id (commission_calculations)                                      │
│                                                                                      │
└─────────────────────────────────────────────────────────────────────────────────────┘

COLUMN NAME CONVENTION:
───────────────────────────
Foreign keys follow: {referenced_table_singular}_id pattern

Examples:
• practitioner_id → REFERENCES identity.practitioners(id)
• facility_id → REFERENCES identity.facilities(id)
• invoice_item_id → REFERENCES billing.invoice_items(id)
• commission_settlement_id → REFERENCES billing.commission_settlements(id)
• revenue_share_stakeholder_id → REFERENCES billing.revenue_share_stakeholders(id)
• parent_revenue_share_stakeholder_id → REFERENCES billing.revenue_share_stakeholders(id) (self-ref)

Key Changes Explained

1. Association Updates

The primary change is updating foreign key references to point to the new schema tables:

Old ReferenceNew ReferenceDomain
clinic_id → clinicsfacility_id → identity.facilitiesIdentity
clinic_doctor_id → clinic_doctorspractitioner_id → identity.practitionersIdentity
clinic_patient_service_id → clinic_patient_servicesinvoice_item_id → billing.invoice_itemsBilling
billing_invoice_id → billing_invoicesinvoice_id → billing.invoicesBilling

2. Tenant Isolation

All tables now include:

  • tenant_id UUID NOT NULL REFERENCES identity.tenants(id)
  • Row Level Security (RLS) policies for automatic tenant filtering
  • Queries automatically scoped to current tenant

3. UUIDv7 Primary Keys

All tables use:

  • id UUID PRIMARY KEY DEFAULT uuid_generate_v7()
  • Provides sortable, time-ordered IDs
  • Better for distributed systems than UUIDv4

4. Column Preservation

All business logic columns remain identical:

  • Commission amounts, percentages, tiers
  • Status workflows (CALCULATED → APPROVED → PAID → CANCELLED)
  • Settlement periods, distributions
  • Export types, formats, statuses
  • All JSONB configuration structures

5. Soft Delete Support (NEW)

Commission rules table now includes:

  • deleted BOOLEAN DEFAULT false
  • deleted_at TIMESTAMPTZ(6)
  • deleted_by UUID REFERENCES identity.users(id)
  • Allows safe deletion without losing historical data

6. Enhanced Status Workflows (NEW)

Commission calculations now support:

  • CALCULATED → APPROVED → PAID
  • CALCULATED → CANCELLED (new)
  • Settlements support cancellation with cancelled_at, cancelled_by, cancellation_reason

Domain Structure

backend/domains/billing/
├── models/
│   ├── base_record.rb (existing)
│   ├── invoice.rb (existing)
│   ├── invoice_item.rb (existing)
│   ├── payment.rb (existing)
│   ├── payment_allocation.rb (existing)
│   ├── commission_rule.rb ✅
│   ├── commission_assignment.rb ✅ (BONUS - not in original plan)
│   ├── commission_calculation.rb ✅
│   ├── commission_settlement.rb ✅
│   ├── commission_workflow.rb ✅
│   ├── revenue_share_config.rb ✅
│   ├── revenue_share_stakeholder.rb ✅
│   ├── revenue_share_calculation.rb ✅
│   ├── revenue_share_distribution.rb ✅
│   ├── revenue_distribution_queue.rb ✅ (BONUS - separate migration)
│   └── report_export.rb ✅
│
├── blueprints/
│   ├── invoice_blueprint.rb (existing)
│   ├── invoice_item_blueprint.rb (existing)
│   ├── payment_blueprint.rb (existing)
│   ├── payment_allocation_blueprint.rb (existing)
│   ├── commission_rule_blueprint.rb ✅
│   ├── commission_calculation_blueprint.rb ✅
│   ├── commission_settlement_blueprint.rb ✅
│   ├── commission_workflow_blueprint.rb ✅
│   ├── commission_assignment_blueprint.rb ✅
│   ├── revenue_share_config_blueprint.rb ✅
│   ├── revenue_share_calculation_blueprint.rb ✅
│   ├── revenue_share_distribution_blueprint.rb ✅
│   └── report_export_blueprint.rb ✅
│
├── controllers/
│   ├── base_controller.rb (existing)
│   ├── invoices_controller.rb (existing)
│   ├── invoice_items_controller.rb (existing)
│   ├── payments_controller.rb (existing)
│   ├── payment_allocations_controller.rb (existing)
│   ├── commission_rules_controller.rb ✅
│   ├── commission_calculations_controller.rb ✅
│   ├── commission_settlements_controller.rb ✅
│   ├── commission_workflows_controller.rb ✅
│   ├── commission_dashboard_controller.rb ✅
│   ├── revenue_share_configs_controller.rb ✅
│   ├── revenue_share_calculations_controller.rb ✅
│   ├── revenue_share_distributions_controller.rb ✅
│   └── premium_reports_controller.rb ✅ (handles all reports)
│
├── services/
│   ├── base_service.rb (existing)
│   ├── invoices/ (existing)
│   ├── payments/ (existing)
│   ├── commissions/
│   │   ├── commission_rules_service.rb ✅
│   │   ├── commission_calculation_service.rb ✅
│   │   ├── tiered_commission_calculation_service.rb ✅
│   │   ├── approve_service.rb ✅
│   │   ├── bulk_update_service.rb ✅
│   │   ├── update_status_service.rb ✅
│   │   ├── settlement_service.rb ✅
│   │   ├── index_service.rb ✅
│   │   ├── workflow_execute_service.rb ✅
│   │   ├── commission_workflows_service.rb ✅
│   │   ├── overview_service.rb ✅
│   │   └── analytics_service.rb ✅
│   ├── revenue_share/
│   │   ├── revenue_share_configs_service.rb ✅
│   │   ├── calculation_service.rb ✅
│   │   └── dashboard_service.rb ✅
│   ├── reports/
│   │   ├── revenue_analysis_service.rb ✅
│   │   ├── revenue_analysis_export_service.rb ✅
│   │   ├── dashboard_service.rb ✅
│   │   ├── period_comparison_service.rb ✅
│   │   ├── location_comparison_service.rb ✅
│   │   ├── consolidated_service.rb ✅
│   │   ├── comparative_export_service.rb ✅
│   │   └── consolidated_export_service.rb ✅
│   └── exports/
│       └── create_service.rb ✅
│
├── policies/
│   ├── invoice_policy.rb (existing)
│   ├── invoice_item_policy.rb (existing)
│   ├── payment_policy.rb (existing)
│   ├── payment_allocation_policy.rb (existing)
│   ├── commission_rule_policy.rb ✅
│   ├── commission_calculation_policy.rb ✅
│   ├── commission_settlement_policy.rb ✅
│   ├── commission_workflow_policy.rb ✅
│   ├── revenue_share_config_policy.rb ✅
│   ├── revenue_share_calculation_policy.rb ✅
│   ├── revenue_share_distribution_policy.rb ✅
│   └── report_export_policy.rb ✅
│
├── routes.rb (existing - extended)
├── jobs/ (NEW - background jobs)
│   ├── commission_workflow_job.rb ✅
│   └── report_export_job.rb ✅
│
└── spec/ (existing - extended)

API Endpoints

Commission Rules

GET    /billing/commission_rules
POST   /billing/commission_rules
GET    /billing/commission_rules/:id
PATCH  /billing/commission_rules/:id
DELETE /billing/commission_rules/:id
POST   /billing/commission_rules/:id/activate
POST   /billing/commission_rules/:id/deactivate

Commission Calculations

GET    /billing/commission_calculations
GET    /billing/commission_calculations/:id
PATCH  /billing/commission_calculations/:id
POST   /billing/commission_calculations/bulk_update
POST   /billing/commission_calculations/export

Commission Settlements

GET    /billing/commission_settlements
POST   /billing/commission_settlements/generate
GET    /billing/commission_settlements/:id
PATCH  /billing/commission_settlements/:id/approve
POST   /billing/commission_settlements/:id/pay
POST   /billing/commission_settlements/:id/cancel

Commission Dashboard

GET    /billing/commission_dashboard
GET    /billing/commission_dashboard/analytics

Commission Workflows

GET    /billing/commission_workflows
POST   /billing/commission_workflows
GET    /billing/commission_workflows/:id
PATCH  /billing/commission_workflows/:id
POST   /billing/commission_workflows/:id/execute

Revenue Share

GET    /billing/revenue_share_configs
POST   /billing/revenue_share_configs
GET    /billing/revenue_share_configs/:id
PATCH  /billing/revenue_share_configs/:id
DELETE /billing/revenue_share_configs/:id

GET    /billing/revenue_share_calculations
POST   /billing/revenue_share_calculations/calculate
GET    /billing/revenue_share_calculations/dashboard
GET    /billing/revenue_share_calculations/:id
PATCH  /billing/revenue_share_calculations/:id/approve

GET    /billing/revenue_share_distributions
GET    /billing/revenue_share_distributions/:id
PATCH  /billing/revenue_share_distributions/:id/approve
POST   /billing/revenue_share_distributions/:id/pay

Reports

GET    /billing/premium_reports/revenue_analysis
POST   /billing/premium_reports/export_revenue_analysis
GET    /billing/premium_reports/dashboard
GET    /billing/premium_reports/period_comparison
GET    /billing/premium_reports/location_comparison
POST   /billing/premium_reports/export_comparative
GET    /billing/premium_reports/consolidated
POST   /billing/premium_reports/export_consolidated

Report Exports

GET    /billing/report_exports
POST   /billing/report_exports
GET    /billing/report_exports/:id
GET    /billing/report_exports/:id/download

Data Migration Strategy

Mapping Table

Old TableNew TablePrimary Changes
clinic_commission_rulesbilling.commission_rulesclinic_id → facility_id, clinic_doctor_ids → practitioner_ids, added soft delete
commission_assignmentsbilling.commission_assignmentsclinic_id → facility_id, clinic_doctor_id → practitioner_id
commission_calculationsbilling.commission_calculationsclinic_id → facility_id, clinic_patient_service_id → invoice_item_id, clinic_doctor_id → practitioner_id, added cancellation support
commission_settlementsbilling.commission_settlementsclinic_id → facility_id, clinic_doctor_id → practitioner_id, added cancellation support
commission_workflowsbilling.commission_workflowsclinic_id → facility_id
clinic_revenue_share_configsbilling.revenue_share_configsclinic_id → facility_id
clinic_revenue_stakeholdersbilling.revenue_share_stakeholdersclinic_id → facility_id, parent_stakeholder_id → parent_revenue_share_stakeholder_id
revenue_share_calculationsbilling.revenue_share_calculationsclinic_id → facility_id, config_id → revenue_share_config_id
revenue_share_distributionsbilling.revenue_share_distributionsclinic_id → facility_id, calculation_id → revenue_share_calculation_id, stakeholder_id → revenue_share_stakeholder_id
report_exportsbilling.report_exportsclinic_id → facility_id
clinicsidentity.facilitiesMigrated separately
clinic_doctorsidentity.practitionersMigrated separately

Migration Approach

  1. Prerequisites: Ensure identity.facilities and identity.practitioners are migrated
  2. Create New Tables: Run the new migration
  3. Migrate Data: Copy data from old tables to new tables with updated references
  4. Verify: Compare counts and sums between old and new
  5. Deploy Cutover: Switch application to use new tables

Summary

Files Created: 115+ files

CategoryPlannedActualStatus
Migration12✅ Complete
Models911✅ Complete (2 bonus)
Blueprints1210✅ Complete
Controllers109✅ Complete
Policies910✅ Complete
Services4031✅ Complete
Background Jobs02✅ Complete (bonus)
API Collections (.bru)074✅ Complete
Specs440⏳ Skipped per requirements

Effort Estimate: COMPLETED

Dependencies

  • Clinical schema (patients, encounters) ✓ (already implemented)
  • Identity schema (facilities, practitioners) ✓ (already implemented)
  • Base billing tables (invoices, invoice_items, payments) ✓ (already implemented)

Bonus Features Delivered

Beyond the original plan, we also implemented:

  1. Commission Assignment Tracking - Separate table with many-to-many relationship between rules and practitioners/staff
  2. Revenue Distribution Queue - Tracks remaining revenue after commission deductions
  3. Soft Delete Support - Commission rules can be soft-deleted
  4. Cancellation Workflows - Both calculations and settlements can be cancelled
  5. Inline Stakeholder Management - Revenue share configs handle stakeholders inline (no separate endpoint needed)
  6. Background Job Support - Dedicated jobs for workflows and export generation
  7. Enhanced Validations - 100% stakeholder percentage checks, uniqueness validations
  8. Hierarchical Stakeholders - Parent-child relationships for complex revenue sharing
  9. Comprehensive API Documentation - 74 .bru files for Bruno HTTP client

Approval Checklist

  • Schema design implemented
  • API structure implemented
  • Migration strategy executed
  • Data preservation verified
  • All business logic migrated
  • Soft delete support added
  • Cancellation workflows added
  • Background jobs created
  • API documentation created
  • Specs created (skipped per requirements)

On this page