Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions edi_purchase_edifact_oca/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
========================
EDI PURCHASE EDIFACT OCA
========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:d2e2602bb615321d18583caff366876c642564652bdfcd412395f69355aa8d72
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
:target: https://odoo-community.org/page/development-status
:alt: Alpha
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fedi-lightgray.png?logo=github
:target: https://github.com/OCA/edi/tree/14.0/edi_purchase_edifact_oca
:alt: OCA/edi
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/edi-14-0/edi-14-0-edi_purchase_edifact_oca
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/edi&target_branch=14.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

UN/EDIFACT
United Nations rules for Elec­tronic Data Interchange for Administration, Commerce and Transport

This module will support exporting and confirming orders in EDIFACT format.

https://www.stedi.com/edi/edifact/D01B/messages/ORDERS
https://www.stedi.com/edi/edifact/D96A/messages/ORDERS
https://www.stedi.com/edi/edifact/D01B/messages/DESADV
https://www.stedi.com/edi/edifact/D96A/messages/DESADV

.. IMPORTANT::
This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.
`More details on development status <https://odoo-community.org/page/development-status>`_

**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/edi/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/edi/issues/new?body=module:%20edi_purchase_edifact_oca%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
~~~~~~~

* Trobz

Contributors
~~~~~~~~~~~~

* Thien (Vo Hong) <[email protected]>

Other credits
~~~~~~~~~~~~~

The development of this module has been financially supported by:

* Trobz

Maintainers
~~~~~~~~~~~

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/edi <https://github.com/OCA/edi/tree/14.0/edi_purchase_edifact_oca>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
3 changes: 3 additions & 0 deletions edi_purchase_edifact_oca/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import models
from . import components
from . import wizard
30 changes: 30 additions & 0 deletions edi_purchase_edifact_oca/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2024 Trobz
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0)
{
"name": "EDI PURCHASE EDIFACT OCA",
"summary": "Create and send EDIFACT order files",
"version": "14.0.1.0.0",
"development_status": "Alpha",
"website": "https://github.com/OCA/edi",
"author": "Trobz, Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
"depends": [
"base_edifact",
"stock",
"edi_storage_oca",
"uom_unece",
"edi_purchase_oca",
"partner_identification_gln",
"base_business_document_import",
],
"data": [
"security/ir.model.access.csv",
"views/purchase.xml",
"views/res_partner.xml",
"data/edi_backend.xml",
"data/edi_exchange_type.xml",
"wizard/purchase_order_import_view.xml",
],
}
3 changes: 3 additions & 0 deletions edi_purchase_edifact_oca/components/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import listener_edifact_output
from . import generate_edifact_output
from . import process_edifact_input
21 changes: 21 additions & 0 deletions edi_purchase_edifact_oca/components/generate_edifact_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2024 Trobz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo.addons.component.core import Component


class EDIExchangeEDIFACTOutGenerate(Component):
_name = "edi.output.edifact.out.generate"
_inherit = "edi.component.output.mixin"
_usage = "output.generate.edifact"

def generate(self):
data = False
exchange_record = self.exchange_record

if exchange_record:
if exchange_record.model == "purchase.order" and exchange_record.res_id:
order = self.env["purchase.order"].browse(exchange_record.res_id)
if order:
data = order.edifact_purchase_generate_data(exchange_record)
return data
56 changes: 56 additions & 0 deletions edi_purchase_edifact_oca/components/listener_edifact_output.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright 2024 Trobz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging

from odoo.addons.component.core import Component

_logger = logging.getLogger(__name__)


class PurchaseOrderEdifactListener(Component):
_name = "purchase.order.event.listener.edifact"
_inherit = "base.event.listener"
_apply_on = ["purchase.order"]

def on_button_confirm_purchase_order(self, order):
if not self._should_create_exchange_record(order):
return None

domain = [
"|",
"|",
("partner_ids", "=", False),
("partner_ids", "=", order.partner_id.id),
("partner_ids", "=", order.partner_id.commercial_partner_id.id),
]
exchange_type = self.env["edi.exchange.type"].sudo().search(domain, limit=1)
if not exchange_type:
return None

record = exchange_type.backend_id.create_record(
exchange_type.code, self._storage_new_exchange_record_vals()
)
# Set related record
record._set_related_record(order)
_logger.info(
"Exchange record for purchase order %s was created: %s",
order.name,
record.identifier,
)

def _should_create_exchange_record(self, order):
if self.env.context.get("skip_send_edifact", False):
return False

partner = order.partner_id
if not partner:
return False

return (
partner.edifact_purchase_order_out
or partner.parent_id.edifact_purchase_order_out
)

def _storage_new_exchange_record_vals(self):
return {"edi_exchange_state": "new"}
36 changes: 36 additions & 0 deletions edi_purchase_edifact_oca/components/process_edifact_input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2024 Trobz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import base64

from odoo.addons.component.core import Component


class EDIExchangeEDIFACTInput(Component):

_name = "edi.input.process.edifact.input"
_inherit = "edi.component.input.mixin"
_usage = "input.process.edifact.input"

def process(self):
"""Process incoming EDIFACT record and confirm record."""
file_content = self.exchange_record._get_file_content()
wizard = self.env["purchase.order.import"].create(
{
"import_type": "edifact",
"order_file": base64.b64encode(file_content.encode()),
"order_filename": self.exchange_record.exchange_filename,
}
)
file_name = self.exchange_record.exchange_filename
action = wizard.import_order_button()
if action and action.get("res_model", False):
self.exchange_record.update(
{
"model": action["res_model"],
"res_id": action["res_id"],
}
)
self.exchange_record.exchange_filename = file_name

return True
11 changes: 11 additions & 0 deletions edi_purchase_edifact_oca/data/edi_backend.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="edi_backend_type_edifact" model="edi.backend.type">
<field name="name">EDIFACT</field>
<field name="code">edifact</field>
</record>
<record id="edi_backend_edifact" model="edi.backend">
<field name="name">EDIFACT</field>
<field name="backend_type_id" ref="edi_backend_type_edifact" />
</record>
</odoo>
49 changes: 49 additions & 0 deletions edi_purchase_edifact_oca/data/edi_exchange_type.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<record id="edi_exchange_type_purchase_order_out" model="edi.exchange.type">
<field name="backend_id" ref="edi_backend_edifact" />
<field name="backend_type_id" ref="edi_backend_type_edifact" />
<field name="name">EDIFACT-OUT-ORDER</field>
<field name="code">edifact_out_order</field>
<field name="direction">output</field>
<field name="exchange_filename_pattern">D{dt}</field>
<field name="exchange_file_ext">txt</field>
<field name="exchange_file_auto_generate">True</field>
<field name="encoding">iso-8859-1</field>
<field name="encoding_out_error_handler">strict</field>
<field name="encoding_in_error_handler">strict</field>
<field name="quick_exec" eval="True" />
<field name="advanced_settings_edit">
components:
generate:
usage: output.generate.edifact
env_ctx:
msg_type: Picking
filename_pattern:
force_tz: Europe/Zurich
date_pattern: "%Y%m%d%H%M%S%f"
</field>
</record>

<record id="edi_exchange_type_purchase_order_input" model="edi.exchange.type">
<field name="backend_id" ref="edi_backend_edifact" />
<field name="backend_type_id" ref="edi_backend_type_edifact" />
<field name="name">EDIFACT-IN-DESPATCH-ADVICE</field>
<field name="code">edifact_in_despatch_advice</field>
<field name="exchange_filename_pattern">output.*</field>
<field name="exchange_file_ext">edi</field>
<field name="direction">input</field>
<field name="quick_exec" eval="True" />
<field name="exchange_file_auto_generate">True</field>
<field name="encoding">iso-8859-1</field>
<field name="encoding_out_error_handler">strict</field>
<field name="encoding_in_error_handler">strict</field>
<field name="advanced_settings_edit">
components:
process:
usage: input.process.edifact.input
env_ctx:
msg_type: "EDIFACT Input"
</field>
</record>
</odoo>
4 changes: 4 additions & 0 deletions edi_purchase_edifact_oca/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import purchase
from . import res_partner
from . import business_document_import
from . import edi_exchange_record
53 changes: 53 additions & 0 deletions edi_purchase_edifact_oca/models/business_document_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright 2024 Trobz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import _, api, exceptions, models


class BusinessDocumentImport(models.AbstractModel):
_inherit = "business.document.import"

@api.model
def _hook_match_partner(self, partner_dict, chatter_msg, domain, order):
"""
2 types
partner_dict = {'gln':""}
partner_dict = {'partner': {'gln':""}, 'address':{'country_code':"ES",...}}
"""
partner = partner_dict.get("partner", partner_dict)
partner_dict.get("address", False)
if not partner.get("gln"):
return super()._hook_match_partner(partner_dict, chatter_msg, domain, order)
party_id = partner["gln"]

partner_id_category = self.env.ref(
"partner_identification_gln.partner_identification_gln_number_category"
)
if not partner_id_category:
raise exceptions.UserError(
_(
"partner_identification_gln module"
" should be installed with a xmlid: "
"partner_identification_gln_number_category"
)
)
id_number = self.env["res.partner.id_number"].search(
[("category_id", "=", int(partner_id_category)), ("name", "=", party_id)],
limit=1,
)
if not id_number:
ctx = partner.get(
"edi_ctx", {"order_filename": _("Unknown"), "rff_va": _("Unknown")}
)
raise exceptions.UserError(
_(
"Partner GLN Code: {party} not found in order file: '{file}' "
"from VAT registration number '{vat}'."
).format(
party=party_id,
file=ctx.get("order_filename"),
vat=ctx.get("rff_va"),
)
)

return id_number.partner_id
15 changes: 15 additions & 0 deletions edi_purchase_edifact_oca/models/edi_exchange_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2024 Trobz
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import models

from odoo.addons.edi_oca.models.edi_exchange_record import EDIExchangeRecord


class EDIExchangeRecord(models.Model):
_inherit = "edi.exchange.record"

_rollback_state_mapping = {
**EDIExchangeRecord._rollback_state_mapping,
"input_processed": "input_received",
}
Loading
Loading