diff --git a/account_move_export/models/account_move_export.py b/account_move_export/models/account_move_export.py index a2d6642..b244fa1 100644 --- a/account_move_export/models/account_move_export.py +++ b/account_move_export/models/account_move_export.py @@ -189,7 +189,7 @@ def _compute_counts(self): rg_move_res = self.env["account.move"]._read_group( [("account_move_export_id", "in", self.ids)], groupby=["account_move_export_id"], - aggregates=['__count'], + aggregates=["__count"], ) move_data = {export.id: move_count for (export, move_count) in rg_move_res} for export in self: @@ -335,11 +335,11 @@ def _prepare_export_options(self): "cols": self._prepare_columns(), } if self.config_id.analytic_option == "plan_filter": - export_options[ - "analytic_plan_ids" - ] = self.config_id.analytic_plan_ids.filtered( - lambda x: x.company_id.id == self.company_id.id - ).ids + export_options["analytic_plan_ids"] = ( + self.config_id.analytic_plan_ids.filtered( + lambda x: x.company_id.id == self.company_id.id + ).ids + ) if self.config_id.partner_option == "accounts": if not self.config_id.partner_account_ids.filtered( lambda x: self.company_id.id in x.company_ids.ids @@ -351,11 +351,11 @@ def _prepare_export_options(self): "will be exported." ) ) - export_options[ - "partner_account_ids" - ] = self.config_id.partner_account_ids.filtered( - lambda x: self.company_id.id in x.company_ids.ids - ).ids + export_options["partner_account_ids"] = ( + self.config_id.partner_account_ids.filtered( + lambda x: self.company_id.id in x.company_ids.ids + ).ids + ) elif self.config_id.partner_option == "receivable_payable": # just for perf export_options["partner_account_ids"] = ( self.env["account.account"] @@ -373,14 +373,17 @@ def _prepare_export_options(self): ) if self.config_id.suspense_account_raise: suspense_account_ids = set() - journals = self.env['account.journal'].search_read([ - ('company_id', '=', self.company_id.id), - ('type', 'in', ('bank', 'cash', 'credit')), - ('suspense_account_id', '!=', False), - ], ['suspense_account_id']) + journals = self.env["account.journal"].search_read( + [ + ("company_id", "=", self.company_id.id), + ("type", "in", ("bank", "cash", "credit")), + ("suspense_account_id", "!=", False), + ], + ["suspense_account_id"], + ) for journal in journals: - suspense_account_ids.add(journal['suspense_account_id'][0]) - export_options['suspense_account_ids'] = list(suspense_account_ids) + suspense_account_ids.add(journal["suspense_account_id"][0]) + export_options["suspense_account_ids"] = list(suspense_account_ids) if self.config_id.file_format and self.config_id.file_format.startswith("csv"): if ( self.config_id.quoting == "none" @@ -502,7 +505,11 @@ def _generate_xlsx_generic(self): def _generate_csv_generic(self): tmpfile = StringIO() export_options = self._prepare_export_options() - col_list = [col["header_label"] for col in export_options["cols"]] + cols = export_options["cols"] + col_list = [] + for col in cols: + col_list.append(col["header_label"]) + # col_list = [col["header_label"] for col in export_options["cols"]] w = csv.DictWriter( tmpfile, col_list, @@ -617,9 +624,9 @@ def _lock(self): ) else: self.message_post( - body=Markup(_( - "Lock date not updated because the end date is not set." - )) + body=Markup( + _("Lock date not updated because the end date is not set.") + ) ) def _update_lock_vals(self, field, vals): diff --git a/account_move_export_quadra/README.rst b/account_move_export_quadra/README.rst index e86963c..f5defb3 100644 --- a/account_move_export_quadra/README.rst +++ b/account_move_export_quadra/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ========================== Account Move Export Quadra ========================== @@ -7,18 +11,18 @@ Account Move Export Quadra !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:7ae4266c76a7a018ff841ee77ed27ef317a8b67f88931803e7429fdba2836772 + !! source digest: sha256:2fdcc9c7e3d6fde82c78f91bfed6ce818fe9d2ba113a66817afc7c3e6f302c1b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |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/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-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-akretion%2Faccount--move--export-lightgray.png?logo=github - :target: https://github.com/akretion/account-move-export/tree/16.0/account_move_export_quadra - :alt: akretion/account-move-export +.. |badge3| image:: https://img.shields.io/badge/github-Akretion%2Faccount--move--export-lightgray.png?logo=github + :target: https://github.com/Akretion/account-move-export/tree/18.0/account_move_export_quadra + :alt: Akretion/account-move-export |badge1| |badge2| |badge3| @@ -47,10 +51,10 @@ The attachment should exist before exporting. Bug Tracker =========== -Bugs are tracked on `GitHub Issues `_. +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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -66,6 +70,7 @@ Contributors ~~~~~~~~~~~~ * Raphaël Reverdy +* Thomas BONNERUE Maintainers ~~~~~~~~~~~ @@ -78,6 +83,6 @@ Current maintainer: |maintainer-hparfr| -This module is part of the `akretion/account-move-export `_ project on GitHub. +This module is part of the `Akretion/account-move-export `_ project on GitHub. You are welcome to contribute. diff --git a/account_move_export_quadra/__manifest__.py b/account_move_export_quadra/__manifest__.py index 22bd411..22e75de 100644 --- a/account_move_export_quadra/__manifest__.py +++ b/account_move_export_quadra/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Account Move Export Quadra", - "version": "16.0.1.0.0", + "version": "18.0.1.0.0", "category": "Accounting", "license": "AGPL-3", "summary": "Export journal entries to Quadratus Compta", @@ -12,7 +12,7 @@ "maintainers": ["hparfr"], "website": "https://github.com/akretion/account-move-export", "depends": ["account_move_export"], - "installable": False, + "installable": True, "data": [ "data/account_move_export_quadra_config.xml", ], diff --git a/account_move_export_quadra/models/__init__.py b/account_move_export_quadra/models/__init__.py index 3dbaebc..4d7732d 100644 --- a/account_move_export_quadra/models/__init__.py +++ b/account_move_export_quadra/models/__init__.py @@ -1,3 +1,4 @@ from . import account_move_export from . import account_move_line from . import account_move_config +from . import account_analytique_line diff --git a/account_move_export_quadra/models/account_analytique_line.py b/account_move_export_quadra/models/account_analytique_line.py new file mode 100644 index 0000000..32b743b --- /dev/null +++ b/account_move_export_quadra/models/account_analytique_line.py @@ -0,0 +1,27 @@ +# Copyright 2025 Akretion France (http://www.akretion.com/) +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from collections import OrderedDict + +from odoo import models + + +class AccuntAnalyticLine(models.Model): + _inherit = "account.analytic.line" + + def _prepare_account_move_export_line(self, export_options): + if "cols_analytic" in export_options.keys(): + amount = str(abs(int(self.amount * 100))) + + code = str(self.x_plan2_id.code) + json_disr = self.move_line_id.analytic_distribution + pourcent = str(int(list(json_disr.values())[0] * 100)) + our = OrderedDict() + our["Type"] = "I" + our["% de la répartition"] = pourcent + our["Montant répartition"] = amount + our["Code centre"] = code + our["Code nature"] = "" + return our + else: + return super()._prepare_account_move_export_line(export_options) diff --git a/account_move_export_quadra/models/account_move_export.py b/account_move_export_quadra/models/account_move_export.py index 9d0dfe0..1f9352b 100644 --- a/account_move_export_quadra/models/account_move_export.py +++ b/account_move_export_quadra/models/account_move_export.py @@ -22,6 +22,7 @@ def _prepare_export_options(self): attachments = self._quadra_attachments() res["attachments"] = attachments res["encoding"] = self.config_id.encoding + res["cols_analytic"] = self._prepare_columns_analytic() return res def _quadra_attachments(self): @@ -76,6 +77,20 @@ def _generate_txt_quadra(self): ) # * to unpack mline_list print(*mline_list, sep="", file=tmpfile) # pylint: disable=W8116 + + if export_options["analytic_option"] == "all": + alines = mline.analytic_line_ids + elif export_options["analytic_option"] == "plan_filter": + alines = mline.analytic_line_ids.filtered( + lambda x: x.plan_id.id in export_options["analytic_plan_ids"] + ) + if export_options["analytic_option"] in ("all", "plan_filter"): + for aline in alines: + aline_dict = aline._prepare_account_move_export_line( + export_options + ) + row = self._quadra_postprocess_line(aline_dict, export_options) + print(*row, sep="", file=tmpfile) return self._quadra_encode(tmpfile, export_options) def _quadra_postprocess_line(self, ldict, export_options): @@ -83,7 +98,10 @@ def _quadra_postprocess_line(self, ldict, export_options): # troncate values and sort columns # we use ljust / rjust instead of fstring # for better support of older version of python - cols = export_options["cols"] + if ldict["Type"] == "I": + cols = export_options["cols_analytic"] + else: + cols = export_options["cols"] res = [] for key, constraint in cols.items(): value = ldict[key] @@ -116,41 +134,55 @@ def _quadra_encode(self, data_str, export_options): return self._csv_encode(data_str, export_options) def _prepare_columns(self): + if self.config_id.name == "Default Quadra Export Configuration": + cols = OrderedDict() + # in French to be constistent with the specification + # Fichier-d-entree-ascii-dans-quadracompta.pdf + cols["Type"] = {"width": 1} + cols["Numéro de compte"] = {"width": 8} + cols["Code journal"] = {"width": 2} + cols["N° folio"] = {"width": 3} # always 000 + cols["Date écriture"] = {"width": 6} + cols["Code libellé"] = {"width": 1} # osef + cols["Libellé libre"] = {"width": 20} # osef + cols["Sens Débit/Crédit"] = {"width": 1} + cols["Signe"] = {"width": 1} + cols["Montant en centimes non signé"] = {"width": 12} + cols["Compte de contrepartie"] = {"width": 8} # osef + cols["Date échéance"] = {"width": 6} + cols["Code lettrage"] = {"width": 2} + cols["Code statistiques"] = {"width": 3} # osef + cols["N° de pièce"] = {"width": 5} + cols["Code affaire"] = {"width": 10} # osef + cols["Quantité 1"] = {"width": 10} + cols["Numéro de pièce"] = {"width": 8} + cols["Code devise"] = {"width": 3} + cols["Code journal sur 3"] = {"width": 3} + cols["Flag Code TVA"] = {"width": 1} # osef + cols["Méthode de calcul TVA"] = {"width": 1} # osef + cols["Code TVA"] = {"width": 1} # osef + cols["Libellé écriture sur 30 caract"] = {"width": 30} + cols["Code TVA 2"] = {"width": 3} + cols["N° de pièce alphanumérique"] = {"width": 10} + cols["Reservé"] = {"width": 10} # osef + cols["Montant dans la devise"] = {"width": 13} # osef + cols["Pièce jointe à l'écriture"] = {"width": 12} # osef + cols["Quantité 2"] = {"width": 10} # osef + cols["NumUniq"] = {"width": 10} # osef + cols["Code opérateur"] = {"width": 4} # osef + cols["Date système"] = {"width": 14} # osef + cols["Numero de pièce"] = {"width": 20} # prio si renseigner + else: + cols = super()._prepare_columns() + + return cols + + def _prepare_columns_analytic(self): cols = OrderedDict() - # in French to be constistent with the specification - # Fichier-d-entree-ascii-dans-quadracompta.pdf cols["Type"] = {"width": 1} - cols["Numéro de compte"] = {"width": 8} - cols["Code journal"] = {"width": 2} - cols["N° folio"] = {"width": 3} # always 000 - cols["Date écriture"] = {"width": 6} - cols["Code libellé"] = {"width": 1} # osef - cols["Libellé libre"] = {"width": 20} # osef - cols["Sens Débit/Crédit"] = {"width": 1} - cols["Signe"] = {"width": 1} - cols["Montant en centimes non signé"] = {"width": 12} - cols["Compte de contrepartie"] = {"width": 8} # osef - cols["Date échéance"] = {"width": 6} - cols["Code lettrage"] = {"width": 2} - cols["Code statistiques"] = {"width": 3} # osef - cols["N° de pièce"] = {"width": 5} - cols["Code affaire"] = {"width": 10} # osef - cols["Quantité 1"] = {"width": 10} - cols["Numéro de pièce"] = {"width": 8} - cols["Code devise"] = {"width": 3} - cols["Code journal sur 3"] = {"width": 3} - cols["Flag Code TVA"] = {"width": 1} # osef - cols["Méthode de calcul TVA"] = {"width": 1} # osef - cols["Code TVA"] = {"width": 1} # osef - cols["Libellé écriture sur 30 caract"] = {"width": 30} - cols["Code TVA 2"] = {"width": 3} - cols["N° de pièce alphanumérique"] = {"width": 10} - cols["Reservé"] = {"width": 10} # osef - cols["Montant dans la devise"] = {"width": 13} # osef - cols["Pièce jointe à l'écriture"] = {"width": 12} # osef - cols["Quantité 2"] = {"width": 10} # osef - cols["NumUniq"] = {"width": 10} # osef - cols["Code opérateur"] = {"width": 4} # osef - cols["Date système"] = {"width": 14} # osef + cols["% de la répartition"] = {"width": 5} + cols["Montant répartition"] = {"width": 13} + cols["Code centre"] = {"width": 10} + cols["Code nature"] = {"width": 10} return cols diff --git a/account_move_export_quadra/models/account_move_line.py b/account_move_export_quadra/models/account_move_line.py index 87f0dba..94e2d8b 100644 --- a/account_move_export_quadra/models/account_move_line.py +++ b/account_move_export_quadra/models/account_move_line.py @@ -10,44 +10,48 @@ class AccountMoveLine(models.Model): _inherit = "account.move.line" def _prepare_account_move_export_line(self, export_options): - attachment_id = export_options["attachments"].get(self.move_id.id, False) - attachment = attachment_id["filename"] if attachment_id else "" + if "attachments" in export_options.keys(): + attachment_id = export_options["attachments"].get(self.move_id.id, False) + attachment = attachment_id["filename"] if attachment_id else "" default = super()._prepare_account_move_export_line(export_options) - - # Always default to "" instead of False - our = OrderedDict() - our["Type"] = "M" - our["Numéro de compte"] = default["account_code"] - our["Code journal"] = default["journal_code"] - our["N° folio"] = "000" - our["Date écriture"] = default["date"] - our["Code libellé"] = "" - our["Libellé libre"] = "" - our["Sens Débit/Crédit"] = "D" if default["debit"] > 0 else "C" - our["Signe"] = "+" if default["balance"] >= 0 else "-" - our["Montant en centimes non signé"] = abs(default["balance"] * 100) - our["Compte de contrepartie"] = "" - our["Date échéance"] = default["due_date"] or "" - our["Code lettrage"] = self.full_reconcile_id.name - our["Code statistiques"] = "" - our["N° de pièce"] = self.move_id.id - our["Code affaire"] = "" - our["Quantité 1"] = "" - our["Numéro de pièce"] = default["entry_ref"] - our["Code devise"] = default["origin_currency_code"] - our["Code journal sur 3"] = default["journal_code"] - our["Flag Code TVA"] = "" - our["Code TVA"] = "" - our["Méthode de calcul TVA"] = "" - our["Libellé écriture sur 30 caract"] = default["item_label"] - our["Code TVA 2"] = "" - our["N° de pièce alphanumérique"] = default["entry_number"] - our["Reservé"] = "" - our["Montant dans la devise"] = default["origin_currency_amount"] - our["Pièce jointe à l'écriture"] = attachment - our["Quantité 2"] = "" - our["NumUniq"] = "" - our["Code opérateur"] = "" - our["Date système"] = "" - return our + if "attachments" in export_options.keys(): + # Always default to "" instead of False + our = OrderedDict() + our["Type"] = "M" + our["Numéro de compte"] = default["account_code"] + our["Code journal"] = default["journal_code"] + our["N° folio"] = "000" + our["Date écriture"] = default["date"] + our["Code libellé"] = "" + our["Libellé libre"] = "" + our["Sens Débit/Crédit"] = "D" if default["debit"] > 0 else "C" + our["Signe"] = "+" # if default["balance"] >= 0 else "-" + our["Montant en centimes non signé"] = abs(default["balance"] * 100) + our["Compte de contrepartie"] = "" + our["Date échéance"] = default["due_date"] or "" + our["Code lettrage"] = "" + our["Code statistiques"] = "" + our["N° de pièce"] = self.move_id.id + our["Code affaire"] = "" + our["Quantité 1"] = "" + our["Numéro de pièce"] = default["entry_ref"] + our["Code devise"] = default["origin_currency_code"] + our["Code journal sur 3"] = default["journal_code"] + our["Flag Code TVA"] = "" + our["Code TVA"] = "" + our["Méthode de calcul TVA"] = "" + our["Libellé écriture sur 30 caract"] = default["item_label"] + our["Code TVA 2"] = "" + our["N° de pièce alphanumérique"] = "" # default["entry_number"] + our["Reservé"] = "" + our["Montant dans la devise"] = default["origin_currency_amount"] + our["Pièce jointe à l'écriture"] = attachment + our["Quantité 2"] = "" + our["NumUniq"] = "" + our["Code opérateur"] = "" + our["Date système"] = "" + our["Numero de pièce"] = default["entry_number"] + return our + else: + return default diff --git a/account_move_export_quadra/readme/CONTRIBUTORS.rst b/account_move_export_quadra/readme/CONTRIBUTORS.rst index dc3bfce..58ef3ea 100644 --- a/account_move_export_quadra/readme/CONTRIBUTORS.rst +++ b/account_move_export_quadra/readme/CONTRIBUTORS.rst @@ -1 +1,2 @@ * Raphaël Reverdy +* Thomas BONNERUE diff --git a/account_move_export_quadra/static/description/index.html b/account_move_export_quadra/static/description/index.html index f232651..0f3b209 100644 --- a/account_move_export_quadra/static/description/index.html +++ b/account_move_export_quadra/static/description/index.html @@ -3,7 +3,7 @@ -Account Move Export Quadra +README.rst -
-

Account Move Export Quadra

+
+ + +Odoo Community Association + +
+

Account Move Export Quadra

-

Beta License: AGPL-3 akretion/account-move-export

+

Beta License: AGPL-3 Akretion/account-move-export

Export account moves for QuadraCOMPTA

Reference: QC_ASC.doc – Mise à jour 02/2015

Fixed format.

@@ -392,35 +397,37 @@

Account Move Export Quadra

-

Bug Tracker

-

Bugs are tracked on GitHub Issues. +

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.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Akretion
-

Maintainers

+

Maintainers

Current maintainer:

hparfr

-

This module is part of the akretion/account-move-export project on GitHub.

+

This module is part of the Akretion/account-move-export project on GitHub.

You are welcome to contribute.

+