Skip to content
Open
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
51 changes: 29 additions & 22 deletions account_move_export/models/account_move_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand All @@ -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"]
Expand All @@ -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"
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -617,9 +624,9 @@ def _lock(self):
)
else:
self.message_post(
body=Markup(_(
"Lock date <b>not updated</b> because the end date is not set."
))
body=Markup(
_("Lock date <b>not updated</b> because the end date is not set.")
)
)

def _update_lock_vals(self, field, vals):
Expand Down
21 changes: 13 additions & 8 deletions account_move_export_quadra/README.rst
Original file line number Diff line number Diff line change
@@ -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
==========================
Expand All @@ -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|

Expand Down Expand Up @@ -47,10 +51,10 @@ The attachment should exist before exporting.
Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/akretion/account-move-export/issues>`_.
Bugs are tracked on `GitHub Issues <https://github.com/Akretion/account-move-export/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/akretion/account-move-export/issues/new?body=module:%20account_move_export_quadra%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/Akretion/account-move-export/issues/new?body=module:%20account_move_export_quadra%0Aversion:%2018.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.

Expand All @@ -66,6 +70,7 @@ Contributors
~~~~~~~~~~~~

* Raphaël Reverdy <[email protected]>
* Thomas BONNERUE <[email protected]>

Maintainers
~~~~~~~~~~~
Expand All @@ -78,6 +83,6 @@ Current maintainer:

|maintainer-hparfr|

This module is part of the `akretion/account-move-export <https://github.com/akretion/account-move-export/tree/16.0/account_move_export_quadra>`_ project on GitHub.
This module is part of the `Akretion/account-move-export <https://github.com/Akretion/account-move-export/tree/18.0/account_move_export_quadra>`_ project on GitHub.

You are welcome to contribute.
4 changes: 2 additions & 2 deletions account_move_export_quadra/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

{
"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",
"author": "Akretion",
"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",
],
Expand Down
1 change: 1 addition & 0 deletions account_move_export_quadra/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from . import account_move_export
from . import account_move_line
from . import account_move_config
from . import account_analytique_line
27 changes: 27 additions & 0 deletions account_move_export_quadra/models/account_analytique_line.py
Original file line number Diff line number Diff line change
@@ -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)
102 changes: 67 additions & 35 deletions account_move_export_quadra/models/account_move_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -76,14 +77,31 @@ 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):
# return an array of string
# 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]
Expand Down Expand Up @@ -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
Loading
Loading