From f3b5f85fc9ff1a355e761370b6c18867a00020ec Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Tue, 22 Oct 2024 14:34:45 +0200 Subject: [PATCH] [IMP] account_bank_reconciliation_summary_xlsx: support bank journals in currency different than company currency Update fr translation --- .../__manifest__.py | 4 +- .../i18n/fr.po | 61 ++++++-- .../report/bank_reconciliation_xlsx.py | 137 +++++++++++------- .../report/report.xml | 3 +- .../views/account_bank_statement.xml | 2 +- .../views/account_journal.xml | 4 +- .../bank_reconciliation_report_wizard.py | 2 +- ...bank_reconciliation_report_wizard_view.xml | 2 +- 8 files changed, 141 insertions(+), 74 deletions(-) diff --git a/account_bank_reconciliation_summary_xlsx/__manifest__.py b/account_bank_reconciliation_summary_xlsx/__manifest__.py index c9dd4c1..3981ccd 100644 --- a/account_bank_reconciliation_summary_xlsx/__manifest__.py +++ b/account_bank_reconciliation_summary_xlsx/__manifest__.py @@ -1,10 +1,10 @@ -# Copyright 2017-2023 Akretion France (http://www.akretion.com/) +# Copyright 2017-2024 Akretion France (http://www.akretion.com/) # @author: Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Bank Reconciliation Report", - "version": "14.0.1.0.0", + "version": "14.0.2.0.0", "license": "AGPL-3", "author": "Akretion", "website": "https://github.com/akretion/odoo-usability", diff --git a/account_bank_reconciliation_summary_xlsx/i18n/fr.po b/account_bank_reconciliation_summary_xlsx/i18n/fr.po index 4fd5912..158cec0 100644 --- a/account_bank_reconciliation_summary_xlsx/i18n/fr.po +++ b/account_bank_reconciliation_summary_xlsx/i18n/fr.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-13 10:31+0000\n" -"PO-Revision-Date: 2023-01-13 10:31+0000\n" +"POT-Creation-Date: 2024-10-22 10:40+0000\n" +"PO-Revision-Date: 2024-10-22 10:40+0000\n" "Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" @@ -49,7 +49,7 @@ msgstr "Rapport de rapprochement bancaire" #. module: account_bank_reconciliation_summary_xlsx #: model:ir.model,name:account_bank_reconciliation_summary_xlsx.model_bank_reconciliation_report_wizard msgid "Bank Reconciliation Report Wizard" -msgstr "Assistant rapport de rapprochement bancaire" +msgstr "Assistant de rapport de rapprochement bancaire" #. module: account_bank_reconciliation_summary_xlsx #: model:ir.actions.report,name:account_bank_reconciliation_summary_xlsx.bank_reconciliation_xlsx @@ -94,6 +94,12 @@ msgstr "Créé par" msgid "Created on" msgstr "Créé le" +#. module: account_bank_reconciliation_summary_xlsx +#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 +#, python-format +msgid "Currency" +msgstr "Devise" + #. module: account_bank_reconciliation_summary_xlsx #: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 #: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 @@ -106,7 +112,7 @@ msgstr "" #: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__display_name #: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_report_bank_reconciliation_xlsx__display_name msgid "Display Name" -msgstr "" +msgstr "Nom affiché" #. module: account_bank_reconciliation_summary_xlsx #: model:ir.model.fields.selection,name:account_bank_reconciliation_summary_xlsx.selection__bank_reconciliation_report_wizard__move_state__draft_posted @@ -123,13 +129,13 @@ msgstr "Écritures" #. module: account_bank_reconciliation_summary_xlsx #: model_terms:ir.ui.view,arch_db:account_bank_reconciliation_summary_xlsx.bank_reconciliation_report_wizard_form msgid "Export XLSX" -msgstr "" +msgstr "Exporter en XLSX" #. module: account_bank_reconciliation_summary_xlsx #: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 #, python-format -msgid "Generated on %s" -msgstr "Généré le %s" +msgid "Generated from Odoo on %s by %s" +msgstr "Généré par Odoo le %s par %s" #. module: account_bank_reconciliation_summary_xlsx #: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__id @@ -143,6 +149,12 @@ msgstr "" msgid "Journal" msgstr "" +#. module: account_bank_reconciliation_summary_xlsx +#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 +#, python-format +msgid "Journal Entry" +msgstr "Pièce" + #. module: account_bank_reconciliation_summary_xlsx #: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 #, python-format @@ -153,23 +165,17 @@ msgstr "Libellé" #: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard____last_update #: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_report_bank_reconciliation_xlsx____last_update msgid "Last Modified on" -msgstr "" +msgstr "Dernière modification le" #. module: account_bank_reconciliation_summary_xlsx #: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__write_uid msgid "Last Updated by" -msgstr "" +msgstr "Dernière mise à jour par" #. module: account_bank_reconciliation_summary_xlsx #: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__write_date msgid "Last Updated on" -msgstr "" - -#. module: account_bank_reconciliation_summary_xlsx -#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 -#, python-format -msgid "Move Number" -msgstr "Numéro de pièce" +msgstr "Dernière mise à jour le" #. module: account_bank_reconciliation_summary_xlsx #: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 @@ -179,10 +185,23 @@ msgstr "Aucun journal de banque sélectionné." #. module: account_bank_reconciliation_summary_xlsx #: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 +#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 #, python-format msgid "None" msgstr "Aucun" +#. module: account_bank_reconciliation_summary_xlsx +#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 +#, python-format +msgid "" +"On bank journal %(journal)s which is configured with currency " +"%(journal_currency)s, the account %(account)s must be configured with the " +"same currency (current account currency: %(account_currency)s)." +msgstr "" +"Sur le journal de banque %(journal)s qui est configuré avec la devise " +"%(journal_currency)s, le compte %(account)s doit être configuré avec la même" +" devise (devise actuelle du compte : %(account_currency)s)." + #. module: account_bank_reconciliation_summary_xlsx #: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 #, python-format @@ -211,3 +230,13 @@ msgstr "Sous-total :" #, python-format msgid "TOTAL:" msgstr "TOTAL :" + +#. module: account_bank_reconciliation_summary_xlsx +#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0 +#, python-format +msgid "" +"The are %(count)s journal items in account %(account)s that have a currency " +"other than %(currency)s or where currency is not set." +msgstr "" +"Il y a %(count)s écritures comptables dans le compte %(account)s qui ont une" +" devise autre que %(currency)s ou dont la devise n'est pas définie." diff --git a/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py b/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py index 7dda405..0260927 100644 --- a/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py +++ b/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py @@ -1,4 +1,4 @@ -# Copyright 2017-2023 Akretion France (http://www.akretion.com/) +# Copyright 2017-2024 Akretion France (http://www.akretion.com/) # @author: Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -14,32 +14,32 @@ class BankReconciliationXlsx(models.AbstractModel): _description = "Bank Reconciliation XLSX Report" _inherit = "report.report_xlsx.abstract" - def _domain_add_move_state(self, wizard, domain): - if wizard.move_state == 'posted': + def _domain_add_move_state(self, jdi, domain): + if jdi['wizard'].move_state == 'posted': domain.append(('parent_state', '=', 'posted')) - elif wizard.move_state == 'draft_posted': + elif jdi['wizard'].move_state == 'draft_posted': domain.append(('parent_state', 'in', ('draft', 'posted'))) - def _get_account_balance(self, account, wizard): + def _get_account_balance(self, jdi): domain = [ - ('account_id', '=', account.id), - ('date', '<=', wizard.date), - ('company_id', '=', wizard.company_id.id), + ('account_id', '=', jdi['bank_account'].id), + ('date', '<=', jdi['wizard'].date), + ('company_id', '=', jdi['company'].id), ] - self._domain_add_move_state(wizard, domain) - res_rg = self.env['account.move.line'].read_group(domain, ['balance:sum'], []) - account_bal = res_rg and res_rg[0].get('balance', 0.0) or 0.0 + self._domain_add_move_state(jdi, domain) + res_rg = self.env['account.move.line'].read_group(domain, ['amount_currency:sum'], []) + account_bal = res_rg and res_rg[0].get('amount_currency', 0.0) or 0.0 return account_bal - def _prepare_payment_move_lines(self, journal, account, wizard, unreconciled_only=True): + def _prepare_payment_move_lines(self, jdi, account, unreconciled_only=True): domain = [ - ("company_id", "=", wizard.company_id.id), + ("company_id", "=", jdi['company'].id), ("account_id", "=", account.id), - ("journal_id", "=", journal.id), - ("date", "<=", wizard.date), + ("journal_id", "=", jdi['journal'].id), + ("date", "<=", jdi['wizard'].date), ] if unreconciled_only: - limit_datetime_naive = datetime.combine(wizard.date, datetime.max.time()) + limit_datetime_naive = datetime.combine(jdi['wizard'].date, datetime.max.time()) tz = pytz.timezone(self.env.user.tz) limit_datetime_aware = tz.localize(limit_datetime_naive) limit_datetime_utc = limit_datetime_aware.astimezone(pytz.utc) @@ -47,7 +47,7 @@ class BankReconciliationXlsx(models.AbstractModel): domain += [ '|', ('full_reconcile_id', '=', False), ('full_reconcile_id.create_date', '>', limit_datetime)] - self._domain_add_move_state(wizard, domain) + self._domain_add_move_state(jdi, domain) mlines = self.env["account.move.line"].search(domain) res = [] for mline in mlines: @@ -60,13 +60,18 @@ class BankReconciliationXlsx(models.AbstractModel): ): cpart.append(line.account_id.code) counterpart = " ,".join(cpart) + if jdi['currency'] == mline.currency_id: + amount = mline.amount_currency + else: + amount = mline.currency_id._convert( + mline.amount_currency, jdi['currency'], jdi['company'], mline.date) res.append( { "date": mline.date, "ref": move.ref or "", "label": mline.name, "partner": mline.partner_id.display_name or "", - "amount": mline.balance, + "amount": amount, "move_name": move.name, "counterpart": counterpart, } @@ -78,10 +83,10 @@ class BankReconciliationXlsx(models.AbstractModel): style = jdi['style'] style_suffix = not add2total and '_warn' or '' subtotal = 0.0 - mlines = self._prepare_payment_move_lines(jdi['journal'], account, jdi['wizard']) + mlines = self._prepare_payment_move_lines(jdi, account) if mlines or add2total: - sheet.write(row, 0, '%s %s' % (account.name, account.code), style['title' + style_suffix]) - sheet.write(row, 1, "", style['title' + style_suffix]) + sheet.write(row, 0, '%s %s' % (account.name, account.code), style[f"title{style_suffix}"]) + sheet.write(row, 1, "", style[f"title{style_suffix}"]) if not mlines: if add2total: @@ -94,7 +99,7 @@ class BankReconciliationXlsx(models.AbstractModel): _("Date"), _("Partner"), _("Amount"), - _("Move Number"), + _("Journal Entry"), _("Counter-part"), _("Ref."), _("Label"), @@ -108,7 +113,7 @@ class BankReconciliationXlsx(models.AbstractModel): for mline in mlines: sheet.write(row, 0, mline["date"], style['regular_date']) sheet.write(row, 1, mline["partner"], style['regular']) - sheet.write(row, 2, mline["amount"], style['currency']) + sheet.write(row, 2, mline["amount"], style[jdi['currency']]) sheet.write(row, 3, mline["move_name"], style['regular']) sheet.write(row, 4, mline["counterpart"], style['regular']) sheet.write(row, 5, mline["ref"], style['regular']) @@ -118,18 +123,21 @@ class BankReconciliationXlsx(models.AbstractModel): end_line = row for col in range(1): - sheet.write(row, col, "", style['title' + style_suffix]) - sheet.write(row, 1, _("Sub-total:") + ' ', style['title_right' + style_suffix]) + sheet.write(row, col, "", style[f"title{style_suffix}"]) + sheet.write(row, 1, _("Sub-total:") + ' ', style[f"title_right{style_suffix}"]) formula = '=SUM(%s%d:%s%d)' % ( jdi['total_col'], start_line, jdi['total_col'], end_line) - sheet.write_formula(row, 2, formula, style['currency_bg' + style_suffix], subtotal) + sheet.write_formula(row, 2, formula, style[f"{jdi['currency']}_bg{style_suffix}"], subtotal) if add2total: jdi['total'] += subtotal jdi['total_formula'] += '+%s%d' % (jdi['total_col'], row + 1) return row def generate_xlsx_report(self, workbook, data, wizard): + lang = self.env.user.lang + self = self.with_context(lang=lang) + wizard = wizard.with_context(lang=lang) if not wizard.journal_ids: raise UserError(_("No bank journal selected.")) date_dt = wizard.date @@ -137,15 +145,21 @@ class BankReconciliationXlsx(models.AbstractModel): style = self._get_style(workbook, company) move_state_label = dict( wizard.fields_get('move_state', 'selection')['move_state']['selection']) - generated_on_label = _('Generated on %s') % format_datetime( - self.env, datetime.utcnow()) + generated_on_label = _('Generated from Odoo on %s by %s') % ( + format_datetime(self.env, datetime.utcnow()), + self.env.user.name) for journal in wizard.journal_ids: row = 0 sheet = workbook.add_worksheet(journal.code or journal.name) + bank_account = journal.default_account_id jdi = { 'wizard': wizard, + 'company': company, 'journal': journal, + 'currency': journal.currency_id or company.currency_id, + 'bank_account': bank_account, 'style': style, + 'workbook': workbook, 'sheet': sheet, 'total': 0.0, 'total_formula': '=', @@ -169,7 +183,7 @@ class BankReconciliationXlsx(models.AbstractModel): sheet.set_column(6, 6, 60) row += 3 sheet.write(row, 0, _("Company"), style['wizard_field']) - sheet.write(row, 1, wizard.company_id.display_name, style['wizard_value']) + sheet.write(row, 1, company.display_name, style['wizard_value']) row += 1 sheet.write(row, 0, _("Date"), style['wizard_field']) sheet.write(row, 1, date_dt, style['wizard_value_date']) @@ -177,18 +191,40 @@ class BankReconciliationXlsx(models.AbstractModel): sheet.write(row, 0, _("Journal"), style['wizard_field']) sheet.write(row, 1, journal.display_name, style['wizard_value']) row += 1 + sheet.write(row, 0, _("Currency"), style['wizard_field']) + sheet.write(row, 1, jdi['currency'].name, style['wizard_value']) + row += 1 sheet.write(row, 0, _("Entries"), style['wizard_field']) sheet.write(row, 1, move_state_label[wizard.move_state], style['wizard_value']) + # Setup check + if journal.currency_id and journal.currency_id != company.currency_id and journal.currency_id != bank_account.currency_id: + raise UserError(_( + "On bank journal %(journal)s which is configured with currency " + "%(journal_currency)s, the account %(account)s must be configured " + "with the same currency (current account currency: %(account_currency)s).", + journal=journal.display_name, + journal_currency=journal.currency_id.name, + account=bank_account.display_name, + account_currency=bank_account.currency_id.name or _('None'))) + bad_line_count = self.env['account.move.line'].search_count([('company_id', '=', company.id), ('account_id', '=', bank_account.id), ('currency_id', '!=', jdi['currency'].id)]) + if bad_line_count: + raise UserError(_( + "The are %(count)s journal items in account %(account)s " + "that have a currency other than %(currency)s or where " + "currency is not set.", + count=bad_line_count, + account=bank_account.display_name, + currency=jdi['currency'].name)) + # 1) Show balance of bank account row += 3 - bank_account = journal.default_account_id for col in range(1): sheet.write(row, col, "", style['title']) sheet.write(row, 1, _("Balance %s:") % bank_account.code + ' ', style['title_right']) - account_bal = self._get_account_balance(bank_account, wizard) + account_bal = self._get_account_balance(jdi) - sheet.write(row, 2, account_bal, style['currency_bg']) + sheet.write(row, 2, account_bal, style[f"{jdi['currency']}_bg"]) jdi['total'] += account_bal jdi['total_formula'] += '%s%d' % (jdi['total_col'], row + 1) @@ -206,7 +242,7 @@ class BankReconciliationXlsx(models.AbstractModel): sheet.write(row, col, "", style['title']) sheet.write(row, 1, _("TOTAL:") + ' ', style['title_right']) sheet.write_formula( - row, 2, jdi['total_formula'], style['currency_bg'], jdi['total']) + row, 2, jdi['total_formula'], style[f"{jdi['currency']}_bg"], jdi['total']) row += 3 # 4) Show suspense account lines @@ -217,11 +253,10 @@ class BankReconciliationXlsx(models.AbstractModel): style = {} font_size = 10 light_grey = "#eeeeee" - title_blue = "#e6e6fa" + light_blue = "#e0edff" subtotal_orange = "#ffcc00" title_warn = "#ff9999" subtotal_warn = "#ffff99" - light_purple = "#ffdeff" lang_code = self.env.user.lang lang = False if lang_code: @@ -249,7 +284,7 @@ class BankReconciliationXlsx(models.AbstractModel): ) title_style = { "bold": True, - "bg_color": title_blue, + "bg_color": light_blue, "font_size": font_size, "align": "left", } @@ -257,7 +292,7 @@ class BankReconciliationXlsx(models.AbstractModel): style['title'] = workbook.add_format(dict(title_style)) style['wizard_field'] = workbook.add_format(dict(title_style, bg_color=light_grey)) wizard_value_style = { - "bg_color": light_purple, + "bg_color": light_blue, "bold": True, "font_size": font_size, "align": "left", @@ -281,16 +316,20 @@ class BankReconciliationXlsx(models.AbstractModel): style['regular_date'] = workbook.add_format( {"num_format": xls_date_format, "font_size": font_size, "align": "left"} ) - cur_format = "#,##0.00 %s" % ( - company.currency_id.symbol or company.currency_id.name - ) - # It seems that Excel replaces automatically the decimal - # and thousand separator by those of the language under which - # Excel runs - currency_style = {"num_format": cur_format, "font_size": font_size} - style['currency'] = workbook.add_format(currency_style) - style['currency_bg'] = workbook.add_format( - dict(currency_style, bg_color=subtotal_orange)) - style['currency_bg_warn'] = workbook.add_format( - dict(currency_style, bg_color=subtotal_warn)) + for currency in self.env['res.currency'].search([]): + symbol = currency.symbol or currency.name + decimals = '0' * currency.decimal_places + if currency.position == 'before': + cur_format = f"{symbol} #,##0.{decimals}" + else: + cur_format = f"#,##0.{decimals} {symbol}" + # It seems that Excel replaces automatically the decimal + # and thousand separator by those of the language under which + # Excel runs + currency_style = {"num_format": cur_format, "font_size": font_size} + style[currency] = workbook.add_format(currency_style) + style[f'{currency}_bg'] = workbook.add_format( + dict(currency_style, bg_color=subtotal_orange)) + style[f'{currency}_bg_warn'] = workbook.add_format( + dict(currency_style, bg_color=subtotal_warn)) return style diff --git a/account_bank_reconciliation_summary_xlsx/report/report.xml b/account_bank_reconciliation_summary_xlsx/report/report.xml index 78a88a5..0052098 100644 --- a/account_bank_reconciliation_summary_xlsx/report/report.xml +++ b/account_bank_reconciliation_summary_xlsx/report/report.xml @@ -1,6 +1,6 @@ @@ -12,7 +12,6 @@ xlsx bank.reconciliation.xlsx bank.reconciliation.xlsx - 'bank_reconciliation-%s' % (object.date) diff --git a/account_bank_reconciliation_summary_xlsx/views/account_bank_statement.xml b/account_bank_reconciliation_summary_xlsx/views/account_bank_statement.xml index ffdbe2d..e4bfacc 100644 --- a/account_bank_reconciliation_summary_xlsx/views/account_bank_statement.xml +++ b/account_bank_reconciliation_summary_xlsx/views/account_bank_statement.xml @@ -1,6 +1,6 @@ diff --git a/account_bank_reconciliation_summary_xlsx/views/account_journal.xml b/account_bank_reconciliation_summary_xlsx/views/account_journal.xml index 31e2824..dfd3074 100644 --- a/account_bank_reconciliation_summary_xlsx/views/account_journal.xml +++ b/account_bank_reconciliation_summary_xlsx/views/account_journal.xml @@ -1,6 +1,6 @@ @@ -9,7 +9,7 @@ bank_reconciliation_summarry.account_journal_dashboard + >bank_reconciliation_summary.account_journal_dashboard account.journal diff --git a/account_bank_reconciliation_summary_xlsx/wizard/bank_reconciliation_report_wizard.py b/account_bank_reconciliation_summary_xlsx/wizard/bank_reconciliation_report_wizard.py index a7b5172..4de7b63 100644 --- a/account_bank_reconciliation_summary_xlsx/wizard/bank_reconciliation_report_wizard.py +++ b/account_bank_reconciliation_summary_xlsx/wizard/bank_reconciliation_report_wizard.py @@ -1,4 +1,4 @@ -# Copyright 2017-2023 Akretion France (http://www.akretion.com/) +# Copyright 2017-2024 Akretion France (http://www.akretion.com/) # @author: Alexis de Lattre # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/account_bank_reconciliation_summary_xlsx/wizard/bank_reconciliation_report_wizard_view.xml b/account_bank_reconciliation_summary_xlsx/wizard/bank_reconciliation_report_wizard_view.xml index ed697c5..7d2090d 100644 --- a/account_bank_reconciliation_summary_xlsx/wizard/bank_reconciliation_report_wizard_view.xml +++ b/account_bank_reconciliation_summary_xlsx/wizard/bank_reconciliation_report_wizard_view.xml @@ -1,6 +1,6 @@