Full-featured Odoo 19 ERP connector for OpenClaw - Sales, CRM, Purchase, Inventory, Projects, HR, Fleet, Manufacturing (80+ operations, complete Python code...
---
name: odoo
description: Full-featured Odoo 19 ERP connector for OpenClaw - Sales, CRM, Purchase, Inventory, Projects, HR, Fleet, Manufacturing (80+ operations, complete Python code included, XML-RPC integration).
repository: https://github.com/NullNaveen/openclaw-odoo-skill
---
# Odoo ERP Connector
Full-featured Odoo 19 ERP integration for OpenClaw. Control your entire business via natural language chat commands.
**๐ฆ Full Source Code:** https://github.com/NullNaveen/openclaw-odoo-skill
## Quick Install
\ash
npx clawhub install odoo-erp-connector
\
## Overview
The Odoo ERP Connector bridges OpenClaw and Odoo 19, enabling autonomous, chat-driven control over 153+ business modules including:
- Sales & CRM
- Purchasing & Inventory
- Invoicing & Accounting
- Projects & Task Management
- Human Resources
- Fleet Management
- Manufacturing (MRP)
- Calendar & Events
- eCommerce
All operations use **smart actions** that handle fuzzy matching and auto-creation workflows.
## Capabilities
### Sales & CRM
- Create quotations with dynamic line items
- Manage sales orders (draft โ confirmed โ done)
- Search and filter orders by status, customer, date range
- Create and qualify leads and opportunities
- Move leads through CRM pipeline stages
- View full sales pipeline with revenue forecasting
### Purchasing
- Create purchase orders from vendors
- Manage PO status (draft โ purchase โ received)
- Receive and validate goods
- Search and filter POs by vendor, status, date
- Track purchase history and vendor performance
### Inventory & Products
- Create products (consumables, stockable, services)
- Query stock levels and availability
- Set reorder points and receive low-stock alerts
- Search products by name, code, or category
- Track stock movements and valuations
### Invoicing & Accounting
- Create and post customer invoices
- Manage payment terms and schedules
- Query unpaid and overdue invoices
- Search by customer, date range, or amount
- Track invoice status (draft โ posted โ paid)
### Projects & Tasks
- Create projects and organize by team/status
- Create tasks with priority, dates, and assignments
- Log timesheets and track project hours
- Search and filter tasks by project, status, assignee
- Manage project stages and closure
### Human Resources
- Create employees and departments
- Manage job titles and work schedules
- Process expense reports and reimbursements
- Search employees by name, department, job
- Track leave requests and attendance
### Fleet Management
- Create and track vehicles
- Log odometer readings and service records
- Track maintenance schedules and costs
- Search fleet by license plate, status, brand
- Generate fleet reports
### Manufacturing (MRP)
- Create Bills of Materials (BOMs)
- Manage manufacturing orders (MOs)
- Track component requirements and production status
- Search MOs by product or status
- Link BOMs to product variants
### Calendar & Events
- Create meetings and events with attendees
- Set reminders and locations
- Search events by date range or attendee
- Track calendar availability
### eCommerce
- Publish products to website
- View website orders and customer activity
- Manage product visibility and pricing
## Command Examples
### Sales
- "Create a quotation for Acme Corp with 10 Widgets at $50 each"
- "Confirm sales order SO00042"
- "Show me all draft quotations from the past week"
- "What's the total revenue from completed orders this month?"
- "Create a quote for Rocky with product Rock"
### CRM
- "Create a lead for Rocky, email rocky@example.com, potential $50k deal"
- "Move lead #47 to Qualified stage"
- "Show me the sales pipeline with all open opportunities"
- "What leads are at proposal stage?"
- "Create an opportunity for Acme with $100k expected value"
### Purchasing
- "Create a PO for 500 widgets from Supplier ABC"
- "Confirm purchase order PO00123"
- "Show all pending purchase orders"
- "Get me the vendor history for ABC Supplies"
- "What's on order that's overdue?"
### Inventory & Products
- "Create a new product: TestWidget, $25 price, min stock 10"
- "Show products with stock below 20 units"
- "What's the stock level for Widget X?"
- "Search for all consumable products"
- "Set reorder point for Product Y to 50 units"
### Invoicing
- "Create an invoice for Acme Corp with 5 units at $50 each"
- "Show me unpaid invoices"
- "What invoices are overdue?"
- "Post invoice INV-001"
- "Send a reminder for invoice INV-002"
### Projects & Tasks
- "Create a project called Website Redesign"
- "Create a task 'Fix login button' in Website Redesign project"
- "Show me all tasks assigned to me"
- "Log 3 hours of work on task #42"
- "What's the status of the Website Redesign project?"
### HR
- "Create employee John Smith, job title Developer"
- "Create department Engineering"
- "Show me all employees in Engineering"
- "Submit expense report for $45.99"
- "What are the pending leave requests?"
### Fleet
- "Create vehicle: Tesla Model 3, license plate TESLA-001"
- "Log odometer reading: 50,000 miles for vehicle #1"
- "Show all vehicles with service due"
- "What's the maintenance cost for this month?"
- "Search for blue vehicles"
### Manufacturing
- "Create BOM: Widget contains 3 Components A and 2 Components B"
- "Create manufacturing order: produce 50 Widgets"
- "Confirm production order #1"
- "What's the status of MO-001?"
- "Show all in-progress manufacturing orders"
### Calendar
- "Create meeting: Team Standup, tomorrow at 10am, 1 hour"
- "Show me my meetings for next week"
- "What events do I have on the 15th?"
- "Schedule a 2-hour planning session with the team"
### eCommerce
- "Publish Widget X to the website"
- "Show me website orders from this week"
- "What's my website revenue?"
## Smart Actions
The connector handles fuzzy/incomplete requests with intelligent find-or-create logic.
### How Smart Actions Work
**Example:** "Create quotation for Rocky with product Rock"
The system:
1. **Searches** for a customer named "Rocky" (case-insensitive, `ilike` matching)
2. **If not found**: Creates a new customer "Rocky" (auto-company flag)
3. **Searches** for product "Rock"
4. **If not found**: Creates a basic product "Rock" (consumable type, default price $0)
5. **Creates** the quotation, linking both the found/created customer and product
6. **Reports** what was found vs. created:
- "Created quotation QT-001 for new customer Rocky with 1 ร Rock at $0.00"
This pattern applies across all smart actions:
- `smart_create_quotation()` โ customer + products
- `smart_create_purchase()` โ vendor + products
- `smart_create_lead()` โ partner (optional)
- `smart_create_task()` โ project + task
- `smart_create_employee()` โ department
- `smart_create_event()` โ event only (no dependencies)
### Benefits
- **Fuzzy matching**: Searches are case-insensitive and forgiving
- **Auto-creation**: Missing dependencies are created automatically
- **Transparency**: Each response explains what was created vs. found
- **No IDs needed**: Use names instead of Odoo IDs
- **Batch operations**: Create multiple related records in one call
## Architecture
### Core Components
**OdooClient** โ Low-level XML-RPC wrapper
- Connects to Odoo 19 instance
- Handles authentication via API key
- Provides `search()`, `read()`, `create()`, `write()`, `unlink()` methods
- Built-in retry logic and error handling
**Model Ops Classes** โ Business logic for each module
- `PartnerOps` โ Customers/suppliers
- `SaleOrderOps` โ Quotations and sales orders
- `InvoiceOps` โ Customer invoices
- `InventoryOps` โ Products and stock
- `CRMOps` โ Leads and opportunities
- `PurchaseOrderOps` โ POs and vendors
- `ProjectOps` โ Projects and tasks
- `HROps` โ Employees, departments, expenses
- `ManufacturingOps` โ BOMs and MOs
- `CalendarOps` โ Events and meetings
- `FleetOps` โ Vehicles and odometer
- `EcommerceOps` โ Website orders and products
**SmartActionHandler** โ High-level natural-language interface
- Wraps all Ops classes
- Implements find-or-create workflows
- Fuzzy name matching (case-insensitive)
- Multi-step transaction orchestration
- Detailed response summaries
### Field Handling
The connector auto-detects required vs. optional fields in Odoo 19:
- **Implicit defaults**: Fields with Odoo defaults (e.g., state) are omitted
- **Smart creation**: Auto-fills reasonable defaults for optional fields
- **Error reporting**: Missing required fields raise clear `OdooError` with field name
## Configuration
### config.json Format
```json
{
"url": "http://localhost:8069",
"db": "your_database",
"username": "api_user@yourcompany.com",
"api_key": "your_api_key_from_odoo_preferences",
"timeout": 60,
"max_retries": 3,
"poll_interval": 60,
"log_level": "INFO",
"webhook_port": 8070,
"webhook_secret": ""
}
```
### Getting Your API Key
1. Log in to your Odoo instance
2. Go to **Settings** โ **Users & Companies** โ **Users**
3. Open your user record
4. Scroll to **Access Tokens**
5. Click **Generate Token**
6. Copy the token and paste into `config.json`
### Environment Variables
Alternatively, set in `.env`:
```
ODOO_URL=http://localhost:8069
ODOO_DB=your_database
ODOO_USERNAME=api_user@yourcompany.com
ODOO_API_KEY=your_api_key
```
The client auto-loads from `.env` if `config.json` is missing.
## Python API
### Basic Usage
```python
from odoo_skill import OdooClient, SmartActionHandler
# Load config from config.json
client = OdooClient.from_config("config.json")
# Test connection
status = client.test_connection()
print(f"Connected to Odoo {status['server_version']}")
# Use smart actions for natural workflows
smart = SmartActionHandler(client)
# Create a quotation with fuzzy partner and product matching
result = smart.smart_create_quotation(
customer_name="Rocky",
product_lines=[
{"name": "Rock", "quantity": 5, "price_unit": 19.99}
],
notes="Fuzzy match quotation"
)
print(result["summary"])
# Output: "Created quotation QT-001 for new customer Rocky with 1 ร Rock at $19.99"
```
### Smart Actions API
```python
# Find-or-create a customer
result = smart.find_or_create_partner(
name="Acme Corp",
is_company=True,
city="New York"
)
partner = result["partner"]
created = result["created"]
# Find-or-create a product
result = smart.find_or_create_product(
name="Widget X",
list_price=49.99,
type="consu"
)
product = result["product"]
# Smart quotation (auto-creates customer & products)
result = smart.smart_create_quotation(
customer_name="Rocky",
product_lines=[
{"name": "Product A", "quantity": 10},
{"name": "Product B", "quantity": 5, "price_unit": 25.0}
],
notes="Created via smart action"
)
order = result["order"]
print(f"Order {order['name']} created with {len(result['products'])} product(s)")
# Smart lead creation
result = smart.smart_create_lead(
name="New Prospect",
contact_name="John Doe",
email="john@prospect.com",
expected_revenue=50000.0
)
lead = result["lead"]
# Smart task creation (auto-creates project if needed)
result = smart.smart_create_task(
project_name="Website Redesign",
task_name="Fix homepage",
description="Update hero section"
)
task = result["task"]
# Smart employee creation (auto-creates department if needed)
result = smart.smart_create_employee(
name="Jane Smith",
job_title="Developer",
department_name="Engineering"
)
employee = result["employee"]
```
### Low-Level Ops API
```python
from odoo_skill.models.sale_order import SaleOrderOps
from odoo_skill.models.partner import PartnerOps
partners = PartnerOps(client)
sales = SaleOrderOps(client)
# Get all customers
customers = partners.search_customers(limit=10)
for cust in customers:
print(f"{cust['name']} โ {cust.get('email')}")
# Create a quotation with specific IDs
order = sales.create_quotation(
partner_id=42,
lines=[
{"product_id": 7, "quantity": 10, "price_unit": 49.99},
{"product_id": 8, "quantity": 5}
],
notes="Manual order"
)
print(f"Created {order['name']}")
# Confirm the order
confirmed = sales.confirm_order(order['id'])
print(f"Order {confirmed['name']} is now {confirmed['state']}")
```
## Response Format
All API methods return structured dictionaries:
### Smart Action Response
```python
{
"summary": "Created quotation QT-001 for new customer Rocky with 1 ร Rock",
"order": {
"id": 1,
"name": "QT-001",
"state": "draft",
"partner_id": [42, "Rocky"],
"amount_total": 19.99
},
"customer": {
"created": True,
"partner": {"id": 42, "name": "Rocky"}
},
"products": [
{
"created": True,
"product": {"id": 7, "name": "Rock"}
}
]
}
```
### Standard Response
```python
{
"id": 1,
"name": "QT-001",
"state": "draft",
"partner_id": [42, "Rocky"],
"amount_total": 19.99,
"order_line": [
{
"id": 1,
"product_id": [7, "Rock"],
"quantity": 1,
"price_unit": 19.99,
"price_subtotal": 19.99
}
]
}
```
## Error Handling
The connector uses custom exceptions:
```python
from odoo_skill.errors import OdooError, OdooAuthError, OdooNotFoundError
try:
result = smart.smart_create_quotation(
customer_name="Acme",
product_lines=[{"name": "Widget"}]
)
except OdooAuthError as e:
print(f"Authentication failed: {e}")
except OdooNotFoundError as e:
print(f"Record not found: {e}")
except OdooError as e:
print(f"Odoo error: {e}")
```
## Supported Odoo Modules
The connector supports 153+ installed modules in Odoo 19:
**Core**
- base, web, website
**Sales & CRM**
- sale, crm, sale_management, website_sale, event, survey
**Purchasing**
- purchase, purchase_stock, purchase_requisition
**Inventory**
- stock, stock_intrastat, stock_dropshipping
**Accounting**
- account, account_accountant, account_analytic, account_payment
**HR**
- hr, hr_attendance, hr_expense, hr_contract, hr_holidays, hr_org_chart
**Projects**
- project, project_enterprise, task_base, project_timesheet_forecast
**Manufacturing**
- mrp, mrp_byproduct, quality, batch, shelf_life
**Fleet**
- fleet, maintenance
**Marketing**
- marketing_automation, email_marketing, mass_mailing, sms, website_form
**eCommerce**
- website_sale, website_sale_analytics, website_sale_comparison, website_form_project
**Tools**
- calendar, documents, spreadsheet, discuss, mail, knowledge
**Plus 50+ more specialized modules**
## Limits & Constraints
- **Search limit**: 100 records by default (configurable)
- **Timeout**: 60 seconds per request (configurable)
- **Retries**: 3 automatic retries on network failure
- **Concurrency**: Single-threaded; queue requests if needed
- **Rate limiting**: Follow your Odoo instance's API limits
## Troubleshooting
### Connection Issues
- Verify `url`, `db`, `username`, `api_key` in config.json
- Check Odoo server is running: `http://your-odoo-url/web`
- Ensure API key is generated in Odoo user settings
- Check network connectivity and firewall rules
### Authentication Errors
- Regenerate API key in Odoo
- Verify username (email format)
- Check that the user has API access enabled
- Ensure database name matches exactly
### Missing Field Errors
- Field names must match Odoo 19 exactly (e.g., `product_tmpl_id`, not `product_id`)
- Some fields are read-only in Odoo (state, computed fields)
- Check Odoo model definition: Settings โ Technical โ Database Structure โ Models
### Smart Action Issues
- Fuzzy matching is case-insensitive but searches only the `name` field
- For exact matching, use the low-level Ops API with `id` directly
- If a name exists in multiple records, the first match is used
### Performance
- Large searches (limit > 100) may timeout
- Use date range filters: `date_from`, `date_to`
- Consider batch operations for bulk data
## Examples in OpenClaw
### Natural Language Sales Order
```
User: "Create a quote for Acme Corp with 10 Widgets at $50 each"
OpenClaw โ OdooClient (smart action):
1. Search for customer "Acme Corp"
2. Search for product "Widgets"
3. Create quotation with both
4. Return summary
Result: "โ
Created quotation QT-001 for Acme Corp with 10 ร Widgets at $50"
```
### Pipeline Status Check
```
User: "Show me the sales pipeline"
OpenClaw โ CRMOps.get_pipeline():
- Query all leads/opportunities
- Group by stage
- Calculate total revenue by stage
- Return formatted summary
Result: "Qualified: $50k | Proposal: $100k | Negotiation: $75k | Total: $225k"
```
### Inventory Alert
```
User: "What products are low on stock?"
OpenClaw โ InventoryOps.get_low_stock_products():
- Query products with stock < reorder point
- List each product, stock level, reorder point
- Suggest PO quantities
Result: "Widget X: 5 on hand (min 20) | Component Y: 0 on hand (min 10)"
```
## Development
### Project Structure
```
OdooConnector/
โโโ odoo_skill/
โ โโโ client.py # Core OdooClient
โ โโโ config.py # Configuration loader
โ โโโ errors.py # Custom exceptions
โ โโโ retry.py # Retry logic
โ โโโ smart_actions.py # Smart action handler
โ โโโ models/
โ โ โโโ partner.py
โ โ โโโ sale_order.py
โ โ โโโ invoice.py
โ โ โโโ inventory.py
โ โ โโโ crm.py
โ โ โโโ purchase.py
โ โ โโโ project.py
โ โ โโโ hr.py
โ โ โโโ manufacturing.py
โ โ โโโ calendar_ops.py
โ โ โโโ fleet.py
โ โ โโโ ecommerce.py
โ โโโ utils/
โ โ โโโ formatting.py # Response formatting
โ โ โโโ validators.py # Input validation
โ โโโ sync/
โ โ โโโ poller.py # Webhook poller
โ โ โโโ webhook.py # Webhook handler
โโโ run_full_test.py # Integration test suite
โโโ config.json # Configuration (create from template)
โโโ config.template.json # Configuration template
โโโ requirements.txt # Python dependencies
โโโ README.md # User setup guide
โโโ SKILL.md # This file
โโโ setup.ps1 # PowerShell installer
```
### Running Tests
```bash
# Run full integration test suite
python run_full_test.py
# Run single test module
python -m pytest tests/test_partners.py -v
# Run with coverage
python -m pytest --cov=odoo_skill tests/
```
### Adding a New Smart Action
1. Implement the method in `SmartActionHandler` class
2. Use `find_or_create_*` primitives for dependencies
3. Return a dict with `summary`, the main record, and creation details
4. Add docstring with example usage
5. Test with `run_full_test.py`
Example:
```python
def smart_create_invoice(self, customer_name: str, product_lines: list[dict], **kwargs) -> dict:
"""Create invoice with fuzzy customer and product matching."""
# Find or create customer
customer_result = self.find_or_create_partner(customer_name)
customer = customer_result["partner"]
# Find or create products
products = []
for line in product_lines:
prod_result = self.find_or_create_product(line["name"], **line)
products.append(prod_result)
# Create invoice with resolved IDs
invoice = self.invoices.create_invoice(
partner_id=customer["id"],
lines=[...],
**kwargs
)
return {
"summary": f"Created invoice INV-001 for {customer['name']}",
"invoice": invoice,
"customer": customer_result,
"products": products
}
```
## License & Support
This connector is part of the OpenClaw project. For issues, questions, or contributions, contact the development team.
---
**Last Updated:** 2026-02-09
**Odoo Version:** 19.0
**Python:** 3.10+
**Status:** Production Ready
don't have the plugin yet? install it then click "run inline in claude" again.