Skip to content

System Components Overview

Complete documentation of all automation components in the Expensis billing platform.


Component Summary

Component Type Count Description
Console Commands 115 CLI commands for management and automation
MessageBus Commands 40 Asynchronous command objects (39 concrete + 1 abstract)
MessageBus Handlers 36 Command handlers that execute business logic
Dispatch Points 45 Locations where commands are dispatched to MessageBus
Event Listeners 10 Components that listen to system events
Cron Jobs 18 Scheduled automated tasks

Total Components: 260+


Quick Navigation


Architecture Layers

graph TB
    subgraph "Entry Layer"
        CRON[Cron Jobs<br/>18 scheduled tasks]
        WEB[Web Controllers<br/>8 dispatch points]
        API[API Services<br/>5 dispatch points]
        CLI[Console Commands<br/>115 commands]
    end

    subgraph "MessageBus Layer"
        COMMANDS[MessageBus Commands<br/>40 command classes]
        HANDLERS[MessageBus Handlers<br/>36 handler classes]
    end

    subgraph "Event Layer"
        EVENTS[Event System<br/>10 listeners]
        CONSUMED[MessageConsumedHandler<br/>Chain execution]
    end

    subgraph "Data Layer"
        DB[Database<br/>Operations]
        EXTERNAL[External APIs<br/>Provider portals]
    end

    CRON --> COMMANDS
    WEB --> COMMANDS
    API --> COMMANDS
    CLI --> COMMANDS

    COMMANDS --> HANDLERS
    HANDLERS --> EVENTS
    CONSUMED --> COMMANDS

    HANDLERS --> DB
    HANDLERS --> EXTERNAL

    style CONSUMED fill:#ff6b6b
    style HANDLERS fill:#4ecdc4
    style COMMANDS fill:#95e1d3

Critical Components

Single Points of Failure

If these components fail, the entire automation system stops:

1. MessageConsumedHandler

Location: src/MessageBus/MessageConsumedHandler.php

Purpose: Enables ALL command chaining - executes sequential commands after a command completes

Impact: Without this, command chains break and workflows incomplete

Usage: Every workflow with chains (99% of workflows)

2. SyncProfileHandler

Location: src/MessageBus/AsynchronousHandler/SyncProfileHandler.php:153

Purpose: Master router that dispatches to provider-specific sync handlers

Impact: All automated provider syncs stop

Routes to: - KpnSp16SyncCommand - VodafoneSyncCommand - TMobileCalviSyncCommand - KpnEenSyncCommand - YielderSyncCommand

3. sync:manager Console Command

Location: src/Command/SyncManagementCommand.php

Purpose: Master cron orchestrator that runs every 5 minutes

Schedule: */5 * * * *

Impact: No automated syncs execute


Component Categories

Sync & Import Commands

Commands that interact with external provider APIs:

  • KPN SP16 Sync (4 commands)
  • Vodafone Sync (2 commands)
  • T-Mobile Calvi Sync (2 commands)
  • KPN EEN Sync (2 commands)
  • Yielder/Odido Sync (3 commands)
  • Routit Mobile Sync (5 commands)

Calculation Commands

Commands that calculate billing totals:

  • CalculateTotalsCommand
  • CalculateTotalsRateplanCommand
  • CalculateTotalsDataProductSP16Command
  • DispatchTotalsCommand (router)
  • DispatchTotalsBackupCommand

Data Management Commands

Commands for data operations:

  • Import commands (CDR, subscriptions, devices)
  • Export commands (reports, backups)
  • Cleanup commands (old data, temp files)

Administrative Commands

Commands for system management:

  • Queue processing
  • Status updates
  • Manual interventions
  • Verification tests

Component Relationships

Command → Handler Mapping

Every MessageBus command has exactly one handler:

// Example: Command class
class CalculateTotalsCommand implements ChainableCommandInterface {
    private int $customerId;
    private \DateTime $cycleStartDate;
    // ... constructor and getters
}

// Handler class
#[AsMessageHandler]
class CalculateTotalsHandler {
    public function __invoke(CalculateTotalsCommand $command) {
        // Business logic here
    }
}

Dispatch Pattern

Commands are dispatched from multiple entry points:

// From controller
$this->commandBus->dispatch(new CalculateTotalsCommand($id, $date));

// From console command
$this->commandBus->dispatch($command);

// From another handler
$this->messageBus->dispatch(new NextCommand());

// From event listener (chaining)
$this->commandBus->dispatch($chainedCommand);

Usage Statistics

Most Frequently Used Commands

Command Dispatched From Frequency
DispatchTotalsCommand 15 locations After every sync
CalculateTotalsCommand 8 locations Multiple times/day
SyncProfileCommand 2 locations Every 5 minutes
SaveStatusCommand 12 locations After workflows

Most Complex Handlers

Handler Lines of Code External Calls Database Tables
KpnSp16SyncHandler ~300 3 APIs 8 tables
RoutitImportCdrsHandler ~250 File system 5 tables
CalculateTotalsHandler ~200 None 6 tables
VodafoneSyncHandler ~180 2 APIs 7 tables

Finding Components

By Functionality

Need to sync a provider?Provider Workflows

Need to calculate totals?Totals Workflow

Need to import CDRs?CDR Processing

Need to trigger manually?User Workflows

By Location

Console commands: /src/Command/ (115 files)

MessageBus commands: /src/MessageBus/Command/ (40 files)

Handlers: /src/MessageBus/AsynchronousHandler/ (36 files)

Events: /src/MessageBus/ (MessageConsumedHandler.php)