OdooWiki OCA HUB
Uncategorised License: LGPL-3

Base EDI backend.

Provides following models:

  • EDI Backend, to centralize configuration
  • EDI Backend Type, to classify EDI backends (eg: UBL, GS1, e-invoice, pick-yours)
  • EDI Exchange Type, to define file types of exchange
  • EDI Exchange Record, to define a record exchanged between systems

Also define a mixin to be inherited by records that will generate EDIs.

In addition, the module ships an edi.configuration mechanism that lets users react to EDI events declaratively, by writing small Python snippets attached to event triggers. This can be used as a lightweight alternative to component event listeners: configurations can react globally (on any exchange) or be scoped to a specific partner (or any related record), exchange type, backend and target model. See CONFIGURE.md for details.

auto_awesome What this module does

AI-generated from the code · Odoo 19.0

This module provides the foundation for exchanging electronic documents (EDI) with external systems: it lets you configure backends, exchange types and exchange records, and automate generating, sending, receiving and processing files.

This module is the technical backbone for electronic data interchange in Odoo. It does not create business documents itself; instead it gives you the screens and rules to configure how files are exchanged with external systems.

What users can set up: - EDI Backends: each backend represents a connection/channel, classified by a Backend Type (for example UBL, GS1 or e-invoice). A backend can belong to a company and can automatically archive or delete old exchange records after a number of days. - Exchange Types: define the kind of file exchanged, its direction (incoming or outgoing), the file name pattern and extension, whether the file is generated automatically, and which handler models perform each step (generate, send, receive, process, check). - Exchange Records: the actual files exchanged, linked to a business record, with a state, an error message and a traceback when something fails.

Automatic behaviour: - Scheduled jobs look for outgoing records that still need a file and generate/send them, and look for incoming records to receive and process. - Other scheduled jobs archive and delete old exchange records according to the backend settings. - Errors are recorded on the exchange record and can trigger notifications.

Where it appears: - Menus and views for backends, backend types, exchange types, exchange records and configurations. - A reusable block of buttons is added to forms of models that support EDI, so users can create an exchange record from a document. - A wizard lets users create an exchange record manually when no backend is preconfigured.

It also adds a configuration mechanism where small code snippets react to EDI events, globally or scoped to a partner, exchange type, backend or model, plus hourly and daily triggers.

Depends on

base_edimailbase_sparse_field

Menus it adds

ExchangesRecentFailedPendingInboundOutboundAllConfigBackendsBackend typesExchange typesExchange type rulesConfigurations
Models and fields (20)
  • ir.model · extends an existing modelis_edi_sender, is_edi_checker, is_edi_receiver, is_edi_generator, is_edi_processor, is_edi_input_validator, is_edi_output_validator
  • edi.backend · new modelname, active, company_id (Company), backend_type_id (EDI Backend type), backend_type_code, output_sent_processed_auto, auto_delete_records_after_days (Auto-delete archived records after (days)), auto_archive_records_after_days (Auto-archive records after (days))
  • edi.id.mixin · new modeledi_id (EDI ID)
  • edi.backend.type · new modelcode, name
  • edi.configuration · new modelname, active, trigger, type_id (Exchange Type), model_id (Model), is_global (Global Configuration), backend_id, model_name (Model tech name), snippet_do, trigger_id, description, snippet_before_do
  • edi.exchange.type · new modelcode, name, active, encoding, rule_ids, direction, backend_id (Backend), quick_exec (Quick execution), ack_type_id (Ack exchange type), partner_ids (Enabled for partners), send_model_id (Sender), check_model_id (Checker), backend_type_id (Backend type), ack_for_type_ids (Ack for exchange type), process_model_id (Processor), receive_model_id (Receiver), exchange_file_ext, generate_model_id (Generator), exchange_record_ids, exchange_record_count (# Exchange Records), advanced_settings_edit (Advanced YAML settings), input_validate_model_id (Input Validator), output_validate_model_id (Output Validator), encoding_in_error_handler (Decoding Error Handler), exchange_filename_pattern, encoding_out_error_handler (Encoding Error Handler), exchange_file_auto_generate, allow_empty_files_on_receive (Allow Empty Files), exchange_filename_sequence_id
  • edi.exchange.record · new modelmodel, active, res_id (Record), type_id (Exchange type), direction, parent_id, retryable, backend_id, company_id (Company), identifier, ack_expected, exchanged_on, related_name, exchange_file, exchange_error (Exchange error), ack_exchange_id (ACK exchange), ack_received_on (ACK received on), exchange_filename, edi_exchange_state (Exchange state), related_record_ids (Related records), external_identifier, exchange_file_frozen, related_exchange_ids (Related exchanges), exchange_filechecksum, related_record_exists, exchange_error_traceback (Exchange error traceback)
  • edi.oca.handler.noop · new model
  • edi.oca.handler.send · new model
  • edi.oca.handler.check · new model
  • edi.exchange.type.rule · new modelkind, name, model (Model code), active, type_id, model_id, enable_domain (Enable on domain), enable_snippet (Enable on snippet), form_btn_label (Form button label), form_btn_tooltip (Form button tooltip)
  • edi.oca.handler.process · new model
  • edi.oca.handler.receive · new model
  • edi.oca.handler.generate · new model
  • edi.configuration.trigger · new modelcode, name, active, model_id, description
  • edi.exchange.consumer.mixin · new modeledi_disable_auto (Disable auto), edi_has_form_config, exchange_record_ids, exchange_record_count, origin_exchange_type_id (EDI origin exchange type), origin_exchange_record_id (EDI origin record), exchange_related_record_ids
  • edi.exchange.related.record · new modelmodel, res_id (Record), exchange_record_id
  • edi.exchange.record.create.wiz · new modelmodel, res_id, backend_id, backend_type_id, exchange_type_id
  • edi.oca.handler.input.validate · new model
  • edi.oca.handler.output.validate · new model

Text generated by AI (DeepSeek) from reading the Odoo 19.0 code on GitHub; it may contain mistakes, so check the code before deciding. The module is very large and only part of the code was read. View the code on GitHub

Availability by version

Reviewed: 2026-11-03
Confirmed (verified in repository and branch) Estimated (unverified) No information

Confirmation status: 2 confirmed, 7 with no information of 9 versions.

Sources · Odoo 19.0

Confirmed on 2026-11-03 in branch 19.0 of OCA/edi-framework.

terminal Installation and usage

OCA documentation · Odoo 19.0

This module aims to provide an infrastructure to simplify interchangability of documents between systems providing a configuration platform. It will be inherited by other modules in order to define the proper implementations of components.

In order to define a new Exchange Record, we need to configure:

  • Backend Type
  • Exchange Type
  • Backend
  • Components

Jobs

  • Internal User: might be an EDI user without even knowing about it, triggering EDI flows by some of his actions on business records; does not need access to related queue jobs.
  • EDI User: more conscious EDI user that might sometimes need to debug things a bit further and thus needs access to related queue jobs.
  • EDI Manager: full configuration access.

Code to execute

By default, EDI Framework uses fields on edi.backend to get the right function to execute. Each function is related to a model where the specific function is defined. This models needs to inherit the specific handler of each case.

  • receive: model edi.oca.handler.receive with function receive.
  • process: model edi.oca.handler.process with function process.
  • generate: model edi.oca.handler.generate with function generate.
  • send: model edi.oca.handler.send with function send.
  • check: model edi.oca.handler.check with function check.
  • validate on inputs: model edi.oca.handler.input.validate with function input_validate.
  • validate on outputs: model edi.oca.handler.output.validate with function input_validate.

You can see an example on the tests fake_models.

For a more complex behaviour, you can use edi_component_oca module to use components.

User EDI generation

On the exchange type, it might be possible to define a set of models, a domain and a snippet of code. After defining this fields, we will automatically see buttons on the view to generate the exchange records. This configuration is useful to define a way of generation managed by user.

Exchange type rules configuration

Exchange types can be further configured with rules. You can use rules to:

  • make buttons automatically appear in forms
  • define your own custom logic

Go to an exchange type and go to the tab "Model rules". There you can add one or more rule, one per model. On each rule you can define a domain or a snippet to activate it. In case of a "Form button" kind, if the domain and/ the snippet is/are satisfied, a form btn will appear on the top of the form. This button can be used by the end user to manually generate an exchange. If there's more than a backend and the exchange type has not a backend set, a wizard will appear asking to select a backend to be used for the exchange.

In case of "Custom" kind, you'll have to define your own logic to do something.

Custom event handlers via edi.configuration

The framework can dispatch EDI lifecycle events to user-defined configurations, providing a declarative alternative to component events. Each edi.configuration record links a trigger (an edi.configuration.trigger code) to a snippet (snippet_do) that is executed every time the matching event fires on an exchange record.

Built-in events fired by EDIExchangeRecord include:

  • on_edi_exchange_done — exchange processed successfully
  • on_edi_exchange_error — exchange ended in error
  • on_edi_exchange_done_ack_received — ACK file received
  • on_edi_exchange_done_ack_missing — expected ACK not received
  • on_edi_exchange_done_ack_received_error — ACK received with errors
  • on_edi_exchange_<action>_complete — generic action completion (e.g. generate_complete, send_complete), fired once on the exchange record and once on its related record when present

The snippet receives at least two variables in its evaluation context:

  • conf — the current edi.configuration record
  • record — the target of the event (either the edi.exchange.record itself or its related business record)

Plus the standard edi_exec_snippet_do extras (operation, edi_action, old_value, vals, ...).

Triggers can also be fired by a scheduled action instead of by an exchange. Add an edi.configuration.trigger with a code of your own, then a scheduled action on edi.configuration running model._cron_run_by_trigger("your_code") on whatever period you need. No such trigger ships as data, since the periods a database needs are its own; the demo data has an hourly and a daily one to copy from.

A scheduled trigger has no originating record, so its configurations run on the records linked to them, or once when they are global.

Two complementary lookup modes are available, and they can be combined freely on the same flow.

Global event configurations

Use this mode when you want a configuration to react to events on any business record that travels through EDI, with no per-partner setup.

Tick Global Configuration (is_global) on the edi.configuration. When an event fires, the framework calls edi.configuration.edi_get_conf_global(exchange_record, trigger) which selects all active global configurations whose trigger matches the event code, filtered by the originating exchange record:

  • Exchange type (type_id): must match the exchange record's type, or be left empty to apply to every type
  • Backend (backend_id): must match the exchange record's backend, or be left empty to apply to every backend
  • Model (model_id / model_name): must match the related record model (e.g. sale.order, account.move), or be left empty to apply to every model

Empty values mean "applies to all". Inactive configurations and non-global configurations are ignored. All matching configurations are executed in sequence.

Typical use cases:

  • Posting a generic chatter message on every exchange that ends in error
  • Pushing a notification to an external system every time an ACK is received for a given backend
  • Logging extra audit information for every exchange of a given type

Partner-specific (relation-based) event configurations

Use this mode when the reaction must depend on the partner (or any other related record) involved in the exchange.

In this case configurations are not marked as global. Instead, the business record exposes an edi_config_ids relation (via edi.exchange.consumer.mixin._edi_config_field_relation, which by default returns self.env["edi.configuration"] and can be overridden, for example to point at self.partner_id.edi_config_ids). When an event fires on the business record (e.g. on create, on write, on send-via-email/EDI), the framework calls edi_confs.edi_get_conf(trigger) on that relation and runs the matching snippets.

Compared with global configurations:

  • Discovery comes from the record's own relation, not from a database-wide search; this is the right place to model "this partner wants this behaviour" rules
  • Filtering is reduced to trigger and (optionally) backend_id, since the recordset is already narrowed by the relation
  • The same snippet_do API applies, so a snippet can be reused verbatim between global and partner-specific configurations

Typical use cases:

  • Sending a specific EDI flow only for a subset of partners
  • Customising the document generation per customer (e.g. different email template, different transport)
  • Switching between EDI and email delivery based on partner preferences

After certain operations or manual execution, Exchange records will be generated. This Exchange records might be input records or outputs records.

The change of state can be manually executed by the system or be managed through by ir.cron.

Output Exchange records

An output record is intended to be used for exchange information from Odoo to another system.

The flow of an output record should be:

  • Creation
  • Generation of data
  • Validation of data
  • Sending data
  • Validation of data processed properly by the other party

Input Exchange records

An input record is intended to be used for exchange information another system to odoo.

The flow of an input record should be:

  • Creation
  • Reception of data
  • Checking data
  • Processing data

No verified information in OCA: Installation.

info

Data imported from GitHub: this sheet reflects the latest catalog review, not a live lookup. Always check the module documentation and staging before installing in production.