Skip to content

BSS-Odoo Billing Synchronization Workflow

Workflow Diagram

BSS-Odoo Billing Synchronization Workflow

Complete sequence diagram showing the three billing synchronization phases: Phase 1 (Product Synchronization from ABS to Odoo), Phase 2 (Subscription Lifecycle from Odoo to ABS), and Phase 3 (Payment Synchronization), including payment overdue and usage-based billing scenarios.

Overview

This workflow defines the billing synchronization pattern between ABS ServicePlan lifecycle and Odoo subscription billing operations. Following DIRAC Framework principles, ABS handles service delivery while Odoo manages all billing and customer sales interactions.

Core Principles

Federation-Based Integration

  • ABS: Service definition, execution, FSM state management
  • Odoo: Billing operations, pricing, customer sales, subscription management
  • FED Layer: Mediates data translation and synchronization (via MQTT)
  • No Schema Pollution: Odoo integration data confined to BSS agent_state

Billing Responsibility Separation

  • ABS Does NOT: Generate invoices, process payments, manage customer billing
  • ABS DOES: Sync payment-cycle FSM states with Odoo billing signals
  • Odoo Leads: All billing decisions, payment processing, subscription lifecycle
  • ABS Follows: Updates internal FSM states based on Odoo billing events

Workflow Phases

Phase 1: Product Synchronization (ABS → Odoo)

ABS ServicePlanTemplate → Odoo Product Template

ABS Event: ServicePlanTemplate Created
  ↓ MQTT: emit/abs/product_template/{template_id}/created
    ↓ FED Layer Translation
      ↓ Odoo: Create Product Template
        ↓ Store: template_id as product.default_code

Key Mappings: - template_idproduct.default_code (linking mechanism) - nameproduct.name - billing_currencyproduct.currency_id - CommonTerms.monthly_feeproduct.list_price

Phase 2: Subscription Lifecycle (Odoo → ABS)

Customer Signs Up in Odoo

Odoo Event: Customer creates subscription
  ↓ MQTT: emit/odoo/subscription/{subscription_id}/created
    ↓ ABS MQTT Listener
      ↓ BSS Agent: createServicePlanFromOdoo()
        ↓ ServicePlan created with odoo_subscription_id link

ServicePlan Creation Pattern:

// BSS Agent receives Odoo subscription creation
const servicePlan = {
  customer_id: payload.partner_id,
  template_id: payload.template_id, // ABS template reference
  plan_state: {
    status: 'ACTIVE',
    agent_state: {
      // Odoo integration data (domain isolation)
      odoo_subscription_id: payload.subscription_id,
      odoo_subscription_state: payload.state,
      odoo_last_sync_at: timestamp
    }
  },
  service_state: 'WAIT_BATTERY_ISSUE', // ABS FSM state
  payment_state: 'CURRENT' // Derived from Odoo
};

Phase 3: Payment Synchronization (Odoo → ABS)

Odoo Billing Events → ABS FSM Updates

Odoo Event: Invoice created/Payment processed
  ↓ MQTT: emit/odoo/subscription/{subscription_id}/payment_updated
    ↓ ABS MQTT Listener
      ↓ BSS Agent: syncOdooSubscription()
        ↓ Update payment_state FSM
          ↓ Emit FSM signals if needed

BSS Agent Integration Points

serviceAgent.syncOdooSubscription()

Purpose: Synchronize ABS payment-cycle FSM with Odoo billing events

Input Pattern:

{
  action: 'SYNC_ODOO_SUBSCRIPTION',
  odoo_payload: {
    subscription_id: 12345,
    payment_state: 'paid', // Odoo payment status
    subscription_state: 'in_progress', // Odoo subscription status
    invoice_id: 'INV-001',
    payment_date: '2025-01-15T14:30:00Z'
  }
}

Agent Logic Flow:

1. Validate odoo_subscription_id matches agent_state
2. Map Odoo payment_state to ABS payment FSM
3. Update agent_state with Odoo sync data
4. Generate FSM inputs if state transition needed
5. Return signals for orchestrator

State Mapping Table: | Odoo Payment State | ABS Payment FSM | FSM Input Generated | |-------------------|-----------------|-------------------| | not_paid | RENEWAL_DUE | SUBSCRIPTION_EXPIRED | | paid | CURRENT | RENEWAL_PAID | | partial | RENEWAL_DUE | (no change) | | overdue | RENEWAL_DUE | QUOTA_EXHAUSTED |

serviceAgent.checkOdooPaymentStatus()

Purpose: Query current payment status for service availability decisions

Validator Array Pattern:

const paymentValidators = [
  {
    check: () => agent_state.odoo_payment_state === 'paid',
    signal: 'PAYMENT_CURRENT'
  },
  {
    check: () => agent_state.odoo_subscription_state === 'to_renew',
    signal: 'RENEWAL_REQUIRED'
  },
  {
    check: () => !agent_state.odoo_subscription_id,
    signal: 'ODOO_SYNC_ERROR'
  }
];

serviceAgent.reportServiceUsageToOdoo()

Purpose: Report ABS service milestones to trigger Odoo billing

Usage Events: - Battery swap completion → Trigger usage-based billing - Service quota exhaustion → Request quota top-up billing - Service termination → Final settlement billing

MQTT Pattern:

ABS Event: Battery swap completed
  ↓ BSS Agent: reportServiceUsageToOdoo()
    ↓ MQTT: emit/abs/service_usage/{plan_id}/battery_swap_completed
      ↓ Odoo: Create milestone invoice
        ↓ MQTT: emit/odoo/subscription/{subscription_id}/invoice_created
          ↓ ABS: Sync billing status

MQTT Topic Patterns

ABS → Odoo (Service Events)

  • emit/abs/product_template/{template_id}/created
  • emit/abs/service_usage/{plan_id}/battery_swap_completed
  • emit/abs/service_usage/{plan_id}/service_terminated

Odoo → ABS (Billing Events)

  • emit/odoo/subscription/{subscription_id}/created
  • emit/odoo/subscription/{subscription_id}/payment_updated
  • emit/odoo/subscription/{subscription_id}/state_changed
  • emit/odoo/subscription/{subscription_id}/invoice_created

Data Flow Examples

Example 1: Monthly Renewal

Day 1: Odoo creates monthly invoice
  ↓ emit/odoo/subscription/123/invoice_created
    ↓ ABS: No action (invoice creation doesn't affect service)

Day 30: Customer pays invoice
  ↓ emit/odoo/subscription/123/payment_updated
    ↓ ABS: syncOdooSubscription() 
      ↓ payment_state: CURRENT
        ↓ Service remains available

Day 35: Payment overdue
  ↓ emit/odoo/subscription/123/payment_updated (overdue)
    ↓ ABS: syncOdooSubscription()
      ↓ payment_state: RENEWAL_DUE
        ↓ FSM: SUBSCRIPTION_EXPIRED
          ↓ Service access blocked until payment

Example 2: Usage-Based Billing

Customer: Completes battery swap
  ↓ ABS: Service milestone completed
    ↓ emit/abs/service_usage/plan-123/battery_swap_completed
      ↓ Odoo: Creates usage invoice
        ↓ emit/odoo/subscription/123/invoice_created
          ↓ ABS: Logs billing event (no state change)

Later: Customer pays usage invoice
  ↓ emit/odoo/subscription/123/payment_updated
    ↓ ABS: Confirms payment received (service continues)

Implementation Guidelines

Agent State Structure

interface BSSAgentState {
  // Core agent state
  agent_version: string;
  swaps_today: number;
  execution_count: number;

  // Odoo integration (domain isolation)
  odoo_subscription_id: number | null;
  odoo_payment_state: string | null;
  odoo_subscription_state: string | null;
  odoo_last_sync_at: string | null;
  odoo_payment_method: string | null;
  odoo_currency_id: string | null;
}

Error Handling Pattern

const syncValidators = [
  {
    check: () => !request.odoo_payload?.subscription_id,
    signal: 'ODOO_SYNC_ERROR',
    metadata: { reason: 'Missing subscription_id' }
  },
  {
    check: () => agent_state.odoo_subscription_id !== request.odoo_payload.subscription_id,
    signal: 'ODOO_SYNC_ERROR', 
    metadata: { reason: 'Subscription ID mismatch' }
  }
];

Integration Testing Points

  1. Product sync: ServicePlanTemplate → Odoo Product creation
  2. Subscription creation: Odoo subscription → ABS ServicePlan
  3. Payment updates: Odoo payment events → ABS FSM transitions
  4. Service milestones: ABS events → Odoo usage billing
  5. Error scenarios: Network failures, mismatched IDs, invalid states

Benefits

Clean Separation

  • ABS: Focuses on service delivery and FSM management
  • Odoo: Handles all customer-facing billing complexity
  • No billing logic in ABS - pure service orchestration

Federation Compliance

  • Zero Odoo customization required
  • Minimal ABS changes - only agent_state fields
  • FED layer mediation via MQTT messaging

Scalability

  • Event-driven architecture supports async processing
  • Domain isolation prevents billing concerns from polluting service logic
  • Standard patterns applicable to other DIRAC services (FCS, EMS)

This workflow ensures ABS remains focused on service delivery while leveraging Odoo's robust billing capabilities through clean, federated integration patterns.