TIP: You can type at any time to perform a new search.
EDI
edi_core_oca · OCA/edi-framework
- Repository
- OCA/edi-framework · module folder · Try on Runboat
- Module version
- 1.3.0
- Category
- Uncategorized
- Folder size
- 0.82 MB
- License
- LGPL-3
- Application
- No
- Auto-installable
- No
- Website
- https://github.com/OCA/edi-framework
- Last tracking update
- 2026-08-07 09:06:36
- Authors
- Camptocamp, Odoo Community Association (OCA), ACSONE, Dixmit
- Maintainers
- Camptocamp, Odoo Community Association (OCA), ACSONE, Dixmit
- Committers
- Guewen Baconnier, Enric Tobella, Miquel Raïch, SilvioC2C, Ricardoalso, Iván Todorovich, Weblate, ThiagoMForgeFlow, OCA-git-bot, oca-ci, Hector Vior
- Odoo dependencies
- Python dependencies
- PyYAML, openupgradelib
- System dependencies
- None
- Required by
- edi_component_oca, edi_endpoint_oca, edi_exchange_deduplicate_oca, edi_notification_oca, edi_product_oca, edi_purchase_oca, edi_queue_oca, edi_record_metadata_oca, edi_sale_oca, edi_ubl_oca
- Description
Base EDI backend. Provides following models: 1. EDI Backend, to centralize configuration 2. EDI Backend Type, to classify EDI backends (eg: UBL, GS1, e-invoice, pick-yours) 3. EDI Exchange Type, to define file types of exchange 4. 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.
Code Analysis ⓘ
Views touched (24)
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
edi_backend_type_view_form |
edi.backend.type | form | New | |
edi_backend_type_view_search |
edi.backend.type | search | New | |
edi_backend_type_view_tree |
edi.backend.type | list | New | |
edi_backend_view_form |
edi.backend | form | New | |
edi_backend_view_search |
edi.backend | search | New | |
edi_backend_view_tree |
edi.backend | list | New | |
edi_configuration_trigger_view_form |
edi.configuration.trigger | form | New | |
edi_configuration_trigger_view_tree |
edi.configuration.trigger | list | New | |
edi_configuration_view_form |
edi.configuration | form | New | |
edi_configuration_view_search |
edi.configuration.view.search | edi.configuration | search | New |
edi_configuration_view_tree |
edi.configuration | list | New | |
edi_exchange_consumer_mixin_buttons |
edi_exchange_consumer_mixin_buttons | ir.ui.view | qweb | New |
edi_exchange_record_create_form_view |
edi.exchange.record.create.wiz.form (in edi) | edi.exchange.record.create.wiz | form | New |
edi_exchange_record_view_form |
edi.exchange.record | form | New | |
edi_exchange_record_view_search |
edi.exchange.record | search | New | |
edi_exchange_record_view_tree |
edi.exchange.record | list | New | |
edi_exchange_type_rule_view_form |
edi.exchange.type.rule | form | New | |
edi_exchange_type_rule_view_search |
edi.exchange.type.rule | search | New | |
edi_exchange_type_rule_view_tree |
edi.exchange.type.rule | list | New | |
edi_exchange_type_view_form |
edi.exchange.type | form | New | |
edi_exchange_type_view_search |
edi.exchange.type | search | New | |
edi_exchange_type_view_tree |
edi.exchange.type | list | New | |
message_edi_exchange_link |
message_edi_exchange_link | ir.ui.view | qweb | New |
view_partner_form |
res.partner.view.form | res.partner | form | Inherits base.view_partner_form |
HTTP endpoints (0)
No HTTP endpoints found for this module.
Models touched (20)
New fields (8)
-
activeBooleandefault=True -
auto_archive_records_after_daysIntegerdefault=0help='Automatically archive EDI exchange records after X days. Set to <= 0 to disable auto-archiving.'string='Auto-archive records after (days)' -
auto_delete_records_after_daysIntegerdefault=0help='Automatically delete archived EDI exchange records after X days. Set to <= 0 to disable auto-deletion.'string='Auto-delete archived records after (days)' -
backend_type_codeCharrelated='backend_type_id.code' -
backend_type_idMany2one → edi.backend.typecomodel_name='edi.backend.type'ondelete='restrict'required=Truestring='EDI Backend type' -
company_idMany2one → res.companystring='Company' args: 'res.company' -
nameCharrequired=True -
output_sent_processed_autoBooleanhelp='\n Automatically set the record as processed after sending.\n Usecase: the web service you send the file to processes it on the fly.\n '
-
action_view_exchange_types(self) -
action_view_exchanges(self) -
create_record(self, type_code, values)Create an exchange record for current backend. :param type_code: edi.exchange.type code :param values: edi.exchange.record values :return: edi.exchange.record record -
exchange_generate(self, exchange_record, store=True, force=False, **kw)Generate output content for given exchange record. :param exchange_record: edi.exchange.record recordset :param store: store output on the record itself :param force: allow to re-generate the content :param kw: keyword args to be propagated to output generate handler -
exchange_generate_send(self, recordset, skip_generate=False, skip_send=False)Generate and send output files for given records. If both are False, the record will be generated and sent right away with chained jobs. If both `skip_generate` and `skip_send` are True, nothing will be done. :param recordset: edi.exchange.record recordset :param skip_generate: only send records :param skip_send: only generate missing output -
exchange_process(self, exchange_record)Process an incoming document. -
exchange_receive(self, exchange_record)Retrieve an incoming document. -
exchange_record_model(self)@property -
exchange_send(self, exchange_record)Send exchange file.
New fields (2)
-
codeCharinverse='_inverse_code'required=True -
nameCharrequired=True
-
copy_data(self, default=None)
New fields (12)
-
activeBooleandefault=True -
backend_idMany2one → edi.backendcomodel_name='edi.backend' -
descriptionCharhelp='Describe what the conf is for' -
is_globalBooleandefault=Falsehelp='If checked, this configuration will be executed for all records, regardless of the partner relation.'string='Global Configuration' -
model_idMany2one → ir.modelhelp='Model the conf applies to. Leave blank to apply for all models'string='Model' args: 'ir.model' -
model_nameCharrelated='model_id.model'store=Truestring='Model tech name' -
nameCharrequired=True -
snippet_before_doTexthelp='Snippet to validate the state and collect records to do' -
snippet_doTexthelp='Used to do something specific here.\n Receives: operation, edi_action, vals, old_vals.' -
triggerCharrelated='trigger_id.code' -
trigger_idMany2one → edi.configuration.triggercomodel_name='edi.configuration.trigger'domain="['|', ('model_id', '=', model_id), ('model_id', '=', False)]"help='Trigger that activates this configuration' -
type_idMany2one → edi.exchange.typebypass_search_access=Truecomodel_name='edi.exchange.type'index=Trueondelete='cascade'string='Exchange Type'
-
action_view_partners(self) -
edi_exec_snippet_before_do(self, record, **kwargs) -
edi_exec_snippet_do(self, record, **kwargs) -
edi_get_conf(self, trigger, backend=None) -
edi_get_conf_global(self, exchange_record, trigger)@api.modelReturn active global configurations matching the given event. Unlike :meth:`edi_get_conf` -- which runs on a recordset of configurations already linked to a partner -- global configurations are not bound to any partner. We therefore have to derive the filtering keys from the originating exchange record: * ``trigger`` must match the event code * ``is_global`` must be True * ``type_id`` must match the exchange type or be empty (applies to all) * ``backend_id`` must match the backend or be empty (applies to all) * ``model_name`` must match the related record model or be empty (applies to all)
New fields (5)
-
activeBooleandefault=True -
codeCharcopy=Falserequired=True -
descriptionCharhelp='Describe what the conf is for' -
model_idMany2one → ir.modelhelp='Model the conf applies to. Leave blank to apply for all models' args: 'ir.model' -
nameCharrequired=True
No public methods.
New fields (7)
-
edi_disable_autoBooleanhelp='When marked, EDI automatic processing will be avoided'string='Disable auto' -
edi_has_form_configBooleancompute='_compute_edi_config' -
exchange_record_countIntegercompute='_compute_exchange_record_count' -
exchange_record_idsOne2many → edi.exchange.recordcompute='_compute_exchange_record_ids' args: 'edi.exchange.record' -
exchange_related_record_idsOne2many → edi.exchange.related.recorddomain=<expr>inverse_name='res_id' args: 'edi.exchange.related.record' -
origin_exchange_record_idMany2one → edi.exchange.recordcomodel_name='edi.exchange.record'copy=Falsehelp='EDI record that originated this document.'ondelete='set null'string='EDI origin record' -
origin_exchange_type_idMany2one → edi.exchange.typecomodel_name='edi.exchange.type'copy=Falseondelete='set null'related='origin_exchange_record_id.type_id'store=Truestring='EDI origin exchange type'
-
action_view_edi_records(self) -
create(self, mvals)@api.model_create_multi -
edi_create_exchange_record(self, exchange_type_id) -
get_edi_access(self, doc_ids, operation, model_name=False)@api.modelRetrieve access policy. The behavior is similar to `mail.thread` and `mail.message` and it relies on the access rules defines on the related record. The behavior can be customized on the related model by defining `_edi_exchange_record_access`. By default `write`, otherwise the custom permission is returned. -
get_view(self, view_id=None, view_type='form', **options)@api.model -
write(self, vals)
New fields (26)
-
ack_exchange_idMany2one → edi.exchange.recordcomodel_name='edi.exchange.record'compute='_compute_ack_exchange_id'help='ACK generated for current exchange.'index=Truestore=Truestring='ACK exchange' -
ack_expectedBooleancompute='_compute_ack_expected' -
ack_received_onDatetimerelated='ack_exchange_id.exchanged_on'string='ACK received on' -
activeBooleandefault=True -
backend_idMany2one → edi.backendcomodel_name='edi.backend'required=True -
company_idMany2one → res.companystring='Company' args: 'res.company' -
directionSelectionrelated='type_id.direction' -
edi_exchange_stateSelectioncopy=Falsedefault='new'index=Truereadonly=Trueselection=[('new', 'New'), ('validate_error', 'Error on validation'), ('output_pending', 'Waiting to be sent'), ('output_error_on_send', 'error on send'), ('output_sent', 'Sent'), ('output_sent_and_processed', 'Sent and processed'), ('output_sent_and_error', 'Sent and error'), ('input_pending', 'Waiting to be received'), ('input_received', 'Received'), ('input_receive_error', 'Error on reception'), ('input_processed', 'Processed'), ('input_processed_error', 'Error on process')]string='Exchange state' -
exchange_errorTextcopy=Falsereadonly=Truestring='Exchange error' -
exchange_error_tracebackTextcopy=Falsereadonly=Truestring='Exchange error traceback' -
exchange_fileBinaryattachment=Truecopy=False -
exchange_file_frozenBooleancompute='_compute_exchange_file_frozen'compute_sudo=Truehelp='Not allowed to change the file anymore.' -
exchange_filechecksumCharcompute='_compute_exchange_filechecksum'readonly=Truestore=Truetracking=True -
exchange_filenameCharcompute='_compute_exchange_filename'readonly=Falsestore=True -
exchanged_onDatetimecompute='_compute_exchanged_on'help='Sent or received on this date.'readonly=Truestore=True -
external_identifierCharcopy=Falseindex=Truereadonly=True -
identifierCharcopy=Falseindex=Truereadonly=Truerequired=True -
modelCharcompute='_compute_record'copy=Falseindex=Trueinverse='_inverse_record'readonly=Falserequired=Falsestore=True -
parent_idMany2one → edi.exchange.recordcomodel_name='edi.exchange.record'help='Original exchange which originated this record'index=True -
related_exchange_idsOne2many → edi.exchange.recordcomodel_name='edi.exchange.record'inverse_name='parent_id'string='Related exchanges' -
related_nameCharcompute='_compute_related_name'compute_sudo=True -
related_record_existsBooleancompute='_compute_related_record_exists' -
related_record_idsOne2many → edi.exchange.related.recordcomodel_name='edi.exchange.related.record'inverse_name='exchange_record_id'string='Related records' -
res_idMany2oneReferencecompute='_compute_record'copy=Falseindex=Trueinverse='_inverse_record'model_field='model'readonly=Falserequired=Falsestore=Truestring='Record' -
retryableBooleancompute='_compute_retryable'help='The record state can be rolled back manually in case of failure.' -
type_idMany2one → edi.exchange.typebypass_search_access=Truecomodel_name='edi.exchange.type'index=Trueondelete='cascade'required=Truestring='Exchange type'
-
action_exchange_generate(self, **kw) -
action_exchange_generate_send(self, **kw) -
action_exchange_generate_send_chained(self) -
action_exchange_process(self) -
action_exchange_receive(self) -
action_exchange_send(self) -
action_open_related_exchanges(self) -
action_open_related_record(self) -
action_regenerate(self) -
action_retry(self) -
check_access(self, operation)In order to check if we can access a record, we are checking if we can access the related document -
create(self, vals_list)@api.model_create_multi -
exchange_create_ack_record(self, **kw) -
exchange_create_child_record(self, exc_type=None, **kw) -
needs_ack(self) -
notify_action_complete(self, action, message=None)Notify current record that an edi action has been completed. Implementers should take care of calling this method if they work on records w/o calling edi_backend methods (eg: action_send). Implementers can hook to this method to do something after any action ends. -
read(self, fields=None, load='_classic_read')Override to explicitely call check_access_rule, that is not called by the ORM. It instead directly fetches ir.rules and apply them. -
record(self)@property -
write(self, vals)
New fields (5)
-
backend_idMany2one → edi.backendrequired=True args: 'edi.backend' -
backend_type_idMany2one → edi.backend.typerelated='exchange_type_id.backend_type_id' args: 'edi.backend.type' -
exchange_type_idMany2one → edi.exchange.typerequired=True args: 'edi.exchange.type' -
modelCharrequired=True -
res_idIntegerrequired=True
-
create_edi(self)
New fields (3)
-
exchange_record_idMany2one → edi.exchange.recordcomodel_name='edi.exchange.record'index=Trueondelete='cascade'required=True -
modelCharindex=Truereadonly=Truerequired=True -
res_idMany2oneReferencecopy=Falseindex=Truemodel_field='model'readonly=Truerequired=Truestring='Record'
-
action_open_related_record(self) -
record(self)@property
New fields (29)
-
ack_for_type_idsMany2many → edi.exchange.typecomodel_name='edi.exchange.type'compute='_compute_ack_for_type_ids'string='Ack for exchange type' -
ack_type_idMany2one → edi.exchange.typecomodel_name='edi.exchange.type'help='Identify the type of the ack. If this field is valued it means an hack is expected.'ondelete='set null'string='Ack exchange type' -
activeBooleandefault=Trueinverse='_inverse_active' -
advanced_settings_editTexthelp='\n Advanced technical settings as YAML format.\n The YAML structure should reproduce a dictionary.\n The backend might use these settings for automated operations.\n\n Currently supported conf:\n\n components:\n generate:\n usage: $comp_usage\n # set a value for component work context\n work_ctx:\n opt1: True\n validate:\n usage: $comp_usage\n env_ctx:\n # set a value for the whole processing env\n opt2: False\n check:\n usage: $comp_usage\n send:\n usage: $comp_usage\n receive:\n usage: $comp_usage\n process:\n usage: $comp_usage\n\n filename_pattern:\n force_tz: Europe/Rome\n date_pattern: %Y-%m-%d-%H-%M-%S\n\n In any case, you can use these settings\n to provide your own configuration for whatever need you might have.\n 'string='Advanced YAML settings' -
allow_empty_files_on_receiveBooleanstring='Allow Empty Files' -
backend_idMany2one → edi.backendcomodel_name='edi.backend'ondelete='set null'string='Backend' -
backend_type_idMany2one → edi.backend.typecomodel_name='edi.backend.type'ondelete='restrict'required=Truestring='Backend type' -
check_model_idMany2one → ir.modeldomain=[('is_edi_checker', '=', True)]string='Checker' args: 'ir.model' -
codeCharcopy=Falserequired=True -
directionSelectionrequired=Trueselection=[('input', 'Input'), ('output', 'Output')] -
encodingCharhelp="Encoding to be applied to generate/process the exchanged file.\nExample: UTF-8, Windows-1252, ASCII...(default is always 'UTF-8')" -
encoding_in_error_handlerSelectionhelp="Handling of decoding errors on process (default is always 'Raise Error')."selection=[('strict', 'Raise Error'), ('ignore', 'Ignore'), ('replace', 'Replace with Replacement Marker'), ('backslashreplace', 'Replace with Backslashed Escape Sequences'), ('surrogateescape', 'Replace Byte with Individual Surrogate Code')]string='Decoding Error Handler' -
encoding_out_error_handlerSelectionhelp="Handling of encoding errors on generate (default is always 'Raise Error')."selection=[('strict', 'Raise Error'), ('ignore', 'Ignore'), ('replace', 'Replace with Replacement Marker'), ('backslashreplace', 'Replace with Backslashed Escape Sequences'), ('surrogateescape', 'Replace Byte with Individual Surrogate Code'), ('xmlcharrefreplace', 'Replace with XML/HTML Numeric Character Reference')]string='Encoding Error Handler' -
exchange_file_auto_generateBooleanhelp='Auto generate output for records missing their payload. If active, a cron will take care of generating the output when not set yet. ' -
exchange_file_extChar -
exchange_filename_patternChardefault='{record_name}-{type.code}-{dt}'help='For output exchange types this should be a formatting string with the following variables available (to be used between brackets, `{}`): `exchange_record`, `record_name`, `type`, `dt` and `seq`. For instance, a valid string would be {record_name}-{type.code}-{dt}-{seq}\nFor more information:\n- `exchange_record` means exchange record\n- `record_name` means name of the exchange record\n- `type` means code of the exchange record type\n- `dt` means datetime\n- `seq` means sequence. You need a sequence to be defined in `Exchange Filename Sequence` to use `seq`\n' -
exchange_filename_sequence_idMany2one → ir.sequencehelp='If the `Exchange Filename Pattern` has `{seq}`, you should define a sequence in this field to show the sequence in your filename' args: 'ir.sequence', 'Exchange Filename Sequence' -
exchange_record_countIntegercompute='_compute_exchange_record_count'string='# Exchange Records' -
exchange_record_idsOne2many → edi.exchange.recordcomodel_name='edi.exchange.record'inverse_name='type_id' -
generate_model_idMany2one → ir.modeldomain=[('is_edi_generator', '=', True)]string='Generator' args: 'ir.model' -
input_validate_model_idMany2one → ir.modeldomain=[('is_edi_input_validator', '=', True)]string='Input Validator' args: 'ir.model' -
nameCharrequired=True -
output_validate_model_idMany2one → ir.modeldomain=[('is_edi_output_validator', '=', True)]string='Output Validator' args: 'ir.model' -
partner_idsMany2many → res.partnercomodel_name='res.partner'help='You can use this field to limit generating/processing exchanges for specific partners. Use it directly or within models rules (domain or snippet).'string='Enabled for partners' -
process_model_idMany2one → ir.modeldomain=[('is_edi_processor', '=', True)]string='Processor' args: 'ir.model' -
quick_execBooleanhelp='When active, records of this type will be processed immediately without waiting for the cron to pass by. Requires auto generate flag to be active as well. The cron will skip these records unless forced.'string='Quick execution' -
receive_model_idMany2one → ir.modeldomain=[('is_edi_receiver', '=', True)]string='Receiver' args: 'ir.model' -
rule_idsOne2many → edi.exchange.type.rulecomodel_name='edi.exchange.type.rule'help='Rules to handle exchanges and UI automatically'inverse_name='type_id' -
send_model_idMany2one → ir.modeldomain=[('is_edi_sender', '=', True)]string='Sender' args: 'ir.model'
-
action_view_exchange_records(self) -
copy_data(self, default=None) -
get_settings(self) -
is_partner_enabled(self, partner)Check if given partner record is allowed for the current type. You can leverage this in your own logic to trigger or not certain exchanges for specific partners. For instance: a customer might require an ORDRSP while another does not. -
set_settings(self, val)
New fields (10)
-
activeBooleandefault=True -
enable_domainCharhelp='Filter domain to be checked on Models'string='Enable on domain' -
enable_snippetCharhelp='Snippet of code to be checked on Models,\n You can use `record` and `exchange_type` here.\n It will be executed if variable result has been defined as True\n 'string='Enable on snippet' -
form_btn_labelCharhelp='Type name used by default'string='Form button label'translate=True -
form_btn_tooltipTexthelp='Help message visible as tooltip on button h-over'string='Form button tooltip'translate=True -
kindSelectiondefault='form_btn'help=KIND_HELPrequired=Trueselection=[('form_btn', 'Form button'), ('custom', 'Custom')] -
modelCharrelated='model_id.model' args: 'Model code' -
model_idMany2one → ir.modelcomodel_name='ir.model'help='Apply to this model'ondelete='cascade' -
nameCharrequired=True -
type_idMany2one → edi.exchange.typecomodel_name='edi.exchange.type'ondelete='cascade'required=True
No public methods.
New fields (1)
-
edi_idCharhelp='Internal or external identifier for records.'string='EDI ID'
No public methods.
New fields (0)
No new fields.
Public methods (1)-
check(self, exchange_record)
New fields (0)
No new fields.
Public methods (1)-
generate(self, exchange_record)
New fields (0)
No new fields.
Public methods (1)-
input_validate(self, exchange_record, **kw)
New fields (0)
No new fields.
Public methods (0)No public methods.
New fields (0)
No new fields.
Public methods (1)-
output_validate(self, exchange_record, **kw)
New fields (0)
No new fields.
Public methods (1)-
process(self, exchange_record)
New fields (0)
No new fields.
Public methods (1)-
receive(self, exchange_record)
New fields (0)
No new fields.
Public methods (1)-
send(self, exchange_record)
New fields (7)
-
is_edi_checkerBoolean -
is_edi_generatorBoolean -
is_edi_input_validatorBoolean -
is_edi_output_validatorBoolean -
is_edi_processorBoolean -
is_edi_receiverBoolean -
is_edi_senderBoolean
No public methods.
Loading…