Revenue Sharing & Commission System - Complete Backend Documentation
Last Updated: January 2025 Status: ✅ Implemented and Production Ready Version: 2.0 (Verified Implementation)
Table of Contents
- Overview
- Architecture
- Database Schema
- Core Models
- API Endpoints
- Business Logic (Interactors)
- Background Jobs & Automation
- Testing
- Deployment & Configuration
- Pending Features & Future Enhancements
Overview
The Revenue Sharing & Commission System provides comprehensive functionality for managing:
- Doctor Commissions: Individual earnings based on consultations and services
- Revenue Sharing: Multi-stakeholder business revenue distribution
- Settlements: Monthly aggregation and payment processing
- Commission Rules: Flexible percentage, fixed, and tiered commission structures
- Analytics & Reporting: Comprehensive financial dashboards
- Automated Workflows: Scheduled calculations and notifications
Verified Implemented Features
✅ Commission Management:
- Commission rule management with percentage, fixed, and tiered types
- Commission calculations (manual and automated)
- Commission workflows (automated daily/weekly/monthly processing)
- Commission dashboard with analytics
- Approval workflow
- Payment tracking
- Export functionality
✅ Revenue Sharing:
- Clinic stakeholder management
- Revenue share configurations
- Stakeholder distribution setup
✅ Financial Reports:
- Revenue analysis reports
- Period comparison reports
- Location comparison reports
- Consolidated reports
- Export functionality (CSV/Excel/PDF)
- Report export history
Architecture
Parts-Based Modular Structure
backend/
├── parts/
│ ├── clinic/
│ │ ├── models/ # Stakeholders, commission rules, configurations
│ │ ├── controllers/ # Stakeholder, configuration, rule management
│ │ ├── interactors/ # Business logic for clinic-level operations
│ │ └── serializers/ # JSON response formatting
│ └── billing/
│ ├── models/ # Calculations, settlements, distributions
│ ├── controllers/ # Dashboards, payments, reports
│ ├── interactors/ # Commission processing, settlements
│ └── serializers/ # Financial data formattingDesign Patterns
- Interactor Pattern: All business logic encapsulated in interactors
- Service Objects: Complex calculations in service classes
- Serializers: Consistent API response formatting
- Background Jobs: Sidekiq for async processing
- Pundit Policies: Authorization and access control
Database Schema
Core Tables
1. Clinic Stakeholders
create_table :clinic_stakeholders do |t|
t.references :clinic, null: false, foreign_key: true
t.references :user, null: true, foreign_key: true
t.string :name, null: false
t.string :email
t.string :phone_number
t.string :country_code, default: '+91'
t.string :stakeholder_type # owner, partner, investor, referrer, platform
t.string :status, default: 'active' # active, inactive, invited, pending
t.timestamp :invited_at
t.boolean :deleted, default: false
t.timestamp :deleted_at
t.string :photo
t.timestamps
end2. Clinic Revenue Share Configurations
create_table :clinic_revenue_share_configs do |t|
t.references :clinic, null: false, foreign_key: true
t.references :clinic_group, null: true, foreign_key: true
t.string :configuration_name, null: false
t.text :description
t.jsonb :distribution_rules, null: false, default: {}
t.jsonb :approval_workflow_config, default: {}
t.datetime :effective_from, null: false
t.datetime :effective_until
t.string :status, default: 'draft' # draft, active, inactive, archived
t.references :created_by_user, null: false
t.references :updated_by_user
t.references :approved_by_user
t.datetime :approved_at
t.timestamps
end3. Clinic Revenue Stakeholders
create_table :clinic_revenue_stakeholders do |t|
t.references :clinic_revenue_share_config, null: false
t.references :clinic, null: false
t.references :clinic_stakeholder, null: true # null for platform fees
t.references :parent_stakeholder # for hierarchical distributions
t.decimal :share_percentage, precision: 5, scale: 2
t.decimal :share_amount, precision: 10, scale: 2
t.decimal :minimum_amount, precision: 10, scale: 2, default: 0
t.decimal :maximum_amount, precision: 10, scale: 2
t.references :billing_account
t.string :payout_method, default: 'bank_transfer'
t.integer :priority, default: 0
t.boolean :active, default: true
t.timestamps
end4. Commission Rules
create_table :clinic_commission_rules do |t|
t.references :clinic, null: false
t.references :clinic_group
t.references :basic_commission_rule_type, null: false
t.string :rule_name, null: false
t.text :rule_description
t.decimal :commission_percentage, precision: 5, scale: 2
t.decimal :fixed_amount, precision: 10, scale: 2
t.datetime :effective_from, null: false
t.datetime :effective_to
t.integer :priority, default: 0
t.boolean :active, default: true
t.boolean :applies_to_all_services, default: true
t.references :created_by_user, null: false
t.references :updated_by_user
t.references :role
t.boolean :deleted, default: false
t.datetime :deleted_at
t.timestamps
end5. Commission Tiers (for tiered rules)
create_table :commission_tiers do |t|
t.references :clinic_commission_rule, null: false
t.string :tier_name, null: false
t.decimal :min_amount, precision: 10, scale: 2, null: false
t.decimal :max_amount, precision: 10, scale: 2
t.decimal :commission_percentage, precision: 5, scale: 2
t.decimal :commission_fixed_amount, precision: 10, scale: 2
t.integer :tier_order, null: false
t.boolean :active, default: true
t.timestamps
end6. Commission Calculations
create_table :commission_calculations do |t|
t.references :clinic, null: false
t.references :clinic_doctor, null: false
t.references :appointment
t.references :billing_payment
t.references :clinic_patient_service
t.references :clinic_commission_rule
t.references :basic_service_type
t.decimal :gross_amount, precision: 10, scale: 2, null: false
t.decimal :commission_percentage_used, precision: 5, scale: 2
t.decimal :fixed_amount_used, precision: 10, scale: 2
t.decimal :calculated_commission, precision: 10, scale: 2, null: false
t.string :status, default: 'CALCULATED' # CALCULATED, APPROVED, PAID, CANCELLED
t.string :calculation_method # percentage, fixed, tiered
t.datetime :calculated_at, null: false
t.datetime :approved_at
t.references :approved_by_user
t.datetime :paid_at
t.references :billing_transfer
t.references :commission_settlement
t.text :notes
t.timestamps
end7. Commission Settlements
create_table :commission_settlements do |t|
t.references :clinic_doctor, null: false
t.references :clinic, null: false
t.references :clinic_group
t.string :settlement_period, null: false # YYYY-MM
t.date :period_start, null: false
t.date :period_end, null: false
t.decimal :total_earnings, precision: 10, scale: 2, null: false
t.decimal :total_deductions, precision: 10, scale: 2, default: 0
t.decimal :net_amount, precision: 10, scale: 2, null: false
t.string :status, default: 'pending' # pending, approved, processing, paid, cancelled
t.date :paid_on
t.string :payment_reference
t.text :notes
t.references :approved_by_user
t.datetime :approved_at
t.references :billing_transfer
t.references :commission_workflow
t.timestamps
end8. Commission Workflows
create_table :commission_workflows do |t|
t.references :clinic, null: false
t.string :commission_type, null: false # COMMISSION_CALCULATION, SETTLEMENT_GENERATION
t.string :schedule_frequency, null: false # DAILY, WEEKLY, MONTHLY
t.time :schedule_time
t.date :last_run_date
t.datetime :last_run_at
t.string :current_status, default: 'RUNNING'
t.boolean :enabled, default: true
t.references :created_by_user
t.timestamps
end9. Revenue Distribution Queue
create_table :revenue_distribution_queue do |t|
t.references :clinic, null: false
t.references :clinic_group
t.decimal :amount, precision: 10, scale: 2, null: false
t.string :source_type, null: false # ClinicPatientPayment, etc.
t.integer :source_id, null: false
t.string :status, default: 'pending_distribution'
t.datetime :revenue_date, null: false
t.datetime :distributed_at
t.text :notes
t.timestamps
end10. Revenue Share Calculations
create_table :revenue_share_calculations do |t|
t.references :clinic_revenue_share_config, null: false
t.references :clinic, null: false
t.datetime :period_start, null: false
t.datetime :period_end, null: false
t.decimal :total_revenue, precision: 12, scale: 2, null: false
t.decimal :distributable_revenue, precision: 12, scale: 2, null: false
t.decimal :platform_fees, precision: 10, scale: 2, default: 0
t.jsonb :calculation_details, default: {}
t.jsonb :distribution_summary, default: {}
t.string :status, default: 'calculated'
t.datetime :calculated_at
t.datetime :approved_at
t.datetime :processed_at
t.jsonb :error_details
t.references :created_by_user
t.timestamps
endReference Tables
Basic Commission Rule Types
create_table :basic_commission_rule_types do |t|
t.string :name, null: false, unique: true
t.string :display_name, null: false
t.text :description
t.boolean :requires_percentage, default: false
t.boolean :requires_fixed_amount, default: false
t.boolean :requires_tiers, default: false
t.boolean :active, default: true
t.timestamps
end
# Seeded values:
# - percentage: "Percentage Commission"
# - fixed: "Fixed Amount Commission"Basic Service Types
create_table :basic_service_types do |t|
t.string :name, null: false, unique: true
t.string :display_name, null: false
t.text :description
t.boolean :active, default: true
t.timestamps
end
# Seeded values:
# - consultation: "Consultation"
# - telemedicine: "Telemedicine"
# - others: "Others"Database Schema Diagram
Entity Relationship Diagrams
Diagram 1: Core Entities & Master Data
Diagram 2: Stakeholders & Revenue Sharing
Diagram 3: Commission Rules & Tiers (VERIFIED: Tiered Support Implemented)
Diagram 4: Commission Calculations & Settlements
Key Tables Overview
Master Data (Reference Tables):
basic_commission_rule_types- Commission calculation methods (percentage, fixed, tiered)basic_service_types- Medical service categories (consultation, procedure, lab_test, imaging, pharmacy, others)
Stakeholder Management:
clinic_stakeholders- All stakeholders (owners, partners, investors, referrers, platform)clinic_revenue_share_configs- Revenue sharing configuration templatesclinic_revenue_stakeholders- Links stakeholders to configs with percentages
Commission System:
clinic_commission_rules- Commission calculation rulescommission_tiers- VERIFIED IMPLEMENTED - Tiered commission structurescommission_rule_service_types- Maps rules to service typesclinic_commission_assignments- Maps rules to doctors/staff (polymorphic)
Transaction Processing:
commission_calculations- Individual commission calculations per appointmentcommission_settlements- Monthly settlement aggregationscommission_workflows- Automated workflow configurationsrevenue_share_calculations- Revenue distribution calculations
Background Jobs (VERIFIED: Exist in codebase):
CommissionCalculationJob(parts/clinic/services/commission_calculation_job.rb)CalculateCommissionJob(parts/clinic/services/calculate_commission_job.rb)CommissionWorkflowExecutionJob(parts/billing/services/commission_workflow_execution_job.rb)RunCommissionWorkflowsJob(parts/billing/services/run_commission_workflows_job.rb)
Schema Features
Verified Implemented:
- Commission tiers table (migration:
20250901132225_create_commission_tiers.rb) - Tiered commission calculation with
calculate_tiered_commissionmethod - Commission workflows with DAILY/WEEKLY/MONTHLY scheduling
- Revenue share stakeholders with hierarchical support (
parent_stakeholder_id) - Polymorphic commission assignments for doctors and staff
Status Enumerations:
- Commission Calculation: CALCULATED, APPROVED, PAID, CANCELLED
- Commission Settlement: pending, approved, processing, paid, cancelled
- Commission Workflow: RUNNING, SUCCESS, FAILED
- Revenue Share Config: draft, active, inactive, archived
- Stakeholder: active, inactive, invited, pending
Core Models
ClinicStakeholder
class ClinicStakeholder < ApplicationRecord
belongs_to :clinic
belongs_to :user, optional: true
has_many :clinic_revenue_stakeholders, dependent: :destroy
validates :name, presence: true
validates :stakeholder_type, inclusion: { in: %w[owner partner investor referrer platform] }
validates :status, inclusion: { in: %w[active inactive invited pending] }
scope :active, -> { where(status: 'active', deleted: false) }
scope :by_type, ->(type) { where(stakeholder_type: type) }
def deactivate!
update!(status: 'inactive')
clinic_revenue_stakeholders.update_all(active: false)
end
endClinicRevenueShareConfig
class ClinicRevenueShareConfig < ApplicationRecord
belongs_to :clinic
belongs_to :created_by_user, class_name: 'User'
has_many :clinic_revenue_stakeholders, dependent: :destroy
has_many :revenue_share_calculations, dependent: :restrict_with_error
validates :configuration_name, presence: true, uniqueness: { scope: :clinic_id }
validates :effective_from, presence: true
validate :validate_stakeholder_percentages
scope :active, -> { where(status: 'active') }
scope :effective_on, ->(date) {
active.where('effective_from <= ?', date)
.where('effective_until IS NULL OR effective_until >= ?', date)
}
def activate!
transaction do
clinic.clinic_revenue_share_configs.where.not(id: id).active.update_all(status: 'inactive')
update!(status: 'active', approved_at: Time.current)
end
end
def total_percentage_allocated
clinic_revenue_stakeholders.where(parent_stakeholder_id: nil).sum(:share_percentage)
end
def calculate_distribution(amount, context = {})
# Returns hash of {stakeholder_id => {stakeholder:, amount:}}
end
endClinicCommissionRule
class ClinicCommissionRule < ApplicationRecord
belongs_to :clinic
belongs_to :basic_commission_rule_type
belongs_to :created_by_user, class_name: 'User'
has_many :commission_rule_service_types, dependent: :destroy
has_many :basic_service_types, through: :commission_rule_service_types
has_many :clinic_commission_assignments, dependent: :destroy
has_many :clinic_doctors, through: :clinic_commission_assignments
has_many :commission_tiers, dependent: :destroy
has_many :commission_calculations, dependent: :restrict_with_error
after_create :ensure_commission_workflow_exists
validates :rule_name, presence: true
validates :effective_from, presence: true
scope :active, -> { where(active: true, deleted: false) }
scope :effective_on, ->(date) {
active.where('effective_from <= ?', date)
.where('effective_to IS NULL OR effective_to >= ?', date)
}
def calculate_commission(amount, service_type_id = nil)
case basic_commission_rule_type.name
when 'percentage' then calculate_percentage_commission(amount)
when 'fixed' then fixed_amount
when 'tiered' then calculate_tiered_commission(amount)
else 0
end
end
def percentage_type?
basic_commission_rule_type&.name == 'percentage'
end
def fixed_type?
basic_commission_rule_type&.name == 'fixed'
end
def tiered_type?
basic_commission_rule_type&.name == 'tiered'
end
endCommissionCalculation
class CommissionCalculation < ApplicationRecord
belongs_to :clinic
belongs_to :clinic_doctor
belongs_to :appointment, optional: true
belongs_to :clinic_commission_rule, optional: true
belongs_to :commission_settlement, optional: true
validates :gross_amount, presence: true
validates :calculated_commission, presence: true
validates :status, inclusion: { in: %w[CALCULATED APPROVED PAID CANCELLED] }
scope :calculated, -> { where(status: 'CALCULATED') }
scope :approved, -> { where(status: 'APPROVED') }
scope :paid, -> { where(status: 'PAID') }
scope :pending_payment, -> { where(status: %w[CALCULATED APPROVED]) }
def approve!(user)
update!(status: 'APPROVED', approved_at: Time.current, approved_by_user: user)
end
def mark_as_paid!(billing_transfer)
update!(status: 'PAID', paid_at: Time.current, billing_transfer: billing_transfer)
end
endCommissionSettlement
class CommissionSettlement < ApplicationRecord
STATUSES = %w[pending approved processing paid cancelled].freeze
belongs_to :clinic_doctor
belongs_to :clinic
has_many :commission_calculations
validates :settlement_period, uniqueness: { scope: :clinic_doctor_id }
validates :status, inclusion: { in: STATUSES }
scope :pending_approval, -> { where(status: 'pending') }
scope :approved, -> { where(status: 'approved') }
scope :paid, -> { where(status: 'paid') }
def self.generate_for_period(clinic_doctor, start_date, end_date)
# Creates settlement and links calculations
end
def approve!(user)
update!(status: 'approved', approved_at: Time.current, approved_by_user: user)
end
def mark_paid!(payment_reference, billing_transfer = nil)
update!(status: 'paid', paid_on: Date.current, payment_reference: payment_reference)
commission_calculations.update_all(status: 'PAID', paid_at: Time.current)
end
def can_be_paid?
status == 'approved' && net_amount > 0
end
endAPI Endpoints
Clinic Stakeholders APIs
List Stakeholders
GET /clinics/:clinic_id/clinic_stakeholdersResponse:
{
"success": true,
"data": {
"clinic_stakeholders": [
{
"id": 1,
"name": "Dr. John Doe",
"email": "john@example.com",
"phone_number": "9876543210",
"country_code": "+91",
"stakeholder_type": "owner",
"status": "active"
}
]
}
}Create Stakeholder
POST /clinics/:clinic_id/clinic_stakeholders
Content-Type: application/json
{
"name": "Jane Smith",
"email": "jane@example.com",
"stakeholder_type": "partner",
"phone_number": "9876543211"
}Delete Stakeholder
DELETE /clinics/:clinic_id/clinic_stakeholders/:idRevenue Share Configuration APIs
List Configurations
GET /clinics/:clinic_id/revenue_share_configurationsResponse:
{
"success": true,
"data": {
"revenue_share_configurations": [
{
"id": 1,
"configuration_name": "Standard Revenue Distribution",
"status": "active",
"effective_from": "2025-01-01",
"total_percentage_allocated": "100.0",
"stakeholders": [
{
"id": 1,
"stakeholder_name": "Kulcare Platform",
"stakeholder_type": "platform",
"share_percentage": "5.0"
},
{
"id": 2,
"stakeholder_name": "John Doe",
"stakeholder_type": "owner",
"share_percentage": "60.0"
}
]
}
]
}
}Create Configuration
POST /clinics/:clinic_id/revenue_share_configurations
Content-Type: application/json
{
"configuration_name": "New Revenue Distribution",
"description": "Updated revenue sharing model",
"effective_from": "2025-02-01",
"stakeholders": [
{
"stakeholder_id": 2,
"share_percentage": 60.0
},
{
"stakeholder_id": 3,
"share_percentage": 40.0
}
],
"distribution_rules": {
"distribution_frequency": "monthly",
"auto_approval_threshold": 50000
}
}Activate Configuration
POST /clinics/:clinic_id/revenue_share_configurations/:id/activateCommission Rules APIs
List Rules
GET /clinics/:clinic_id/commission_rules?page=1&per_page=20Query Parameters:
page(optional): Page numberper_page(optional): Items per pagerule_type_id(optional): Filter by rule typeservice_type_id(optional): Filter by service typesearch_text(optional): Search in rule names
Response:
{
"success": true,
"data": {
"commission_rules": [
{
"id": 1,
"rule_name": "Standard Consultation",
"commission_percentage": "30.0",
"effective_from": "2024-01-01",
"active": true,
"basic_commission_rule_type": {
"id": 1,
"name": "percentage",
"display_name": "Percentage Commission"
},
"basic_service_types": [...],
"clinic_doctors": [...]
}
]
},
"total_records": 5,
"total_pages": 1
}Create Rule (Percentage)
POST /clinics/:clinic_id/commission_rules
Content-Type: application/json
{
"basic_commission_rule_type_id": 1,
"rule_name": "Senior Doctor Commission",
"commission_percentage": 80.0,
"applies_to_all_services": false,
"basic_service_type_ids": [1, 2],
"clinic_doctor_ids": [456, 789],
"priority": 1
}Create Rule (Tiered)
POST /clinics/:clinic_id/commission_rules
Content-Type: application/json
{
"basic_commission_rule_type_id": 3,
"rule_name": "Tiered Revenue Commission",
"tiers": [
{
"tier_name": "Bronze",
"min_amount": 0,
"max_amount": 25000,
"commission_percentage": 15.0
},
{
"tier_name": "Silver",
"min_amount": 25001,
"max_amount": 50000,
"commission_percentage": 20.0
},
{
"tier_name": "Gold",
"min_amount": 50001,
"max_amount": null,
"commission_percentage": 25.0
}
],
"clinic_doctor_ids": [123, 456]
}Commission Calculations APIs
List Calculations
GET /clinics/:clinic_id/commission_calculations?start_date=2025-01-01&end_date=2025-01-31Query Parameters:
start_date(required): Start date (YYYY-MM-DD)end_date(required): End date (YYYY-MM-DD)clinic_doctor_id(optional): Filter by doctorstatus(optional): Filter by statuspage(optional): Page numberper_page(optional): Items per page
Calculate Batch
POST /clinics/:clinic_id/commission_calculations/calculate_batch
Content-Type: application/json
{
"start_date": "2025-01-01",
"end_date": "2025-01-31",
"clinic_doctor_ids": [1, 2, 3],
"recalculate": false
}Commission Dashboard APIs
Overview
GET /clinics/:clinic_id/commission_dashboardResponse:
{
"success": true,
"data": {
"summary": {
"total_revenue": 150000.0,
"total_commission": 45000.0,
"appointment_count": 120,
"average_commission_rate": 30.0
},
"period": {
"start": "2025-01-01",
"end": "2025-01-31"
},
"calculations": [...],
"pagination": {...}
}
}Analytics
GET /clinics/:clinic_id/commission_analytics?period=2025-01Settlement APIs
List Settlements
GET /clinics/:clinic_id/settlements?period=2025-01&status=pendingResponse:
{
"success": true,
"data": {
"settlements": [
{
"id": 1,
"settlement_period": "2025-01",
"clinic_doctor_id": 7,
"doctor_name": "Dr. Smith",
"total_earnings": "35000.0",
"net_amount": "35000.0",
"status": "pending",
"calculation_count": 45
}
],
"pending_amount": "100000.0",
"approved_amount": "50000.0"
}
}Generate Monthly Settlements
POST /settlements/generate
Content-Type: application/json
{
"clinic_id": 123,
"period": "2025-01"
}Approve Settlement
POST /settlements/:id/approve
Content-Type: application/json
{
"notes": "Approved after review"
}Process Payment
POST /settlements/:id/process_payment
Content-Type: application/json
{
"payment_method": "bank_transfer",
"notes": "Payment processed via NEFT"
}Commission Workflows APIs
List Workflows
GET /clinics/:clinic_id/commission_workflowsResponse:
{
"success": true,
"data": {
"commission_workflows": [
{
"id": 1,
"commission_type": "COMMISSION_CALCULATION",
"schedule_frequency": "DAILY",
"schedule_time": "06:00:00",
"current_status": "RUNNING",
"enabled": true,
"last_run_at": "2025-01-15T06:00:00Z"
}
]
}
}Update Workflow
PUT /clinics/:clinic_id/commission_workflows/:id
Content-Type: application/json
{
"enabled": true,
"schedule_time": "08:00:00"
}Revenue Distribution Queue APIs
List Queue Entries
GET /clinics/:clinic_id/revenue_distribution_queue?status=pending&page=1Export Queue
GET /clinics/:clinic_id/revenue_distribution_queue/export?format=csvRevenue Share Calculations APIs
List Calculations
GET /clinics/:clinic_id/revenue_share_calculations?period=2025-01Show Calculation Details
GET /clinics/:clinic_id/revenue_share_calculations/:idMeta Data APIs
Get Basic Service Types
GET /basic_service_typesResponse:
{
"success": true,
"data": [
{
"id": 1,
"name": "consultation",
"display_name": "Consultation",
"active": true
}
]
}Get Basic Commission Rule Types
GET /basic_commission_rule_typesBusiness Logic (Interactors)
Commission Calculation Flow
# parts/billing/interactors/commissions/calculate_batch.rb
module Commissions
class CalculateBatch < BaseInteractor
def call
require_context(:clinic_id, :start_date, :end_date)
validate_inputs
create_job_record
process_calculations
generate_summaries
end
private
def process_calculations
appointments.find_each do |appointment|
CommissionCalculationService.calculate_for_appointment(appointment)
end
end
end
endSettlement Generation Flow
# parts/billing/interactors/settlements/generate_monthly.rb
module Settlements
class GenerateMonthly < BaseInteractor
def call
require_context(:clinic_id)
validate_inputs
generate_commission_settlements
generate_revenue_share_calculations
end
private
def generate_commission_settlements
clinic_doctors.each do |clinic_doctor|
settlement = CommissionSettlement.generate_for_period(
clinic_doctor, period_start, period_end
)
context.commission_settlements << settlement if settlement
end
end
end
endRevenue Share Configuration Flow
# parts/clinic/interactors/revenue_share/create_configuration.rb
module RevenueShare
class CreateConfiguration < BaseInteractor
def call
require_context(:clinic_id, :configuration_name, :stakeholders)
validate_clinic
validate_stakeholders
create_configuration
create_stakeholder_assignments
end
end
endBackground Jobs & Automation
Daily Commission Calculation
# lib/tasks/daily_revenue_calculation.rake
namespace :revenue do
desc "Calculate daily commissions for all active clinics"
task calculate_daily_commissions: :environment do
Clinic.active.where(commission_enabled: true).find_each do |clinic|
Commissions::CalculateBatch.call(
clinic_id: clinic.id,
start_date: Date.yesterday,
end_date: Date.yesterday,
current_user: system_user
)
end
end
end
# Scheduled via cron: Daily at 6 AMMonthly Settlement Generation
# lib/tasks/settlements_generate_monthly.rake
namespace :settlements do
desc "Generate monthly settlements for all clinics"
task generate_monthly: :environment do
period = ENV['PERIOD'] || 1.month.ago.strftime('%Y-%m')
Clinic.active.find_each do |clinic|
Settlements::GenerateMonthly.call(
clinic_id: clinic.id,
period: period,
current_user: system_user
)
end
end
end
# Scheduled via cron: Monthly on 1st at 12:01 AMCommission Workflow Scheduler
# lib/tasks/schedule_commission_workflows.rake
namespace :commission_workflows do
desc "Process scheduled commission workflows"
task process: :environment do
CommissionWorkflow.enabled.find_each do |workflow|
next unless workflow.should_run_today?
CommissionWorkflows::Execute.call(
workflow_id: workflow.id,
current_user: system_user
)
end
end
end
# Scheduled via cron: Every hourTesting
RSpec Examples
# spec/models/clinic_commission_rule_spec.rb
RSpec.describe ClinicCommissionRule, type: :model do
describe '#calculate_commission' do
context 'percentage type' do
let(:rule) { create(:commission_rule, :percentage, commission_percentage: 30) }
it 'calculates 30% commission' do
expect(rule.calculate_commission(1000)).to eq(300.0)
end
end
context 'tiered type' do
let(:rule) { create(:commission_rule, :tiered) }
before do
create(:commission_tier, rule: rule, min: 0, max: 10000, percentage: 10)
create(:commission_tier, rule: rule, min: 10001, max: nil, percentage: 15)
end
it 'applies correct tier' do
expect(rule.calculate_commission(15000)).to eq(2250.0)
end
end
end
end
# spec/interactors/settlements/generate_monthly_spec.rb
RSpec.describe Settlements::GenerateMonthly do
let(:clinic) { create(:clinic) }
let(:doctor) { create(:clinic_doctor, clinic: clinic) }
it 'generates settlement for doctor with calculations' do
create_list(:commission_calculation, 5, clinic_doctor: doctor)
result = described_class.call(
clinic_id: clinic.id,
period: '2025-01',
current_user: create(:user)
)
expect(result).to be_success
expect(doctor.commission_settlements.count).to eq(1)
end
endDeployment & Configuration
Environment Variables
# Required
DATABASE_URL=postgresql://...
REDIS_URL=redis://...
# Optional
COMMISSION_CALCULATION_ENABLED=true
SETTLEMENT_GENERATION_ENABLED=true
COMMISSION_WORKFLOW_ENABLED=trueDatabase Seeds
# Seed basic reference data
bundle exec rails db:seed
# This seeds:
# - basic_commission_rule_types (percentage, fixed, tiered)
# - basic_service_types (consultation, procedure, etc.)Rake Tasks
# One-time setup
bundle exec rake db:migrate
bundle exec rake db:seed
# Daily operations
bundle exec rake revenue:calculate_daily_commissions
bundle exec rake commission_workflows:process
# Monthly operations
bundle exec rake settlements:generate_monthly PERIOD=2025-01
# Monitoring
bundle exec rake commission_workflows:statusCron Schedule
# config/schedule.rb (whenever gem)
# Daily commission calculation - 6 AM
every 1.day, at: '6:00 am' do
rake "revenue:calculate_daily_commissions"
end
# Hourly workflow processing
every 1.hour do
rake "commission_workflows:process"
end
# Monthly settlement generation - 1st of month at 12:01 AM
every '0 1 1 * *' do
rake "settlements:generate_monthly"
endAPI Error Handling
All APIs return consistent error responses:
{
"success": false,
"error": {
"message": "Error description",
"details": {
"field": ["validation error"]
}
}
}HTTP Status Codes:
200: Success201: Created400: Bad Request401: Unauthorized403: Forbidden404: Not Found422: Validation Error500: Server Error
Performance Considerations
- Batch Processing: Use
find_eachfor large datasets - Database Indexing: All foreign keys and query fields indexed
- Caching: Redis caching for analytics dashboards
- Background Jobs: Sidekiq for async processing
- Query Optimization: Use
includesto avoid N+1 queries
Security & Authorization
- Pundit Policies: All controllers protected by Pundit authorization
- Role-Based Access: Clinic owners, admins, finance managers
- Audit Logging: All financial operations logged in
system_logs - Data Encryption: Sensitive financial data encrypted at rest
Pending Features & Future Enhancements
This section documents features that were planned in the original PRD and implementation documents but are not yet fully implemented. These are organized by priority and complexity.
High Priority - Pending Implementation
1. Revenue Share Calculation Automation
Status: 🔄 Partially Implemented
What exists:
- Database schema (revenue_share_calculations table)
- Model associations
- Basic controller endpoints
- Background jobs already exist:
CommissionCalculationJob(parts/clinic/services/commission_calculation_job.rb)CalculateCommissionJob(parts/clinic/services/calculate_commission_job.rb)CommissionWorkflowExecutionJob(parts/billing/services/commission_workflow_execution_job.rb)RunCommissionWorkflowsJob(parts/billing/services/run_commission_workflows_job.rb)
What's missing:
- Revenue share calculation interactor with full business logic
- Integration between existing jobs and revenue share calculations
- Distribution breakdown by stakeholder
- Platform fee calculation logic
Implementation needed:
# Create: RevenueSharing::CalculateDistribution interactor
# Update: Existing jobs (CommissionWorkflowExecutionJob) to handle revenue share calculations
# Logic: Calculate monthly revenue, apply active config, distribute by percentagesAPIs to implement:
POST /clinics/:clinic_id/revenue_share_calculations/calculate
GET /clinics/:clinic_id/revenue_share_calculations/dashboard (needs full implementation)2. Revenue Share Payout Processing
Status: ❌ Not Implemented
What exists:
- Revenue distribution queue table
- Basic tracking structure
What's missing:
- Payout workflow (approve, process, mark paid)
- Integration with payment gateways
- Payout status tracking
- Payout history and audit trail
- Multi-stakeholder batch payouts
Implementation needed:
# Model: RevenueSharePayout (new)
# Interactor: RevenueSharing::ProcessPayout (new)
# Controller: RevenueSharePayoutsController (enhance existing)APIs to implement:
POST /clinics/:clinic_id/revenue_share_distributions/:id/approve
POST /clinics/:clinic_id/revenue_share_distributions/:id/process_payment
GET /clinics/:clinic_id/revenue_share_distributions/:id/history3. Commission Settlement Workflow Completion
Status: 🔄 Partially Implemented
What exists:
- CommissionSettlement model
- Basic settlement generation method
- Database schema
- Background jobs already exist:
CommissionCalculationJob(parts/clinic/services/commission_calculation_job.rb)CalculateCommissionJob(parts/clinic/services/calculate_commission_job.rb)CommissionWorkflowExecutionJob(parts/billing/services/commission_workflow_execution_job.rb)RunCommissionWorkflowsJob(parts/billing/services/run_commission_workflows_job.rb)
What's missing:
- Integration of existing jobs with settlement generation
- Settlement approval workflow UI integration
- Settlement payment processing integration
- Settlement export functionality
- Settlement reconciliation tools
Implementation needed:
# Create: Commissions::GenerateMonthlySettlements interactor
# Update: Existing jobs (CommissionWorkflowExecutionJob) to trigger settlement generation
# Create: CommissionSettlementsController (full CRUD)APIs to implement:
GET /clinics/:clinic_id/commission_settlements
GET /clinics/:clinic_id/commission_settlements/:id
POST /clinics/:clinic_id/commission_settlements/generate
POST /clinics/:clinic_id/commission_settlements/:id/approve
POST /clinics/:clinic_id/commission_settlements/:id/process_payment
DELETE /clinics/:clinic_id/commission_settlements/:id/cancel
POST /clinics/:clinic_id/commission_settlements/export4. Commission Workflow - Settlement Generation Type
Status: 🔄 Partially Implemented
What exists:
- CommissionWorkflow model supports SETTLEMENT_GENERATION type
- Workflow scheduler framework
What's missing:
- Actual settlement generation workflow processor
- Monthly settlement job integration
- Workflow logs for settlement generation
- Error handling and retry logic
Implementation needed:
# Update: CommissionWorkflowProcessorJob
# Add: Handle SETTLEMENT_GENERATION workflow type
# Logic: Generate settlements for all doctors on scheduleMedium Priority - Future Enhancements
5. Performance-Based Bonuses
Status: ❌ Not Implemented
Planned features:
- Performance metrics tracking (patient_satisfaction, revenue_target, appointment_count, conversion_rate)
- Performance bonus rules configuration
- Automated bonus calculations based on achievement percentages
- Bonus approval workflow
- Performance dashboards
Database schema needed:
# Tables to create:
# - performance_metrics
# - performance_bonus_rules
# - performance_bonus_calculationsModels to create:
# - PerformanceMetric
# - PerformanceBonusRule
# - PerformanceBonusCalculation6. Advanced Payment Methods
Status: ❌ Not Implemented
Planned features:
- UPI payment integration
- Digital wallet support (Paytm, PhonePe, Google Pay)
- International payment methods
- Multi-currency support
- Payment method preferences per stakeholder
Implementation needed:
# Service: PaymentGatewayService
# Models: PaymentMethod, PaymentTransaction
# Integration with Razorpay/Stripe for multiple methods7. Bulk Operations
Status: ❌ Not Implemented
Planned features:
- Bulk commission approval (exists in frontend, needs backend completion)
- Bulk settlement generation
- Bulk payment processing
- Bulk calculation recalculation
- Batch export operations
APIs to implement:
POST /clinics/:clinic_id/commission_calculations/bulk_approve
POST /clinics/:clinic_id/commission_settlements/bulk_generate
POST /clinics/:clinic_id/commission_settlements/bulk_process
POST /clinics/:clinic_id/commission_calculations/bulk_recalculate8. Advanced Analytics & Reporting
Status: 🔄 Partially Implemented
What exists:
- Basic commission dashboard analytics
- Revenue analysis reports
- Period comparison reports
- Location comparison reports
- Consolidated reports
What's missing:
- Revenue share analytics dashboard
- Stakeholder performance comparison
- Forecast and projections
- Trend analysis over multiple periods
- Custom report builder
- Scheduled report generation
- Report subscriptions (email reports)
Implementation needed:
# Controllers:
# - RevenueShareAnalyticsController
# - AdvancedReportsController
#
# Features:
# - Predictive analytics for revenue trends
# - Commission forecast based on historical data
# - Stakeholder ROI calculations
# - Comparative performance across clinics9. Audit Trail & Compliance Tools
Status: 🔄 Partially Implemented
What exists:
- System logs association on CommissionCalculation
- System logs association on CommissionSettlement
- Basic audit trail tracking
What's missing:
- Complete audit trail UI
- Detailed change tracking (before/after values)
- Audit report generation
- Compliance reports (tax, regulatory)
- Audit log export
- Audit log search and filtering
- User action history
APIs to implement:
GET /clinics/:clinic_id/audit_trail
GET /clinics/:clinic_id/audit_trail/commissions
GET /clinics/:clinic_id/audit_trail/settlements
GET /clinics/:clinic_id/audit_trail/revenue_shares
POST /clinics/:clinic_id/audit_trail/export
GET /users/:user_id/activity_log10. Hierarchical Revenue Distribution
Status: ❌ Not Implemented
Planned features:
- Multi-level stakeholder hierarchy
- Parent-child revenue distribution
- Cascading percentage calculations
- Hierarchical approval workflows
What exists:
parent_stakeholder_idcolumn inclinic_revenue_stakeholderstable
What's missing:
- Business logic for hierarchical calculations
- Recursive distribution algorithms
- Hierarchy visualization
- Multi-level approval workflows
Low Priority - Nice to Have
11. GraphQL API Support
Status: ❌ Not Implemented
Planned features:
- GraphQL schema for commissions and revenue sharing
- Real-time subscriptions for calculation updates
- Flexible querying capabilities
- Mobile app optimized endpoints
12. Webhook System
Status: ❌ Not Implemented
Planned features:
- Webhooks for commission calculations
- Webhooks for settlement approvals
- Webhooks for payment processing
- Webhook configuration UI
- Webhook delivery status tracking
- Webhook retry mechanism
13. Commission Forecasting
Status: ❌ Not Implemented
Planned features:
- Predict future commissions based on historical data
- Revenue forecasting for stakeholders
- Budget vs actual comparisons
- What-if scenario analysis
- Commission rule impact analysis
14. Multi-Currency & International Support
Status: ❌ Not Implemented
Planned features:
- Multi-currency commission rules
- Exchange rate management
- International payment methods
- Tax compliance for multiple jurisdictions
- Region-specific regulatory compliance
15. Mobile App Optimizations
Status: ❌ Not Implemented
Planned features:
- Lightweight mobile-optimized API endpoints
- Push notifications for commission updates
- Offline data sync capabilities
- Mobile-specific analytics
- QR code payment integration
Implementation Roadmap
Phase 1 (Q1 2025) - High Priority
- Complete revenue share calculation automation
- Implement revenue share payout processing
- Complete commission settlement workflow
- Add settlement generation workflow type
Phase 2 (Q2 2025) - Medium Priority
- Performance-based bonuses
- Advanced analytics dashboards
- Bulk operations
- Complete audit trail system
Phase 3 (Q3 2025) - Future Enhancements
- Advanced payment methods
- Hierarchical revenue distribution
- Commission forecasting
- Webhook system