155 lines
7.7 KiB
Markdown
155 lines
7.7 KiB
Markdown
# fusion_accounting — AI Accounting Co-Pilot
|
|
|
|
## What This Module Does
|
|
An AI agent (Claude/GPT with tool-calling) embedded in Odoo 19 Enterprise Accounting. Conversational interface backed by a dashboard for bank reconciliation, HST/GST management, AR/AP analysis, journal review, month-end close, payroll, inventory, ADP reconciliation, financial reporting, and auditing.
|
|
|
|
## Architecture
|
|
```
|
|
fusion_accounting/
|
|
├── models/ 7 models (6 new + 1 inherit on account.move)
|
|
├── services/
|
|
│ ├── agent.py AI orchestrator (prompt assembly, tool dispatch loop)
|
|
│ ├── adapters/ Claude + OpenAI adapters with native tool-calling
|
|
│ ├── tools/ 85 tool functions across 11 domain files
|
|
│ ├── prompts/ System prompt builder + 12 domain-specific prompts
|
|
│ └── scoring.py Confidence scoring + tier promotion logic
|
|
├── controllers/ 8 JSON-RPC endpoints
|
|
├── wizards/ Rule creation wizard
|
|
├── static/src/ OWL dashboard + chat panel + approval cards
|
|
├── views/ List/form/search views, menus, settings
|
|
├── security/ 3 groups (User/Manager/Admin), record rules, ACLs
|
|
├── data/ 82 tool definitions, 2 default rules, 2 crons
|
|
└── report/ Audit report QWeb template
|
|
```
|
|
|
|
## Key Design Decisions
|
|
|
|
### AI Provider Integration
|
|
- Uses `fusion.api.service` (from fusion_api module) for API key resolution with fallback to `ir.config_parameter` — NO hard dependency on fusion_api
|
|
- Claude adapter: native `tool_use` blocks, extended thinking enabled (8K budget) for 4.5+ models
|
|
- OpenAI adapter: Chat Completions API with o-series reasoning model support (`developer` role, `max_completion_tokens`, `reasoning_effort`)
|
|
- API keys stored in `ir.config_parameter` with `fusion_accounting.` prefix
|
|
|
|
### Tool Tiering
|
|
- **Tier 1** (Free): Read-only, execute immediately — 60+ tools
|
|
- **Tier 2** (Auto-approved): Low-risk writes, logged — ~10 tools
|
|
- **Tier 3** (Requires approval): Financial writes, user must approve — ~15 tools
|
|
- Auto-promotion: Tier 3 → Tier 2 at 95% accuracy over 30+ decisions (atomic SQL counters)
|
|
|
|
### Menu Location
|
|
- **Parent**: `accountant.menu_accounting` (NOT `account.menu_finance` — that's Community Edition only)
|
|
- Enterprise uses `accountant.menu_accounting` (ID 1663) as the visible menu root
|
|
|
|
### Session Persistence
|
|
- Chat sessions stored in `fusion.accounting.session` with `message_ids_json` (JSON text field)
|
|
- On page load, chat panel calls `/session/latest` to restore the most recent active session
|
|
- "New Chat" button closes current session and creates a fresh one
|
|
|
|
## Odoo 19 Gotchas (Learned the Hard Way)
|
|
|
|
### Search Views
|
|
- NO `string` attribute on `<search>` element
|
|
- NO `string` attribute on `<group>` element inside search views
|
|
- Group-by filters MUST have `domain="[]"` attribute
|
|
- Add `<separator/>` before `<group>` in search views
|
|
|
|
### OWL Client Actions
|
|
- Components registered as client actions receive props: `action`, `actionId`, `updateActionState`, `className`
|
|
- Must use `static props = ["*"]` (accept any) — NOT `static props = []` (accept none)
|
|
|
|
### Cron Safe Eval
|
|
- NO `import` statements (forbidden opcode `IMPORT_NAME`)
|
|
- `datetime` module available as `datetime` (use `datetime.datetime.now()`, `datetime.timedelta()`)
|
|
- NO `from datetime import X` pattern
|
|
|
|
### read_group Deprecated
|
|
- `read_group()` is deprecated in Odoo 19 — use `_read_group()` instead
|
|
- Still works but throws DeprecationWarning
|
|
|
|
### Config Parameter Values
|
|
- When changing a Selection field's options, the stored DB value in `ir_config_parameter` must match one of the new options or Settings page will crash with `ValueError: Wrong value`
|
|
- Fix: UPDATE the value in DB after changing selection options
|
|
|
|
### Field Label Conflicts
|
|
- Odoo warns if two fields on the same model have the same `string` label
|
|
- Our `display_name_field` conflicted with built-in `display_name` — renamed string to "Tool Label"
|
|
|
|
### Group Assignment
|
|
- `implied_ids` on groups only applies to NEWLY added users, not existing ones
|
|
- After installing, manually add existing users to groups via SQL:
|
|
```sql
|
|
INSERT INTO res_groups_users_rel (gid, uid)
|
|
SELECT <group_id>, gu.uid FROM res_groups_users_rel gu
|
|
JOIN ir_model_data imd ON imd.res_id = gu.gid AND imd.model = 'res.groups'
|
|
WHERE imd.module = 'account' AND imd.name = 'group_account_manager'
|
|
ON CONFLICT DO NOTHING;
|
|
```
|
|
|
|
## Server Details
|
|
- **Server**: odoo-westin (192.168.1.40, SSH via `ssh odoo-westin`)
|
|
- **Container**: odoo-dev-app (Odoo), odoo-dev-db (PostgreSQL)
|
|
- **Database**: westin-v19
|
|
- **Module path**: `/mnt/extra-addons/fusion_accounting/`
|
|
- **Python deps**: anthropic (v0.88.0), openai (v2.30.0) — installed with `--break-system-packages`
|
|
|
|
## Deployment Commands
|
|
```bash
|
|
# Deploy module to server
|
|
ssh odoo-westin "docker exec -u 0 odoo-dev-app rm -rf /mnt/extra-addons/fusion_accounting"
|
|
scp -r "K:\Github\Odoo-Modules\fusion_accounting" odoo-westin:/tmp/fusion_accounting
|
|
ssh odoo-westin "docker cp /tmp/fusion_accounting odoo-dev-app:/mnt/extra-addons/fusion_accounting && rm -rf /tmp/fusion_accounting"
|
|
|
|
# Upgrade module (use alt port to avoid conflict with running instance)
|
|
ssh odoo-westin "docker exec odoo-dev-app odoo -d westin-v19 -u fusion_accounting --stop-after-init --http-port=8099 -c /etc/odoo/odoo.conf"
|
|
|
|
# Restart container
|
|
ssh odoo-westin "docker restart odoo-dev-app"
|
|
|
|
# Check logs
|
|
ssh odoo-westin "docker logs odoo-dev-app --tail 100"
|
|
```
|
|
|
|
## Security Groups
|
|
| Group ID | XML ID | Name | Access |
|
|
|---|---|---|---|
|
|
| 564 | `group_fusion_accounting_user` | User | Dashboard, chat (read-only tools) |
|
|
| 565 | `group_fusion_accounting_manager` | Manager | + Approve/reject, Tier 2 tools, rules |
|
|
| 566 | `group_fusion_accounting_admin` | Administrator | + Config, all tools, rule admin |
|
|
|
|
Auto-assigned: `account.group_account_user` → User, `account.group_account_manager` → Admin
|
|
|
|
## Models
|
|
| Model | Type | Purpose |
|
|
|---|---|---|
|
|
| `fusion.accounting.session` | Model | Chat sessions with message JSON storage |
|
|
| `fusion.accounting.match.history` | Model | Every AI tool call + decision (approved/rejected/pending) |
|
|
| `fusion.accounting.rule` | Model | Fusion Rules engine with versioning and auto-promotion |
|
|
| `fusion.accounting.tool` | Model | Tool registry (82 tools seeded from XML) |
|
|
| `fusion.accounting.dashboard` | TransientModel | Computed health metrics (use `.new()` not `.create()`) |
|
|
| `fusion.accounting.agent` | AbstractModel | AI orchestrator |
|
|
| `fusion.accounting.adapter.claude` | AbstractModel | Claude tool-calling adapter |
|
|
| `fusion.accounting.adapter.openai` | AbstractModel | OpenAI tool-calling adapter |
|
|
| `fusion.accounting.scoring` | AbstractModel | Confidence scoring |
|
|
| `account.move` (inherit) | Model | Post-action audit hook |
|
|
|
|
## AI Models Available
|
|
**Claude** (default: claude-sonnet-4-6):
|
|
- claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5
|
|
- claude-sonnet-4-5, claude-opus-4-5, claude-sonnet-4-0, claude-opus-4-0
|
|
|
|
**OpenAI** (default: gpt-5.4-mini):
|
|
- gpt-5.4, gpt-5.4-mini, gpt-5.4-nano
|
|
- o3, o4-mini
|
|
- gpt-4o, gpt-4o-mini (legacy)
|
|
|
|
## Theme / Styling Rules
|
|
- NO hardcoded colours — use CSS variables (`var(--o-border-color)`, `var(--bs-body-color-rgb)`) and Bootstrap utility classes
|
|
- Must work in both light and dark mode
|
|
- Box shadows: use `rgba(var(--bs-body-color-rgb), 0.1)` not `rgba(0,0,0,0.1)`
|
|
|
|
## Known Issues / Future Work
|
|
- `read_group()` deprecation warnings — migrate to `_read_group()` when format is documented
|
|
- `verify_source_deductions`, `generate_t4`, `generate_roe` are stubs pointing to fusion_payroll (by design — Phase 2)
|
|
- `account.return` model used in HST tools may not exist in all Odoo 19 setups — needs try/except guard
|
|
- Batch approval "Approve All" / "Reject All" buttons are in the chat panel but not yet in the match history list view
|