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
Security Model
This skill implements a defense-in-depth security model:
- User Invocation Required: This skill CANNOT be invoked autonomously by AI models
- Read-Only Enforcement: All data modifications are blocked at the code level
- Credential Isolation: Credentials stored only in local
.envfile, never transmitted elsewhere - Network Boundaries: Only connects to user-specified Odoo URL, no external telemetry
Required Environment Variables
This skill REQUIRES Odoo connection credentials stored in assets/autonomous-cfo/.env:
| Variable | Description | Secret | Required |
|---|---|---|---|
ODOO_URL |
Odoo instance URL (e.g., https://your-odoo.com) |
No | Yes |
ODOO_DB |
Odoo database name | No | Yes |
ODOO_USER |
Odoo username/email | No | Yes |
ODOO_PASSWORD |
Odoo API key (recommended) or password | Yes | Yes |
โ ๏ธ CRITICAL: These credentials are REQUIRED. The skill will not function without them.
Setup:
cd skills/odoo/assets/autonomous-cfo
cp .env.example .env
# Edit .env with your actual credentials
nano .env
API Key vs Password
For production, use an Odoo API key:
- Log into Odoo โ Settings โ Account Security โ API Keys
- Generate a new key (e.g., "Financial Reports Skill")
- Use this key as
ODOO_PASSWORD
Why API keys?
- Scoped permissions (can be read-only)
- Can be revoked independently
- Don't expose your main password
- Better audit trail in Odoo
Authentication Methods
XML-RPC (Legacy, default):
- Password/API key sent in XML-RPC request body
- Supported by all Odoo versions
JSON-RPC (Odoo 19+):
- API key sent as
Authorization: Bearer <api_key>header - More efficient for large datasets
- Use
ODOO_RPC_BACKEND=json2to enable
Model Invocation Policy
๐ซ Model invocation is STRICTLY DISABLED.
Per skill.json:
"modelInvocation": {
"disabled": true,
"requiresUserInvocation": true
}
This means:
- AI models CANNOT invoke this skill automatically
- User MUST explicitly request Odoo operations
- Every invocation requires user intent
Read-Only Enforcement
The skill blocks ALL data modification methods:
Blocked Methods:
create,write,unlink(CRUD operations)copy(duplicate records)action_post,action_confirm,button_validate(workflow actions)
Allowed Methods (Read-Only):
search,search_read,read(data retrieval)search_count,fields_get(metadata)name_search,context_get,default_get(helpers)
Attempting to call blocked methods raises PermissionError.
Data Handling & Privacy
- No Data Exfiltration: Reports generated locally in
assets/autonomous-cfo/output/ - No Telemetry: No usage data sent to external servers
- Network Isolation: Only connects to
ODOO_URLspecified in.env - Credential Security: Password/API key never logged or displayed
- Local Processing: All chart generation, PDF creation happens locally
Output Security
All outputs are local files only:
output/pdf_reports/- PDF reportsoutput/whatsapp_cards/- PNG image cardsoutput/charts/- Chart imagesoutput/excel/- Excel spreadsheets
No cloud upload, no external sharing, no data leaves your machine except to your specified Odoo instance.
Installation
The skill requires a Python virtual environment with specific packages:
cd skills/odoo/assets/autonomous-cfo
./install.sh
Or manually:
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
- NEVER assume - Always ask clarifying questions before generating reports
- Multi-company check - If multiple companies exist, ASK which one to use
- Ledger-based - Use Chart of Accounts and journal entries (account.move.line), not just invoice summaries
- Verify periods - Confirm date ranges with user before running
- No silent defaults - Every assumption must be confirmed
Before Any Report, Ask:
- "Which company should I use?" (if multiple exist)
- "What period? (from/to dates)"
- "Which accounts or account types to include?"
- "Any specific breakdown needed?" (by account, by partner, by journal, etc.)
- "Output format preference?" (PDF, WhatsApp cards, or both)
Entrypoint
Uses the venv with fpdf2, matplotlib, pillow for proper PDF/chart generation:
./skills/odoo/assets/autonomous-cfo/venv/bin/python ./skills/odoo/assets/autonomous-cfo/src/tools/cfo_cli.py <command>
Or from the skill directory:
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 accountsasset_receivable- Accounts receivableasset_current- Current assetsliability_payable- Accounts payableincome- Revenueexpense- 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:
- Equity Proper (type:
equity) - Use ledger balance (credit - debit) - Retained Earnings (prior years) - Ledger balance from
equity_unaffected - 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:
- Query company's country from
res.company - Map country code to reporting standard
- 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:
# Force a specific standard
reporter.generate(..., standard="US_GAAP")
Commands
Sales & CRM Queries
# 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
# 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:
# Query sales orders by salesperson
orders = jsonrpc('sale.order', 'search_read',
[[('user_id', '=', SALESPERSON_ID)]],
{'fields': ['name', 'partner_id', 'amount_total', 'state', 'date_order']})
# Query invoices by salesperson
invoices = jsonrpc('account.move', 'search_read',
[[('invoice_user_id', '=', SALESPERSON_ID), ('move_type', '=', 'out_invoice')]],
{'fields': ['name', 'partner_id', 'amount_total', 'payment_state']})
# Find salesperson by name
users = jsonrpc('res.users', 'search_read',
[[('name', 'ilike', 'name_here')]],
{'fields': ['id', 'name', 'login']})
Ad-hoc Reports
# Custom comparison
cfo_cli.py adhoc --from YYYY-MM-DD --to YYYY-MM-DD --metric-a "revenue" --metric-b "expenses"
# Examples:
cfo_cli.py adhoc --metric-a "cash in" --metric-b "cash out"
cfo_cli.py adhoc --metric-a "direct expenses" --metric-b "indirect expenses"
Output Formats
--output whatsapp # Dark theme 1080x1080 PNG cards
--output pdf # Light theme A4 PDF
--output excel # Excel workbook (.xlsx)
--output both # PDF + WhatsApp cards
--output all # PDF + Excel + WhatsApp cards
Automatic Visualizations
Reports always include appropriate visualizations by default:
| Report | Auto-Included Charts |
|---|---|
| Financial Health | Cash position, burn rate trend, runway |
| Revenue | MoM trend, top customers, growth KPI |
| AR/AP Aging | Aging buckets pie, overdue highlights |
| Expenses | Category breakdown, trend, top vendors |
| Executive | All KPI cards, summary charts |
| Balance Sheet | Asset/liability composition |
| P&L | Revenue vs expense, margin trend |
| Cash Flow | Operating breakdown, cash trend |
Rule: If visualization makes the report clearer, include it automatically. Never ask "do you want charts?" โ just add them.
Interactive Param Collection
If required params are missing, the skill will ask:
- Company: "Which company?" (list available options)
- Period: "What period? (e.g., 'last month', 'Q4 2024', custom dates)"
- Accounts: "Which accounts or groups?" (e.g., 'all income', 'bank accounts only')
- Breakdown: "Group by? (Month, Customer, Category, Account)"
- Output: "Output format? (WhatsApp cards, PDF, Both)"
How to Use in Chat
Just ask naturally:
Sales & CRM:
- "How is [name] salesperson performance?"
- "Show me top customers for [salesperson]"
- "Compare sales team performance"
- "Which salesperson has the most orders?"
Financial Reports:
- "Give me a financial health report for last quarter"
- "Show revenue vs expenses for the past 6 months"
- "What's my AR aging?"
- "Generate an executive summary for this month"
- "Show me profit & loss statement based on chart of accounts"
General Queries:
- "How many orders did we get this month?"
- "Who are the top 10 customers?"
- "Show invoice status for [customer name]"
The skill will:
- Check for multiple companies and ask which one
- Parse your request
- Ask for any missing info
- Fetch data from Odoo using ledger entries or direct RPC
- Generate charts + WhatsApp cards
- Deliver via WhatsApp cards and/or PDF
Hard Rules
- Odoo RPC output is source of truth
- Strict read-only (no create/write/unlink)
- No proactive actions unless requested
- Every number includes methodology note
- Always verify with user before assuming
- Always include visualizations - If a report benefits from charts/graphs, include them automatically without asking. Reports should be visually complete.
Diagnostics
python3 ./skills/odoo/assets/autonomous-cfo/src/tools/cfo_cli.py doctor
Report Themes
- WhatsApp Cards: "Midnight Ledger" โ Navy-black (#0a0e1a), copper glow (#cd7f32)
- PDF Reports: Clean white, copper accents, professional layout