Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0][MIG] base_edifact: Migration to 16.0 #813

Merged
merged 5 commits into from
Oct 18, 2023
Merged
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
131 changes: 131 additions & 0 deletions base_edifact/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
============
Base EDIFACT
============

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

.. |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/16.0/base_edifact
:alt: OCA/edi
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/edi-16-0/edi-16-0-base_edifact
: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=16.0
:alt: Try me on Runboat

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


This module contains methods to generate and parse EDIFACT/D96A files

.. 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:

Installation
============


This module requires 'pydifact' python library.

Configuration
=============

Requires partner_identification_gln module to store GLN identifiers.

Partner identification code assigned by the European Article Numbering Association.

Use two identification categories:

- "GLN Identificatin Number". Partner identification like invoice or delivery address.
- "GCP Identification Number". Global Company Prefix.

If GCP codes are needed in UNB interchange header.

If you need group partners, consider oca/partner-contact/partner_company_group module.

Usage
=====


This module doesn't do anything useful by itself, but it is used by several other modules:

* *sale_order_import_edifact* that imports EDIFACT/D96A sale orders.

Changelog
=========


14.0.1.0.0 (2023-04-13)
~~~~~~~~~~~~~~~~~~~~~~~
Strong migration from 12.0.1.0.1 because it's not working for Amazon vendor orders.

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:%20base_edifact%0Aversion:%2016.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
~~~~~~~

* ALBA Software
* PlanetaTIC

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

* Rafa Morant <rmorant@albasoft.com> (www.albasoft.com)
* Marc Poch <mpoch@planetatic.com>
* Duong (Tran Quoc) <duongtq@trobz.com>

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.

.. |maintainer-rmorant| image:: https://github.com/rmorant.png?size=40px
:target: https://github.com/rmorant
:alt: rmorant

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-rmorant|

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

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions base_edifact/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
27 changes: 27 additions & 0 deletions base_edifact/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Copyright 2023 ALBA Software S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0)
{
"name": "Base EDIFACT",
"summary": "UN/EDIFACT/D96A utilities using pydifact parser",
"version": "16.0.1.0.0",
"development_status": "Alpha",
"category": "Tools",
"website": "https://github.com/OCA/edi",
"author": "ALBA Software, PlanetaTIC, Odoo Community Association (OCA)",
"maintainers": ["rmorant"],
"license": "AGPL-3",
"application": False,
"installable": True,
# "preloadable": True,
"external_dependencies": {
"python": ["pydifact"],
"bin": [],
},
"depends": [
# for configuration
"account",
"partner_identification",
"partner_identification_gln",
],
"data": [],
}
1 change: 1 addition & 0 deletions base_edifact/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import edifact
206 changes: 206 additions & 0 deletions base_edifact/models/edifact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# Copyright 2023 ALBA Software S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0)


import datetime
import logging

from pydifact.segmentcollection import Interchange, Message
from pydifact.segments import Segment

from odoo import api, models

logger = logging.getLogger(__name__)


# https://github.com/nerdocs/pydifact
class BasePydifact(models.AbstractModel):
_name = "base.edifact"
_description = "Generate and parse Edifact documents"

MAP_AGENCY_CODE_2_RES_PARTNER_NAMEREF = {"9": "gln"}
CURRENCY_SYMBOLS = {
"EUR": "€",
"USD": "$",
}
PRODUCT_CODE_TYPES = {"EN": "EAN", "UP": "UPC", "SRV": "GTIN"}

@api.model
def pydifact_import(self, names):
classes = {
"Segment": Segment,
"Message": Message,
"Interchange": Interchange,
}
return [classes.get(name, None) for name in names]

@api.model
def pydifact_obj(self, docu):
obj = []
interchange = self._loads_edifact(docu)
header_seg = interchange.get_header_segment()
header_dict = dict()
header_dict[header_seg.tag] = header_seg.elements
obj.append(header_dict)
for message in interchange.get_messages():
segms = []
msg = {
"reference_number": message.reference_number,
"type": message.type,
"version": message.version,
"identifier": message.identifier,
"HEADER_TAG": message.HEADER_TAG,
"FOOTER_TAG": message.FOOTER_TAG,
"characters": str(message.characters),
"extra_header_elements": message.extra_header_elements,
"has_una_segment": message.has_una_segment,
}
logger.info(message)
for segment in message.segments:
logger.info(
"Segment tag: {}, content: {}".format(segment.tag, segment.elements)
)
# segms.append((segment.tag, segment.elements))
seg = dict()
seg[segment.tag] = segment.elements
segms.append(seg)
msg["segments"] = segms
obj.append(msg)
return obj

@api.model
def _loads_edifact(self, order_file):
interchange = Interchange.from_str(order_file.decode())
return interchange

@api.model
def _get_msg_type(self, interchange):
seg = interchange.get_segment("UNH")
# MSG_TYPE, EDIFACT_MSG_TYPE_RELEASE
return (seg[1][0], "{}{}".format(seg[1][1], seg[1][2]))

@api.model
def map2odoo_date(self, dt):
# '102'
dtt = datetime.datetime.strptime(dt[1], "%Y%m%d")
return dtt.date()

@api.model
def map2odoo_partner(self, seg):
"""
BY. Party to which merchandise is sold.
NAD+BY+5550534000017::9'
NAD segment: ['BY', ['5550534001649', '', '9']]

SU. Party which manufactures or otherwise has possession of
goods,and consigns or makes them available in trade.
NAD+SU+<Supplier GLN>::9'
"""

partner_dict = {}
codes = ["BY", "SU"]
reference_code = seg[0]
if reference_code not in codes:
raise NotImplementedError(f"Code '{reference_code}' not implemented")
#
party_identification = seg[1]
party_id = party_identification[0]
agency_code = party_identification[2]
nameref = self.MAP_AGENCY_CODE_2_RES_PARTNER_NAMEREF.get(agency_code, "gln")
partner_dict[nameref] = party_id
return partner_dict

@api.model
def map2odoo_address(self, seg):
"""
DP. Party to which goods should be delivered, if not identical with
consignee.
NAD+DP+5550534000086::9+++++++DE'
NAD segment: ['DP', ['5550534022101', '', '9'], '', '', '', '', '', '', 'ES']
IV. Party to whom an invoice is issued.
NAD+IV+5450534005838::9++AMAZON EU SARL:NIEDERLASSUNG
DEUTSCHLAND+MARCEL-BREUER-STR. 12+MUENCHEN++80807+DE

:returns: {
'type':
'partner': {'gln':''}
'address': {...}
}
"""
if seg[0] not in ("DP", "IV"):
return False
order_type = "delivery" if seg[0] == "DP" else "invoice"
address = dict(type=order_type, partner={}, address={})
# PARTY IDENTIFICATION DETAILS
iden = seg[1]
party_id = iden[0]
agency_code = iden[2]
nameref = self.MAP_AGENCY_CODE_2_RES_PARTNER_NAMEREF.get(agency_code, "gln")
address["partner"][nameref] = party_id
d = address["address"]
# PARTY NAME
if bool(seg[2]):
d["name"] = seg[2]
if bool(seg[3]):
d["name"] = "{}{}".format(f"{d['name']}. " if d.get("name") else "", seg[3])
if bool(seg[4]):
# Street address and/or PO Box number in a structured address: one to three lines.
d["street"] = seg[4]
if bool(seg[5]):
d["city"] = seg[5]
if bool(seg[6]):
# Country sub-entity identification
d["state_code"] = seg[6]
if bool(seg[7]):
d["zip"] = seg[7]
if bool(seg[8]):
# Country, coded ISO 3166
d["country_code"] = seg[8]

return address

@api.model
def map2odoo_currency(self, seg):
"""
['2', 'EUR', '9']
"""
# Identification of the name or symbol of the monetary unit involved in the transaction.
currency_coded = seg[1]
return {
"iso": currency_coded,
"symbol": self.CURRENCY_SYMBOLS.get(currency_coded, False),
}

@api.model
def map2odoo_product(self, seg):
"""
:seg: LIN segment
['1', '', ['8885583503464', 'EN']]
EN. International Article Numbering Association (EAN)
UP. UPC (Universal product code)
SRV. GTIN
"""
product = seg[2]
pct = product[1]
return dict(code=product[0]) if pct == "SRV" else dict(barcode=product[0])

@api.model
def map2odoo_qty(self, seg):
"""
'QTY' EDI segment: [['21', '2']]
'21'. Ordered quantity
"""
return float(seg[0][1])

@api.model
def map2odoo_unit_price(self, seg):
"""
'PRI' EDI segment: [['AAA', '19.75']]
Price qualifier:
* 'AAA'. Calculation net
* 'AAB'. Calculation gross
"""
pri = seg[0]
if pri[0] == "AAA":
return float(pri[1])
return 0.0
12 changes: 12 additions & 0 deletions base_edifact/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Requires partner_identification_gln module to store GLN identifiers.

Partner identification code assigned by the European Article Numbering Association.

Use two identification categories:

- "GLN Identificatin Number". Partner identification like invoice or delivery address.
- "GCP Identification Number". Global Company Prefix.

If GCP codes are needed in UNB interchange header.

If you need group partners, consider oca/partner-contact/partner_company_group module.
3 changes: 3 additions & 0 deletions base_edifact/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* Rafa Morant <rmorant@albasoft.com> (www.albasoft.com)
* Marc Poch <mpoch@planetatic.com>
* Duong (Tran Quoc) <duongtq@trobz.com>
2 changes: 2 additions & 0 deletions base_edifact/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

This module contains methods to generate and parse EDIFACT/D96A files
4 changes: 4 additions & 0 deletions base_edifact/readme/HISTORY.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

14.0.1.0.0 (2023-04-13)
~~~~~~~~~~~~~~~~~~~~~~~
Strong migration from 12.0.1.0.1 because it's not working for Amazon vendor orders.
2 changes: 2 additions & 0 deletions base_edifact/readme/INSTALL.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

This module requires 'pydifact' python library.
Loading