Enable Dark Mode!
practical-guide-to-odoo-models-fields-and-domains-for-mobo-developers.jpg
By: Muhammed Shehzad K

Practical Guide to Odoo Models, Fields, and Domains for Mobo Developers

Technical Flutter mobo

If you're a Flutter developer looking to build mobile applications with Odoo as your backend, understanding Models, Fields, and Domains is essential. These three concepts form the foundation of how you'll query, filter, and manipulate data from your Odoo server.

This guide will walk you through each concept with clear explanations and practical examples using the odoo_rpc package for Flutter.

What is Odoo?

Odoo is an open-source ERP (Enterprise Resource Planning) system that provides a suite of business applications, including CRM, Sales, Inventory, Accounting, and more. For mobile developers, Odoo serves as a powerful backend that:

  • Provides pre-built business logic and data models
  • Offers a JSON-RPC API for external integration
  • Handles complex business workflows out of the box
  • Supports multi-user, role-based access control

Instead of building your own backend from scratch, you can leverage Odoo's existing infrastructure and focus on creating a great mobile experience.

Prerequisites

Before diving into this guide, you should have:

  • Basic Flutter/Dart knowledge
  • Access to an Odoo instance (self-hosted or cloud)
  • Odoo login credentials (database name, username, password)
  • The odoo_rpc package added to your Flutter project

Add the package to your pubspec.yaml:

dependencies:  odoo_rpc: ^0.4.3

Core Concepts

1. Odoo Models - The Data Blueprints

In Odoo, a Model is essentially a database table that represents a business entity. Think of it as a blueprint for storing structured data.

Common Odoo Models:

  • res.partner - Customers, vendors, contacts
  • product.product - Products in inventory
  • sale.order - Sales orders
  • stock.picking - Warehouse transfers/deliveries
  • account.move - Invoices and journal entries

Each model has a technical name (like res.partner) that you'll use when querying data from your Flutter app.

2. Fields - The Data Attributes

Fields are the columns in a model—they define what data each record stores. When querying Odoo, you specify which fields to retrieve to optimize performance.

Basic Field Types:

  • Char - Text strings (e.g., name, email)
  • Integer/Float - Numbers (e.g., quantity, price)
  • Boolean - True/false values (e.g., active, is_company)
  • Date/Datetime - Timestamps (e.g., create_date, date_order)
  • Selection - Dropdown values (e.g., state: draft, confirmed, done)

Relational Fields:

  • Many2one - Foreign key to another record (e.g., partner_id links to a customer)
  • One2many - Reverse relationship (e.g., order_line contains multiple sale order lines)
  • Many2many - Multiple relationships (e.g., category_id can have multiple tags)

Important: Many2one fields return [id, 'name'] by default (e.g., [42, 'John Doe']).

3. Domains - The Query Filters

Domains are Odoo's powerful filtering mechanism. They let you specify which records to retrieve from a model—think of them as the WHERE clause in SQL.

A domain is a list of conditions written in Polish notation (prefix notation). Each condition is a tuple: ['field', 'operator', value].

Common Domain Operators:

  • = - Equals
  • != - Not equals
  • >, >=, <, <= - Comparison operators
  • in - Value is in list
  • not in - Value is not in list
  • like - Pattern matching (case-insensitive, use % as wildcard)
  • ilike - Case-insensitive like
  • =? - Unset or equals (useful for optional filters)

Domain Examples:

// Single condition: find active partners
[['active', '=', true]]
// Multiple conditions (implicit AND): customers in California
[['customer_rank', '>', 0], ['state_id.name', '=', 'California']]
// OR logic: partners from USA or Canada
['|', ['country_id.code', '=', 'US'], ['country_id.code', '=', 'CA']]
// Search by name pattern
[['name', 'ilike', '%john%']]

Logical Operators:

  • & - AND (implicit between consecutive conditions)
  • | - OR
  • ! - NOT

Complex Example: Find active customers from USA with credit limit > 1000 OR VIP status:

[  '&', '&',  ['active', '=', true],  ['customer_rank', '>', 0],  ['country_id.code', '=', 'US'],  '|',  ['credit_limit', '>', 1000],  ['property_payment_term_id.name', '=', 'VIP']]

Real-World Flutter Example

Let's build a practical example: a customer search screen that demonstrates model selection, domain filtering, and field selection using the odoo_rpc package.

Step 1: Initialize Odoo Connection

import 'package:odoo_rpc/odoo_rpc.dart';
class OdooService {
  static OdooClient? _client;
  static Future<void> initialize() async {
    _client = OdooClient('https://your-odoo-instance.com');
    try {
      await _client!.authenticate(
        'your_database',
        'username',
        'password',
      );
    } catch (e) {
      print('Authentication failed: $e');
    }
  }
  static OdooClient get client => _client!;
}

Step 2: Create a Customer Search Function

Future<List<Map<String, dynamic>>> searchCustomers({
  String? searchTerm,
  bool onlyActive = true,
  String? countryCode,
}) async {

  // 1. BUILD DOMAIN (filtering logic)

  List<dynamic> domain = [];
  // Filter only customers (not suppliers)
  domain.add(['customer_rank', '>', 0]);
  // Filter by active status
  if (onlyActive) {
    domain.add(['active', '=', true]);
  }
  // Search by name, email, or phone
  if (searchTerm != null && searchTerm.isNotEmpty) {
    domain.addAll([
      '|', '|',  // OR operator for 3 conditions
      ['name', 'ilike', '%$searchTerm%'],
      ['email', 'ilike', '%$searchTerm%'],
      ['phone', 'ilike', '%$searchTerm%'],
    ]);
  }
  // Filter by country using relational field
  if (countryCode != null) {
    domain.add(['country_id.code', '=', countryCode]);
  }

// 2. DEFINE FIELDS TO RETRIEVE

// Only fetch what you need for better performance
  final fields = [
    'id',           // Record ID
    'name',         // Customer name
    'email',        // Email address
    'phone',        // Phone number
    'mobile',       // Mobile number
    'street',       // Address
    'city',
    'country_id',   // Many2one: returns [id, 'Country Name']
    'image_128',    // Small profile image (base64)
  ];

// 3. EXECUTE SEARCH ON THE MODEL

try {
    final result = await OdooService.client.callKw({
      'model': 'res.partner',  // The Odoo model
      'method': 'search_read', // Method to call
      'args': [domain],        // Our domain filters
      'kwargs': {
        'fields': fields,      // Fields to retrieve
        'limit': 50,           // Maximum records
        'order': 'name ASC',   // Sort by name
      },
    });
    // Return list of customer records
    return List<Map<String, dynamic>>.from(result);
  } catch (e) {
    print('Error searching customers: $e');
    return [];
  }
}

Step 3: Use in Your Flutter Widget

class CustomerSearchScreen extends StatefulWidget {
  @override
  _CustomerSearchScreenState createState() => _CustomerSearchScreenState();
}
class _CustomerSearchScreenState extends State<CustomerSearchScreen> {
  List<Map<String, dynamic>> customers = [];
  bool isLoading = false;
  String searchQuery = '';
  Future<void> performSearch() async {
    setState(() => isLoading = true);
    final results = await searchCustomers(
      searchTerm: searchQuery.isEmpty ? null : searchQuery,
      onlyActive: true,
      countryCode: 'US', // Optional: filter by country
    );
    setState(() {
      customers = results;
      isLoading = false;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Customer Search')),
      body: Column(
        children: [
          Padding(
            padding: EdgeInsets.all(16),
            child: TextField(
              decoration: InputDecoration(
                hintText: 'Search customers...',
                suffixIcon: IconButton(
                  icon: Icon(Icons.search),
                  onPressed: performSearch,
                ),
              ),
              onChanged: (value) => searchQuery = value,
            ),
          ),
          Expanded(
            child: isLoading
                ? Center(child: CircularProgressIndicator())
                : ListView.builder(
                    itemCount: customers.length,
                    itemBuilder: (context, index) {
                      final customer = customers[index];
                      return ListTile(
                        title: Text(customer['name'] ?? 'Unknown'),
                        subtitle: Text(
                          '${customer['email'] ?? ''} | ${customer['phone'] ?? ''}',
                        ),
                        trailing: Text(
                          // Many2one field returns [id, 'name']
                          customer['country_id'] != null
                              ? customer['country_id'][1]
                              : '',
                        ),
                      );
                    },
                  ),
          ),
        ],
      ),
    );
  }
}

Key Takeaways

  • Models define the data structure (e.g., res.partner for customers)
  • Fields specify which attributes to retrieve (optimize by fetching only what you need)
  • Domains filter records server-side using operators like =, ilike, and >
  • Many2one fields return [id, name] tuples
  • Use search_read for efficient queries that combine searching and reading in one call
  • Always handle errors gracefully when making RPC calls

Next Steps

Now that you understand the basics, you can:

  • Explore other Odoo models like sale.order, product.product, and stock.picking
  • Learn about creating and updating records using create and write methods
  • Implement pagination for large datasets using limit and offset
  • Build complex domains with nested AND/OR logic
  • Study Odoo's API documentation to discover available models and methods

Understanding models, fields, and domains is fundamental to building effective Mobo applications with Odoo as your backend. These concepts allow you to query exactly the data you need, filter results server-side for performance, and work with Odoo's rich business logic.

With this foundation, you're ready to build powerful, data-driven mobile applications that leverage Odoo's comprehensive ERP capabilities.

To read more about How to Integrate RESTful APIs in Flutter Applications, refer to our blog How to Integrate RESTful APIs in Flutter Applications.


If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, KINFRA Techno Park
Kakkanchery, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message