Skip to content

Latest commit

 

History

History
467 lines (368 loc) · 12.1 KB

File metadata and controls

467 lines (368 loc) · 12.1 KB

odoo_model_generator

pub version Dart SDK License Test Coverage

Ultra-pro Dart package for automating Odoo module generation.
Turn a clean Dart API into production-ready models.py, __manifest__.py, views.xml, and security/ir.model.access.csv — in milliseconds.


image

Table of Contents

  1. Why odoo_model_generator?
  2. Installation
  3. Quick Start
  4. API Reference
  5. CLI Tool (oomg)
  6. Generated File Structure
  7. Examples
  8. Testing
  9. Licensing & Pricing
  10. Support

Why?

Every Odoo Partner repeats the same tedious cycle for every custom module:

  1. Write models.py field by field — Char, Many2one, Selection
  2. Create __manifest__.py with correct dependencies
  3. Build form/tree/search views in XML
  4. Add security CSV rows
  5. Wire everything up with __init__.py

odoo_model_generator automates 100% of steps 1–5.

Metric Without With
Simple 10-field model ~2 hours < 1 minute
Complex 30-field model ~1 day < 5 minutes
Human error rate High Zero (validated)

Installation

Add to pubspec.yaml:

dependencies:
  odoo_model_generator: ^2.0.0
dart pub get

For CLI usage, activate globally:

dart pub global activate odoo_model_generator
oomg version

Quick Start

import 'package:odoo_model_generator/odoo_model_generator.dart';

Future<void> main() async {
  await OdooModel('x_product_custom')
      .field(const NameField())
      .field(const Many2one('supplier_id', relation: 'res.partner'))
      .field(const Float('price', digits: (10, 2)))
      .field(const Integer('quantity'))
      .field(const Text('description'))
      .generate(outputPath: './my_module');
}

This generates:

my_module/
├── __init__.py
├── __manifest__.py
├── models/
│   ├── __init__.py
│   └── x_product_custom.py
├── views/
│   └── x_product_custom_view.xml
├── security/
│   └── ir.model.access.csv
├── data/
├── static/
│   └── description/
├── wizards/
├── reports/
└── controllers/

API Reference

OdooModel

The primary fluent builder. All methods return this for chaining.

OdooModel(
  String modelName,          // e.g. 'x_invoice_system'
  {
    String? docstring,       // _description
    String stringField,      // _rec_name (default: 'name')
    bool createTimestamp,    // add shadow timestamp fields
    bool createSequence,     // add sequence integer + auto-assign
    String? order,           // _order value
  }
)
Method Description
.field(OdooField) Add a field
.inherit(String) Add a mixin parent (mail.thread, etc.)
.dependency(String) Add a module dependency
.onchange(OnchangeDefinition) Register an onchange stub
.constraint(ConstraintDefinition) Register a Python constraint
.compute(ComputeDefinition) Register a compute method body
.sqlConstraint(id, expr, msg) Add a _sql_constraints entry
.generate(...) Validate and write all files

Field Types

Dart class Odoo Python type Notes
NameField() fields.Char required=True, convenience shortcut
Char(name) fields.Char size, translate options
Text(name) fields.Text Renders nolabel="1" in form
Html(name) fields.Html sanitize option
Integer(name) fields.Integer
Float(name) fields.Float digits: (10, 2)
Monetary(name) fields.Monetary currencyField option
Boolean(name) fields.Boolean
Date(name) fields.Date
Datetime(name) fields.Datetime
Binary(name) fields.Binary attachment option
Image(name) fields.Image maxWidth, maxHeight
Selection(name, options) fields.Selection rawOptions for custom labels
Many2one(name, relation: ...) fields.Many2one ondelete, domain, onchange
One2many(name, relation: ..., inverseField: ...) fields.One2many
Many2many(name, relation: ...) fields.Many2many relationTable, column1/2
ComputedField(name, computeMethod: ...) Any computed field store, depends, fieldType
Reference(name, allowedModels: [...]) fields.Reference

All fields accept:

const MyField(
  'field_name',
  string: 'Human Label',       // optional, auto-generated if omitted
  required: true,
  defaultValue: 'default',
  help: 'Tooltip text',
  inTree: true,                // appear in tree view
  inSearch: true,              // appear in search view
  readonly: false,
  cssClass: 'oe_inline',
  extra: {'tracking': '1'},    // arbitrary extra Python kwargs
)

GeneratorConfig

const GeneratorConfig({
  String version = '1.0.0',
  String author = 'Your Company',
  String website = 'https://yourcompany.com',
  String license = 'LGPL-3',
  String category = 'Custom',
  bool isApplication = false,
  bool openFolder = false,
  bool generateModelsInit = true,
  bool generateSecurity = true,
  bool generateDemoStub = false,
  List<String> extraDependencies = const [],
})

OdooGenerator — Dry Run

Preview the generated content WITHOUT writing to disk:

final gen = OdooGenerator(model);
final files = gen.dryRun();  // Map<String, String>

for (final entry in files.entries) {
  print('${entry.key}:\n${entry.value}\n');
}

ParallelGenerator

Generate multiple models concurrently:

final result = await ParallelGenerator(
  config: config,
  concurrency: 4,        // max simultaneous tasks; null = unlimited
).generateAll(
  [model1, model2, model3],
  outputPath: './output',
);

print('Generated: ${result.successful.length}');
print('Failed   : ${result.failed.length}');
print('Files    : ${result.totalFiles}');

ModuleExporter

Package a generated module directory into a ZIP or TAR archive:

final exporter = ModuleExporter();

await exporter.export(
  './output/x_my_module',
  outputFile: './dist/x_my_module_v16.zip',
  format: ExportFormat.zip,  // or ExportFormat.tar
);

Advanced Features

Computed fields with method bodies

OdooModel('x_order')
  .field(const Float('price'))
  .field(const Integer('qty'))
  .field(const ComputedField(
    'total',
    computeMethod: '_compute_total',
    store: true,
    depends: ['price', 'qty'],
    fieldType: 'Float',
    digits: (14, 2),
  ))
  .compute(const ComputeDefinition(
    methodName: '_compute_total',
    dependsOn: ['price', 'qty'],
    bodyLines: [
      'for record in self:',
      '    record.total = record.price * record.qty',
    ],
  ))

Onchange methods

  .onchange(const OnchangeDefinition(
    triggerFields: ['partner_id'],
    methodName: '_onchange_partner_id',
    bodyLines: [
      'if self.partner_id:',
      '    self.currency_id = self.partner_id.property_purchase_currency_id',
    ],
  ))

Python constraints

  .constraint(const ConstraintDefinition(
    constrainedFields: ['amount'],
    methodName: '_check_amount_positive',
    errorMessage: 'Amount must be positive',
    bodyLines: [
      'for r in self:',
      '    if r.amount <= 0:',
      '        raise ValidationError("Amount must be positive")',
    ],
  ))

SQL constraints

  .sqlConstraint(
    'unique_code_company',
    'UNIQUE(code, company_id)',
    'Code must be unique per company',
  )

CLI Tool (oomg)

Usage: oomg <command> [options]

Commands:
  generate   Generate a full Odoo module
  validate   Validate a model without generating files
  dry-run    Preview generated content (no files written)
  export     Package a module directory into a ZIP archive
  version    Print version

Options for generate / dry-run:
  -s, --schema     Path to JSON schema file
  -m, --model      Odoo model name (e.g. x_product_custom)
  -o, --output     Output directory (default: ./generated)
      --open       Open the output folder after generation
  -v, --verbose    Verbose logging
      --author     Author name in manifest
      --version    Module version
      --license    License identifier
      --no-security  Skip ir.model.access.csv
      --demo         Generate data/demo.xml stub

JSON Schema format

{
  "modelName": "x_product_custom",
  "docstring": "Custom Product",
  "stringField": "name",
  "dependencies": ["sale", "stock"],
  "inherits": ["mail.thread"],
  "fields": [
    { "type": "Char",     "name": "name",        "required": true, "inTree": true },
    { "type": "Float",    "name": "price",        "digits": [10, 2] },
    { "type": "Integer",  "name": "quantity",     "inTree": true },
    { "type": "Many2one", "name": "supplier_id",  "relation": "res.partner" },
    { "type": "Selection","name": "state",
      "options": ["draft", "confirmed", "done"], "defaultValue": "draft" }
  ]
}
# Generate from schema
oomg generate --schema product.json --output ./modules/x_product

# Quick dry-run preview
oomg dry-run --model x_test_model --file models

# Validate only
oomg validate --schema product.json

# Export to ZIP
oomg export --module ./modules/x_product --zip ./dist/product.zip

Generated File Structure

<output_path>/
├── __init__.py                          # from . import models
├── __manifest__.py                      # Module metadata & dependencies
├── models/
│   ├── __init__.py                      # from . import <model_name>
│   └── <model_name>.py                  # Class definition + fields + methods
├── views/
│   └── <model_name>_view.xml            # Form + Tree + Search + Action + Menu
├── security/
│   └── ir.model.access.csv              # User + Manager access rows
├── data/
│   └── demo.xml                         # (optional) demo data stub
├── static/description/
├── wizards/
├── reports/
└── controllers/

Examples

File Description
example/simple_model.dart Minimal 5-field model
example/complex_model.dart Full invoice model with all features
example/with_parallel.dart 5-model ERP suite in parallel
example/dry_run_preview.dart Preview without writing files
example/with_export.dart Generate + export to ZIP

Testing

# Run all tests
dart test

# Run with coverage
dart test --coverage=coverage
dart pub global run coverage:format_coverage \
  --lcov --in=coverage --out=coverage/lcov.info --report-on=lib

# Run a specific test file
dart test test/integration_test.dart -v

Test coverage target: > 95%


Licensing & Pricing

Plan Price Seats Support
Developer $500 / company 1 developer Email
Team $1,000 / company 5 developers Priority email
Enterprise Custom Unlimited 24/7 dedicated
Trial Free 1 developer Community

The trial is limited to models with ≤ 5 fields.


Support

  • 🐛 Issues: github.com/Brah-Timo/odoo_model_generator/issues

Generated by TIMSoftDZ odoo_model_generator v2.0.0 — © 2026 Odoo Generator LLC. All rights reserved.