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