Skip to content

Data Flows

This section details the critical paths data takes through the BSS stack.

1. CRM Subscriber Provisioning (gRPC)

When a telco administrator creates a new subscriber in the crm2 dashboard, the following sequence occurs:

sequenceDiagram
    participant Admin as Operator (Web UI)
    participant CRM2 as crm2.micro.bss (PHP)
    participant gRPC as CRMServer (C++)
    participant DB as DB_layer (C++)
    participant MySQL as MySQL Database

    Admin->>CRM2: POST /subscriber/new (Form Data)
    CRM2->>CRM2: Validate form & create JWT
    CRM2->>gRPC: AddSubscriber(Subscriber proto) + JWT

    gRPC->>gRPC: auth_interceptor validates JWT
    gRPC->>DB: DB_layer::insert(billing::Subscriber)
    DB->>MySQL: INSERT INTO subscribers ...
    MySQL-->>DB: Success (ID)
    DB-->>gRPC: Return 0

    gRPC-->>CRM2: CRMResponse(status: ACK_OK)
    CRM2-->>Admin: HTTP 200 (Success Toast)

Security Notice

All gRPC calls from the CRM to the C++ Server must be signed with a JWT indicating an authorized admin user. The auth_interceptor.hpp validates the token before CRMServiceImpl executes any logic.


2. Real-Time Prepaid Charging (DIAMETER)

This scenario occurs when a prepaid subscriber initiates a mobile data session or a voice call.

sequenceDiagram
    participant NE as Network Element (GGSN)
    participant DIA as PrepaidServer (DIAMETER)
    participant Charge as BalanceReserve / Charge
    participant DB as DB_layer

    %% INITIAL PHASE
    NE->>DIA: CCR (INITIAL)
    DIA->>Charge: fromCCR(ccr)
    Charge->>DB: has_balance()
    DB-->>Charge: true
    Charge->>DB: reserve_balance(amount)
    DIA-->>NE: CCA (GRANTED_UNITS)

    %% UPDATE PHASE
    loop While Session Active
        NE->>DIA: CCR (UPDATE)
        DIA->>Charge: Update usage / Request more
        Charge->>DB: deduct_used() & reserve_new()
        DIA-->>NE: CCA (GRANTED_UNITS)
    end

    %% TERMINATION PHASE
    NE->>DIA: CCR (TERMINATE)
    DIA->>Charge: Calculate final_price
    Charge->>DB: debit_balance(final_price)
    Charge->>DB: db_insert(Charge proto)
    DIA-->>NE: CCA (2001 SUCCESS)

Balance Preconditions

Before authorizing any granted units, the system must invoke Subscriber::has_balance() and successfully execute DB_layer::reserve_balance. If this fails, a DIAMETER_CREDIT_LIMIT_REACHED (4012) CCA is returned, immediately terminating the network session.


3. Offline Postpaid Billing (CDR Loader)

For postpaid accounts, or flat-file scenarios, the server asynchronously polls a directory.

sequenceDiagram
    participant Cron as ACE Reactor Timer
    participant Loader as CDRLoader
    participant Rater as Rater
    participant DB as DB_layer

    Cron->>Loader: handle_timeout()
    Loader->>Loader: Scan /new_cdr directory
    loop For each CDR file via std::filesystem
        Loader->>Loader: Read and deserialize() CDR
        Loader->>Loader: validate() CDR
        Loader->>Rater: pre_rate()
        Rater->>DB: Get Price Plan & Rates
        Loader->>Rater: rate(CDR)
        Loader->>Rater: post_rate()

        Loader->>DB: DB_layer::insert(CDR)
        Loader->>Loader: rename() file to /processed_cdr (or /error_cdr on failure)
    end

4. Asynchronous Invoice Generation

When a bill run creates NEW bills, an asynchronous background task orchestrates PDF conversion without blocking the main event loops.

sequenceDiagram
    participant Timer as ACE Reactor Timer
    participant Handler as BillFormatterHandler
    participant Inja as Inja Template Engine
    participant Pluto as Plutobook (litehtml)
    participant FS as File System

    Timer->>Handler: handle_timeout()
    Handler->>Handler: Scan DB for NEW bills
    loop For each NEW bill
        Handler->>Inja: inject pre-formatted context (month, year, amounts)
        Inja->>Handler: render HTML string
        Handler->>Pluto: load_html() & apply print CSS
        Pluto->>Handler: render_pdf()
        Handler->>FS: write to ./invoices/{year}/{month}/{type}/...
    end