diff --git a/README.md b/README.md index 86a749f..cfac112 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,16 @@ Enterprise modules for the Mexican localization [//]: # (addons) -This part will be replaced when running the oca-gen-addons-table script from OCA/maintainer-tools. +Available addons +---------------- +addon | version | maintainers | summary +--- | --- | --- | --- +[l10n_mx_edi_addenda_audi](l10n_mx_edi_addenda_audi/) | 19.0.1.0.1 | | Mexican Localization Addendum For Audi +[l10n_mx_edi_addenda_ford](l10n_mx_edi_addenda_ford/) | 19.0.1.0.1 | | Mexican Localization Addendum For Ford +[l10n_mx_edi_addenda_kuehne_nagel](l10n_mx_edi_addenda_kuehne_nagel/) | 19.0.1.0.0 | max3903 | Mexican Localization Addendum KNRECEPCION For Kuehne+Nagel +[l10n_mx_edi_addenda_mabe](l10n_mx_edi_addenda_mabe/) | 19.0.1.0.1 | | Mexican Localization Addendum For MABE +[l10n_mx_edi_addenda_volkswagen](l10n_mx_edi_addenda_volkswagen/) | 19.0.1.0.1 | | Mexican Localization Addendum For Volkswagen +[l10n_mx_edi_addenda_whirlpool](l10n_mx_edi_addenda_whirlpool/) | 19.0.1.0.1 | | Mexican Localization Addendum For Whirlpool [//]: # (end addons) diff --git a/l10n_mx_edi_addenda_audi/README.rst b/l10n_mx_edi_addenda_audi/README.rst index 4385868..f74dfeb 100644 --- a/l10n_mx_edi_addenda_audi/README.rst +++ b/l10n_mx_edi_addenda_audi/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ====================================== Mexican Addendum For Invoices For Audi ====================================== diff --git a/l10n_mx_edi_addenda_ford/README.rst b/l10n_mx_edi_addenda_ford/README.rst index 1b26d86..d6e2220 100644 --- a/l10n_mx_edi_addenda_ford/README.rst +++ b/l10n_mx_edi_addenda_ford/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ====================================== Mexican Addendum For Invoices For Ford ====================================== diff --git a/l10n_mx_edi_addenda_kuehne_nagel/README.rst b/l10n_mx_edi_addenda_kuehne_nagel/README.rst new file mode 100644 index 0000000..a869cff --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/README.rst @@ -0,0 +1,124 @@ +============================================== +Mexican Addendum For Invoices For Kuehne+Nagel +============================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:18a950ab56edfe89d856583366dd2bb0584a13d9798868fc6d1da3e80f18dc9a + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-amxodoo%2Fenterprise-lightgray.png?logo=github + :target: https://github.com/amxodoo/enterprise/tree/19.0/l10n_mx_edi_addenda_kuehne_nagel + :alt: amxodoo/enterprise + +|badge1| |badge2| |badge3| + +This module adds the KNRECEPCION addenda for Kuehne+Nagel and allows you +to generate electronic invoices (CFDI 4.0) with the required reception +block. + +The addenda is inserted under ``cfdi:Addenda`` with this structure: + +- ``kn:KNRECEPCION`` + + - ``kn:Tipo`` + + - ``kn:FacturasKN`` + + - ``kn:Purchase_Order`` + - ``kn:FileNumber_GL`` + - ``kn:Branch_Centre`` + - ``kn:TransportRef`` + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +To configure this module, you need to: + +1. Go to Accounting > Customers > Customers +2. Open the Kuehne+Nagel partner +3. In the Sales & Purchase tab, Fiscal Information section, add + **Addenda Kuehne Nagel** to the Addendas & Complements field + +Usage +===== + +To use this module, you need to: + +1. Go to Accounting > Customers > Invoices +2. Create an invoice for the partner configured with **Addenda Kuehne + Nagel** +3. Set the Customer Reference for the Purchase Order when applicable +4. Open the **Kuehne+Nagel Addenda** tab and optionally fill: + + - File / Tracking Type + - File / Tracking Number + - Branch Centre + - Transport Ref + +5. Validate and stamp the invoice as usual + +The module does not enforce a format for the Customer Reference or +addenda fields. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub 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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Gray Matter Logic +* Odoo Mexican Association (AMOdoo) + +Contributors +------------ + +- `Gray Matter Logic `__: + + - Maxime Chambreuil + +Other credits +------------- + +The development of this module has been financially supported by: + +- `Gray Matter Logic `__ + +Maintainers +----------- + +.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px + :target: https://github.com/max3903 + :alt: max3903 + +Current maintainer: + +|maintainer-max3903| + +This module is part of the `amxodoo/enterprise `_ project on GitHub. + +You are welcome to contribute. diff --git a/l10n_mx_edi_addenda_kuehne_nagel/__init__.py b/l10n_mx_edi_addenda_kuehne_nagel/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/l10n_mx_edi_addenda_kuehne_nagel/__manifest__.py b/l10n_mx_edi_addenda_kuehne_nagel/__manifest__.py new file mode 100644 index 0000000..7c50886 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/__manifest__.py @@ -0,0 +1,28 @@ +# Copyright (C) 2026 Gray Matter Logic (https://www.graymatterlogic.com) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "Mexican Addendum For Invoices For Kuehne+Nagel", + "version": "19.0.1.0.0", + "license": "LGPL-3", + "summary": "Mexican Localization Addendum KNRECEPCION For Kuehne+Nagel", + "author": "Gray Matter Logic, Odoo Mexican Association (AMOdoo)", + "maintainer": "Gray Matter Logic", + "website": "https://github.com/amxodoo/enterprise", + "depends": [ + "account", + "l10n_mx_edi", + ], + "data": [ + "data/l10n_mx_edi_addenda_kuehne_nagel_data.xml", + "views/account_move_views.xml", + ], + "images": [ + "static/description/icon.png", + ], + "icon": "/l10n_mx_edi_addenda_kuehne_nagel/static/description/icon.png", + "installable": True, + "application": False, + "development_status": "Beta", + "maintainers": ["max3903"], +} diff --git a/l10n_mx_edi_addenda_kuehne_nagel/data/l10n_mx_edi_addenda_kuehne_nagel_data.xml b/l10n_mx_edi_addenda_kuehne_nagel/data/l10n_mx_edi_addenda_kuehne_nagel_data.xml new file mode 100644 index 0000000..291fc68 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/data/l10n_mx_edi_addenda_kuehne_nagel_data.xml @@ -0,0 +1,34 @@ + + + + Addenda Kuehne Nagel + + + + + + + + + + + + + + + + + + + + + diff --git a/l10n_mx_edi_addenda_kuehne_nagel/i18n/es_MX.po b/l10n_mx_edi_addenda_kuehne_nagel/i18n/es_MX.po new file mode 100644 index 0000000..006e37d --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/i18n/es_MX.po @@ -0,0 +1,98 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_mx_edi_addenda_kuehne_nagel +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 19.0\n" +"Report-Msgid-Bugs-To: \n" +"Language: es_MX\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:l10n_mx_edi.addenda,name:l10n_mx_edi_addenda_kuehne_nagel.l10n_mx_edi_addenda_kuehne_nagel +msgid "Addenda Kuehne Nagel" +msgstr "Adenda Kuehne Nagel" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Addenda fields are optional and do not enforce a format." +msgstr "Los campos de la adenda son opcionales y no requieren un formato." + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Branch Centre" +msgstr "Centro de sucursal" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields.selection,name:l10n_mx_edi_addenda_kuehne_nagel.selection__account_move__kn_file_type__file +msgid "File Number" +msgstr "Número de expediente" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "File / Tracking Number" +msgstr "Número de expediente / rastreo" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "File / Tracking Type" +msgstr "Tipo de expediente / rastreo" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Hints" +msgstr "Indicaciones" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_branch_centre +msgid "KN Branch Centre" +msgstr "Centro de sucursal KN" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_file_number_gl +msgid "KN File Number GL" +msgstr "Número de expediente GL KN" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_file_type +msgid "KN File/Tracking Type" +msgstr "Tipo de expediente/rastreo KN" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_flag +msgid "KN Flag" +msgstr "Indicador KN" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_transport_ref +msgid "KN Transport Ref" +msgstr "Referencia de transporte KN" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Kuehne+Nagel Addenda" +msgstr "Adenda Kuehne+Nagel" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model,name:l10n_mx_edi_addenda_kuehne_nagel.model_account_move +msgid "Journal Entry" +msgstr "Asiento contable" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Purchase Order uses the Customer Reference field as entered." +msgstr "La orden de compra usa la referencia del cliente tal como fue capturada." + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields.selection,name:l10n_mx_edi_addenda_kuehne_nagel.selection__account_move__kn_file_type__tracking +msgid "Tracking Number" +msgstr "Número de rastreo" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Transport Ref" +msgstr "Referencia de transporte" diff --git a/l10n_mx_edi_addenda_kuehne_nagel/i18n/l10n_mx_edi_addenda_kuehne_nagel.pot b/l10n_mx_edi_addenda_kuehne_nagel/i18n/l10n_mx_edi_addenda_kuehne_nagel.pot new file mode 100644 index 0000000..1c843c6 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/i18n/l10n_mx_edi_addenda_kuehne_nagel.pot @@ -0,0 +1,97 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_mx_edi_addenda_kuehne_nagel +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 19.0\n" +"Report-Msgid-Bugs-To: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:l10n_mx_edi.addenda,name:l10n_mx_edi_addenda_kuehne_nagel.l10n_mx_edi_addenda_kuehne_nagel +msgid "Addenda Kuehne Nagel" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Addenda fields are optional and do not enforce a format." +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Branch Centre" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields.selection,name:l10n_mx_edi_addenda_kuehne_nagel.selection__account_move__kn_file_type__file +msgid "File Number" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "File / Tracking Number" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "File / Tracking Type" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Hints" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_branch_centre +msgid "KN Branch Centre" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_file_number_gl +msgid "KN File Number GL" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_file_type +msgid "KN File/Tracking Type" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_flag +msgid "KN Flag" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields,field_description:l10n_mx_edi_addenda_kuehne_nagel.field_account_move__kn_transport_ref +msgid "KN Transport Ref" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Kuehne+Nagel Addenda" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model,name:l10n_mx_edi_addenda_kuehne_nagel.model_account_move +msgid "Journal Entry" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Purchase Order uses the Customer Reference field as entered." +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model:ir.model.fields.selection,name:l10n_mx_edi_addenda_kuehne_nagel.selection__account_move__kn_file_type__tracking +msgid "Tracking Number" +msgstr "" + +#. module: l10n_mx_edi_addenda_kuehne_nagel +#: model_terms:ir.ui.view,arch_db:l10n_mx_edi_addenda_kuehne_nagel.view_account_move_form_inherit_addenda_kuehne_nagel +msgid "Transport Ref" +msgstr "" diff --git a/l10n_mx_edi_addenda_kuehne_nagel/models/__init__.py b/l10n_mx_edi_addenda_kuehne_nagel/models/__init__.py new file mode 100644 index 0000000..9c0a421 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/models/__init__.py @@ -0,0 +1 @@ +from . import account_move diff --git a/l10n_mx_edi_addenda_kuehne_nagel/models/account_move.py b/l10n_mx_edi_addenda_kuehne_nagel/models/account_move.py new file mode 100644 index 0000000..7842730 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/models/account_move.py @@ -0,0 +1,51 @@ +# Copyright (C) 2026 Gray Matter Logic (https://www.graymatterlogic.com) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import api, fields, models + + +class AccountMove(models.Model): + _inherit = "account.move" + + kn_file_type = fields.Selection( + selection=[ + ("file", "File Number"), + ("tracking", "Tracking Number"), + ], + string="KN File/Tracking Type", + ) + kn_file_number_gl = fields.Char(string="KN File Number GL") + kn_branch_centre = fields.Char(string="KN Branch Centre") + kn_transport_ref = fields.Char(string="KN Transport Ref") + kn_flag = fields.Boolean(compute="_compute_kn_flag", store=True) + + @api.depends("partner_id.l10n_mx_edi_addenda_ids") + def _compute_kn_flag(self): + addenda = self.env.ref( + "l10n_mx_edi_addenda_kuehne_nagel.l10n_mx_edi_addenda_kuehne_nagel", + raise_if_not_found=False, + ) + for record in self: + record.kn_flag = bool( + addenda and addenda in record.partner_id.l10n_mx_edi_addenda_ids + ) + + def _l10n_mx_edi_kn_normalize_vals(self, vals): + """Normalize KN-specific values before create/write.""" + vals = dict(vals) + if vals.get("kn_branch_centre"): + vals["kn_branch_centre"] = vals["kn_branch_centre"].strip().upper() + if vals.get("kn_file_number_gl"): + vals["kn_file_number_gl"] = vals["kn_file_number_gl"].strip() + if vals.get("kn_transport_ref"): + vals["kn_transport_ref"] = vals["kn_transport_ref"].strip() + return vals + + @api.model_create_multi + def create(self, vals_list): + vals_list = [self._l10n_mx_edi_kn_normalize_vals(vals) for vals in vals_list] + return super().create(vals_list) + + def write(self, vals): + vals = self._l10n_mx_edi_kn_normalize_vals(vals) + return super().write(vals) diff --git a/l10n_mx_edi_addenda_kuehne_nagel/pyproject.toml b/l10n_mx_edi_addenda_kuehne_nagel/pyproject.toml new file mode 100644 index 0000000..4231d0c --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/l10n_mx_edi_addenda_kuehne_nagel/readme/CONFIGURE.md b/l10n_mx_edi_addenda_kuehne_nagel/readme/CONFIGURE.md new file mode 100644 index 0000000..e7017c1 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/readme/CONFIGURE.md @@ -0,0 +1,6 @@ +To configure this module, you need to: + +1. Go to Accounting \> Customers \> Customers +2. Open the Kuehne+Nagel partner +3. In the Sales & Purchase tab, Fiscal Information section, add + **Addenda Kuehne Nagel** to the Addendas & Complements field diff --git a/l10n_mx_edi_addenda_kuehne_nagel/readme/CONTRIBUTORS.md b/l10n_mx_edi_addenda_kuehne_nagel/readme/CONTRIBUTORS.md new file mode 100644 index 0000000..f7c3861 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [Gray Matter Logic](https://www.graymatterlogic.com): + - Maxime Chambreuil \ diff --git a/l10n_mx_edi_addenda_kuehne_nagel/readme/CREDITS.md b/l10n_mx_edi_addenda_kuehne_nagel/readme/CREDITS.md new file mode 100644 index 0000000..e516e9a --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/readme/CREDITS.md @@ -0,0 +1,3 @@ +The development of this module has been financially supported by: + +- [Gray Matter Logic](https://www.graymatterlogic.com) diff --git a/l10n_mx_edi_addenda_kuehne_nagel/readme/DESCRIPTION.md b/l10n_mx_edi_addenda_kuehne_nagel/readme/DESCRIPTION.md new file mode 100644 index 0000000..49fb97c --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/readme/DESCRIPTION.md @@ -0,0 +1,12 @@ +This module adds the KNRECEPCION addenda for Kuehne+Nagel and allows you to +generate electronic invoices (CFDI 4.0) with the required reception block. + +The addenda is inserted under `cfdi:Addenda` with this structure: + +- `kn:KNRECEPCION` + - `kn:Tipo` + - `kn:FacturasKN` + - `kn:Purchase_Order` + - `kn:FileNumber_GL` + - `kn:Branch_Centre` + - `kn:TransportRef` diff --git a/l10n_mx_edi_addenda_kuehne_nagel/readme/USAGE.md b/l10n_mx_edi_addenda_kuehne_nagel/readme/USAGE.md new file mode 100644 index 0000000..6783ddd --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/readme/USAGE.md @@ -0,0 +1,13 @@ +To use this module, you need to: + +1. Go to Accounting \> Customers \> Invoices +2. Create an invoice for the partner configured with **Addenda Kuehne Nagel** +3. Set the Customer Reference for the Purchase Order when applicable +4. Open the **Kuehne+Nagel Addenda** tab and optionally fill: + - File / Tracking Type + - File / Tracking Number + - Branch Centre + - Transport Ref +5. Validate and stamp the invoice as usual + +The module does not enforce a format for the Customer Reference or addenda fields. diff --git a/l10n_mx_edi_addenda_kuehne_nagel/static/description/icon.png b/l10n_mx_edi_addenda_kuehne_nagel/static/description/icon.png new file mode 100644 index 0000000..cb23e16 Binary files /dev/null and b/l10n_mx_edi_addenda_kuehne_nagel/static/description/icon.png differ diff --git a/l10n_mx_edi_addenda_kuehne_nagel/static/description/index.html b/l10n_mx_edi_addenda_kuehne_nagel/static/description/index.html new file mode 100644 index 0000000..1eeea1d --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/static/description/index.html @@ -0,0 +1,480 @@ + + + + + +Mexican Addendum For Invoices For Kuehne+Nagel + + + +
+

Mexican Addendum For Invoices For Kuehne+Nagel

+ + +

Beta License: LGPL-3 amxodoo/enterprise

+

This module adds the KNRECEPCION addenda for Kuehne+Nagel and allows you +to generate electronic invoices (CFDI 4.0) with the required reception +block.

+

The addenda is inserted under cfdi:Addenda with this structure:

+
    +
  • kn:KNRECEPCION
      +
    • kn:Tipo
        +
      • kn:FacturasKN
          +
        • kn:Purchase_Order
        • +
        • kn:FileNumber_GL
        • +
        • kn:Branch_Centre
        • +
        • kn:TransportRef
        • +
        +
      • +
      +
    • +
    +
  • +
+

Table of contents

+ +
+

Configuration

+

To configure this module, you need to:

+
    +
  1. Go to Accounting > Customers > Customers
  2. +
  3. Open the Kuehne+Nagel partner
  4. +
  5. In the Sales & Purchase tab, Fiscal Information section, add +Addenda Kuehne Nagel to the Addendas & Complements field
  6. +
+
+
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to Accounting > Customers > Invoices
  2. +
  3. Create an invoice for the partner configured with Addenda Kuehne +Nagel
  4. +
  5. Set the Customer Reference for the Purchase Order when applicable
  6. +
  7. Open the Kuehne+Nagel Addenda tab and optionally fill:
      +
    • File / Tracking Type
    • +
    • File / Tracking Number
    • +
    • Branch Centre
    • +
    • Transport Ref
    • +
    +
  8. +
  9. Validate and stamp the invoice as usual
  10. +
+

The module does not enforce a format for the Customer Reference or +addenda fields.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub 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.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Gray Matter Logic
  • +
  • Odoo Mexican Association (AMOdoo)
  • +
+
+ +
+

Other credits

+

The development of this module has been financially supported by:

+ +
+
+

Maintainers

+

Current maintainer:

+

max3903

+

This module is part of the amxodoo/enterprise project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/l10n_mx_edi_addenda_kuehne_nagel/tests/__init__.py b/l10n_mx_edi_addenda_kuehne_nagel/tests/__init__.py new file mode 100644 index 0000000..f15da20 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/tests/__init__.py @@ -0,0 +1 @@ +from . import test_account_move diff --git a/l10n_mx_edi_addenda_kuehne_nagel/tests/test_account_move.py b/l10n_mx_edi_addenda_kuehne_nagel/tests/test_account_move.py new file mode 100644 index 0000000..2dd9394 --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/tests/test_account_move.py @@ -0,0 +1,173 @@ +# Copyright (C) 2026 Gray Matter Logic (https://www.graymatterlogic.com) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from lxml import etree + +from odoo.tests import tagged + +from odoo.addons.account.tests.common import AccountTestInvoicingCommon + +KN_NS = {"kn": "http://www.w3.org/2001/XMLSchema"} + + +@tagged("post_install", "-at_install") +class TestKnAddenda(AccountTestInvoicingCommon): + @classmethod + @AccountTestInvoicingCommon.setup_country("mx") + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) + cls.addenda = cls.env.ref( + "l10n_mx_edi_addenda_kuehne_nagel.l10n_mx_edi_addenda_kuehne_nagel" + ) + cls.partner_kn = cls.env["res.partner"].create( + { + "name": "Kuehne Nagel Test", + "company_type": "company", + "l10n_mx_edi_addenda_ids": [(6, 0, cls.addenda.ids)], + } + ) + cls.partner_other = cls.env["res.partner"].create( + { + "name": "Other Customer", + "company_type": "company", + } + ) + + def _create_invoice(self, partner, **extra): + invoice = self.init_invoice( + "out_invoice", + partner=partner, + products=self.product_a, + ) + if extra: + invoice.write(extra) + return invoice + + def _render_kn_addenda(self, invoice): + """Render the KN addenda QWeb arch for an invoice. + + In 19.0 the addenda is ``l10n_mx_edi.addenda``, not ``ir.ui.view``, so + ``ir.qweb._render(self.addenda.id)`` is invalid. Decode the arch the + same way CFDI generation does, then render that fragment. + """ + decoded = self.addenda._decode_single_addenda_arch() + self.assertNotIn("error", decoded, decoded.get("error")) + nsmap = { + **decoded.get("comprobante", {}).get("nsmap", {}), + **decoded.get("addenda", {}).get("nsmap", {}), + } + if not nsmap: + nsmap = dict(KN_NS) + template_xml = self.env["l10n_mx_edi.addenda"]._wrap_xml_with_namespaces( + decoded["addenda"]["arch"], nsmap + ) + rendered = self.env["ir.qweb"]._render( + etree.fromstring(template_xml), + {"record": invoice}, + ) + return etree.fromstring(rendered) + + def _kn_field_text(self, root, name): + element = root.find(f".//kn:{name}", namespaces=KN_NS) + self.assertIsNotNone(element, name) + return (element.text or "").strip() + + def test_addenda_record_loaded(self): + self.assertEqual(self.addenda.name, "Addenda Kuehne Nagel") + + def test_kn_flag_on_partner_with_addenda(self): + invoice = self._create_invoice(self.partner_kn) + self.assertTrue(invoice.kn_flag) + self.assertIn(self.addenda, self.partner_kn.l10n_mx_edi_addenda_ids) + + def test_kn_flag_false_for_other_partner(self): + invoice = self._create_invoice(self.partner_other) + self.assertFalse(invoice.kn_flag) + + def test_normalize_kn_values(self): + invoice = self._create_invoice( + self.partner_kn, + kn_file_type="file", + kn_file_number_gl=" 7310880180505405 ", + kn_branch_centre=" 10dwt ", + kn_transport_ref=" 2886541 ", + ) + self.assertEqual(invoice.kn_file_number_gl, "7310880180505405") + self.assertEqual(invoice.kn_branch_centre, "10DWT") + self.assertEqual(invoice.kn_transport_ref, "2886541") + + def test_ref_is_preserved_for_kn(self): + invoice = self._create_invoice( + self.partner_kn, + ref="Customer PO/abc-123", + ) + self.assertEqual(invoice.ref, "Customer PO/abc-123") + + def test_arbitrary_kn_field_formats_are_allowed(self): + invoice = self._create_invoice(self.partner_kn) + invoice.write( + { + "kn_file_type": "file", + "kn_file_number_gl": "12345", + "kn_branch_centre": "AB", + "kn_transport_ref": "123", + } + ) + self.assertEqual(invoice.kn_file_number_gl, "12345") + self.assertEqual(invoice.kn_branch_centre, "AB") + self.assertEqual(invoice.kn_transport_ref, "123") + + def test_empty_optional_fields_are_allowed(self): + invoice = self._create_invoice(self.partner_kn, ref=False) + self.assertFalse(invoice.ref) + self.assertFalse(invoice.kn_file_type) + self.assertFalse(invoice.kn_file_number_gl) + self.assertFalse(invoice.kn_branch_centre) + self.assertFalse(invoice.kn_transport_ref) + + def test_qweb_addenda_xml_structure(self): + invoice = self._create_invoice( + self.partner_kn, + ref=False, + kn_file_type="file", + kn_file_number_gl="7310880180505405", + kn_branch_centre="10DWT", + kn_transport_ref="2886541", + ) + root = self._render_kn_addenda(invoice) + self.assertTrue(root.tag.endswith("KNRECEPCION")) + self.assertEqual(self._kn_field_text(root, "Purchase_Order"), "") + self.assertEqual(self._kn_field_text(root, "FileNumber_GL"), "7310880180505405") + self.assertEqual(self._kn_field_text(root, "Branch_Centre"), "10DWT") + self.assertEqual(self._kn_field_text(root, "TransportRef"), "2886541") + + def test_qweb_addenda_with_purchase_order(self): + invoice = self._create_invoice( + self.partner_kn, + ref="Customer PO/abc-123", + kn_file_type="tracking", + kn_file_number_gl="1023950106-1815", + kn_branch_centre="99NFP", + kn_transport_ref="1234567", + ) + root = self._render_kn_addenda(invoice) + self.assertTrue(root.tag.endswith("KNRECEPCION")) + self.assertEqual( + self._kn_field_text(root, "Purchase_Order"), "Customer PO/abc-123" + ) + self.assertEqual(self._kn_field_text(root, "FileNumber_GL"), "1023950106-1815") + self.assertEqual(self._kn_field_text(root, "Branch_Centre"), "99NFP") + self.assertEqual(self._kn_field_text(root, "TransportRef"), "1234567") + + def test_qweb_addenda_with_empty_optional_fields(self): + invoice = self._create_invoice(self.partner_kn, ref=False) + root = self._render_kn_addenda(invoice) + self.assertTrue(root.tag.endswith("KNRECEPCION")) + for field_name in ( + "Purchase_Order", + "FileNumber_GL", + "Branch_Centre", + "TransportRef", + ): + self.assertEqual(self._kn_field_text(root, field_name), "") diff --git a/l10n_mx_edi_addenda_kuehne_nagel/views/account_move_views.xml b/l10n_mx_edi_addenda_kuehne_nagel/views/account_move_views.xml new file mode 100644 index 0000000..3725d5e --- /dev/null +++ b/l10n_mx_edi_addenda_kuehne_nagel/views/account_move_views.xml @@ -0,0 +1,38 @@ + + + + account.move.form.inherit.addenda.kuehne.nagel + account.move + + + + + + + + + + + + +
+

+ Purchase Order uses the Customer Reference field as entered. +

+

+ Addenda fields are optional and do not enforce a format. +

+
+
+
+
+
+
+
diff --git a/l10n_mx_edi_addenda_mabe/README.rst b/l10n_mx_edi_addenda_mabe/README.rst index 2b091a2..59c5acf 100644 --- a/l10n_mx_edi_addenda_mabe/README.rst +++ b/l10n_mx_edi_addenda_mabe/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ====================================== Mexican Addendum For Invoices For MABE ====================================== diff --git a/l10n_mx_edi_addenda_volkswagen/README.rst b/l10n_mx_edi_addenda_volkswagen/README.rst index 9640cf7..8ed3db5 100644 --- a/l10n_mx_edi_addenda_volkswagen/README.rst +++ b/l10n_mx_edi_addenda_volkswagen/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ============================================ Mexican Addendum For Invoices For Volkswagen ============================================ diff --git a/l10n_mx_edi_addenda_whirlpool/README.rst b/l10n_mx_edi_addenda_whirlpool/README.rst index ef00849..a327430 100644 --- a/l10n_mx_edi_addenda_whirlpool/README.rst +++ b/l10n_mx_edi_addenda_whirlpool/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - =========================================== Mexican Addendum For Invoices For Whirlpool ===========================================