Products Manager APP

Features

Odoo ERP Integration

Synchronize your product catalog with Odoo ERP. Bidirectional sync, configurable field mappings, automated schedules, and detailed sync history tracking with 80 tests validating the implementation.


Overview

The Odoo Integration enables seamless bidirectional synchronization between Products Manager and your Odoo ERP instance. Built on Odoo's XML-RPC protocol, this integration supports both export (push products to Odoo) and import (pull products from Odoo) workflows.

Key Features

  • Bidirectional Sync: Export products to Odoo or import from Odoo
  • Configurable Field Mapping: Map local fields to Odoo fields with transformations
  • Scheduled Syncs: Cron-based automation with Celery workers
  • Sync History: Complete audit trail of all synchronization operations
  • Category & Tax Mapping: Match categories and tax rates between systems
  • Encrypted Credentials: Fernet encryption for secure credential storage

Quality Assurance

The integration has been thoroughly tested:

  • 80 total tests covering the entire integration
  • 51 unit tests for OdooService and Celery tasks
  • 29 integration tests for schema validation
  • Coverage includes encryption, connections, transformations, and async operations

Connection Configuration

Prerequisites

Before configuring the integration, ensure you have:

  • Odoo instance URL (e.g., https://yourcompany.odoo.com)
  • Odoo database name
  • User credentials (email and password or API key)
  • User with appropriate permissions (Sales/Inventory/Product access)

Configuration Steps

  1. Navigate to Odoo Sync > Configuration
  2. Enter your connection details:
{
  "name": "Production Odoo",
  "odoo_url": "https://yourcompany.odoo.com",
  "odoo_db": "your_database_name",
  "odoo_username": "integration@company.com",
  "odoo_password": "your_api_key_or_password"
}
  1. Click Test Connection to verify

Credential Security

Passwords are encrypted using Fernet symmetric encryption before storage. The encryption key is derived from your application's SECRET_KEY.

Testing the Connection

The test connection endpoint verifies:

  • Network connectivity to the Odoo URL
  • XML-RPC authentication
  • Database accessibility
  • API permissions
POST /api/v1/odoo/test-connection

Response:
{
  "success": true,
  "message": "Connection successful",
  "odoo_version": "17.0",
  "user_id": 42,
  "database": "production_db"
}

Field Mapping

Field mappings define how product data is transformed between Products Manager and Odoo.

Default Field Mappings

Local FieldOdoo FieldTypeRequiredNotes
titlenamedirectYesProduct name
eanbarcodedirectYesEAN/UPC code
descriptiondescription_saledirectNoSales description
pricelist_pricetransformNoSelling price
weightweightdirectNoWeight in kg
brand_namex_brandcustomNoCustom brand field
categorycateg_idtransformNoCategory mapping
image_urlimage_1920transformNoProduct image

Mapping Types

  • direct: Value copied as-is between systems
  • transform: Value converted using a transformation function
  • custom: Special handling for custom Odoo fields

Creating Custom Mappings

Navigate to Odoo Sync > Mappings to configure field mappings:

{
  "local_field": "supplier_reference",
  "odoo_field": "default_code",
  "odoo_model": "product.template",
  "mapping_type": "direct",
  "is_bidirectional": true,
  "is_required": false,
  "is_active": true,
  "priority": 10
}

Category Mapping

Map Products Manager categories to Odoo category IDs:

Products Manager CategoryOdoo Category IDOdoo Path
Electronics5All / Saleable / Electronics
Clothing12All / Saleable / Clothing
Accessories18All / Saleable / Accessories

Tax Mapping

Configure tax rate correspondences between systems for accurate pricing synchronization.


Bidirectional Sync

Export to Odoo

Push products from Products Manager to your Odoo instance.

Single Product Sync

POST /api/v1/odoo/sync/{product_id}

Request Body:
{
  "force_update": false,
  "sync_images": true
}

Response:
{
  "success": true,
  "odoo_product_id": 1547,
  "fields_synced": ["name", "barcode", "list_price", "description_sale"],
  "duration_ms": 342
}

Bulk Export

Export multiple products with filters:

POST /api/v1/odoo/bulk-sync

Request Body:
{
  "filters": {
    "supplier_id": 15,
    "has_ean": true,
    "modified_since": "2025-01-01T00:00:00Z"
  },
  "batch_size": 100,
  "sync_images": true
}

Response:
{
  "success": true,
  "batch_id": "sync_20251216_143022",
  "products_queued": 250,
  "estimated_duration_minutes": 5
}

Import from Odoo

Pull products from Odoo into Products Manager.

POST /api/v1/odoo/import

Request Body:
{
  "odoo_filters": {
    "categ_id": [5, 12],
    "active": true
  },
  "create_missing": true,
  "update_existing": true,
  "batch_size": 50
}

Response:
{
  "success": true,
  "batch_id": "import_20251216_150033",
  "products_found": 423,
  "message": "Import queued for processing"
}

Sync Direction Options

  • to_odoo: Export from Products Manager to Odoo
  • from_odoo: Import from Odoo to Products Manager
  • bidirectional: Full two-way synchronization (requires conflict resolution)

Scheduled Syncs with Cron

Automate your synchronization with scheduled tasks using cron expressions.

Creating a Schedule

Navigate to Odoo Sync > Schedules or use the API:

POST /api/v1/odoo/schedules

Request Body:
{
  "name": "Daily Product Export",
  "description": "Export all modified products to Odoo every morning",
  "cron_expression": "0 6 * * *",
  "sync_direction": "to_odoo",
  "sync_type": "incremental",
  "filters": {
    "modified_today": true
  },
  "batch_size": 100,
  "is_enabled": true
}

Cron Expression Examples

ScheduleCron ExpressionDescription
Every morning at 6 AM0 6 * * *Daily sync before business hours
Every 4 hours0 */4 * * *Regular updates throughout day
Monday mornings0 7 * * 1Weekly sync at week start
Every 30 minutes*/30 * * * *Near real-time sync

Schedule Management

# Toggle schedule on/off
PATCH /api/v1/odoo/schedules/{id}/toggle

# Run schedule immediately
POST /api/v1/odoo/schedules/{id}/run

# Update schedule settings
PUT /api/v1/odoo/schedules/{id}
{
  "cron_expression": "0 8 * * *",
  "batch_size": 200
}

# Delete schedule
DELETE /api/v1/odoo/schedules/{id}

Celery Worker Configuration

Schedules are processed by Celery workers with the following configuration:

# Beat schedule checks every 5 minutes
"check-scheduled-odoo-syncs": {
    "task": "api.services.odoo_tasks.process_scheduled_odoo_syncs",
    "schedule": 300.0,  # 5 minutes
}

# Dedicated queue for Odoo operations
Queue("odoo", Exchange("odoo"), routing_key="odoo.*")

Sync History and Logs

Every synchronization operation is logged for audit and troubleshooting.

Viewing Sync History

Navigate to Odoo Sync > History to view:

  • Recent sync operations with status
  • Success/failure counts
  • Detailed error messages
  • Sync duration metrics

Log Entry Structure

{
  "id": 15842,
  "product_id": "uuid-of-product",
  "odoo_product_id": 1547,
  "sync_direction": "to_odoo",
  "sync_type": "create",
  "sync_status": "success",
  "fields_synced": ["name", "barcode", "list_price"],
  "duration_ms": 342,
  "started_at": "2025-12-16T14:30:22Z",
  "completed_at": "2025-12-16T14:30:22Z",
  "triggered_by": "schedule",
  "schedule_id": 3,
  "batch_id": "sync_20251216_143022"
}

Sync Statistics

GET /api/v1/odoo/stats

Response:
{
  "total_syncs": 15842,
  "successful_syncs": 15623,
  "failed_syncs": 219,
  "success_rate": 98.62,
  "avg_duration_ms": 285,
  "last_sync_at": "2025-12-16T14:30:22Z",
  "products_with_odoo_id": 8472
}

Error Handling

Failed syncs include detailed error information:

{
  "sync_status": "error",
  "error_message": "Field 'barcode' must be unique",
  "error_details": {
    "odoo_error_code": "UNIQUE_VIOLATION",
    "field": "barcode",
    "value": "3700123456789",
    "existing_product_id": 892
  }
}

Features for handling errors:

  • Bulk Retry: Retry all failed syncs from a batch
  • Error Details Modal: View full error context
  • Automatic Retry: Transient failures retried automatically

API Reference

Configuration Endpoints

MethodEndpointDescription
GET/api/v1/odoo/configGet current configuration
PUT/api/v1/odoo/configUpdate configuration
POST/api/v1/odoo/test-connectionTest Odoo connection
GET/api/v1/odoo/statusGet connection status

Sync Operations

MethodEndpointDescription
POST/api/v1/odoo/sync/{product_id}Sync single product
POST/api/v1/odoo/bulk-syncBulk sync with filters
POST/api/v1/odoo/importImport from Odoo

Field Mappings

MethodEndpointDescription
GET/api/v1/odoo/field-mappingsList all mappings
POST/api/v1/odoo/field-mappingsCreate/update mapping
DELETE/api/v1/odoo/field-mappings/{id}Delete mapping
GET/api/v1/odoo/odoo-fieldsGet Odoo model fields

Schedules

MethodEndpointDescription
GET/api/v1/odoo/schedulesList schedules
POST/api/v1/odoo/schedulesCreate schedule
PUT/api/v1/odoo/schedules/{id}Update schedule
DELETE/api/v1/odoo/schedules/{id}Delete schedule
PATCH/api/v1/odoo/schedules/{id}/toggleToggle enabled
POST/api/v1/odoo/schedules/{id}/runRun immediately

Logs & Statistics

MethodEndpointDescription
GET/api/v1/odoo/logsList sync logs
GET/api/v1/odoo/statsGet sync statistics

Security

Credential Protection

  • Fernet Encryption: Passwords encrypted with 32-byte key from SECRET_KEY
  • No Plain Text Storage: Credentials never stored in clear text
  • Secure Transmission: All API calls use HTTPS/TLS

Permission Requirements

Access to Odoo configuration requires:

  • Permission.MANAGE_SETTINGS for configuration changes
  • Standard authentication for sync operations

Audit Logging

All operations logged with:

  • User context (who triggered the sync)
  • Timestamps (when it occurred)
  • Full operation details (what was synced)

Known Limitations

Current Limitations

  • Single Instance: Only one Odoo configuration supported per deployment
  • No Real-time Updates: UI requires manual refresh after syncs
  • Last Write Wins: No conflict resolution for bidirectional sync
  • Basic Transformations: Limited field type transformations
  • No Image Compression: Images sent to Odoo as-is

Unsupported Features

  • Multi-company Odoo configurations
  • Manufacturing/MRP bill of materials
  • Variant synchronization (roadmap)
  • Stock level sync (roadmap)
  • Real-time WebSocket updates (roadmap)

Troubleshooting

Connection Issues

Error: "Access Denied"

  • Verify username and password/API key
  • Check user has XML-RPC access enabled
  • Confirm user is active in Odoo

Error: "Database not found"

  • Verify exact database name (case-sensitive)
  • Check Odoo URL is correct (no trailing slash)

Sync Failures

Error: "Unique constraint violation"

  • Product with same barcode already exists in Odoo
  • Check existing products before sync

Error: "Required field missing"

  • Verify all required field mappings are configured
  • Check product has required data (e.g., title, EAN)

Performance Issues

For large catalogs (1000+ products):

  • Use incremental sync instead of full sync
  • Increase batch_size to reduce API calls
  • Schedule syncs during off-peak hours

Next Steps