Module Architecture
flowchart TD
SUBSMOD["sadeem_subscription\nSubscription Base"]
CFG["sadeem.waha.config\nWAHA server config\nAPI URL · API key · engine · webhooks"]
LINE["sadeem.waha.config.line\nsubscription WhatsApp line\nsession name · status · phone"]
SUB["sadeem.subscription (inherit)\nlinks to WAHA config lines\nadd WhatsApp access"]
SUBSMOD --> SUB
CFG --> LINE
LINE --> SUB
CFG --> A1([action_test_connection\nGET /health on WAHA server])
CFG --> A2([action_view_lines\nopen subscription lines for this config])
LINE --> A3([action_provision\ncreate WAHA session on slave instance])
LINE --> A4([action_refresh_status\nsync session status from slave])
LINE --> A5([action_stop_session\nstop WhatsApp session on slave])
LINE --> A6([action_disable\nmark line as disabled])
LINE --> A7([action_activate\nmark line as active])
LINE --> A8([_compute_session_name\nderive session name from subscription domain])
LINE --> A9([_get_slave_url\nresolve slave base URL from subscription domain])
LINE --> A10([_build_webhook_url\nconstruct WAHA webhook URL pointing to slave])
SLAVE[/Slave Odoo Instance\nWAHA module installed on slave/]
WAHA[/WAHA API Server\nWhatsApp session management/]
A3 --> SLAVE
A4 --> SLAVE
A5 --> SLAVE
SLAVE --> WAHA
Module Description
SAAS Subscription WhatsApp (WAHA) integrates the WAHA (WhatsApp HTTP API) service into
the Sadeem SAAS platform.
| Area |
What it does |
| WAHA Configurations |
Store WAHA server credentials (URL, API key, engine type, webhook events) — admin-only, never exposed to clients |
| Subscription Lines |
Link subscriptions to WAHA configs with start/end dates and session lifecycle tracking |
| Session Provisioning |
Provision a WhatsApp session on the slave Odoo instance, which then talks to the WAHA server |
| QR Code Authentication |
Session status tracks when a QR code scan is needed for WhatsApp authentication |
| Status Sync |
Refresh session status (stopped / starting / scan_qr_code / working / failed) from slave |
| Overlap Prevention |
Only one active or draft WAHA line allowed per subscription at a time |
Dependencies
SAAS Management
└─ Infrastructure
└─ WhatsApp (WAHA)
├─ WAHA Configurations
└─ Subscription Lines
Session Lifecycle
Draft → Active (provision session on slave)
↓
scan_qr_code (customer scans QR)
↓
working (connected)
↓
Expired / Disabled
| Status |
Description |
| draft |
Line created but session not yet provisioned |
| active |
Session provisioned and running on slave |
| expired |
End date passed |
| disabled |
Manually disabled by admin |
| Session Status |
Description |
| stopped |
Session exists but not running |
| starting |
Session initializing |
| scan_qr_code |
Waiting for customer to scan QR |
| working |
Connected and operational |
| failed |
Session encountered an error |
| unknown |
Status not yet synced |
Architecture Notes
- The master (this module) stores WAHA server credentials and calls the slave instance's provisioning endpoint — it never calls the WAHA API directly.
- The slave's
sadeem_waha_whatsapp_saas module handles the actual WAHA communication.
- Session names are derived from the subscription domain (dots replaced with underscores): e.g.
client.sadeem.cloud → client_sadeem_cloud.
- One WAHA config can be marked as default per company for automatic assignment.
Key Fields
WAHA Configuration (sadeem.waha.config)
| Field |
Type |
Description |
| waha_server_url |
Char |
Base URL of the WAHA API server (required) |
| api_key |
Char |
API key for authenticating with WAHA |
| engine |
Selection |
WAHA engine type (e.g., WEBJS, NOWEB) |
| webhook_events |
Char |
Comma-separated list of WAHA webhook events to subscribe to |
| is_default |
Boolean |
Whether this is the default WAHA config per company |
| line_ids |
One2many |
Subscription lines using this WAHA config |
WAHA Config Line (sadeem.waha.config.line)
| Field |
Type |
Description |
| waha_config_id |
Many2one |
The WAHA configuration this line belongs to |
| subscription_id |
Many2one |
The subscription this WhatsApp line is for |
| start_date / end_date |
Date |
Active period for this WhatsApp session |
| status |
Selection |
Line status: draft, active, expired, disabled |
| session_name |
Char |
Computed WhatsApp session name (derived from subscription domain) |
| session_status |
Selection |
Live WAHA session status: stopped, starting, scan_qr_code, working, failed, unknown |
| phone_number |
Char |
WhatsApp phone number for the session |
| profile_name |
Char |
WhatsApp profile name (read-only, synced from WAHA) |
| notes |
Text |
Internal notes |
Subscription — WAHA additions (sadeem.subscription inherit)
| Field |
Type |
Description |
| waha_line_id |
Many2one |
Currently active WAHA line |
| waha_enabled |
Boolean |
Whether WhatsApp is enabled for this subscription |
| waha_session_status |
Selection |
Related field showing current session status |
| waha_phone_number |
Char |
Related field showing the WhatsApp phone number |
Key Actions
| Action |
Model |
Description |
action_test_connection |
sadeem.waha.config |
GETs /health on the WAHA server to verify connectivity |
action_view_lines |
sadeem.waha.config |
Opens all subscription lines for this WAHA config |
action_provision |
sadeem.waha.config.line |
Installs sadeem_waha_whatsapp_saas on the slave if needed, then calls the slave's provisioning endpoint to create the WAHA session |
action_refresh_status |
sadeem.waha.config.line |
Syncs current session status from the slave instance |
action_stop_session |
sadeem.waha.config.line |
Stops the WhatsApp session on the slave |
action_disable |
sadeem.waha.config.line |
Sets line status to disabled |
action_activate |
sadeem.waha.config.line |
Sets line status to active |
Warnings & Important Notes
- One default per company:
@api.constrains raises UserError if more than one WAHA config is marked as is_default per company.
- Overlap prevention:
@api.constrains raises UserError if a subscription already has an active or draft WAHA line when adding a new one (one active line per subscription at a time).
- Subscription domain required:
action_provision raises UserError if the linked subscription has no domain set (session name cannot be computed).
- Session name format: Dots in the domain are replaced with underscores, e.g.,
client.sadeem.cloud → client_sadeem_cloud.
- Slave module check: Before provisioning,
action_provision checks that sadeem_waha_whatsapp_saas is installed on the slave; installs it if not, or raises UserError if unreachable.
- Slave communication errors: All slave API calls raise
UserError with HTTP status or exception details on failure.
- SQL constraint:
_sql_constraints on sadeem.waha.config.line enforces uniqueness of session names per WAHA config.
- No direct WAHA API calls: The master never calls WAHA directly — all WAHA operations go through the slave Odoo instance.