Add module account_bank_reconciliation_summary_xlsx
This commit is contained in:
27
account_bank_reconciliation_summary_xlsx/README.rst
Normal file
27
account_bank_reconciliation_summary_xlsx/README.rst
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
===============================
|
||||||
|
Bank Reconciliation Report XLSX
|
||||||
|
===============================
|
||||||
|
|
||||||
|
In Odoo v13+, a bank reconciliation report is not really needed because all the payments executed that are not debited/credited on the bank account are in separate waiting accounts. But accountants want a bank reconciliation report, so this module adds one, even if it is quite different from a classic bank reconciliation report.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
|
This module doesn't require any configuration.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
You can launch the Bank Reconciliation Report wizard from:
|
||||||
|
|
||||||
|
* the menu *Accounting > Reports > Bank > Bank Reconciliation*,
|
||||||
|
* the invoicing dashboard: on a bank journal, click on the options, then select *Bank Reconciliation*.
|
||||||
|
* the form view of a bank statement: click on the button *Bank Reconciliation Report*.
|
||||||
|
|
||||||
|
Credits
|
||||||
|
=======
|
||||||
|
|
||||||
|
Contributors
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
2
account_bank_reconciliation_summary_xlsx/__init__.py
Normal file
2
account_bank_reconciliation_summary_xlsx/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
from . import report
|
||||||
|
from . import wizard
|
||||||
21
account_bank_reconciliation_summary_xlsx/__manifest__.py
Normal file
21
account_bank_reconciliation_summary_xlsx/__manifest__.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Copyright 2017-2023 Akretion France (http://www.akretion.com/)
|
||||||
|
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Bank Reconciliation Report",
|
||||||
|
"version": "14.0.1.0.0",
|
||||||
|
"license": "AGPL-3",
|
||||||
|
"author": "Akretion",
|
||||||
|
"website": "https://github.com/akretion/odoo-usability",
|
||||||
|
"summary": "Bank reconciliation XLSX report",
|
||||||
|
"depends": ["account", "report_xlsx"],
|
||||||
|
"data": [
|
||||||
|
"report/report.xml",
|
||||||
|
"wizard/bank_reconciliation_report_wizard_view.xml",
|
||||||
|
"views/account_bank_statement.xml",
|
||||||
|
"views/account_journal.xml",
|
||||||
|
"security/ir.model.access.csv",
|
||||||
|
],
|
||||||
|
"installable": True,
|
||||||
|
}
|
||||||
213
account_bank_reconciliation_summary_xlsx/i18n/fr.po
Normal file
213
account_bank_reconciliation_summary_xlsx/i18n/fr.po
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
# Translation of Odoo Server.
|
||||||
|
# This file contains the translation of the following modules:
|
||||||
|
# * account_bank_reconciliation_summary_xlsx
|
||||||
|
#
|
||||||
|
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"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: \n"
|
||||||
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "Amount"
|
||||||
|
msgstr "Montant"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "Balance %s:"
|
||||||
|
msgstr "Solde %s :"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__journal_ids
|
||||||
|
msgid "Bank Journals"
|
||||||
|
msgstr "Journaux de banque"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.actions.act_window,name:account_bank_reconciliation_summary_xlsx.bank_reconciliation_report_wizard_action
|
||||||
|
#: model:ir.ui.menu,name:account_bank_reconciliation_summary_xlsx.bank_reconciliation_report_wizard_menu
|
||||||
|
#: model_terms:ir.ui.view,arch_db:account_bank_reconciliation_summary_xlsx.account_journal_dashboard_kanban_view
|
||||||
|
msgid "Bank Reconciliation"
|
||||||
|
msgstr "Rapprochement bancaire"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#: model_terms:ir.ui.view,arch_db:account_bank_reconciliation_summary_xlsx.view_bank_statement_form
|
||||||
|
#, python-format
|
||||||
|
msgid "Bank Reconciliation Report"
|
||||||
|
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"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.actions.report,name:account_bank_reconciliation_summary_xlsx.bank_reconciliation_xlsx
|
||||||
|
msgid "Bank Reconciliation XLSX"
|
||||||
|
msgstr "Rapprochement bancaire XLSX"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.model,name:account_bank_reconciliation_summary_xlsx.model_report_bank_reconciliation_xlsx
|
||||||
|
msgid "Bank Reconciliation XLSX Report"
|
||||||
|
msgstr "Rapport de rapprochement bancaire XLSX"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.ui.menu,name:account_bank_reconciliation_summary_xlsx.menu_report_bank_root
|
||||||
|
msgid "Bank Reports"
|
||||||
|
msgstr "Rapports bancaires"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model_terms:ir.ui.view,arch_db:account_bank_reconciliation_summary_xlsx.bank_reconciliation_report_wizard_form
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Annuler"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__company_id
|
||||||
|
#, python-format
|
||||||
|
msgid "Company"
|
||||||
|
msgstr "Société"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "Counter-part"
|
||||||
|
msgstr "Contre partie"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__create_uid
|
||||||
|
msgid "Created by"
|
||||||
|
msgstr "Créé par"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__create_date
|
||||||
|
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
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__date
|
||||||
|
#, python-format
|
||||||
|
msgid "Date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: 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 ""
|
||||||
|
|
||||||
|
#. 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
|
||||||
|
msgid "Draft and Posted Entries"
|
||||||
|
msgstr "Écritures brouillon et comptabilisées"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__move_state
|
||||||
|
#, python-format
|
||||||
|
msgid "Entries"
|
||||||
|
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 ""
|
||||||
|
|
||||||
|
#. 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"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_bank_reconciliation_report_wizard__id
|
||||||
|
#: model:ir.model.fields,field_description:account_bank_reconciliation_summary_xlsx.field_report_bank_reconciliation_xlsx__id
|
||||||
|
msgid "ID"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#, python-format
|
||||||
|
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 "Label"
|
||||||
|
msgstr "Libellé"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: 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 ""
|
||||||
|
|
||||||
|
#. 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 ""
|
||||||
|
|
||||||
|
#. 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"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "No bank journal selected."
|
||||||
|
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
|
||||||
|
#, 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 "Partner"
|
||||||
|
msgstr "Partenaire"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: model:ir.model.fields.selection,name:account_bank_reconciliation_summary_xlsx.selection__bank_reconciliation_report_wizard__move_state__posted
|
||||||
|
msgid "Posted Entries"
|
||||||
|
msgstr "Écritures comptabilisées"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "Ref."
|
||||||
|
msgstr "Réf."
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "Sub-total:"
|
||||||
|
msgstr "Sous-total :"
|
||||||
|
|
||||||
|
#. module: account_bank_reconciliation_summary_xlsx
|
||||||
|
#: code:addons/account_bank_reconciliation_summary_xlsx/report/bank_reconciliation_xlsx.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "TOTAL:"
|
||||||
|
msgstr "TOTAL :"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from . import bank_reconciliation_xlsx
|
||||||
@@ -0,0 +1,296 @@
|
|||||||
|
# Copyright 2017-2023 Akretion France (http://www.akretion.com/)
|
||||||
|
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import _, models
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
from datetime import datetime
|
||||||
|
from odoo.tools.misc import format_datetime
|
||||||
|
import pytz
|
||||||
|
|
||||||
|
|
||||||
|
class BankReconciliationXlsx(models.AbstractModel):
|
||||||
|
_name = "report.bank.reconciliation.xlsx"
|
||||||
|
_description = "Bank Reconciliation XLSX Report"
|
||||||
|
_inherit = "report.report_xlsx.abstract"
|
||||||
|
|
||||||
|
def _domain_add_move_state(self, wizard, domain):
|
||||||
|
if wizard.move_state == 'posted':
|
||||||
|
domain.append(('parent_state', '=', 'posted'))
|
||||||
|
elif wizard.move_state == 'draft_posted':
|
||||||
|
domain.append(('parent_state', 'in', ('draft', 'posted')))
|
||||||
|
|
||||||
|
def _get_account_balance(self, account, wizard):
|
||||||
|
domain = [
|
||||||
|
('account_id', '=', account.id),
|
||||||
|
('date', '<=', wizard.date),
|
||||||
|
('company_id', '=', wizard.company_id.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
|
||||||
|
return account_bal
|
||||||
|
|
||||||
|
def _prepare_payment_move_lines(self, journal, account, wizard, unreconciled_only=True):
|
||||||
|
domain = [
|
||||||
|
("company_id", "=", wizard.company_id.id),
|
||||||
|
("account_id", "=", account.id),
|
||||||
|
("journal_id", "=", journal.id),
|
||||||
|
("date", "<=", wizard.date),
|
||||||
|
]
|
||||||
|
if unreconciled_only:
|
||||||
|
limit_datetime_naive = datetime.combine(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)
|
||||||
|
limit_datetime = limit_datetime_utc.replace(tzinfo=None)
|
||||||
|
domain += [
|
||||||
|
'|', ('full_reconcile_id', '=', False),
|
||||||
|
('full_reconcile_id.create_date', '<=', limit_datetime)]
|
||||||
|
self._domain_add_move_state(wizard, domain)
|
||||||
|
mlines = self.env["account.move.line"].search(domain)
|
||||||
|
res = []
|
||||||
|
for mline in mlines:
|
||||||
|
move = mline.move_id
|
||||||
|
cpart = []
|
||||||
|
for line in move.line_ids:
|
||||||
|
if (
|
||||||
|
line.account_id != account
|
||||||
|
and line.account_id.code not in cpart
|
||||||
|
):
|
||||||
|
cpart.append(line.account_id.code)
|
||||||
|
counterpart = " ,".join(cpart)
|
||||||
|
res.append(
|
||||||
|
{
|
||||||
|
"date": mline.date,
|
||||||
|
"ref": move.ref or "",
|
||||||
|
"label": mline.name,
|
||||||
|
"partner": mline.partner_id.display_name or "",
|
||||||
|
"amount": mline.balance,
|
||||||
|
"move_name": move.name,
|
||||||
|
"counterpart": counterpart,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def _write_move_lines_block(self, jdi, row, account, add2total=True):
|
||||||
|
sheet = jdi['sheet']
|
||||||
|
style = jdi['style']
|
||||||
|
style_suffix = not add2total and '_warn' or ''
|
||||||
|
subtotal = 0.0
|
||||||
|
mlines = self._prepare_payment_move_lines(jdi['journal'], account, jdi['wizard'])
|
||||||
|
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])
|
||||||
|
|
||||||
|
if not mlines:
|
||||||
|
if add2total:
|
||||||
|
sheet.write(row, 2, _("None"), style['none'])
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
row += 1
|
||||||
|
col_labels = [
|
||||||
|
_("Date"),
|
||||||
|
_("Partner"),
|
||||||
|
_("Amount"),
|
||||||
|
_("Move Number"),
|
||||||
|
_("Counter-part"),
|
||||||
|
_("Ref."),
|
||||||
|
_("Label"),
|
||||||
|
]
|
||||||
|
col = 0
|
||||||
|
for col_label in col_labels:
|
||||||
|
sheet.write(row, col, col_label, style['col_header'])
|
||||||
|
col += 1
|
||||||
|
row += 1
|
||||||
|
start_line = row + 1
|
||||||
|
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, 3, mline["move_name"], style['regular'])
|
||||||
|
sheet.write(row, 4, mline["counterpart"], style['regular'])
|
||||||
|
sheet.write(row, 5, mline["ref"], style['regular'])
|
||||||
|
sheet.write(row, 6, mline["label"], style['regular'])
|
||||||
|
subtotal += mline["amount"]
|
||||||
|
row += 1
|
||||||
|
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])
|
||||||
|
|
||||||
|
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)
|
||||||
|
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):
|
||||||
|
if not wizard.journal_ids:
|
||||||
|
raise UserError(_("No bank journal selected."))
|
||||||
|
date_dt = wizard.date
|
||||||
|
company = wizard.company_id
|
||||||
|
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())
|
||||||
|
for journal in wizard.journal_ids:
|
||||||
|
row = 0
|
||||||
|
sheet = workbook.add_worksheet(journal.code or journal.name)
|
||||||
|
jdi = {
|
||||||
|
'wizard': wizard,
|
||||||
|
'journal': journal,
|
||||||
|
'style': style,
|
||||||
|
'sheet': sheet,
|
||||||
|
'total': 0.0,
|
||||||
|
'total_formula': '=',
|
||||||
|
'total_col': 'C',
|
||||||
|
}
|
||||||
|
sheet.write(
|
||||||
|
row,
|
||||||
|
0,
|
||||||
|
_("Bank Reconciliation Report"),
|
||||||
|
style['doc_title'],
|
||||||
|
)
|
||||||
|
row += 1
|
||||||
|
sheet.write(row, 0, generated_on_label, style['small'])
|
||||||
|
sheet.set_row(0, 26)
|
||||||
|
sheet.set_column(0, 0, 10)
|
||||||
|
sheet.set_column(1, 1, 35)
|
||||||
|
sheet.set_column(2, 2, 15)
|
||||||
|
sheet.set_column(3, 3, 15)
|
||||||
|
sheet.set_column(4, 4, 25)
|
||||||
|
sheet.set_column(5, 5, 30)
|
||||||
|
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'])
|
||||||
|
row += 1
|
||||||
|
sheet.write(row, 0, _("Date"), style['wizard_field'])
|
||||||
|
sheet.write(row, 1, date_dt, style['wizard_value_date'])
|
||||||
|
row += 1
|
||||||
|
sheet.write(row, 0, _("Journal"), style['wizard_field'])
|
||||||
|
sheet.write(row, 1, journal.display_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'])
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
sheet.write(row, 2, account_bal, style['currency_bg'])
|
||||||
|
jdi['total'] += account_bal
|
||||||
|
jdi['total_formula'] += '%s%d' % (jdi['total_col'], row + 1)
|
||||||
|
|
||||||
|
row += 2
|
||||||
|
# 2) Show payment lines IN (debit)
|
||||||
|
debit_account = journal.payment_debit_account_id
|
||||||
|
row = self._write_move_lines_block(jdi, row, debit_account)
|
||||||
|
row += 2
|
||||||
|
# 3) Show payment lines OUT (credit)
|
||||||
|
credit_account = journal.payment_credit_account_id
|
||||||
|
row = self._write_move_lines_block(jdi, row, credit_account)
|
||||||
|
row += 2
|
||||||
|
|
||||||
|
for col in range(1):
|
||||||
|
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 += 3
|
||||||
|
|
||||||
|
# 4) Show suspense account lines
|
||||||
|
row = self._write_move_lines_block(
|
||||||
|
jdi, row, journal.suspense_account_id, add2total=False)
|
||||||
|
|
||||||
|
def _get_style(self, workbook, company):
|
||||||
|
style = {}
|
||||||
|
font_size = 10
|
||||||
|
light_grey = "#eeeeee"
|
||||||
|
title_blue = "#e6e6fa"
|
||||||
|
subtotal_orange = "#ffcc00"
|
||||||
|
title_warn = "#ff9999"
|
||||||
|
subtotal_warn = "#ffff99"
|
||||||
|
light_purple = "#ffdeff"
|
||||||
|
lang_code = self.env.user.lang
|
||||||
|
lang = False
|
||||||
|
if lang_code:
|
||||||
|
lang = self.env["res.lang"].search([("code", "=", lang_code)])
|
||||||
|
if not lang:
|
||||||
|
lang = self.env["res.lang"].search([], limit=1)
|
||||||
|
xls_date_format = (
|
||||||
|
lang.date_format.replace("%Y", "yyyy")
|
||||||
|
.replace("%m", "mm")
|
||||||
|
.replace("%d", "dd")
|
||||||
|
.replace("%y", "yy")
|
||||||
|
)
|
||||||
|
|
||||||
|
style['doc_title'] = workbook.add_format(
|
||||||
|
{"bold": True, "font_size": font_size + 4})
|
||||||
|
style['small'] = workbook.add_format({"font_size": font_size - 3})
|
||||||
|
style['col_header'] = workbook.add_format(
|
||||||
|
{
|
||||||
|
"bold": True,
|
||||||
|
"bg_color": light_grey,
|
||||||
|
"text_wrap": True,
|
||||||
|
"font_size": font_size,
|
||||||
|
"align": "center",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
title_style = {
|
||||||
|
"bold": True,
|
||||||
|
"bg_color": title_blue,
|
||||||
|
"font_size": font_size,
|
||||||
|
"align": "left",
|
||||||
|
}
|
||||||
|
style['title_right'] = workbook.add_format(dict(title_style, align="right"))
|
||||||
|
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,
|
||||||
|
"bold": True,
|
||||||
|
"font_size": font_size,
|
||||||
|
"align": "left",
|
||||||
|
}
|
||||||
|
|
||||||
|
style['wizard_value'] = workbook.add_format(wizard_value_style)
|
||||||
|
style['wizard_value_date'] = workbook.add_format(
|
||||||
|
dict(wizard_value_style, num_format=xls_date_format))
|
||||||
|
style['none'] = workbook.add_format(
|
||||||
|
{"bold": True, "font_size": font_size, "align": "right", "bg_color": subtotal_orange}
|
||||||
|
)
|
||||||
|
# WARN for suspense account
|
||||||
|
style['title_warn'] = workbook.add_format(
|
||||||
|
dict(title_style, align="left", bg_color=title_warn))
|
||||||
|
style['title_right_warn'] = workbook.add_format(
|
||||||
|
dict(title_style, align="right", bg_color=title_warn))
|
||||||
|
style['regular'] = workbook.add_format({"font_size": font_size})
|
||||||
|
if "%" in xls_date_format:
|
||||||
|
# fallback
|
||||||
|
xls_date_format = "yyyy-mm-dd"
|
||||||
|
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))
|
||||||
|
return style
|
||||||
18
account_bank_reconciliation_summary_xlsx/report/report.xml
Normal file
18
account_bank_reconciliation_summary_xlsx/report/report.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!--
|
||||||
|
Copyright 2017-2023 Akretion France (http://www.akretion.com/)
|
||||||
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
-->
|
||||||
|
<odoo>
|
||||||
|
|
||||||
|
<record id="bank_reconciliation_xlsx" model="ir.actions.report">
|
||||||
|
<field name="name">Bank Reconciliation XLSX</field>
|
||||||
|
<field name="model">bank.reconciliation.report.wizard</field>
|
||||||
|
<field name="report_type">xlsx</field>
|
||||||
|
<field name="report_name">bank.reconciliation.xlsx</field>
|
||||||
|
<field name="report_file">bank.reconciliation.xlsx</field>
|
||||||
|
<!-- print_report_name doesn't work here... -->
|
||||||
|
<field name="print_report_name">'bank_reconciliation-%s' % (object.date)</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_bank_reconciliation_report_wizard_user,Full access on bank.reconciliation.report.wizard,model_bank_reconciliation_report_wizard,account.group_account_user,1,1,1,1
|
||||||
|
access_bank_reconciliation_report_wizard_readonly,Full access on bank.reconciliation.report.wizard,model_bank_reconciliation_report_wizard,account.group_account_readonly,1,1,1,1
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!--
|
||||||
|
Copyright 2017-2020 Akretion France (http://www.akretion.com/)
|
||||||
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
-->
|
||||||
|
<odoo>
|
||||||
|
<record id="view_bank_statement_form" model="ir.ui.view">
|
||||||
|
<field name="name">bank_rec_summary.account.bank.statement.form</field>
|
||||||
|
<field name="model">account.bank.statement</field>
|
||||||
|
<field name="inherit_id" ref="account.view_bank_statement_form" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<button name="button_reprocess" position="after">
|
||||||
|
<button
|
||||||
|
name="%(bank_reconciliation_report_wizard_action)d"
|
||||||
|
type="action"
|
||||||
|
string="Bank Reconciliation Report"
|
||||||
|
context="{'default_journal_ids': [journal_id]}"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!--
|
||||||
|
Copyright 2018-2023 Akretion France (http://www.akretion.com/)
|
||||||
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
-->
|
||||||
|
<odoo>
|
||||||
|
<!-- Accounting Dashboard -->
|
||||||
|
<record id="account_journal_dashboard_kanban_view" model="ir.ui.view">
|
||||||
|
<field
|
||||||
|
name="name"
|
||||||
|
>bank_reconciliation_summarry.account_journal_dashboard</field>
|
||||||
|
<field name="model">account.journal</field>
|
||||||
|
<field name="inherit_id" ref="account.account_journal_dashboard_kanban_view" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//a[@name='open_collect_money']/.." position="before">
|
||||||
|
<div name="bank_reconciliation_report">
|
||||||
|
<a
|
||||||
|
role="menuitem"
|
||||||
|
type="action"
|
||||||
|
name="%(bank_reconciliation_report_wizard_action)d"
|
||||||
|
context="{'default_journal_ids': [active_id]}"
|
||||||
|
>Bank Reconciliation</a>
|
||||||
|
</div>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from . import bank_reconciliation_report_wizard
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
# Copyright 2017-2023 Akretion France (http://www.akretion.com/)
|
||||||
|
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
|
class BankReconciliationReportWizard(models.TransientModel):
|
||||||
|
_name = "bank.reconciliation.report.wizard"
|
||||||
|
_description = "Bank Reconciliation Report Wizard"
|
||||||
|
_check_company_auto = True
|
||||||
|
|
||||||
|
company_id = fields.Many2one(
|
||||||
|
'res.company', string='Company',
|
||||||
|
ondelete='cascade', required=True,
|
||||||
|
default=lambda self: self.env.company)
|
||||||
|
date = fields.Date(required=True, default=fields.Date.context_today)
|
||||||
|
move_state = fields.Selection(
|
||||||
|
[("posted", "Posted Entries"), ("draft_posted", "Draft and Posted Entries")],
|
||||||
|
string="Entries",
|
||||||
|
required=True,
|
||||||
|
default="posted",
|
||||||
|
)
|
||||||
|
journal_ids = fields.Many2many(
|
||||||
|
"account.journal",
|
||||||
|
string="Bank Journals",
|
||||||
|
domain="[('type', '=', 'bank'), ('company_id', '=', company_id)]",
|
||||||
|
required=True,
|
||||||
|
check_company=True,
|
||||||
|
default=lambda self: self._default_journal_ids(),
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _default_journal_ids(self):
|
||||||
|
journals = self.env["account.journal"].search(
|
||||||
|
[
|
||||||
|
("type", "=", "bank"),
|
||||||
|
("bank_account_id", "!=", False),
|
||||||
|
("company_id", "=", self.env.company.id),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return journals
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<!--
|
||||||
|
Copyright 2017-2023 Akretion France (http://www.akretion.com/)
|
||||||
|
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
-->
|
||||||
|
<odoo>
|
||||||
|
<record id="bank_reconciliation_report_wizard_form" model="ir.ui.view">
|
||||||
|
<field name="name">bank.reconciliation.report.wizard.form</field>
|
||||||
|
<field name="model">bank.reconciliation.report.wizard</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form>
|
||||||
|
<group name="main">
|
||||||
|
<field name="company_id" invisible="1" />
|
||||||
|
<field name="date" />
|
||||||
|
<field name="journal_ids" widget="many2many_tags" options="{'no_open': True, 'no_create': True}"/>
|
||||||
|
<field name="move_state" widget="radio"/>
|
||||||
|
</group>
|
||||||
|
<footer>
|
||||||
|
<button
|
||||||
|
name="%(account_bank_reconciliation_summary_xlsx.bank_reconciliation_xlsx)d"
|
||||||
|
string="Export XLSX"
|
||||||
|
type="action"
|
||||||
|
class="btn-primary"
|
||||||
|
/>
|
||||||
|
<button special="cancel" string="Cancel" />
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="bank_reconciliation_report_wizard_action" model="ir.actions.act_window">
|
||||||
|
<field name="name">Bank Reconciliation</field>
|
||||||
|
<field name="res_model">bank.reconciliation.report.wizard</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="target">new</field>
|
||||||
|
</record>
|
||||||
|
<menuitem
|
||||||
|
id="menu_report_bank_root"
|
||||||
|
parent="account.menu_finance_reports"
|
||||||
|
name="Bank Reports"
|
||||||
|
sequence="12"
|
||||||
|
/>
|
||||||
|
<menuitem
|
||||||
|
id="bank_reconciliation_report_wizard_menu"
|
||||||
|
action="bank_reconciliation_report_wizard_action"
|
||||||
|
parent="menu_report_bank_root"
|
||||||
|
sequence="10"
|
||||||
|
/>
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user