Query Odoo data including salesperson performance, customer analytics, orders, invoices, CRM, accounting, VAT, inventory, and AR/AP. Generates WhatsApp cards...
OpenClaw skills run inside an OpenClaw container. EasyClawd deploys and manages yours — no server setup needed.
Version 2.0.5 - Model invocation is now disabled per skill policy; the skill must be explicitly called by the user. - Updated documentation to reflect new invocation and security policy. - Added new documentation in assets/autonomous-cfo/README.md. - Removed obsolete logic file assets/autonomous-cfo/src/logic/openclaw_intelligence.py.
---
name: odoo
description: "Query Odoo data including salesperson performance, customer analytics, orders, invoices, CRM, accounting, VAT, inventory, and AR/AP. Generates WhatsApp cards, PDFs, Excel. Use when user explicitly mentions Odoo or asks for Odoo data."
---
# Odoo Financial Intelligence
**Read-only, Evidence-First, Ledger-Based Reports**
## Quick Reference: Common Odoo Models
| Model | What It Contains | Use For |
|-------|------------------|---------|
| `res.users` | Users/Salespeople | Find salesperson by name, get user_id |
| `sale.order` | Sales Orders | Revenue by salesperson, order counts, status |
| `account.move` | Invoices/Journal Entries | Invoice tracking, payments, P&L data |
| `res.partner` | Contacts/Customers | Customer info, top customers by revenue |
| `product.product` | Products | Product sales, inventory |
| `account.account` | Chart of Accounts | Financial reporting, balance sheet |
| `account.move.line` | Journal Lines | Detailed ledger entries |
## Security & Credentials
### Required Environment Variables
This skill requires Odoo connection credentials stored in `assets/autonomous-cfo/.env`:
| Variable | Description | Secret |
|----------|-------------|--------|
| `ODOO_URL` | Odoo instance URL (e.g., `https://your-odoo.com`) | No |
| `ODOO_DB` | Odoo database name | No |
| `ODOO_USER` | Odoo username/email | No |
| `ODOO_PASSWORD` | Odoo password or API key | **Yes** |
**Setup:**
```bash
cd skills/odoo/assets/autonomous-cfo
cp .env.example .env
# Edit .env with your actual credentials
nano .env
```
### Model Invocation Policy
**Model invocation is DISABLED** per `skill.json` policy. This skill handles sensitive financial data and external Odoo connections — it must be explicitly invoked by the user.
**Data Handling:** All queries are read-only. No data is modified or exfiltrated.
### Data Handling
- **Read-only:** All mutating methods (`create`, `write`, `unlink`, etc.) are blocked at the client level
- **No exfiltration:** Reports are generated locally in `assets/autonomous-cfo/output/`
- **Network endpoints:** Only connects to the Odoo URL specified in `.env`
- **Output formats:** PDF, Excel, and WhatsApp image cards (local files only)
### Installation
The skill requires a Python virtual environment with specific packages:
```bash
cd skills/odoo/assets/autonomous-cfo
./install.sh
```
Or manually:
```bash
cd skills/odoo/assets/autonomous-cfo
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
```
**Dependencies:** `requests`, `matplotlib`, `pillow`, `fpdf2`, `openpyxl`
## Critical Rules
1. **NEVER assume** - Always ask clarifying questions before generating reports
2. **Multi-company check** - If multiple companies exist, ASK which one to use
3. **Ledger-based** - Use Chart of Accounts and journal entries (account.move.line), not just invoice summaries
4. **Verify periods** - Confirm date ranges with user before running
5. **No silent defaults** - Every assumption must be confirmed
## Before Any Report, Ask:
1. "Which company should I use?" (if multiple exist)
2. "What period? (from/to dates)"
3. "Which accounts or account types to include?"
4. "Any specific breakdown needed?" (by account, by partner, by journal, etc.)
5. "Output format preference?" (PDF, WhatsApp cards, or both)
## Entrypoint
Uses the venv with fpdf2, matplotlib, pillow for proper PDF/chart generation:
```bash
./skills/odoo/assets/autonomous-cfo/venv/bin/python ./skills/odoo/assets/autonomous-cfo/src/tools/cfo_cli.py <command>
```
Or from the skill directory:
```bash
cd skills/odoo/assets/autonomous-cfo && ./venv/bin/python src/tools/cfo_cli.py <command>
```
## Chart of Accounts Based Reporting
Reports should be built from:
- `account.account` - Chart of Accounts structure (code, name, type, internal_group)
- `account.move.line` - Journal entry lines (debit, credit, account_id, date)
- `account.journal` - Source journals (type: sale, purchase, cash, bank, general)
### Account Internal Groups
- **ASSET** - Assets (current, non-current, cash, receivables)
- **LIABILITY** - Liabilities (payables, taxes, accrued)
- **EQUITY** - Owner's equity
- **INCOME** - Revenue accounts
- **EXPENSE** - Cost and expense accounts
- **OFF_BALANCE** - Off-balance sheet accounts
### Common Account Types
- `asset_cash` - Bank and cash accounts
- `asset_receivable` - Accounts receivable
- `asset_current` - Current assets
- `liability_payable` - Accounts payable
- `income` - Revenue
- `expense` - Expenses
### Special Equity Types (Odoo-Specific)
- `equity` - Standard equity accounts (share capital, retained earnings)
- `equity_unaffected` - **Suspense account** for undistributed profits/losses (e.g., 999999)
**CRITICAL for Balance Sheet:**
Odoo's `equity_unaffected` is a SUSPENSE account. Do NOT use its ledger balance directly.
**Correct Equity Calculation:**
1. **Equity Proper** (type: `equity`) - Use ledger balance (credit - debit)
2. **Retained Earnings** (prior years) - Ledger balance from `equity_unaffected`
3. **Current Year Earnings** - Compute real-time: Income - Expenses
```
Total Equity = Equity Proper + Retained Earnings + Current Year Earnings
```
Where Current Year Earnings = Σ(income credit-debit) - Σ(expense debit-credit)
**Why this matters:** Odoo computes Current Year Earnings in real-time on the Balance Sheet. Using only the `equity_unaffected` ledger balance will cause the balance sheet to NOT balance.
## Automatic Reporting Standard Detection
The skill automatically detects the company's accounting standard based on country/jurisdiction and formats reports accordingly.
**Supported Standards:**
| Standard | Jurisdiction | Notes |
|----------|--------------|-------|
| IFRS | International | Default for most countries |
| US GAAP | United States | SEC registrants |
| Ind-AS | India | Indian GAAP converged with IFRS |
| UK GAAP | United Kingdom | FRS 102 |
| SOCPA | Saudi Arabia | IFRS adopted |
| EU IFRS | European Union | IAS Regulation |
| CAS | China | Chinese Accounting Standards |
| JGAAP | Japan | Japanese GAAP |
| ASPE | Canada | Private enterprises |
| AASB | Australia | Australian standards |
**Detection Logic:**
1. Query company's country from `res.company`
2. Map country code to reporting standard
3. Apply standard-specific formatting:
- Number format (1,234.56 vs 1.234,56)
- Negative display ((123) vs -123)
- Date format (DD/MM/YYYY vs MM/DD/YYYY)
- Statement titles (Balance Sheet vs Statement of Financial Position)
- Cash flow method (indirect vs direct)
**Override:**
```python
# Force a specific standard
reporter.generate(..., standard="US_GAAP")
```
## Commands
### Sales & CRM Queries
```bash
# Salesperson performance - use direct RPC for flexibility
./venv/bin/python -c "
from src.visualizers.whatsapp_cards import WhatsAppCardGenerator
# Query sale.order by user_id, aggregate by month/status
# Generate cards with generate_kpi_card() and generate_comparison_card()
"
# Example RPC query for salesperson:
# - sale.order (user_id, amount_total, state, date_order)
# - account.move (invoice_user_id, amount_total, payment_state)
# - res.users (salesperson info)
# - res.partner (customer info)
```
### Pre-built Reports
```bash
# Financial Health - cash flow, liquidity, burn rate, runway
cfo_cli.py health --from YYYY-MM-DD --to YYYY-MM-DD --company-id ID
# Revenue Analytics - MoM trends, top customers
cfo_cli.py revenue --from YYYY-MM-DD --to YYYY-MM-DD --company-id ID
# AR/AP Aging - overdue buckets
cfo_cli.py aging --as-of YYYY-MM-DD --company-id ID
# Expense Breakdown - by vendor/category
cfo_cli.py expenses --from YYYY-MM-DD --to YYYY-MM-DD --company-id ID
# Executive Summary - one-page CFO snapshot
cfo_cli.py executive --from YYYY-MM-DD --to YYYY-MM-DD --company-id ID
```
### Direct RPC Queries (Advanced)
For sales/CRM data not covered by pre-built commands, use direct RPC:
```python
# Query sales orders by salesperson
orders = jsonrpc('sale.order', 'search_read'Read full documentation on ClawHub