OCA-git-bot
4 years ago
89 changed files with 47757 additions and 0 deletions
-
151account_financial_report/README.rst
-
7account_financial_report/__init__.py
-
49account_financial_report/__manifest__.py
-
1786account_financial_report/i18n/account_financial_report.pot
-
2013account_financial_report/i18n/ar.po
-
1832account_financial_report/i18n/ca.po
-
2152account_financial_report/i18n/de.po
-
1919account_financial_report/i18n/es.po
-
1826account_financial_report/i18n/es_AR.po
-
2085account_financial_report/i18n/fr.po
-
2068account_financial_report/i18n/fr_CH.po
-
1770account_financial_report/i18n/hr.po
-
1809account_financial_report/i18n/hr_HR.po
-
1947account_financial_report/i18n/it.po
-
1778account_financial_report/i18n/ja.po
-
2156account_financial_report/i18n/nl.po
-
1797account_financial_report/i18n/nl_NL.po
-
1807account_financial_report/i18n/pt.po
-
2204account_financial_report/i18n/pt_BR.po
-
1986account_financial_report/i18n/ro.po
-
45account_financial_report/menuitems.xml
-
4account_financial_report/models/__init__.py
-
14account_financial_report/models/account.py
-
65account_financial_report/models/account_group.py
-
40account_financial_report/models/account_move_line.py
-
25account_financial_report/models/ir_actions_report.py
-
27account_financial_report/readme/CONTRIBUTORS.rst
-
16account_financial_report/readme/DESCRIPTION.rst
-
19account_financial_report/readme/HISTORY.rst
-
7account_financial_report/readme/ROADMAP.rst
-
18account_financial_report/report/__init__.py
-
687account_financial_report/report/abstract_report_xlsx.py
-
479account_financial_report/report/aged_partner_balance.py
-
325account_financial_report/report/aged_partner_balance_xlsx.py
-
870account_financial_report/report/general_ledger.py
-
346account_financial_report/report/general_ledger_xlsx.py
-
359account_financial_report/report/journal_ledger.py
-
263account_financial_report/report/journal_ledger_xlsx.py
-
392account_financial_report/report/open_items.py
-
216account_financial_report/report/open_items_xlsx.py
-
714account_financial_report/report/templates/aged_partner_balance.xml
-
847account_financial_report/report/templates/general_ledger.xml
-
487account_financial_report/report/templates/journal_ledger.xml
-
32account_financial_report/report/templates/layouts.xml
-
308account_financial_report/report/templates/open_items.xml
-
1008account_financial_report/report/templates/trial_balance.xml
-
195account_financial_report/report/templates/vat_report.xml
-
772account_financial_report/report/trial_balance.py
-
323account_financial_report/report/trial_balance_xlsx.py
-
235account_financial_report/report/vat_report.py
-
61account_financial_report/report/vat_report_xlsx.py
-
173account_financial_report/reports.xml
-
7account_financial_report/security/ir.model.access.csv
-
BINaccount_financial_report/static/description/icon.png
-
506account_financial_report/static/description/index.html
-
113account_financial_report/static/src/css/report.css
-
109account_financial_report/static/src/js/account_financial_report_backend.js
-
88account_financial_report/static/src/js/account_financial_report_widgets.js
-
8account_financial_report/tests/__init__.py
-
701account_financial_report/tests/test_general_ledger.py
-
306account_financial_report/tests/test_journal_ledger.py
-
24account_financial_report/tests/test_open_items.py
-
825account_financial_report/tests/test_trial_balance.py
-
368account_financial_report/tests/test_vat_report.py
-
14account_financial_report/view/account_view.xml
-
9account_financial_report/view/report_aged_partner_balance.xml
-
9account_financial_report/view/report_general_ledger.xml
-
9account_financial_report/view/report_journal_ledger.xml
-
9account_financial_report/view/report_open_items.xml
-
83account_financial_report/view/report_template.xml
-
9account_financial_report/view/report_trial_balance.xml
-
9account_financial_report/view/report_vat_report.xml
-
7account_financial_report/wizard/__init__.py
-
29account_financial_report/wizard/abstract_wizard.py
-
167account_financial_report/wizard/aged_partner_balance_wizard.py
-
96account_financial_report/wizard/aged_partner_balance_wizard_view.xml
-
348account_financial_report/wizard/general_ledger_wizard.py
-
183account_financial_report/wizard/general_ledger_wizard_view.xml
-
175account_financial_report/wizard/journal_ledger_wizard.py
-
74account_financial_report/wizard/journal_ledger_wizard_view.xml
-
193account_financial_report/wizard/open_items_wizard.py
-
117account_financial_report/wizard/open_items_wizard_view.xml
-
301account_financial_report/wizard/trial_balance_wizard.py
-
157account_financial_report/wizard/trial_balance_wizard_view.xml
-
121account_financial_report/wizard/vat_report_wizard.py
-
60account_financial_report/wizard/vat_report_wizard_view.xml
-
2oca_dependencies.txt
-
1setup/account_financial_report/odoo/addons/account_financial_report
-
6setup/account_financial_report/setup.py
@ -0,0 +1,151 @@ |
|||||
|
========================= |
||||
|
Account Financial Reports |
||||
|
========================= |
||||
|
|
||||
|
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||||
|
!! This file is generated by oca-gen-addon-readme !! |
||||
|
!! changes will be overwritten. !! |
||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||||
|
|
||||
|
.. |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 |
||||
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--financial--reporting-lightgray.png?logo=github |
||||
|
:target: https://github.com/OCA/account-financial-reporting/tree/14.0/account_financial_report |
||||
|
:alt: OCA/account-financial-reporting |
||||
|
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png |
||||
|
:target: https://translation.odoo-community.org/projects/account-financial-reporting-14-0/account-financial-reporting-14-0-account_financial_report |
||||
|
:alt: Translate me on Weblate |
||||
|
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png |
||||
|
:target: https://runbot.odoo-community.org/runbot/91/14.0 |
||||
|
:alt: Try me on Runbot |
||||
|
|
||||
|
|badge1| |badge2| |badge3| |badge4| |badge5| |
||||
|
|
||||
|
This module adds a set of financial reports. They are accessible under |
||||
|
Invoicing / Reporting / OCA accounting reports. |
||||
|
|
||||
|
- General ledger |
||||
|
- Trial Balance |
||||
|
- Open Items |
||||
|
- Aged Partner Balance |
||||
|
- VAT Report |
||||
|
- Journal Ledger |
||||
|
|
||||
|
Currently General ledger, Trial Balance and Open Items are fully compatible with a foreign |
||||
|
currency set up in account in order to display balances. Moreover, any foreign |
||||
|
currency used in account move lines is properly shown. |
||||
|
|
||||
|
In case that in an account has not been configured a second currency foreign |
||||
|
currency balances are not available. |
||||
|
|
||||
|
**Table of contents** |
||||
|
|
||||
|
.. contents:: |
||||
|
:local: |
||||
|
|
||||
|
Known issues / Roadmap |
||||
|
====================== |
||||
|
|
||||
|
* 'VAT Report' is valid only for cases where it's met that for each |
||||
|
Tax defined: all the "Account tags" of all the |
||||
|
'Repartition for Invoices' or 'Repartition for Credit Notes' |
||||
|
are different. |
||||
|
* It would be nice to have in reports a column indicating the |
||||
|
state of the entries when the option "All Entries" is selected |
||||
|
in "Target Moves" field in a wizard |
||||
|
|
||||
|
Changelog |
||||
|
========= |
||||
|
|
||||
|
11.0.2.5.0 (2019-04-26) |
||||
|
~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
* In the Trial Balance you have an option to hide parent hierarchy levels |
||||
|
|
||||
|
11.0.2.4.1 (2019-01-08) |
||||
|
~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
* Handle better multicompany behaviour |
||||
|
* Improve how title appears in the reports |
||||
|
* Improve performance in General Ledger |
||||
|
|
||||
|
|
||||
|
11.0.2.3.1 (2018-11-29) |
||||
|
~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
* In the Trial Balance you can apply a filter by hierarchy levels |
||||
|
* In the General Ledger you can apply a filter by Analytic Tag |
||||
|
* In the Journal Ledger the field 'Journal' is now optional |
||||
|
|
||||
|
Bug Tracker |
||||
|
=========== |
||||
|
|
||||
|
Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-financial-reporting/issues>`_. |
||||
|
In case of trouble, please check there if your issue has already been reported. |
||||
|
If you spotted it first, help us smashing it by providing a detailed and welcomed |
||||
|
`feedback <https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_financial_report%0Aversion:%2014.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. |
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
|
||||
|
Authors |
||||
|
~~~~~~~ |
||||
|
|
||||
|
* Camptocamp SA |
||||
|
* initOS GmbH |
||||
|
* redCOR AG |
||||
|
* ForgeFlow |
||||
|
|
||||
|
Contributors |
||||
|
~~~~~~~~~~~~ |
||||
|
|
||||
|
* Jordi Ballester <jordi.ballester@forgeflow.com> |
||||
|
* Yannick Vaucher <yannick.vaucher@camptocamp.com> |
||||
|
* Simone Orsi <simone.orsi@abstract.com> |
||||
|
* Leonardo Pistone <leonardo.pistone@camptocamp.com> |
||||
|
* Damien Crier <damien.crier@camptocamp.com> |
||||
|
* Andrea Stirpe <a.stirpe@onestein.nl> |
||||
|
* Thomas Rehn <thomas.rehn@initos.com> |
||||
|
* Andrea Gallina <4everamd@gmail.com> |
||||
|
* Robert Rottermann <robert@redcor.ch> |
||||
|
* Ciro Urselli <c.urselli@apuliasoftware.it> |
||||
|
* Francesco Apruzzese <opencode@e-ware.org> |
||||
|
* Lorenzo Battistini <https://github.com/eLBati> |
||||
|
* Julien Coux <julien.coux@camptocamp.com> |
||||
|
* Akim Juillerat <akim.juillerat@camptocamp.com> |
||||
|
* Alexis de Lattre <alexis@via.ecp.fr> |
||||
|
* Mihai Fekete <feketemihai@gmail.com> |
||||
|
* Miquel Raïch <miquel.raich@forgeflow.com> |
||||
|
* Joan Sisquella <joan.sisquella@forgeflow.com> |
||||
|
* `Tecnativa <https://www.tecnativa.com>`__: |
||||
|
|
||||
|
* Pedro M. Baeza |
||||
|
* Sergio Teruel |
||||
|
* Ernesto Tejeda |
||||
|
* João Marques |
||||
|
|
||||
|
Much of the work in this module was done at a sprint in Sorrento, Italy in |
||||
|
April 2016. |
||||
|
|
||||
|
Maintainers |
||||
|
~~~~~~~~~~~ |
||||
|
|
||||
|
This module is maintained by the OCA. |
||||
|
|
||||
|
.. image:: https://odoo-community.org/logo.png |
||||
|
:alt: Odoo Community Association |
||||
|
:target: https://odoo-community.org |
||||
|
|
||||
|
OCA, or the Odoo Community Association, is a nonprofit organization whose |
||||
|
mission is to support the collaborative development of Odoo features and |
||||
|
promote its widespread use. |
||||
|
|
||||
|
This module is part of the `OCA/account-financial-reporting <https://github.com/OCA/account-financial-reporting/tree/14.0/account_financial_report>`_ project on GitHub. |
||||
|
|
||||
|
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
@ -0,0 +1,7 @@ |
|||||
|
# Author: Damien Crier |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import models |
||||
|
from . import report |
||||
|
from . import wizard |
@ -0,0 +1,49 @@ |
|||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# Copyright 2021 Tecnativa - João Marques |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
{ |
||||
|
"name": "Account Financial Reports", |
||||
|
"version": "14.0.1.0.0", |
||||
|
"category": "Reporting", |
||||
|
"summary": "OCA Financial Reports", |
||||
|
"author": "Camptocamp SA," |
||||
|
"initOS GmbH," |
||||
|
"redCOR AG," |
||||
|
"ForgeFlow," |
||||
|
"Odoo Community Association (OCA)", |
||||
|
"website": "https://github.com/OCA/account-financial-reporting", |
||||
|
"depends": ["account", "date_range", "report_xlsx"], |
||||
|
"data": [ |
||||
|
"security/ir.model.access.csv", |
||||
|
"wizard/aged_partner_balance_wizard_view.xml", |
||||
|
"wizard/general_ledger_wizard_view.xml", |
||||
|
"wizard/journal_ledger_wizard_view.xml", |
||||
|
"wizard/open_items_wizard_view.xml", |
||||
|
"wizard/trial_balance_wizard_view.xml", |
||||
|
"wizard/vat_report_wizard_view.xml", |
||||
|
"menuitems.xml", |
||||
|
"reports.xml", |
||||
|
"report/templates/layouts.xml", |
||||
|
"report/templates/aged_partner_balance.xml", |
||||
|
"report/templates/general_ledger.xml", |
||||
|
"report/templates/journal_ledger.xml", |
||||
|
"report/templates/open_items.xml", |
||||
|
"report/templates/trial_balance.xml", |
||||
|
"report/templates/vat_report.xml", |
||||
|
"view/account_view.xml", |
||||
|
"view/report_template.xml", |
||||
|
"view/report_general_ledger.xml", |
||||
|
"view/report_journal_ledger.xml", |
||||
|
"view/report_trial_balance.xml", |
||||
|
"view/report_open_items.xml", |
||||
|
"view/report_aged_partner_balance.xml", |
||||
|
"view/report_vat_report.xml", |
||||
|
], |
||||
|
"installable": True, |
||||
|
"application": True, |
||||
|
"auto_install": False, |
||||
|
"license": "AGPL-3", |
||||
|
} |
1786
account_financial_report/i18n/account_financial_report.pot
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2013
account_financial_report/i18n/ar.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1832
account_financial_report/i18n/ca.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2152
account_financial_report/i18n/de.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1919
account_financial_report/i18n/es.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1826
account_financial_report/i18n/es_AR.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2085
account_financial_report/i18n/fr.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2068
account_financial_report/i18n/fr_CH.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1770
account_financial_report/i18n/hr.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1809
account_financial_report/i18n/hr_HR.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1947
account_financial_report/i18n/it.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1778
account_financial_report/i18n/ja.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2156
account_financial_report/i18n/nl.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1797
account_financial_report/i18n/nl_NL.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1807
account_financial_report/i18n/pt.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2204
account_financial_report/i18n/pt_BR.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1986
account_financial_report/i18n/ro.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,45 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<menuitem |
||||
|
parent="account.menu_finance_reports" |
||||
|
id="menu_oca_reports" |
||||
|
name="OCA accounting reports" |
||||
|
groups="account.group_account_manager,account.group_account_user" |
||||
|
/> |
||||
|
<menuitem |
||||
|
parent="menu_oca_reports" |
||||
|
action="action_general_ledger_wizard" |
||||
|
id="menu_general_ledger_wizard" |
||||
|
sequence="10" |
||||
|
/> |
||||
|
<menuitem |
||||
|
parent="menu_oca_reports" |
||||
|
action="action_journal_ledger_wizard" |
||||
|
id="menu_journal_ledger_wizard" |
||||
|
sequence="15" |
||||
|
/> |
||||
|
<menuitem |
||||
|
parent="menu_oca_reports" |
||||
|
action="action_trial_balance_wizard" |
||||
|
id="menu_trial_balance_wizard" |
||||
|
sequence="20" |
||||
|
/> |
||||
|
<menuitem |
||||
|
parent="menu_oca_reports" |
||||
|
action="action_open_items_wizard" |
||||
|
id="menu_open_items_wizard" |
||||
|
sequence="30" |
||||
|
/> |
||||
|
<menuitem |
||||
|
parent="menu_oca_reports" |
||||
|
action="action_aged_partner_balance_wizard" |
||||
|
id="menu_aged_partner_balance_wizard" |
||||
|
sequence="40" |
||||
|
/> |
||||
|
<menuitem |
||||
|
parent="menu_oca_reports" |
||||
|
action="action_vat_report_wizard" |
||||
|
id="menu_vat_report_wizard" |
||||
|
sequence="50" |
||||
|
/> |
||||
|
</odoo> |
@ -0,0 +1,4 @@ |
|||||
|
from . import account_group |
||||
|
from . import account |
||||
|
from . import account_move_line |
||||
|
from . import ir_actions_report |
@ -0,0 +1,14 @@ |
|||||
|
# © 2011 Guewen Baconnier (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
from odoo import fields, models |
||||
|
|
||||
|
|
||||
|
class AccountAccount(models.Model): |
||||
|
_inherit = "account.account" |
||||
|
|
||||
|
centralized = fields.Boolean( |
||||
|
"Centralized", |
||||
|
help="If flagged, no details will be displayed in " |
||||
|
"the General Ledger report (the webkit one only), " |
||||
|
"only centralized amounts per period.", |
||||
|
) |
@ -0,0 +1,65 @@ |
|||||
|
# © 2018 Forest and Biomass Romania SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class AccountGroup(models.Model): |
||||
|
_inherit = "account.group" |
||||
|
|
||||
|
group_child_ids = fields.One2many( |
||||
|
comodel_name="account.group", inverse_name="parent_id", string="Child Groups" |
||||
|
) |
||||
|
level = fields.Integer(string="Level", compute="_compute_level") |
||||
|
account_ids = fields.One2many( |
||||
|
comodel_name="account.account", inverse_name="group_id", string="Accounts" |
||||
|
) |
||||
|
compute_account_ids = fields.Many2many( |
||||
|
"account.account", |
||||
|
compute="_compute_group_accounts", |
||||
|
string="Compute accounts", |
||||
|
store=True, |
||||
|
) |
||||
|
complete_name = fields.Char("Full Name", compute="_compute_complete_name") |
||||
|
complete_code = fields.Char("Full Code", compute="_compute_complete_code") |
||||
|
|
||||
|
@api.depends("name", "parent_id.complete_name") |
||||
|
def _compute_complete_name(self): |
||||
|
""" Forms complete name of location from parent location to child location. """ |
||||
|
if self.parent_id.complete_name: |
||||
|
self.complete_name = "{}/{}".format(self.parent_id.complete_name, self.name) |
||||
|
else: |
||||
|
self.complete_name = self.name |
||||
|
|
||||
|
@api.depends("code_prefix_start", "parent_id.complete_code") |
||||
|
def _compute_complete_code(self): |
||||
|
""" Forms complete code of location from parent location to child location. """ |
||||
|
if self.parent_id.complete_code: |
||||
|
self.complete_code = "{}/{}".format( |
||||
|
self.parent_id.complete_code, self.code_prefix_start |
||||
|
) |
||||
|
else: |
||||
|
self.complete_code = self.code_prefix_start |
||||
|
|
||||
|
@api.depends("parent_id", "parent_id.level") |
||||
|
def _compute_level(self): |
||||
|
for group in self: |
||||
|
if not group.parent_id: |
||||
|
group.level = 0 |
||||
|
else: |
||||
|
group.level = group.parent_id.level + 1 |
||||
|
|
||||
|
@api.depends( |
||||
|
"code_prefix_start", |
||||
|
"account_ids", |
||||
|
"account_ids.code", |
||||
|
"group_child_ids", |
||||
|
"group_child_ids.account_ids.code", |
||||
|
) |
||||
|
def _compute_group_accounts(self): |
||||
|
account_obj = self.env["account.account"] |
||||
|
accounts = account_obj.search([]) |
||||
|
for group in self: |
||||
|
prefix = group.code_prefix_start if group.code_prefix_start else group.name |
||||
|
gr_acc = accounts.filtered(lambda a: a.code.startswith(prefix)).ids |
||||
|
group.compute_account_ids = [(6, 0, gr_acc)] |
@ -0,0 +1,40 @@ |
|||||
|
# Copyright 2019 ACSONE SA/NV (<http://acsone.eu>) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
from odoo import api, models |
||||
|
|
||||
|
|
||||
|
class AccountMoveLine(models.Model): |
||||
|
_inherit = "account.move.line" |
||||
|
|
||||
|
def init(self): |
||||
|
""" |
||||
|
The join between accounts_partners subquery and account_move_line |
||||
|
can be heavy to compute on big databases. |
||||
|
Join sample: |
||||
|
JOIN |
||||
|
account_move_line ml |
||||
|
ON ap.account_id = ml.account_id |
||||
|
AND ml.date < '2018-12-30' |
||||
|
AND ap.partner_id = ml.partner_id |
||||
|
AND ap.include_initial_balance = TRUE |
||||
|
By adding the following index, performances are strongly increased. |
||||
|
:return: |
||||
|
""" |
||||
|
self._cr.execute( |
||||
|
"SELECT indexname FROM pg_indexes WHERE indexname = " "%s", |
||||
|
("account_move_line_account_id_partner_id_index",), |
||||
|
) |
||||
|
if not self._cr.fetchone(): |
||||
|
self._cr.execute( |
||||
|
""" |
||||
|
CREATE INDEX account_move_line_account_id_partner_id_index |
||||
|
ON account_move_line (account_id, partner_id)""" |
||||
|
) |
||||
|
|
||||
|
@api.model |
||||
|
def search_count(self, args): |
||||
|
# In Big DataBase every time you change the domain widget this method |
||||
|
# takes a lot of time. This improves performance |
||||
|
if self.env.context.get("skip_search_count"): |
||||
|
return 0 |
||||
|
return super(AccountMoveLine, self).search_count(args) |
@ -0,0 +1,25 @@ |
|||||
|
# Copyright 2020 Onestein (<https://www.onestein.eu>) |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from odoo import api, models |
||||
|
|
||||
|
|
||||
|
class IrActionsReport(models.Model): |
||||
|
_inherit = "ir.actions.report" |
||||
|
|
||||
|
@api.model |
||||
|
def _prepare_account_financial_report_context(self, data): |
||||
|
lang = data and data.get("account_financial_report_lang") or "" |
||||
|
return dict(self.env.context or {}, lang=lang) if lang else False |
||||
|
|
||||
|
@api.model |
||||
|
def render_qweb_html(self, docids, data=None): |
||||
|
context = self._prepare_account_financial_report_context(data) |
||||
|
obj = self.with_context(context) if context else self |
||||
|
return super(IrActionsReport, obj).render_qweb_html(docids, data) |
||||
|
|
||||
|
@api.model |
||||
|
def render_xlsx(self, docids, data): |
||||
|
context = self._prepare_account_financial_report_context(data) |
||||
|
obj = self.with_context(context) if context else self |
||||
|
return super(IrActionsReport, obj).render_xlsx(docids, data) |
@ -0,0 +1,27 @@ |
|||||
|
* Jordi Ballester <jordi.ballester@forgeflow.com> |
||||
|
* Yannick Vaucher <yannick.vaucher@camptocamp.com> |
||||
|
* Simone Orsi <simone.orsi@abstract.com> |
||||
|
* Leonardo Pistone <leonardo.pistone@camptocamp.com> |
||||
|
* Damien Crier <damien.crier@camptocamp.com> |
||||
|
* Andrea Stirpe <a.stirpe@onestein.nl> |
||||
|
* Thomas Rehn <thomas.rehn@initos.com> |
||||
|
* Andrea Gallina <4everamd@gmail.com> |
||||
|
* Robert Rottermann <robert@redcor.ch> |
||||
|
* Ciro Urselli <c.urselli@apuliasoftware.it> |
||||
|
* Francesco Apruzzese <opencode@e-ware.org> |
||||
|
* Lorenzo Battistini <https://github.com/eLBati> |
||||
|
* Julien Coux <julien.coux@camptocamp.com> |
||||
|
* Akim Juillerat <akim.juillerat@camptocamp.com> |
||||
|
* Alexis de Lattre <alexis@via.ecp.fr> |
||||
|
* Mihai Fekete <feketemihai@gmail.com> |
||||
|
* Miquel Raïch <miquel.raich@forgeflow.com> |
||||
|
* Joan Sisquella <joan.sisquella@forgeflow.com> |
||||
|
* `Tecnativa <https://www.tecnativa.com>`__: |
||||
|
|
||||
|
* Pedro M. Baeza |
||||
|
* Sergio Teruel |
||||
|
* Ernesto Tejeda |
||||
|
* João Marques |
||||
|
|
||||
|
Much of the work in this module was done at a sprint in Sorrento, Italy in |
||||
|
April 2016. |
@ -0,0 +1,16 @@ |
|||||
|
This module adds a set of financial reports. They are accessible under |
||||
|
Invoicing / Reporting / OCA accounting reports. |
||||
|
|
||||
|
- General ledger |
||||
|
- Trial Balance |
||||
|
- Open Items |
||||
|
- Aged Partner Balance |
||||
|
- VAT Report |
||||
|
- Journal Ledger |
||||
|
|
||||
|
Currently General ledger, Trial Balance and Open Items are fully compatible with a foreign |
||||
|
currency set up in account in order to display balances. Moreover, any foreign |
||||
|
currency used in account move lines is properly shown. |
||||
|
|
||||
|
In case that in an account has not been configured a second currency foreign |
||||
|
currency balances are not available. |
@ -0,0 +1,19 @@ |
|||||
|
11.0.2.5.0 (2019-04-26) |
||||
|
~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
* In the Trial Balance you have an option to hide parent hierarchy levels |
||||
|
|
||||
|
11.0.2.4.1 (2019-01-08) |
||||
|
~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
* Handle better multicompany behaviour |
||||
|
* Improve how title appears in the reports |
||||
|
* Improve performance in General Ledger |
||||
|
|
||||
|
|
||||
|
11.0.2.3.1 (2018-11-29) |
||||
|
~~~~~~~~~~~~~~~~~~~~~~~ |
||||
|
|
||||
|
* In the Trial Balance you can apply a filter by hierarchy levels |
||||
|
* In the General Ledger you can apply a filter by Analytic Tag |
||||
|
* In the Journal Ledger the field 'Journal' is now optional |
@ -0,0 +1,7 @@ |
|||||
|
* 'VAT Report' is valid only for cases where it's met that for each |
||||
|
Tax defined: all the "Account tags" of all the |
||||
|
'Repartition for Invoices' or 'Repartition for Credit Notes' |
||||
|
are different. |
||||
|
* It would be nice to have in reports a column indicating the |
||||
|
state of the entries when the option "All Entries" is selected |
||||
|
in "Target Moves" field in a wizard |
@ -0,0 +1,18 @@ |
|||||
|
# © 2015 Yannick Vaucher (Camptocamp) |
||||
|
# © 2016 Damien Crier (Camptocamp) |
||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
|
||||
|
from . import abstract_report_xlsx |
||||
|
from . import aged_partner_balance |
||||
|
from . import aged_partner_balance_xlsx |
||||
|
from . import general_ledger |
||||
|
from . import general_ledger_xlsx |
||||
|
from . import journal_ledger |
||||
|
from . import journal_ledger_xlsx |
||||
|
from . import open_items |
||||
|
from . import open_items_xlsx |
||||
|
from . import trial_balance |
||||
|
from . import trial_balance_xlsx |
||||
|
from . import vat_report |
||||
|
from . import vat_report_xlsx |
@ -0,0 +1,687 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2021 Tecnativa - João Marques |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
|
class AbstractReportXslx(models.AbstractModel): |
||||
|
_name = "report.account_financial_report.abstract_report_xlsx" |
||||
|
_description = "Abstract XLSX Account Financial Report" |
||||
|
_inherit = "report.report_xlsx.abstract" |
||||
|
|
||||
|
def get_workbook_options(self): |
||||
|
vals = super().get_workbook_options() |
||||
|
vals.update({"constant_memory": True}) |
||||
|
return vals |
||||
|
|
||||
|
def generate_xlsx_report(self, workbook, data, objects): |
||||
|
# Initialize report variables |
||||
|
report_data = { |
||||
|
"workbook": None, |
||||
|
"sheet": None, # main sheet which will contains report |
||||
|
"columns": None, # columns of the report |
||||
|
"row_pos": None, # row_pos must be incremented at each writing lines |
||||
|
"formats": None, |
||||
|
} |
||||
|
self._define_formats(workbook, report_data) |
||||
|
# Get report data |
||||
|
report_name = self._get_report_name(objects, data=data) |
||||
|
report_footer = self._get_report_footer() |
||||
|
filters = self._get_report_filters(objects) |
||||
|
report_data["columns"] = self._get_report_columns(objects) |
||||
|
report_data["workbook"] = workbook |
||||
|
report_data["sheet"] = workbook.add_worksheet(report_name[:31]) |
||||
|
self._set_column_width(report_data) |
||||
|
# Fill report |
||||
|
report_data["row_pos"] = 0 |
||||
|
self._write_report_title(report_name, report_data) |
||||
|
self._write_filters(filters, report_data) |
||||
|
self._generate_report_content(workbook, objects, data, report_data) |
||||
|
self._write_report_footer(report_footer, report_data) |
||||
|
|
||||
|
def _define_formats(self, workbook, report_data): |
||||
|
"""Add cell formats to current workbook. |
||||
|
Those formats can be used on all cell. |
||||
|
Available formats are : |
||||
|
* format_bold |
||||
|
* format_right |
||||
|
* format_right_bold_italic |
||||
|
* format_header_left |
||||
|
* format_header_center |
||||
|
* format_header_right |
||||
|
* format_header_amount |
||||
|
* format_amount |
||||
|
* format_percent_bold_italic |
||||
|
""" |
||||
|
currency_id = self.env["res.company"]._default_currency_id() |
||||
|
report_data["formats"] = { |
||||
|
"format_bold": workbook.add_format({"bold": True}), |
||||
|
"format_right": workbook.add_format({"align": "right"}), |
||||
|
"format_left": workbook.add_format({"align": "left"}), |
||||
|
"format_right_bold_italic": workbook.add_format( |
||||
|
{"align": "right", "bold": True, "italic": True} |
||||
|
), |
||||
|
"format_header_left": workbook.add_format( |
||||
|
{"bold": True, "border": True, "bg_color": "#FFFFCC"} |
||||
|
), |
||||
|
"format_header_center": workbook.add_format( |
||||
|
{"bold": True, "align": "center", "border": True, "bg_color": "#FFFFCC"} |
||||
|
), |
||||
|
"format_header_right": workbook.add_format( |
||||
|
{"bold": True, "align": "right", "border": True, "bg_color": "#FFFFCC"} |
||||
|
), |
||||
|
"format_header_amount": workbook.add_format( |
||||
|
{"bold": True, "border": True, "bg_color": "#FFFFCC"} |
||||
|
).set_num_format("#,##0." + "0" * currency_id.decimal_places), |
||||
|
"format_amount": workbook.add_format().set_num_format( |
||||
|
"#,##0." + "0" * currency_id.decimal_places |
||||
|
), |
||||
|
"format_amount_bold": workbook.add_format({"bold": True}).set_num_format( |
||||
|
"#,##0." + "0" * currency_id.decimal_places |
||||
|
), |
||||
|
"format_percent_bold_italic": workbook.add_format( |
||||
|
{"bold": True, "italic": True} |
||||
|
).set_num_format("#,##0.00%"), |
||||
|
} |
||||
|
|
||||
|
def _set_column_width(self, report_data): |
||||
|
"""Set width for all defined columns. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
for position, column in report_data["columns"].items(): |
||||
|
report_data["sheet"].set_column(position, position, column["width"]) |
||||
|
|
||||
|
def _write_report_title(self, title, report_data): |
||||
|
"""Write report title on current line using all defined columns width. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
report_data["sheet"].merge_range( |
||||
|
report_data["row_pos"], |
||||
|
0, |
||||
|
report_data["row_pos"], |
||||
|
len(report_data["columns"]) - 1, |
||||
|
title, |
||||
|
report_data["formats"]["format_bold"], |
||||
|
) |
||||
|
report_data["row_pos"] += 3 |
||||
|
|
||||
|
def _write_report_footer(self, footer, report_data): |
||||
|
"""Write report footer . |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
if footer: |
||||
|
report_data["row_pos"] += 1 |
||||
|
report_data["sheet"].merge_range( |
||||
|
report_data["row_pos"], |
||||
|
0, |
||||
|
report_data["row_pos"], |
||||
|
len(report_data["columns"]) - 1, |
||||
|
footer, |
||||
|
report_data["formats"]["format_left"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def _write_filters(self, filters, report_data): |
||||
|
"""Write one line per filters on starting on current line. |
||||
|
Columns number for filter name is defined |
||||
|
with `_get_col_count_filter_name` method. |
||||
|
Columns number for filter value is define |
||||
|
with `_get_col_count_filter_value` method. |
||||
|
""" |
||||
|
col_name = 1 |
||||
|
col_count_filter_name = self._get_col_count_filter_name() |
||||
|
col_count_filter_value = self._get_col_count_filter_value() |
||||
|
col_value = col_name + col_count_filter_name + 1 |
||||
|
for title, value in filters: |
||||
|
report_data["sheet"].merge_range( |
||||
|
report_data["row_pos"], |
||||
|
col_name, |
||||
|
report_data["row_pos"], |
||||
|
col_name + col_count_filter_name - 1, |
||||
|
title, |
||||
|
report_data["formats"]["format_header_left"], |
||||
|
) |
||||
|
report_data["sheet"].merge_range( |
||||
|
report_data["row_pos"], |
||||
|
col_value, |
||||
|
report_data["row_pos"], |
||||
|
col_value + col_count_filter_value - 1, |
||||
|
value, |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
report_data["row_pos"] += 2 |
||||
|
|
||||
|
def write_array_title(self, title, report_data): |
||||
|
"""Write array title on current line using all defined columns width. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
report_data["sheet"].merge_range( |
||||
|
report_data["row_pos"], |
||||
|
0, |
||||
|
report_data["row_pos"], |
||||
|
len(report_data["columns"]) - 1, |
||||
|
title, |
||||
|
report_data["formats"]["format_bold"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def write_array_header(self, report_data): |
||||
|
"""Write array header on current line using all defined columns name. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
report_data["sheet"].write( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
column["header"], |
||||
|
report_data["formats"]["format_header_center"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def write_line(self, line_object, report_data): |
||||
|
"""Write a line on current line using all defined columns field name. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
value = getattr(line_object, column["field"]) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "many2one": |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value.name or "", |
||||
|
report_data["formats"]["format_right"], |
||||
|
) |
||||
|
elif cell_type == "string": |
||||
|
if ( |
||||
|
hasattr(line_object, "account_group_id") |
||||
|
and line_object.account_group_id |
||||
|
): |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value or "", |
||||
|
report_data["formats"]["format_bold"], |
||||
|
) |
||||
|
else: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], col_pos, value or "" |
||||
|
) |
||||
|
elif cell_type == "amount": |
||||
|
if ( |
||||
|
hasattr(line_object, "account_group_id") |
||||
|
and line_object.account_group_id |
||||
|
): |
||||
|
cell_format = report_data["formats"]["format_amount_bold"] |
||||
|
else: |
||||
|
cell_format = report_data["formats"]["format_amount"] |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), cell_format |
||||
|
) |
||||
|
elif cell_type == "amount_currency": |
||||
|
if line_object.currency_id: |
||||
|
format_amt = self._get_currency_amt_format(line_object, report_data) |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), format_amt |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def write_line_from_dict(self, line_dict, report_data): |
||||
|
"""Write a line on current line""" |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
value = line_dict.get(column["field"], False) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "string": |
||||
|
if ( |
||||
|
line_dict.get("account_group_id", False) |
||||
|
and line_dict["account_group_id"] |
||||
|
): |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value or "", |
||||
|
report_data["formats"]["format_bold"], |
||||
|
) |
||||
|
else: |
||||
|
if ( |
||||
|
not isinstance(value, str) |
||||
|
and not isinstance(value, bool) |
||||
|
and not isinstance(value, int) |
||||
|
): |
||||
|
value = value and value.strftime("%d/%m/%Y") |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], col_pos, value or "" |
||||
|
) |
||||
|
elif cell_type == "amount": |
||||
|
if ( |
||||
|
line_dict.get("account_group_id", False) |
||||
|
and line_dict["account_group_id"] |
||||
|
): |
||||
|
cell_format = report_data["formats"]["format_amount_bold"] |
||||
|
else: |
||||
|
cell_format = report_data["formats"]["format_amount"] |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), cell_format |
||||
|
) |
||||
|
elif cell_type == "amount_currency": |
||||
|
if line_dict.get("currency_name", False): |
||||
|
format_amt = self._get_currency_amt_format_dict( |
||||
|
line_dict, report_data |
||||
|
) |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), format_amt |
||||
|
) |
||||
|
elif cell_type == "currency_name": |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value or "", |
||||
|
report_data["formats"]["format_right"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def write_initial_balance(self, my_object, label, report_data): |
||||
|
"""Write a specific initial balance line on current line |
||||
|
using defined columns field_initial_balance name. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
col_pos_label = self._get_col_pos_initial_balance_label() |
||||
|
report_data["sheet"].write( |
||||
|
report_data["row_pos"], |
||||
|
col_pos_label, |
||||
|
label, |
||||
|
report_data["formats"]["format_right"], |
||||
|
) |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
if column.get("field_initial_balance"): |
||||
|
value = getattr(my_object, column["field_initial_balance"]) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "string": |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], col_pos, value or "" |
||||
|
) |
||||
|
elif cell_type == "amount": |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
float(value), |
||||
|
report_data["formats"]["format_amount"], |
||||
|
) |
||||
|
elif cell_type == "amount_currency": |
||||
|
if my_object.currency_id: |
||||
|
format_amt = self._get_currency_amt_format( |
||||
|
my_object, report_data |
||||
|
) |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), format_amt |
||||
|
) |
||||
|
elif column.get("field_currency_balance"): |
||||
|
value = getattr(my_object, column["field_currency_balance"]) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "many2one": |
||||
|
if my_object.currency_id: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value.name or "", |
||||
|
report_data["formats"]["format_right"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def write_initial_balance_from_dict(self, my_object, label, report_data): |
||||
|
"""Write a specific initial balance line on current line |
||||
|
using defined columns field_initial_balance name. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
col_pos_label = self._get_col_pos_initial_balance_label() |
||||
|
report_data["sheet"].write( |
||||
|
report_data["row_pos"], |
||||
|
col_pos_label, |
||||
|
label, |
||||
|
report_data["formats"]["format_right"], |
||||
|
) |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
if column.get("field_initial_balance"): |
||||
|
value = my_object.get(column["field_initial_balance"], False) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "string": |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], col_pos, value or "" |
||||
|
) |
||||
|
elif cell_type == "amount": |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
float(value), |
||||
|
report_data["formats"]["format_amount"], |
||||
|
) |
||||
|
elif cell_type == "amount_currency": |
||||
|
if my_object["currency_id"]: |
||||
|
format_amt = self._get_currency_amt_format( |
||||
|
my_object, report_data |
||||
|
) |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), format_amt |
||||
|
) |
||||
|
elif column.get("field_currency_balance"): |
||||
|
value = my_object.get(column["field_currency_balance"], False) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "many2one": |
||||
|
if my_object["currency_id"]: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value.name or "", |
||||
|
report_data["formats"]["format_right"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def write_ending_balance(self, my_object, name, label, report_data): |
||||
|
"""Write a specific ending balance line on current line |
||||
|
using defined columns field_final_balance name. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
for i in range(0, len(report_data["columns"])): |
||||
|
report_data["sheet"].write( |
||||
|
report_data["row_pos"], |
||||
|
i, |
||||
|
"", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
row_count_name = self._get_col_count_final_balance_name() |
||||
|
col_pos_label = self._get_col_pos_final_balance_label() |
||||
|
report_data["sheet"].merge_range( |
||||
|
report_data["row_pos"], |
||||
|
0, |
||||
|
report_data["row_pos"], |
||||
|
row_count_name - 1, |
||||
|
name, |
||||
|
report_data["formats"]["format_header_left"], |
||||
|
) |
||||
|
report_data["sheet"].write( |
||||
|
report_data["row_pos"], |
||||
|
col_pos_label, |
||||
|
label, |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
if column.get("field_final_balance"): |
||||
|
value = getattr(my_object, column["field_final_balance"]) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "string": |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value or "", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
elif cell_type == "amount": |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
float(value), |
||||
|
report_data["formats"]["format_header_amount"], |
||||
|
) |
||||
|
elif cell_type == "amount_currency": |
||||
|
if my_object.currency_id: |
||||
|
format_amt = self._get_currency_amt_header_format( |
||||
|
my_object, report_data |
||||
|
) |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), format_amt |
||||
|
) |
||||
|
elif column.get("field_currency_balance"): |
||||
|
value = getattr(my_object, column["field_currency_balance"]) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "many2one": |
||||
|
if my_object.currency_id: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value.name or "", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def write_ending_balance_from_dict(self, my_object, name, label, report_data): |
||||
|
"""Write a specific ending balance line on current line |
||||
|
using defined columns field_final_balance name. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
for i in range(0, len(report_data["columns"])): |
||||
|
report_data["sheet"].write( |
||||
|
report_data["row_pos"], |
||||
|
i, |
||||
|
"", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
row_count_name = self._get_col_count_final_balance_name() |
||||
|
col_pos_label = self._get_col_pos_final_balance_label() |
||||
|
report_data["sheet"].merge_range( |
||||
|
report_data["row_pos"], |
||||
|
0, |
||||
|
report_data["row_pos"], |
||||
|
row_count_name - 1, |
||||
|
name, |
||||
|
report_data["formats"]["format_header_left"], |
||||
|
) |
||||
|
report_data["sheet"].write( |
||||
|
report_data["row_pos"], |
||||
|
col_pos_label, |
||||
|
label, |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
if column.get("field_final_balance"): |
||||
|
value = my_object.get(column["field_final_balance"], False) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "string": |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value or "", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
elif cell_type == "amount": |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
float(value), |
||||
|
report_data["formats"]["format_header_amount"], |
||||
|
) |
||||
|
elif cell_type == "amount_currency": |
||||
|
if my_object["currency_id"] and value: |
||||
|
format_amt = self._get_currency_amt_format_dict( |
||||
|
my_object, report_data |
||||
|
) |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), format_amt |
||||
|
) |
||||
|
elif column.get("field_currency_balance"): |
||||
|
value = my_object.get(column["field_currency_balance"], False) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "many2one": |
||||
|
if my_object["currency_id"]: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value or "", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
elif cell_type == "currency_name": |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value or "", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def _get_currency_amt_format(self, line_object, report_data): |
||||
|
""" Return amount format specific for each currency. """ |
||||
|
if "account_group_id" in line_object and line_object["account_group_id"]: |
||||
|
format_amt = report_data["formats"]["format_amount_bold"] |
||||
|
field_prefix = "format_amount_bold" |
||||
|
else: |
||||
|
format_amt = report_data["formats"]["format_amount"] |
||||
|
field_prefix = "format_amount" |
||||
|
if "currency_id" in line_object and line_object.get("currency_id", False): |
||||
|
field_name = "{}_{}".format(field_prefix, line_object["currency_id"].name) |
||||
|
if hasattr(self, field_name): |
||||
|
format_amt = getattr(self, field_name) |
||||
|
else: |
||||
|
format_amt = report_data["workbook"].add_format() |
||||
|
report_data["field_name"] = format_amt |
||||
|
format_amount = "#,##0." + ( |
||||
|
"0" * line_object["currency_id"].decimal_places |
||||
|
) |
||||
|
format_amt.set_num_format(format_amount) |
||||
|
return format_amt |
||||
|
|
||||
|
def _get_currency_amt_format_dict(self, line_dict, report_data): |
||||
|
""" Return amount format specific for each currency. """ |
||||
|
if line_dict.get("account_group_id", False) and line_dict["account_group_id"]: |
||||
|
format_amt = report_data["formats"]["format_amount_bold"] |
||||
|
field_prefix = "format_amount_bold" |
||||
|
else: |
||||
|
format_amt = report_data["formats"]["format_amount"] |
||||
|
field_prefix = "format_amount" |
||||
|
if line_dict.get("currency_id", False) and line_dict["currency_id"]: |
||||
|
if isinstance(line_dict["currency_id"], int): |
||||
|
currency = self.env["res.currency"].browse(line_dict["currency_id"]) |
||||
|
else: |
||||
|
currency = line_dict["currency_id"] |
||||
|
field_name = "{}_{}".format(field_prefix, currency.name) |
||||
|
if hasattr(self, field_name): |
||||
|
format_amt = getattr(self, field_name) |
||||
|
else: |
||||
|
format_amt = report_data["workbook"].add_format() |
||||
|
report_data["field_name"] = format_amt |
||||
|
format_amount = "#,##0." + ("0" * currency.decimal_places) |
||||
|
format_amt.set_num_format(format_amount) |
||||
|
return format_amt |
||||
|
|
||||
|
def _get_currency_amt_header_format(self, line_object, report_data): |
||||
|
""" Return amount header format for each currency. """ |
||||
|
format_amt = report_data["formats"]["format_header_amount"] |
||||
|
if line_object.currency_id: |
||||
|
field_name = "format_header_amount_%s" % line_object.currency_id.name |
||||
|
if hasattr(self, field_name): |
||||
|
format_amt = getattr(self, field_name) |
||||
|
else: |
||||
|
format_amt = report_data["workbook"].add_format( |
||||
|
{"bold": True, "border": True, "bg_color": "#FFFFCC"} |
||||
|
) |
||||
|
report_data["field_name"] = format_amt |
||||
|
format_amount = "#,##0." + ( |
||||
|
"0" * line_object.currency_id.decimal_places |
||||
|
) |
||||
|
format_amt.set_num_format(format_amount) |
||||
|
return format_amt |
||||
|
|
||||
|
def _get_currency_amt_header_format_dict(self, line_object, report_data): |
||||
|
""" Return amount header format for each currency. """ |
||||
|
format_amt = report_data["formats"]["format_header_amount"] |
||||
|
if line_object["currency_id"]: |
||||
|
field_name = "format_header_amount_%s" % line_object["currency_name"] |
||||
|
if hasattr(self, field_name): |
||||
|
format_amt = getattr(self, field_name) |
||||
|
else: |
||||
|
format_amt = report_data["workbook"].add_format( |
||||
|
{"bold": True, "border": True, "bg_color": "#FFFFCC"} |
||||
|
) |
||||
|
report_data["field_name"] = format_amt |
||||
|
format_amount = "#,##0." + ( |
||||
|
"0" * line_object["currency_id"].decimal_places |
||||
|
) |
||||
|
format_amt.set_num_format(format_amount) |
||||
|
return format_amt |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report, data, report_data): |
||||
|
""" |
||||
|
Allow to fetch report content to be displayed. |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_report_complete_name(self, report, prefix, data=None): |
||||
|
if report.company_id: |
||||
|
suffix = " - {} - {}".format( |
||||
|
report.company_id.name, report.company_id.currency_id.name |
||||
|
) |
||||
|
return prefix + suffix |
||||
|
return prefix |
||||
|
|
||||
|
def _get_report_name(self, report, data=False): |
||||
|
""" |
||||
|
Allow to define the report name. |
||||
|
Report name will be used as sheet name and as report title. |
||||
|
:return: the report name |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_report_footer(self): |
||||
|
""" |
||||
|
Allow to define the report footer. |
||||
|
:return: the report footer |
||||
|
""" |
||||
|
return False |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
""" |
||||
|
Allow to define the report columns |
||||
|
which will be used to generate report. |
||||
|
:return: the report columns as dict |
||||
|
:Example: |
||||
|
{ |
||||
|
0: {'header': 'Simple column', |
||||
|
'field': 'field_name_on_my_object', |
||||
|
'width': 11}, |
||||
|
1: {'header': 'Amount column', |
||||
|
'field': 'field_name_on_my_object', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
} |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_report_filters(self, report): |
||||
|
""" |
||||
|
:return: the report filters as list |
||||
|
:Example: |
||||
|
[ |
||||
|
['first_filter_name', 'first_filter_value'], |
||||
|
['second_filter_name', 'second_filter_value'] |
||||
|
] |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_col_count_filter_name(self): |
||||
|
""" |
||||
|
:return: the columns number used for filter names. |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_col_count_filter_value(self): |
||||
|
""" |
||||
|
:return: the columns number used for filter values. |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_col_pos_initial_balance_label(self): |
||||
|
""" |
||||
|
:return: the columns position used for initial balance label. |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_col_count_final_balance_name(self): |
||||
|
""" |
||||
|
:return: the columns number used for final balance name. |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_col_pos_final_balance_label(self): |
||||
|
""" |
||||
|
:return: the columns position used for final balance label. |
||||
|
""" |
||||
|
raise NotImplementedError() |
@ -0,0 +1,479 @@ |
|||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import operator |
||||
|
from datetime import date, datetime, timedelta |
||||
|
|
||||
|
from odoo import api, models |
||||
|
from odoo.tools import float_is_zero |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReport(models.AbstractModel): |
||||
|
_name = "report.account_financial_report.aged_partner_balance" |
||||
|
_description = "Aged Partner Balance Report" |
||||
|
|
||||
|
@api.model |
||||
|
def _initialize_account(self, ag_pb_data, acc_id): |
||||
|
ag_pb_data[acc_id] = {} |
||||
|
ag_pb_data[acc_id]["id"] = acc_id |
||||
|
ag_pb_data[acc_id]["residual"] = 0.0 |
||||
|
ag_pb_data[acc_id]["current"] = 0.0 |
||||
|
ag_pb_data[acc_id]["30_days"] = 0.0 |
||||
|
ag_pb_data[acc_id]["60_days"] = 0.0 |
||||
|
ag_pb_data[acc_id]["90_days"] = 0.0 |
||||
|
ag_pb_data[acc_id]["120_days"] = 0.0 |
||||
|
ag_pb_data[acc_id]["older"] = 0.0 |
||||
|
return ag_pb_data |
||||
|
|
||||
|
@api.model |
||||
|
def _initialize_partner(self, ag_pb_data, acc_id, prt_id): |
||||
|
ag_pb_data[acc_id][prt_id] = {} |
||||
|
ag_pb_data[acc_id][prt_id]["id"] = acc_id |
||||
|
ag_pb_data[acc_id][prt_id]["residual"] = 0.0 |
||||
|
ag_pb_data[acc_id][prt_id]["current"] = 0.0 |
||||
|
ag_pb_data[acc_id][prt_id]["30_days"] = 0.0 |
||||
|
ag_pb_data[acc_id][prt_id]["60_days"] = 0.0 |
||||
|
ag_pb_data[acc_id][prt_id]["90_days"] = 0.0 |
||||
|
ag_pb_data[acc_id][prt_id]["120_days"] = 0.0 |
||||
|
ag_pb_data[acc_id][prt_id]["older"] = 0.0 |
||||
|
ag_pb_data[acc_id][prt_id]["move_lines"] = [] |
||||
|
return ag_pb_data |
||||
|
|
||||
|
def _get_journals_data(self, journals_ids): |
||||
|
journals = self.env["account.journal"].browse(journals_ids) |
||||
|
journals_data = {} |
||||
|
for journal in journals: |
||||
|
journals_data.update({journal.id: {"id": journal.id, "code": journal.code}}) |
||||
|
return journals_data |
||||
|
|
||||
|
def _get_accounts_data(self, accounts_ids): |
||||
|
accounts = self.env["account.account"].browse(accounts_ids) |
||||
|
accounts_data = {} |
||||
|
for account in accounts: |
||||
|
accounts_data.update( |
||||
|
{ |
||||
|
account.id: { |
||||
|
"id": account.id, |
||||
|
"code": account.code, |
||||
|
"name": account.name, |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
return accounts_data |
||||
|
|
||||
|
@api.model |
||||
|
def _get_move_lines_domain( |
||||
|
self, company_id, account_ids, partner_ids, only_posted_moves, date_from |
||||
|
): |
||||
|
domain = [ |
||||
|
("account_id", "in", account_ids), |
||||
|
("company_id", "=", company_id), |
||||
|
("reconciled", "=", False), |
||||
|
] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
if date_from: |
||||
|
domain += [("date", ">", date_from)] |
||||
|
return domain |
||||
|
|
||||
|
@api.model |
||||
|
def _calculate_amounts( |
||||
|
self, ag_pb_data, acc_id, prt_id, residual, due_date, date_at_object |
||||
|
): |
||||
|
ag_pb_data[acc_id]["residual"] += residual |
||||
|
ag_pb_data[acc_id][prt_id]["residual"] += residual |
||||
|
today = date_at_object |
||||
|
if not due_date or today <= due_date: |
||||
|
ag_pb_data[acc_id]["current"] += residual |
||||
|
ag_pb_data[acc_id][prt_id]["current"] += residual |
||||
|
elif today <= due_date + timedelta(days=30): |
||||
|
ag_pb_data[acc_id]["30_days"] += residual |
||||
|
ag_pb_data[acc_id][prt_id]["30_days"] += residual |
||||
|
elif today <= due_date + timedelta(days=60): |
||||
|
ag_pb_data[acc_id]["60_days"] += residual |
||||
|
ag_pb_data[acc_id][prt_id]["60_days"] += residual |
||||
|
elif today <= due_date + timedelta(days=90): |
||||
|
ag_pb_data[acc_id]["90_days"] += residual |
||||
|
ag_pb_data[acc_id][prt_id]["90_days"] += residual |
||||
|
elif today <= due_date + timedelta(days=120): |
||||
|
ag_pb_data[acc_id]["120_days"] += residual |
||||
|
ag_pb_data[acc_id][prt_id]["120_days"] += residual |
||||
|
else: |
||||
|
ag_pb_data[acc_id]["older"] += residual |
||||
|
ag_pb_data[acc_id][prt_id]["older"] += residual |
||||
|
return ag_pb_data |
||||
|
|
||||
|
def _get_account_partial_reconciled(self, company_id, date_at_object): |
||||
|
domain = [("max_date", ">", date_at_object), ("company_id", "=", company_id)] |
||||
|
fields = ["debit_move_id", "credit_move_id", "amount"] |
||||
|
accounts_partial_reconcile = self.env["account.partial.reconcile"].search_read( |
||||
|
domain=domain, fields=fields |
||||
|
) |
||||
|
debit_amount = {} |
||||
|
credit_amount = {} |
||||
|
for account_partial_reconcile_data in accounts_partial_reconcile: |
||||
|
debit_move_id = account_partial_reconcile_data["debit_move_id"][0] |
||||
|
credit_move_id = account_partial_reconcile_data["credit_move_id"][0] |
||||
|
if debit_move_id not in debit_amount.keys(): |
||||
|
debit_amount[debit_move_id] = 0.0 |
||||
|
debit_amount[debit_move_id] += account_partial_reconcile_data["amount"] |
||||
|
if credit_move_id not in credit_amount.keys(): |
||||
|
credit_amount[credit_move_id] = 0.0 |
||||
|
credit_amount[credit_move_id] += account_partial_reconcile_data["amount"] |
||||
|
account_partial_reconcile_data.update( |
||||
|
{"debit_move_id": debit_move_id, "credit_move_id": credit_move_id} |
||||
|
) |
||||
|
return accounts_partial_reconcile, debit_amount, credit_amount |
||||
|
|
||||
|
@api.model |
||||
|
def _get_new_move_lines_domain( |
||||
|
self, new_ml_ids, account_ids, company_id, partner_ids, only_posted_moves |
||||
|
): |
||||
|
domain = [ |
||||
|
("account_id", "in", account_ids), |
||||
|
("company_id", "=", company_id), |
||||
|
("id", "in", new_ml_ids), |
||||
|
] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
return domain |
||||
|
|
||||
|
def _recalculate_move_lines( |
||||
|
self, |
||||
|
move_lines, |
||||
|
debit_ids, |
||||
|
credit_ids, |
||||
|
debit_amount, |
||||
|
credit_amount, |
||||
|
ml_ids, |
||||
|
account_ids, |
||||
|
company_id, |
||||
|
partner_ids, |
||||
|
only_posted_moves, |
||||
|
): |
||||
|
debit_ids = set(debit_ids) |
||||
|
credit_ids = set(credit_ids) |
||||
|
in_credit_but_not_in_debit = credit_ids - debit_ids |
||||
|
reconciled_ids = list(debit_ids) + list(in_credit_but_not_in_debit) |
||||
|
reconciled_ids = set(reconciled_ids) |
||||
|
ml_ids = set(ml_ids) |
||||
|
new_ml_ids = reconciled_ids - ml_ids |
||||
|
new_ml_ids = list(new_ml_ids) |
||||
|
new_domain = self._get_new_move_lines_domain( |
||||
|
new_ml_ids, account_ids, company_id, partner_ids, only_posted_moves |
||||
|
) |
||||
|
ml_fields = [ |
||||
|
"id", |
||||
|
"name", |
||||
|
"date", |
||||
|
"move_id", |
||||
|
"journal_id", |
||||
|
"account_id", |
||||
|
"partner_id", |
||||
|
"amount_residual", |
||||
|
"date_maturity", |
||||
|
"ref", |
||||
|
"reconciled", |
||||
|
] |
||||
|
new_move_lines = self.env["account.move.line"].search_read( |
||||
|
domain=new_domain, fields=ml_fields |
||||
|
) |
||||
|
move_lines = move_lines + new_move_lines |
||||
|
for move_line in move_lines: |
||||
|
ml_id = move_line["id"] |
||||
|
if ml_id in debit_ids: |
||||
|
move_line["amount_residual"] += debit_amount[ml_id] |
||||
|
if ml_id in credit_ids: |
||||
|
move_line["amount_residual"] -= credit_amount[ml_id] |
||||
|
return move_lines |
||||
|
|
||||
|
def _get_move_lines_data( |
||||
|
self, |
||||
|
company_id, |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
date_at_object, |
||||
|
date_from, |
||||
|
only_posted_moves, |
||||
|
show_move_line_details, |
||||
|
): |
||||
|
domain = self._get_move_lines_domain( |
||||
|
company_id, account_ids, partner_ids, only_posted_moves, date_from |
||||
|
) |
||||
|
ml_fields = [ |
||||
|
"id", |
||||
|
"name", |
||||
|
"date", |
||||
|
"move_id", |
||||
|
"journal_id", |
||||
|
"account_id", |
||||
|
"partner_id", |
||||
|
"amount_residual", |
||||
|
"date_maturity", |
||||
|
"ref", |
||||
|
"reconciled", |
||||
|
] |
||||
|
move_lines = self.env["account.move.line"].search_read( |
||||
|
domain=domain, fields=ml_fields |
||||
|
) |
||||
|
journals_ids = set() |
||||
|
partners_ids = set() |
||||
|
partners_data = {} |
||||
|
ag_pb_data = {} |
||||
|
if date_at_object < date.today(): |
||||
|
( |
||||
|
acc_partial_rec, |
||||
|
debit_amount, |
||||
|
credit_amount, |
||||
|
) = self._get_account_partial_reconciled(company_id, date_at_object) |
||||
|
if acc_partial_rec: |
||||
|
ml_ids = list(map(operator.itemgetter("id"), move_lines)) |
||||
|
debit_ids = list( |
||||
|
map(operator.itemgetter("debit_move_id"), acc_partial_rec) |
||||
|
) |
||||
|
credit_ids = list( |
||||
|
map(operator.itemgetter("credit_move_id"), acc_partial_rec) |
||||
|
) |
||||
|
move_lines = self._recalculate_move_lines( |
||||
|
move_lines, |
||||
|
debit_ids, |
||||
|
credit_ids, |
||||
|
debit_amount, |
||||
|
credit_amount, |
||||
|
ml_ids, |
||||
|
account_ids, |
||||
|
company_id, |
||||
|
partner_ids, |
||||
|
only_posted_moves, |
||||
|
) |
||||
|
move_lines = [ |
||||
|
move_line |
||||
|
for move_line in move_lines |
||||
|
if move_line["date"] <= date_at_object |
||||
|
and not float_is_zero(move_line["amount_residual"], precision_digits=2) |
||||
|
] |
||||
|
for move_line in move_lines: |
||||
|
journals_ids.add(move_line["journal_id"][0]) |
||||
|
acc_id = move_line["account_id"][0] |
||||
|
if move_line["partner_id"]: |
||||
|
prt_id = move_line["partner_id"][0] |
||||
|
prt_name = move_line["partner_id"][1] |
||||
|
else: |
||||
|
prt_id = 0 |
||||
|
prt_name = "" |
||||
|
if prt_id not in partners_ids: |
||||
|
partners_data.update({prt_id: {"id": prt_id, "name": prt_name}}) |
||||
|
partners_ids.add(prt_id) |
||||
|
if acc_id not in ag_pb_data.keys(): |
||||
|
ag_pb_data = self._initialize_account(ag_pb_data, acc_id) |
||||
|
if prt_id not in ag_pb_data[acc_id]: |
||||
|
ag_pb_data = self._initialize_partner(ag_pb_data, acc_id, prt_id) |
||||
|
move_line_data = {} |
||||
|
if show_move_line_details: |
||||
|
if move_line["ref"] == move_line["name"]: |
||||
|
if move_line["ref"]: |
||||
|
ref_label = move_line["ref"] |
||||
|
else: |
||||
|
ref_label = "" |
||||
|
elif not move_line["ref"]: |
||||
|
ref_label = move_line["name"] |
||||
|
elif not move_line["name"]: |
||||
|
ref_label = move_line["ref"] |
||||
|
else: |
||||
|
ref_label = move_line["ref"] + str(" - ") + move_line["name"] |
||||
|
move_line_data.update( |
||||
|
{ |
||||
|
"date": move_line["date"], |
||||
|
"entry": move_line["move_id"][1], |
||||
|
"jnl_id": move_line["journal_id"][0], |
||||
|
"acc_id": acc_id, |
||||
|
"partner": prt_name, |
||||
|
"ref_label": ref_label, |
||||
|
"due_date": move_line["date_maturity"], |
||||
|
"residual": move_line["amount_residual"], |
||||
|
} |
||||
|
) |
||||
|
ag_pb_data[acc_id][prt_id]["move_lines"].append(move_line_data) |
||||
|
ag_pb_data = self._calculate_amounts( |
||||
|
ag_pb_data, |
||||
|
acc_id, |
||||
|
prt_id, |
||||
|
move_line["amount_residual"], |
||||
|
move_line["date_maturity"], |
||||
|
date_at_object, |
||||
|
) |
||||
|
journals_data = self._get_journals_data(list(journals_ids)) |
||||
|
accounts_data = self._get_accounts_data(ag_pb_data.keys()) |
||||
|
return ag_pb_data, accounts_data, partners_data, journals_data |
||||
|
|
||||
|
@api.model |
||||
|
def _compute_maturity_date(self, ml, date_at_object): |
||||
|
ml.update( |
||||
|
{ |
||||
|
"current": 0.0, |
||||
|
"30_days": 0.0, |
||||
|
"60_days": 0.0, |
||||
|
"90_days": 0.0, |
||||
|
"120_days": 0.0, |
||||
|
"older": 0.0, |
||||
|
} |
||||
|
) |
||||
|
due_date = ml["due_date"] |
||||
|
amount = ml["residual"] |
||||
|
today = date_at_object |
||||
|
if not due_date or today <= due_date: |
||||
|
ml["current"] += amount |
||||
|
elif today <= due_date + timedelta(days=30): |
||||
|
ml["30_days"] += amount |
||||
|
elif today <= due_date + timedelta(days=60): |
||||
|
ml["60_days"] += amount |
||||
|
elif today <= due_date + timedelta(days=90): |
||||
|
ml["90_days"] += amount |
||||
|
elif today <= due_date + timedelta(days=120): |
||||
|
ml["120_days"] += amount |
||||
|
else: |
||||
|
ml["older"] += amount |
||||
|
|
||||
|
def _create_account_list( |
||||
|
self, |
||||
|
ag_pb_data, |
||||
|
accounts_data, |
||||
|
partners_data, |
||||
|
journals_data, |
||||
|
show_move_line_details, |
||||
|
date_at_oject, |
||||
|
): |
||||
|
aged_partner_data = [] |
||||
|
for account in accounts_data.values(): |
||||
|
acc_id = account["id"] |
||||
|
account.update( |
||||
|
{ |
||||
|
"residual": ag_pb_data[acc_id]["residual"], |
||||
|
"current": ag_pb_data[acc_id]["current"], |
||||
|
"30_days": ag_pb_data[acc_id]["30_days"], |
||||
|
"60_days": ag_pb_data[acc_id]["60_days"], |
||||
|
"90_days": ag_pb_data[acc_id]["90_days"], |
||||
|
"120_days": ag_pb_data[acc_id]["120_days"], |
||||
|
"older": ag_pb_data[acc_id]["older"], |
||||
|
"partners": [], |
||||
|
} |
||||
|
) |
||||
|
for prt_id in ag_pb_data[acc_id]: |
||||
|
if isinstance(prt_id, int): |
||||
|
partner = { |
||||
|
"name": partners_data[prt_id]["name"], |
||||
|
"residual": ag_pb_data[acc_id][prt_id]["residual"], |
||||
|
"current": ag_pb_data[acc_id][prt_id]["current"], |
||||
|
"30_days": ag_pb_data[acc_id][prt_id]["30_days"], |
||||
|
"60_days": ag_pb_data[acc_id][prt_id]["60_days"], |
||||
|
"90_days": ag_pb_data[acc_id][prt_id]["90_days"], |
||||
|
"120_days": ag_pb_data[acc_id][prt_id]["120_days"], |
||||
|
"older": ag_pb_data[acc_id][prt_id]["older"], |
||||
|
} |
||||
|
if show_move_line_details: |
||||
|
move_lines = [] |
||||
|
for ml in ag_pb_data[acc_id][prt_id]["move_lines"]: |
||||
|
ml.update( |
||||
|
{ |
||||
|
"journal": journals_data[ml["jnl_id"]]["code"], |
||||
|
"account": accounts_data[ml["acc_id"]]["code"], |
||||
|
} |
||||
|
) |
||||
|
self._compute_maturity_date(ml, date_at_oject) |
||||
|
move_lines.append(ml) |
||||
|
move_lines = sorted(move_lines, key=lambda k: (k["date"])) |
||||
|
partner.update({"move_lines": move_lines}) |
||||
|
account["partners"].append(partner) |
||||
|
aged_partner_data.append(account) |
||||
|
return aged_partner_data |
||||
|
|
||||
|
@api.model |
||||
|
def _calculate_percent(self, aged_partner_data): |
||||
|
for account in aged_partner_data: |
||||
|
if abs(account["residual"]) > 0.01: |
||||
|
total = account["residual"] |
||||
|
account.update( |
||||
|
{ |
||||
|
"percent_current": abs( |
||||
|
round((account["current"] / total) * 100, 2) |
||||
|
), |
||||
|
"percent_30_days": abs( |
||||
|
round((account["30_days"] / total) * 100, 2) |
||||
|
), |
||||
|
"percent_60_days": abs( |
||||
|
round((account["60_days"] / total) * 100, 2) |
||||
|
), |
||||
|
"percent_90_days": abs( |
||||
|
round((account["90_days"] / total) * 100, 2) |
||||
|
), |
||||
|
"percent_120_days": abs( |
||||
|
round((account["120_days"] / total) * 100, 2) |
||||
|
), |
||||
|
"percent_older": abs( |
||||
|
round((account["older"] / total) * 100, 2) |
||||
|
), |
||||
|
} |
||||
|
) |
||||
|
else: |
||||
|
account.update( |
||||
|
{ |
||||
|
"percent_current": 0.0, |
||||
|
"percent_30_days": 0.0, |
||||
|
"percent_60_days": 0.0, |
||||
|
"percent_90_days": 0.0, |
||||
|
"percent_120_days": 0.0, |
||||
|
"percent_older": 0.0, |
||||
|
} |
||||
|
) |
||||
|
return aged_partner_data |
||||
|
|
||||
|
def _get_report_values(self, docids, data): |
||||
|
wizard_id = data["wizard_id"] |
||||
|
company = self.env["res.company"].browse(data["company_id"]) |
||||
|
company_id = data["company_id"] |
||||
|
account_ids = data["account_ids"] |
||||
|
partner_ids = data["partner_ids"] |
||||
|
date_at = data["date_at"] |
||||
|
date_at_object = datetime.strptime(date_at, "%Y-%m-%d").date() |
||||
|
date_from = data["date_from"] |
||||
|
only_posted_moves = data["only_posted_moves"] |
||||
|
show_move_line_details = data["show_move_line_details"] |
||||
|
( |
||||
|
ag_pb_data, |
||||
|
accounts_data, |
||||
|
partners_data, |
||||
|
journals_data, |
||||
|
) = self._get_move_lines_data( |
||||
|
company_id, |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
date_at_object, |
||||
|
date_from, |
||||
|
only_posted_moves, |
||||
|
show_move_line_details, |
||||
|
) |
||||
|
aged_partner_data = self._create_account_list( |
||||
|
ag_pb_data, |
||||
|
accounts_data, |
||||
|
partners_data, |
||||
|
journals_data, |
||||
|
show_move_line_details, |
||||
|
date_at_object, |
||||
|
) |
||||
|
aged_partner_data = self._calculate_percent(aged_partner_data) |
||||
|
return { |
||||
|
"doc_ids": [wizard_id], |
||||
|
"doc_model": "open.items.report.wizard", |
||||
|
"docs": self.env["open.items.report.wizard"].browse(wizard_id), |
||||
|
"company_name": company.display_name, |
||||
|
"currency_name": company.currency_id.name, |
||||
|
"date_at": date_at, |
||||
|
"only_posted_moves": only_posted_moves, |
||||
|
"aged_partner_balance": aged_partner_data, |
||||
|
"show_move_lines_details": show_move_line_details, |
||||
|
} |
@ -0,0 +1,325 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2021 Tecnativa - João Marques |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import _, models |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceXslx(models.AbstractModel): |
||||
|
_name = "report.a_f_r.report_aged_partner_balance_xlsx" |
||||
|
_description = "Aged Partner Balance XLSL Report" |
||||
|
_inherit = "report.account_financial_report.abstract_report_xlsx" |
||||
|
|
||||
|
def _get_report_name(self, report, data=False): |
||||
|
company_id = data.get("company_id", False) |
||||
|
report_name = _("Aged Partner Balance") |
||||
|
if company_id: |
||||
|
company = self.env["res.company"].browse(company_id) |
||||
|
suffix = " - {} - {}".format(company.name, company.currency_id.name) |
||||
|
report_name = report_name + suffix |
||||
|
return report_name |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
if not report.show_move_line_details: |
||||
|
return { |
||||
|
0: {"header": _("Partner"), "field": "name", "width": 70}, |
||||
|
1: { |
||||
|
"header": _("Residual"), |
||||
|
"field": "residual", |
||||
|
"field_footer_total": "residual", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
2: { |
||||
|
"header": _("Current"), |
||||
|
"field": "current", |
||||
|
"field_footer_total": "current", |
||||
|
"field_footer_percent": "percent_current", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
3: { |
||||
|
"header": _(u"Age ≤ 30 d."), |
||||
|
"field": "30_days", |
||||
|
"field_footer_total": "30_days", |
||||
|
"field_footer_percent": "percent_30_days", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
4: { |
||||
|
"header": _(u"Age ≤ 60 d."), |
||||
|
"field": "60_days", |
||||
|
"field_footer_total": "60_days", |
||||
|
"field_footer_percent": "percent_60_days", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
5: { |
||||
|
"header": _(u"Age ≤ 90 d."), |
||||
|
"field": "90_days", |
||||
|
"field_footer_total": "90_days", |
||||
|
"field_footer_percent": "percent_90_days", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
6: { |
||||
|
"header": _(u"Age ≤ 120 d."), |
||||
|
"field": "120_days", |
||||
|
"field_footer_total": "120_days", |
||||
|
"field_footer_percent": "percent_120_days", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
7: { |
||||
|
"header": _("Older"), |
||||
|
"field": "older", |
||||
|
"field_footer_total": "older", |
||||
|
"field_footer_percent": "percent_older", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
return { |
||||
|
0: {"header": _("Date"), "field": "date", "width": 11}, |
||||
|
1: {"header": _("Entry"), "field": "entry", "width": 18}, |
||||
|
2: {"header": _("Journal"), "field": "journal", "width": 8}, |
||||
|
3: {"header": _("Account"), "field": "account", "width": 9}, |
||||
|
4: {"header": _("Partner"), "field": "partner", "width": 25}, |
||||
|
5: {"header": _("Ref - Label"), "field": "ref_label", "width": 40}, |
||||
|
6: {"header": _("Due date"), "field": "due_date", "width": 11}, |
||||
|
7: { |
||||
|
"header": _("Residual"), |
||||
|
"field": "residual", |
||||
|
"field_footer_total": "residual", |
||||
|
"field_final_balance": "residual", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
8: { |
||||
|
"header": _("Current"), |
||||
|
"field": "current", |
||||
|
"field_footer_total": "current", |
||||
|
"field_footer_percent": "percent_current", |
||||
|
"field_final_balance": "current", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
9: { |
||||
|
"header": _(u"Age ≤ 30 d."), |
||||
|
"field": "30_days", |
||||
|
"field_footer_total": "30_days", |
||||
|
"field_footer_percent": "percent_30_days", |
||||
|
"field_final_balance": "30_days", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
10: { |
||||
|
"header": _(u"Age ≤ 60 d."), |
||||
|
"field": "60_days", |
||||
|
"field_footer_total": "60_days", |
||||
|
"field_footer_percent": "percent_60_days", |
||||
|
"field_final_balance": "60_days", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
11: { |
||||
|
"header": _(u"Age ≤ 90 d."), |
||||
|
"field": "90_days", |
||||
|
"field_footer_total": "90_days", |
||||
|
"field_footer_percent": "percent_90_days", |
||||
|
"field_final_balance": "90_days", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
12: { |
||||
|
"header": _(u"Age ≤ 120 d."), |
||||
|
"field": "120_days", |
||||
|
"field_footer_total": "120_days", |
||||
|
"field_footer_percent": "percent_120_days", |
||||
|
"field_final_balance": "120_days", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
13: { |
||||
|
"header": _("Older"), |
||||
|
"field": "older", |
||||
|
"field_footer_total": "older", |
||||
|
"field_footer_percent": "percent_older", |
||||
|
"field_final_balance": "older", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
def _get_report_filters(self, report): |
||||
|
return [ |
||||
|
[_("Date at filter"), report.date_at.strftime("%d/%m/%Y")], |
||||
|
[ |
||||
|
_("Target moves filter"), |
||||
|
_("All posted entries") |
||||
|
if report.target_move == "posted" |
||||
|
else _("All entries"), |
||||
|
], |
||||
|
] |
||||
|
|
||||
|
def _get_col_count_filter_name(self): |
||||
|
return 2 |
||||
|
|
||||
|
def _get_col_count_filter_value(self): |
||||
|
return 3 |
||||
|
|
||||
|
def _get_col_pos_footer_label(self, report): |
||||
|
return 0 if not report.show_move_line_details else 5 |
||||
|
|
||||
|
def _get_col_count_final_balance_name(self): |
||||
|
return 5 |
||||
|
|
||||
|
def _get_col_pos_final_balance_label(self): |
||||
|
return 5 |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report, data, report_data): |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.aged_partner_balance" |
||||
|
]._get_report_values(report, data) |
||||
|
show_move_line_details = res_data["show_move_lines_details"] |
||||
|
aged_partner_balance = res_data["aged_partner_balance"] |
||||
|
if not show_move_line_details: |
||||
|
# For each account |
||||
|
for account in aged_partner_balance: |
||||
|
# Write account title |
||||
|
self.write_array_title( |
||||
|
account["code"] + " - " + account["name"], report_data |
||||
|
) |
||||
|
|
||||
|
# Display array header for partners lines |
||||
|
self.write_array_header(report_data) |
||||
|
|
||||
|
# Display partner lines |
||||
|
for partner in account["partners"]: |
||||
|
self.write_line_from_dict(partner, report_data) |
||||
|
|
||||
|
# Display account lines |
||||
|
self.write_account_footer_from_dict( |
||||
|
report, |
||||
|
account, |
||||
|
("Total"), |
||||
|
"field_footer_total", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
report_data["formats"]["format_header_amount"], |
||||
|
False, |
||||
|
report_data, |
||||
|
) |
||||
|
self.write_account_footer_from_dict( |
||||
|
report, |
||||
|
account, |
||||
|
("Percents"), |
||||
|
"field_footer_percent", |
||||
|
report_data["formats"]["format_right_bold_italic"], |
||||
|
report_data["formats"]["format_percent_bold_italic"], |
||||
|
True, |
||||
|
report_data, |
||||
|
) |
||||
|
|
||||
|
# 2 lines break |
||||
|
report_data["row_pos"] += 2 |
||||
|
else: |
||||
|
# For each account |
||||
|
for account in aged_partner_balance: |
||||
|
# Write account title |
||||
|
self.write_array_title( |
||||
|
account["code"] + " - " + account["name"], report_data |
||||
|
) |
||||
|
|
||||
|
# For each partner |
||||
|
for partner in account["partners"]: |
||||
|
# Write partner title |
||||
|
self.write_array_title(partner["name"], report_data) |
||||
|
|
||||
|
# Display array header for move lines |
||||
|
self.write_array_header(report_data) |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in partner["move_lines"]: |
||||
|
self.write_line_from_dict(line, report_data) |
||||
|
|
||||
|
# Display ending balance line for partner |
||||
|
self.write_ending_balance_from_dict(partner, report_data) |
||||
|
|
||||
|
# Line break |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
# Display account lines |
||||
|
self.write_account_footer_from_dict( |
||||
|
report, |
||||
|
account, |
||||
|
("Total"), |
||||
|
"field_footer_total", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
report_data["formats"]["format_header_amount"], |
||||
|
False, |
||||
|
report_data, |
||||
|
) |
||||
|
|
||||
|
self.write_account_footer_from_dict( |
||||
|
report, |
||||
|
account, |
||||
|
("Percents"), |
||||
|
"field_footer_percent", |
||||
|
report_data["formats"]["format_right_bold_italic"], |
||||
|
report_data["formats"]["format_percent_bold_italic"], |
||||
|
True, |
||||
|
report_data, |
||||
|
) |
||||
|
|
||||
|
# 2 lines break |
||||
|
report_data["row_pos"] += 2 |
||||
|
|
||||
|
def write_ending_balance_from_dict(self, my_object, report_data): |
||||
|
""" |
||||
|
Specific function to write ending partner balance |
||||
|
for Aged Partner Balance |
||||
|
""" |
||||
|
name = None |
||||
|
label = _("Partner cumul aged balance") |
||||
|
super().write_ending_balance_from_dict(my_object, name, label, report_data) |
||||
|
|
||||
|
def write_account_footer_from_dict( |
||||
|
self, |
||||
|
report, |
||||
|
account, |
||||
|
label, |
||||
|
field_name, |
||||
|
string_format, |
||||
|
amount_format, |
||||
|
amount_is_percent, |
||||
|
report_data, |
||||
|
): |
||||
|
""" |
||||
|
Specific function to write account footer for Aged Partner Balance |
||||
|
""" |
||||
|
col_pos_footer_label = self._get_col_pos_footer_label(report) |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
if col_pos == col_pos_footer_label or column.get(field_name): |
||||
|
if col_pos == col_pos_footer_label: |
||||
|
value = label |
||||
|
else: |
||||
|
value = account.get(column[field_name], False) |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "string" or col_pos == col_pos_footer_label: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], col_pos, value or "", string_format |
||||
|
) |
||||
|
elif cell_type == "amount": |
||||
|
number = float(value) |
||||
|
if amount_is_percent: |
||||
|
number /= 100 |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, number, amount_format |
||||
|
) |
||||
|
else: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], col_pos, "", string_format |
||||
|
) |
||||
|
|
||||
|
report_data["row_pos"] += 1 |
@ -0,0 +1,870 @@ |
|||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import calendar |
||||
|
import datetime |
||||
|
import operator |
||||
|
|
||||
|
from odoo import _, api, models |
||||
|
from odoo.tools import float_is_zero |
||||
|
|
||||
|
|
||||
|
class GeneralLedgerReport(models.AbstractModel): |
||||
|
_name = "report.account_financial_report.general_ledger" |
||||
|
_description = "General Ledger Report" |
||||
|
|
||||
|
def _get_accounts_data(self, account_ids): |
||||
|
accounts = self.env["account.account"].browse(account_ids) |
||||
|
accounts_data = {} |
||||
|
for account in accounts: |
||||
|
accounts_data.update( |
||||
|
{ |
||||
|
account.id: { |
||||
|
"id": account.id, |
||||
|
"code": account.code, |
||||
|
"name": account.name, |
||||
|
"group_id": account.group_id.id, |
||||
|
"currency_id": account.currency_id or False, |
||||
|
"currency_name": account.currency_id.name, |
||||
|
"centralized": account.centralized, |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
return accounts_data |
||||
|
|
||||
|
def _get_journals_data(self, journals_ids): |
||||
|
journals = self.env["account.journal"].browse(journals_ids) |
||||
|
journals_data = {} |
||||
|
for journal in journals: |
||||
|
journals_data.update({journal.id: {"id": journal.id, "code": journal.code}}) |
||||
|
return journals_data |
||||
|
|
||||
|
def _get_tags_data(self, tags_ids): |
||||
|
tags = self.env["account.analytic.tag"].browse(tags_ids) |
||||
|
tags_data = {} |
||||
|
for tag in tags: |
||||
|
tags_data.update({tag.id: {"name": tag.name}}) |
||||
|
return tags_data |
||||
|
|
||||
|
def _get_taxes_data(self, taxes_ids): |
||||
|
taxes = self.env["account.tax"].browse(taxes_ids) |
||||
|
taxes_data = {} |
||||
|
for tax in taxes: |
||||
|
taxes_data.update( |
||||
|
{ |
||||
|
tax.id: { |
||||
|
"id": tax.id, |
||||
|
"amount": tax.amount, |
||||
|
"amount_type": tax.amount_type, |
||||
|
"display_name": tax.display_name, |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
if tax.amount_type == "percent" or tax.amount_type == "division": |
||||
|
taxes_data[tax.id]["string"] = "%" |
||||
|
else: |
||||
|
taxes_data[tax.id]["string"] = "" |
||||
|
taxes_data[tax.id]["tax_name"] = ( |
||||
|
tax.display_name |
||||
|
+ " (" |
||||
|
+ str(tax.amount) |
||||
|
+ taxes_data[tax.id]["string"] |
||||
|
+ ")" |
||||
|
) |
||||
|
return taxes_data |
||||
|
|
||||
|
def _get_acc_prt_accounts_ids(self, company_id): |
||||
|
accounts_domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("internal_type", "in", ["receivable", "payable"]), |
||||
|
] |
||||
|
acc_prt_accounts = self.env["account.account"].search(accounts_domain) |
||||
|
return acc_prt_accounts.ids |
||||
|
|
||||
|
def _get_initial_balances_bs_ml_domain( |
||||
|
self, account_ids, company_id, date_from, base_domain, acc_prt=False |
||||
|
): |
||||
|
accounts_domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("user_type_id.include_initial_balance", "=", True), |
||||
|
] |
||||
|
if account_ids: |
||||
|
accounts_domain += [("id", "in", account_ids)] |
||||
|
domain = [] |
||||
|
domain += base_domain |
||||
|
domain += [("date", "<", date_from)] |
||||
|
accounts = self.env["account.account"].search(accounts_domain) |
||||
|
domain += [("account_id", "in", accounts.ids)] |
||||
|
if acc_prt: |
||||
|
domain += [("account_id.internal_type", "in", ["receivable", "payable"])] |
||||
|
return domain |
||||
|
|
||||
|
def _get_initial_balances_pl_ml_domain( |
||||
|
self, account_ids, company_id, date_from, fy_start_date, base_domain |
||||
|
): |
||||
|
accounts_domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("user_type_id.include_initial_balance", "=", False), |
||||
|
] |
||||
|
if account_ids: |
||||
|
accounts_domain += [("id", "in", account_ids)] |
||||
|
domain = [] |
||||
|
domain += base_domain |
||||
|
domain += [("date", "<", date_from), ("date", ">=", fy_start_date)] |
||||
|
accounts = self.env["account.account"].search(accounts_domain) |
||||
|
domain += [("account_id", "in", accounts.ids)] |
||||
|
return domain |
||||
|
|
||||
|
def _get_accounts_initial_balance(self, initial_domain_bs, initial_domain_pl): |
||||
|
gl_initial_acc_bs = self.env["account.move.line"].read_group( |
||||
|
domain=initial_domain_bs, |
||||
|
fields=["account_id", "debit", "credit", "balance", "amount_currency"], |
||||
|
groupby=["account_id"], |
||||
|
) |
||||
|
gl_initial_acc_pl = self.env["account.move.line"].read_group( |
||||
|
domain=initial_domain_pl, |
||||
|
fields=["account_id", "debit", "credit", "balance", "amount_currency"], |
||||
|
groupby=["account_id"], |
||||
|
) |
||||
|
gl_initial_acc = gl_initial_acc_bs + gl_initial_acc_pl |
||||
|
return gl_initial_acc |
||||
|
|
||||
|
def _get_initial_balance_fy_pl_ml_domain( |
||||
|
self, account_ids, company_id, fy_start_date, base_domain |
||||
|
): |
||||
|
accounts_domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("user_type_id.include_initial_balance", "=", False), |
||||
|
] |
||||
|
if account_ids: |
||||
|
accounts_domain += [("id", "in", account_ids)] |
||||
|
domain = [] |
||||
|
domain += base_domain |
||||
|
domain += [("date", "<", fy_start_date)] |
||||
|
accounts = self.env["account.account"].search(accounts_domain) |
||||
|
domain += [("account_id", "in", accounts.ids)] |
||||
|
return domain |
||||
|
|
||||
|
def _get_pl_initial_balance( |
||||
|
self, account_ids, company_id, fy_start_date, foreign_currency, base_domain |
||||
|
): |
||||
|
domain = self._get_initial_balance_fy_pl_ml_domain( |
||||
|
account_ids, company_id, fy_start_date, base_domain |
||||
|
) |
||||
|
initial_balances = self.env["account.move.line"].read_group( |
||||
|
domain=domain, |
||||
|
fields=["account_id", "debit", "credit", "balance", "amount_currency"], |
||||
|
groupby=["account_id"], |
||||
|
) |
||||
|
pl_initial_balance = { |
||||
|
"debit": 0.0, |
||||
|
"credit": 0.0, |
||||
|
"balance": 0.0, |
||||
|
"bal_curr": 0.0, |
||||
|
} |
||||
|
for initial_balance in initial_balances: |
||||
|
pl_initial_balance["debit"] += initial_balance["debit"] |
||||
|
pl_initial_balance["credit"] += initial_balance["credit"] |
||||
|
pl_initial_balance["balance"] += initial_balance["balance"] |
||||
|
pl_initial_balance["bal_curr"] += initial_balance["amount_currency"] |
||||
|
return pl_initial_balance |
||||
|
|
||||
|
def _get_initial_balance_data( |
||||
|
self, |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_from, |
||||
|
foreign_currency, |
||||
|
only_posted_moves, |
||||
|
unaffected_earnings_account, |
||||
|
fy_start_date, |
||||
|
analytic_tag_ids, |
||||
|
cost_center_ids, |
||||
|
extra_domain, |
||||
|
): |
||||
|
base_domain = [] |
||||
|
if company_id: |
||||
|
base_domain += [("company_id", "=", company_id)] |
||||
|
if partner_ids: |
||||
|
base_domain += [("partner_id", "in", partner_ids)] |
||||
|
if only_posted_moves: |
||||
|
base_domain += [("move_id.state", "=", "posted")] |
||||
|
if analytic_tag_ids: |
||||
|
base_domain += [("analytic_tag_ids", "in", analytic_tag_ids)] |
||||
|
if cost_center_ids: |
||||
|
base_domain += [("analytic_account_id", "in", cost_center_ids)] |
||||
|
if extra_domain: |
||||
|
base_domain += extra_domain |
||||
|
initial_domain_bs = self._get_initial_balances_bs_ml_domain( |
||||
|
account_ids, company_id, date_from, base_domain |
||||
|
) |
||||
|
initial_domain_pl = self._get_initial_balances_pl_ml_domain( |
||||
|
account_ids, company_id, date_from, fy_start_date, base_domain |
||||
|
) |
||||
|
gl_initial_acc = self._get_accounts_initial_balance( |
||||
|
initial_domain_bs, initial_domain_pl |
||||
|
) |
||||
|
initial_domain_acc_prt = self._get_initial_balances_bs_ml_domain( |
||||
|
account_ids, company_id, date_from, base_domain, acc_prt=True |
||||
|
) |
||||
|
gl_initial_acc_prt = self.env["account.move.line"].read_group( |
||||
|
domain=initial_domain_acc_prt, |
||||
|
fields=[ |
||||
|
"account_id", |
||||
|
"partner_id", |
||||
|
"debit", |
||||
|
"credit", |
||||
|
"balance", |
||||
|
"amount_currency", |
||||
|
], |
||||
|
groupby=["account_id", "partner_id"], |
||||
|
lazy=False, |
||||
|
) |
||||
|
gen_ld_data = {} |
||||
|
for gl in gl_initial_acc: |
||||
|
acc_id = gl["account_id"][0] |
||||
|
gen_ld_data[acc_id] = {} |
||||
|
gen_ld_data[acc_id]["id"] = acc_id |
||||
|
gen_ld_data[acc_id]["partners"] = False |
||||
|
gen_ld_data[acc_id]["init_bal"] = {} |
||||
|
gen_ld_data[acc_id]["init_bal"]["credit"] = gl["credit"] |
||||
|
gen_ld_data[acc_id]["init_bal"]["debit"] = gl["debit"] |
||||
|
gen_ld_data[acc_id]["init_bal"]["balance"] = gl["balance"] |
||||
|
gen_ld_data[acc_id]["fin_bal"] = {} |
||||
|
gen_ld_data[acc_id]["fin_bal"]["credit"] = gl["credit"] |
||||
|
gen_ld_data[acc_id]["fin_bal"]["debit"] = gl["debit"] |
||||
|
gen_ld_data[acc_id]["fin_bal"]["balance"] = gl["balance"] |
||||
|
gen_ld_data[acc_id]["init_bal"]["bal_curr"] = gl["amount_currency"] |
||||
|
gen_ld_data[acc_id]["fin_bal"]["bal_curr"] = gl["amount_currency"] |
||||
|
partners_data = {} |
||||
|
partners_ids = set() |
||||
|
if gl_initial_acc_prt: |
||||
|
for gl in gl_initial_acc_prt: |
||||
|
if not gl["partner_id"]: |
||||
|
prt_id = 0 |
||||
|
prt_name = "Missing Partner" |
||||
|
else: |
||||
|
prt_id = gl["partner_id"][0] |
||||
|
prt_name = gl["partner_id"][1] |
||||
|
prt_name = prt_name._value |
||||
|
if prt_id not in partners_ids: |
||||
|
partners_ids.add(prt_id) |
||||
|
partners_data.update({prt_id: {"id": prt_id, "name": prt_name}}) |
||||
|
acc_id = gl["account_id"][0] |
||||
|
gen_ld_data[acc_id][prt_id] = {} |
||||
|
gen_ld_data[acc_id][prt_id]["id"] = prt_id |
||||
|
gen_ld_data[acc_id]["partners"] = True |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"] = {} |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"]["credit"] = gl["credit"] |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"]["debit"] = gl["debit"] |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"]["balance"] = gl["balance"] |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"] = {} |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["credit"] = gl["credit"] |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["debit"] = gl["debit"] |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["balance"] = gl["balance"] |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"]["bal_curr"] = gl[ |
||||
|
"amount_currency" |
||||
|
] |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["bal_curr"] = gl[ |
||||
|
"amount_currency" |
||||
|
] |
||||
|
accounts_ids = list(gen_ld_data.keys()) |
||||
|
unaffected_id = unaffected_earnings_account |
||||
|
if unaffected_id not in accounts_ids: |
||||
|
accounts_ids.append(unaffected_id) |
||||
|
self._initialize_account(gen_ld_data, unaffected_id, foreign_currency) |
||||
|
pl_initial_balance = self._get_pl_initial_balance( |
||||
|
account_ids, company_id, fy_start_date, foreign_currency, base_domain |
||||
|
) |
||||
|
gen_ld_data[unaffected_id]["init_bal"]["debit"] += pl_initial_balance["debit"] |
||||
|
gen_ld_data[unaffected_id]["init_bal"]["credit"] += pl_initial_balance["credit"] |
||||
|
gen_ld_data[unaffected_id]["init_bal"]["balance"] += pl_initial_balance[ |
||||
|
"balance" |
||||
|
] |
||||
|
gen_ld_data[unaffected_id]["fin_bal"]["debit"] += pl_initial_balance["debit"] |
||||
|
gen_ld_data[unaffected_id]["fin_bal"]["credit"] += pl_initial_balance["credit"] |
||||
|
gen_ld_data[unaffected_id]["fin_bal"]["balance"] += pl_initial_balance[ |
||||
|
"balance" |
||||
|
] |
||||
|
if foreign_currency: |
||||
|
gen_ld_data[unaffected_id]["init_bal"]["bal_curr"] += pl_initial_balance[ |
||||
|
"bal_curr" |
||||
|
] |
||||
|
gen_ld_data[unaffected_id]["fin_bal"]["bal_curr"] += pl_initial_balance[ |
||||
|
"bal_curr" |
||||
|
] |
||||
|
return gen_ld_data, partners_data, partner_ids |
||||
|
|
||||
|
@api.model |
||||
|
def _get_move_line_data(self, move_line): |
||||
|
move_line_data = { |
||||
|
"id": move_line["id"], |
||||
|
"date": move_line["date"], |
||||
|
"entry": move_line["move_id"][1], |
||||
|
"entry_id": move_line["move_id"][0], |
||||
|
"journal_id": move_line["journal_id"][0], |
||||
|
"account_id": move_line["account_id"][0], |
||||
|
"partner_id": move_line["partner_id"][0] |
||||
|
if move_line["partner_id"] |
||||
|
else False, |
||||
|
"partner_name": move_line["partner_id"][1] |
||||
|
if move_line["partner_id"] |
||||
|
else "", |
||||
|
"ref": "" if not move_line["ref"] else move_line["ref"], |
||||
|
"name": "" if not move_line["name"] else move_line["name"], |
||||
|
"tax_ids": move_line["tax_ids"], |
||||
|
"debit": move_line["debit"], |
||||
|
"credit": move_line["credit"], |
||||
|
"balance": move_line["balance"], |
||||
|
"bal_curr": move_line["amount_currency"], |
||||
|
"rec_id": move_line["full_reconcile_id"][0] |
||||
|
if move_line["full_reconcile_id"] |
||||
|
else False, |
||||
|
"rec_name": move_line["full_reconcile_id"][1] |
||||
|
if move_line["full_reconcile_id"] |
||||
|
else "", |
||||
|
"tag_ids": move_line["analytic_tag_ids"], |
||||
|
"currency_id": move_line["currency_id"], |
||||
|
"analytic_account": move_line["analytic_account_id"][1] |
||||
|
if move_line["analytic_account_id"] |
||||
|
else "", |
||||
|
"analytic_account_id": move_line["analytic_account_id"][0] |
||||
|
if move_line["analytic_account_id"] |
||||
|
else False, |
||||
|
} |
||||
|
if ( |
||||
|
move_line_data["ref"] == move_line_data["name"] |
||||
|
or move_line_data["ref"] == "" |
||||
|
): |
||||
|
ref_label = move_line_data["name"] |
||||
|
elif move_line_data["name"] == "": |
||||
|
ref_label = move_line_data["ref"] |
||||
|
else: |
||||
|
ref_label = move_line_data["ref"] + str(" - ") + move_line_data["name"] |
||||
|
move_line_data.update({"ref_label": ref_label}) |
||||
|
return move_line_data |
||||
|
|
||||
|
@api.model |
||||
|
def _get_period_domain( |
||||
|
self, |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
only_posted_moves, |
||||
|
date_to, |
||||
|
date_from, |
||||
|
analytic_tag_ids, |
||||
|
cost_center_ids, |
||||
|
): |
||||
|
domain = [ |
||||
|
("display_type", "=", False), |
||||
|
("date", ">=", date_from), |
||||
|
("date", "<=", date_to), |
||||
|
] |
||||
|
if account_ids: |
||||
|
domain += [("account_id", "in", account_ids)] |
||||
|
if company_id: |
||||
|
domain += [("company_id", "=", company_id)] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
if analytic_tag_ids: |
||||
|
domain += [("analytic_tag_ids", "in", analytic_tag_ids)] |
||||
|
if cost_center_ids: |
||||
|
domain += [("analytic_account_id", "in", cost_center_ids)] |
||||
|
return domain |
||||
|
|
||||
|
@api.model |
||||
|
def _initialize_partner(self, gen_ld_data, acc_id, prt_id, foreign_currency): |
||||
|
gen_ld_data[acc_id]["partners"] = True |
||||
|
gen_ld_data[acc_id][prt_id] = {} |
||||
|
gen_ld_data[acc_id][prt_id]["id"] = prt_id |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"] = {} |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"]["balance"] = 0.0 |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"]["credit"] = 0.0 |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"]["debit"] = 0.0 |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"] = {} |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["credit"] = 0.0 |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["debit"] = 0.0 |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["balance"] = 0.0 |
||||
|
if foreign_currency: |
||||
|
gen_ld_data[acc_id][prt_id]["init_bal"]["bal_curr"] = 0.0 |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["bal_curr"] = 0.0 |
||||
|
return gen_ld_data |
||||
|
|
||||
|
def _initialize_account(self, gen_ld_data, acc_id, foreign_currency): |
||||
|
gen_ld_data[acc_id] = {} |
||||
|
gen_ld_data[acc_id]["id"] = acc_id |
||||
|
gen_ld_data[acc_id]["partners"] = False |
||||
|
gen_ld_data[acc_id]["init_bal"] = {} |
||||
|
gen_ld_data[acc_id]["init_bal"]["balance"] = 0.0 |
||||
|
gen_ld_data[acc_id]["init_bal"]["credit"] = 0.0 |
||||
|
gen_ld_data[acc_id]["init_bal"]["debit"] = 0.0 |
||||
|
gen_ld_data[acc_id]["fin_bal"] = {} |
||||
|
gen_ld_data[acc_id]["fin_bal"]["credit"] = 0.0 |
||||
|
gen_ld_data[acc_id]["fin_bal"]["debit"] = 0.0 |
||||
|
gen_ld_data[acc_id]["fin_bal"]["balance"] = 0.0 |
||||
|
if foreign_currency: |
||||
|
gen_ld_data[acc_id]["init_bal"]["bal_curr"] = 0.0 |
||||
|
gen_ld_data[acc_id]["fin_bal"]["bal_curr"] = 0.0 |
||||
|
return gen_ld_data |
||||
|
|
||||
|
def _get_reconciled_after_date_to_ids(self, full_reconcile_ids, date_to): |
||||
|
full_reconcile_ids = list(full_reconcile_ids) |
||||
|
domain = [ |
||||
|
("max_date", ">", date_to), |
||||
|
("full_reconcile_id", "in", full_reconcile_ids), |
||||
|
] |
||||
|
fields = ["full_reconcile_id"] |
||||
|
reconciled_after_date_to = self.env["account.partial.reconcile"].search_read( |
||||
|
domain=domain, fields=fields |
||||
|
) |
||||
|
rec_after_date_to_ids = list( |
||||
|
map(operator.itemgetter("full_reconcile_id"), reconciled_after_date_to) |
||||
|
) |
||||
|
rec_after_date_to_ids = [i[0] for i in rec_after_date_to_ids] |
||||
|
return rec_after_date_to_ids |
||||
|
|
||||
|
def _get_period_ml_data( |
||||
|
self, |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
foreign_currency, |
||||
|
only_posted_moves, |
||||
|
date_from, |
||||
|
date_to, |
||||
|
partners_data, |
||||
|
gen_ld_data, |
||||
|
partners_ids, |
||||
|
analytic_tag_ids, |
||||
|
cost_center_ids, |
||||
|
extra_domain, |
||||
|
): |
||||
|
domain = self._get_period_domain( |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
only_posted_moves, |
||||
|
date_to, |
||||
|
date_from, |
||||
|
analytic_tag_ids, |
||||
|
cost_center_ids, |
||||
|
) |
||||
|
if extra_domain: |
||||
|
domain += extra_domain |
||||
|
ml_fields = [ |
||||
|
"id", |
||||
|
"name", |
||||
|
"date", |
||||
|
"move_id", |
||||
|
"journal_id", |
||||
|
"account_id", |
||||
|
"partner_id", |
||||
|
"debit", |
||||
|
"credit", |
||||
|
"balance", |
||||
|
"currency_id", |
||||
|
"full_reconcile_id", |
||||
|
"tax_ids", |
||||
|
"analytic_tag_ids", |
||||
|
"amount_currency", |
||||
|
"ref", |
||||
|
"name", |
||||
|
"analytic_account_id", |
||||
|
] |
||||
|
move_lines = self.env["account.move.line"].search_read( |
||||
|
domain=domain, fields=ml_fields |
||||
|
) |
||||
|
journal_ids = set() |
||||
|
full_reconcile_ids = set() |
||||
|
taxes_ids = set() |
||||
|
tags_ids = set() |
||||
|
full_reconcile_data = {} |
||||
|
acc_prt_account_ids = self._get_acc_prt_accounts_ids(company_id) |
||||
|
for move_line in move_lines: |
||||
|
journal_ids.add(move_line["journal_id"][0]) |
||||
|
for tax_id in move_line["tax_ids"]: |
||||
|
taxes_ids.add(tax_id) |
||||
|
for analytic_tag_id in move_line["analytic_tag_ids"]: |
||||
|
tags_ids.add(analytic_tag_id) |
||||
|
if move_line["full_reconcile_id"]: |
||||
|
rec_id = move_line["full_reconcile_id"][0] |
||||
|
if rec_id not in full_reconcile_ids: |
||||
|
full_reconcile_data.update( |
||||
|
{ |
||||
|
rec_id: { |
||||
|
"id": rec_id, |
||||
|
"name": move_line["full_reconcile_id"][1], |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
full_reconcile_ids.add(rec_id) |
||||
|
acc_id = move_line["account_id"][0] |
||||
|
ml_id = move_line["id"] |
||||
|
if move_line["partner_id"]: |
||||
|
prt_id = move_line["partner_id"][0] |
||||
|
partner_name = move_line["partner_id"][1] |
||||
|
if acc_id not in gen_ld_data.keys(): |
||||
|
gen_ld_data = self._initialize_account( |
||||
|
gen_ld_data, acc_id, foreign_currency |
||||
|
) |
||||
|
if acc_id in acc_prt_account_ids: |
||||
|
if not move_line["partner_id"]: |
||||
|
prt_id = 0 |
||||
|
partner_name = "Missing Partner" |
||||
|
partners_ids.append(prt_id) |
||||
|
partners_data.update({prt_id: {"id": prt_id, "name": partner_name}}) |
||||
|
if prt_id not in gen_ld_data[acc_id]: |
||||
|
gen_ld_data = self._initialize_partner( |
||||
|
gen_ld_data, acc_id, prt_id, foreign_currency |
||||
|
) |
||||
|
gen_ld_data[acc_id][prt_id][ml_id] = self._get_move_line_data(move_line) |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["credit"] += move_line["credit"] |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["debit"] += move_line["debit"] |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["balance"] += move_line[ |
||||
|
"balance" |
||||
|
] |
||||
|
if foreign_currency: |
||||
|
gen_ld_data[acc_id][prt_id]["fin_bal"]["bal_curr"] += move_line[ |
||||
|
"amount_currency" |
||||
|
] |
||||
|
else: |
||||
|
gen_ld_data[acc_id][ml_id] = self._get_move_line_data(move_line) |
||||
|
gen_ld_data[acc_id]["fin_bal"]["credit"] += move_line["credit"] |
||||
|
gen_ld_data[acc_id]["fin_bal"]["debit"] += move_line["debit"] |
||||
|
gen_ld_data[acc_id]["fin_bal"]["balance"] += move_line["balance"] |
||||
|
if foreign_currency: |
||||
|
gen_ld_data[acc_id]["fin_bal"]["bal_curr"] += move_line[ |
||||
|
"amount_currency" |
||||
|
] |
||||
|
journals_data = self._get_journals_data(list(journal_ids)) |
||||
|
accounts_data = self._get_accounts_data(gen_ld_data.keys()) |
||||
|
taxes_data = self._get_taxes_data(list(taxes_ids)) |
||||
|
tags_data = self._get_tags_data(list(tags_ids)) |
||||
|
rec_after_date_to_ids = self._get_reconciled_after_date_to_ids( |
||||
|
full_reconcile_data.keys(), date_to |
||||
|
) |
||||
|
return ( |
||||
|
gen_ld_data, |
||||
|
accounts_data, |
||||
|
partners_data, |
||||
|
journals_data, |
||||
|
full_reconcile_data, |
||||
|
taxes_data, |
||||
|
tags_data, |
||||
|
rec_after_date_to_ids, |
||||
|
) |
||||
|
|
||||
|
@api.model |
||||
|
def _recalculate_cumul_balance( |
||||
|
self, move_lines, last_cumul_balance, rec_after_date_to_ids |
||||
|
): |
||||
|
for move_line in move_lines: |
||||
|
move_line["balance"] += last_cumul_balance |
||||
|
last_cumul_balance = move_line["balance"] |
||||
|
if move_line["rec_id"] in rec_after_date_to_ids: |
||||
|
move_line["rec_name"] = "(" + _("future") + ") " + move_line["rec_name"] |
||||
|
return move_lines |
||||
|
|
||||
|
def _create_account(self, account, acc_id, gen_led_data, rec_after_date_to_ids): |
||||
|
move_lines = [] |
||||
|
for ml_id in gen_led_data[acc_id].keys(): |
||||
|
if not isinstance(ml_id, int): |
||||
|
account.update({ml_id: gen_led_data[acc_id][ml_id]}) |
||||
|
else: |
||||
|
move_lines += [gen_led_data[acc_id][ml_id]] |
||||
|
move_lines = sorted(move_lines, key=lambda k: (k["date"])) |
||||
|
move_lines = self._recalculate_cumul_balance( |
||||
|
move_lines, |
||||
|
gen_led_data[acc_id]["init_bal"]["balance"], |
||||
|
rec_after_date_to_ids, |
||||
|
) |
||||
|
account.update({"move_lines": move_lines}) |
||||
|
return account |
||||
|
|
||||
|
def _create_account_not_show_partner( |
||||
|
self, account, acc_id, gen_led_data, rec_after_date_to_ids |
||||
|
): |
||||
|
move_lines = [] |
||||
|
for prt_id in gen_led_data[acc_id].keys(): |
||||
|
if not isinstance(prt_id, int): |
||||
|
account.update({prt_id: gen_led_data[acc_id][prt_id]}) |
||||
|
else: |
||||
|
for ml_id in gen_led_data[acc_id][prt_id].keys(): |
||||
|
if isinstance(ml_id, int): |
||||
|
move_lines += [gen_led_data[acc_id][prt_id][ml_id]] |
||||
|
move_lines = sorted(move_lines, key=lambda k: (k["date"])) |
||||
|
move_lines = self._recalculate_cumul_balance( |
||||
|
move_lines, |
||||
|
gen_led_data[acc_id]["init_bal"]["balance"], |
||||
|
rec_after_date_to_ids, |
||||
|
) |
||||
|
account.update({"move_lines": move_lines, "partners": False}) |
||||
|
return account |
||||
|
|
||||
|
def _create_general_ledger( |
||||
|
self, |
||||
|
gen_led_data, |
||||
|
accounts_data, |
||||
|
show_partner_details, |
||||
|
rec_after_date_to_ids, |
||||
|
hide_account_at_0, |
||||
|
): |
||||
|
general_ledger = [] |
||||
|
rounding = self.env.user.company_id.currency_id.rounding |
||||
|
for acc_id in gen_led_data.keys(): |
||||
|
account = {} |
||||
|
account.update( |
||||
|
{ |
||||
|
"code": accounts_data[acc_id]["code"], |
||||
|
"name": accounts_data[acc_id]["name"], |
||||
|
"type": "account", |
||||
|
"currency_id": accounts_data[acc_id]["currency_id"], |
||||
|
"centralized": accounts_data[acc_id]["centralized"], |
||||
|
} |
||||
|
) |
||||
|
if not gen_led_data[acc_id]["partners"]: |
||||
|
account = self._create_account( |
||||
|
account, acc_id, gen_led_data, rec_after_date_to_ids |
||||
|
) |
||||
|
if ( |
||||
|
hide_account_at_0 |
||||
|
and float_is_zero( |
||||
|
gen_led_data[acc_id]["init_bal"]["balance"], |
||||
|
precision_rounding=rounding, |
||||
|
) |
||||
|
and account["move_lines"] == [] |
||||
|
): |
||||
|
continue |
||||
|
else: |
||||
|
if show_partner_details: |
||||
|
list_partner = [] |
||||
|
for prt_id in gen_led_data[acc_id].keys(): |
||||
|
partner = {} |
||||
|
move_lines = [] |
||||
|
if not isinstance(prt_id, int): |
||||
|
account.update({prt_id: gen_led_data[acc_id][prt_id]}) |
||||
|
else: |
||||
|
for ml_id in gen_led_data[acc_id][prt_id].keys(): |
||||
|
if not isinstance(ml_id, int): |
||||
|
partner.update( |
||||
|
{ml_id: gen_led_data[acc_id][prt_id][ml_id]} |
||||
|
) |
||||
|
else: |
||||
|
move_lines += [gen_led_data[acc_id][prt_id][ml_id]] |
||||
|
move_lines = sorted(move_lines, key=lambda k: (k["date"])) |
||||
|
move_lines = self._recalculate_cumul_balance( |
||||
|
move_lines, |
||||
|
gen_led_data[acc_id][prt_id]["init_bal"]["balance"], |
||||
|
rec_after_date_to_ids, |
||||
|
) |
||||
|
partner.update({"move_lines": move_lines}) |
||||
|
if ( |
||||
|
hide_account_at_0 |
||||
|
and float_is_zero( |
||||
|
gen_led_data[acc_id][prt_id]["init_bal"]["balance"], |
||||
|
precision_rounding=rounding, |
||||
|
) |
||||
|
and partner["move_lines"] == [] |
||||
|
): |
||||
|
continue |
||||
|
list_partner += [partner] |
||||
|
account.update({"list_partner": list_partner}) |
||||
|
if ( |
||||
|
hide_account_at_0 |
||||
|
and float_is_zero( |
||||
|
gen_led_data[acc_id]["init_bal"]["balance"], |
||||
|
precision_rounding=rounding, |
||||
|
) |
||||
|
and account["list_partner"] == [] |
||||
|
): |
||||
|
continue |
||||
|
else: |
||||
|
account = self._create_account_not_show_partner( |
||||
|
account, acc_id, gen_led_data, rec_after_date_to_ids |
||||
|
) |
||||
|
if ( |
||||
|
hide_account_at_0 |
||||
|
and float_is_zero( |
||||
|
gen_led_data[acc_id]["init_bal"]["balance"], |
||||
|
precision_rounding=rounding, |
||||
|
) |
||||
|
and account["move_lines"] == [] |
||||
|
): |
||||
|
continue |
||||
|
general_ledger += [account] |
||||
|
return general_ledger |
||||
|
|
||||
|
@api.model |
||||
|
def _calculate_centralization(self, centralized_ml, move_line, date_to): |
||||
|
jnl_id = move_line["journal_id"] |
||||
|
month = move_line["date"].month |
||||
|
if jnl_id not in centralized_ml.keys(): |
||||
|
centralized_ml[jnl_id] = {} |
||||
|
if month not in centralized_ml[jnl_id].keys(): |
||||
|
centralized_ml[jnl_id][month] = {} |
||||
|
last_day_month = calendar.monthrange(move_line["date"].year, month) |
||||
|
date = datetime.date(move_line["date"].year, month, last_day_month[1]) |
||||
|
if date > date_to: |
||||
|
date = date_to |
||||
|
centralized_ml[jnl_id][month].update( |
||||
|
{ |
||||
|
"journal_id": jnl_id, |
||||
|
"ref_label": "Centralized entries", |
||||
|
"date": date, |
||||
|
"debit": 0.0, |
||||
|
"credit": 0.0, |
||||
|
"balance": 0.0, |
||||
|
"bal_curr": 0.0, |
||||
|
"partner_id": False, |
||||
|
"rec_id": 0, |
||||
|
"entry_id": False, |
||||
|
"tax_ids": [], |
||||
|
"full_reconcile_id": False, |
||||
|
"id": False, |
||||
|
"tag_ids": False, |
||||
|
"currency_id": False, |
||||
|
"analytic_account_id": False, |
||||
|
} |
||||
|
) |
||||
|
centralized_ml[jnl_id][month]["debit"] += move_line["debit"] |
||||
|
centralized_ml[jnl_id][month]["credit"] += move_line["credit"] |
||||
|
centralized_ml[jnl_id][month]["balance"] += ( |
||||
|
move_line["debit"] - move_line["credit"] |
||||
|
) |
||||
|
centralized_ml[jnl_id][month]["bal_curr"] += move_line["bal_curr"] |
||||
|
return centralized_ml |
||||
|
|
||||
|
@api.model |
||||
|
def _get_centralized_ml(self, account, date_to): |
||||
|
centralized_ml = {} |
||||
|
if isinstance(date_to, str): |
||||
|
date_to = datetime.datetime.strptime(date_to, "%Y-%m-%d").date() |
||||
|
if account["partners"]: |
||||
|
for partner in account["list_partner"]: |
||||
|
for move_line in partner["move_lines"]: |
||||
|
centralized_ml = self._calculate_centralization( |
||||
|
centralized_ml, |
||||
|
move_line, |
||||
|
date_to, |
||||
|
) |
||||
|
else: |
||||
|
for move_line in account["move_lines"]: |
||||
|
centralized_ml = self._calculate_centralization( |
||||
|
centralized_ml, |
||||
|
move_line, |
||||
|
date_to, |
||||
|
) |
||||
|
list_centralized_ml = [] |
||||
|
for jnl_id in centralized_ml.keys(): |
||||
|
list_centralized_ml += list(centralized_ml[jnl_id].values()) |
||||
|
return list_centralized_ml |
||||
|
|
||||
|
def _get_report_values(self, docids, data): |
||||
|
wizard_id = data["wizard_id"] |
||||
|
company = self.env["res.company"].browse(data["company_id"]) |
||||
|
company_id = data["company_id"] |
||||
|
date_to = data["date_to"] |
||||
|
date_from = data["date_from"] |
||||
|
partner_ids = data["partner_ids"] |
||||
|
if not partner_ids: |
||||
|
filter_partner_ids = False |
||||
|
else: |
||||
|
filter_partner_ids = True |
||||
|
account_ids = data["account_ids"] |
||||
|
analytic_tag_ids = data["analytic_tag_ids"] |
||||
|
cost_center_ids = data["cost_center_ids"] |
||||
|
show_partner_details = data["show_partner_details"] |
||||
|
hide_account_at_0 = data["hide_account_at_0"] |
||||
|
foreign_currency = data["foreign_currency"] |
||||
|
only_posted_moves = data["only_posted_moves"] |
||||
|
unaffected_earnings_account = data["unaffected_earnings_account"] |
||||
|
fy_start_date = data["fy_start_date"] |
||||
|
extra_domain = data["domain"] |
||||
|
gen_ld_data, partners_data, partners_ids = self._get_initial_balance_data( |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_from, |
||||
|
foreign_currency, |
||||
|
only_posted_moves, |
||||
|
unaffected_earnings_account, |
||||
|
fy_start_date, |
||||
|
analytic_tag_ids, |
||||
|
cost_center_ids, |
||||
|
extra_domain, |
||||
|
) |
||||
|
centralize = data["centralize"] |
||||
|
( |
||||
|
gen_ld_data, |
||||
|
accounts_data, |
||||
|
partners_data, |
||||
|
journals_data, |
||||
|
full_reconcile_data, |
||||
|
taxes_data, |
||||
|
tags_data, |
||||
|
rec_after_date_to_ids, |
||||
|
) = self._get_period_ml_data( |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
foreign_currency, |
||||
|
only_posted_moves, |
||||
|
date_from, |
||||
|
date_to, |
||||
|
partners_data, |
||||
|
gen_ld_data, |
||||
|
partners_ids, |
||||
|
analytic_tag_ids, |
||||
|
cost_center_ids, |
||||
|
extra_domain, |
||||
|
) |
||||
|
general_ledger = self._create_general_ledger( |
||||
|
gen_ld_data, |
||||
|
accounts_data, |
||||
|
show_partner_details, |
||||
|
rec_after_date_to_ids, |
||||
|
hide_account_at_0, |
||||
|
) |
||||
|
if centralize: |
||||
|
for account in general_ledger: |
||||
|
if account["centralized"]: |
||||
|
centralized_ml = self._get_centralized_ml(account, date_to) |
||||
|
account["move_lines"] = centralized_ml |
||||
|
account["move_lines"] = self._recalculate_cumul_balance( |
||||
|
account["move_lines"], |
||||
|
gen_ld_data[account["id"]]["init_bal"]["balance"], |
||||
|
rec_after_date_to_ids, |
||||
|
) |
||||
|
if account["partners"]: |
||||
|
account["partners"] = False |
||||
|
del account["list_partner"] |
||||
|
general_ledger = sorted(general_ledger, key=lambda k: k["code"]) |
||||
|
return { |
||||
|
"doc_ids": [wizard_id], |
||||
|
"doc_model": "general.ledger.report.wizard", |
||||
|
"docs": self.env["general.ledger.report.wizard"].browse(wizard_id), |
||||
|
"foreign_currency": data["foreign_currency"], |
||||
|
"company_name": company.display_name, |
||||
|
"company_currency": company.currency_id, |
||||
|
"currency_name": company.currency_id.name, |
||||
|
"date_from": data["date_from"], |
||||
|
"date_to": data["date_to"], |
||||
|
"only_posted_moves": data["only_posted_moves"], |
||||
|
"hide_account_at_0": data["hide_account_at_0"], |
||||
|
"show_analytic_tags": data["show_analytic_tags"], |
||||
|
"show_cost_center": data["show_cost_center"], |
||||
|
"general_ledger": general_ledger, |
||||
|
"accounts_data": accounts_data, |
||||
|
"partners_data": partners_data, |
||||
|
"journals_data": journals_data, |
||||
|
"full_reconcile_data": full_reconcile_data, |
||||
|
"taxes_data": taxes_data, |
||||
|
"centralize": centralize, |
||||
|
"tags_data": tags_data, |
||||
|
"filter_partner_ids": filter_partner_ids, |
||||
|
} |
@ -0,0 +1,346 @@ |
|||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2021 Tecnativa - João Marques |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import _, models |
||||
|
|
||||
|
|
||||
|
class GeneralLedgerXslx(models.AbstractModel): |
||||
|
_name = "report.a_f_r.report_general_ledger_xlsx" |
||||
|
_description = "General Ledger XLSL Report" |
||||
|
_inherit = "report.account_financial_report.abstract_report_xlsx" |
||||
|
|
||||
|
def _get_report_name(self, report, data=False): |
||||
|
company_id = data.get("company_id", False) |
||||
|
report_name = _("General Ledger") |
||||
|
if company_id: |
||||
|
company = self.env["res.company"].browse(company_id) |
||||
|
suffix = " - {} - {}".format(company.name, company.currency_id.name) |
||||
|
report_name = report_name + suffix |
||||
|
return report_name |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
res = [ |
||||
|
{"header": _("Date"), "field": "date", "width": 11}, |
||||
|
{"header": _("Entry"), "field": "entry", "width": 18}, |
||||
|
{"header": _("Journal"), "field": "journal", "width": 8}, |
||||
|
{"header": _("Account"), "field": "account", "width": 9}, |
||||
|
{"header": _("Taxes"), "field": "taxes_description", "width": 15}, |
||||
|
{"header": _("Partner"), "field": "partner_name", "width": 25}, |
||||
|
{"header": _("Ref - Label"), "field": "ref_label", "width": 40}, |
||||
|
] |
||||
|
if report.show_cost_center: |
||||
|
res += [ |
||||
|
{ |
||||
|
"header": _("Analytic Account"), |
||||
|
"field": "analytic_account", |
||||
|
"width": 20, |
||||
|
}, |
||||
|
] |
||||
|
if report.show_analytic_tags: |
||||
|
res += [ |
||||
|
{"header": _("Tags"), "field": "tags", "width": 10}, |
||||
|
] |
||||
|
res += [ |
||||
|
{"header": _("Rec."), "field": "rec_name", "width": 15}, |
||||
|
{ |
||||
|
"header": _("Debit"), |
||||
|
"field": "debit", |
||||
|
"field_initial_balance": "initial_debit", |
||||
|
"field_final_balance": "final_debit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
{ |
||||
|
"header": _("Credit"), |
||||
|
"field": "credit", |
||||
|
"field_initial_balance": "initial_credit", |
||||
|
"field_final_balance": "final_credit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
{ |
||||
|
"header": _("Cumul. Bal."), |
||||
|
"field": "balance", |
||||
|
"field_initial_balance": "initial_balance", |
||||
|
"field_final_balance": "final_balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
] |
||||
|
if report.foreign_currency: |
||||
|
res += [ |
||||
|
{ |
||||
|
"header": _("Cur."), |
||||
|
"field": "currency_name", |
||||
|
"field_currency_balance": "currency_name", |
||||
|
"type": "currency_name", |
||||
|
"width": 7, |
||||
|
}, |
||||
|
{ |
||||
|
"header": _("Amount cur."), |
||||
|
"field": "bal_curr", |
||||
|
"field_initial_balance": "initial_bal_curr", |
||||
|
"field_final_balance": "final_bal_curr", |
||||
|
"type": "amount_currency", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
] |
||||
|
res_as_dict = {} |
||||
|
for i, column in enumerate(res): |
||||
|
res_as_dict[i] = column |
||||
|
return res_as_dict |
||||
|
|
||||
|
def _get_report_filters(self, report): |
||||
|
return [ |
||||
|
[ |
||||
|
_("Date range filter"), |
||||
|
_("From: %s To: %s") % (report.date_from, report.date_to), |
||||
|
], |
||||
|
[ |
||||
|
_("Target moves filter"), |
||||
|
_("All posted entries") |
||||
|
if report.target_move == "posted" |
||||
|
else _("All entries"), |
||||
|
], |
||||
|
[ |
||||
|
_("Account balance at 0 filter"), |
||||
|
_("Hide") if report.hide_account_at_0 else _("Show"), |
||||
|
], |
||||
|
[_("Centralize filter"), _("Yes") if report.centralize else _("No")], |
||||
|
[ |
||||
|
_("Show analytic tags"), |
||||
|
_("Yes") if report.show_analytic_tags else _("No"), |
||||
|
], |
||||
|
[ |
||||
|
_("Show foreign currency"), |
||||
|
_("Yes") if report.foreign_currency else _("No"), |
||||
|
], |
||||
|
] |
||||
|
|
||||
|
def _get_col_count_filter_name(self): |
||||
|
return 2 |
||||
|
|
||||
|
def _get_col_count_filter_value(self): |
||||
|
return 2 |
||||
|
|
||||
|
def _get_col_pos_initial_balance_label(self): |
||||
|
return 5 |
||||
|
|
||||
|
def _get_col_count_final_balance_name(self): |
||||
|
return 5 |
||||
|
|
||||
|
def _get_col_pos_final_balance_label(self): |
||||
|
return 5 |
||||
|
|
||||
|
# flake8: noqa: C901 |
||||
|
def _generate_report_content(self, workbook, report, data, report_data): |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.general_ledger" |
||||
|
]._get_report_values(report, data) |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
accounts_data = res_data["accounts_data"] |
||||
|
partners_data = res_data["partners_data"] |
||||
|
journals_data = res_data["journals_data"] |
||||
|
taxes_data = res_data["taxes_data"] |
||||
|
tags_data = res_data["tags_data"] |
||||
|
filter_partner_ids = res_data["filter_partner_ids"] |
||||
|
foreign_currency = res_data["foreign_currency"] |
||||
|
# For each account |
||||
|
for account in general_ledger: |
||||
|
# Write account title |
||||
|
self.write_array_title( |
||||
|
account["code"] + " - " + accounts_data[account["id"]]["name"], |
||||
|
report_data, |
||||
|
) |
||||
|
|
||||
|
if not account["partners"]: |
||||
|
# Display array header for move lines |
||||
|
self.write_array_header(report_data) |
||||
|
|
||||
|
# Display initial balance line for account |
||||
|
account.update( |
||||
|
{ |
||||
|
"initial_debit": account["init_bal"]["debit"], |
||||
|
"initial_credit": account["init_bal"]["credit"], |
||||
|
"initial_balance": account["init_bal"]["balance"], |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency: |
||||
|
account.update( |
||||
|
{"initial_bal_curr": account["init_bal"]["bal_curr"]} |
||||
|
) |
||||
|
self.write_initial_balance_from_dict(account, report_data) |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in account["move_lines"]: |
||||
|
line.update( |
||||
|
{ |
||||
|
"account": account["code"], |
||||
|
"journal": journals_data[line["journal_id"]]["code"], |
||||
|
} |
||||
|
) |
||||
|
if line["currency_id"]: |
||||
|
line.update( |
||||
|
{ |
||||
|
"currency_name": line["currency_id"][1], |
||||
|
"currency_id": line["currency_id"][0], |
||||
|
} |
||||
|
) |
||||
|
if line["ref_label"] != "Centralized entries": |
||||
|
taxes_description = "" |
||||
|
tags = "" |
||||
|
for tax_id in line["tax_ids"]: |
||||
|
taxes_description += taxes_data[tax_id]["tax_name"] + " " |
||||
|
for tag_id in line["tag_ids"]: |
||||
|
tags += tags_data[tag_id]["name"] + " " |
||||
|
line.update( |
||||
|
{ |
||||
|
"taxes_description": taxes_description, |
||||
|
"tags": tags, |
||||
|
} |
||||
|
) |
||||
|
self.write_line_from_dict(line, report_data) |
||||
|
# Display ending balance line for account |
||||
|
account.update( |
||||
|
{ |
||||
|
"final_debit": account["fin_bal"]["debit"], |
||||
|
"final_credit": account["fin_bal"]["credit"], |
||||
|
"final_balance": account["fin_bal"]["balance"], |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency: |
||||
|
account.update( |
||||
|
{ |
||||
|
"final_bal_curr": account["fin_bal"]["bal_curr"], |
||||
|
} |
||||
|
) |
||||
|
self.write_ending_balance_from_dict(account, report_data) |
||||
|
|
||||
|
else: |
||||
|
# For each partner |
||||
|
for partner in account["list_partner"]: |
||||
|
# Write partner title |
||||
|
self.write_array_title( |
||||
|
partners_data[partner["id"]]["name"], report_data |
||||
|
) |
||||
|
|
||||
|
# Display array header for move lines |
||||
|
self.write_array_header(report_data) |
||||
|
|
||||
|
# Display initial balance line for partner |
||||
|
partner.update( |
||||
|
{ |
||||
|
"initial_debit": partner["init_bal"]["debit"], |
||||
|
"initial_credit": partner["init_bal"]["credit"], |
||||
|
"initial_balance": partner["init_bal"]["balance"], |
||||
|
"name": partners_data[partner["id"]]["name"], |
||||
|
"type": "partner", |
||||
|
"currency_id": accounts_data[account["id"]]["currency_id"], |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency: |
||||
|
partner.update( |
||||
|
{ |
||||
|
"initial_bal_curr": partner["init_bal"]["bal_curr"], |
||||
|
} |
||||
|
) |
||||
|
self.write_initial_balance_from_dict(partner, report_data) |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in partner["move_lines"]: |
||||
|
line.update( |
||||
|
{ |
||||
|
"account": account["code"], |
||||
|
"journal": journals_data[line["journal_id"]]["code"], |
||||
|
} |
||||
|
) |
||||
|
if line["currency_id"]: |
||||
|
line.update( |
||||
|
{ |
||||
|
"currency_name": line["currency_id"][1], |
||||
|
"currency_id": line["currency_id"][0], |
||||
|
} |
||||
|
) |
||||
|
if line["ref_label"] != "Centralized entries": |
||||
|
taxes_description = "" |
||||
|
tags = "" |
||||
|
for tax_id in line["tax_ids"]: |
||||
|
taxes_description += ( |
||||
|
taxes_data[tax_id]["tax_name"] + " " |
||||
|
) |
||||
|
for tag_id in line["tag_ids"]: |
||||
|
tags += tags_data[tag_id]["name"] + " " |
||||
|
line.update( |
||||
|
{ |
||||
|
"taxes_description": taxes_description, |
||||
|
"tags": tags, |
||||
|
} |
||||
|
) |
||||
|
self.write_line_from_dict(line, report_data) |
||||
|
|
||||
|
# Display ending balance line for partner |
||||
|
partner.update( |
||||
|
{ |
||||
|
"final_debit": partner["fin_bal"]["debit"], |
||||
|
"final_credit": partner["fin_bal"]["credit"], |
||||
|
"final_balance": partner["fin_bal"]["balance"], |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency and partner["currency_id"]: |
||||
|
partner.update( |
||||
|
{ |
||||
|
"final_bal_curr": partner["fin_bal"]["bal_curr"], |
||||
|
"currency_name": partner["currency_id"].name, |
||||
|
"currency_id": partner["currency_id"].id, |
||||
|
} |
||||
|
) |
||||
|
self.write_ending_balance_from_dict(partner, report_data) |
||||
|
|
||||
|
# Line break |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
if not filter_partner_ids: |
||||
|
account.update( |
||||
|
{ |
||||
|
"final_debit": account["fin_bal"]["debit"], |
||||
|
"final_credit": account["fin_bal"]["credit"], |
||||
|
"final_balance": account["fin_bal"]["balance"], |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency and account["currency_id"]: |
||||
|
account.update( |
||||
|
{ |
||||
|
"final_bal_curr": account["fin_bal"]["bal_curr"], |
||||
|
"currency_name": account["currency_id"].name, |
||||
|
"currency_id": account["currency_id"].id, |
||||
|
} |
||||
|
) |
||||
|
self.write_ending_balance_from_dict(account, report_data) |
||||
|
|
||||
|
# 2 lines break |
||||
|
report_data["row_pos"] += 2 |
||||
|
|
||||
|
def write_initial_balance_from_dict(self, my_object, report_data): |
||||
|
"""Specific function to write initial balance for General Ledger""" |
||||
|
if "partner" in my_object["type"]: |
||||
|
label = _("Partner Initial balance") |
||||
|
elif "account" in my_object["type"]: |
||||
|
label = _("Initial balance") |
||||
|
super(GeneralLedgerXslx, self).write_initial_balance_from_dict( |
||||
|
my_object, label, report_data |
||||
|
) |
||||
|
|
||||
|
def write_ending_balance_from_dict(self, my_object, report_data): |
||||
|
"""Specific function to write ending balance for General Ledger""" |
||||
|
if "partner" in my_object["type"]: |
||||
|
name = my_object["name"] |
||||
|
label = _("Partner ending balance") |
||||
|
elif "account" in my_object["type"]: |
||||
|
name = my_object["code"] + " - " + my_object["name"] |
||||
|
label = _("Ending balance") |
||||
|
super(GeneralLedgerXslx, self).write_ending_balance_from_dict( |
||||
|
my_object, name, label, report_data |
||||
|
) |
@ -0,0 +1,359 @@ |
|||||
|
# Copyright 2019-20 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import itertools |
||||
|
import operator |
||||
|
|
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
|
class JournalLedgerReport(models.AbstractModel): |
||||
|
_name = "report.account_financial_report.journal_ledger" |
||||
|
_description = "Journal Ledger Report" |
||||
|
|
||||
|
def _get_journal_ledger_data(self, journal): |
||||
|
return { |
||||
|
"id": journal.id, |
||||
|
"name": journal.name, |
||||
|
"currency_id": journal.currency_id.id, |
||||
|
"currency_name": journal.currency_id |
||||
|
and journal.currency_id.name |
||||
|
or journal.company_id.currency_id.name, |
||||
|
"debit": 0.0, |
||||
|
"credit": 0.0, |
||||
|
} |
||||
|
|
||||
|
def _get_journal_ledgers_domain(self, wizard, journal_ids, company): |
||||
|
domain = [] |
||||
|
if company: |
||||
|
domain += [("company_id", "=", company.id)] |
||||
|
if journal_ids: |
||||
|
domain += [("id", "in", journal_ids)] |
||||
|
return domain |
||||
|
|
||||
|
def _get_journal_ledgers(self, wizard, journal_ids, company): |
||||
|
journals = self.env["account.journal"].search( |
||||
|
self._get_journal_ledgers_domain(wizard, journal_ids, company), |
||||
|
order="name asc", |
||||
|
) |
||||
|
journal_ledgers_data = [] |
||||
|
for journal in journals: |
||||
|
journal_ledgers_data.append(self._get_journal_ledger_data(journal)) |
||||
|
return journal_ledgers_data |
||||
|
|
||||
|
def _get_moves_domain(self, wizard, journal_ids): |
||||
|
domain = [ |
||||
|
("journal_id", "in", journal_ids), |
||||
|
("date", ">=", wizard.date_from), |
||||
|
("date", "<=", wizard.date_to), |
||||
|
] |
||||
|
if wizard.move_target != "all": |
||||
|
domain += [("state", "=", wizard.move_target)] |
||||
|
return domain |
||||
|
|
||||
|
def _get_moves_order(self, wizard, journal_ids): |
||||
|
search_order = "" |
||||
|
if wizard.sort_option == "move_name": |
||||
|
search_order = "name asc" |
||||
|
elif wizard.sort_option == "date": |
||||
|
search_order = "date asc, name asc" |
||||
|
return search_order |
||||
|
|
||||
|
def _get_moves_data(self, move): |
||||
|
return { |
||||
|
"move_id": move.id, |
||||
|
"journal_id": move.journal_id.id, |
||||
|
"entry": move.name, |
||||
|
} |
||||
|
|
||||
|
def _get_moves(self, wizard, journal_ids): |
||||
|
moves = self.env["account.move"].search( |
||||
|
self._get_moves_domain(wizard, journal_ids), |
||||
|
order=self._get_moves_order(wizard, journal_ids), |
||||
|
) |
||||
|
Moves = [] |
||||
|
move_data = {} |
||||
|
for move in moves: |
||||
|
move_data[move.id] = self._get_moves_data(move) |
||||
|
Moves.append(move_data[move.id]) |
||||
|
return moves.ids, Moves, move_data |
||||
|
|
||||
|
def _get_move_lines_domain(self, move_ids, wizard, journal_ids): |
||||
|
return [("display_type", "=", False), ("move_id", "in", move_ids)] |
||||
|
|
||||
|
def _get_move_lines_order(self, move_ids, wizard, journal_ids): |
||||
|
return "" |
||||
|
|
||||
|
def _get_move_lines_data(self, ml, wizard, ml_taxes): |
||||
|
base_debit = ( |
||||
|
base_credit |
||||
|
) = tax_debit = tax_credit = base_balance = tax_balance = 0.0 |
||||
|
if ml.tax_exigible: |
||||
|
base_debit = ml_taxes and ml.debit or 0.0 |
||||
|
base_credit = ml_taxes and ml.credit or 0.0 |
||||
|
base_balance = ml_taxes and ml.balance or 0.0 |
||||
|
tax_debit = ml.tax_line_id and ml.debit or 0.0 |
||||
|
tax_credit = ml.tax_line_id and ml.credit or 0.0 |
||||
|
tax_balance = ml.tax_line_id and ml.balance or 0.0 |
||||
|
return { |
||||
|
"move_line_id": ml.id, |
||||
|
"move_id": ml.move_id.id, |
||||
|
"date": ml.date, |
||||
|
"journal_id": ml.journal_id.id, |
||||
|
"account_id": ml.account_id.id, |
||||
|
"partner_id": ml.partner_id.id, |
||||
|
"label": ml.name, |
||||
|
"debit": ml.debit, |
||||
|
"credit": ml.credit, |
||||
|
"company_currency_id": ml.company_currency_id.id, |
||||
|
"amount_currency": ml.amount_currency, |
||||
|
"currency_id": ml.currency_id.id, |
||||
|
"tax_line_id": ml.tax_line_id.id, |
||||
|
"tax_ids": list(ml_taxes.keys()), |
||||
|
"base_debit": base_debit, |
||||
|
"base_credit": base_credit, |
||||
|
"tax_debit": tax_debit, |
||||
|
"tax_credit": tax_credit, |
||||
|
"base_balance": base_balance, |
||||
|
"tax_balance": tax_balance, |
||||
|
} |
||||
|
|
||||
|
def _get_account_data(self, accounts): |
||||
|
data = {} |
||||
|
for account in accounts: |
||||
|
data[account.id] = self._get_account_id_data(account) |
||||
|
return data |
||||
|
|
||||
|
def _get_account_id_data(self, account): |
||||
|
return { |
||||
|
"name": account.name, |
||||
|
"code": account.code, |
||||
|
"internal_type": account.internal_type, |
||||
|
} |
||||
|
|
||||
|
def _get_partner_data(self, partners): |
||||
|
data = {} |
||||
|
for partner in partners: |
||||
|
data[partner.id] = self._get_partner_id_data(partner) |
||||
|
return data |
||||
|
|
||||
|
def _get_partner_id_data(self, partner): |
||||
|
return {"name": partner.name} |
||||
|
|
||||
|
def _get_currency_data(self, currencies): |
||||
|
data = {} |
||||
|
for currency in currencies: |
||||
|
data[currency.id] = self._get_currency_id_data(currency) |
||||
|
return data |
||||
|
|
||||
|
def _get_currency_id_data(self, currency): |
||||
|
return {"name": currency.name} |
||||
|
|
||||
|
def _get_tax_line_data(self, taxes): |
||||
|
data = {} |
||||
|
for tax in taxes: |
||||
|
data[tax.id] = self._get_tax_line_id_data(tax) |
||||
|
return data |
||||
|
|
||||
|
def _get_tax_line_id_data(self, tax): |
||||
|
return {"name": tax.name, "description": tax.description} |
||||
|
|
||||
|
def _get_query_taxes(self): |
||||
|
return """ |
||||
|
SELECT aml_at_rel.account_move_line_id, aml_at_rel.account_tax_id, |
||||
|
at.description, at.name |
||||
|
FROM account_move_line_account_tax_rel AS aml_at_rel |
||||
|
LEFT JOIN |
||||
|
account_tax AS at on (at.id = aml_at_rel.account_tax_id) |
||||
|
WHERE account_move_line_id IN %(move_line_ids)s |
||||
|
""" |
||||
|
|
||||
|
def _get_query_taxes_params(self, move_lines): |
||||
|
return {"move_line_ids": tuple(move_lines.ids)} |
||||
|
|
||||
|
def _get_move_lines(self, move_ids, wizard, journal_ids): |
||||
|
move_lines = self.env["account.move.line"].search( |
||||
|
self._get_move_lines_domain(move_ids, wizard, journal_ids), |
||||
|
order=self._get_move_lines_order(move_ids, wizard, journal_ids), |
||||
|
) |
||||
|
move_line_ids_taxes_data = {} |
||||
|
if move_lines: |
||||
|
# Get the taxes ids for the move lines |
||||
|
query_taxes_params = self._get_query_taxes_params(move_lines) |
||||
|
query_taxes = self._get_query_taxes() |
||||
|
self.env.cr.execute(query_taxes, query_taxes_params) |
||||
|
# Fetch the taxes associated to the move line |
||||
|
for ( |
||||
|
move_line_id, |
||||
|
account_tax_id, |
||||
|
tax_description, |
||||
|
tax_name, |
||||
|
) in self.env.cr.fetchall(): |
||||
|
if move_line_id not in move_line_ids_taxes_data.keys(): |
||||
|
move_line_ids_taxes_data[move_line_id] = {} |
||||
|
move_line_ids_taxes_data[move_line_id][account_tax_id] = { |
||||
|
"name": tax_name, |
||||
|
"description": tax_description, |
||||
|
} |
||||
|
Move_Lines = {} |
||||
|
accounts = self.env["account.account"] |
||||
|
partners = self.env["res.partner"] |
||||
|
currencies = self.env["res.currency"] |
||||
|
tax_lines = self.env["account.tax"] |
||||
|
for ml in move_lines: |
||||
|
if ml.account_id not in accounts: |
||||
|
accounts |= ml.account_id |
||||
|
if ml.partner_id not in partners: |
||||
|
partners |= ml.partner_id |
||||
|
if ml.currency_id not in currencies: |
||||
|
currencies |= ml.currency_id |
||||
|
if ml.tax_line_id not in tax_lines: |
||||
|
tax_lines |= ml.tax_line_id |
||||
|
if ml.move_id.id not in Move_Lines.keys(): |
||||
|
Move_Lines[ml.move_id.id] = [] |
||||
|
taxes = ( |
||||
|
ml.id in move_line_ids_taxes_data.keys() |
||||
|
and move_line_ids_taxes_data[ml.id] |
||||
|
or {} |
||||
|
) |
||||
|
Move_Lines[ml.move_id.id].append( |
||||
|
self._get_move_lines_data(ml, wizard, taxes) |
||||
|
) |
||||
|
account_ids_data = self._get_account_data(accounts) |
||||
|
partner_ids_data = self._get_partner_data(partners) |
||||
|
currency_ids_data = self._get_currency_data(currencies) |
||||
|
tax_line_ids_data = self._get_tax_line_data(tax_lines) |
||||
|
return ( |
||||
|
move_lines.ids, |
||||
|
Move_Lines, |
||||
|
account_ids_data, |
||||
|
partner_ids_data, |
||||
|
currency_ids_data, |
||||
|
tax_line_ids_data, |
||||
|
move_line_ids_taxes_data, |
||||
|
) |
||||
|
|
||||
|
def _get_journal_tax_lines(self, wizard, moves_data): |
||||
|
journals_taxes_data = {} |
||||
|
for move_data in moves_data: |
||||
|
report_move_lines = move_data["report_move_lines"] |
||||
|
for report_move_line in report_move_lines: |
||||
|
ml_data = report_move_line |
||||
|
tax_ids = [] |
||||
|
if ml_data["tax_line_id"]: |
||||
|
tax_ids.append(ml_data["tax_line_id"]) |
||||
|
if ml_data["tax_ids"]: |
||||
|
tax_ids += ml_data["tax_ids"] |
||||
|
tax_ids = list(set(tax_ids)) |
||||
|
journal_id = ml_data["journal_id"] |
||||
|
if journal_id not in journals_taxes_data.keys(): |
||||
|
journals_taxes_data[journal_id] = {} |
||||
|
taxes = self.env["account.tax"].browse(tax_ids) |
||||
|
for tax in taxes: |
||||
|
if tax.id not in journals_taxes_data[journal_id]: |
||||
|
journals_taxes_data[journal_id][tax.id] = { |
||||
|
"base_debit": 0.0, |
||||
|
"base_credit": 0.0, |
||||
|
"base_balance": 0.0, |
||||
|
"tax_debit": 0.0, |
||||
|
"tax_credit": 0.0, |
||||
|
"tax_balance": 0.0, |
||||
|
"tax_name": tax.name, |
||||
|
"tax_code": tax.description, |
||||
|
} |
||||
|
field_keys = [ |
||||
|
"base_debit", |
||||
|
"base_credit", |
||||
|
"base_balance", |
||||
|
"tax_debit", |
||||
|
"tax_credit", |
||||
|
"tax_balance", |
||||
|
] |
||||
|
for field_key in field_keys: |
||||
|
journals_taxes_data[journal_id][tax.id][field_key] += ml_data[ |
||||
|
field_key |
||||
|
] |
||||
|
journals_taxes_data_2 = {} |
||||
|
for journal_id in journals_taxes_data.keys(): |
||||
|
journals_taxes_data_2[journal_id] = [] |
||||
|
for tax_id in journals_taxes_data[journal_id].keys(): |
||||
|
journals_taxes_data_2[journal_id] += [ |
||||
|
journals_taxes_data[journal_id][tax_id] |
||||
|
] |
||||
|
return journals_taxes_data_2 |
||||
|
|
||||
|
def _get_report_values(self, docids, data): |
||||
|
wizard_id = data["wizard_id"] |
||||
|
wizard = self.env["journal.ledger.report.wizard"].browse(wizard_id) |
||||
|
company = self.env["res.company"].browse(data["company_id"]) |
||||
|
journal_ids = data["journal_ids"] |
||||
|
journal_ledgers_data = self._get_journal_ledgers(wizard, journal_ids, company) |
||||
|
move_ids, moves_data, move_ids_data = self._get_moves(wizard, journal_ids) |
||||
|
journal_moves_data = {} |
||||
|
for key, items in itertools.groupby( |
||||
|
moves_data, operator.itemgetter("journal_id") |
||||
|
): |
||||
|
if key not in journal_moves_data.keys(): |
||||
|
journal_moves_data[key] = [] |
||||
|
journal_moves_data[key] += list(items) |
||||
|
move_lines_data = ( |
||||
|
account_ids_data |
||||
|
) = ( |
||||
|
partner_ids_data |
||||
|
) = currency_ids_data = tax_line_ids_data = move_line_ids_taxes_data = {} |
||||
|
if move_ids: |
||||
|
move_lines = self._get_move_lines(move_ids, wizard, journal_ids) |
||||
|
move_lines_data = move_lines[1] |
||||
|
account_ids_data = move_lines[2] |
||||
|
partner_ids_data = move_lines[3] |
||||
|
currency_ids_data = move_lines[4] |
||||
|
tax_line_ids_data = move_lines[5] |
||||
|
for move_data in moves_data: |
||||
|
move_id = move_data["move_id"] |
||||
|
move_data["report_move_lines"] = [] |
||||
|
if move_id in move_lines_data.keys(): |
||||
|
move_data["report_move_lines"] += move_lines_data[move_id] |
||||
|
journals_taxes_data = {} |
||||
|
if moves_data: |
||||
|
journals_taxes_data = self._get_journal_tax_lines(wizard, moves_data) |
||||
|
for journal_ledger_data in journal_ledgers_data: |
||||
|
journal_id = journal_ledger_data["id"] |
||||
|
journal_ledger_data["tax_lines"] = journals_taxes_data.get(journal_id, []) |
||||
|
journal_totals = {} |
||||
|
for move_id in move_lines_data.keys(): |
||||
|
for move_line_data in move_lines_data[move_id]: |
||||
|
journal_id = move_line_data["journal_id"] |
||||
|
if journal_id not in journal_totals.keys(): |
||||
|
journal_totals[journal_id] = {"debit": 0.0, "credit": 0.0} |
||||
|
for item in ["debit", "credit"]: |
||||
|
journal_totals[journal_id][item] += move_line_data[item] |
||||
|
for journal_ledger_data in journal_ledgers_data: |
||||
|
journal_id = journal_ledger_data["id"] |
||||
|
if journal_id in journal_moves_data.keys(): |
||||
|
journal_ledger_data["report_moves"] = journal_moves_data[journal_id] |
||||
|
else: |
||||
|
journal_ledger_data["report_moves"] = [] |
||||
|
if journal_id in journal_totals.keys(): |
||||
|
for item in ["debit", "credit"]: |
||||
|
journal_ledger_data[item] += journal_totals[journal_id][item] |
||||
|
return { |
||||
|
"doc_ids": [wizard_id], |
||||
|
"doc_model": "journal.ledger.report.wizard", |
||||
|
"docs": self.env["journal.ledger.report.wizard"].browse(wizard_id), |
||||
|
"group_option": data["group_option"], |
||||
|
"foreign_currency": data["foreign_currency"], |
||||
|
"with_account_name": data["with_account_name"], |
||||
|
"company_name": company.display_name, |
||||
|
"currency_name": company.currency_id.name, |
||||
|
"date_from": data["date_from"], |
||||
|
"date_to": data["date_to"], |
||||
|
"move_target": data["move_target"], |
||||
|
"account_ids_data": account_ids_data, |
||||
|
"partner_ids_data": partner_ids_data, |
||||
|
"currency_ids_data": currency_ids_data, |
||||
|
"move_ids_data": move_ids_data, |
||||
|
"tax_line_data": tax_line_ids_data, |
||||
|
"move_line_ids_taxes_data": move_line_ids_taxes_data, |
||||
|
"Journal_Ledgers": journal_ledgers_data, |
||||
|
"Moves": moves_data, |
||||
|
} |
@ -0,0 +1,263 @@ |
|||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2021 Tecnativa - João Marques |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import _, models |
||||
|
|
||||
|
|
||||
|
class JournalLedgerXslx(models.AbstractModel): |
||||
|
_name = "report.a_f_r.report_journal_ledger_xlsx" |
||||
|
_description = "Journal Ledger XLSX Report" |
||||
|
_inherit = "report.account_financial_report.abstract_report_xlsx" |
||||
|
|
||||
|
def _get_report_name(self, report, data=False): |
||||
|
company_id = data.get("company_id", False) |
||||
|
report_name = _("Journal Ledger") |
||||
|
if company_id: |
||||
|
company = self.env["res.company"].browse(company_id) |
||||
|
suffix = " - {} - {}".format(company.name, company.currency_id.name) |
||||
|
report_name = report_name + suffix |
||||
|
return report_name |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
columns = [ |
||||
|
{"header": _("Entry"), "field": "entry", "width": 18}, |
||||
|
{"header": _("Date"), "field": "date", "width": 11}, |
||||
|
{"header": _("Account"), "field": "account_code", "width": 9}, |
||||
|
] |
||||
|
|
||||
|
if report.with_account_name: |
||||
|
columns.append( |
||||
|
{"header": _("Account Name"), "field": "account_name", "width": 15} |
||||
|
) |
||||
|
|
||||
|
columns += [ |
||||
|
{"header": _("Partner"), "field": "partner", "width": 25}, |
||||
|
{"header": _("Ref - Label"), "field": "label", "width": 40}, |
||||
|
{"header": _("Taxes"), "field": "taxes_description", "width": 11}, |
||||
|
{"header": _("Debit"), "field": "debit", "type": "amount", "width": 14}, |
||||
|
{"header": _("Credit"), "field": "credit", "type": "amount", "width": 14}, |
||||
|
] |
||||
|
|
||||
|
if report.foreign_currency: |
||||
|
columns += [ |
||||
|
{ |
||||
|
"header": _("Currency"), |
||||
|
"field": "currency_name", |
||||
|
"width": 14, |
||||
|
"type": "currency_name", |
||||
|
}, |
||||
|
{ |
||||
|
"header": _("Amount Currency"), |
||||
|
"field": "amount_currency", |
||||
|
"type": "amount", |
||||
|
"width": 18, |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
columns_as_dict = {} |
||||
|
for i, column in enumerate(columns): |
||||
|
columns_as_dict[i] = column |
||||
|
return columns_as_dict |
||||
|
|
||||
|
def _get_journal_tax_columns(self, report): |
||||
|
return { |
||||
|
0: {"header": _("Name"), "field": "tax_name", "width": 35}, |
||||
|
1: {"header": _("Description"), "field": "tax_code", "width": 18}, |
||||
|
2: { |
||||
|
"header": _("Base Debit"), |
||||
|
"field": "base_debit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
3: { |
||||
|
"header": _("Base Credit"), |
||||
|
"field": "base_credit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
4: { |
||||
|
"header": _("Base Balance"), |
||||
|
"field": "base_balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
5: { |
||||
|
"header": _("Tax Debit"), |
||||
|
"field": "tax_debit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
6: { |
||||
|
"header": _("Tax Credit"), |
||||
|
"field": "tax_credit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
7: { |
||||
|
"header": _("Tax Balance"), |
||||
|
"field": "tax_balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
|
||||
|
def _get_col_count_filter_name(self): |
||||
|
return 2 |
||||
|
|
||||
|
def _get_col_count_filter_value(self): |
||||
|
return 3 |
||||
|
|
||||
|
def _get_report_filters(self, report): |
||||
|
target_label_by_value = { |
||||
|
value: label |
||||
|
for value, label in self.env[ |
||||
|
"journal.ledger.report.wizard" |
||||
|
]._get_move_targets() |
||||
|
} |
||||
|
|
||||
|
sort_option_label_by_value = { |
||||
|
value: label |
||||
|
for value, label in self.env[ |
||||
|
"journal.ledger.report.wizard" |
||||
|
]._get_sort_options() |
||||
|
} |
||||
|
|
||||
|
return [ |
||||
|
[_("Company"), report.company_id.name], |
||||
|
[ |
||||
|
_("Date range filter"), |
||||
|
_("From: %s To: %s") % (report.date_from, report.date_to), |
||||
|
], |
||||
|
[ |
||||
|
_("Target moves filter"), |
||||
|
_("%s") % target_label_by_value[report.move_target], |
||||
|
], |
||||
|
[ |
||||
|
_("Entries sorted by"), |
||||
|
_("%s") % sort_option_label_by_value[report.sort_option], |
||||
|
], |
||||
|
[ |
||||
|
_("Journals"), |
||||
|
", ".join( |
||||
|
[ |
||||
|
"{} - {}".format(report_journal.code, report_journal.name) |
||||
|
for report_journal in report.journal_ids |
||||
|
] |
||||
|
), |
||||
|
], |
||||
|
] |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report, data, report_data): |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.journal_ledger" |
||||
|
]._get_report_values(report, data) |
||||
|
group_option = report.group_option |
||||
|
if group_option == "journal": |
||||
|
for ledger in res_data["Journal_Ledgers"]: |
||||
|
self._generate_journal_content( |
||||
|
workbook, report, res_data, ledger, report_data |
||||
|
) |
||||
|
elif group_option == "none": |
||||
|
self._generate_no_group_content(workbook, report, res_data, report_data) |
||||
|
|
||||
|
def _generate_no_group_content(self, workbook, report, res_data, report_data): |
||||
|
self._generate_moves_content( |
||||
|
workbook, "Report", report, res_data, res_data["Moves"], report_data |
||||
|
) |
||||
|
self._generate_no_group_taxes_summary(workbook, report, res_data, report_data) |
||||
|
|
||||
|
def _generate_journal_content( |
||||
|
self, workbook, report, res_data, ledger, report_data |
||||
|
): |
||||
|
journal = self.env["account.journal"].browse(ledger["id"]) |
||||
|
currency_name = ( |
||||
|
journal.currency_id |
||||
|
and journal.currency_id.name |
||||
|
or journal.company_id.currency_id.name |
||||
|
) |
||||
|
sheet_name = "{} ({}) - {}".format(journal.code, currency_name, journal.name) |
||||
|
self._generate_moves_content( |
||||
|
workbook, sheet_name, report, res_data, ledger["report_moves"], report_data |
||||
|
) |
||||
|
self._generate_journal_taxes_summary(workbook, ledger, report_data) |
||||
|
|
||||
|
def _generate_no_group_taxes_summary(self, workbook, report, res_data, report_data): |
||||
|
self._generate_taxes_summary( |
||||
|
workbook, "Tax Report", res_data["tax_line_data"], report_data |
||||
|
) |
||||
|
|
||||
|
def _generate_journal_taxes_summary(self, workbook, ledger, report_data): |
||||
|
journal = self.env["account.journal"].browse(ledger["id"]) |
||||
|
currency_name = ( |
||||
|
journal.currency_id |
||||
|
and journal.currency_id.name |
||||
|
or journal.company_id.currency_id.name |
||||
|
) |
||||
|
sheet_name = "Tax - {} ({}) - {}".format( |
||||
|
journal.code, currency_name, journal.name |
||||
|
) |
||||
|
self._generate_taxes_summary( |
||||
|
workbook, sheet_name, ledger["tax_lines"], report_data |
||||
|
) |
||||
|
|
||||
|
def _generate_moves_content( |
||||
|
self, workbook, sheet_name, report, res_data, moves, report_data |
||||
|
): |
||||
|
report_data["workbook"] = workbook |
||||
|
report_data["sheet"] = workbook.add_worksheet(sheet_name) |
||||
|
self._set_column_width(report_data) |
||||
|
|
||||
|
report_data["row_pos"] = 1 |
||||
|
|
||||
|
self.write_array_title(sheet_name, report_data) |
||||
|
report_data["row_pos"] += 2 |
||||
|
|
||||
|
self.write_array_header(report_data) |
||||
|
account_ids_data = res_data["account_ids_data"] |
||||
|
partner_ids_data = res_data["partner_ids_data"] |
||||
|
currency_ids_data = res_data["currency_ids_data"] |
||||
|
move_ids_data = res_data["move_ids_data"] |
||||
|
for move in moves: |
||||
|
for line in move["report_move_lines"]: |
||||
|
currency_data = currency_ids_data.get(line["currency_id"], False) |
||||
|
currency_name = currency_data and currency_data["name"] or "" |
||||
|
account_data = account_ids_data.get(line["account_id"], False) |
||||
|
account_name = account_data and account_data["name"] or "" |
||||
|
account_code = account_data and account_data["code"] or "" |
||||
|
move_data = move_ids_data.get(line["move_id"], False) |
||||
|
move_entry = move_data and move_data["entry"] or "" |
||||
|
line["partner"] = self._get_partner_name( |
||||
|
line["partner_id"], partner_ids_data |
||||
|
) |
||||
|
line["account_code"] = account_code |
||||
|
line["account_name"] = account_name |
||||
|
line["currency_name"] = currency_name |
||||
|
line["entry"] = move_entry |
||||
|
line["taxes_description"] = report._get_ml_tax_description( |
||||
|
line, |
||||
|
res_data["tax_line_data"].get(line["tax_line_id"]), |
||||
|
res_data["move_line_ids_taxes_data"].get( |
||||
|
line["move_line_id"], False |
||||
|
), |
||||
|
) |
||||
|
self.write_line_from_dict(line, report_data) |
||||
|
report_data["row_pos"] += 1 |
||||
|
|
||||
|
def _generate_taxes_summary( |
||||
|
self, workbook, sheet_name, tax_lines_dict, report_data |
||||
|
): |
||||
|
report_data["workbook"] = workbook |
||||
|
report_data["sheet"] = workbook.add_worksheet(sheet_name) |
||||
|
|
||||
|
report_data["row_pos"] = 1 |
||||
|
self.write_array_title(sheet_name, report_data) |
||||
|
report_data["row_pos"] += 2 |
||||
|
|
||||
|
def _get_partner_name(self, partner_id, partner_data): |
||||
|
if partner_id in partner_data.keys(): |
||||
|
return partner_data[partner_id]["name"] |
||||
|
else: |
||||
|
return "" |
@ -0,0 +1,392 @@ |
|||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import operator |
||||
|
from datetime import date, datetime |
||||
|
|
||||
|
from odoo import api, models |
||||
|
from odoo.tools import float_is_zero |
||||
|
|
||||
|
|
||||
|
class OpenItemsReport(models.AbstractModel): |
||||
|
_name = "report.account_financial_report.open_items" |
||||
|
_description = "Open Items Report" |
||||
|
|
||||
|
@api.model |
||||
|
def get_html(self, given_context=None): |
||||
|
return self._get_html() |
||||
|
|
||||
|
def _get_html(self): |
||||
|
result = {} |
||||
|
rcontext = {} |
||||
|
context = dict(self.env.context) |
||||
|
rcontext.update(context.get("data")) |
||||
|
active_id = context.get("active_id") |
||||
|
wiz = self.env["open.items.report.wizard"].browse(active_id) |
||||
|
rcontext["o"] = wiz |
||||
|
result["html"] = self.env.ref( |
||||
|
"account_financial_report.report_open_items" |
||||
|
).render(rcontext) |
||||
|
return result |
||||
|
|
||||
|
def _get_account_partial_reconciled(self, company_id, date_at_object): |
||||
|
domain = [("max_date", ">", date_at_object), ("company_id", "=", company_id)] |
||||
|
fields = ["debit_move_id", "credit_move_id", "amount"] |
||||
|
accounts_partial_reconcile = self.env["account.partial.reconcile"].search_read( |
||||
|
domain=domain, fields=fields |
||||
|
) |
||||
|
debit_amount = {} |
||||
|
credit_amount = {} |
||||
|
for account_partial_reconcile_data in accounts_partial_reconcile: |
||||
|
debit_move_id = account_partial_reconcile_data["debit_move_id"][0] |
||||
|
credit_move_id = account_partial_reconcile_data["credit_move_id"][0] |
||||
|
if debit_move_id not in debit_amount.keys(): |
||||
|
debit_amount[debit_move_id] = 0.0 |
||||
|
debit_amount[debit_move_id] += account_partial_reconcile_data["amount"] |
||||
|
if credit_move_id not in credit_amount.keys(): |
||||
|
credit_amount[credit_move_id] = 0.0 |
||||
|
credit_amount[credit_move_id] += account_partial_reconcile_data["amount"] |
||||
|
account_partial_reconcile_data.update( |
||||
|
{"debit_move_id": debit_move_id, "credit_move_id": credit_move_id} |
||||
|
) |
||||
|
return accounts_partial_reconcile, debit_amount, credit_amount |
||||
|
|
||||
|
@api.model |
||||
|
def _get_new_move_lines_domain( |
||||
|
self, new_ml_ids, account_ids, company_id, partner_ids, target_moves |
||||
|
): |
||||
|
domain = [ |
||||
|
("account_id", "in", account_ids), |
||||
|
("company_id", "=", company_id), |
||||
|
("id", "in", new_ml_ids), |
||||
|
] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if target_moves == "posted": |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
return domain |
||||
|
|
||||
|
def _recalculate_move_lines( |
||||
|
self, |
||||
|
move_lines, |
||||
|
debit_ids, |
||||
|
credit_ids, |
||||
|
debit_amount, |
||||
|
credit_amount, |
||||
|
ml_ids, |
||||
|
account_ids, |
||||
|
company_id, |
||||
|
partner_ids, |
||||
|
target_moves, |
||||
|
): |
||||
|
debit_ids = set(debit_ids) |
||||
|
credit_ids = set(credit_ids) |
||||
|
in_credit_but_not_in_debit = credit_ids - debit_ids |
||||
|
reconciled_ids = list(debit_ids) + list(in_credit_but_not_in_debit) |
||||
|
reconciled_ids = set(reconciled_ids) |
||||
|
ml_ids = set(ml_ids) |
||||
|
new_ml_ids = reconciled_ids - ml_ids |
||||
|
new_ml_ids = list(new_ml_ids) |
||||
|
new_domain = self._get_new_move_lines_domain( |
||||
|
new_ml_ids, account_ids, company_id, partner_ids, target_moves |
||||
|
) |
||||
|
ml_fields = [ |
||||
|
"id", |
||||
|
"name", |
||||
|
"date", |
||||
|
"move_id", |
||||
|
"journal_id", |
||||
|
"account_id", |
||||
|
"partner_id", |
||||
|
"amount_residual", |
||||
|
"date_maturity", |
||||
|
"ref", |
||||
|
"debit", |
||||
|
"credit", |
||||
|
"reconciled", |
||||
|
"currency_id", |
||||
|
"amount_currency", |
||||
|
"amount_residual_currency", |
||||
|
] |
||||
|
new_move_lines = self.env["account.move.line"].search_read( |
||||
|
domain=new_domain, fields=ml_fields |
||||
|
) |
||||
|
move_lines = move_lines + new_move_lines |
||||
|
for move_line in move_lines: |
||||
|
ml_id = move_line["id"] |
||||
|
if ml_id in debit_ids: |
||||
|
move_line["amount_residual"] += debit_amount[ml_id] |
||||
|
if ml_id in credit_ids: |
||||
|
move_line["amount_residual"] -= credit_amount[ml_id] |
||||
|
return move_lines |
||||
|
|
||||
|
@api.model |
||||
|
def _get_move_lines_domain( |
||||
|
self, company_id, account_ids, partner_ids, target_move, date_from |
||||
|
): |
||||
|
domain = [ |
||||
|
("account_id", "in", account_ids), |
||||
|
("company_id", "=", company_id), |
||||
|
("reconciled", "=", False), |
||||
|
] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if target_move == "posted": |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
if date_from: |
||||
|
domain += [("date", ">", date_from)] |
||||
|
return domain |
||||
|
|
||||
|
def _get_accounts_data(self, accounts_ids): |
||||
|
accounts = self.env["account.account"].browse(accounts_ids) |
||||
|
accounts_data = {} |
||||
|
for account in accounts: |
||||
|
accounts_data.update( |
||||
|
{ |
||||
|
account.id: { |
||||
|
"id": account.id, |
||||
|
"code": account.code, |
||||
|
"name": account.name, |
||||
|
"hide_account": False, |
||||
|
"currency_id": account.currency_id or False, |
||||
|
"currency_name": account.currency_id.name, |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
return accounts_data |
||||
|
|
||||
|
def _get_journals_data(self, journals_ids): |
||||
|
journals = self.env["account.journal"].browse(journals_ids) |
||||
|
journals_data = {} |
||||
|
for journal in journals: |
||||
|
journals_data.update({journal.id: {"id": journal.id, "code": journal.code}}) |
||||
|
return journals_data |
||||
|
|
||||
|
def _get_data( |
||||
|
self, |
||||
|
account_ids, |
||||
|
partner_ids, |
||||
|
date_at_object, |
||||
|
target_move, |
||||
|
company_id, |
||||
|
date_from, |
||||
|
): |
||||
|
domain = self._get_move_lines_domain( |
||||
|
company_id, account_ids, partner_ids, target_move, date_from |
||||
|
) |
||||
|
ml_fields = [ |
||||
|
"id", |
||||
|
"name", |
||||
|
"date", |
||||
|
"move_id", |
||||
|
"journal_id", |
||||
|
"account_id", |
||||
|
"partner_id", |
||||
|
"amount_residual", |
||||
|
"date_maturity", |
||||
|
"ref", |
||||
|
"debit", |
||||
|
"credit", |
||||
|
"reconciled", |
||||
|
"currency_id", |
||||
|
"amount_currency", |
||||
|
"amount_residual_currency", |
||||
|
] |
||||
|
move_lines = self.env["account.move.line"].search_read( |
||||
|
domain=domain, fields=ml_fields |
||||
|
) |
||||
|
journals_ids = set() |
||||
|
partners_ids = set() |
||||
|
partners_data = {} |
||||
|
if date_at_object < date.today(): |
||||
|
( |
||||
|
acc_partial_rec, |
||||
|
debit_amount, |
||||
|
credit_amount, |
||||
|
) = self._get_account_partial_reconciled(company_id, date_at_object) |
||||
|
if acc_partial_rec: |
||||
|
ml_ids = list(map(operator.itemgetter("id"), move_lines)) |
||||
|
debit_ids = list( |
||||
|
map(operator.itemgetter("debit_move_id"), acc_partial_rec) |
||||
|
) |
||||
|
credit_ids = list( |
||||
|
map(operator.itemgetter("credit_move_id"), acc_partial_rec) |
||||
|
) |
||||
|
move_lines = self._recalculate_move_lines( |
||||
|
move_lines, |
||||
|
debit_ids, |
||||
|
credit_ids, |
||||
|
debit_amount, |
||||
|
credit_amount, |
||||
|
ml_ids, |
||||
|
account_ids, |
||||
|
company_id, |
||||
|
partner_ids, |
||||
|
target_move, |
||||
|
) |
||||
|
move_lines = [ |
||||
|
move_line |
||||
|
for move_line in move_lines |
||||
|
if move_line["date"] <= date_at_object |
||||
|
and not float_is_zero(move_line["amount_residual"], precision_digits=2) |
||||
|
] |
||||
|
|
||||
|
open_items_move_lines_data = {} |
||||
|
for move_line in move_lines: |
||||
|
journals_ids.add(move_line["journal_id"][0]) |
||||
|
acc_id = move_line["account_id"][0] |
||||
|
# Partners data |
||||
|
if move_line["partner_id"]: |
||||
|
prt_id = move_line["partner_id"][0] |
||||
|
prt_name = move_line["partner_id"][1] |
||||
|
else: |
||||
|
prt_id = 0 |
||||
|
prt_name = "Missing Partner" |
||||
|
if prt_id not in partners_ids: |
||||
|
partners_data.update({prt_id: {"id": prt_id, "name": prt_name}}) |
||||
|
partners_ids.add(prt_id) |
||||
|
|
||||
|
# Move line update |
||||
|
original = 0 |
||||
|
|
||||
|
if not float_is_zero(move_line["credit"], precision_digits=2): |
||||
|
original = move_line["credit"] * (-1) |
||||
|
if not float_is_zero(move_line["debit"], precision_digits=2): |
||||
|
original = move_line["debit"] |
||||
|
|
||||
|
if move_line["ref"] == move_line["name"]: |
||||
|
if move_line["ref"]: |
||||
|
ref_label = move_line["ref"] |
||||
|
else: |
||||
|
ref_label = "" |
||||
|
elif not move_line["ref"]: |
||||
|
ref_label = move_line["name"] |
||||
|
elif not move_line["name"]: |
||||
|
ref_label = move_line["ref"] |
||||
|
else: |
||||
|
ref_label = move_line["ref"] + str(" - ") + move_line["name"] |
||||
|
|
||||
|
move_line.update( |
||||
|
{ |
||||
|
"date": move_line["date"], |
||||
|
"date_maturity": move_line["date_maturity"] |
||||
|
and move_line["date_maturity"].strftime("%d/%m/%Y"), |
||||
|
"original": original, |
||||
|
"partner_id": prt_id, |
||||
|
"partner_name": prt_name, |
||||
|
"ref_label": ref_label, |
||||
|
"journal_id": move_line["journal_id"][0], |
||||
|
"move_name": move_line["move_id"][1], |
||||
|
"currency_id": move_line["currency_id"][0] |
||||
|
if move_line["currency_id"] |
||||
|
else False, |
||||
|
"currency_name": move_line["currency_id"][1] |
||||
|
if move_line["currency_id"] |
||||
|
else False, |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
# Open Items Move Lines Data |
||||
|
if acc_id not in open_items_move_lines_data.keys(): |
||||
|
open_items_move_lines_data[acc_id] = {prt_id: [move_line]} |
||||
|
else: |
||||
|
if prt_id not in open_items_move_lines_data[acc_id].keys(): |
||||
|
open_items_move_lines_data[acc_id][prt_id] = [move_line] |
||||
|
else: |
||||
|
open_items_move_lines_data[acc_id][prt_id].append(move_line) |
||||
|
journals_data = self._get_journals_data(list(journals_ids)) |
||||
|
accounts_data = self._get_accounts_data(open_items_move_lines_data.keys()) |
||||
|
return ( |
||||
|
move_lines, |
||||
|
partners_data, |
||||
|
journals_data, |
||||
|
accounts_data, |
||||
|
open_items_move_lines_data, |
||||
|
) |
||||
|
|
||||
|
@api.model |
||||
|
def _calculate_amounts(self, open_items_move_lines_data): |
||||
|
total_amount = {} |
||||
|
for account_id in open_items_move_lines_data.keys(): |
||||
|
total_amount[account_id] = {} |
||||
|
total_amount[account_id]["residual"] = 0.0 |
||||
|
for partner_id in open_items_move_lines_data[account_id].keys(): |
||||
|
total_amount[account_id][partner_id] = {} |
||||
|
total_amount[account_id][partner_id]["residual"] = 0.0 |
||||
|
for move_line in open_items_move_lines_data[account_id][partner_id]: |
||||
|
total_amount[account_id][partner_id]["residual"] += move_line[ |
||||
|
"amount_residual" |
||||
|
] |
||||
|
total_amount[account_id]["residual"] += move_line["amount_residual"] |
||||
|
return total_amount |
||||
|
|
||||
|
@api.model |
||||
|
def _order_open_items_by_date( |
||||
|
self, open_items_move_lines_data, show_partner_details |
||||
|
): |
||||
|
new_open_items = {} |
||||
|
if not show_partner_details: |
||||
|
for acc_id in open_items_move_lines_data.keys(): |
||||
|
new_open_items[acc_id] = {} |
||||
|
move_lines = [] |
||||
|
for prt_id in open_items_move_lines_data[acc_id]: |
||||
|
for move_line in open_items_move_lines_data[acc_id][prt_id]: |
||||
|
move_lines += [move_line] |
||||
|
move_lines = sorted(move_lines, key=lambda k: (k["date"])) |
||||
|
new_open_items[acc_id] = move_lines |
||||
|
else: |
||||
|
for acc_id in open_items_move_lines_data.keys(): |
||||
|
new_open_items[acc_id] = {} |
||||
|
for prt_id in open_items_move_lines_data[acc_id]: |
||||
|
new_open_items[acc_id][prt_id] = {} |
||||
|
move_lines = [] |
||||
|
for move_line in open_items_move_lines_data[acc_id][prt_id]: |
||||
|
move_lines += [move_line] |
||||
|
move_lines = sorted(move_lines, key=lambda k: (k["date"])) |
||||
|
new_open_items[acc_id][prt_id] = move_lines |
||||
|
return new_open_items |
||||
|
|
||||
|
def _get_report_values(self, docids, data): |
||||
|
wizard_id = data["wizard_id"] |
||||
|
company = self.env["res.company"].browse(data["company_id"]) |
||||
|
company_id = data["company_id"] |
||||
|
account_ids = data["account_ids"] |
||||
|
partner_ids = data["partner_ids"] |
||||
|
date_at = data["date_at"] |
||||
|
date_at_object = datetime.strptime(date_at, "%Y-%m-%d").date() |
||||
|
date_from = data["date_from"] |
||||
|
target_move = data["target_move"] |
||||
|
show_partner_details = data["show_partner_details"] |
||||
|
|
||||
|
( |
||||
|
move_lines_data, |
||||
|
partners_data, |
||||
|
journals_data, |
||||
|
accounts_data, |
||||
|
open_items_move_lines_data, |
||||
|
) = self._get_data( |
||||
|
account_ids, partner_ids, date_at_object, target_move, company_id, date_from |
||||
|
) |
||||
|
|
||||
|
total_amount = self._calculate_amounts(open_items_move_lines_data) |
||||
|
open_items_move_lines_data = self._order_open_items_by_date( |
||||
|
open_items_move_lines_data, show_partner_details |
||||
|
) |
||||
|
return { |
||||
|
"doc_ids": [wizard_id], |
||||
|
"doc_model": "open.items.report.wizard", |
||||
|
"docs": self.env["open.items.report.wizard"].browse(wizard_id), |
||||
|
"foreign_currency": data["foreign_currency"], |
||||
|
"show_partner_details": data["show_partner_details"], |
||||
|
"company_name": company.display_name, |
||||
|
"currency_name": company.currency_id.name, |
||||
|
"date_at": date_at_object.strftime("%d/%m/%Y"), |
||||
|
"hide_account_at_0": data["hide_account_at_0"], |
||||
|
"target_move": data["target_move"], |
||||
|
"journals_data": journals_data, |
||||
|
"partners_data": partners_data, |
||||
|
"accounts_data": accounts_data, |
||||
|
"total_amount": total_amount, |
||||
|
"Open_Items": open_items_move_lines_data, |
||||
|
} |
@ -0,0 +1,216 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2021 Tecnativa - João Marques |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import _, models |
||||
|
|
||||
|
|
||||
|
class OpenItemsXslx(models.AbstractModel): |
||||
|
_name = "report.a_f_r.report_open_items_xlsx" |
||||
|
_description = "Open Items XLSX Report" |
||||
|
_inherit = "report.account_financial_report.abstract_report_xlsx" |
||||
|
|
||||
|
def _get_report_name(self, report, data=False): |
||||
|
company_id = data.get("company_id", False) |
||||
|
report_name = _("Open Items") |
||||
|
if company_id: |
||||
|
company = self.env["res.company"].browse(company_id) |
||||
|
suffix = " - {} - {}".format(company.name, company.currency_id.name) |
||||
|
report_name = report_name + suffix |
||||
|
return report_name |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
res = { |
||||
|
0: {"header": _("Date"), "field": "date", "width": 11}, |
||||
|
1: {"header": _("Entry"), "field": "move_name", "width": 18}, |
||||
|
2: {"header": _("Journal"), "field": "journal", "width": 8}, |
||||
|
3: {"header": _("Account"), "field": "account", "width": 9}, |
||||
|
4: {"header": _("Partner"), "field": "partner_name", "width": 25}, |
||||
|
5: {"header": _("Ref - Label"), "field": "ref_label", "width": 40}, |
||||
|
6: {"header": _("Due date"), "field": "date_maturity", "width": 11}, |
||||
|
7: { |
||||
|
"header": _("Original"), |
||||
|
"field": "original", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
8: { |
||||
|
"header": _("Residual"), |
||||
|
"field": "amount_residual", |
||||
|
"field_final_balance": "residual", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
if report.foreign_currency: |
||||
|
foreign_currency = { |
||||
|
9: { |
||||
|
"header": _("Cur."), |
||||
|
"field": "currency_name", |
||||
|
"field_currency_balance": "currency_name", |
||||
|
"type": "currency_name", |
||||
|
"width": 7, |
||||
|
}, |
||||
|
10: { |
||||
|
"header": _("Cur. Original"), |
||||
|
"field": "amount_currency", |
||||
|
"field_final_balance": "amount_currency", |
||||
|
"type": "amount_currency", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
11: { |
||||
|
"header": _("Cur. Residual"), |
||||
|
"field": "amount_residual_currency", |
||||
|
"field_final_balance": "amount_currency", |
||||
|
"type": "amount_currency", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
res = {**res, **foreign_currency} |
||||
|
return res |
||||
|
|
||||
|
def _get_report_filters(self, report): |
||||
|
return [ |
||||
|
[_("Date at filter"), report.date_at.strftime("%d/%m/%Y")], |
||||
|
[ |
||||
|
_("Target moves filter"), |
||||
|
_("All posted entries") |
||||
|
if report.target_move == "posted" |
||||
|
else _("All entries"), |
||||
|
], |
||||
|
[ |
||||
|
_("Account balance at 0 filter"), |
||||
|
_("Hide") if report.hide_account_at_0 else _("Show"), |
||||
|
], |
||||
|
[ |
||||
|
_("Show foreign currency"), |
||||
|
_("Yes") if report.foreign_currency else _("No"), |
||||
|
], |
||||
|
] |
||||
|
|
||||
|
def _get_col_count_filter_name(self): |
||||
|
return 2 |
||||
|
|
||||
|
def _get_col_count_filter_value(self): |
||||
|
return 2 |
||||
|
|
||||
|
def _get_col_count_final_balance_name(self): |
||||
|
return 5 |
||||
|
|
||||
|
def _get_col_pos_final_balance_label(self): |
||||
|
return 5 |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report, data, report_data): |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.open_items" |
||||
|
]._get_report_values(report, data) |
||||
|
# For each account |
||||
|
Open_items = res_data["Open_Items"] |
||||
|
accounts_data = res_data["accounts_data"] |
||||
|
partners_data = res_data["partners_data"] |
||||
|
journals_data = res_data["journals_data"] |
||||
|
total_amount = res_data["total_amount"] |
||||
|
show_partner_details = res_data["show_partner_details"] |
||||
|
for account_id in Open_items.keys(): |
||||
|
# Write account title |
||||
|
self.write_array_title( |
||||
|
accounts_data[account_id]["code"] |
||||
|
+ " - " |
||||
|
+ accounts_data[account_id]["name"], |
||||
|
report_data, |
||||
|
) |
||||
|
|
||||
|
# For each partner |
||||
|
if Open_items[account_id]: |
||||
|
if show_partner_details: |
||||
|
for partner_id in Open_items[account_id]: |
||||
|
type_object = "partner" |
||||
|
# Write partner title |
||||
|
self.write_array_title( |
||||
|
partners_data[partner_id]["name"], report_data |
||||
|
) |
||||
|
|
||||
|
# Display array header for move lines |
||||
|
self.write_array_header(report_data) |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in Open_items[account_id][partner_id]: |
||||
|
line.update( |
||||
|
{ |
||||
|
"account": accounts_data[account_id]["code"], |
||||
|
"journal": journals_data[line["journal_id"]][ |
||||
|
"code" |
||||
|
], |
||||
|
} |
||||
|
) |
||||
|
self.write_line_from_dict(line, report_data) |
||||
|
|
||||
|
# Display ending balance line for partner |
||||
|
partners_data[partner_id].update( |
||||
|
{ |
||||
|
"currency_id": accounts_data[account_id]["currency_id"], |
||||
|
"currency_name": accounts_data[account_id][ |
||||
|
"currency_name" |
||||
|
], |
||||
|
} |
||||
|
) |
||||
|
self.write_ending_balance_from_dict( |
||||
|
partners_data[partner_id], |
||||
|
type_object, |
||||
|
total_amount, |
||||
|
report_data, |
||||
|
account_id, |
||||
|
partner_id, |
||||
|
) |
||||
|
|
||||
|
# Line break |
||||
|
report_data["row_pos"] += 1 |
||||
|
else: |
||||
|
# Display array header for move lines |
||||
|
self.write_array_header(report_data) |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in Open_items[account_id]: |
||||
|
line.update( |
||||
|
{ |
||||
|
"account": accounts_data[account_id]["code"], |
||||
|
"journal": journals_data[line["journal_id"]]["code"], |
||||
|
} |
||||
|
) |
||||
|
self.write_line_from_dict(line, report_data) |
||||
|
|
||||
|
# Display ending balance line for account |
||||
|
type_object = "account" |
||||
|
self.write_ending_balance_from_dict( |
||||
|
accounts_data[account_id], |
||||
|
type_object, |
||||
|
report_data, |
||||
|
total_amount, |
||||
|
account_id, |
||||
|
) |
||||
|
|
||||
|
# 2 lines break |
||||
|
report_data["row_pos"] += 2 |
||||
|
|
||||
|
def write_ending_balance_from_dict( |
||||
|
self, |
||||
|
my_object, |
||||
|
type_object, |
||||
|
total_amount, |
||||
|
report_data, |
||||
|
account_id=False, |
||||
|
partner_id=False, |
||||
|
): |
||||
|
"""Specific function to write ending balance for Open Items""" |
||||
|
if type_object == "partner": |
||||
|
name = my_object["name"] |
||||
|
my_object["residual"] = total_amount[account_id][partner_id]["residual"] |
||||
|
label = _("Partner ending balance") |
||||
|
elif type_object == "account": |
||||
|
name = my_object["code"] + " - " + my_object["name"] |
||||
|
my_object["residual"] = total_amount[account_id]["residual"] |
||||
|
label = _("Ending balance") |
||||
|
super(OpenItemsXslx, self).write_ending_balance_from_dict( |
||||
|
my_object, name, label, report_data |
||||
|
) |
@ -0,0 +1,714 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="aged_partner_balance"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<t t-call="account_financial_report.internal_layout"> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_aged_partner_balance_base" |
||||
|
/> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
<template id="report_aged_partner_balance_base"> |
||||
|
<!-- Saved flag fields into variables, used to define columns display --> |
||||
|
<t t-set="show_move_line_details" t-value="show_move_line_details" /> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title"> |
||||
|
Aged Partner Balance - |
||||
|
<t t-raw="company_name" /> |
||||
|
- |
||||
|
<t t-raw="currency_name" /> |
||||
|
</t> |
||||
|
<div class="page"> |
||||
|
<div class="row"> |
||||
|
<h4 |
||||
|
class="mt0" |
||||
|
t-esc="title or 'Odoo Report'" |
||||
|
style="text-align: center;" |
||||
|
/> |
||||
|
</div> |
||||
|
<!-- Display filters --> |
||||
|
<t t-call="account_financial_report.report_aged_partner_balance_filters" /> |
||||
|
<t t-foreach="aged_partner_balance" t-as="account"> |
||||
|
<div class="page_break"> |
||||
|
<!-- Display account header --> |
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;" /> |
||||
|
<div class="act_as_caption account_title" style="width: 100%;"> |
||||
|
<span t-esc="account['code']" /> |
||||
|
- |
||||
|
<span t-esc="account['name']" /> |
||||
|
</div> |
||||
|
<!-- Display account lines --> |
||||
|
<t t-if="not show_move_line_details"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<!-- Display account header --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_aged_partner_balance_lines_header" |
||||
|
/> |
||||
|
<t t-foreach="account['partners']" t-as="partner"> |
||||
|
<!-- Display one line per partner --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_aged_partner_balance_lines" |
||||
|
/> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!-- Display account footer --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_aged_partner_balance_account_ending_cumul" |
||||
|
/> |
||||
|
</t> |
||||
|
<!-- Display account move lines --> |
||||
|
<t t-if="show_move_line_details"> |
||||
|
<!-- Display account partners --> |
||||
|
<t t-foreach="account['partners']" t-as="partner"> |
||||
|
<div class="page_break"> |
||||
|
<!-- Display partner header --> |
||||
|
<div class="act_as_caption account_title"> |
||||
|
<span t-esc="partner['name']" /> |
||||
|
</div> |
||||
|
<!-- Display partner move lines --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_aged_partner_balance_move_lines" |
||||
|
/> |
||||
|
<!-- Display partner footer --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_aged_partner_balance_partner_ending_cumul" |
||||
|
> |
||||
|
<t t-set="partner_cumul_line" t-value="partner" /> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<!-- Display account footer --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_aged_partner_balance_account_ending_cumul" |
||||
|
/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="report_aged_partner_balance_filters"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<div class="act_as_cell">Date at filter</div> |
||||
|
<div class="act_as_cell">Target moves filter</div> |
||||
|
</div> |
||||
|
<div class="act_as_row"> |
||||
|
<div class="act_as_cell"> |
||||
|
<span t-esc="date_at" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="only_posted_moves">All posted entries</t> |
||||
|
<t t-if="not only_posted_moves">All entries</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="report_aged_partner_balance_lines_header"> |
||||
|
<!-- Display table headers for lines --> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell" style="width: 32.52%;">Partner</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">Residual</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">Not due</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">1 - 30 d.</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">31 - 60 d.</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">61 - 90 d.</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">91 - 120 d.</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">> 120 d.</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="report_aged_partner_balance_lines"> |
||||
|
<!-- Display each partner lines --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-esc="partner['name']" /> |
||||
|
</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-esc="partner['residual']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-esc="partner['current']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-esc="partner['30_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-esc="partner['60_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-esc="partner['90_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-esc="partner['120_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-esc="partner['older']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="report_aged_partner_balance_move_lines"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<!-- Display table headers for move lines --> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell first_column" style="width: 6.00%;"> |
||||
|
Date |
||||
|
</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell" style="width: 7.00%;">Entry</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell" style="width: 5.00%;">Journal</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;">Account</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell" style="width: 10.50%;">Partner</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell" style="width: 18.00%;"> |
||||
|
Ref - |
||||
|
Label |
||||
|
</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;"> |
||||
|
Due |
||||
|
date |
||||
|
</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;">Residual</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;">Current</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;"> |
||||
|
Age ≤ 30 |
||||
|
d. |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;"> |
||||
|
Age ≤ 60 |
||||
|
d. |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;"> |
||||
|
Age ≤ 90 |
||||
|
d. |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;"> |
||||
|
Age ≤ 120 |
||||
|
d. |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;">Older</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- Display each move lines --> |
||||
|
<t t-foreach="partner['move_lines']" t-as="line"> |
||||
|
<!-- # lines or centralized lines --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="line.move_line_id.id"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<!--## We don't use t-field because it throws an error on click --> |
||||
|
<t t-esc="line['date']" t-options="{'widget': 'date'}" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="line.move_line_id.move_id.id"--> |
||||
|
<!-- t-att-data-res-model="'account.move'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t t-raw="line['entry']" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="line.move_line_id.move_id.journal_id.id"--> |
||||
|
<!-- t-att-data-res-model="'account.journal'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t t-raw="line['journal']" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="line.move_line_id.account_id.id"--> |
||||
|
<!-- t-att-data-res-model="'account.account'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t t-raw="line['account']" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="line.move_line_id.partner_id.id"--> |
||||
|
<!-- t-att-data-res-model="'res.partner'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t t-raw="line['partner']" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="line.move_line_id.id"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t t-raw="line['ref_label']" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="line.move_line_id.id"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<!--## We don't use t-field because it throws an error on click --> |
||||
|
<t t-esc="line['due_date']" t-options="{'widget': 'date'}" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t |
||||
|
t-raw="line['residual']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<!-- <t t-if="line.current != 0">--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t |
||||
|
t-raw="line['current']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
<!-- </t>--> |
||||
|
<!-- <t t-if="line.current == 0">--> |
||||
|
<!-- <span t-field="line.current" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>--> |
||||
|
<!-- </t>--> |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<!-- <t t-if="line.age_30_days != 0">--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t |
||||
|
t-raw="line['30_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
<!-- </t>--> |
||||
|
<!-- <t t-if="line.age_30_days == 0">--> |
||||
|
<!-- <span t-field="line.age_30_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>--> |
||||
|
<!-- </t>--> |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<!-- <t t-if="line.age_60_days != 0">--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t |
||||
|
t-raw="line['60_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
<!-- </t>--> |
||||
|
<!-- <t t-if="line.age_60_days == 0">--> |
||||
|
<!-- <span t-field="line.age_60_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>--> |
||||
|
<!-- </t>--> |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<!-- <t t-if="line.age_90_days != 0">--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t |
||||
|
t-raw="line['90_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
<!-- </t>--> |
||||
|
<!-- <t t-if="line.age_90_days == 0">--> |
||||
|
<!-- <span t-field="line.age_90_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>--> |
||||
|
<!-- </t>--> |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<!-- <t t-if="line.age_120_days != 0">--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t |
||||
|
t-raw="line['120_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
<!-- </t>--> |
||||
|
<!-- <t t-if="line.age_120_days == 0">--> |
||||
|
<!-- <span t-field="line.age_120_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>--> |
||||
|
<!-- </t>--> |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<!-- <t t-if="line.older != 0">--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- style="color: black;">--> |
||||
|
<t |
||||
|
t-raw="line['older']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
<!-- </t>--> |
||||
|
<!-- <t t-if="line.older == 0">--> |
||||
|
<!-- <span t-field="line.older" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>--> |
||||
|
<!-- </t>--> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="report_aged_partner_balance_partner_ending_cumul"> |
||||
|
<!-- Display ending balance line for partner --> |
||||
|
<div class="act_as_table list_table" style="width: 100%;"> |
||||
|
<div class="act_as_row lines" style="font-weight: bold;"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell right" style="width: 52.00%;"> |
||||
|
Partner |
||||
|
cumul aged balance |
||||
|
</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;" /> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%;"> |
||||
|
<span |
||||
|
t-esc="partner_cumul_line['residual']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%;"> |
||||
|
<span |
||||
|
t-esc="partner_cumul_line['current']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%;"> |
||||
|
<span |
||||
|
t-esc="partner_cumul_line['30_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%;"> |
||||
|
<span |
||||
|
t-esc="partner_cumul_line['60_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%;"> |
||||
|
<span |
||||
|
t-esc="partner_cumul_line['90_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%;"> |
||||
|
<span |
||||
|
t-esc="partner_cumul_line['120_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%;"> |
||||
|
<span |
||||
|
t-esc="partner_cumul_line['older']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="report_aged_partner_balance_account_ending_cumul"> |
||||
|
<!-- Display ending balance line for account --> |
||||
|
<div class="act_as_table list_table" style="width: 100%;"> |
||||
|
<div class="act_as_row lines" style="font-weight: bold;"> |
||||
|
<t t-if="not show_move_line_details"> |
||||
|
<!--## total--> |
||||
|
<div class="act_as_cell right" style="width: 32.52%;">Total</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span |
||||
|
t-esc="account['residual']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span |
||||
|
t-esc="account['current']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span |
||||
|
t-esc="account['30_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span |
||||
|
t-esc="account['60_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span |
||||
|
t-esc="account['90_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span |
||||
|
t-esc="account['120_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span |
||||
|
t-esc="account['older']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="show_move_line_details"> |
||||
|
<!--## total--> |
||||
|
<div class="act_as_cell right" style="width: 52.00%;">Total</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;" /> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span |
||||
|
t-esc="account['residual']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span |
||||
|
t-esc="account['current']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span |
||||
|
t-esc="account['30_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span |
||||
|
t-esc="account['60_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span |
||||
|
t-esc="account['90_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span |
||||
|
t-esc="account['120_days']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span |
||||
|
t-esc="account['older']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
<div class="act_as_row" style="font-weight: bold; font-style: italic;"> |
||||
|
<t t-if="not show_move_line_details"> |
||||
|
<!--## total--> |
||||
|
<div class="act_as_cell right" style="width: 32.52%;">Percents</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;" /> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span t-esc="account['percent_current']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span t-esc="account['percent_30_days']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span t-esc="account['percent_60_days']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span t-esc="account['percent_90_days']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span t-esc="account['percent_120_days']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<span t-esc="account['percent_older']" /> |
||||
|
% |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="show_move_line_details"> |
||||
|
<!--## total--> |
||||
|
<div class="act_as_cell right" style="width: 52.00%;">Percents</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 6.00%;" /> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%" /> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span t-esc="account['percent_current']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span t-esc="account['percent_30_days']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span t-esc="account['percent_60_days']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span t-esc="account['percent_90_days']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span t-esc="account['percent_120_days']" /> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"> |
||||
|
<span t-esc="account['percent_older']" /> |
||||
|
% |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,847 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="general_ledger"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<t t-call="account_financial_report.internal_layout"> |
||||
|
<t t-call="account_financial_report.report_general_ledger_base" /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
<template id="report_general_ledger_base"> |
||||
|
<!-- Saved flag fields into variables, used to define columns display --> |
||||
|
<t t-set="foreign_currency" t-value="foreign_currency" /> |
||||
|
<t t-set="filter_partner_ids" t-value="filter_partner_ids" /> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title"> |
||||
|
General Ledger - |
||||
|
<t t-raw="company_name" /> |
||||
|
- |
||||
|
<t t-raw="currency_name" /> |
||||
|
</t> |
||||
|
<div class="page"> |
||||
|
<div class="row"> |
||||
|
<h4 |
||||
|
class="mt0" |
||||
|
t-esc="title or 'Odoo Report'" |
||||
|
style="text-align: center;" |
||||
|
/> |
||||
|
</div> |
||||
|
<!-- Display filters --> |
||||
|
<t t-call="account_financial_report.report_general_ledger_filters" /> |
||||
|
<t t-foreach="general_ledger" t-as="account"> |
||||
|
<div class="page_break"> |
||||
|
<!-- Display account header --> |
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;" /> |
||||
|
<div class="act_as_caption account_title" style="width: 100%"> |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'code')" |
||||
|
/> |
||||
|
- |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'name')" |
||||
|
/> |
||||
|
</div> |
||||
|
<t t-if="not account['partners']"> |
||||
|
<!-- Display account move lines without partner regroup --> |
||||
|
<t t-set="type" t-value='"account_type"' /> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_general_ledger_lines" |
||||
|
> |
||||
|
<t t-set="account_or_partner_object" t-value="account" /> |
||||
|
</t> |
||||
|
<!-- Display account footer --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_general_ledger_ending_cumul" |
||||
|
> |
||||
|
<t t-set="account_or_partner_object" t-value="account" /> |
||||
|
<t t-set="type" t-value='"account_type"' /> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="account['partners']"> |
||||
|
<!-- Display account partners --> |
||||
|
<t t-foreach="account['list_partner']" t-as="partner"> |
||||
|
<t t-set="type" t-value='"partner_type"' /> |
||||
|
<div class="page_break"> |
||||
|
<!-- Display partner header --> |
||||
|
<div class="act_as_caption account_title"> |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(partner['id'], partners_data, 'name')" |
||||
|
/> |
||||
|
</div> |
||||
|
<!-- Display partner move lines --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_general_ledger_lines" |
||||
|
> |
||||
|
<t |
||||
|
t-set="account_or_partner_object" |
||||
|
t-value="partner" |
||||
|
/> |
||||
|
</t> |
||||
|
<!-- Display partner footer --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_general_ledger_ending_cumul" |
||||
|
> |
||||
|
<t |
||||
|
t-set="account_or_partner_object" |
||||
|
t-value="partner" |
||||
|
/> |
||||
|
<t t-set="type" t-value='"partner_type"' /> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<!-- Display account footer --> |
||||
|
<t t-if="not filter_partner_ids"> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_general_ledger_ending_cumul" |
||||
|
> |
||||
|
<t |
||||
|
t-set="account_or_partner_object" |
||||
|
t-value="account" |
||||
|
/> |
||||
|
<t t-set="type" t-value='"account_type"' /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_general_ledger_filters"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<div class="act_as_cell">Date range filter</div> |
||||
|
<div class="act_as_cell">Target moves filter</div> |
||||
|
<div class="act_as_cell">Account balance at 0 filter</div> |
||||
|
<div class="act_as_cell">Centralize filter</div> |
||||
|
<div class="act_as_cell">Show analytic tags</div> |
||||
|
</div> |
||||
|
<div class="act_as_row"> |
||||
|
<div class="act_as_cell"> |
||||
|
From: |
||||
|
<span t-esc="date_from" /> |
||||
|
To: |
||||
|
<span t-esc="date_to" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="only_posted_moves">All posted entries</t> |
||||
|
<t t-if="not only_posted_moves">All entries</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="hide_account_at_0">Hide</t> |
||||
|
<t t-if="not hide_account_at_0">Show</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="centralize">Yes</t> |
||||
|
<t t-if="not centralize">No</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="show_analytic_tags">Yes</t> |
||||
|
<t t-if="not show_analytic_tags">No</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_general_ledger_lines"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<!-- Display table headers for lines --> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell first_column" style="width: 3.51%;"> |
||||
|
Date |
||||
|
</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell" style="width: 8.03%">Entry</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell" style="width: 4.13%;">Journal</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell" style="width: 4.75%;">Account</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell" style="width: 8.89%;">Taxes</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell" style="width: 12.01%;">Partner</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell" style="width: 16.9%;"> |
||||
|
Ref - |
||||
|
Label |
||||
|
</div> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<!--## cost_center--> |
||||
|
<div class="act_as_cell" style="width: 8.03%;"> |
||||
|
Analytic Account |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="show_analytic_tags"> |
||||
|
<!--## analytic tags--> |
||||
|
<div class="act_as_cell" style="width: 4.75%;">Tags</div> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell" style="width: 2.41%;">Rec.</div> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount" style="width: 8.02%;">Debit</div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount" style="width: 8.02%;">Credit</div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount" style="width: 8.02%;"> |
||||
|
Cumul. Bal. |
||||
|
</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" style="width: 2.08%;">Cur.</div> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 5.19%;"> |
||||
|
Amount cur. |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!-- Display first line with initial balance --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## taxes--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell amount">Initial balance</div> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<!--## cost_center--> |
||||
|
<div class="act_as_cell" /> |
||||
|
</t> |
||||
|
<t t-if="show_analytic_tags"> |
||||
|
<!--## analytic tags--> |
||||
|
<div class="act_as_cell" /> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('date', '<', date_from), |
||||
|
('debit', '<>', 0)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['init_bal']['debit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('partner_id', '=', partner['id']), |
||||
|
('date', '<', date_from), |
||||
|
('debit', '<>', 0)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['init_bal']['debit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('date', '<', date_from), |
||||
|
('credit', '<>', 0)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['init_bal']['credit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('partner_id', '=', partner['id']), |
||||
|
('date', '<', date_from), |
||||
|
('credit', '<>', 0)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['init_bal']['credit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('date', '<', date_from)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['init_bal']['balance']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('partner_id', '=', partner['id']), |
||||
|
('date', '<', date_from)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['init_bal']['balance']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t |
||||
|
t-if="o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')" |
||||
|
> |
||||
|
<div class="act_as_cell amount" style="width: 2.08%;"> |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'currency_name')" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" style="width: 5.19%;"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('date', '<', o.date_from)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['init_bal']['bal_curr']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('partner_id', '=', partner['id']), |
||||
|
('date', '<', o.date_from)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['init_bal']['bal_curr']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t |
||||
|
t-if="not o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')" |
||||
|
> |
||||
|
<div class="act_as_cell" style="width: 2.08%;" /> |
||||
|
<div class="act_as_cell" style="width: 5.19%;" /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!-- Display each lines --> |
||||
|
<t t-foreach="account_or_partner_object['move_lines']" t-as="line"> |
||||
|
<!-- # lines or centralized lines --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'" /> |
||||
|
<span> |
||||
|
<t t-if="line['id']"> |
||||
|
<a |
||||
|
t-att-data-active-id="line['id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<!--## We don't use t-field because it throws an error on click --> |
||||
|
<t |
||||
|
t-esc="line['date']" |
||||
|
t-options="{'widget': 'date'}" |
||||
|
/> |
||||
|
</a> |
||||
|
</t> |
||||
|
<t t-if="not line['id']"> |
||||
|
<a |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<!--## We don't use t-field because it throws an error on click --> |
||||
|
<t |
||||
|
t-esc="line['date']" |
||||
|
t-options="{'widget': 'date'}" |
||||
|
/> |
||||
|
</a> |
||||
|
</t> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'account.move'" /> |
||||
|
<t t-if="line['entry_id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="line['entry_id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t t-raw="line['entry']" /> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'account.journal'" /> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="line['journal_id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="o._get_atr_from_dict(line['journal_id'], journals_data, 'code')" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'account.account'" /> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="account['id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="o._get_atr_from_dict(account['id'], accounts_data, 'code')" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## taxes--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-if="taxes_data and line['tax_ids']"> |
||||
|
<t t-foreach="line['tax_ids']" t-as="tax_id"> |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(tax_id, taxes_data, 'tax_name')" |
||||
|
/> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'res.partner'" /> |
||||
|
<span t-if="line['partner_id']"> |
||||
|
<a |
||||
|
t-att-data-active-id="line['partner_id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t t-raw="line['partner_name']" /> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'" /> |
||||
|
<t t-if="line['id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="line['id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t t-raw="line['ref_label']" /> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="not line['id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t t-raw="line['ref_label']" /> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## cost_center--> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'account.analytic.account'" /> |
||||
|
<span t-if="line['analytic_account_id']"> |
||||
|
<a |
||||
|
t-att-data-active-id="line['analytic_account_id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t t-raw="line['analytic_account']" /> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="show_analytic_tags"> |
||||
|
<!--## analytic tags--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-if="line['tag_ids']"> |
||||
|
<t t-foreach="line['tag_ids']" t-as="tag_id"> |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(tag_id, tags_data, 'name')" |
||||
|
/> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-set="res_model" t-value="'account.full.reconcile'" /> |
||||
|
<span t-if="line['rec_id']"> |
||||
|
<a |
||||
|
t-att-data-active-id="line['rec_id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t t-raw="line['rec_name']" /> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'" /> |
||||
|
<t t-if="line['id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="line['id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action_monetary" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="line['debit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="not line['id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
class="o_account_financial_reports_web_action_monetary" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="line['debit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'" /> |
||||
|
<t t-if="line['id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="line['id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action_monetary" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="line['credit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="not line['id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
class="o_account_financial_reports_web_action_monetary" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="line['credit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'" /> |
||||
|
<t t-if="line['id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="line['id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action_monetary" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="line['balance']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="not line['id']"> |
||||
|
<span> |
||||
|
<a |
||||
|
class="o_account_financial_reports_web_action_monetary" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="line['balance']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t t-if="line['currency_id']"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell amount" style="width: 2.08%;"> |
||||
|
<span t-esc="line['currency_id'][1]" /> |
||||
|
</div> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 5.19%;"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'" /> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="line['id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t t-raw="line['bal_curr']" /> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not line['currency_id']"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell amount" style="width: 2.08%;" /> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 5.19%;" /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_general_ledger_ending_cumul"> |
||||
|
<!-- Display ending balance line for account or partner --> |
||||
|
<div class="act_as_table list_table" style="width: 100%;"> |
||||
|
<div class="act_as_row labels" style="font-weight: bold;"> |
||||
|
<!--## date--> |
||||
|
<t t-if='type == "account_type"'> |
||||
|
<div class="act_as_cell first_column" style="width: 41.32%;"> |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'code')" |
||||
|
/> |
||||
|
- |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'name')" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell right" style="width: 16.9%;"> |
||||
|
Ending balance |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if='type == "partner_type"'> |
||||
|
<div class="act_as_cell first_column" style="width: 41.32%;" /> |
||||
|
<div class="act_as_cell right" style="width: 16.9%;"> |
||||
|
Partner ending balance |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<!--## cost_center--> |
||||
|
<div class="act_as_cell" style="width: 8.03%" /> |
||||
|
</t> |
||||
|
<t t-if="show_analytic_tags"> |
||||
|
<!--## analytic tags--> |
||||
|
<div class="act_as_cell" style="width: 4.75%;" /> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell" style="width: 2.41%;" /> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount" style="width: 8.02%;"> |
||||
|
<span |
||||
|
t-esc="account_or_partner_object['fin_bal']['debit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount" style="width: 8.02%;"> |
||||
|
<span |
||||
|
t-esc="account_or_partner_object['fin_bal']['credit']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount" style="width: 8.02%;"> |
||||
|
<span |
||||
|
t-esc="account_or_partner_object['fin_bal']['balance']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## currency_name + amount_currency--> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t |
||||
|
t-if="o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')" |
||||
|
> |
||||
|
<div class="act_as_cell amount" style="width: 2.08%;"> |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'currency_name')" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" style="width: 5.19%;"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('date', '<', date_from)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['fin_bal']['bal_curr']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t |
||||
|
t-set="domain" |
||||
|
t-value="[('account_id', '=', account['id']), |
||||
|
('partner_id', '=', partner['id']), |
||||
|
('date', '<', date_from)]" |
||||
|
/> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-raw="account_or_partner_object['fin_bal']['bal_curr']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')}" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t |
||||
|
t-if="not o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')" |
||||
|
> |
||||
|
<div class="act_as_cell amount" style="width: 2.08%;" /> |
||||
|
<div class="act_as_cell amount" style="width: 5.19%;" /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,487 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<!-- Copyright 2018 ForgeFlow S.L. |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> |
||||
|
<odoo> |
||||
|
<template id="journal_ledger"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<t t-call="account_financial_report.internal_layout"> |
||||
|
<t t-call="account_financial_report.report_journal_ledger_base" /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
<template id="report_journal_ledger_base"> |
||||
|
<t t-set="display_currency" t-value="foreign_currency" /> |
||||
|
<t t-set="display_account_name" t-value="with_account_name" /> |
||||
|
<t t-set="title"> |
||||
|
Journal Ledger - |
||||
|
<t t-raw="company_name" /> |
||||
|
- |
||||
|
<t t-raw="currency_name" /> |
||||
|
</t> |
||||
|
<t t-set="company_name" t-value="Company_Name" /> |
||||
|
<div class="page"> |
||||
|
<div class="row"> |
||||
|
<h4 |
||||
|
class="mt0" |
||||
|
t-esc="title or 'Odoo Report'" |
||||
|
style="text-align: center;" |
||||
|
/> |
||||
|
</div> |
||||
|
<t t-if="group_option == 'none'"> |
||||
|
<div class="page_break"> |
||||
|
<t t-call="account_financial_report.report_journal_all" /> |
||||
|
<br /> |
||||
|
<t t-call="account_financial_report.report_journal_all_taxes" /> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="group_option == 'journal'"> |
||||
|
<t t-foreach="Journal_Ledgers" t-as="journal"> |
||||
|
<div class="page_break"> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_journal_ledger_journal" |
||||
|
/> |
||||
|
<br /> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_journal_ledger_journal_taxes" |
||||
|
/> |
||||
|
<br /> |
||||
|
</div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_journal_all"> |
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;" /> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_journal_ledger_journal_table_header" |
||||
|
/> |
||||
|
<t t-foreach="Moves" t-as="move"> |
||||
|
<t t-call="account_financial_report.report_journal_move" /> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_journal_ledger_journal"> |
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;" /> |
||||
|
<div class="act_as_caption account_title" style="width: 100%;"> |
||||
|
<span t-esc="journal['name']" /> |
||||
|
( |
||||
|
<span t-esc="journal['currency_name']" /> |
||||
|
) - |
||||
|
<span t-esc="date_from" t-options="{'widget': 'date'}" /> |
||||
|
to |
||||
|
<span t-esc="date_to" t-options="{'widget': 'date'}" /> |
||||
|
- |
||||
|
<span t-esc="move_target" /> |
||||
|
Moves |
||||
|
</div> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_journal_ledger_journal_table_header" |
||||
|
/> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_journal_ledger_journal_first_line" |
||||
|
/> |
||||
|
<t t-foreach="journal['report_moves']" t-as="move"> |
||||
|
<t t-call="account_financial_report.report_journal_move" /> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_journal_ledger_journal_table_header"> |
||||
|
<t t-if="not display_account_name"> |
||||
|
<t t-set="account_column_style">width: 8.11%;</t> |
||||
|
<t t-set="label_column_style">width: 38.92%;</t> |
||||
|
</t> |
||||
|
<t t-else=""> |
||||
|
<t t-set="account_column_style">width: 23.78%;</t> |
||||
|
<t t-set="label_column_style">width: 23.24%;</t> |
||||
|
</t> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<div |
||||
|
class="act_as_cell first_column" |
||||
|
name="entry" |
||||
|
style="width: 7.57%;" |
||||
|
> |
||||
|
Entry |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="date" style="width: 5.41%;">Date</div> |
||||
|
<div |
||||
|
class="act_as_cell" |
||||
|
name="account" |
||||
|
t-att-style="account_column_style" |
||||
|
> |
||||
|
Account |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="partner" style="width: 15.14%;"> |
||||
|
Partner |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="label" t-att-style="label_column_style"> |
||||
|
Ref - Label |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="taxes" style="width: 7.57%;">Taxes</div> |
||||
|
<div class="act_as_cell" name="debit" style="width: 8.65%;">Debit</div> |
||||
|
<div class="act_as_cell" name="credit" style="width: 8.65%;"> |
||||
|
Credit |
||||
|
</div> |
||||
|
<t t-if="display_currency"> |
||||
|
<div class="act_as_cell" name="currency_name" style="width: 2.16%;"> |
||||
|
Cur. |
||||
|
</div> |
||||
|
<div |
||||
|
class="act_as_cell" |
||||
|
name="amount_currency" |
||||
|
style="width: 6.49%;" |
||||
|
> |
||||
|
Amount Cur. |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_journal_ledger_journal_first_line"> |
||||
|
<div class="act_as_row lines"> |
||||
|
<div class="act_as_cell" name="entry" /> |
||||
|
<div class="act_as_cell" name="date" /> |
||||
|
<div class="act_as_cell" name="account" /> |
||||
|
<div class="act_as_cell" name="partner" /> |
||||
|
<div class="act_as_cell" name="label" /> |
||||
|
<div class="act_as_cell" name="taxes" /> |
||||
|
<div class="act_as_cell amount" name="debit"> |
||||
|
<b> |
||||
|
<span |
||||
|
t-esc="journal['debit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</b> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="credit"> |
||||
|
<b> |
||||
|
<span |
||||
|
t-esc="journal['credit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</b> |
||||
|
</div> |
||||
|
<t t-if="display_currency"> |
||||
|
<div class="act_as_cell" name="currency_name"> |
||||
|
|
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="amount_currency"> |
||||
|
|
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
<div style="width: 100%" /> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_journal_move"> |
||||
|
<t t-set="display_move_info" t-value="True" /> |
||||
|
<t t-set="last_partner" t-eval="None" /> |
||||
|
<t t-set="display_partner" t-eval="True" /> |
||||
|
<t t-foreach="move['report_move_lines']" t-as="move_line"> |
||||
|
<div class="act_as_row lines"> |
||||
|
<t |
||||
|
t-set="current_partner" |
||||
|
t-value="o._get_partner_name(move_line['partner_id'], partner_ids_data)" |
||||
|
/> |
||||
|
<t t-set="display_partner" t-value="current_partner != last_partner" /> |
||||
|
<t t-call="account_financial_report.report_journal_move_line" /> |
||||
|
<t t-set="last_partner" t-value="current_partner" /> |
||||
|
<t t-set="display_move_info" t-value="False" /> |
||||
|
</div> |
||||
|
</t> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_journal_move_line"> |
||||
|
<div class="act_as_cell left" name="entry"> |
||||
|
<t t-set="res_model" t-value="'account.move'" /> |
||||
|
<span t-if="display_move_info"> |
||||
|
<a |
||||
|
t-att-data-active-id="move_line['move_id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t |
||||
|
t-esc="o._get_atr_from_dict(move_line['move_id'], move_ids_data, 'entry')" |
||||
|
/> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" name="date"> |
||||
|
<span |
||||
|
t-if="display_move_info" |
||||
|
t-esc="move_line['date']" |
||||
|
t-options="{'widget': 'date'}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" name="account"> |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(move_line['account_id'], account_ids_data, 'code')" |
||||
|
/> |
||||
|
<span t-if="display_account_name"> |
||||
|
- |
||||
|
<span |
||||
|
t-esc="o._get_atr_from_dict(move_line['account_id'], account_ids_data, 'name')" |
||||
|
/> |
||||
|
</span> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" name="partner"> |
||||
|
<span |
||||
|
t-if="display_partner" |
||||
|
t-esc="o._get_partner_name(move_line['partner_id'], partner_ids_data)" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" name="label"> |
||||
|
<span t-if="move_line['label']" t-esc="move_line['label']" /> |
||||
|
<span t-if="not move_line['label']">/</span> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" name="taxes"> |
||||
|
<t |
||||
|
t-set="tax_line_dat" |
||||
|
t-value="o._get_data_from_dict(move_line['tax_line_id'], tax_line_data)" |
||||
|
/> |
||||
|
<t |
||||
|
t-set="move_line_ids_taxes_dat" |
||||
|
t-value="o._get_data_from_dict(move_line['move_line_id'], move_line_ids_taxes_data)" |
||||
|
/> |
||||
|
<span |
||||
|
t-esc="o._get_ml_tax_description(move_line, tax_line_dat, move_line_ids_taxes_dat)" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="debit"> |
||||
|
<t t-if="move_line['debit']"> |
||||
|
<span |
||||
|
t-esc="move_line['debit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="credit"> |
||||
|
<t t-if="move_line['credit']"> |
||||
|
<span |
||||
|
t-esc="move_line['credit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</t> |
||||
|
</div> |
||||
|
<t t-if="display_currency"> |
||||
|
<div class="act_as_cell" name="currency_name"> |
||||
|
<t t-if="move_line['currency_id']"> |
||||
|
<span t-esc="currency_ids_data.get(move_line['currency_id'], '')" /> |
||||
|
</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="amount_currency"> |
||||
|
<t |
||||
|
t-if="move_line['amount_currency']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
> |
||||
|
<span |
||||
|
t-esc="move_line['amount_currency']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_journal_ledger_journal_taxes"> |
||||
|
<b>Taxes summary</b> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<div |
||||
|
class="act_as_cell first_column" |
||||
|
name="name" |
||||
|
style="width: 30.97%;" |
||||
|
> |
||||
|
Name |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="description" style="width: 13.27%;"> |
||||
|
Description |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="base_amount" style="width: 27.88%;"> |
||||
|
Base Amount |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="tax_amount" style="width: 27.88%;"> |
||||
|
Tax Amount |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<div |
||||
|
class="act_as_cell first_column" |
||||
|
name="name" |
||||
|
style="width: 30.97%;" |
||||
|
/> |
||||
|
<div class="act_as_cell" name="description" style="width: 13.27%;" /> |
||||
|
<div class="act_as_cell" name="base_debit" style="width: 9.29%;"> |
||||
|
Debit |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="base_credit" style="width: 9.29%;"> |
||||
|
Credit |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="base_balance" style="width: 9.29%;"> |
||||
|
Balance |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="tax_debit" style="width: 9.29%;"> |
||||
|
Debit |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="tax_credit" style="width: 9.29%;"> |
||||
|
Credit |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="tax_balance" style="width: 9.29%;"> |
||||
|
Balance |
||||
|
</div> |
||||
|
</div> |
||||
|
<t t-foreach="journal['tax_lines']" t-as="tax_line"> |
||||
|
<div class="act_as_row lines"> |
||||
|
<div class="act_as_cell left" name="tax_name"> |
||||
|
<span t-esc="tax_line['tax_name']" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" name="tax_code"> |
||||
|
<span t-esc="tax_line['tax_code']" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="base_debit"> |
||||
|
<span |
||||
|
t-esc="tax_line['base_debit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="base_credit"> |
||||
|
<span |
||||
|
t-esc="tax_line['base_credit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="base_balance"> |
||||
|
<span |
||||
|
t-esc="tax_line['base_balance']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="tax_debit"> |
||||
|
<span |
||||
|
t-esc="tax_line['tax_debit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="tax_credit"> |
||||
|
<span |
||||
|
t-esc="tax_line['tax_credit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="tax_balance"> |
||||
|
<span |
||||
|
t-esc="tax_line['tax_balance']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_journal_all_taxes"> |
||||
|
<b>Taxes summary</b> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<div |
||||
|
class="act_as_cell first_column" |
||||
|
name="name" |
||||
|
style="width: 30.97%;" |
||||
|
> |
||||
|
Name |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="description" style="width: 13.27%;"> |
||||
|
Description |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="base_amount" style="width: 27.88%;"> |
||||
|
Base Amount |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="tax_amount" style="width: 27.88%;"> |
||||
|
Tax Amount |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
10 |
||||
|
<div class="act_as_row labels"> |
||||
|
<div |
||||
|
class="act_as_cell first_column" |
||||
|
name="name" |
||||
|
style="width: 30.97%;" |
||||
|
/> |
||||
|
<div class="act_as_cell" name="description" style="width: 13.27%;" /> |
||||
|
<div class="act_as_cell" name="base_debit" style="width: 9.29%;"> |
||||
|
Debit |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="base_credit" style="width: 9.29%;"> |
||||
|
Credit |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="base_balance" style="width: 9.29%;"> |
||||
|
Balance |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="tax_debit" style="width: 9.29%;"> |
||||
|
Debit |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="tax_credit" style="width: 9.29%;"> |
||||
|
Credit |
||||
|
</div> |
||||
|
<div class="act_as_cell" name="tax_balance" style="width: 9.29%;"> |
||||
|
Balance |
||||
|
</div> |
||||
|
</div> |
||||
|
<t t-foreach="ReportTaxLines" t-as="tax_line"> |
||||
|
<div class="act_as_row lines"> |
||||
|
<div class="act_as_cell left" name="tax_name"> |
||||
|
<span t-esc="tax_line['tax_name']" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" name="tax_code"> |
||||
|
<span t-esc="tax_line['tax_code']" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="base_debit"> |
||||
|
<span |
||||
|
t-esc="tax_line['base_debit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="base_credit"> |
||||
|
<span |
||||
|
t-esc="tax_line['base_credit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="base_balance"> |
||||
|
<span |
||||
|
t-esc="tax_line['base_balance']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="tax_debit"> |
||||
|
<span |
||||
|
t-esc="tax_line['tax_debit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="tax_credit"> |
||||
|
<span |
||||
|
t-esc="tax_line['tax_credit']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" name="tax_balance"> |
||||
|
<span |
||||
|
t-esc="tax_line['tax_balance']" |
||||
|
t-options="{'widget': 'float', 'precision': 2}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,32 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="account_financial_report.internal_layout"> |
||||
|
<div class="article"> |
||||
|
<link |
||||
|
href="/account_financial_report/static/src/css/report.css" |
||||
|
rel="stylesheet" |
||||
|
/> |
||||
|
<t t-raw="0" /> |
||||
|
</div> |
||||
|
<div class="footer"> |
||||
|
<div class="row"> |
||||
|
<div class="col-6 custom_footer"> |
||||
|
<span |
||||
|
t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="col-6 text-right custom_footer"> |
||||
|
<ul class="list-inline"> |
||||
|
<li class="list-inline-item"> |
||||
|
<span class="page" /> |
||||
|
</li> |
||||
|
<li class="list-inline-item">/</li> |
||||
|
<li class="list-inline-item"> |
||||
|
<span class="topage" /> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,308 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="open_items"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<t t-call="account_financial_report.internal_layout"> |
||||
|
<t t-call="account_financial_report.report_open_items_base" /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_open_items_base"> |
||||
|
<!-- Saved flag fields into variables, used to define columns display --> |
||||
|
<t t-set="foreign_currency" t-value="foreign_currency" /> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title"> |
||||
|
Open Items - |
||||
|
<t t-raw="company_name" /> |
||||
|
- |
||||
|
<t t-raw="currency_name" /> |
||||
|
</t> |
||||
|
<t t-set="company_name" t-value="Company_Name" /> |
||||
|
<div class="page"> |
||||
|
<div class="row"> |
||||
|
<h4 |
||||
|
class="mt0" |
||||
|
t-esc="title or 'Odoo Report'" |
||||
|
style="text-align: center;" |
||||
|
/> |
||||
|
</div> |
||||
|
<!-- Display filters --> |
||||
|
<t t-call="account_financial_report.report_open_items_filters" /> |
||||
|
<t t-foreach="Open_Items.keys()" t-as="account_id"> |
||||
|
<!-- Display account header --> |
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;" /> |
||||
|
<div class="account_title" style="width: 100%;"> |
||||
|
<span t-esc="accounts_data[account_id]['code']" /> |
||||
|
- |
||||
|
<span t-esc="accounts_data[account_id]['name']" /> |
||||
|
</div> |
||||
|
<t t-if="not show_partner_details"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_open_items_lines_header" |
||||
|
/> |
||||
|
<!-- Display account move lines --> |
||||
|
<t t-foreach="Open_Items[account_id]" t-as="line"> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_open_items_lines" |
||||
|
/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="show_partner_details"> |
||||
|
<div class="page_break"> |
||||
|
<!-- Display account partners --> |
||||
|
<t t-foreach="Open_Items[account_id]" t-as="partner_id"> |
||||
|
<div class="act_as_caption account_title"> |
||||
|
<span t-esc="partners_data[partner_id]['name']" /> |
||||
|
</div> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<!-- Display partner header --> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_open_items_lines_header" |
||||
|
/> |
||||
|
<!-- Display partner move lines --> |
||||
|
<t |
||||
|
t-foreach="Open_Items[account_id][partner_id]" |
||||
|
t-as="line" |
||||
|
> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_open_items_lines" |
||||
|
/> |
||||
|
</t> |
||||
|
</div> |
||||
|
<t |
||||
|
t-call="account_financial_report.report_open_items_ending_cumul" |
||||
|
> |
||||
|
<t |
||||
|
t-set="account_or_partner_id" |
||||
|
t-value="partners_data[partner_id]" |
||||
|
/> |
||||
|
<t |
||||
|
t-set="currency_id" |
||||
|
t-value="accounts_data[account_id]['currency_name']" |
||||
|
/> |
||||
|
<t t-set="type" t-value='"partner_type"' /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<!-- Display account footer --> |
||||
|
<t t-call="account_financial_report.report_open_items_ending_cumul"> |
||||
|
<t |
||||
|
t-set="account_or_partner_id" |
||||
|
t-value="accounts_data[account_id]" |
||||
|
/> |
||||
|
<t |
||||
|
t-set="currency_id" |
||||
|
t-value="accounts_data[account_id]['currency_name']" |
||||
|
/> |
||||
|
<t t-set="type" t-value='"account_type"' /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_open_items_filters"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<div class="act_as_cell">Date at filter</div> |
||||
|
<div class="act_as_cell">Target moves filter</div> |
||||
|
<div class="act_as_cell">Account balance at 0 filter</div> |
||||
|
</div> |
||||
|
<div class="act_as_row"> |
||||
|
<div class="act_as_cell"> |
||||
|
<span t-esc="date_at" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="target_move == 'posted'">All posted entries</t> |
||||
|
<t t-if="target_move == 'all'">All entries</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="hide_account_at_0">Hide</t> |
||||
|
<t t-if="not hide_account_at_0">Show</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_open_items_lines_header"> |
||||
|
<!-- Display table headers for lines --> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell first_column" style="width: 5.51%;">Date</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell" style="width: 9.76%;">Entry</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell" style="width: 4.78%;">Journal</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell" style="width: 5.38%;">Account</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell" style="width: 15.07%;">Partner</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell" style="width: 24.5%;"> |
||||
|
Ref - |
||||
|
Label |
||||
|
</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 6.47%;"> |
||||
|
Due |
||||
|
date |
||||
|
</div> |
||||
|
<!--## amount_total_due--> |
||||
|
<div class="act_as_cell" style="width: 6.57%;">Original</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell" style="width: 6.57%;">Residual</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" style="width: 2.25%;">Cur.</div> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 6.57%;"> |
||||
|
Cur. Original |
||||
|
</div> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 6.57%;"> |
||||
|
Cur. Residual |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_open_items_lines"> |
||||
|
<!-- # lines or centralized lines --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-raw="line['date'].strftime('%d/%m/%Y')" /> |
||||
|
</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'account.move'" /> |
||||
|
<span> |
||||
|
<a |
||||
|
t-att-data-active-id="line['move_id']" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;" |
||||
|
> |
||||
|
<t t-esc="line['move_name']" /> |
||||
|
</a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-esc="journals_data[line['journal_id']]['code']" /> |
||||
|
</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-esc="accounts_data[account_id]['code']" /> |
||||
|
</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<!-- <span t-if="line.get('partner_id', False)" t-esc="line['partner_id']"/>--> |
||||
|
<span t-esc="line['partner_name']" /> |
||||
|
</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-esc="line['ref_label']" /> |
||||
|
</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-esc="line['date_maturity']" /> |
||||
|
</div> |
||||
|
<!--## amount_total_due--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-if="line.get('original', False)" |
||||
|
t-esc="line['original']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span |
||||
|
t-esc="line['amount_residual']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t t-if="line['currency_id']"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-esc="line['currency_name']" /> |
||||
|
</div> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-esc="line['amount_currency']" /> |
||||
|
</div> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-esc="line['amount_residual_currency']" /> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not line['currency_id']"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell" /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_open_items_ending_cumul"> |
||||
|
<!-- Display ending balance line for account or partner --> |
||||
|
<div class="act_as_table list_table" style="width: 100%;"> |
||||
|
<div class="act_as_row labels" style="font-weight: bold;"> |
||||
|
<!--## date--> |
||||
|
<t t-if='type == "account_type"'> |
||||
|
<div class="act_as_cell first_column" style="width: 36.34%;"> |
||||
|
<span t-esc="accounts_data[account_id]['code']" /> |
||||
|
- |
||||
|
<span t-esc="accounts_data[account_id]['name']" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell right" style="width: 28.66%;"> |
||||
|
Ending |
||||
|
balance |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if='type == "partner_type"'> |
||||
|
<div class="act_as_cell first_column" style="width: 36.34%;" /> |
||||
|
<div class="act_as_cell right" style="width: 28.66%;"> |
||||
|
Partner ending balance |
||||
|
</div> |
||||
|
</t> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 6.47%;" /> |
||||
|
<!--## amount_total_due--> |
||||
|
<div class="act_as_cell amount" style="width: 6.57%;" /> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 6.57%;"> |
||||
|
<t t-if='type == "account_type"'> |
||||
|
<span |
||||
|
t-esc="total_amount[account_id]['residual']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</t> |
||||
|
<t t-if='type == "partner_type"'> |
||||
|
<span |
||||
|
t-esc="total_amount[account_id][partner_id]['residual']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## amount_total_due_currency + amount_residual_currency --> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell" /> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell" /> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
1008
account_financial_report/report/templates/trial_balance.xml
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,195 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="vat_report"> |
||||
|
<t t-call="web.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<t t-call="account_financial_report.internal_layout"> |
||||
|
<t t-call="account_financial_report.report_vat_report_base" /> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_vat_report_base"> |
||||
|
<t t-set="title"> |
||||
|
VAT Report - |
||||
|
<t t-raw="company_name" /> |
||||
|
- |
||||
|
<t t-raw="currency_name" /> |
||||
|
</t> |
||||
|
<t t-set="company_name" t-value="company_name" /> |
||||
|
<div class="page"> |
||||
|
<div class="row"> |
||||
|
<h4 |
||||
|
class="mt0" |
||||
|
t-esc="title or 'Odoo Report'" |
||||
|
style="text-align: center;" |
||||
|
/> |
||||
|
</div> |
||||
|
<!-- Display filters --> |
||||
|
<t t-call="account_financial_report.report_vat_report_filters" /> |
||||
|
<div class="page_break" /> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<!-- Display table headers for lines --> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<!--## code--> |
||||
|
<div class="act_as_cell first_column" style="width: 5%;"> |
||||
|
Code |
||||
|
</div> |
||||
|
<!--## name--> |
||||
|
<div class="act_as_cell" style="width: 65%;">Name</div> |
||||
|
<!--## net--> |
||||
|
<div class="act_as_cell" style="width: 15%;">Net</div> |
||||
|
<!--## tax--> |
||||
|
<div class="act_as_cell" style="width: 15%;">Tax</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<t t-foreach="vat_report" t-as="tag_or_group"> |
||||
|
<div class="act_as_row lines" style="font-weight: bold;"> |
||||
|
<div |
||||
|
class="act_as_cell left oe_tooltip_string" |
||||
|
style="width: 5%;" |
||||
|
> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="res_id"--> |
||||
|
<!-- t-att-data-res-model="res_model"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- t-att-style="style">--> |
||||
|
<t t-att-style="style" t-raw="tag_or_group['code']" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<div |
||||
|
class="act_as_cell left oe_tooltip_string" |
||||
|
style="width: 65%;" |
||||
|
> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="res_id"--> |
||||
|
<!-- t-att-data-res-model="res_model"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- t-att-style="style">--> |
||||
|
<t t-att-style="style" t-raw="tag_or_group['name']" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" style="width: 15%;"> |
||||
|
<!-- <t t-set="domain"--> |
||||
|
<!-- t-value="[('tax_ids', 'in', [tax.tax_id.id for tax in tag.tax_ids]),--> |
||||
|
<!-- ('date', '>=', o.date_from),--> |
||||
|
<!-- ('date', '<=', o.date_to)]"/>--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="domain"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- t-att-style="style">--> |
||||
|
<t |
||||
|
t-att-style="style" |
||||
|
t-raw="tag_or_group['net']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" style="width: 15%;"> |
||||
|
<!-- <t t-set="domain"--> |
||||
|
<!-- t-value="[('tax_line_id', 'in', [tax.tax_id.id for tax in tag.tax_ids]),--> |
||||
|
<!-- ('date', '>=', o.date_from),--> |
||||
|
<!-- ('date', '<=', o.date_to),--> |
||||
|
<!-- ('tax_exigible', '=', True)]"/>--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="domain"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- t-att-style="style">--> |
||||
|
<t |
||||
|
t-att-style="style" |
||||
|
t-raw="tag_or_group['tax']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
</div> |
||||
|
<t t-if="tax_detail"> |
||||
|
<t t-foreach="tag_or_group['taxes']" t-as="tax"> |
||||
|
<div class="act_as_row lines"> |
||||
|
<div class="act_as_cell" style="width: 5%;" /> |
||||
|
<div |
||||
|
class="act_as_cell left oe_tooltip_string" |
||||
|
style="padding-left: 20px; width: 65%;" |
||||
|
> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-active-id="tax.tax_id.id"--> |
||||
|
<!-- t-att-data-res-model="res_model"--> |
||||
|
<!-- class="o_account_financial_reports_web_action"--> |
||||
|
<!-- t-att-style="style">--> |
||||
|
<t t-att-style="style" t-raw="tax['name']" /> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" style="width: 15%;"> |
||||
|
<!-- <t t-set="domain"--> |
||||
|
<!-- t-value="[('tax_ids', 'in', tax.tax_id.ids),--> |
||||
|
<!-- ('date', '>=', o.date_from),--> |
||||
|
<!-- ('date', '<=', o.date_to),--> |
||||
|
<!-- ('tax_exigible', '=', True)]"/>--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="domain"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- t-att-style="style">--> |
||||
|
<t |
||||
|
t-att-style="style" |
||||
|
t-raw="tax['net']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" style="width: 15%;"> |
||||
|
<!-- <t t-set="domain"--> |
||||
|
<!-- t-value="[('tax_line_id', '=', tax.tax_id.id),--> |
||||
|
<!-- ('date', '>=', o.date_from),--> |
||||
|
<!-- ('date', '<=', o.date_to),--> |
||||
|
<!-- ('tax_exigible', '=', True)]"/>--> |
||||
|
<!-- <span>--> |
||||
|
<!-- <a t-att-data-domain="domain"--> |
||||
|
<!-- t-att-data-res-model="'account.move.line'"--> |
||||
|
<!-- class="o_account_financial_reports_web_action_multi"--> |
||||
|
<!-- t-att-style="style">--> |
||||
|
<t |
||||
|
t-att-style="style" |
||||
|
t-raw="tax['tax']" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}" |
||||
|
/> |
||||
|
<!-- </a>--> |
||||
|
<!-- </span>--> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_vat_report_filters"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<div class="act_as_cell">Date From</div> |
||||
|
<div class="act_as_cell">Date To</div> |
||||
|
<div class="act_as_cell">Based On</div> |
||||
|
</div> |
||||
|
<div class="act_as_row"> |
||||
|
<div class="act_as_cell"> |
||||
|
<span t-esc="date_from" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<span t-esc="date_to" /> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<span t-esc="based_on" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,772 @@ |
|||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# © 2018 Forest and Biomass Romania SA |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
|
||||
|
from odoo import api, models |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReport(models.AbstractModel): |
||||
|
_name = "report.account_financial_report.trial_balance" |
||||
|
_description = "Trial Balance Report" |
||||
|
|
||||
|
@api.model |
||||
|
def get_html(self, given_context=None): |
||||
|
return self._get_html() |
||||
|
|
||||
|
def _get_html(self): |
||||
|
result = {} |
||||
|
rcontext = {} |
||||
|
context = dict(self.env.context) |
||||
|
rcontext.update(context.get("data")) |
||||
|
active_id = context.get("active_id") |
||||
|
wiz = self.env["open.items.report.wizard"].browse(active_id) |
||||
|
rcontext["o"] = wiz |
||||
|
result["html"] = self.env.ref( |
||||
|
"account_financial_report.report_trial_balance" |
||||
|
).render(rcontext) |
||||
|
return result |
||||
|
|
||||
|
def _get_accounts_data(self, account_ids): |
||||
|
accounts = self.env["account.account"].browse(account_ids) |
||||
|
accounts_data = {} |
||||
|
for account in accounts: |
||||
|
accounts_data.update( |
||||
|
{ |
||||
|
account.id: { |
||||
|
"id": account.id, |
||||
|
"code": account.code, |
||||
|
"name": account.name, |
||||
|
"group_id": account.group_id.id, |
||||
|
"hide_account": False, |
||||
|
"currency_id": account.currency_id or False, |
||||
|
"currency_name": account.currency_id.name, |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
return accounts_data |
||||
|
|
||||
|
def _get_initial_balances_bs_ml_domain( |
||||
|
self, |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_from, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
): |
||||
|
accounts_domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("user_type_id.include_initial_balance", "=", True), |
||||
|
] |
||||
|
if account_ids: |
||||
|
accounts_domain += [("id", "in", account_ids)] |
||||
|
domain = [("date", "<", date_from)] |
||||
|
accounts = self.env["account.account"].search(accounts_domain) |
||||
|
domain += [("account_id", "in", accounts.ids)] |
||||
|
if company_id: |
||||
|
domain += [("company_id", "=", company_id)] |
||||
|
if journal_ids: |
||||
|
domain += [("journal_id", "in", journal_ids)] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
if show_partner_details: |
||||
|
domain += [("account_id.internal_type", "in", ["receivable", "payable"])] |
||||
|
return domain |
||||
|
|
||||
|
def _get_initial_balances_pl_ml_domain( |
||||
|
self, |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_from, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
fy_start_date, |
||||
|
): |
||||
|
accounts_domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("user_type_id.include_initial_balance", "=", False), |
||||
|
] |
||||
|
if account_ids: |
||||
|
accounts_domain += [("id", "in", account_ids)] |
||||
|
domain = [("date", "<", date_from), ("date", ">=", fy_start_date)] |
||||
|
accounts = self.env["account.account"].search(accounts_domain) |
||||
|
domain += [("account_id", "in", accounts.ids)] |
||||
|
if company_id: |
||||
|
domain += [("company_id", "=", company_id)] |
||||
|
if journal_ids: |
||||
|
domain += [("journal_id", "in", journal_ids)] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
if show_partner_details: |
||||
|
domain += [("account_id.internal_type", "in", ["receivable", "payable"])] |
||||
|
return domain |
||||
|
|
||||
|
@api.model |
||||
|
def _get_period_ml_domain( |
||||
|
self, |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_to, |
||||
|
date_from, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
): |
||||
|
domain = [ |
||||
|
("display_type", "=", False), |
||||
|
("date", ">=", date_from), |
||||
|
("date", "<=", date_to), |
||||
|
] |
||||
|
if company_id: |
||||
|
domain += [("company_id", "=", company_id)] |
||||
|
if account_ids: |
||||
|
domain += [("account_id", "in", account_ids)] |
||||
|
if journal_ids: |
||||
|
domain += [("journal_id", "in", journal_ids)] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
if show_partner_details: |
||||
|
domain += [("account_id.internal_type", "in", ["receivable", "payable"])] |
||||
|
return domain |
||||
|
|
||||
|
def _get_initial_balance_fy_pl_ml_domain( |
||||
|
self, |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
fy_start_date, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
): |
||||
|
accounts_domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("user_type_id.include_initial_balance", "=", False), |
||||
|
] |
||||
|
if account_ids: |
||||
|
accounts_domain += [("id", "in", account_ids)] |
||||
|
domain = [("date", "<", fy_start_date)] |
||||
|
accounts = self.env["account.account"].search(accounts_domain) |
||||
|
domain += [("account_id", "in", accounts.ids)] |
||||
|
if company_id: |
||||
|
domain += [("company_id", "=", company_id)] |
||||
|
if journal_ids: |
||||
|
domain += [("journal_id", "in", journal_ids)] |
||||
|
if partner_ids: |
||||
|
domain += [("partner_id", "in", partner_ids)] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
if show_partner_details: |
||||
|
domain += [("account_id.internal_type", "in", ["receivable", "payable"])] |
||||
|
return domain |
||||
|
|
||||
|
def _get_pl_initial_balance( |
||||
|
self, |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
fy_start_date, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
foreign_currency, |
||||
|
): |
||||
|
domain = self._get_initial_balance_fy_pl_ml_domain( |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
fy_start_date, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
) |
||||
|
initial_balances = self.env["account.move.line"].read_group( |
||||
|
domain=domain, |
||||
|
fields=["account_id", "balance", "amount_currency"], |
||||
|
groupby=["account_id"], |
||||
|
) |
||||
|
pl_initial_balance = 0.0 |
||||
|
pl_initial_currency_balance = 0.0 |
||||
|
for initial_balance in initial_balances: |
||||
|
pl_initial_balance += initial_balance["balance"] |
||||
|
if foreign_currency: |
||||
|
pl_initial_currency_balance += round( |
||||
|
initial_balance["amount_currency"], 2 |
||||
|
) |
||||
|
return pl_initial_balance, pl_initial_currency_balance |
||||
|
|
||||
|
@api.model |
||||
|
def _compute_account_amount( |
||||
|
self, total_amount, tb_initial_acc, tb_period_acc, foreign_currency |
||||
|
): |
||||
|
for tb in tb_period_acc: |
||||
|
acc_id = tb["account_id"][0] |
||||
|
total_amount[acc_id] = {} |
||||
|
total_amount[acc_id]["credit"] = tb["credit"] |
||||
|
total_amount[acc_id]["debit"] = tb["debit"] |
||||
|
total_amount[acc_id]["balance"] = tb["balance"] |
||||
|
total_amount[acc_id]["initial_balance"] = 0.0 |
||||
|
total_amount[acc_id]["ending_balance"] = tb["balance"] |
||||
|
if foreign_currency: |
||||
|
total_amount[acc_id]["initial_currency_balance"] = 0.0 |
||||
|
total_amount[acc_id]["ending_currency_balance"] = round( |
||||
|
tb["amount_currency"], 2 |
||||
|
) |
||||
|
for tb in tb_initial_acc: |
||||
|
acc_id = tb["account_id"] |
||||
|
if acc_id not in total_amount.keys(): |
||||
|
total_amount[acc_id] = {} |
||||
|
total_amount[acc_id]["credit"] = 0.0 |
||||
|
total_amount[acc_id]["debit"] = 0.0 |
||||
|
total_amount[acc_id]["balance"] = 0.0 |
||||
|
total_amount[acc_id]["initial_balance"] = tb["balance"] |
||||
|
total_amount[acc_id]["ending_balance"] = tb["balance"] |
||||
|
if foreign_currency: |
||||
|
total_amount[acc_id]["initial_currency_balance"] = round( |
||||
|
tb["amount_currency"], 2 |
||||
|
) |
||||
|
total_amount[acc_id]["ending_currency_balance"] = round( |
||||
|
tb["amount_currency"], 2 |
||||
|
) |
||||
|
else: |
||||
|
total_amount[acc_id]["initial_balance"] = tb["balance"] |
||||
|
total_amount[acc_id]["ending_balance"] += tb["balance"] |
||||
|
if foreign_currency: |
||||
|
total_amount[acc_id]["initial_currency_balance"] = round( |
||||
|
tb["amount_currency"], 2 |
||||
|
) |
||||
|
total_amount[acc_id]["ending_currency_balance"] += round( |
||||
|
tb["amount_currency"], 2 |
||||
|
) |
||||
|
return total_amount |
||||
|
|
||||
|
@api.model |
||||
|
def _compute_partner_amount( |
||||
|
self, total_amount, tb_initial_prt, tb_period_prt, foreign_currency |
||||
|
): |
||||
|
partners_ids = set() |
||||
|
partners_data = {} |
||||
|
for tb in tb_period_prt: |
||||
|
acc_id = tb["account_id"][0] |
||||
|
if tb["partner_id"]: |
||||
|
prt_id = tb["partner_id"][0] |
||||
|
if tb["partner_id"] not in partners_ids: |
||||
|
partners_data.update( |
||||
|
{prt_id: {"id": prt_id, "name": tb["partner_id"][1]}} |
||||
|
) |
||||
|
total_amount[acc_id][prt_id] = {} |
||||
|
total_amount[acc_id][prt_id]["credit"] = tb["credit"] |
||||
|
total_amount[acc_id][prt_id]["debit"] = tb["debit"] |
||||
|
total_amount[acc_id][prt_id]["balance"] = tb["balance"] |
||||
|
total_amount[acc_id][prt_id]["initial_balance"] = 0.0 |
||||
|
total_amount[acc_id][prt_id]["ending_balance"] = tb["balance"] |
||||
|
if foreign_currency: |
||||
|
total_amount[acc_id][prt_id]["initial_currency_balance"] = 0.0 |
||||
|
total_amount[acc_id][prt_id]["ending_currency_balance"] = round( |
||||
|
tb["amount_currency"], 2 |
||||
|
) |
||||
|
partners_ids.add(tb["partner_id"]) |
||||
|
for tb in tb_initial_prt: |
||||
|
acc_id = tb["account_id"][0] |
||||
|
if tb["partner_id"]: |
||||
|
prt_id = tb["partner_id"][0] |
||||
|
if tb["partner_id"] not in partners_ids: |
||||
|
partners_data.update( |
||||
|
{prt_id: {"id": prt_id, "name": tb["partner_id"][1]}} |
||||
|
) |
||||
|
if acc_id not in total_amount.keys(): |
||||
|
total_amount[acc_id][prt_id] = {} |
||||
|
total_amount[acc_id][prt_id]["credit"] = 0.0 |
||||
|
total_amount[acc_id][prt_id]["debit"] = 0.0 |
||||
|
total_amount[acc_id][prt_id]["balance"] = 0.0 |
||||
|
total_amount[acc_id][prt_id]["initial_balance"] = tb["balance"] |
||||
|
total_amount[acc_id][prt_id]["ending_balance"] = tb["balance"] |
||||
|
if foreign_currency: |
||||
|
total_amount[acc_id][prt_id][ |
||||
|
"initial_currency_balance" |
||||
|
] = round(tb["amount_currency"], 2) |
||||
|
total_amount[acc_id][prt_id]["ending_currency_balance"] = round( |
||||
|
tb["amount_currency"], 2 |
||||
|
) |
||||
|
partners_ids.add(tb["partner_id"]) |
||||
|
elif prt_id not in total_amount[acc_id].keys(): |
||||
|
total_amount[acc_id][prt_id] = {} |
||||
|
total_amount[acc_id][prt_id]["credit"] = 0.0 |
||||
|
total_amount[acc_id][prt_id]["debit"] = 0.0 |
||||
|
total_amount[acc_id][prt_id]["balance"] = 0.0 |
||||
|
total_amount[acc_id][prt_id]["initial_balance"] = tb["balance"] |
||||
|
total_amount[acc_id][prt_id]["ending_balance"] = tb["balance"] |
||||
|
if foreign_currency: |
||||
|
total_amount[acc_id][prt_id][ |
||||
|
"initial_currency_balance" |
||||
|
] = round(tb["amount_currency"], 2) |
||||
|
total_amount[acc_id][prt_id]["ending_currency_balance"] = round( |
||||
|
tb["amount_currency"], 2 |
||||
|
) |
||||
|
partners_ids.add(tb["partner_id"]) |
||||
|
else: |
||||
|
total_amount[acc_id][prt_id]["initial_balance"] += tb["balance"] |
||||
|
total_amount[acc_id][prt_id]["ending_balance"] += tb["balance"] |
||||
|
if foreign_currency: |
||||
|
total_amount[acc_id][prt_id][ |
||||
|
"initial_currency_balance" |
||||
|
] += round(tb["amount_currency"], 2) |
||||
|
total_amount[acc_id][prt_id][ |
||||
|
"ending_currency_balance" |
||||
|
] += round(tb["amount_currency"], 2) |
||||
|
return total_amount, partners_data |
||||
|
|
||||
|
@api.model |
||||
|
def _get_data( |
||||
|
self, |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_to, |
||||
|
date_from, |
||||
|
foreign_currency, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
hide_account_at_0, |
||||
|
unaffected_earnings_account, |
||||
|
fy_start_date, |
||||
|
): |
||||
|
accounts_domain = [("company_id", "=", company_id)] |
||||
|
if account_ids: |
||||
|
accounts_domain += [("id", "in", account_ids)] |
||||
|
accounts = self.env["account.account"].search(accounts_domain) |
||||
|
tb_initial_acc = [] |
||||
|
for account in accounts: |
||||
|
tb_initial_acc.append( |
||||
|
{"account_id": account.id, "balance": 0.0, "amount_currency": 0.0} |
||||
|
) |
||||
|
initial_domain_bs = self._get_initial_balances_bs_ml_domain( |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_from, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
) |
||||
|
tb_initial_acc_bs = self.env["account.move.line"].read_group( |
||||
|
domain=initial_domain_bs, |
||||
|
fields=["account_id", "balance", "amount_currency"], |
||||
|
groupby=["account_id"], |
||||
|
) |
||||
|
initial_domain_pl = self._get_initial_balances_pl_ml_domain( |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_from, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
fy_start_date, |
||||
|
) |
||||
|
tb_initial_acc_pl = self.env["account.move.line"].read_group( |
||||
|
domain=initial_domain_pl, |
||||
|
fields=["account_id", "balance", "amount_currency"], |
||||
|
groupby=["account_id"], |
||||
|
) |
||||
|
tb_initial_acc_rg = tb_initial_acc_bs + tb_initial_acc_pl |
||||
|
for account_rg in tb_initial_acc_rg: |
||||
|
element = list( |
||||
|
filter( |
||||
|
lambda acc_dict: acc_dict["account_id"] |
||||
|
== account_rg["account_id"][0], |
||||
|
tb_initial_acc, |
||||
|
) |
||||
|
) |
||||
|
if element: |
||||
|
element[0]["balance"] += account_rg["balance"] |
||||
|
element[0]["amount_currency"] += account_rg["amount_currency"] |
||||
|
if hide_account_at_0: |
||||
|
tb_initial_acc = [p for p in tb_initial_acc if p["balance"] != 0] |
||||
|
|
||||
|
period_domain = self._get_period_ml_domain( |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_to, |
||||
|
date_from, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
) |
||||
|
tb_period_acc = self.env["account.move.line"].read_group( |
||||
|
domain=period_domain, |
||||
|
fields=["account_id", "debit", "credit", "balance", "amount_currency"], |
||||
|
groupby=["account_id"], |
||||
|
) |
||||
|
|
||||
|
if show_partner_details: |
||||
|
tb_initial_prt_bs = self.env["account.move.line"].read_group( |
||||
|
domain=initial_domain_bs, |
||||
|
fields=["account_id", "partner_id", "balance", "amount_currency"], |
||||
|
groupby=["account_id", "partner_id"], |
||||
|
lazy=False, |
||||
|
) |
||||
|
tb_initial_prt_pl = self.env["account.move.line"].read_group( |
||||
|
domain=initial_domain_pl, |
||||
|
fields=["account_id", "partner_id", "balance", "amount_currency"], |
||||
|
groupby=["account_id", "partner_id"], |
||||
|
) |
||||
|
tb_initial_prt = tb_initial_prt_bs + tb_initial_prt_pl |
||||
|
if hide_account_at_0: |
||||
|
tb_initial_prt = [p for p in tb_initial_prt if p["balance"] != 0] |
||||
|
tb_period_prt = self.env["account.move.line"].read_group( |
||||
|
domain=period_domain, |
||||
|
fields=[ |
||||
|
"account_id", |
||||
|
"partner_id", |
||||
|
"debit", |
||||
|
"credit", |
||||
|
"balance", |
||||
|
"amount_currency", |
||||
|
], |
||||
|
groupby=["account_id", "partner_id"], |
||||
|
lazy=False, |
||||
|
) |
||||
|
total_amount = {} |
||||
|
partners_data = [] |
||||
|
total_amount = self._compute_account_amount( |
||||
|
total_amount, tb_initial_acc, tb_period_acc, foreign_currency |
||||
|
) |
||||
|
if show_partner_details: |
||||
|
total_amount, partners_data = self._compute_partner_amount( |
||||
|
total_amount, tb_initial_prt, tb_period_prt, foreign_currency |
||||
|
) |
||||
|
accounts_ids = list(total_amount.keys()) |
||||
|
unaffected_id = unaffected_earnings_account |
||||
|
if unaffected_id not in accounts_ids: |
||||
|
accounts_ids.append(unaffected_id) |
||||
|
total_amount[unaffected_id] = {} |
||||
|
total_amount[unaffected_id]["initial_balance"] = 0.0 |
||||
|
total_amount[unaffected_id]["balance"] = 0.0 |
||||
|
total_amount[unaffected_id]["credit"] = 0.0 |
||||
|
total_amount[unaffected_id]["debit"] = 0.0 |
||||
|
total_amount[unaffected_id]["ending_balance"] = 0.0 |
||||
|
if foreign_currency: |
||||
|
total_amount[unaffected_id]["initial_currency_balance"] = 0.0 |
||||
|
total_amount[unaffected_id]["ending_currency_balance"] = 0.0 |
||||
|
accounts_data = self._get_accounts_data(accounts_ids) |
||||
|
pl_initial_balance, pl_initial_currency_balance = self._get_pl_initial_balance( |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
fy_start_date, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
foreign_currency, |
||||
|
) |
||||
|
total_amount[unaffected_id]["ending_balance"] += pl_initial_balance |
||||
|
total_amount[unaffected_id]["initial_balance"] += pl_initial_balance |
||||
|
if foreign_currency: |
||||
|
total_amount[unaffected_id][ |
||||
|
"ending_currency_balance" |
||||
|
] += pl_initial_currency_balance |
||||
|
total_amount[unaffected_id][ |
||||
|
"initial_currency_balance" |
||||
|
] += pl_initial_currency_balance |
||||
|
return total_amount, accounts_data, partners_data |
||||
|
|
||||
|
def _get_hierarchy_groups( |
||||
|
self, group_ids, groups_data, old_groups_ids, foreign_currency |
||||
|
): |
||||
|
new_parents = False |
||||
|
for group_id in group_ids: |
||||
|
if groups_data[group_id]["parent_id"]: |
||||
|
new_parents = True |
||||
|
nw_id = groups_data[group_id]["parent_id"] |
||||
|
if nw_id in groups_data.keys(): |
||||
|
groups_data[nw_id]["initial_balance"] += groups_data[group_id][ |
||||
|
"initial_balance" |
||||
|
] |
||||
|
groups_data[nw_id]["debit"] += groups_data[group_id]["debit"] |
||||
|
groups_data[nw_id]["credit"] += groups_data[group_id]["credit"] |
||||
|
groups_data[nw_id]["balance"] += groups_data[group_id]["balance"] |
||||
|
groups_data[nw_id]["ending_balance"] += groups_data[group_id][ |
||||
|
"ending_balance" |
||||
|
] |
||||
|
if foreign_currency: |
||||
|
groups_data[nw_id]["initial_currency_balance"] += groups_data[ |
||||
|
group_id |
||||
|
]["initial_currency_balance"] |
||||
|
groups_data[nw_id]["ending_currency_balance"] += groups_data[ |
||||
|
group_id |
||||
|
]["ending_currency_balance"] |
||||
|
else: |
||||
|
groups_data[nw_id] = {} |
||||
|
groups_data[nw_id]["initial_balance"] = groups_data[group_id][ |
||||
|
"initial_balance" |
||||
|
] |
||||
|
groups_data[nw_id]["debit"] = groups_data[group_id]["debit"] |
||||
|
groups_data[nw_id]["credit"] = groups_data[group_id]["credit"] |
||||
|
groups_data[nw_id]["balance"] = groups_data[group_id]["balance"] |
||||
|
groups_data[nw_id]["ending_balance"] = groups_data[group_id][ |
||||
|
"ending_balance" |
||||
|
] |
||||
|
if foreign_currency: |
||||
|
groups_data[nw_id]["initial_currency_balance"] = groups_data[ |
||||
|
group_id |
||||
|
]["initial_currency_balance"] |
||||
|
groups_data[nw_id]["ending_currency_balance"] = groups_data[ |
||||
|
group_id |
||||
|
]["ending_currency_balance"] |
||||
|
if new_parents: |
||||
|
nw_groups_ids = [] |
||||
|
for group_id in list(groups_data.keys()): |
||||
|
if group_id not in old_groups_ids: |
||||
|
nw_groups_ids.append(group_id) |
||||
|
old_groups_ids.append(group_id) |
||||
|
groups = self.env["account.group"].browse(nw_groups_ids) |
||||
|
for group in groups: |
||||
|
groups_data[group.id].update( |
||||
|
{ |
||||
|
"id": group.id, |
||||
|
"code": group.code_prefix_start, |
||||
|
"name": group.name, |
||||
|
"parent_id": group.parent_id.id, |
||||
|
"parent_path": group.parent_path, |
||||
|
"complete_code": group.complete_code, |
||||
|
"account_ids": group.compute_account_ids.ids, |
||||
|
"type": "group_type", |
||||
|
} |
||||
|
) |
||||
|
groups_data = self._get_hierarchy_groups( |
||||
|
nw_groups_ids, groups_data, old_groups_ids, foreign_currency |
||||
|
) |
||||
|
return groups_data |
||||
|
|
||||
|
def _get_groups_data(self, accounts_data, total_amount, foreign_currency): |
||||
|
accounts_ids = list(accounts_data.keys()) |
||||
|
accounts = self.env["account.account"].browse(accounts_ids) |
||||
|
account_group_relation = {} |
||||
|
for account in accounts: |
||||
|
accounts_data[account.id]["complete_code"] = ( |
||||
|
account.group_id.complete_code if account.group_id.id else "" |
||||
|
) |
||||
|
if account.group_id.id: |
||||
|
if account.group_id.id not in account_group_relation.keys(): |
||||
|
account_group_relation.update({account.group_id.id: [account.id]}) |
||||
|
else: |
||||
|
account_group_relation[account.group_id.id].append(account.id) |
||||
|
groups = self.env["account.group"].browse(account_group_relation.keys()) |
||||
|
groups_data = {} |
||||
|
for group in groups: |
||||
|
groups_data.update( |
||||
|
{ |
||||
|
group.id: { |
||||
|
"id": group.id, |
||||
|
"code": group.code_prefix_start, |
||||
|
"name": group.name, |
||||
|
"parent_id": group.parent_id.id, |
||||
|
"parent_path": group.parent_path, |
||||
|
"type": "group_type", |
||||
|
"complete_code": group.complete_code, |
||||
|
"account_ids": group.compute_account_ids.ids, |
||||
|
"initial_balance": 0.0, |
||||
|
"credit": 0.0, |
||||
|
"debit": 0.0, |
||||
|
"balance": 0.0, |
||||
|
"ending_balance": 0.0, |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency: |
||||
|
groups_data[group.id]["initial_currency_balance"] = 0.0 |
||||
|
groups_data[group.id]["ending_currency_balance"] = 0.0 |
||||
|
for group_id in account_group_relation.keys(): |
||||
|
for account_id in account_group_relation[group_id]: |
||||
|
groups_data[group_id]["initial_balance"] += total_amount[account_id][ |
||||
|
"initial_balance" |
||||
|
] |
||||
|
groups_data[group_id]["debit"] += total_amount[account_id]["debit"] |
||||
|
groups_data[group_id]["credit"] += total_amount[account_id]["credit"] |
||||
|
groups_data[group_id]["balance"] += total_amount[account_id]["balance"] |
||||
|
groups_data[group_id]["ending_balance"] += total_amount[account_id][ |
||||
|
"ending_balance" |
||||
|
] |
||||
|
if foreign_currency: |
||||
|
groups_data[group_id]["initial_currency_balance"] += total_amount[ |
||||
|
account_id |
||||
|
]["initial_currency_balance"] |
||||
|
groups_data[group_id]["ending_currency_balance"] += total_amount[ |
||||
|
account_id |
||||
|
]["ending_currency_balance"] |
||||
|
group_ids = list(groups_data.keys()) |
||||
|
old_group_ids = list(groups_data.keys()) |
||||
|
groups_data = self._get_hierarchy_groups( |
||||
|
group_ids, groups_data, old_group_ids, foreign_currency |
||||
|
) |
||||
|
return groups_data |
||||
|
|
||||
|
def _get_computed_groups_data(self, accounts_data, total_amount, foreign_currency): |
||||
|
groups = self.env["account.group"].search([("id", "!=", False)]) |
||||
|
groups_data = {} |
||||
|
for group in groups: |
||||
|
len_group_code = len(group.code_prefix_start) |
||||
|
groups_data.update( |
||||
|
{ |
||||
|
group.id: { |
||||
|
"id": group.id, |
||||
|
"code": group.code_prefix_start, |
||||
|
"name": group.name, |
||||
|
"parent_id": group.parent_id.id, |
||||
|
"parent_path": group.parent_path, |
||||
|
"type": "group_type", |
||||
|
"complete_code": group.complete_code, |
||||
|
"account_ids": group.compute_account_ids.ids, |
||||
|
"initial_balance": 0.0, |
||||
|
"credit": 0.0, |
||||
|
"debit": 0.0, |
||||
|
"balance": 0.0, |
||||
|
"ending_balance": 0.0, |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency: |
||||
|
groups_data[group.id]["initial_currency_balance"] = 0.0 |
||||
|
groups_data[group.id]["ending_currency_balance"] = 0.0 |
||||
|
for account in accounts_data.values(): |
||||
|
if group.code_prefix_start == account["code"][:len_group_code]: |
||||
|
acc_id = account["id"] |
||||
|
group_id = group.id |
||||
|
groups_data[group_id]["initial_balance"] += total_amount[acc_id][ |
||||
|
"initial_balance" |
||||
|
] |
||||
|
groups_data[group_id]["debit"] += total_amount[acc_id]["debit"] |
||||
|
groups_data[group_id]["credit"] += total_amount[acc_id]["credit"] |
||||
|
groups_data[group_id]["balance"] += total_amount[acc_id]["balance"] |
||||
|
groups_data[group_id]["ending_balance"] += total_amount[acc_id][ |
||||
|
"ending_balance" |
||||
|
] |
||||
|
if foreign_currency: |
||||
|
groups_data[group_id][ |
||||
|
"initial_currency_balance" |
||||
|
] += total_amount[acc_id]["initial_currency_balance"] |
||||
|
groups_data[group_id][ |
||||
|
"ending_currency_balance" |
||||
|
] += total_amount[acc_id]["ending_currency_balance"] |
||||
|
return groups_data |
||||
|
|
||||
|
def _get_report_values(self, docids, data): |
||||
|
show_partner_details = data["show_partner_details"] |
||||
|
wizard_id = data["wizard_id"] |
||||
|
company = self.env["res.company"].browse(data["company_id"]) |
||||
|
company_id = data["company_id"] |
||||
|
partner_ids = data["partner_ids"] |
||||
|
journal_ids = data["journal_ids"] |
||||
|
account_ids = data["account_ids"] |
||||
|
date_to = data["date_to"] |
||||
|
date_from = data["date_from"] |
||||
|
hide_account_at_0 = data["hide_account_at_0"] |
||||
|
hierarchy_on = data["hierarchy_on"] |
||||
|
show_hierarchy_level = data["show_hierarchy_level"] |
||||
|
foreign_currency = data["foreign_currency"] |
||||
|
only_posted_moves = data["only_posted_moves"] |
||||
|
unaffected_earnings_account = data["unaffected_earnings_account"] |
||||
|
fy_start_date = data["fy_start_date"] |
||||
|
total_amount, accounts_data, partners_data = self._get_data( |
||||
|
account_ids, |
||||
|
journal_ids, |
||||
|
partner_ids, |
||||
|
company_id, |
||||
|
date_to, |
||||
|
date_from, |
||||
|
foreign_currency, |
||||
|
only_posted_moves, |
||||
|
show_partner_details, |
||||
|
hide_account_at_0, |
||||
|
unaffected_earnings_account, |
||||
|
fy_start_date, |
||||
|
) |
||||
|
trial_balance = [] |
||||
|
if not show_partner_details: |
||||
|
for account_id in accounts_data.keys(): |
||||
|
accounts_data[account_id].update( |
||||
|
{ |
||||
|
"initial_balance": total_amount[account_id]["initial_balance"], |
||||
|
"credit": total_amount[account_id]["credit"], |
||||
|
"debit": total_amount[account_id]["debit"], |
||||
|
"balance": total_amount[account_id]["balance"], |
||||
|
"ending_balance": total_amount[account_id]["ending_balance"], |
||||
|
"type": "account_type", |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency: |
||||
|
accounts_data[account_id].update( |
||||
|
{ |
||||
|
"ending_currency_balance": total_amount[account_id][ |
||||
|
"ending_currency_balance" |
||||
|
], |
||||
|
"initial_currency_balance": total_amount[account_id][ |
||||
|
"initial_currency_balance" |
||||
|
], |
||||
|
} |
||||
|
) |
||||
|
if hierarchy_on == "relation": |
||||
|
groups_data = self._get_groups_data( |
||||
|
accounts_data, total_amount, foreign_currency |
||||
|
) |
||||
|
trial_balance = list(groups_data.values()) |
||||
|
trial_balance += list(accounts_data.values()) |
||||
|
trial_balance = sorted(trial_balance, key=lambda k: k["complete_code"]) |
||||
|
for trial in trial_balance: |
||||
|
counter = trial["complete_code"].count("/") |
||||
|
trial["level"] = counter |
||||
|
if hierarchy_on == "computed": |
||||
|
groups_data = self._get_computed_groups_data( |
||||
|
accounts_data, total_amount, foreign_currency |
||||
|
) |
||||
|
trial_balance = list(groups_data.values()) |
||||
|
trial_balance += list(accounts_data.values()) |
||||
|
trial_balance = sorted(trial_balance, key=lambda k: k["code"]) |
||||
|
if hierarchy_on == "none": |
||||
|
trial_balance = list(accounts_data.values()) |
||||
|
trial_balance = sorted(trial_balance, key=lambda k: k["code"]) |
||||
|
else: |
||||
|
if foreign_currency: |
||||
|
for account_id in accounts_data.keys(): |
||||
|
total_amount[account_id]["currency_id"] = accounts_data[account_id][ |
||||
|
"currency_id" |
||||
|
] |
||||
|
total_amount[account_id]["currency_name"] = accounts_data[ |
||||
|
account_id |
||||
|
]["currency_name"] |
||||
|
return { |
||||
|
"doc_ids": [wizard_id], |
||||
|
"doc_model": "trial.balance.report.wizard", |
||||
|
"docs": self.env["trial.balance.report.wizard"].browse(wizard_id), |
||||
|
"foreign_currency": data["foreign_currency"], |
||||
|
"company_name": company.display_name, |
||||
|
"company_currency": company.currency_id, |
||||
|
"currency_name": company.currency_id.name, |
||||
|
"date_from": data["date_from"], |
||||
|
"date_to": data["date_to"], |
||||
|
"only_posted_moves": data["only_posted_moves"], |
||||
|
"hide_account_at_0": data["hide_account_at_0"], |
||||
|
"show_partner_details": data["show_partner_details"], |
||||
|
"limit_hierarchy_level": data["limit_hierarchy_level"], |
||||
|
"hierarchy_on": hierarchy_on, |
||||
|
"trial_balance": trial_balance, |
||||
|
"total_amount": total_amount, |
||||
|
"accounts_data": accounts_data, |
||||
|
"partners_data": partners_data, |
||||
|
"show_hierarchy_level": show_hierarchy_level, |
||||
|
} |
@ -0,0 +1,323 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2021 Tecnativa - João Marques |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
|
||||
|
from odoo import _, models |
||||
|
|
||||
|
|
||||
|
class TrialBalanceXslx(models.AbstractModel): |
||||
|
_name = "report.a_f_r.report_trial_balance_xlsx" |
||||
|
_description = "Trial Balance XLSX Report" |
||||
|
_inherit = "report.account_financial_report.abstract_report_xlsx" |
||||
|
|
||||
|
def _get_report_name(self, report, data=False): |
||||
|
company_id = data.get("company_id", False) |
||||
|
report_name = _("Trial Balance") |
||||
|
if company_id: |
||||
|
company = self.env["res.company"].browse(company_id) |
||||
|
suffix = " - {} - {}".format(company.name, company.currency_id.name) |
||||
|
report_name = report_name + suffix |
||||
|
return report_name |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
if not report.show_partner_details: |
||||
|
res = { |
||||
|
0: {"header": _("Code"), "field": "code", "width": 10}, |
||||
|
1: {"header": _("Account"), "field": "name", "width": 60}, |
||||
|
2: { |
||||
|
"header": _("Initial balance"), |
||||
|
"field": "initial_balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
3: { |
||||
|
"header": _("Debit"), |
||||
|
"field": "debit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
4: { |
||||
|
"header": _("Credit"), |
||||
|
"field": "credit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
5: { |
||||
|
"header": _("Period balance"), |
||||
|
"field": "balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
6: { |
||||
|
"header": _("Ending balance"), |
||||
|
"field": "ending_balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
if report.foreign_currency: |
||||
|
foreign_currency = { |
||||
|
7: { |
||||
|
"header": _("Cur."), |
||||
|
"field": "currency_id", |
||||
|
"field_currency_balance": "currency_id", |
||||
|
"type": "many2one", |
||||
|
"width": 7, |
||||
|
}, |
||||
|
8: { |
||||
|
"header": _("Initial balance"), |
||||
|
"field": "initial_currency_balance", |
||||
|
"type": "amount_currency", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
9: { |
||||
|
"header": _("Ending balance"), |
||||
|
"field": "ending_currency_balance", |
||||
|
"type": "amount_currency", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
res = {**res, **foreign_currency} |
||||
|
return res |
||||
|
else: |
||||
|
res = { |
||||
|
0: {"header": _("Partner"), "field": "name", "width": 70}, |
||||
|
1: { |
||||
|
"header": _("Initial balance"), |
||||
|
"field": "initial_balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
2: { |
||||
|
"header": _("Debit"), |
||||
|
"field": "debit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
3: { |
||||
|
"header": _("Credit"), |
||||
|
"field": "credit", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
4: { |
||||
|
"header": _("Period balance"), |
||||
|
"field": "balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
5: { |
||||
|
"header": _("Ending balance"), |
||||
|
"field": "ending_balance", |
||||
|
"type": "amount", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
if report.foreign_currency: |
||||
|
foreign_currency = { |
||||
|
6: { |
||||
|
"header": _("Cur."), |
||||
|
"field": "currency_id", |
||||
|
"field_currency_balance": "currency_id", |
||||
|
"type": "many2one", |
||||
|
"width": 7, |
||||
|
}, |
||||
|
7: { |
||||
|
"header": _("Initial balance"), |
||||
|
"field": "initial_currency_balance", |
||||
|
"type": "amount_currency", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
8: { |
||||
|
"header": _("Ending balance"), |
||||
|
"field": "ending_currency_balance", |
||||
|
"type": "amount_currency", |
||||
|
"width": 14, |
||||
|
}, |
||||
|
} |
||||
|
res = {**res, **foreign_currency} |
||||
|
return res |
||||
|
|
||||
|
def _get_report_filters(self, report): |
||||
|
return [ |
||||
|
[ |
||||
|
_("Date range filter"), |
||||
|
_("From: %s To: %s") % (report.date_from, report.date_to), |
||||
|
], |
||||
|
[ |
||||
|
_("Target moves filter"), |
||||
|
_("All posted entries") |
||||
|
if report.target_move == "all" |
||||
|
else _("All entries"), |
||||
|
], |
||||
|
[ |
||||
|
_("Account at 0 filter"), |
||||
|
_("Hide") if report.hide_account_at_0 else _("Show"), |
||||
|
], |
||||
|
[ |
||||
|
_("Show foreign currency"), |
||||
|
_("Yes") if report.foreign_currency else _("No"), |
||||
|
], |
||||
|
[ |
||||
|
_("Limit hierarchy levels"), |
||||
|
_("Level %s" % report.show_hierarchy_level) |
||||
|
if report.limit_hierarchy_level |
||||
|
else _("No limit"), |
||||
|
], |
||||
|
] |
||||
|
|
||||
|
def _get_col_count_filter_name(self): |
||||
|
return 2 |
||||
|
|
||||
|
def _get_col_count_filter_value(self): |
||||
|
return 3 |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report, data, report_data): |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.trial_balance" |
||||
|
]._get_report_values(report, data) |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
total_amount = res_data["total_amount"] |
||||
|
partners_data = res_data["partners_data"] |
||||
|
accounts_data = res_data["accounts_data"] |
||||
|
hierarchy_on = res_data["hierarchy_on"] |
||||
|
show_partner_details = res_data["show_partner_details"] |
||||
|
show_hierarchy_level = res_data["show_hierarchy_level"] |
||||
|
foreign_currency = res_data["foreign_currency"] |
||||
|
limit_hierarchy_level = res_data["limit_hierarchy_level"] |
||||
|
if not show_partner_details: |
||||
|
# Display array header for account lines |
||||
|
self.write_array_header(report_data) |
||||
|
|
||||
|
# For each account |
||||
|
if not show_partner_details: |
||||
|
for balance in trial_balance: |
||||
|
if hierarchy_on == "relation": |
||||
|
if limit_hierarchy_level: |
||||
|
if show_hierarchy_level > balance["level"]: |
||||
|
# Display account lines |
||||
|
self.write_line_from_dict(balance, report_data) |
||||
|
else: |
||||
|
self.write_line_from_dict(balance, report_data) |
||||
|
elif hierarchy_on == "computed": |
||||
|
if balance["type"] == "account_type": |
||||
|
if limit_hierarchy_level: |
||||
|
if show_hierarchy_level > balance["level"]: |
||||
|
# Display account lines |
||||
|
self.write_line_from_dict(balance, report_data) |
||||
|
else: |
||||
|
self.write_line_from_dict(balance, report_data) |
||||
|
else: |
||||
|
self.write_line_from_dict(balance, report_data) |
||||
|
else: |
||||
|
for account_id in total_amount: |
||||
|
# Write account title |
||||
|
self.write_array_title( |
||||
|
accounts_data[account_id]["code"] |
||||
|
+ "- " |
||||
|
+ accounts_data[account_id]["name"], |
||||
|
report_data, |
||||
|
) |
||||
|
# Display array header for partner lines |
||||
|
self.write_array_header(report_data) |
||||
|
|
||||
|
# For each partner |
||||
|
for partner_id in total_amount[account_id]: |
||||
|
if isinstance(partner_id, int): |
||||
|
# Display partner lines |
||||
|
self.write_line_from_dict_order( |
||||
|
total_amount[account_id][partner_id], |
||||
|
partners_data[partner_id], |
||||
|
report_data, |
||||
|
) |
||||
|
|
||||
|
# Display account footer line |
||||
|
accounts_data[account_id].update( |
||||
|
{ |
||||
|
"initial_balance": total_amount[account_id]["initial_balance"], |
||||
|
"credit": total_amount[account_id]["credit"], |
||||
|
"debit": total_amount[account_id]["debit"], |
||||
|
"balance": total_amount[account_id]["balance"], |
||||
|
"ending_balance": total_amount[account_id]["ending_balance"], |
||||
|
} |
||||
|
) |
||||
|
if foreign_currency: |
||||
|
accounts_data[account_id].update( |
||||
|
{ |
||||
|
"initial_currency_balance": total_amount[account_id][ |
||||
|
"initial_currency_balance" |
||||
|
], |
||||
|
"ending_currency_balance": total_amount[account_id][ |
||||
|
"ending_currency_balance" |
||||
|
], |
||||
|
} |
||||
|
) |
||||
|
self.write_account_footer( |
||||
|
accounts_data[account_id], |
||||
|
accounts_data[account_id]["code"] |
||||
|
+ "- " |
||||
|
+ accounts_data[account_id]["name"], |
||||
|
report_data, |
||||
|
) |
||||
|
|
||||
|
# Line break |
||||
|
report_data["row_pos"] += 2 |
||||
|
|
||||
|
def write_line_from_dict_order(self, total_amount, partner_data, report_data): |
||||
|
total_amount.update({"name": str(partner_data["name"])}) |
||||
|
self.write_line_from_dict(total_amount, report_data) |
||||
|
|
||||
|
def write_line(self, line_object, type_object, report_data): |
||||
|
"""Write a line on current line using all defined columns field name. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
if type_object == "partner": |
||||
|
line_object.currency_id = line_object.report_account_id.currency_id |
||||
|
elif type_object == "account": |
||||
|
line_object.currency_id = line_object.currency_id |
||||
|
super(TrialBalanceXslx, self).write_line(line_object, report_data) |
||||
|
|
||||
|
def write_account_footer(self, account, name_value, report_data): |
||||
|
"""Specific function to write account footer for Trial Balance""" |
||||
|
format_amt = self._get_currency_amt_header_format_dict(account, report_data) |
||||
|
for col_pos, column in report_data["columns"].items(): |
||||
|
if column["field"] == "name": |
||||
|
value = name_value |
||||
|
else: |
||||
|
value = account[column["field"]] |
||||
|
cell_type = column.get("type", "string") |
||||
|
if cell_type == "string": |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value or "", |
||||
|
report_data["formats"]["format_header_left"], |
||||
|
) |
||||
|
elif cell_type == "amount": |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
float(value), |
||||
|
report_data["formats"]["format_header_amount"], |
||||
|
) |
||||
|
elif cell_type == "many2one" and account["currency_id"]: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
value.name or "", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
elif cell_type == "amount_currency" and account["currency_id"]: |
||||
|
report_data["sheet"].write_number( |
||||
|
report_data["row_pos"], col_pos, float(value), format_amt |
||||
|
) |
||||
|
else: |
||||
|
report_data["sheet"].write_string( |
||||
|
report_data["row_pos"], |
||||
|
col_pos, |
||||
|
"", |
||||
|
report_data["formats"]["format_header_right"], |
||||
|
) |
||||
|
report_data["row_pos"] += 1 |
@ -0,0 +1,235 @@ |
|||||
|
# Copyright 2018 Forest and Biomass Romania |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import operator |
||||
|
|
||||
|
from odoo import api, models |
||||
|
|
||||
|
|
||||
|
class VATReport(models.AbstractModel): |
||||
|
_name = "report.account_financial_report.vat_report" |
||||
|
_description = "Vat Report Report" |
||||
|
|
||||
|
def _get_tax_data(self, tax_ids): |
||||
|
taxes = self.env["account.tax"].browse(tax_ids) |
||||
|
tax_data = {} |
||||
|
for tax in taxes: |
||||
|
tax_data.update( |
||||
|
{ |
||||
|
tax.id: { |
||||
|
"id": tax.id, |
||||
|
"name": tax.name, |
||||
|
"tax_group_id": tax.tax_group_id.id, |
||||
|
"type_tax_use": tax.type_tax_use, |
||||
|
"amount_type": tax.amount_type, |
||||
|
"tags_ids": tax.invoice_repartition_line_ids.tag_ids.ids, |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
return tax_data |
||||
|
|
||||
|
@api.model |
||||
|
def _get_tax_report_domain(self, company_id, date_from, date_to, only_posted_moves): |
||||
|
domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("date", ">=", date_from), |
||||
|
("date", "<=", date_to), |
||||
|
("tax_line_id", "!=", False), |
||||
|
("tax_exigible", "=", True), |
||||
|
] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
return domain |
||||
|
|
||||
|
@api.model |
||||
|
def _get_net_report_domain(self, company_id, date_from, date_to, only_posted_moves): |
||||
|
domain = [ |
||||
|
("company_id", "=", company_id), |
||||
|
("date", ">=", date_from), |
||||
|
("date", "<=", date_to), |
||||
|
("tax_exigible", "=", True), |
||||
|
] |
||||
|
if only_posted_moves: |
||||
|
domain += [("move_id.state", "=", "posted")] |
||||
|
return domain |
||||
|
|
||||
|
def _get_vat_report_data(self, company_id, date_from, date_to, only_posted_moves): |
||||
|
tax_domain = self._get_tax_report_domain( |
||||
|
company_id, date_from, date_to, only_posted_moves |
||||
|
) |
||||
|
ml_fields = [ |
||||
|
"id", |
||||
|
"tax_base_amount", |
||||
|
"balance", |
||||
|
"tax_line_id", |
||||
|
"tax_ids", |
||||
|
"analytic_tag_ids", |
||||
|
] |
||||
|
tax_move_lines = self.env["account.move.line"].search_read( |
||||
|
domain=tax_domain, |
||||
|
fields=ml_fields, |
||||
|
) |
||||
|
net_domain = self._get_net_report_domain( |
||||
|
company_id, date_from, date_to, only_posted_moves |
||||
|
) |
||||
|
taxed_move_lines = self.env["account.move.line"].search_read( |
||||
|
domain=net_domain, |
||||
|
fields=ml_fields, |
||||
|
) |
||||
|
taxed_move_lines = list(filter(lambda d: d["tax_ids"], taxed_move_lines)) |
||||
|
vat_data = [] |
||||
|
for tax_move_line in tax_move_lines: |
||||
|
vat_data.append( |
||||
|
{ |
||||
|
"net": 0.0, |
||||
|
"tax": tax_move_line["balance"], |
||||
|
"tax_line_id": tax_move_line["tax_line_id"][0], |
||||
|
} |
||||
|
) |
||||
|
for taxed_move_line in taxed_move_lines: |
||||
|
for tax_id in taxed_move_line["tax_ids"]: |
||||
|
vat_data.append( |
||||
|
{ |
||||
|
"net": taxed_move_line["balance"], |
||||
|
"tax": 0.0, |
||||
|
"tax_line_id": tax_id, |
||||
|
} |
||||
|
) |
||||
|
tax_ids = list(map(operator.itemgetter("tax_line_id"), vat_data)) |
||||
|
tax_ids = list(set(tax_ids)) |
||||
|
tax_data = self._get_tax_data(tax_ids) |
||||
|
return vat_data, tax_data |
||||
|
|
||||
|
def _get_tax_group_data(self, tax_group_ids): |
||||
|
tax_groups = self.env["account.tax.group"].browse(tax_group_ids) |
||||
|
tax_group_data = {} |
||||
|
for tax_group in tax_groups: |
||||
|
tax_group_data.update( |
||||
|
{ |
||||
|
tax_group.id: { |
||||
|
"id": tax_group.id, |
||||
|
"name": tax_group.name, |
||||
|
"code": str(tax_group.sequence), |
||||
|
} |
||||
|
} |
||||
|
) |
||||
|
return tax_group_data |
||||
|
|
||||
|
def _get_vat_report_group_data(self, vat_report_data, tax_data, tax_detail): |
||||
|
vat_report = {} |
||||
|
for tax_move_line in vat_report_data: |
||||
|
tax_id = tax_move_line["tax_line_id"] |
||||
|
if tax_data[tax_id]["amount_type"] == "group": |
||||
|
pass |
||||
|
else: |
||||
|
tax_group_id = tax_data[tax_id]["tax_group_id"] |
||||
|
if tax_group_id not in vat_report.keys(): |
||||
|
vat_report[tax_group_id] = {} |
||||
|
vat_report[tax_group_id]["net"] = 0.0 |
||||
|
vat_report[tax_group_id]["tax"] = 0.0 |
||||
|
vat_report[tax_group_id][tax_id] = dict(tax_data[tax_id]) |
||||
|
vat_report[tax_group_id][tax_id].update({"net": 0.0, "tax": 0.0}) |
||||
|
else: |
||||
|
if tax_id not in vat_report[tax_group_id].keys(): |
||||
|
vat_report[tax_group_id][tax_id] = dict(tax_data[tax_id]) |
||||
|
vat_report[tax_group_id][tax_id].update( |
||||
|
{"net": 0.0, "tax": 0.0} |
||||
|
) |
||||
|
vat_report[tax_group_id]["net"] += tax_move_line["net"] |
||||
|
vat_report[tax_group_id]["tax"] += tax_move_line["tax"] |
||||
|
vat_report[tax_group_id][tax_id]["net"] += tax_move_line["net"] |
||||
|
vat_report[tax_group_id][tax_id]["tax"] += tax_move_line["tax"] |
||||
|
tax_group_data = self._get_tax_group_data(vat_report.keys()) |
||||
|
vat_report_list = [] |
||||
|
for tax_group_id in vat_report.keys(): |
||||
|
vat_report[tax_group_id]["name"] = tax_group_data[tax_group_id]["name"] |
||||
|
vat_report[tax_group_id]["code"] = tax_group_data[tax_group_id]["code"] |
||||
|
if tax_detail: |
||||
|
vat_report[tax_group_id]["taxes"] = [] |
||||
|
for tax_id in vat_report[tax_group_id]: |
||||
|
if isinstance(tax_id, int): |
||||
|
vat_report[tax_group_id]["taxes"].append( |
||||
|
vat_report[tax_group_id][tax_id] |
||||
|
) |
||||
|
vat_report_list.append(vat_report[tax_group_id]) |
||||
|
return vat_report_list |
||||
|
|
||||
|
def _get_tags_data(self, tags_ids): |
||||
|
tags = self.env["account.account.tag"].browse(tags_ids) |
||||
|
tags_data = {} |
||||
|
for tag in tags: |
||||
|
tags_data.update({tag.id: {"code": "", "name": tag.name}}) |
||||
|
return tags_data |
||||
|
|
||||
|
def _get_vat_report_tag_data(self, vat_report_data, tax_data, tax_detail): |
||||
|
vat_report = {} |
||||
|
for tax_move_line in vat_report_data: |
||||
|
tax_id = tax_move_line["tax_line_id"] |
||||
|
tags_ids = tax_data[tax_id]["tags_ids"] |
||||
|
if tax_data[tax_id]["amount_type"] == "group": |
||||
|
continue |
||||
|
else: |
||||
|
if tags_ids: |
||||
|
for tag_id in tags_ids: |
||||
|
if tag_id not in vat_report.keys(): |
||||
|
vat_report[tag_id] = {} |
||||
|
vat_report[tag_id]["net"] = 0.0 |
||||
|
vat_report[tag_id]["tax"] = 0.0 |
||||
|
vat_report[tag_id][tax_id] = dict(tax_data[tax_id]) |
||||
|
vat_report[tag_id][tax_id].update({"net": 0.0, "tax": 0.0}) |
||||
|
else: |
||||
|
if tax_id not in vat_report[tag_id].keys(): |
||||
|
vat_report[tag_id][tax_id] = dict(tax_data[tax_id]) |
||||
|
vat_report[tag_id][tax_id].update( |
||||
|
{"net": 0.0, "tax": 0.0} |
||||
|
) |
||||
|
vat_report[tag_id][tax_id]["net"] += tax_move_line["net"] |
||||
|
vat_report[tag_id][tax_id]["tax"] += tax_move_line["tax"] |
||||
|
vat_report[tag_id]["net"] += tax_move_line["net"] |
||||
|
vat_report[tag_id]["tax"] += tax_move_line["tax"] |
||||
|
tags_data = self._get_tags_data(vat_report.keys()) |
||||
|
vat_report_list = [] |
||||
|
for tag_id in vat_report.keys(): |
||||
|
vat_report[tag_id]["name"] = tags_data[tag_id]["name"] |
||||
|
vat_report[tag_id]["code"] = tags_data[tag_id]["code"] |
||||
|
if tax_detail: |
||||
|
vat_report[tag_id]["taxes"] = [] |
||||
|
for tax_id in vat_report[tag_id]: |
||||
|
if isinstance(tax_id, int): |
||||
|
vat_report[tag_id]["taxes"].append(vat_report[tag_id][tax_id]) |
||||
|
vat_report_list.append(vat_report[tag_id]) |
||||
|
return vat_report_list |
||||
|
|
||||
|
def _get_report_values(self, docids, data): |
||||
|
wizard_id = data["wizard_id"] |
||||
|
company = self.env["res.company"].browse(data["company_id"]) |
||||
|
company_id = data["company_id"] |
||||
|
date_from = data["date_from"] |
||||
|
date_to = data["date_to"] |
||||
|
based_on = data["based_on"] |
||||
|
tax_detail = data["tax_detail"] |
||||
|
only_posted_moves = data["only_posted_moves"] |
||||
|
vat_report_data, tax_data = self._get_vat_report_data( |
||||
|
company_id, date_from, date_to, only_posted_moves |
||||
|
) |
||||
|
if based_on == "taxgroups": |
||||
|
vat_report = self._get_vat_report_group_data( |
||||
|
vat_report_data, tax_data, tax_detail |
||||
|
) |
||||
|
else: |
||||
|
vat_report = self._get_vat_report_tag_data( |
||||
|
vat_report_data, tax_data, tax_detail |
||||
|
) |
||||
|
return { |
||||
|
"doc_ids": [wizard_id], |
||||
|
"doc_model": "open.items.report.wizard", |
||||
|
"docs": self.env["open.items.report.wizard"].browse(wizard_id), |
||||
|
"company_name": company.display_name, |
||||
|
"currency_name": company.currency_id.name, |
||||
|
"date_to": data["date_to"], |
||||
|
"date_from": data["date_from"], |
||||
|
"based_on": data["based_on"], |
||||
|
"tax_detail": data["tax_detail"], |
||||
|
"vat_report": vat_report, |
||||
|
} |
@ -0,0 +1,61 @@ |
|||||
|
# Copyright 2018 Forest and Biomass Romania |
||||
|
# Copyright 2021 Tecnativa - João Marques |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import _, models |
||||
|
|
||||
|
|
||||
|
class VATReportXslx(models.AbstractModel): |
||||
|
_name = "report.a_f_r.report_vat_report_xlsx" |
||||
|
_description = "Vat Report XLSX Report" |
||||
|
_inherit = "report.account_financial_report.abstract_report_xlsx" |
||||
|
|
||||
|
def _get_report_name(self, report, data): |
||||
|
company_id = data.get("company_id", False) |
||||
|
report_name = _("Vat Report") |
||||
|
if company_id: |
||||
|
company = self.env["res.company"].browse(company_id) |
||||
|
suffix = " - {} - {}".format(company.name, company.currency_id.name) |
||||
|
report_name = report_name + suffix |
||||
|
return report_name |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
return { |
||||
|
0: {"header": _("Code"), "field": "code", "width": 5}, |
||||
|
1: {"header": _("Name"), "field": "name", "width": 100}, |
||||
|
2: {"header": _("Net"), "field": "net", "type": "amount", "width": 14}, |
||||
|
3: {"header": _("Tax"), "field": "tax", "type": "amount", "width": 14}, |
||||
|
} |
||||
|
|
||||
|
def _get_report_filters(self, report): |
||||
|
return [ |
||||
|
[_("Date from"), report.date_from.strftime("%d/%m/%Y")], |
||||
|
[_("Date to"), report.date_to.strftime("%d/%m/%Y")], |
||||
|
[ |
||||
|
_("Based on"), |
||||
|
_("Tax Tags") if report.based_on == "taxtags" else _("Tax Groups"), |
||||
|
], |
||||
|
] |
||||
|
|
||||
|
def _get_col_count_filter_name(self): |
||||
|
return 0 |
||||
|
|
||||
|
def _get_col_count_filter_value(self): |
||||
|
return 2 |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report, data, report_data): |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.vat_report" |
||||
|
]._get_report_values(report, data) |
||||
|
vat_report = res_data["vat_report"] |
||||
|
tax_detail = res_data["tax_detail"] |
||||
|
# For each tax_tag tax_group |
||||
|
self.write_array_header(report_data) |
||||
|
for tag_or_group in vat_report: |
||||
|
# Write taxtag line |
||||
|
self.write_line_from_dict(tag_or_group, report_data) |
||||
|
|
||||
|
# For each tax if detail taxes |
||||
|
if tax_detail: |
||||
|
for tax in tag_or_group["taxes"]: |
||||
|
self.write_line_from_dict(tax, report_data) |
@ -0,0 +1,173 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<!-- PDF REPORTS : paperformat --> |
||||
|
<record id="report_qweb_paperformat" model="report.paperformat"> |
||||
|
<field name="name">Account financial report qweb paperformat</field> |
||||
|
<field name="default" eval="True" /> |
||||
|
<field name="format">custom</field> |
||||
|
<field name="page_height">297</field> |
||||
|
<field name="page_width">210</field> |
||||
|
<field name="orientation">Portrait</field> |
||||
|
<field name="margin_top">12</field> |
||||
|
<field name="margin_bottom">8</field> |
||||
|
<field name="margin_left">5</field> |
||||
|
<field name="margin_right">5</field> |
||||
|
<field name="header_line" eval="False" /> |
||||
|
<field name="header_spacing">10</field> |
||||
|
<field name="dpi">110</field> |
||||
|
</record> |
||||
|
|
||||
|
<!-- PDF/HMTL REPORTS --> |
||||
|
<!-- General Ledger --> |
||||
|
<record id="action_print_report_general_ledger_qweb" model="ir.actions.report"> |
||||
|
<field name="name">General Ledger</field> |
||||
|
<field name="model">general.ledger.report.wizard</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name">account_financial_report.general_ledger</field> |
||||
|
<field name="report_file">account_financial_report.general_ledger</field> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat" /> |
||||
|
</record> |
||||
|
<record id="action_print_report_general_ledger_html" model="ir.actions.report"> |
||||
|
<field name="name">General Ledger</field> |
||||
|
<field name="model">general.ledger.report.wizard</field> |
||||
|
<field name="report_type">qweb-html</field> |
||||
|
<field name="report_name">account_financial_report.general_ledger</field> |
||||
|
<field name="report_file">account_financial_report.general_ledger</field> |
||||
|
</record> |
||||
|
<!-- Journal Ledger --> |
||||
|
<record id="action_print_journal_ledger_wizard_qweb" model="ir.actions.report"> |
||||
|
<field name="name">ournal Ledger</field> |
||||
|
<field name="model">journal.ledger.report.wizard</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name">account_financial_report.journal_ledger</field> |
||||
|
<field name="report_file">account_financial_report.journal_ledger</field> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat" /> |
||||
|
</record> |
||||
|
<record id="action_print_journal_ledger_wizard_html" model="ir.actions.report"> |
||||
|
<field name="name">Journal Ledger</field> |
||||
|
<field name="model">journal.ledger.report.wizard</field> |
||||
|
<field name="report_type">qweb-html</field> |
||||
|
<field name="report_name">account_financial_report.journal_ledger</field> |
||||
|
<field name="report_file">account_financial_report.journal_ledger</field> |
||||
|
</record> |
||||
|
<!-- Trial Balance --> |
||||
|
<record id="action_report_trial_balance_qweb" model="ir.actions.report"> |
||||
|
<field name="name">Trial Balance</field> |
||||
|
<field name="model">trial.balance.report.wizard</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name">account_financial_report.trial_balance</field> |
||||
|
<field name="report_file">account_financial_report.trial_balance</field> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat" /> |
||||
|
</record> |
||||
|
<record id="action_report_trial_balance_html" model="ir.actions.report"> |
||||
|
<field name="name">Trial Balance</field> |
||||
|
<field name="model">trial.balance.report.wizard</field> |
||||
|
<field name="report_type">qweb-html</field> |
||||
|
<field name="report_name">account_financial_report.trial_balance</field> |
||||
|
<field name="report_file">account_financial_report.trial_balance</field> |
||||
|
</record> |
||||
|
<!-- Open Items --> |
||||
|
<record id="action_print_report_open_items_qweb" model="ir.actions.report"> |
||||
|
<field name="name">Open Items</field> |
||||
|
<field name="model">open.items.report.wizard</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name">account_financial_report.open_items</field> |
||||
|
<field name="report_file">account_financial_report.open_items</field> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat" /> |
||||
|
</record> |
||||
|
<record id="action_print_report_open_items_html" model="ir.actions.report"> |
||||
|
<field name="name">Open Items</field> |
||||
|
<field name="model">open.items.report.wizard</field> |
||||
|
<field name="report_type">qweb-html</field> |
||||
|
<field name="report_name">account_financial_report.open_items</field> |
||||
|
<field name="report_file">account_financial_report.open_items</field> |
||||
|
</record> |
||||
|
<!-- Aged Partner Balance --> |
||||
|
<record |
||||
|
id="action_print_report_aged_partner_balance_qweb" |
||||
|
model="ir.actions.report" |
||||
|
> |
||||
|
<field name="name">Aged Partner Balance</field> |
||||
|
<field name="model">aged.partner.balance.report.wizard</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name">account_financial_report.aged_partner_balance</field> |
||||
|
<field name="report_file">account_financial_report.aged_partner_balance</field> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat" /> |
||||
|
</record> |
||||
|
<record |
||||
|
id="action_print_report_aged_partner_balance_html" |
||||
|
model="ir.actions.report" |
||||
|
> |
||||
|
<field name="name">Aged Partner Balance</field> |
||||
|
<field name="model">aged.partner.balance.report.wizard</field> |
||||
|
<field name="report_type">qweb-html</field> |
||||
|
<field name="report_name">account_financial_report.aged_partner_balance</field> |
||||
|
<field name="report_file">account_financial_report.aged_partner_balance</field> |
||||
|
</record> |
||||
|
<!-- VAT Report --> |
||||
|
<record id="action_print_report_vat_report_qweb" model="ir.actions.report"> |
||||
|
<field name="name">VAT Report</field> |
||||
|
<field name="model">vat.report.wizard</field> |
||||
|
<field name="report_type">qweb-pdf</field> |
||||
|
<field name="report_name">account_financial_report.vat_report</field> |
||||
|
<field name="report_file">account_financial_report.vat_report</field> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat" /> |
||||
|
</record> |
||||
|
<record id="action_print_report_vat_report_html" model="ir.actions.report"> |
||||
|
<field name="name">VAT Report</field> |
||||
|
<field name="model">vat.report.wizard</field> |
||||
|
<field name="report_type">qweb-html</field> |
||||
|
<field name="report_name">account_financial_report.vat_report</field> |
||||
|
<field name="report_file">account_financial_report.vat_report</field> |
||||
|
</record> |
||||
|
|
||||
|
<!-- XLSX REPORTS --> |
||||
|
<record id="action_report_general_ledger_xlsx" model="ir.actions.report"> |
||||
|
<field name="name">General Ledger XLSX</field> |
||||
|
<field name="model">general.ledger.report.wizard</field> |
||||
|
<field name="type">ir.actions.report</field> |
||||
|
<field name="report_name">a_f_r.report_general_ledger_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="report_file">report_general_ledger</field> |
||||
|
</record> |
||||
|
<record id="action_report_journal_ledger_xlsx" model="ir.actions.report"> |
||||
|
<field name="name">Journal Ledger XLSX</field> |
||||
|
<field name="model">journal.ledger.report.wizard</field> |
||||
|
<field name="type">ir.actions.report</field> |
||||
|
<field name="report_name">a_f_r.report_journal_ledger_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="report_file">report_journal_ledger</field> |
||||
|
</record> |
||||
|
<record id="action_report_trial_balance_xlsx" model="ir.actions.report"> |
||||
|
<field name="name">Trial Balance XLSX</field> |
||||
|
<field name="model">trial.balance.report.wizard</field> |
||||
|
<field name="type">ir.actions.report</field> |
||||
|
<field name="report_name">a_f_r.report_trial_balance_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="report_file">report_trial_balance</field> |
||||
|
</record> |
||||
|
<record id="action_report_open_items_xlsx" model="ir.actions.report"> |
||||
|
<field name="name">Open Items XLSX</field> |
||||
|
<field name="model">open.items.report.wizard</field> |
||||
|
<field name="type">ir.actions.report</field> |
||||
|
<field name="report_name">a_f_r.report_open_items_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="report_file">report_open_items</field> |
||||
|
</record> |
||||
|
<record id="action_report_aged_partner_balance_xlsx" model="ir.actions.report"> |
||||
|
<field name="name">Aged Partner Balance XLSX</field> |
||||
|
<field name="model">aged.partner.balance.report.wizard</field> |
||||
|
<field name="type">ir.actions.report</field> |
||||
|
<field name="report_name">a_f_r.report_aged_partner_balance_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="report_file">report_aged_partner_balance</field> |
||||
|
</record> |
||||
|
<record id="action_report_vat_report_xlsx" model="ir.actions.report"> |
||||
|
<field name="name">VAT Report XLSX</field> |
||||
|
<field name="model">vat.report.wizard</field> |
||||
|
<field name="type">ir.actions.report</field> |
||||
|
<field name="report_name">a_f_r.report_vat_report_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="report_file">report_vat_report</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,7 @@ |
|||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
||||
|
access_aged_partner_balance_report_wizard,access_aged_partner_balance_report_wizard,model_aged_partner_balance_report_wizard,base.group_user,1,1,1,1 |
||||
|
access_general_ledger_report_wizard,access_general_ledger_report_wizard,model_general_ledger_report_wizard,base.group_user,1,1,1,1 |
||||
|
access_journal_ledger_report_wizard,access_journal_ledger_report_wizard,model_journal_ledger_report_wizard,base.group_user,1,1,1,1 |
||||
|
access_open_items_report_wizard,access_open_items_report_wizard,model_open_items_report_wizard,base.group_user,1,1,1,1 |
||||
|
access_trial_balance_report_wizard,access_trial_balance_report_wizard,model_trial_balance_report_wizard,base.group_user,1,1,1,1 |
||||
|
access_vat_report_wizard,access_vat_report_wizard,model_vat_report_wizard,base.group_user,1,1,1,1 |
After Width: 256 | Height: 256 | Size: 15 KiB |
@ -0,0 +1,506 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
||||
|
<head> |
||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
||||
|
<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" /> |
||||
|
<title>Account Financial Reports</title> |
||||
|
<style type="text/css"> |
||||
|
|
||||
|
/* |
||||
|
:Author: David Goodger (goodger@python.org) |
||||
|
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $ |
||||
|
:Copyright: This stylesheet has been placed in the public domain. |
||||
|
|
||||
|
Default cascading style sheet for the HTML output of Docutils. |
||||
|
|
||||
|
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to |
||||
|
customize this style sheet. |
||||
|
*/ |
||||
|
|
||||
|
/* used to remove borders from tables and images */ |
||||
|
.borderless, table.borderless td, table.borderless th { |
||||
|
border: 0 } |
||||
|
|
||||
|
table.borderless td, table.borderless th { |
||||
|
/* Override padding for "table.docutils td" with "! important". |
||||
|
The right padding separates the table cells. */ |
||||
|
padding: 0 0.5em 0 0 ! important } |
||||
|
|
||||
|
.first { |
||||
|
/* Override more specific margin styles with "! important". */ |
||||
|
margin-top: 0 ! important } |
||||
|
|
||||
|
.last, .with-subtitle { |
||||
|
margin-bottom: 0 ! important } |
||||
|
|
||||
|
.hidden { |
||||
|
display: none } |
||||
|
|
||||
|
.subscript { |
||||
|
vertical-align: sub; |
||||
|
font-size: smaller } |
||||
|
|
||||
|
.superscript { |
||||
|
vertical-align: super; |
||||
|
font-size: smaller } |
||||
|
|
||||
|
a.toc-backref { |
||||
|
text-decoration: none ; |
||||
|
color: black } |
||||
|
|
||||
|
blockquote.epigraph { |
||||
|
margin: 2em 5em ; } |
||||
|
|
||||
|
dl.docutils dd { |
||||
|
margin-bottom: 0.5em } |
||||
|
|
||||
|
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
/* Uncomment (and remove this text!) to get bold-faced definition list terms |
||||
|
dl.docutils dt { |
||||
|
font-weight: bold } |
||||
|
*/ |
||||
|
|
||||
|
div.abstract { |
||||
|
margin: 2em 5em } |
||||
|
|
||||
|
div.abstract p.topic-title { |
||||
|
font-weight: bold ; |
||||
|
text-align: center } |
||||
|
|
||||
|
div.admonition, div.attention, div.caution, div.danger, div.error, |
||||
|
div.hint, div.important, div.note, div.tip, div.warning { |
||||
|
margin: 2em ; |
||||
|
border: medium outset ; |
||||
|
padding: 1em } |
||||
|
|
||||
|
div.admonition p.admonition-title, div.hint p.admonition-title, |
||||
|
div.important p.admonition-title, div.note p.admonition-title, |
||||
|
div.tip p.admonition-title { |
||||
|
font-weight: bold ; |
||||
|
font-family: sans-serif } |
||||
|
|
||||
|
div.attention p.admonition-title, div.caution p.admonition-title, |
||||
|
div.danger p.admonition-title, div.error p.admonition-title, |
||||
|
div.warning p.admonition-title, .code .error { |
||||
|
color: red ; |
||||
|
font-weight: bold ; |
||||
|
font-family: sans-serif } |
||||
|
|
||||
|
/* Uncomment (and remove this text!) to get reduced vertical space in |
||||
|
compound paragraphs. |
||||
|
div.compound .compound-first, div.compound .compound-middle { |
||||
|
margin-bottom: 0.5em } |
||||
|
|
||||
|
div.compound .compound-last, div.compound .compound-middle { |
||||
|
margin-top: 0.5em } |
||||
|
*/ |
||||
|
|
||||
|
div.dedication { |
||||
|
margin: 2em 5em ; |
||||
|
text-align: center ; |
||||
|
font-style: italic } |
||||
|
|
||||
|
div.dedication p.topic-title { |
||||
|
font-weight: bold ; |
||||
|
font-style: normal } |
||||
|
|
||||
|
div.figure { |
||||
|
margin-left: 2em ; |
||||
|
margin-right: 2em } |
||||
|
|
||||
|
div.footer, div.header { |
||||
|
clear: both; |
||||
|
font-size: smaller } |
||||
|
|
||||
|
div.line-block { |
||||
|
display: block ; |
||||
|
margin-top: 1em ; |
||||
|
margin-bottom: 1em } |
||||
|
|
||||
|
div.line-block div.line-block { |
||||
|
margin-top: 0 ; |
||||
|
margin-bottom: 0 ; |
||||
|
margin-left: 1.5em } |
||||
|
|
||||
|
div.sidebar { |
||||
|
margin: 0 0 0.5em 1em ; |
||||
|
border: medium outset ; |
||||
|
padding: 1em ; |
||||
|
background-color: #ffffee ; |
||||
|
width: 40% ; |
||||
|
float: right ; |
||||
|
clear: right } |
||||
|
|
||||
|
div.sidebar p.rubric { |
||||
|
font-family: sans-serif ; |
||||
|
font-size: medium } |
||||
|
|
||||
|
div.system-messages { |
||||
|
margin: 5em } |
||||
|
|
||||
|
div.system-messages h1 { |
||||
|
color: red } |
||||
|
|
||||
|
div.system-message { |
||||
|
border: medium outset ; |
||||
|
padding: 1em } |
||||
|
|
||||
|
div.system-message p.system-message-title { |
||||
|
color: red ; |
||||
|
font-weight: bold } |
||||
|
|
||||
|
div.topic { |
||||
|
margin: 2em } |
||||
|
|
||||
|
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, |
||||
|
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { |
||||
|
margin-top: 0.4em } |
||||
|
|
||||
|
h1.title { |
||||
|
text-align: center } |
||||
|
|
||||
|
h2.subtitle { |
||||
|
text-align: center } |
||||
|
|
||||
|
hr.docutils { |
||||
|
width: 75% } |
||||
|
|
||||
|
img.align-left, .figure.align-left, object.align-left, table.align-left { |
||||
|
clear: left ; |
||||
|
float: left ; |
||||
|
margin-right: 1em } |
||||
|
|
||||
|
img.align-right, .figure.align-right, object.align-right, table.align-right { |
||||
|
clear: right ; |
||||
|
float: right ; |
||||
|
margin-left: 1em } |
||||
|
|
||||
|
img.align-center, .figure.align-center, object.align-center { |
||||
|
display: block; |
||||
|
margin-left: auto; |
||||
|
margin-right: auto; |
||||
|
} |
||||
|
|
||||
|
table.align-center { |
||||
|
margin-left: auto; |
||||
|
margin-right: auto; |
||||
|
} |
||||
|
|
||||
|
.align-left { |
||||
|
text-align: left } |
||||
|
|
||||
|
.align-center { |
||||
|
clear: both ; |
||||
|
text-align: center } |
||||
|
|
||||
|
.align-right { |
||||
|
text-align: right } |
||||
|
|
||||
|
/* reset inner alignment in figures */ |
||||
|
div.align-right { |
||||
|
text-align: inherit } |
||||
|
|
||||
|
/* div.align-center * { */ |
||||
|
/* text-align: left } */ |
||||
|
|
||||
|
.align-top { |
||||
|
vertical-align: top } |
||||
|
|
||||
|
.align-middle { |
||||
|
vertical-align: middle } |
||||
|
|
||||
|
.align-bottom { |
||||
|
vertical-align: bottom } |
||||
|
|
||||
|
ol.simple, ul.simple { |
||||
|
margin-bottom: 1em } |
||||
|
|
||||
|
ol.arabic { |
||||
|
list-style: decimal } |
||||
|
|
||||
|
ol.loweralpha { |
||||
|
list-style: lower-alpha } |
||||
|
|
||||
|
ol.upperalpha { |
||||
|
list-style: upper-alpha } |
||||
|
|
||||
|
ol.lowerroman { |
||||
|
list-style: lower-roman } |
||||
|
|
||||
|
ol.upperroman { |
||||
|
list-style: upper-roman } |
||||
|
|
||||
|
p.attribution { |
||||
|
text-align: right ; |
||||
|
margin-left: 50% } |
||||
|
|
||||
|
p.caption { |
||||
|
font-style: italic } |
||||
|
|
||||
|
p.credits { |
||||
|
font-style: italic ; |
||||
|
font-size: smaller } |
||||
|
|
||||
|
p.label { |
||||
|
white-space: nowrap } |
||||
|
|
||||
|
p.rubric { |
||||
|
font-weight: bold ; |
||||
|
font-size: larger ; |
||||
|
color: maroon ; |
||||
|
text-align: center } |
||||
|
|
||||
|
p.sidebar-title { |
||||
|
font-family: sans-serif ; |
||||
|
font-weight: bold ; |
||||
|
font-size: larger } |
||||
|
|
||||
|
p.sidebar-subtitle { |
||||
|
font-family: sans-serif ; |
||||
|
font-weight: bold } |
||||
|
|
||||
|
p.topic-title { |
||||
|
font-weight: bold } |
||||
|
|
||||
|
pre.address { |
||||
|
margin-bottom: 0 ; |
||||
|
margin-top: 0 ; |
||||
|
font: inherit } |
||||
|
|
||||
|
pre.literal-block, pre.doctest-block, pre.math, pre.code { |
||||
|
margin-left: 2em ; |
||||
|
margin-right: 2em } |
||||
|
|
||||
|
pre.code .ln { color: grey; } /* line numbers */ |
||||
|
pre.code, code { background-color: #eeeeee } |
||||
|
pre.code .comment, code .comment { color: #5C6576 } |
||||
|
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } |
||||
|
pre.code .literal.string, code .literal.string { color: #0C5404 } |
||||
|
pre.code .name.builtin, code .name.builtin { color: #352B84 } |
||||
|
pre.code .deleted, code .deleted { background-color: #DEB0A1} |
||||
|
pre.code .inserted, code .inserted { background-color: #A3D289} |
||||
|
|
||||
|
span.classifier { |
||||
|
font-family: sans-serif ; |
||||
|
font-style: oblique } |
||||
|
|
||||
|
span.classifier-delimiter { |
||||
|
font-family: sans-serif ; |
||||
|
font-weight: bold } |
||||
|
|
||||
|
span.interpreted { |
||||
|
font-family: sans-serif } |
||||
|
|
||||
|
span.option { |
||||
|
white-space: nowrap } |
||||
|
|
||||
|
span.pre { |
||||
|
white-space: pre } |
||||
|
|
||||
|
span.problematic { |
||||
|
color: red } |
||||
|
|
||||
|
span.section-subtitle { |
||||
|
/* font-size relative to parent (h1..h6 element) */ |
||||
|
font-size: 80% } |
||||
|
|
||||
|
table.citation { |
||||
|
border-left: solid 1px gray; |
||||
|
margin-left: 1px } |
||||
|
|
||||
|
table.docinfo { |
||||
|
margin: 2em 4em } |
||||
|
|
||||
|
table.docutils { |
||||
|
margin-top: 0.5em ; |
||||
|
margin-bottom: 0.5em } |
||||
|
|
||||
|
table.footnote { |
||||
|
border-left: solid 1px black; |
||||
|
margin-left: 1px } |
||||
|
|
||||
|
table.docutils td, table.docutils th, |
||||
|
table.docinfo td, table.docinfo th { |
||||
|
padding-left: 0.5em ; |
||||
|
padding-right: 0.5em ; |
||||
|
vertical-align: top } |
||||
|
|
||||
|
table.docutils th.field-name, table.docinfo th.docinfo-name { |
||||
|
font-weight: bold ; |
||||
|
text-align: left ; |
||||
|
white-space: nowrap ; |
||||
|
padding-left: 0 } |
||||
|
|
||||
|
/* "booktabs" style (no vertical lines) */ |
||||
|
table.docutils.booktabs { |
||||
|
border: 0px; |
||||
|
border-top: 2px solid; |
||||
|
border-bottom: 2px solid; |
||||
|
border-collapse: collapse; |
||||
|
} |
||||
|
table.docutils.booktabs * { |
||||
|
border: 0px; |
||||
|
} |
||||
|
table.docutils.booktabs th { |
||||
|
border-bottom: thin solid; |
||||
|
text-align: left; |
||||
|
} |
||||
|
|
||||
|
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, |
||||
|
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { |
||||
|
font-size: 100% } |
||||
|
|
||||
|
ul.auto-toc { |
||||
|
list-style-type: none } |
||||
|
|
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="document" id="account-financial-reports"> |
||||
|
<h1 class="title">Account Financial Reports</h1> |
||||
|
|
||||
|
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
||||
|
!! This file is generated by oca-gen-addon-readme !! |
||||
|
!! changes will be overwritten. !! |
||||
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> |
||||
|
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-financial-reporting/tree/14.0/account_financial_report"><img alt="OCA/account-financial-reporting" src="https://img.shields.io/badge/github-OCA%2Faccount--financial--reporting-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-financial-reporting-14-0/account-financial-reporting-14-0-account_financial_report"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/91/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p> |
||||
|
<p>This module adds a set of financial reports. They are accessible under |
||||
|
Invoicing / Reporting / OCA accounting reports.</p> |
||||
|
<ul class="simple"> |
||||
|
<li>General ledger</li> |
||||
|
<li>Trial Balance</li> |
||||
|
<li>Open Items</li> |
||||
|
<li>Aged Partner Balance</li> |
||||
|
<li>VAT Report</li> |
||||
|
<li>Journal Ledger</li> |
||||
|
</ul> |
||||
|
<p>Currently General ledger, Trial Balance and Open Items are fully compatible with a foreign |
||||
|
currency set up in account in order to display balances. Moreover, any foreign |
||||
|
currency used in account move lines is properly shown.</p> |
||||
|
<p>In case that in an account has not been configured a second currency foreign |
||||
|
currency balances are not available.</p> |
||||
|
<p><strong>Table of contents</strong></p> |
||||
|
<div class="contents local topic" id="contents"> |
||||
|
<ul class="simple"> |
||||
|
<li><a class="reference internal" href="#known-issues-roadmap" id="id4">Known issues / Roadmap</a></li> |
||||
|
<li><a class="reference internal" href="#changelog" id="id5">Changelog</a><ul> |
||||
|
<li><a class="reference internal" href="#id1" id="id6">11.0.2.5.0 (2019-04-26)</a></li> |
||||
|
<li><a class="reference internal" href="#id2" id="id7">11.0.2.4.1 (2019-01-08)</a></li> |
||||
|
<li><a class="reference internal" href="#id3" id="id8">11.0.2.3.1 (2018-11-29)</a></li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
<li><a class="reference internal" href="#bug-tracker" id="id9">Bug Tracker</a></li> |
||||
|
<li><a class="reference internal" href="#credits" id="id10">Credits</a><ul> |
||||
|
<li><a class="reference internal" href="#authors" id="id11">Authors</a></li> |
||||
|
<li><a class="reference internal" href="#contributors" id="id12">Contributors</a></li> |
||||
|
<li><a class="reference internal" href="#maintainers" id="id13">Maintainers</a></li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="known-issues-roadmap"> |
||||
|
<h1><a class="toc-backref" href="#id4">Known issues / Roadmap</a></h1> |
||||
|
<ul class="simple"> |
||||
|
<li>‘VAT Report’ is valid only for cases where it’s met that for each |
||||
|
Tax defined: all the “Account tags” of all the |
||||
|
‘Repartition for Invoices’ or ‘Repartition for Credit Notes’ |
||||
|
are different.</li> |
||||
|
<li>It would be nice to have in reports a column indicating the |
||||
|
state of the entries when the option “All Entries” is selected |
||||
|
in “Target Moves” field in a wizard</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="changelog"> |
||||
|
<h1><a class="toc-backref" href="#id5">Changelog</a></h1> |
||||
|
<div class="section" id="id1"> |
||||
|
<h2><a class="toc-backref" href="#id6">11.0.2.5.0 (2019-04-26)</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>In the Trial Balance you have an option to hide parent hierarchy levels</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="id2"> |
||||
|
<h2><a class="toc-backref" href="#id7">11.0.2.4.1 (2019-01-08)</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>Handle better multicompany behaviour</li> |
||||
|
<li>Improve how title appears in the reports</li> |
||||
|
<li>Improve performance in General Ledger</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="id3"> |
||||
|
<h2><a class="toc-backref" href="#id8">11.0.2.3.1 (2018-11-29)</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>In the Trial Balance you can apply a filter by hierarchy levels</li> |
||||
|
<li>In the General Ledger you can apply a filter by Analytic Tag</li> |
||||
|
<li>In the Journal Ledger the field ‘Journal’ is now optional</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="section" id="bug-tracker"> |
||||
|
<h1><a class="toc-backref" href="#id9">Bug Tracker</a></h1> |
||||
|
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-financial-reporting/issues">GitHub Issues</a>. |
||||
|
In case of trouble, please check there if your issue has already been reported. |
||||
|
If you spotted it first, help us smashing it by providing a detailed and welcomed |
||||
|
<a class="reference external" href="https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_financial_report%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> |
||||
|
<p>Do not contact contributors directly about support or help with technical issues.</p> |
||||
|
</div> |
||||
|
<div class="section" id="credits"> |
||||
|
<h1><a class="toc-backref" href="#id10">Credits</a></h1> |
||||
|
<div class="section" id="authors"> |
||||
|
<h2><a class="toc-backref" href="#id11">Authors</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>Camptocamp SA</li> |
||||
|
<li>initOS GmbH</li> |
||||
|
<li>redCOR AG</li> |
||||
|
<li>ForgeFlow</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="contributors"> |
||||
|
<h2><a class="toc-backref" href="#id12">Contributors</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>Jordi Ballester <<a class="reference external" href="mailto:jordi.ballester@forgeflow.com">jordi.ballester@forgeflow.com</a>></li> |
||||
|
<li>Yannick Vaucher <<a class="reference external" href="mailto:yannick.vaucher@camptocamp.com">yannick.vaucher@camptocamp.com</a>></li> |
||||
|
<li>Simone Orsi <<a class="reference external" href="mailto:simone.orsi@abstract.com">simone.orsi@abstract.com</a>></li> |
||||
|
<li>Leonardo Pistone <<a class="reference external" href="mailto:leonardo.pistone@camptocamp.com">leonardo.pistone@camptocamp.com</a>></li> |
||||
|
<li>Damien Crier <<a class="reference external" href="mailto:damien.crier@camptocamp.com">damien.crier@camptocamp.com</a>></li> |
||||
|
<li>Andrea Stirpe <<a class="reference external" href="mailto:a.stirpe@onestein.nl">a.stirpe@onestein.nl</a>></li> |
||||
|
<li>Thomas Rehn <<a class="reference external" href="mailto:thomas.rehn@initos.com">thomas.rehn@initos.com</a>></li> |
||||
|
<li>Andrea Gallina <<a class="reference external" href="mailto:4everamd@gmail.com">4everamd@gmail.com</a>></li> |
||||
|
<li>Robert Rottermann <<a class="reference external" href="mailto:robert@redcor.ch">robert@redcor.ch</a>></li> |
||||
|
<li>Ciro Urselli <<a class="reference external" href="mailto:c.urselli@apuliasoftware.it">c.urselli@apuliasoftware.it</a>></li> |
||||
|
<li>Francesco Apruzzese <<a class="reference external" href="mailto:opencode@e-ware.org">opencode@e-ware.org</a>></li> |
||||
|
<li>Lorenzo Battistini <<a class="reference external" href="https://github.com/eLBati">https://github.com/eLBati</a>></li> |
||||
|
<li>Julien Coux <<a class="reference external" href="mailto:julien.coux@camptocamp.com">julien.coux@camptocamp.com</a>></li> |
||||
|
<li>Akim Juillerat <<a class="reference external" href="mailto:akim.juillerat@camptocamp.com">akim.juillerat@camptocamp.com</a>></li> |
||||
|
<li>Alexis de Lattre <<a class="reference external" href="mailto:alexis@via.ecp.fr">alexis@via.ecp.fr</a>></li> |
||||
|
<li>Mihai Fekete <<a class="reference external" href="mailto:feketemihai@gmail.com">feketemihai@gmail.com</a>></li> |
||||
|
<li>Miquel Raïch <<a class="reference external" href="mailto:miquel.raich@forgeflow.com">miquel.raich@forgeflow.com</a>></li> |
||||
|
<li>Joan Sisquella <<a class="reference external" href="mailto:joan.sisquella@forgeflow.com">joan.sisquella@forgeflow.com</a>></li> |
||||
|
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul> |
||||
|
<li>Pedro M. Baeza</li> |
||||
|
<li>Sergio Teruel</li> |
||||
|
<li>Ernesto Tejeda</li> |
||||
|
<li>João Marques</li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<p>Much of the work in this module was done at a sprint in Sorrento, Italy in |
||||
|
April 2016.</p> |
||||
|
</div> |
||||
|
<div class="section" id="maintainers"> |
||||
|
<h2><a class="toc-backref" href="#id13">Maintainers</a></h2> |
||||
|
<p>This module is maintained by the OCA.</p> |
||||
|
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a> |
||||
|
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose |
||||
|
mission is to support the collaborative development of Odoo features and |
||||
|
promote its widespread use.</p> |
||||
|
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-financial-reporting/tree/14.0/account_financial_report">OCA/account-financial-reporting</a> project on GitHub.</p> |
||||
|
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,113 @@ |
|||||
|
.act_as_table { |
||||
|
display: table !important; |
||||
|
background-color: white; |
||||
|
} |
||||
|
.act_as_row { |
||||
|
display: table-row !important; |
||||
|
page-break-inside: avoid; |
||||
|
} |
||||
|
.act_as_cell { |
||||
|
display: table-cell !important; |
||||
|
page-break-inside: avoid; |
||||
|
} |
||||
|
.act_as_thead { |
||||
|
display: table-header-group !important; |
||||
|
} |
||||
|
.act_as_tbody { |
||||
|
display: table-row-group !important; |
||||
|
} |
||||
|
.list_table, |
||||
|
.data_table, |
||||
|
.totals_table { |
||||
|
width: 100% !important; |
||||
|
} |
||||
|
.act_as_row.labels { |
||||
|
background-color: #f0f0f0 !important; |
||||
|
} |
||||
|
.list_table, |
||||
|
.data_table, |
||||
|
.totals_table, |
||||
|
.list_table .act_as_row { |
||||
|
border-left: 0px; |
||||
|
border-right: 0px; |
||||
|
text-align: center; |
||||
|
font-size: 10px; |
||||
|
padding-right: 3px; |
||||
|
padding-left: 3px; |
||||
|
padding-top: 2px; |
||||
|
padding-bottom: 2px; |
||||
|
border-collapse: collapse; |
||||
|
} |
||||
|
.totals_table { |
||||
|
font-weight: bold; |
||||
|
text-align: center; |
||||
|
} |
||||
|
.list_table .act_as_row.labels, |
||||
|
.list_table .act_as_row.initial_balance, |
||||
|
.list_table .act_as_row.lines { |
||||
|
border-color: grey !important; |
||||
|
border-bottom: 1px solid lightGrey !important; |
||||
|
} |
||||
|
.data_table .act_as_cell { |
||||
|
border: 1px solid lightGrey; |
||||
|
text-align: center; |
||||
|
} |
||||
|
.data_table .act_as_cell, |
||||
|
.list_table .act_as_cell, |
||||
|
.totals_table .act_as_cell { |
||||
|
word-wrap: break-word; |
||||
|
} |
||||
|
.data_table .act_as_row.labels, |
||||
|
.totals_table .act_as_row.labels { |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.initial_balance .act_as_cell { |
||||
|
font-style: italic; |
||||
|
} |
||||
|
.account_title { |
||||
|
font-size: 11px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.account_title.labels { |
||||
|
background-color: #f0f0f0 !important; |
||||
|
} |
||||
|
.act_as_cell.amount { |
||||
|
word-wrap: normal; |
||||
|
text-align: right; |
||||
|
} |
||||
|
.act_as_cell.left { |
||||
|
text-align: left; |
||||
|
} |
||||
|
.act_as_cell.right { |
||||
|
text-align: right; |
||||
|
} |
||||
|
.list_table .act_as_cell { |
||||
|
/* border-right:1px solid lightGrey; uncomment to active column lines */ |
||||
|
} |
||||
|
.list_table .act_as_cell.first_column { |
||||
|
padding-left: 0px; |
||||
|
/* border-left:1px solid lightGrey; uncomment to active column lines */ |
||||
|
} |
||||
|
.overflow_ellipsis { |
||||
|
text-overflow: ellipsis; |
||||
|
overflow: hidden; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
.custom_footer { |
||||
|
font-size: 7px !important; |
||||
|
} |
||||
|
.page_break { |
||||
|
page-break-inside: avoid; |
||||
|
} |
||||
|
|
||||
|
.button_row { |
||||
|
padding-bottom: 10px; |
||||
|
} |
||||
|
|
||||
|
.o_account_financial_reports_page { |
||||
|
padding-top: 10px; |
||||
|
width: 90%; |
||||
|
margin-right: auto; |
||||
|
margin-left: auto; |
||||
|
font-family: Helvetica, Arial; |
||||
|
} |
@ -0,0 +1,109 @@ |
|||||
|
odoo.define("account_financial_report.account_financial_report_backend", function ( |
||||
|
require |
||||
|
) { |
||||
|
"use strict"; |
||||
|
|
||||
|
var core = require("web.core"); |
||||
|
var Widget = require("web.Widget"); |
||||
|
var ControlPanelMixin = require("web.ControlPanelMixin"); |
||||
|
var ReportWidget = require("account_financial_report.account_financial_report_widget"); |
||||
|
|
||||
|
var report_backend = Widget.extend(ControlPanelMixin, { |
||||
|
// Stores all the parameters of the action.
|
||||
|
events: { |
||||
|
"click .o_account_financial_reports_print": "print", |
||||
|
"click .o_account_financial_reports_export": "export", |
||||
|
}, |
||||
|
init: function (parent, action) { |
||||
|
this.actionManager = parent; |
||||
|
this.given_context = {}; |
||||
|
this.odoo_context = action.context; |
||||
|
this.controller_url = action.context.url; |
||||
|
if (action.context.context) { |
||||
|
this.given_context = action.context.context; |
||||
|
} |
||||
|
this.given_context.active_id = |
||||
|
action.context.active_id || action.params.active_id; |
||||
|
this.given_context.model = action.context.active_model || false; |
||||
|
this.given_context.ttype = action.context.ttype || false; |
||||
|
return this._super.apply(this, arguments); |
||||
|
}, |
||||
|
willStart: function () { |
||||
|
return $.when(this.get_html()); |
||||
|
}, |
||||
|
set_html: function () { |
||||
|
var self = this; |
||||
|
var def = $.when(); |
||||
|
if (!this.report_widget) { |
||||
|
this.report_widget = new ReportWidget(this, this.given_context); |
||||
|
def = this.report_widget.appendTo(this.$el); |
||||
|
} |
||||
|
def.then(function () { |
||||
|
self.report_widget.$el.html(self.html); |
||||
|
}); |
||||
|
}, |
||||
|
start: function () { |
||||
|
this.set_html(); |
||||
|
return this._super(); |
||||
|
}, |
||||
|
// Fetches the html and is previous report.context if any,
|
||||
|
// else create it
|
||||
|
get_html: function () { |
||||
|
var self = this; |
||||
|
var defs = []; |
||||
|
return this._rpc({ |
||||
|
model: this.given_context.model, |
||||
|
method: "get_html", |
||||
|
args: [self.given_context], |
||||
|
context: self.odoo_context, |
||||
|
}).then(function (result) { |
||||
|
self.html = result.html; |
||||
|
defs.push(self.update_cp()); |
||||
|
return $.when.apply($, defs); |
||||
|
}); |
||||
|
}, |
||||
|
// Updates the control panel and render the elements that have yet
|
||||
|
// to be rendered
|
||||
|
update_cp: function () { |
||||
|
if (this.$buttons) { |
||||
|
var status = { |
||||
|
breadcrumbs: this.actionManager.get_breadcrumbs(), |
||||
|
cp_content: {$buttons: this.$buttons}, |
||||
|
}; |
||||
|
return this.update_control_panel(status); |
||||
|
} |
||||
|
}, |
||||
|
do_show: function () { |
||||
|
this._super(); |
||||
|
this.update_cp(); |
||||
|
}, |
||||
|
print: function () { |
||||
|
var self = this; |
||||
|
this._rpc({ |
||||
|
model: this.given_context.model, |
||||
|
method: "print_report", |
||||
|
args: [this.given_context.active_id, "qweb-pdf"], |
||||
|
context: self.odoo_context, |
||||
|
}).then(function (result) { |
||||
|
self.do_action(result); |
||||
|
}); |
||||
|
}, |
||||
|
export: function () { |
||||
|
var self = this; |
||||
|
this._rpc({ |
||||
|
model: this.given_context.model, |
||||
|
method: "print_report", |
||||
|
args: [this.given_context.active_id, "xlsx"], |
||||
|
context: self.odoo_context, |
||||
|
}).then(function (result) { |
||||
|
self.do_action(result); |
||||
|
}); |
||||
|
}, |
||||
|
canBeRemoved: function () { |
||||
|
return $.when(); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
core.action_registry.add("account_financial_report_backend", report_backend); |
||||
|
return report_backend; |
||||
|
}); |
@ -0,0 +1,88 @@ |
|||||
|
odoo.define("account_financial_report.account_financial_report_widget", function ( |
||||
|
require |
||||
|
) { |
||||
|
"use strict"; |
||||
|
|
||||
|
var Widget = require("web.Widget"); |
||||
|
|
||||
|
var accountFinancialReportWidget = Widget.extend({ |
||||
|
events: { |
||||
|
"click .o_account_financial_reports_web_action": "boundLink", |
||||
|
"click .o_account_financial_reports_web_action_multi": "boundLinkmulti", |
||||
|
"click .o_account_financial_reports_web_action_monetary": |
||||
|
"boundLinkMonetary", |
||||
|
"click .o_account_financial_reports_web_action_monetary_multi": |
||||
|
"boundLinkMonetarymulti", |
||||
|
}, |
||||
|
init: function () { |
||||
|
this._super.apply(this, arguments); |
||||
|
}, |
||||
|
start: function () { |
||||
|
return this._super.apply(this, arguments); |
||||
|
}, |
||||
|
boundLink: function (e) { |
||||
|
var res_model = $(e.target).data("res-model"); |
||||
|
var res_id = $(e.target).data("active-id"); |
||||
|
return this.do_action({ |
||||
|
type: "ir.actions.act_window", |
||||
|
res_model: res_model, |
||||
|
res_id: res_id, |
||||
|
views: [[false, "form"]], |
||||
|
target: "current", |
||||
|
}); |
||||
|
}, |
||||
|
boundLinkmulti: function (e) { |
||||
|
var res_model = $(e.target).data("res-model"); |
||||
|
var domain = $(e.target).data("domain"); |
||||
|
if (!res_model) { |
||||
|
res_model = $(e.target.parentElement).data("res-model"); |
||||
|
} |
||||
|
if (!domain) { |
||||
|
domain = $(e.target.parentElement).data("domain"); |
||||
|
} |
||||
|
return this.do_action({ |
||||
|
type: "ir.actions.act_window", |
||||
|
name: this._toTitleCase(res_model.split(".").join(" ")), |
||||
|
res_model: res_model, |
||||
|
domain: domain, |
||||
|
views: [ |
||||
|
[false, "list"], |
||||
|
[false, "form"], |
||||
|
], |
||||
|
target: "current", |
||||
|
}); |
||||
|
}, |
||||
|
boundLinkMonetary: function (e) { |
||||
|
var res_model = $(e.target.parentElement).data("res-model"); |
||||
|
var res_id = $(e.target.parentElement).data("active-id"); |
||||
|
return this.do_action({ |
||||
|
type: "ir.actions.act_window", |
||||
|
res_model: res_model, |
||||
|
res_id: res_id, |
||||
|
views: [[false, "form"]], |
||||
|
target: "current", |
||||
|
}); |
||||
|
}, |
||||
|
boundLinkMonetarymulti: function (e) { |
||||
|
var res_model = $(e.target.parentElement).data("res-model"); |
||||
|
var domain = $(e.target.parentElement).data("domain"); |
||||
|
return this.do_action({ |
||||
|
type: "ir.actions.act_window", |
||||
|
res_model: res_model, |
||||
|
domain: domain, |
||||
|
views: [ |
||||
|
[false, "list"], |
||||
|
[false, "form"], |
||||
|
], |
||||
|
target: "current", |
||||
|
}); |
||||
|
}, |
||||
|
_toTitleCase: function (str) { |
||||
|
return str.replace(/\w\S*/g, function (txt) { |
||||
|
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); |
||||
|
}); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
return accountFinancialReportWidget; |
||||
|
}); |
@ -0,0 +1,8 @@ |
|||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
|
||||
|
from . import test_general_ledger |
||||
|
from . import test_journal_ledger |
||||
|
from . import test_open_items |
||||
|
from . import test_trial_balance |
||||
|
from . import test_vat_report |
@ -0,0 +1,701 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
from datetime import date |
||||
|
|
||||
|
from odoo import api, fields |
||||
|
from odoo.tests import common |
||||
|
|
||||
|
|
||||
|
class TestGeneralLedgerReport(common.TransactionCase): |
||||
|
def setUp(self): |
||||
|
super(TestGeneralLedgerReport, self).setUp() |
||||
|
self.before_previous_fy_year = fields.Date.from_string("2014-05-05") |
||||
|
self.previous_fy_date_start = fields.Date.from_string("2015-01-01") |
||||
|
self.previous_fy_date_end = fields.Date.from_string("2015-12-31") |
||||
|
self.fy_date_start = fields.Date.from_string("2016-01-01") |
||||
|
self.fy_date_end = fields.Date.from_string("2016-12-31") |
||||
|
|
||||
|
self.receivable_account = self.env["account.account"].search( |
||||
|
[("user_type_id.name", "=", "Receivable")], limit=1 |
||||
|
) |
||||
|
self.income_account = self.env["account.account"].search( |
||||
|
[("user_type_id.name", "=", "Income")], limit=1 |
||||
|
) |
||||
|
self.unaffected_account = self.env["account.account"].search( |
||||
|
[ |
||||
|
( |
||||
|
"user_type_id", |
||||
|
"=", |
||||
|
self.env.ref("account.data_unaffected_earnings").id, |
||||
|
) |
||||
|
], |
||||
|
limit=1, |
||||
|
) |
||||
|
self.partner = self.env.ref("base.res_partner_12") |
||||
|
|
||||
|
def _add_move( |
||||
|
self, |
||||
|
date, |
||||
|
receivable_debit, |
||||
|
receivable_credit, |
||||
|
income_debit, |
||||
|
income_credit, |
||||
|
unaffected_debit=0, |
||||
|
unaffected_credit=0, |
||||
|
): |
||||
|
journal = self.env["account.journal"].search([], limit=1) |
||||
|
partner = self.env.ref("base.res_partner_12") |
||||
|
move_vals = { |
||||
|
"journal_id": journal.id, |
||||
|
"date": date, |
||||
|
"line_ids": [ |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"debit": receivable_debit, |
||||
|
"credit": receivable_credit, |
||||
|
"account_id": self.receivable_account.id, |
||||
|
"partner_id": partner.id, |
||||
|
}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"debit": income_debit, |
||||
|
"credit": income_credit, |
||||
|
"account_id": self.income_account.id, |
||||
|
"partner_id": partner.id, |
||||
|
}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"debit": unaffected_debit, |
||||
|
"credit": unaffected_credit, |
||||
|
"account_id": self.unaffected_account.id, |
||||
|
"partner_id": partner.id, |
||||
|
}, |
||||
|
), |
||||
|
], |
||||
|
} |
||||
|
move = self.env["account.move"].create(move_vals) |
||||
|
move.action_post() |
||||
|
|
||||
|
def _get_report_lines(self, with_partners=False): |
||||
|
centralize = True |
||||
|
if with_partners: |
||||
|
centralize = False |
||||
|
company = self.env.ref("base.main_company") |
||||
|
general_ledger = self.env["general.ledger.report.wizard"].create( |
||||
|
{ |
||||
|
"date_from": self.fy_date_start, |
||||
|
"date_to": self.fy_date_end, |
||||
|
"target_move": "posted", |
||||
|
"hide_account_at_0": False, |
||||
|
"company_id": company.id, |
||||
|
"fy_start_date": self.fy_date_start, |
||||
|
"centralize": centralize, |
||||
|
} |
||||
|
) |
||||
|
data = general_ledger._prepare_report_general_ledger() |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.general_ledger" |
||||
|
]._get_report_values(general_ledger, data) |
||||
|
return res_data |
||||
|
|
||||
|
@api.model |
||||
|
def check_account_in_report(self, account_id, general_ledger): |
||||
|
account_in_report = False |
||||
|
for account in general_ledger: |
||||
|
if account["id"] == account_id: |
||||
|
account_in_report = True |
||||
|
break |
||||
|
return account_in_report |
||||
|
|
||||
|
@api.model |
||||
|
def check_partner_in_report(self, account_id, partner_id, general_ledger): |
||||
|
partner_in_report = False |
||||
|
for account in general_ledger: |
||||
|
if account["id"] == account_id and account["partners"]: |
||||
|
for partner in account["list_partner"]: |
||||
|
if partner["id"] == partner_id: |
||||
|
partner_in_report = True |
||||
|
return partner_in_report |
||||
|
|
||||
|
@api.model |
||||
|
def _get_initial_balance(self, account_id, general_ledger): |
||||
|
initial_balance = False |
||||
|
for account in general_ledger: |
||||
|
if account["id"] == account_id: |
||||
|
initial_balance = account["init_bal"] |
||||
|
return initial_balance |
||||
|
|
||||
|
@api.model |
||||
|
def _get_partner_initial_balance(self, account_id, partner_id, general_ledger): |
||||
|
initial_balance = False |
||||
|
for account in general_ledger: |
||||
|
if account["id"] == account_id and account["partners"]: |
||||
|
for partner in account["list_partner"]: |
||||
|
if partner["id"] == partner_id: |
||||
|
initial_balance = partner["init_bal"] |
||||
|
return initial_balance |
||||
|
|
||||
|
@api.model |
||||
|
def _get_final_balance(self, account_id, general_ledger): |
||||
|
final_balance = False |
||||
|
for account in general_ledger: |
||||
|
if account["id"] == account_id: |
||||
|
final_balance = account["fin_bal"] |
||||
|
return final_balance |
||||
|
|
||||
|
@api.model |
||||
|
def _get_partner_final_balance(self, account_id, partner_id, general_ledger): |
||||
|
final_balance = False |
||||
|
for account in general_ledger: |
||||
|
if account["id"] == account_id and account["partners"]: |
||||
|
for partner in account["list_partner"]: |
||||
|
if partner["id"] == partner_id: |
||||
|
final_balance = partner["fin_bal"] |
||||
|
return final_balance |
||||
|
|
||||
|
def test_01_account_balance(self): |
||||
|
# Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
self.assertFalse(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.income_account.id, general_ledger |
||||
|
) |
||||
|
self.assertFalse(check_income_account) |
||||
|
|
||||
|
# Add a move at the previous day of the first day of fiscal year |
||||
|
# to check the initial balance |
||||
|
self._add_move( |
||||
|
date=self.previous_fy_date_end, |
||||
|
receivable_debit=1000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=1000, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.income_account.id, general_ledger |
||||
|
) |
||||
|
self.assertFalse(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
receivable_init_balance = self._get_initial_balance( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
receivable_fin_balance = self._get_final_balance( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(receivable_init_balance["debit"], 1000) |
||||
|
self.assertEqual(receivable_init_balance["credit"], 0) |
||||
|
self.assertEqual(receivable_init_balance["balance"], 1000) |
||||
|
self.assertEqual(receivable_fin_balance["debit"], 1000) |
||||
|
self.assertEqual(receivable_fin_balance["credit"], 0) |
||||
|
self.assertEqual(receivable_fin_balance["balance"], 1000) |
||||
|
|
||||
|
# Add reversale move of the initial move the first day of fiscal year |
||||
|
# to check the first day of fiscal year is not used |
||||
|
# to compute the initial balance |
||||
|
self._add_move( |
||||
|
date=self.fy_date_start, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.income_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
receivable_init_balance = self._get_initial_balance( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
receivable_fin_balance = self._get_final_balance( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
income_init_balance = self._get_initial_balance( |
||||
|
self.income_account.id, general_ledger |
||||
|
) |
||||
|
income_fin_balance = self._get_final_balance( |
||||
|
self.income_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(receivable_init_balance["debit"], 1000) |
||||
|
self.assertEqual(receivable_init_balance["credit"], 0) |
||||
|
self.assertEqual(receivable_init_balance["balance"], 1000) |
||||
|
self.assertEqual(receivable_fin_balance["debit"], 1000) |
||||
|
self.assertEqual(receivable_fin_balance["credit"], 1000) |
||||
|
self.assertEqual(receivable_fin_balance["balance"], 0) |
||||
|
|
||||
|
self.assertEqual(income_init_balance["debit"], 0) |
||||
|
self.assertEqual(income_init_balance["credit"], 0) |
||||
|
self.assertEqual(income_init_balance["balance"], 0) |
||||
|
self.assertEqual(income_fin_balance["debit"], 1000) |
||||
|
self.assertEqual(income_fin_balance["credit"], 0) |
||||
|
self.assertEqual(income_fin_balance["balance"], 1000) |
||||
|
|
||||
|
# Add another move at the end day of fiscal year |
||||
|
# to check that it correctly used on report |
||||
|
self._add_move( |
||||
|
date=self.fy_date_end, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.income_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
receivable_init_balance = self._get_initial_balance( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
receivable_fin_balance = self._get_final_balance( |
||||
|
self.receivable_account.id, general_ledger |
||||
|
) |
||||
|
income_init_balance = self._get_initial_balance( |
||||
|
self.income_account.id, general_ledger |
||||
|
) |
||||
|
income_fin_balance = self._get_final_balance( |
||||
|
self.income_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(receivable_init_balance["debit"], 1000) |
||||
|
self.assertEqual(receivable_init_balance["credit"], 0) |
||||
|
self.assertEqual(receivable_init_balance["balance"], 1000) |
||||
|
self.assertEqual(receivable_fin_balance["debit"], 1000) |
||||
|
self.assertEqual(receivable_fin_balance["credit"], 2000) |
||||
|
self.assertEqual(receivable_fin_balance["balance"], -1000) |
||||
|
|
||||
|
self.assertEqual(income_init_balance["debit"], 0) |
||||
|
self.assertEqual(income_init_balance["credit"], 0) |
||||
|
self.assertEqual(income_init_balance["balance"], 0) |
||||
|
self.assertEqual(income_fin_balance["debit"], 2000) |
||||
|
self.assertEqual(income_fin_balance["credit"], 0) |
||||
|
self.assertEqual(income_fin_balance["balance"], 2000) |
||||
|
|
||||
|
def test_02_partner_balance(self): |
||||
|
# Generate the general ledger line |
||||
|
res_data = self._get_report_lines(with_partners=True) |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_partner = self.check_partner_in_report( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
self.assertFalse(check_partner) |
||||
|
|
||||
|
# Add a move at the previous day of the first day of fiscal year |
||||
|
# to check the initial balance |
||||
|
self._add_move( |
||||
|
date=self.previous_fy_date_end, |
||||
|
receivable_debit=1000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=1000, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines(with_partners=True) |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_partner = self.check_partner_in_report( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_partner) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
partner_initial_balance = self._get_partner_initial_balance( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
partner_final_balance = self._get_partner_final_balance( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(partner_initial_balance["debit"], 1000) |
||||
|
self.assertEqual(partner_initial_balance["credit"], 0) |
||||
|
self.assertEqual(partner_initial_balance["balance"], 1000) |
||||
|
self.assertEqual(partner_final_balance["debit"], 1000) |
||||
|
self.assertEqual(partner_final_balance["credit"], 0) |
||||
|
self.assertEqual(partner_final_balance["balance"], 1000) |
||||
|
|
||||
|
# Add reversale move of the initial move the first day of fiscal year |
||||
|
# to check the first day of fiscal year is not used |
||||
|
# to compute the initial balance |
||||
|
self._add_move( |
||||
|
date=self.fy_date_start, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines(with_partners=True) |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_partner = self.check_partner_in_report( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_partner) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
partner_initial_balance = self._get_partner_initial_balance( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
partner_final_balance = self._get_partner_final_balance( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(partner_initial_balance["debit"], 1000) |
||||
|
self.assertEqual(partner_initial_balance["credit"], 0) |
||||
|
self.assertEqual(partner_initial_balance["balance"], 1000) |
||||
|
self.assertEqual(partner_final_balance["debit"], 1000) |
||||
|
self.assertEqual(partner_final_balance["credit"], 1000) |
||||
|
self.assertEqual(partner_final_balance["balance"], 0) |
||||
|
|
||||
|
# Add another move at the end day of fiscal year |
||||
|
# to check that it correctly used on report |
||||
|
self._add_move( |
||||
|
date=self.fy_date_end, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines(with_partners=True) |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_partner = self.check_partner_in_report( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_partner) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
partner_initial_balance = self._get_partner_initial_balance( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
partner_final_balance = self._get_partner_final_balance( |
||||
|
self.receivable_account.id, self.partner.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(partner_initial_balance["debit"], 1000) |
||||
|
self.assertEqual(partner_initial_balance["credit"], 0) |
||||
|
self.assertEqual(partner_initial_balance["balance"], 1000) |
||||
|
self.assertEqual(partner_final_balance["debit"], 1000) |
||||
|
self.assertEqual(partner_final_balance["credit"], 2000) |
||||
|
self.assertEqual(partner_final_balance["balance"], -1000) |
||||
|
|
||||
|
def test_03_unaffected_account_balance(self): |
||||
|
# Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
unaffected_init_balance = self._get_initial_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
unaffected_fin_balance = self._get_final_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_init_balance["debit"], 0) |
||||
|
self.assertEqual(unaffected_init_balance["credit"], 0) |
||||
|
self.assertEqual(unaffected_init_balance["balance"], 0) |
||||
|
self.assertEqual(unaffected_fin_balance["debit"], 0) |
||||
|
self.assertEqual(unaffected_fin_balance["credit"], 0) |
||||
|
self.assertEqual(unaffected_fin_balance["balance"], 0) |
||||
|
|
||||
|
# Add a move at the previous day of the first day of fiscal year |
||||
|
# to check the initial balance |
||||
|
self._add_move( |
||||
|
date=self.previous_fy_date_end, |
||||
|
receivable_debit=1000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=1000, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
unaffected_init_balance = self._get_initial_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
unaffected_fin_balance = self._get_final_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_init_balance["debit"], 0) |
||||
|
self.assertEqual(unaffected_init_balance["credit"], 1000) |
||||
|
self.assertEqual(unaffected_init_balance["balance"], -1000) |
||||
|
self.assertEqual(unaffected_fin_balance["debit"], 0) |
||||
|
self.assertEqual(unaffected_fin_balance["credit"], 1000) |
||||
|
self.assertEqual(unaffected_fin_balance["balance"], -1000) |
||||
|
|
||||
|
# Add reversale move of the initial move the first day of fiscal year |
||||
|
# to check the first day of fiscal year is not used |
||||
|
# to compute the initial balance |
||||
|
self._add_move( |
||||
|
date=self.fy_date_start, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=1000, |
||||
|
unaffected_debit=1000, |
||||
|
unaffected_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
unaffected_init_balance = self._get_initial_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
unaffected_fin_balance = self._get_final_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_init_balance["debit"], 0) |
||||
|
self.assertEqual(unaffected_init_balance["credit"], 1000) |
||||
|
self.assertEqual(unaffected_init_balance["balance"], -1000) |
||||
|
self.assertEqual(unaffected_fin_balance["debit"], 1000) |
||||
|
self.assertEqual(unaffected_fin_balance["credit"], 1000) |
||||
|
self.assertEqual(unaffected_fin_balance["balance"], 0) |
||||
|
|
||||
|
# Add another move at the end day of fiscal year |
||||
|
# to check that it correctly used on report |
||||
|
self._add_move( |
||||
|
date=self.fy_date_end, |
||||
|
receivable_debit=3000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=0, |
||||
|
unaffected_debit=0, |
||||
|
unaffected_credit=3000, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
unaffected_init_balance = self._get_initial_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
unaffected_fin_balance = self._get_final_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_init_balance["debit"], 0) |
||||
|
self.assertEqual(unaffected_init_balance["credit"], 1000) |
||||
|
self.assertEqual(unaffected_init_balance["balance"], -1000) |
||||
|
self.assertEqual(unaffected_fin_balance["debit"], 1000) |
||||
|
self.assertEqual(unaffected_fin_balance["credit"], 4000) |
||||
|
self.assertEqual(unaffected_fin_balance["balance"], -3000) |
||||
|
|
||||
|
def test_04_unaffected_account_balance_2_years(self): |
||||
|
# Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
unaffected_init_balance = self._get_initial_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
unaffected_fin_balance = self._get_final_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_init_balance["debit"], 0) |
||||
|
self.assertEqual(unaffected_init_balance["credit"], 0) |
||||
|
self.assertEqual(unaffected_init_balance["balance"], 0) |
||||
|
self.assertEqual(unaffected_fin_balance["debit"], 0) |
||||
|
self.assertEqual(unaffected_fin_balance["credit"], 0) |
||||
|
self.assertEqual(unaffected_fin_balance["balance"], 0) |
||||
|
|
||||
|
# Add a move at any date 2 years before the balance |
||||
|
# (to create an historic) |
||||
|
self._add_move( |
||||
|
date=self.before_previous_fy_year, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
unaffected_init_balance = self._get_initial_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
unaffected_fin_balance = self._get_final_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_init_balance["debit"], 1000) |
||||
|
self.assertEqual(unaffected_init_balance["credit"], 0) |
||||
|
self.assertEqual(unaffected_init_balance["balance"], 1000) |
||||
|
self.assertEqual(unaffected_fin_balance["debit"], 1000) |
||||
|
self.assertEqual(unaffected_fin_balance["credit"], 0) |
||||
|
self.assertEqual(unaffected_fin_balance["balance"], 1000) |
||||
|
|
||||
|
# Affect the company's result last year |
||||
|
self._add_move( |
||||
|
date=self.previous_fy_date_start, |
||||
|
receivable_debit=1000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=0, |
||||
|
unaffected_debit=0, |
||||
|
unaffected_credit=1000, |
||||
|
) |
||||
|
|
||||
|
# Add another move last year to test the initial balance this year |
||||
|
self._add_move( |
||||
|
date=self.previous_fy_date_start, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=500, |
||||
|
income_debit=500, |
||||
|
income_credit=0, |
||||
|
unaffected_debit=0, |
||||
|
unaffected_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
general_ledger = res_data["general_ledger"] |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
unaffected_init_balance = self._get_initial_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
unaffected_fin_balance = self._get_final_balance( |
||||
|
self.unaffected_account.id, general_ledger |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_init_balance["debit"], 1500) |
||||
|
self.assertEqual(unaffected_init_balance["credit"], 1000) |
||||
|
self.assertEqual(unaffected_init_balance["balance"], 500) |
||||
|
self.assertEqual(unaffected_fin_balance["debit"], 1500) |
||||
|
self.assertEqual(unaffected_fin_balance["credit"], 1000) |
||||
|
self.assertEqual(unaffected_fin_balance["balance"], 500) |
||||
|
|
||||
|
def test_partner_filter(self): |
||||
|
partner_1 = self.env.ref("base.res_partner_1") |
||||
|
partner_2 = self.env.ref("base.res_partner_2") |
||||
|
partner_3 = self.env.ref("base.res_partner_3") |
||||
|
partner_4 = self.env.ref("base.res_partner_4") |
||||
|
partner_1.write({"is_company": False, "parent_id": partner_2.id}) |
||||
|
partner_3.write({"is_company": False}) |
||||
|
|
||||
|
expected_list = [partner_2.id, partner_3.id, partner_4.id] |
||||
|
context = { |
||||
|
"active_ids": [partner_1.id, partner_2.id, partner_3.id, partner_4.id], |
||||
|
"active_model": "res.partner", |
||||
|
} |
||||
|
|
||||
|
wizard = self.env["general.ledger.report.wizard"].with_context(context) |
||||
|
self.assertEqual(wizard._default_partners(), expected_list) |
||||
|
|
||||
|
def test_validate_date(self): |
||||
|
company_id = self.env.ref("base.main_company") |
||||
|
company_id.write({"fiscalyear_last_day": 31, "fiscalyear_last_month": "12"}) |
||||
|
user = self.env.ref("base.user_root").with_context(company_id=company_id.id) |
||||
|
wizard = self.env["general.ledger.report.wizard"].with_context(user=user.id) |
||||
|
self.assertEqual(wizard._init_date_from(), time.strftime("%Y") + "-01-01") |
||||
|
|
||||
|
def test_validate_date_range(self): |
||||
|
data_type = self.env["date.range.type"].create( |
||||
|
{"name": "Fiscal year", "company_id": False, "allow_overlap": False} |
||||
|
) |
||||
|
|
||||
|
dr = self.env["date.range"].create( |
||||
|
{ |
||||
|
"name": "FS2015", |
||||
|
"date_start": "2018-01-01", |
||||
|
"date_end": "2018-12-31", |
||||
|
"type_id": data_type.id, |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
wizard = self.env["general.ledger.report.wizard"].create( |
||||
|
{"date_range_id": dr.id} |
||||
|
) |
||||
|
wizard.onchange_date_range_id() |
||||
|
self.assertEqual(wizard.date_from, date(2018, 1, 1)) |
||||
|
self.assertEqual(wizard.date_to, date(2018, 12, 31)) |
@ -0,0 +1,306 @@ |
|||||
|
# Copyright 2017 ACSONE SA/NV |
||||
|
# Copyright 2019-20 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from datetime import datetime |
||||
|
|
||||
|
from dateutil.relativedelta import relativedelta |
||||
|
|
||||
|
from odoo.fields import Date |
||||
|
from odoo.tests.common import Form, TransactionCase |
||||
|
|
||||
|
|
||||
|
class TestJournalReport(TransactionCase): |
||||
|
def setUp(self): |
||||
|
super(TestJournalReport, self).setUp() |
||||
|
self.AccountObj = self.env["account.account"] |
||||
|
self.InvoiceObj = self.env["account.move"] |
||||
|
self.JournalObj = self.env["account.journal"] |
||||
|
self.MoveObj = self.env["account.move"] |
||||
|
self.TaxObj = self.env["account.tax"] |
||||
|
|
||||
|
self.JournalLedgerReportWizard = self.env["journal.ledger.report.wizard"] |
||||
|
self.JournalLedgerReport = self.env[ |
||||
|
"report.account_financial_report.journal_ledger" |
||||
|
] |
||||
|
self.company = self.env.ref("base.main_company") |
||||
|
self.company.account_sale_tax_id = False |
||||
|
self.company.account_purchase_tax_id = False |
||||
|
|
||||
|
today = datetime.today() |
||||
|
last_year = today - relativedelta(years=1) |
||||
|
|
||||
|
self.previous_fy_date_start = Date.to_string(last_year.replace(month=1, day=1)) |
||||
|
self.previous_fy_date_end = Date.to_string(last_year.replace(month=12, day=31)) |
||||
|
self.fy_date_start = Date.to_string(today.replace(month=1, day=1)) |
||||
|
self.fy_date_end = Date.to_string(today.replace(month=12, day=31)) |
||||
|
|
||||
|
self.receivable_account = self.AccountObj.search( |
||||
|
[("user_type_id.name", "=", "Receivable")], limit=1 |
||||
|
) |
||||
|
self.income_account = self.AccountObj.search( |
||||
|
[("user_type_id.name", "=", "Income")], limit=1 |
||||
|
) |
||||
|
self.expense_account = self.AccountObj.search( |
||||
|
[("user_type_id.name", "=", "Expenses")], limit=1 |
||||
|
) |
||||
|
self.payable_account = self.AccountObj.search( |
||||
|
[("user_type_id.name", "=", "Payable")], limit=1 |
||||
|
) |
||||
|
|
||||
|
self.journal_sale = self.JournalObj.create( |
||||
|
{ |
||||
|
"name": "Test journal sale", |
||||
|
"code": "TST-JRNL-S", |
||||
|
"type": "sale", |
||||
|
"company_id": self.company.id, |
||||
|
} |
||||
|
) |
||||
|
self.journal_purchase = self.JournalObj.create( |
||||
|
{ |
||||
|
"name": "Test journal purchase", |
||||
|
"code": "TST-JRNL-P", |
||||
|
"type": "purchase", |
||||
|
"company_id": self.company.id, |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
self.tax_15_s = self.TaxObj.create( |
||||
|
{ |
||||
|
"sequence": 30, |
||||
|
"name": "Tax 15.0% (Percentage of Price)", |
||||
|
"amount": 15.0, |
||||
|
"amount_type": "percent", |
||||
|
"include_base_amount": False, |
||||
|
"type_tax_use": "sale", |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
self.tax_20_s = self.TaxObj.create( |
||||
|
{ |
||||
|
"sequence": 30, |
||||
|
"name": "Tax 20.0% (Percentage of Price)", |
||||
|
"amount": 20.0, |
||||
|
"amount_type": "percent", |
||||
|
"include_base_amount": False, |
||||
|
"type_tax_use": "sale", |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
self.tax_15_p = self.TaxObj.create( |
||||
|
{ |
||||
|
"sequence": 30, |
||||
|
"name": "Tax 15.0% (Percentage of Price)", |
||||
|
"amount": 15.0, |
||||
|
"amount_type": "percent", |
||||
|
"include_base_amount": False, |
||||
|
"type_tax_use": "purchase", |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
self.tax_20_p = self.TaxObj.create( |
||||
|
{ |
||||
|
"sequence": 30, |
||||
|
"name": "Tax 20.0% (Percentage of Price)", |
||||
|
"amount": 20.0, |
||||
|
"amount_type": "percent", |
||||
|
"include_base_amount": False, |
||||
|
"type_tax_use": "purchase", |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
self.partner_2 = self.env.ref("base.res_partner_2") |
||||
|
|
||||
|
def _add_move( |
||||
|
self, |
||||
|
date, |
||||
|
journal, |
||||
|
receivable_debit, |
||||
|
receivable_credit, |
||||
|
income_debit, |
||||
|
income_credit, |
||||
|
): |
||||
|
move_name = "move name" |
||||
|
move_vals = { |
||||
|
"journal_id": journal.id, |
||||
|
"date": date, |
||||
|
"line_ids": [ |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"name": move_name, |
||||
|
"debit": receivable_debit, |
||||
|
"credit": receivable_credit, |
||||
|
"account_id": self.receivable_account.id, |
||||
|
}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"name": move_name, |
||||
|
"debit": income_debit, |
||||
|
"credit": income_credit, |
||||
|
"account_id": self.income_account.id, |
||||
|
}, |
||||
|
), |
||||
|
], |
||||
|
} |
||||
|
return self.MoveObj.create(move_vals) |
||||
|
|
||||
|
def check_report_journal_debit_credit( |
||||
|
self, res_data, expected_debit, expected_credit |
||||
|
): |
||||
|
self.assertEqual( |
||||
|
expected_debit, sum([rec["debit"] for rec in res_data["Journal_Ledgers"]]) |
||||
|
) |
||||
|
|
||||
|
self.assertEqual( |
||||
|
expected_credit, sum([rec["credit"] for rec in res_data["Journal_Ledgers"]]) |
||||
|
) |
||||
|
|
||||
|
def check_report_journal_debit_credit_taxes( |
||||
|
self, |
||||
|
res_data, |
||||
|
expected_base_debit, |
||||
|
expected_base_credit, |
||||
|
expected_tax_debit, |
||||
|
expected_tax_credit, |
||||
|
): |
||||
|
for rec in res_data["Journal_Ledgers"]: |
||||
|
self.assertEqual( |
||||
|
expected_base_debit, |
||||
|
sum([tax_line["base_debit"] for tax_line in rec["tax_lines"]]), |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_base_credit, |
||||
|
sum([tax_line["base_credit"] for tax_line in rec["tax_lines"]]), |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_tax_debit, |
||||
|
sum([tax_line["tax_debit"] for tax_line in rec["tax_lines"]]), |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_tax_credit, |
||||
|
sum([tax_line["tax_credit"] for tax_line in rec["tax_lines"]]), |
||||
|
) |
||||
|
|
||||
|
def test_01_test_total(self): |
||||
|
today_date = Date.today() |
||||
|
last_year_date = Date.to_string(datetime.today() - relativedelta(years=1)) |
||||
|
|
||||
|
move1 = self._add_move(today_date, self.journal_sale, 0, 100, 100, 0) |
||||
|
move2 = self._add_move(last_year_date, self.journal_sale, 0, 100, 100, 0) |
||||
|
|
||||
|
wiz = self.JournalLedgerReportWizard.create( |
||||
|
{ |
||||
|
"date_from": self.fy_date_start, |
||||
|
"date_to": self.fy_date_end, |
||||
|
"company_id": self.company.id, |
||||
|
"journal_ids": [(6, 0, self.journal_sale.ids)], |
||||
|
"move_target": "all", |
||||
|
} |
||||
|
) |
||||
|
data = wiz._prepare_report_journal_ledger() |
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
self.check_report_journal_debit_credit(res_data, 100, 100) |
||||
|
|
||||
|
move3 = self._add_move(today_date, self.journal_sale, 0, 100, 100, 0) |
||||
|
|
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
self.check_report_journal_debit_credit(res_data, 200, 200) |
||||
|
wiz.move_target = "posted" |
||||
|
data = wiz._prepare_report_journal_ledger() |
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
self.check_report_journal_debit_credit(res_data, 0, 0) |
||||
|
|
||||
|
move1.action_post() |
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
self.check_report_journal_debit_credit(res_data, 100, 100) |
||||
|
|
||||
|
move2.action_post() |
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
self.check_report_journal_debit_credit(res_data, 100, 100) |
||||
|
|
||||
|
move3.action_post() |
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
self.check_report_journal_debit_credit(res_data, 200, 200) |
||||
|
|
||||
|
wiz.date_from = self.previous_fy_date_start |
||||
|
data = wiz._prepare_report_journal_ledger() |
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
self.check_report_journal_debit_credit(res_data, 300, 300) |
||||
|
|
||||
|
def test_02_test_taxes_out_invoice(self): |
||||
|
move_form = Form( |
||||
|
self.env["account.move"].with_context(default_move_type="out_invoice") |
||||
|
) |
||||
|
move_form.partner_id = self.partner_2 |
||||
|
move_form.journal_id = self.journal_sale |
||||
|
with move_form.invoice_line_ids.new() as line_form: |
||||
|
line_form.name = "test" |
||||
|
line_form.quantity = 1.0 |
||||
|
line_form.price_unit = 100 |
||||
|
line_form.account_id = self.income_account |
||||
|
line_form.tax_ids.add(self.tax_15_s) |
||||
|
with move_form.invoice_line_ids.new() as line_form: |
||||
|
line_form.name = "test" |
||||
|
line_form.quantity = 1.0 |
||||
|
line_form.price_unit = 100 |
||||
|
line_form.account_id = self.income_account |
||||
|
line_form.tax_ids.add(self.tax_15_s) |
||||
|
line_form.tax_ids.add(self.tax_20_s) |
||||
|
invoice = move_form.save() |
||||
|
invoice.action_post() |
||||
|
|
||||
|
wiz = self.JournalLedgerReportWizard.create( |
||||
|
{ |
||||
|
"date_from": self.fy_date_start, |
||||
|
"date_to": self.fy_date_end, |
||||
|
"company_id": self.company.id, |
||||
|
"journal_ids": [(6, 0, self.journal_sale.ids)], |
||||
|
"move_target": "all", |
||||
|
} |
||||
|
) |
||||
|
data = wiz._prepare_report_journal_ledger() |
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
self.check_report_journal_debit_credit(res_data, 250, 250) |
||||
|
self.check_report_journal_debit_credit_taxes(res_data, 0, 300, 0, 50) |
||||
|
|
||||
|
def test_03_test_taxes_in_invoice(self): |
||||
|
move_form = Form( |
||||
|
self.env["account.move"].with_context(default_move_type="in_invoice") |
||||
|
) |
||||
|
move_form.partner_id = self.partner_2 |
||||
|
move_form.journal_id = self.journal_purchase |
||||
|
with move_form.invoice_line_ids.new() as line_form: |
||||
|
line_form.name = "test" |
||||
|
line_form.quantity = 1.0 |
||||
|
line_form.price_unit = 100 |
||||
|
line_form.account_id = self.expense_account |
||||
|
line_form.tax_ids.add(self.tax_15_p) |
||||
|
with move_form.invoice_line_ids.new() as line_form: |
||||
|
line_form.name = "test" |
||||
|
line_form.quantity = 1.0 |
||||
|
line_form.price_unit = 100 |
||||
|
line_form.account_id = self.expense_account |
||||
|
line_form.tax_ids.add(self.tax_15_p) |
||||
|
line_form.tax_ids.add(self.tax_20_p) |
||||
|
invoice = move_form.save() |
||||
|
invoice.action_post() |
||||
|
|
||||
|
wiz = self.JournalLedgerReportWizard.create( |
||||
|
{ |
||||
|
"date_from": self.fy_date_start, |
||||
|
"date_to": self.fy_date_end, |
||||
|
"company_id": self.company.id, |
||||
|
"journal_ids": [(6, 0, self.journal_purchase.ids)], |
||||
|
"move_target": "all", |
||||
|
} |
||||
|
) |
||||
|
data = wiz._prepare_report_journal_ledger() |
||||
|
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
||||
|
|
||||
|
self.check_report_journal_debit_credit(res_data, 250, 250) |
||||
|
self.check_report_journal_debit_credit_taxes(res_data, 300, 0, 50, 0) |
@ -0,0 +1,24 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo.tests.common import TransactionCase |
||||
|
|
||||
|
|
||||
|
class TestOpenItems(TransactionCase): |
||||
|
def test_partner_filter(self): |
||||
|
partner_1 = self.env.ref("base.res_partner_1") |
||||
|
partner_2 = self.env.ref("base.res_partner_2") |
||||
|
partner_3 = self.env.ref("base.res_partner_3") |
||||
|
partner_4 = self.env.ref("base.res_partner_4") |
||||
|
partner_1.write({"is_company": False, "parent_id": partner_2.id}) |
||||
|
partner_3.write({"is_company": False}) |
||||
|
|
||||
|
expected_list = [partner_2.id, partner_3.id, partner_4.id] |
||||
|
context = { |
||||
|
"active_ids": [partner_1.id, partner_2.id, partner_3.id, partner_4.id], |
||||
|
"active_model": "res.partner", |
||||
|
} |
||||
|
|
||||
|
wizard = self.env["open.items.report.wizard"].with_context(context) |
||||
|
self.assertEqual(wizard._default_partners(), expected_list) |
@ -0,0 +1,825 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo.tests import common |
||||
|
|
||||
|
|
||||
|
class TestTrialBalanceReport(common.TransactionCase): |
||||
|
def setUp(self): |
||||
|
super(TestTrialBalanceReport, self).setUp() |
||||
|
group_obj = self.env["account.group"] |
||||
|
self.group1 = group_obj.create({"code_prefix_start": "1", "name": "Group 1"}) |
||||
|
self.group11 = group_obj.create( |
||||
|
{"code_prefix_start": "11", "name": "Group 11", "parent_id": self.group1.id} |
||||
|
) |
||||
|
self.group2 = group_obj.create({"code_prefix_start": "2", "name": "Group 2"}) |
||||
|
self.account100 = self._create_account_account( |
||||
|
{ |
||||
|
"code": "100", |
||||
|
"name": "Account 100", |
||||
|
"group_id": self.group1.id, |
||||
|
"user_type_id": self.env.ref("account.data_account_type_receivable").id, |
||||
|
"reconcile": True, |
||||
|
} |
||||
|
) |
||||
|
self.account110 = self.env["account.account"].search( |
||||
|
[ |
||||
|
( |
||||
|
"user_type_id", |
||||
|
"=", |
||||
|
self.env.ref("account.data_unaffected_earnings").id, |
||||
|
) |
||||
|
], |
||||
|
limit=1, |
||||
|
) |
||||
|
self.account200 = self._create_account_account( |
||||
|
{ |
||||
|
"code": "200", |
||||
|
"name": "Account 200", |
||||
|
"group_id": self.group2.id, |
||||
|
"user_type_id": self.env.ref( |
||||
|
"account.data_account_type_other_income" |
||||
|
).id, |
||||
|
} |
||||
|
) |
||||
|
self.account300 = self._create_account_account( |
||||
|
{ |
||||
|
"code": "300", |
||||
|
"name": "Account 300", |
||||
|
"user_type_id": self.env.ref( |
||||
|
"account.data_account_type_other_income" |
||||
|
).id, |
||||
|
} |
||||
|
) |
||||
|
self.account301 = self._create_account_account( |
||||
|
{ |
||||
|
"code": "301", |
||||
|
"name": "Account 301", |
||||
|
"group_id": self.group2.id, |
||||
|
"user_type_id": self.env.ref( |
||||
|
"account.data_account_type_other_income" |
||||
|
).id, |
||||
|
} |
||||
|
) |
||||
|
self.previous_fy_date_start = "2015-01-01" |
||||
|
self.previous_fy_date_end = "2015-12-31" |
||||
|
self.fy_date_start = "2016-01-01" |
||||
|
self.fy_date_end = "2016-12-31" |
||||
|
self.date_start = "2016-01-01" |
||||
|
self.date_end = "2016-12-31" |
||||
|
self.partner = self.env.ref("base.res_partner_12") |
||||
|
self.unaffected_account = self.env["account.account"].search( |
||||
|
[ |
||||
|
( |
||||
|
"user_type_id", |
||||
|
"=", |
||||
|
self.env.ref("account.data_unaffected_earnings").id, |
||||
|
) |
||||
|
], |
||||
|
limit=1, |
||||
|
) |
||||
|
|
||||
|
def _create_account_account(self, vals): |
||||
|
item = self.env["account.account"].create(vals) |
||||
|
if "group_id" in vals: |
||||
|
item.group_id = vals["group_id"] |
||||
|
return item |
||||
|
|
||||
|
def _add_move( |
||||
|
self, |
||||
|
date, |
||||
|
receivable_debit, |
||||
|
receivable_credit, |
||||
|
income_debit, |
||||
|
income_credit, |
||||
|
unaffected_debit=0, |
||||
|
unaffected_credit=0, |
||||
|
): |
||||
|
journal = self.env["account.journal"].search([], limit=1) |
||||
|
partner = self.env.ref("base.res_partner_12") |
||||
|
move_vals = { |
||||
|
"journal_id": journal.id, |
||||
|
"date": date, |
||||
|
"line_ids": [ |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"debit": receivable_debit, |
||||
|
"credit": receivable_credit, |
||||
|
"partner_id": partner.id, |
||||
|
"account_id": self.account100.id, |
||||
|
}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"debit": income_debit, |
||||
|
"credit": income_credit, |
||||
|
"partner_id": partner.id, |
||||
|
"account_id": self.account200.id, |
||||
|
}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"debit": unaffected_debit, |
||||
|
"credit": unaffected_credit, |
||||
|
"partner_id": partner.id, |
||||
|
"account_id": self.account110.id, |
||||
|
}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"debit": receivable_debit, |
||||
|
"credit": receivable_credit, |
||||
|
"partner_id": partner.id, |
||||
|
"account_id": self.account300.id, |
||||
|
}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"debit": receivable_credit, |
||||
|
"credit": receivable_debit, |
||||
|
"partner_id": partner.id, |
||||
|
"account_id": self.account301.id, |
||||
|
}, |
||||
|
), |
||||
|
], |
||||
|
} |
||||
|
move = self.env["account.move"].create(move_vals) |
||||
|
move.action_post() |
||||
|
|
||||
|
def _get_report_lines(self, with_partners=False, hierarchy_on="computed"): |
||||
|
company = self.env.ref("base.main_company") |
||||
|
trial_balance = self.env["trial.balance.report.wizard"].create( |
||||
|
{ |
||||
|
"date_from": self.date_start, |
||||
|
"date_to": self.date_end, |
||||
|
"target_move": "posted", |
||||
|
"hide_account_at_0": True, |
||||
|
"hierarchy_on": hierarchy_on, |
||||
|
"company_id": company.id, |
||||
|
"fy_start_date": self.fy_date_start, |
||||
|
"show_partner_details": with_partners, |
||||
|
} |
||||
|
) |
||||
|
data = trial_balance._prepare_report_trial_balance() |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.trial_balance" |
||||
|
]._get_report_values(trial_balance, data) |
||||
|
return res_data |
||||
|
|
||||
|
def check_account_in_report(self, account_id, trial_balance): |
||||
|
account_in_report = False |
||||
|
for account in trial_balance: |
||||
|
if account["id"] == account_id and account["type"] == "account_type": |
||||
|
account_in_report = True |
||||
|
break |
||||
|
return account_in_report |
||||
|
|
||||
|
def _get_account_lines(self, account_id, trial_balance): |
||||
|
lines = False |
||||
|
for account in trial_balance: |
||||
|
if account["id"] == account_id and account["type"] == "account_type": |
||||
|
lines = { |
||||
|
"initial_balance": account["initial_balance"], |
||||
|
"debit": account["debit"], |
||||
|
"credit": account["credit"], |
||||
|
"final_balance": account["ending_balance"], |
||||
|
} |
||||
|
return lines |
||||
|
|
||||
|
def _get_group_lines(self, group_id, trial_balance): |
||||
|
lines = False |
||||
|
for group in trial_balance: |
||||
|
if group["id"] == group_id and group["type"] == "group_type": |
||||
|
lines = { |
||||
|
"initial_balance": group["initial_balance"], |
||||
|
"debit": group["debit"], |
||||
|
"credit": group["credit"], |
||||
|
"final_balance": group["ending_balance"], |
||||
|
} |
||||
|
return lines |
||||
|
|
||||
|
def check_partner_in_report(self, account_id, partner_id, total_amount): |
||||
|
partner_in_report = False |
||||
|
if account_id in total_amount.keys(): |
||||
|
if partner_id in total_amount[account_id]: |
||||
|
partner_in_report = True |
||||
|
return partner_in_report |
||||
|
|
||||
|
def _get_partner_lines(self, account_id, partner_id, total_amount): |
||||
|
acc_id = account_id |
||||
|
prt_id = partner_id |
||||
|
lines = { |
||||
|
"initial_balance": total_amount[acc_id][prt_id]["initial_balance"], |
||||
|
"debit": total_amount[acc_id][prt_id]["debit"], |
||||
|
"credit": total_amount[acc_id][prt_id]["credit"], |
||||
|
"final_balance": total_amount[acc_id][prt_id]["ending_balance"], |
||||
|
} |
||||
|
return lines |
||||
|
|
||||
|
def _sum_all_accounts(self, trial_balance, feature): |
||||
|
total = 0.0 |
||||
|
for account in trial_balance: |
||||
|
if account["type"] == "account_type": |
||||
|
for key in account.keys(): |
||||
|
if key == feature: |
||||
|
total += account[key] |
||||
|
return total |
||||
|
|
||||
|
def test_00_account_group(self): |
||||
|
self.assertTrue(self.account100 in self.group1.compute_account_ids) |
||||
|
self.assertTrue(self.account200 in self.group2.compute_account_ids) |
||||
|
|
||||
|
def test_01_account_balance_computed(self): |
||||
|
# Make sure there's no account of type "Current Year Earnings" in the |
||||
|
# groups - We change the code |
||||
|
earning_accs = self.env["account.account"].search( |
||||
|
[("user_type_id", "=", self.env.ref("account.data_unaffected_earnings").id)] |
||||
|
) |
||||
|
for acc in earning_accs: |
||||
|
if acc.code.startswith("1") or acc.code.startswith("2"): |
||||
|
acc.code = "999" + acc.code |
||||
|
# Generate the general ledger line |
||||
|
res_data = self._get_report_lines() |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
|
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
self.assertFalse(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
self.assertFalse(check_income_account) |
||||
|
|
||||
|
# Add a move at the previous day of the first day of fiscal year |
||||
|
# to check the initial balance |
||||
|
self._add_move( |
||||
|
date=self.previous_fy_date_end, |
||||
|
receivable_debit=1000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=1000, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines() |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
self.assertFalse(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
account_receivable_lines = self._get_account_lines( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
group1_lines = self._get_group_lines(self.group1.id, trial_balance) |
||||
|
|
||||
|
self.assertEqual(account_receivable_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(account_receivable_lines["debit"], 0) |
||||
|
self.assertEqual(account_receivable_lines["credit"], 0) |
||||
|
self.assertEqual(account_receivable_lines["final_balance"], 1000) |
||||
|
|
||||
|
self.assertEqual(group1_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(group1_lines["debit"], 0) |
||||
|
self.assertEqual(group1_lines["credit"], 0) |
||||
|
self.assertEqual(group1_lines["final_balance"], 1000) |
||||
|
|
||||
|
# Add reversed move of the initial move the first day of fiscal year |
||||
|
# to check the first day of fiscal year is not used |
||||
|
# to compute the initial balance |
||||
|
self._add_move( |
||||
|
date=self.fy_date_start, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines() |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
account_receivable_lines = self._get_account_lines( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
account_income_lines = self._get_account_lines( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
group1_lines = self._get_group_lines(self.group1.id, trial_balance) |
||||
|
group2_lines = self._get_group_lines(self.group2.id, trial_balance) |
||||
|
|
||||
|
self.assertEqual(account_receivable_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(account_receivable_lines["debit"], 0) |
||||
|
self.assertEqual(account_receivable_lines["credit"], 1000) |
||||
|
self.assertEqual(account_receivable_lines["final_balance"], 0) |
||||
|
|
||||
|
self.assertEqual(account_income_lines["initial_balance"], 0) |
||||
|
self.assertEqual(account_income_lines["debit"], 1000) |
||||
|
self.assertEqual(account_income_lines["credit"], 0) |
||||
|
self.assertEqual(account_income_lines["final_balance"], 1000) |
||||
|
|
||||
|
self.assertEqual(group1_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(group1_lines["debit"], 0) |
||||
|
self.assertEqual(group1_lines["credit"], 1000) |
||||
|
self.assertEqual(group1_lines["final_balance"], 0) |
||||
|
|
||||
|
self.assertEqual(group2_lines["initial_balance"], 0) |
||||
|
self.assertEqual(group2_lines["debit"], 1000) |
||||
|
self.assertEqual(group2_lines["credit"], 0) |
||||
|
self.assertEqual(group2_lines["final_balance"], 1000) |
||||
|
|
||||
|
# Add another move at the end day of fiscal year |
||||
|
# to check that it correctly used on report |
||||
|
self._add_move( |
||||
|
date=self.fy_date_end, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines() |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
account_receivable_lines = self._get_account_lines( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
account_income_lines = self._get_account_lines( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
group1_lines = self._get_group_lines(self.group1.id, trial_balance) |
||||
|
group2_lines = self._get_group_lines(self.group2.id, trial_balance) |
||||
|
|
||||
|
self.assertEqual(account_receivable_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(account_receivable_lines["debit"], 0) |
||||
|
self.assertEqual(account_receivable_lines["credit"], 2000) |
||||
|
self.assertEqual(account_receivable_lines["final_balance"], -1000) |
||||
|
|
||||
|
self.assertEqual(account_income_lines["initial_balance"], 0) |
||||
|
self.assertEqual(account_income_lines["debit"], 2000) |
||||
|
self.assertEqual(account_income_lines["credit"], 0) |
||||
|
self.assertEqual(account_income_lines["final_balance"], 2000) |
||||
|
|
||||
|
self.assertEqual(group1_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(group1_lines["debit"], 0) |
||||
|
self.assertEqual(group1_lines["credit"], 2000) |
||||
|
self.assertEqual(group1_lines["final_balance"], -1000) |
||||
|
|
||||
|
self.assertEqual(group2_lines["initial_balance"], 0) |
||||
|
self.assertEqual(group2_lines["debit"], 2000) |
||||
|
self.assertEqual(group2_lines["credit"], 0) |
||||
|
self.assertEqual(group2_lines["final_balance"], 2000) |
||||
|
|
||||
|
def test_02_account_balance_hierarchy(self): |
||||
|
# Generate the general ledger line |
||||
|
res_data = self._get_report_lines(hierarchy_on="relation") |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
self.assertFalse(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
self.assertFalse(check_income_account) |
||||
|
|
||||
|
# Add a move at the previous day of the first day of fiscal year |
||||
|
# to check the initial balance |
||||
|
self._add_move( |
||||
|
date=self.previous_fy_date_end, |
||||
|
receivable_debit=1000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=1000, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines(hierarchy_on="relation") |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
self.assertFalse(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
account_receivable_lines = self._get_account_lines( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
group1_lines = self._get_group_lines(self.group1.id, trial_balance) |
||||
|
|
||||
|
self.assertEqual(account_receivable_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(account_receivable_lines["debit"], 0) |
||||
|
self.assertEqual(account_receivable_lines["credit"], 0) |
||||
|
self.assertEqual(account_receivable_lines["final_balance"], 1000) |
||||
|
|
||||
|
self.assertEqual(group1_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(group1_lines["debit"], 0) |
||||
|
self.assertEqual(group1_lines["credit"], 0) |
||||
|
self.assertEqual(group1_lines["final_balance"], 1000) |
||||
|
|
||||
|
# Add reversale move of the initial move the first day of fiscal year |
||||
|
# to check the first day of fiscal year is not used |
||||
|
# to compute the initial balance |
||||
|
self._add_move( |
||||
|
date=self.fy_date_start, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines(hierarchy_on="relation") |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
account_receivable_lines = self._get_account_lines( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
account_income_lines = self._get_account_lines( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
group1_lines = self._get_group_lines(self.group1.id, trial_balance) |
||||
|
group2_lines = self._get_group_lines(self.group2.id, trial_balance) |
||||
|
|
||||
|
self.assertEqual(account_receivable_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(account_receivable_lines["debit"], 0) |
||||
|
self.assertEqual(account_receivable_lines["credit"], 1000) |
||||
|
self.assertEqual(account_receivable_lines["final_balance"], 0) |
||||
|
|
||||
|
self.assertEqual(account_income_lines["initial_balance"], 0) |
||||
|
self.assertEqual(account_income_lines["debit"], 1000) |
||||
|
self.assertEqual(account_income_lines["credit"], 0) |
||||
|
self.assertEqual(account_income_lines["final_balance"], 1000) |
||||
|
|
||||
|
self.assertEqual(group1_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(group1_lines["debit"], 0) |
||||
|
self.assertEqual(group1_lines["credit"], 1000) |
||||
|
self.assertEqual(group1_lines["final_balance"], 0) |
||||
|
|
||||
|
self.assertEqual(group2_lines["initial_balance"], 0) |
||||
|
self.assertEqual(group2_lines["debit"], 2000) |
||||
|
self.assertEqual(group2_lines["credit"], 0) |
||||
|
self.assertEqual(group2_lines["final_balance"], 2000) |
||||
|
|
||||
|
# Add another move at the end day of fiscal year |
||||
|
# to check that it correctly used on report |
||||
|
self._add_move( |
||||
|
date=self.fy_date_end, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines(hierarchy_on="relation") |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
check_receivable_account = self.check_account_in_report( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_receivable_account) |
||||
|
check_income_account = self.check_account_in_report( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_income_account) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
account_receivable_lines = self._get_account_lines( |
||||
|
self.account100.id, trial_balance |
||||
|
) |
||||
|
account_income_lines = self._get_account_lines( |
||||
|
self.account200.id, trial_balance |
||||
|
) |
||||
|
group1_lines = self._get_group_lines(self.group1.id, trial_balance) |
||||
|
group2_lines = self._get_group_lines(self.group2.id, trial_balance) |
||||
|
|
||||
|
self.assertEqual(account_receivable_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(account_receivable_lines["debit"], 0) |
||||
|
self.assertEqual(account_receivable_lines["credit"], 2000) |
||||
|
self.assertEqual(account_receivable_lines["final_balance"], -1000) |
||||
|
|
||||
|
self.assertEqual(account_income_lines["initial_balance"], 0) |
||||
|
self.assertEqual(account_income_lines["debit"], 2000) |
||||
|
self.assertEqual(account_income_lines["credit"], 0) |
||||
|
self.assertEqual(account_income_lines["final_balance"], 2000) |
||||
|
|
||||
|
self.assertEqual(group1_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(group1_lines["debit"], 0) |
||||
|
self.assertEqual(group1_lines["credit"], 2000) |
||||
|
self.assertEqual(group1_lines["final_balance"], -1000) |
||||
|
|
||||
|
self.assertEqual(group2_lines["initial_balance"], 0) |
||||
|
self.assertEqual(group2_lines["debit"], 4000) |
||||
|
self.assertEqual(group2_lines["credit"], 0) |
||||
|
self.assertEqual(group2_lines["final_balance"], 4000) |
||||
|
|
||||
|
def test_03_partner_balance(self): |
||||
|
# Generate the trial balance line |
||||
|
res_data = self._get_report_lines(with_partners=True) |
||||
|
total_amount = res_data["total_amount"] |
||||
|
check_partner_receivable = self.check_partner_in_report( |
||||
|
self.account100.id, self.partner.id, total_amount |
||||
|
) |
||||
|
self.assertFalse(check_partner_receivable) |
||||
|
|
||||
|
# Add a move at the previous day of the first day of fiscal year |
||||
|
# to check the initial balance |
||||
|
self._add_move( |
||||
|
date=self.previous_fy_date_end, |
||||
|
receivable_debit=1000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=1000, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines(with_partners=True) |
||||
|
total_amount = res_data["total_amount"] |
||||
|
check_partner_receivable = self.check_partner_in_report( |
||||
|
self.account100.id, self.partner.id, total_amount |
||||
|
) |
||||
|
self.assertTrue(check_partner_receivable) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
partner_lines = self._get_partner_lines( |
||||
|
self.account100.id, self.partner.id, total_amount |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(partner_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(partner_lines["debit"], 0) |
||||
|
self.assertEqual(partner_lines["credit"], 0) |
||||
|
self.assertEqual(partner_lines["final_balance"], 1000) |
||||
|
|
||||
|
# Add reversale move of the initial move the first day of fiscal year |
||||
|
# to check the first day of fiscal year is not used |
||||
|
# to compute the initial balance |
||||
|
self._add_move( |
||||
|
date=self.fy_date_start, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines(with_partners=True) |
||||
|
total_amount = res_data["total_amount"] |
||||
|
check_partner_receivable = self.check_partner_in_report( |
||||
|
self.account100.id, self.partner.id, total_amount |
||||
|
) |
||||
|
self.assertTrue(check_partner_receivable) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
partner_lines = self._get_partner_lines( |
||||
|
self.account100.id, self.partner.id, total_amount |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(partner_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(partner_lines["debit"], 0) |
||||
|
self.assertEqual(partner_lines["credit"], 1000) |
||||
|
self.assertEqual(partner_lines["final_balance"], 0) |
||||
|
|
||||
|
# Add another move at the end day of fiscal year |
||||
|
# to check that it correctly used on report |
||||
|
self._add_move( |
||||
|
date=self.fy_date_end, |
||||
|
receivable_debit=0, |
||||
|
receivable_credit=1000, |
||||
|
income_debit=1000, |
||||
|
income_credit=0, |
||||
|
) |
||||
|
|
||||
|
# Re Generate the trial balance line |
||||
|
res_data = self._get_report_lines(with_partners=True) |
||||
|
total_amount = res_data["total_amount"] |
||||
|
check_partner_receivable = self.check_partner_in_report( |
||||
|
self.account100.id, self.partner.id, total_amount |
||||
|
) |
||||
|
self.assertTrue(check_partner_receivable) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
partner_lines = self._get_partner_lines( |
||||
|
self.account100.id, self.partner.id, total_amount |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(partner_lines["initial_balance"], 1000) |
||||
|
self.assertEqual(partner_lines["debit"], 0) |
||||
|
self.assertEqual(partner_lines["credit"], 2000) |
||||
|
self.assertEqual(partner_lines["final_balance"], -1000) |
||||
|
|
||||
|
def test_04_undistributed_pl(self): |
||||
|
# Add a P&L Move in the previous FY |
||||
|
journal = self.env["account.journal"].search([], limit=1) |
||||
|
move_vals = { |
||||
|
"journal_id": journal.id, |
||||
|
"date": self.previous_fy_date_end, |
||||
|
"line_ids": [ |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{"debit": 0.0, "credit": 1000.0, "account_id": self.account300.id}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{"debit": 1000.0, "credit": 0.0, "account_id": self.account100.id}, |
||||
|
), |
||||
|
], |
||||
|
} |
||||
|
move = self.env["account.move"].create(move_vals) |
||||
|
move.action_post() |
||||
|
# Generate the trial balance line |
||||
|
company = self.env.ref("base.main_company") |
||||
|
trial_balance = self.env["trial.balance.report.wizard"].create( |
||||
|
{ |
||||
|
"date_from": self.date_start, |
||||
|
"date_to": self.date_end, |
||||
|
"target_move": "posted", |
||||
|
"hide_account_at_0": False, |
||||
|
"hierarchy_on": "none", |
||||
|
"company_id": company.id, |
||||
|
"fy_start_date": self.fy_date_start, |
||||
|
} |
||||
|
) |
||||
|
data = trial_balance._prepare_report_trial_balance() |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.trial_balance" |
||||
|
]._get_report_values(trial_balance, data) |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
|
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
unaffected_lines = self._get_account_lines( |
||||
|
self.unaffected_account.id, trial_balance |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_lines["initial_balance"], -1000) |
||||
|
self.assertEqual(unaffected_lines["debit"], 0) |
||||
|
self.assertEqual(unaffected_lines["credit"], 0) |
||||
|
self.assertEqual(unaffected_lines["final_balance"], -1000) |
||||
|
# Add a P&L Move to the current FY |
||||
|
journal = self.env["account.journal"].search([], limit=1) |
||||
|
move_vals = { |
||||
|
"journal_id": journal.id, |
||||
|
"date": self.date_start, |
||||
|
"line_ids": [ |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{"debit": 0.0, "credit": 1000.0, "account_id": self.account300.id}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{"debit": 1000.0, "credit": 0.0, "account_id": self.account100.id}, |
||||
|
), |
||||
|
], |
||||
|
} |
||||
|
move = self.env["account.move"].create(move_vals) |
||||
|
move.action_post() |
||||
|
# Re Generate the trial balance line |
||||
|
trial_balance = self.env["trial.balance.report.wizard"].create( |
||||
|
{ |
||||
|
"date_from": self.date_start, |
||||
|
"date_to": self.date_end, |
||||
|
"target_move": "posted", |
||||
|
"hide_account_at_0": False, |
||||
|
"hierarchy_on": "none", |
||||
|
"company_id": company.id, |
||||
|
"fy_start_date": self.fy_date_start, |
||||
|
} |
||||
|
) |
||||
|
data = trial_balance._prepare_report_trial_balance() |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.trial_balance" |
||||
|
]._get_report_values(trial_balance, data) |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
# The unaffected earnings account is not affected by a journal entry |
||||
|
# made to the P&L in the current fiscal year. |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
unaffected_lines = self._get_account_lines( |
||||
|
self.unaffected_account.id, trial_balance |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_lines["initial_balance"], -1000) |
||||
|
self.assertEqual(unaffected_lines["debit"], 0) |
||||
|
self.assertEqual(unaffected_lines["credit"], 0) |
||||
|
self.assertEqual(unaffected_lines["final_balance"], -1000) |
||||
|
# Add a Move including Unaffected Earnings to the current FY |
||||
|
journal = self.env["account.journal"].search([], limit=1) |
||||
|
move_vals = { |
||||
|
"journal_id": journal.id, |
||||
|
"date": self.date_start, |
||||
|
"line_ids": [ |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{"debit": 0.0, "credit": 1000.0, "account_id": self.account110.id}, |
||||
|
), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{"debit": 1000.0, "credit": 0.0, "account_id": self.account100.id}, |
||||
|
), |
||||
|
], |
||||
|
} |
||||
|
move = self.env["account.move"].create(move_vals) |
||||
|
move.action_post() |
||||
|
# Re Generate the trial balance line |
||||
|
trial_balance = self.env["trial.balance.report.wizard"].create( |
||||
|
{ |
||||
|
"date_from": self.date_start, |
||||
|
"date_to": self.date_end, |
||||
|
"target_move": "posted", |
||||
|
"hide_account_at_0": False, |
||||
|
"hierarchy_on": "none", |
||||
|
"company_id": company.id, |
||||
|
"fy_start_date": self.fy_date_start, |
||||
|
} |
||||
|
) |
||||
|
data = trial_balance._prepare_report_trial_balance() |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.trial_balance" |
||||
|
]._get_report_values(trial_balance, data) |
||||
|
trial_balance = res_data["trial_balance"] |
||||
|
# The unaffected earnings account affected by a journal entry |
||||
|
# made to the unaffected earnings in the current fiscal year. |
||||
|
check_unaffected_account = self.check_account_in_report( |
||||
|
self.unaffected_account.id, trial_balance |
||||
|
) |
||||
|
self.assertTrue(check_unaffected_account) |
||||
|
|
||||
|
unaffected_lines = self._get_account_lines( |
||||
|
self.unaffected_account.id, trial_balance |
||||
|
) |
||||
|
|
||||
|
self.assertEqual(unaffected_lines["initial_balance"], -1000) |
||||
|
self.assertEqual(unaffected_lines["debit"], 0) |
||||
|
self.assertEqual(unaffected_lines["credit"], 1000) |
||||
|
self.assertEqual(unaffected_lines["final_balance"], -2000) |
||||
|
|
||||
|
# The totals for the Trial Balance are zero |
||||
|
total_initial_balance = self._sum_all_accounts(trial_balance, "initial_balance") |
||||
|
total_final_balance = self._sum_all_accounts(trial_balance, "ending_balance") |
||||
|
total_debit = self._sum_all_accounts(trial_balance, "debit") |
||||
|
total_credit = self._sum_all_accounts(trial_balance, "credit") |
||||
|
|
||||
|
self.assertEqual(total_initial_balance, 0) |
||||
|
self.assertEqual(total_final_balance, 0) |
||||
|
self.assertEqual(total_debit, total_credit) |
@ -0,0 +1,368 @@ |
|||||
|
# Copyright 2018 Forest and Biomass Romania |
||||
|
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
from datetime import date |
||||
|
|
||||
|
from odoo.tests import common |
||||
|
|
||||
|
|
||||
|
class TestVATReport(common.TransactionCase): |
||||
|
def setUp(self): |
||||
|
super(TestVATReport, self).setUp() |
||||
|
self.date_from = time.strftime("%Y-%m-01") |
||||
|
self.date_to = time.strftime("%Y-%m-28") |
||||
|
self.company = self.env.ref("base.main_company") |
||||
|
self.receivable_account = self.env["account.account"].search( |
||||
|
[ |
||||
|
("company_id", "=", self.company.id), |
||||
|
("user_type_id.name", "=", "Receivable"), |
||||
|
], |
||||
|
limit=1, |
||||
|
) |
||||
|
self.income_account = self.env["account.account"].search( |
||||
|
[ |
||||
|
("company_id", "=", self.company.id), |
||||
|
("user_type_id.name", "=", "Income"), |
||||
|
], |
||||
|
limit=1, |
||||
|
) |
||||
|
self.tax_account = self.env["account.account"].search( |
||||
|
[ |
||||
|
("company_id", "=", self.company.id), |
||||
|
( |
||||
|
"user_type_id", |
||||
|
"=", |
||||
|
self.env.ref( |
||||
|
"account.data_account_type_non_current_liabilities" |
||||
|
).id, |
||||
|
), |
||||
|
], |
||||
|
limit=1, |
||||
|
) |
||||
|
self.bank_journal = self.env["account.journal"].search( |
||||
|
[("type", "=", "bank"), ("company_id", "=", self.company.id)], limit=1 |
||||
|
) |
||||
|
self.tax_tag_01 = self.env["account.account.tag"].create( |
||||
|
{ |
||||
|
"name": "Tag 01", |
||||
|
"applicability": "taxes", |
||||
|
"country_id": self.company.country_id.id, |
||||
|
} |
||||
|
) |
||||
|
self.tax_tag_02 = self.env["account.account.tag"].create( |
||||
|
{ |
||||
|
"name": "Tag 02", |
||||
|
"applicability": "taxes", |
||||
|
"country_id": self.company.country_id.id, |
||||
|
} |
||||
|
) |
||||
|
self.tax_tag_03 = self.env["account.account.tag"].create( |
||||
|
{ |
||||
|
"name": "Tag 03", |
||||
|
"applicability": "taxes", |
||||
|
"country_id": self.company.country_id.id, |
||||
|
} |
||||
|
) |
||||
|
self.tax_group_10 = self.env["account.tax.group"].create( |
||||
|
{"name": "Tax 10%", "sequence": 1} |
||||
|
) |
||||
|
self.tax_group_20 = self.env["account.tax.group"].create( |
||||
|
{"name": "Tax 20%", "sequence": 2} |
||||
|
) |
||||
|
self.tax_10 = self.env["account.tax"].create( |
||||
|
{ |
||||
|
"name": "Tax 10.0%", |
||||
|
"amount": 10.0, |
||||
|
"amount_type": "percent", |
||||
|
"type_tax_use": "sale", |
||||
|
"company_id": self.company.id, |
||||
|
"tax_group_id": self.tax_group_10.id, |
||||
|
"invoice_repartition_line_ids": [ |
||||
|
(0, 0, {"factor_percent": 100, "repartition_type": "base"}), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"factor_percent": 100, |
||||
|
"repartition_type": "tax", |
||||
|
"account_id": self.tax_account.id, |
||||
|
"tag_ids": [ |
||||
|
(6, 0, [self.tax_tag_01.id, self.tax_tag_02.id]) |
||||
|
], |
||||
|
}, |
||||
|
), |
||||
|
], |
||||
|
"refund_repartition_line_ids": [ |
||||
|
(0, 0, {"factor_percent": 100, "repartition_type": "base"}), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"factor_percent": 100, |
||||
|
"repartition_type": "tax", |
||||
|
"account_id": self.tax_account.id, |
||||
|
}, |
||||
|
), |
||||
|
], |
||||
|
} |
||||
|
) |
||||
|
self.tax_20 = self.env["account.tax"].create( |
||||
|
{ |
||||
|
"sequence": 30, |
||||
|
"name": "Tax 20.0%", |
||||
|
"amount": 20.0, |
||||
|
"amount_type": "percent", |
||||
|
"type_tax_use": "sale", |
||||
|
"company_id": self.company.id, |
||||
|
"cash_basis_transition_account_id": self.tax_account.id, |
||||
|
"tax_group_id": self.tax_group_20.id, |
||||
|
"invoice_repartition_line_ids": [ |
||||
|
(0, 0, {"factor_percent": 100, "repartition_type": "base"}), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"factor_percent": 100, |
||||
|
"repartition_type": "tax", |
||||
|
"account_id": self.tax_account.id, |
||||
|
"tag_ids": [ |
||||
|
(6, 0, [self.tax_tag_02.id, self.tax_tag_03.id]) |
||||
|
], |
||||
|
}, |
||||
|
), |
||||
|
], |
||||
|
"refund_repartition_line_ids": [ |
||||
|
(0, 0, {"factor_percent": 100, "repartition_type": "base"}), |
||||
|
( |
||||
|
0, |
||||
|
0, |
||||
|
{ |
||||
|
"factor_percent": 100, |
||||
|
"repartition_type": "tax", |
||||
|
"account_id": self.tax_account.id, |
||||
|
}, |
||||
|
), |
||||
|
], |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
move_form = common.Form( |
||||
|
self.env["account.move"].with_context(default_move_type="out_invoice") |
||||
|
) |
||||
|
move_form.partner_id = self.env.ref("base.res_partner_2") |
||||
|
move_form.invoice_date = time.strftime("%Y-%m-03") |
||||
|
with move_form.invoice_line_ids.new() as line_form: |
||||
|
line_form.product_id = self.env.ref("product.product_product_4") |
||||
|
line_form.quantity = 1.0 |
||||
|
line_form.price_unit = 100.0 |
||||
|
line_form.account_id = self.income_account |
||||
|
line_form.tax_ids.add(self.tax_10) |
||||
|
invoice = move_form.save() |
||||
|
invoice.action_post() |
||||
|
|
||||
|
move_form = common.Form( |
||||
|
self.env["account.move"].with_context(default_move_type="out_invoice") |
||||
|
) |
||||
|
move_form.partner_id = self.env.ref("base.res_partner_2") |
||||
|
move_form.invoice_date = time.strftime("%Y-%m-04") |
||||
|
with move_form.invoice_line_ids.new() as line_form: |
||||
|
line_form.product_id = self.env.ref("product.product_product_4") |
||||
|
line_form.quantity = 1.0 |
||||
|
line_form.price_unit = 250.0 |
||||
|
line_form.account_id = self.income_account |
||||
|
line_form.tax_ids.add(self.tax_20) |
||||
|
invoice = move_form.save() |
||||
|
invoice.action_post() |
||||
|
|
||||
|
def _get_report_lines(self, taxgroups=False): |
||||
|
based_on = "taxtags" |
||||
|
if taxgroups: |
||||
|
based_on = "taxgroups" |
||||
|
vat_report = self.env["vat.report.wizard"].create( |
||||
|
{ |
||||
|
"date_from": self.date_from, |
||||
|
"date_to": self.date_to, |
||||
|
"company_id": self.company.id, |
||||
|
"based_on": based_on, |
||||
|
"tax_detail": True, |
||||
|
} |
||||
|
) |
||||
|
data = vat_report._prepare_vat_report() |
||||
|
res_data = self.env[ |
||||
|
"report.account_financial_report.vat_report" |
||||
|
]._get_report_values(vat_report, data) |
||||
|
return res_data |
||||
|
|
||||
|
def check_tag_or_group_in_report(self, tag_or_group_name, vat_report): |
||||
|
tag_or_group_in_report = False |
||||
|
for tag_or_group in vat_report: |
||||
|
if tag_or_group["name"] == tag_or_group_name: |
||||
|
tag_or_group_in_report = True |
||||
|
break |
||||
|
return tag_or_group_in_report |
||||
|
|
||||
|
def check_tax_in_report(self, tax_name, vat_report): |
||||
|
tax_in_report = False |
||||
|
for tag_or_group in vat_report: |
||||
|
if tag_or_group["taxes"]: |
||||
|
for tax in tag_or_group["taxes"]: |
||||
|
if tax["name"] == tax_name: |
||||
|
tax_in_report = True |
||||
|
return tax_in_report |
||||
|
|
||||
|
def _get_tag_or_group_line(self, tag_or_group_name, vat_report): |
||||
|
tag_or_group_net = False |
||||
|
tag_or_group_tax = False |
||||
|
for tag_or_group in vat_report: |
||||
|
if tag_or_group["name"] == tag_or_group_name: |
||||
|
tag_or_group_net = tag_or_group["net"] |
||||
|
tag_or_group_tax = tag_or_group["tax"] |
||||
|
return tag_or_group_net, tag_or_group_tax |
||||
|
|
||||
|
def _get_tax_line(self, tax_name, vat_report): |
||||
|
tax_net = False |
||||
|
tax_tax = False |
||||
|
for tag_or_group in vat_report: |
||||
|
if tag_or_group["taxes"]: |
||||
|
for tax in tag_or_group["taxes"]: |
||||
|
if tax["name"] == tax_name: |
||||
|
tax_net = tax["net"] |
||||
|
tax_tax = tax["tax"] |
||||
|
return tax_net, tax_tax |
||||
|
|
||||
|
def test_01_compute(self): |
||||
|
# Generate the vat lines |
||||
|
res_data = self._get_report_lines() |
||||
|
vat_report = res_data["vat_report"] |
||||
|
|
||||
|
# Check report based on taxtags |
||||
|
check_tax_tag_01 = self.check_tag_or_group_in_report( |
||||
|
self.tax_tag_01.name, vat_report |
||||
|
) |
||||
|
self.assertTrue(check_tax_tag_01) |
||||
|
check_tax_tag_02 = self.check_tag_or_group_in_report( |
||||
|
self.tax_tag_02.name, vat_report |
||||
|
) |
||||
|
self.assertTrue(check_tax_tag_02) |
||||
|
check_tax_tag_03 = self.check_tag_or_group_in_report( |
||||
|
self.tax_tag_03.name, vat_report |
||||
|
) |
||||
|
self.assertTrue(check_tax_tag_03) |
||||
|
check_tax_10 = self.check_tax_in_report(self.tax_10.name, vat_report) |
||||
|
self.assertTrue(check_tax_10) |
||||
|
check_tax_20 = self.check_tax_in_report(self.tax_20.name, vat_report) |
||||
|
self.assertTrue(check_tax_20) |
||||
|
|
||||
|
tag_01_net, tag_01_tax = self._get_tag_or_group_line( |
||||
|
self.tax_tag_01.name, vat_report |
||||
|
) |
||||
|
tag_02_net, tag_02_tax = self._get_tag_or_group_line( |
||||
|
self.tax_tag_02.name, vat_report |
||||
|
) |
||||
|
tag_03_net, tag_03_tax = self._get_tag_or_group_line( |
||||
|
self.tax_tag_03.name, vat_report |
||||
|
) |
||||
|
tax_10_net, tax_10_tax = self._get_tax_line(self.tax_10.name, vat_report) |
||||
|
tax_20_net, tax_20_tax = self._get_tax_line(self.tax_20.name, vat_report) |
||||
|
|
||||
|
self.assertEqual(tag_01_net, -100) |
||||
|
self.assertEqual(tag_01_tax, -10) |
||||
|
self.assertEqual(tag_02_net, -350) |
||||
|
self.assertEqual(tag_02_tax, -60) |
||||
|
self.assertEqual(tag_03_net, -250) |
||||
|
self.assertEqual(tag_03_tax, -50) |
||||
|
self.assertEqual(tax_10_net, -100) |
||||
|
self.assertEqual(tax_10_tax, -10) |
||||
|
self.assertEqual(tax_20_net, -250) |
||||
|
self.assertEqual(tax_20_tax, -50) |
||||
|
|
||||
|
# Check report based on taxgroups |
||||
|
res_data = self._get_report_lines(taxgroups=True) |
||||
|
vat_report = res_data["vat_report"] |
||||
|
|
||||
|
check_group_10 = self.check_tag_or_group_in_report( |
||||
|
self.tax_group_10.name, vat_report |
||||
|
) |
||||
|
self.assertTrue(check_group_10) |
||||
|
check_group_20 = self.check_tag_or_group_in_report( |
||||
|
self.tax_group_20.name, vat_report |
||||
|
) |
||||
|
self.assertTrue(check_group_20) |
||||
|
check_tax_10 = self.check_tax_in_report(self.tax_10.name, vat_report) |
||||
|
self.assertTrue(check_tax_10) |
||||
|
check_tax_20 = self.check_tax_in_report(self.tax_20.name, vat_report) |
||||
|
self.assertTrue(check_tax_20) |
||||
|
|
||||
|
group_10_net, group_10_tax = self._get_tag_or_group_line( |
||||
|
self.tax_group_10.name, vat_report |
||||
|
) |
||||
|
group_20_net, group_20_tax = self._get_tag_or_group_line( |
||||
|
self.tax_group_20.name, vat_report |
||||
|
) |
||||
|
tax_10_net, tax_10_tax = self._get_tax_line(self.tax_10.name, vat_report) |
||||
|
tax_20_net, tax_20_tax = self._get_tax_line(self.tax_20.name, vat_report) |
||||
|
|
||||
|
self.assertEqual(group_10_net, -100) |
||||
|
self.assertEqual(group_10_tax, -10) |
||||
|
self.assertEqual(group_20_net, -250) |
||||
|
self.assertEqual(group_20_tax, -50) |
||||
|
self.assertEqual(tax_10_net, -100) |
||||
|
self.assertEqual(tax_10_tax, -10) |
||||
|
self.assertEqual(tax_20_net, -250) |
||||
|
self.assertEqual(tax_20_tax, -50) |
||||
|
|
||||
|
def test_wizard_date_range(self): |
||||
|
vat_wizard = self.env["vat.report.wizard"] |
||||
|
date_range = self.env["date.range"] |
||||
|
self.type = self.env["date.range.type"].create( |
||||
|
{"name": "Month", "company_id": False, "allow_overlap": False} |
||||
|
) |
||||
|
dt = date_range.create( |
||||
|
{ |
||||
|
"name": "FS2016", |
||||
|
"date_start": time.strftime("%Y-%m-01"), |
||||
|
"date_end": time.strftime("%Y-%m-28"), |
||||
|
"type_id": self.type.id, |
||||
|
} |
||||
|
) |
||||
|
wizard = vat_wizard.create( |
||||
|
{ |
||||
|
"date_range_id": dt.id, |
||||
|
"date_from": time.strftime("%Y-%m-28"), |
||||
|
"date_to": time.strftime("%Y-%m-01"), |
||||
|
"tax_detail": True, |
||||
|
} |
||||
|
) |
||||
|
wizard.onchange_date_range_id() |
||||
|
self.assertEqual( |
||||
|
wizard.date_from, date(date.today().year, date.today().month, 1) |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
wizard.date_to, date(date.today().year, date.today().month, 28) |
||||
|
) |
||||
|
wizard._export("qweb-pdf") |
||||
|
wizard.button_export_html() |
||||
|
wizard.button_export_pdf() |
||||
|
wizard.button_export_xlsx() |
||||
|
wizard = vat_wizard.create( |
||||
|
{ |
||||
|
"date_range_id": dt.id, |
||||
|
"date_from": time.strftime("%Y-%m-28"), |
||||
|
"date_to": time.strftime("%Y-%m-01"), |
||||
|
"based_on": "taxgroups", |
||||
|
"tax_detail": True, |
||||
|
} |
||||
|
) |
||||
|
wizard.onchange_date_range_id() |
||||
|
self.assertEqual( |
||||
|
wizard.date_from, date(date.today().year, date.today().month, 1) |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
wizard.date_to, date(date.today().year, date.today().month, 28) |
||||
|
) |
||||
|
wizard._export("qweb-pdf") |
||||
|
wizard.button_export_html() |
||||
|
wizard.button_export_pdf() |
||||
|
wizard.button_export_xlsx() |
@ -0,0 +1,14 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<record model="ir.ui.view" id="view_account_specific_form"> |
||||
|
<field name="name">account.account.form.inherit</field> |
||||
|
<field name="inherit_id" ref="account.view_account_form" /> |
||||
|
<field name="model">account.account</field> |
||||
|
<field name="type">form</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="deprecated" position="after"> |
||||
|
<field name="centralized" /> |
||||
|
</field> |
||||
|
</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="report_aged_partner_balance"> |
||||
|
<div class="o_account_financial_reports_page"> |
||||
|
<t t-call="account_financial_report.report_buttons" /> |
||||
|
<t t-call="account_financial_report.report_aged_partner_balance_base" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="report_general_ledger"> |
||||
|
<div class="o_account_financial_reports_page"> |
||||
|
<t t-call="account_financial_report.report_buttons" /> |
||||
|
<t t-call="account_financial_report.report_general_ledger_base" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="report_journal_ledger"> |
||||
|
<div class="o_account_financial_reports_page"> |
||||
|
<t t-call="account_financial_report.report_buttons" /> |
||||
|
<t t-call="account_financial_report.report_journal_ledger_base" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="report_open_items"> |
||||
|
<div class="o_account_financial_reports_page"> |
||||
|
<t t-call="account_financial_report.report_buttons" /> |
||||
|
<t t-call="account_financial_report.report_open_items_base" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,83 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template |
||||
|
id="account_financial_report_assets_backend" |
||||
|
name="account_financial_report assets" |
||||
|
inherit_id="web.assets_backend" |
||||
|
> |
||||
|
<xpath expr="." position="inside"> |
||||
|
<link |
||||
|
href="/account_financial_report/static/src/css/report.css" |
||||
|
rel="stylesheet" |
||||
|
/> |
||||
|
<script |
||||
|
type="text/javascript" |
||||
|
src="/account_financial_report/static/src/js/account_financial_report_backend.js" |
||||
|
/> |
||||
|
<script |
||||
|
type="text/javascript" |
||||
|
src="/account_financial_report/static/src/js/account_financial_report_widgets.js" |
||||
|
/> |
||||
|
</xpath> |
||||
|
</template> |
||||
|
<template id="report_buttons"> |
||||
|
<div class="button_row"> |
||||
|
<button class="o_account_financial_reports_print btn btn-sm oe_button"> |
||||
|
<span class="fa fa-print" /> |
||||
|
Print |
||||
|
</button> |
||||
|
<button class="o_account_financial_reports_export btn btn-sm oe_button"> |
||||
|
<span class="fa fa-download" /> |
||||
|
Export |
||||
|
</button> |
||||
|
</div> |
||||
|
</template> |
||||
|
<record id="action_report_general_ledger" model="ir.actions.client"> |
||||
|
<field name="name">General Ledger</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field |
||||
|
name="context" |
||||
|
eval="{'model': 'report.account_financial_report.general_ledger'}" |
||||
|
/> |
||||
|
</record> |
||||
|
<record id="action_report_journal_ledger" model="ir.actions.client"> |
||||
|
<field name="name">Journal</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field |
||||
|
name="context" |
||||
|
eval="{'model': 'report.account_financial_report.journal_ledger'}" |
||||
|
/> |
||||
|
</record> |
||||
|
<record id="action_report_open_items" model="ir.actions.client"> |
||||
|
<field name="name">Open Items</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field |
||||
|
name="context" |
||||
|
eval="{'model': 'report.account_financial_report.open_items'}" |
||||
|
/> |
||||
|
</record> |
||||
|
<record id="action_report_trial_balance" model="ir.actions.client"> |
||||
|
<field name="name">Trial Balance</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field |
||||
|
name="context" |
||||
|
eval="{'model': 'report.account_financial_report.trial_balance'}" |
||||
|
/> |
||||
|
</record> |
||||
|
<record id="action_report_aged_partner_balance" model="ir.actions.client"> |
||||
|
<field name="name">Aged Partner Balance</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field |
||||
|
name="context" |
||||
|
eval="{'model': 'report.account_financial_report.aged_partner_balance'}" |
||||
|
/> |
||||
|
</record> |
||||
|
<record id="action_report_vat_report" model="ir.actions.client"> |
||||
|
<field name="name">VAT Report</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field |
||||
|
name="context" |
||||
|
eval="{'model': 'report.account_financial_report.vat_report'}" |
||||
|
/> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="report_trial_balance"> |
||||
|
<div class="o_account_financial_reports_page"> |
||||
|
<t t-call="account_financial_report.report_buttons" /> |
||||
|
<t t-call="account_financial_report.report_trial_balance_base" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,9 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<template id="report_vat_report"> |
||||
|
<div class="o_account_financial_reports_page"> |
||||
|
<t t-call="account_financial_report.report_buttons" /> |
||||
|
<t t-call="account_financial_report.report_vat_report_base" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,7 @@ |
|||||
|
from . import abstract_wizard |
||||
|
from . import aged_partner_balance_wizard |
||||
|
from . import general_ledger_wizard |
||||
|
from . import journal_ledger_wizard |
||||
|
from . import open_items_wizard |
||||
|
from . import trial_balance_wizard |
||||
|
from . import vat_report_wizard |
@ -0,0 +1,29 @@ |
|||||
|
# Copyright 2019 Lorenzo Battistini @ TAKOBI |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
|
class AbstractWizard(models.AbstractModel): |
||||
|
_name = "account_financial_report_abstract_wizard" |
||||
|
_description = "Abstract Wizard" |
||||
|
|
||||
|
def _get_partner_ids_domain(self): |
||||
|
return [ |
||||
|
"&", |
||||
|
"|", |
||||
|
("company_id", "=", self.company_id.id), |
||||
|
("company_id", "=", False), |
||||
|
"|", |
||||
|
("parent_id", "=", False), |
||||
|
("is_company", "=", True), |
||||
|
] |
||||
|
|
||||
|
def _default_partners(self): |
||||
|
context = self.env.context |
||||
|
if context.get("active_ids") and context.get("active_model") == "res.partner": |
||||
|
partners = self.env["res.partner"].browse(context["active_ids"]) |
||||
|
corp_partners = partners.filtered("parent_id") |
||||
|
partners -= corp_partners |
||||
|
partners |= corp_partners.mapped("commercial_partner_id") |
||||
|
return partners.ids |
@ -0,0 +1,167 @@ |
|||||
|
# Author: Damien Crier, Andrea Stirpe, Kevin Graveman, Dennis Sluijk |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA, Onestein B.V. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceWizard(models.TransientModel): |
||||
|
"""Aged partner balance report wizard.""" |
||||
|
|
||||
|
_name = "aged.partner.balance.report.wizard" |
||||
|
_description = "Aged Partner Balance Wizard" |
||||
|
_inherit = "account_financial_report_abstract_wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name="res.company", |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
required=False, |
||||
|
string="Company", |
||||
|
) |
||||
|
date_at = fields.Date(required=True, default=fields.Date.context_today) |
||||
|
date_from = fields.Date(string="Date From") |
||||
|
target_move = fields.Selection( |
||||
|
[("posted", "All Posted Entries"), ("all", "All Entries")], |
||||
|
string="Target Moves", |
||||
|
required=True, |
||||
|
default="posted", |
||||
|
) |
||||
|
account_ids = fields.Many2many( |
||||
|
comodel_name="account.account", |
||||
|
string="Filter accounts", |
||||
|
domain=[("reconcile", "=", True)], |
||||
|
required=True, |
||||
|
) |
||||
|
receivable_accounts_only = fields.Boolean() |
||||
|
payable_accounts_only = fields.Boolean() |
||||
|
partner_ids = fields.Many2many(comodel_name="res.partner", string="Filter partners") |
||||
|
show_move_line_details = fields.Boolean() |
||||
|
|
||||
|
account_code_from = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
string="Account Code From", |
||||
|
help="Starting account in a range", |
||||
|
) |
||||
|
account_code_to = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
string="Account Code To", |
||||
|
help="Ending account in a range", |
||||
|
) |
||||
|
|
||||
|
@api.onchange("account_code_from", "account_code_to") |
||||
|
def on_change_account_range(self): |
||||
|
if ( |
||||
|
self.account_code_from |
||||
|
and self.account_code_from.code.isdigit() |
||||
|
and self.account_code_to |
||||
|
and self.account_code_to.code.isdigit() |
||||
|
): |
||||
|
start_range = int(self.account_code_from.code) |
||||
|
end_range = int(self.account_code_to.code) |
||||
|
self.account_ids = self.env["account.account"].search( |
||||
|
[ |
||||
|
("code", "in", [x for x in range(start_range, end_range + 1)]), |
||||
|
("reconcile", "=", True), |
||||
|
] |
||||
|
) |
||||
|
if self.company_id: |
||||
|
self.account_ids = self.account_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
return { |
||||
|
"domain": { |
||||
|
"account_code_from": [("reconcile", "=", True)], |
||||
|
"account_code_to": [("reconcile", "=", True)], |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@api.onchange("company_id") |
||||
|
def onchange_company_id(self): |
||||
|
"""Handle company change.""" |
||||
|
if self.company_id and self.partner_ids: |
||||
|
self.partner_ids = self.partner_ids.filtered( |
||||
|
lambda p: p.company_id == self.company_id or not p.company_id |
||||
|
) |
||||
|
if self.company_id and self.account_ids: |
||||
|
if self.receivable_accounts_only or self.payable_accounts_only: |
||||
|
self.onchange_type_accounts_only() |
||||
|
else: |
||||
|
self.account_ids = self.account_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
res = {"domain": {"account_ids": [], "partner_ids": []}} |
||||
|
if not self.company_id: |
||||
|
return res |
||||
|
else: |
||||
|
res["domain"]["account_ids"] += [("company_id", "=", self.company_id.id)] |
||||
|
res["domain"]["partner_ids"] += self._get_partner_ids_domain() |
||||
|
return res |
||||
|
|
||||
|
@api.onchange("account_ids") |
||||
|
def onchange_account_ids(self): |
||||
|
return {"domain": {"account_ids": [("reconcile", "=", True)]}} |
||||
|
|
||||
|
@api.onchange("receivable_accounts_only", "payable_accounts_only") |
||||
|
def onchange_type_accounts_only(self): |
||||
|
"""Handle receivable/payable accounts only change.""" |
||||
|
domain = [("company_id", "=", self.company_id.id)] |
||||
|
if self.receivable_accounts_only or self.payable_accounts_only: |
||||
|
if self.receivable_accounts_only and self.payable_accounts_only: |
||||
|
domain += [("internal_type", "in", ("receivable", "payable"))] |
||||
|
elif self.receivable_accounts_only: |
||||
|
domain += [("internal_type", "=", "receivable")] |
||||
|
elif self.payable_accounts_only: |
||||
|
domain += [("internal_type", "=", "payable")] |
||||
|
self.account_ids = self.env["account.account"].search(domain) |
||||
|
else: |
||||
|
self.account_ids = None |
||||
|
|
||||
|
def _print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
data = self._prepare_report_aged_partner_balance() |
||||
|
if report_type == "xlsx": |
||||
|
report_name = "a_f_r.report_aged_partner_balance_xlsx" |
||||
|
else: |
||||
|
report_name = "account_financial_report.aged_partner_balance" |
||||
|
return ( |
||||
|
self.env["ir.actions.report"] |
||||
|
.search( |
||||
|
[("report_name", "=", report_name), ("report_type", "=", report_type)], |
||||
|
limit=1, |
||||
|
) |
||||
|
.report_action(self, data=data) |
||||
|
) |
||||
|
|
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-html" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-pdf" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "xlsx" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def _prepare_report_aged_partner_balance(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
"wizard_id": self.id, |
||||
|
"date_at": self.date_at, |
||||
|
"date_from": self.date_from or False, |
||||
|
"only_posted_moves": self.target_move == "posted", |
||||
|
"company_id": self.company_id.id, |
||||
|
"account_ids": self.account_ids.ids, |
||||
|
"partner_ids": self.partner_ids.ids, |
||||
|
"show_move_line_details": self.show_move_line_details, |
||||
|
"account_financial_report_lang": self.env.lang, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
return self._print_report(report_type) |
@ -0,0 +1,96 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<!-- AGED PARTNER BALANCE --> |
||||
|
<record id="aged_partner_balance_wizard" model="ir.ui.view"> |
||||
|
<field name="name">Aged Partner Balance</field> |
||||
|
<field name="model">aged.partner.balance.report.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group name="main_info"> |
||||
|
<field |
||||
|
name="company_id" |
||||
|
options="{'no_create': True}" |
||||
|
groups="base.group_multi_company" |
||||
|
/> |
||||
|
</group> |
||||
|
<group name="filters"> |
||||
|
<group name="date_range"> |
||||
|
<field name="date_at" /> |
||||
|
<field name="date_from" /> |
||||
|
</group> |
||||
|
<group name="other_filters"> |
||||
|
<field name="target_move" widget="radio" /> |
||||
|
<field name="show_move_line_details" /> |
||||
|
</group> |
||||
|
</group> |
||||
|
<group name="partner_filter" col="1"> |
||||
|
<label for="partner_ids" /> |
||||
|
<field |
||||
|
name="partner_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</group> |
||||
|
<group name="account_filter" col="4"> |
||||
|
<label for="account_ids" colspan="4" /> |
||||
|
<field name="receivable_accounts_only" /> |
||||
|
<field name="payable_accounts_only" /> |
||||
|
<label for="account_code_from" string="From Code" /> |
||||
|
<div> |
||||
|
<div class="o_row"> |
||||
|
<field |
||||
|
name="account_code_from" |
||||
|
class="oe_inline" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
<span class="oe_inline">To</span> |
||||
|
<field |
||||
|
name="account_code_to" |
||||
|
class="oe_inline" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
<field |
||||
|
name="account_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
colspan="4" |
||||
|
/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button |
||||
|
name="button_export_html" |
||||
|
string="View" |
||||
|
type="object" |
||||
|
default_focus="1" |
||||
|
class="oe_highlight" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_pdf" |
||||
|
string="Export PDF" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_xlsx" |
||||
|
string="Export XLSX" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record id="action_aged_partner_balance_wizard" model="ir.actions.act_window"> |
||||
|
<field name="name">Aged Partner Balance</field> |
||||
|
<field name="res_model">aged.partner.balance.report.wizard</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="aged_partner_balance_wizard" /> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,348 @@ |
|||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Author: Jordi Ballester |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2017 Akretion - Alexis de Lattre |
||||
|
# Copyright 2017 ForgeFlow, S.L. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
|
||||
|
import time |
||||
|
from ast import literal_eval |
||||
|
|
||||
|
from odoo import _, api, fields, models |
||||
|
from odoo.exceptions import ValidationError |
||||
|
from odoo.tools import date_utils |
||||
|
|
||||
|
|
||||
|
class GeneralLedgerReportWizard(models.TransientModel): |
||||
|
"""General ledger report wizard.""" |
||||
|
|
||||
|
_name = "general.ledger.report.wizard" |
||||
|
_description = "General Ledger Report Wizard" |
||||
|
_inherit = "account_financial_report_abstract_wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name="res.company", |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
required=False, |
||||
|
string="Company", |
||||
|
) |
||||
|
date_range_id = fields.Many2one(comodel_name="date.range", string="Date range") |
||||
|
date_from = fields.Date(required=True, default=lambda self: self._init_date_from()) |
||||
|
date_to = fields.Date(required=True, default=fields.Date.context_today) |
||||
|
fy_start_date = fields.Date(compute="_compute_fy_start_date") |
||||
|
target_move = fields.Selection( |
||||
|
[("posted", "All Posted Entries"), ("all", "All Entries")], |
||||
|
string="Target Moves", |
||||
|
required=True, |
||||
|
default="posted", |
||||
|
) |
||||
|
account_ids = fields.Many2many( |
||||
|
comodel_name="account.account", string="Filter accounts" |
||||
|
) |
||||
|
centralize = fields.Boolean(string="Activate centralization", default=True) |
||||
|
hide_account_at_0 = fields.Boolean( |
||||
|
string="Hide account ending balance at 0", |
||||
|
help="Use this filter to hide an account or a partner " |
||||
|
"with an ending balance at 0. " |
||||
|
"If partners are filtered, " |
||||
|
"debits and credits totals will not match the trial balance.", |
||||
|
) |
||||
|
show_analytic_tags = fields.Boolean( |
||||
|
string="Show analytic tags", |
||||
|
) |
||||
|
receivable_accounts_only = fields.Boolean() |
||||
|
payable_accounts_only = fields.Boolean() |
||||
|
partner_ids = fields.Many2many( |
||||
|
comodel_name="res.partner", |
||||
|
string="Filter partners", |
||||
|
default=lambda self: self._default_partners(), |
||||
|
) |
||||
|
analytic_tag_ids = fields.Many2many( |
||||
|
comodel_name="account.analytic.tag", string="Filter analytic tags" |
||||
|
) |
||||
|
account_journal_ids = fields.Many2many( |
||||
|
comodel_name="account.journal", string="Filter journals" |
||||
|
) |
||||
|
cost_center_ids = fields.Many2many( |
||||
|
comodel_name="account.analytic.account", string="Filter cost centers" |
||||
|
) |
||||
|
|
||||
|
not_only_one_unaffected_earnings_account = fields.Boolean( |
||||
|
readonly=True, string="Not only one unaffected earnings account" |
||||
|
) |
||||
|
foreign_currency = fields.Boolean( |
||||
|
string="Show foreign currency", |
||||
|
help="Display foreign currency for move lines, unless " |
||||
|
"account currency is not setup through chart of accounts " |
||||
|
"will display initial and final balance in that currency.", |
||||
|
default=lambda self: self._default_foreign_currency(), |
||||
|
) |
||||
|
account_code_from = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
string="Account Code From", |
||||
|
help="Starting account in a range", |
||||
|
) |
||||
|
account_code_to = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
string="Account Code To", |
||||
|
help="Ending account in a range", |
||||
|
) |
||||
|
show_partner_details = fields.Boolean( |
||||
|
string="Show Partner Details", |
||||
|
default=True, |
||||
|
) |
||||
|
show_cost_center = fields.Boolean( |
||||
|
string="Show Analytic Account", |
||||
|
default=True, |
||||
|
) |
||||
|
domain = fields.Char( |
||||
|
string="Journal Items Domain", |
||||
|
default=[], |
||||
|
help="This domain will be used to select specific domain for Journal " "Items", |
||||
|
) |
||||
|
|
||||
|
def _get_account_move_lines_domain(self): |
||||
|
domain = literal_eval(self.domain) if self.domain else [] |
||||
|
return domain |
||||
|
|
||||
|
@api.onchange("account_code_from", "account_code_to") |
||||
|
def on_change_account_range(self): |
||||
|
if ( |
||||
|
self.account_code_from |
||||
|
and self.account_code_from.code.isdigit() |
||||
|
and self.account_code_to |
||||
|
and self.account_code_to.code.isdigit() |
||||
|
): |
||||
|
start_range = int(self.account_code_from.code) |
||||
|
end_range = int(self.account_code_to.code) |
||||
|
self.account_ids = self.env["account.account"].search( |
||||
|
[("code", "in", [x for x in range(start_range, end_range + 1)])] |
||||
|
) |
||||
|
if self.company_id: |
||||
|
self.account_ids = self.account_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
|
||||
|
def _init_date_from(self): |
||||
|
"""set start date to begin of current year if fiscal year running""" |
||||
|
today = fields.Date.context_today(self) |
||||
|
last_fsc_month = self.env.user.company_id.fiscalyear_last_month |
||||
|
last_fsc_day = self.env.user.company_id.fiscalyear_last_day |
||||
|
|
||||
|
if ( |
||||
|
today.month < int(last_fsc_month) |
||||
|
or today.month == int(last_fsc_month) |
||||
|
and today.day <= last_fsc_day |
||||
|
): |
||||
|
return time.strftime("%Y-01-01") |
||||
|
else: |
||||
|
return False |
||||
|
|
||||
|
def _default_foreign_currency(self): |
||||
|
return self.env.user.has_group("base.group_multi_currency") |
||||
|
|
||||
|
@api.depends("date_from") |
||||
|
def _compute_fy_start_date(self): |
||||
|
for wiz in self: |
||||
|
if wiz.date_from: |
||||
|
date_from, date_to = date_utils.get_fiscal_year( |
||||
|
wiz.date_from, |
||||
|
day=self.company_id.fiscalyear_last_day, |
||||
|
month=int(self.company_id.fiscalyear_last_month), |
||||
|
) |
||||
|
wiz.fy_start_date = date_from |
||||
|
else: |
||||
|
wiz.fy_start_date = False |
||||
|
|
||||
|
@api.onchange("company_id") |
||||
|
def onchange_company_id(self): |
||||
|
"""Handle company change.""" |
||||
|
account_type = self.env.ref("account.data_unaffected_earnings") |
||||
|
count = self.env["account.account"].search_count( |
||||
|
[ |
||||
|
("user_type_id", "=", account_type.id), |
||||
|
("company_id", "=", self.company_id.id), |
||||
|
] |
||||
|
) |
||||
|
self.not_only_one_unaffected_earnings_account = count != 1 |
||||
|
if ( |
||||
|
self.company_id |
||||
|
and self.date_range_id.company_id |
||||
|
and self.date_range_id.company_id != self.company_id |
||||
|
): |
||||
|
self.date_range_id = False |
||||
|
if self.company_id and self.account_journal_ids: |
||||
|
self.account_journal_ids = self.account_journal_ids.filtered( |
||||
|
lambda p: p.company_id == self.company_id or not p.company_id |
||||
|
) |
||||
|
if self.company_id and self.partner_ids: |
||||
|
self.partner_ids = self.partner_ids.filtered( |
||||
|
lambda p: p.company_id == self.company_id or not p.company_id |
||||
|
) |
||||
|
if self.company_id and self.account_ids: |
||||
|
if self.receivable_accounts_only or self.payable_accounts_only: |
||||
|
self.onchange_type_accounts_only() |
||||
|
else: |
||||
|
self.account_ids = self.account_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
if self.company_id and self.cost_center_ids: |
||||
|
self.cost_center_ids = self.cost_center_ids.filtered( |
||||
|
lambda c: c.company_id == self.company_id |
||||
|
) |
||||
|
res = { |
||||
|
"domain": { |
||||
|
"account_ids": [], |
||||
|
"partner_ids": [], |
||||
|
"account_journal_ids": [], |
||||
|
"cost_center_ids": [], |
||||
|
"date_range_id": [], |
||||
|
} |
||||
|
} |
||||
|
if not self.company_id: |
||||
|
return res |
||||
|
else: |
||||
|
res["domain"]["account_ids"] += [("company_id", "=", self.company_id.id)] |
||||
|
res["domain"]["account_journal_ids"] += [ |
||||
|
("company_id", "=", self.company_id.id) |
||||
|
] |
||||
|
res["domain"]["partner_ids"] += self._get_partner_ids_domain() |
||||
|
res["domain"]["cost_center_ids"] += [ |
||||
|
("company_id", "=", self.company_id.id) |
||||
|
] |
||||
|
res["domain"]["date_range_id"] += [ |
||||
|
"|", |
||||
|
("company_id", "=", self.company_id.id), |
||||
|
("company_id", "=", False), |
||||
|
] |
||||
|
return res |
||||
|
|
||||
|
@api.onchange("date_range_id") |
||||
|
def onchange_date_range_id(self): |
||||
|
"""Handle date range change.""" |
||||
|
if self.date_range_id: |
||||
|
self.date_from = self.date_range_id.date_start |
||||
|
self.date_to = self.date_range_id.date_end |
||||
|
|
||||
|
@api.constrains("company_id", "date_range_id") |
||||
|
def _check_company_id_date_range_id(self): |
||||
|
for rec in self.sudo(): |
||||
|
if ( |
||||
|
rec.company_id |
||||
|
and rec.date_range_id.company_id |
||||
|
and rec.company_id != rec.date_range_id.company_id |
||||
|
): |
||||
|
raise ValidationError( |
||||
|
_( |
||||
|
"The Company in the General Ledger Report Wizard and in " |
||||
|
"Date Range must be the same." |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
@api.onchange("receivable_accounts_only", "payable_accounts_only") |
||||
|
def onchange_type_accounts_only(self): |
||||
|
"""Handle receivable/payable accounts only change.""" |
||||
|
if self.receivable_accounts_only or self.payable_accounts_only: |
||||
|
domain = [("company_id", "=", self.company_id.id)] |
||||
|
if self.receivable_accounts_only and self.payable_accounts_only: |
||||
|
domain += [("internal_type", "in", ("receivable", "payable"))] |
||||
|
elif self.receivable_accounts_only: |
||||
|
domain += [("internal_type", "=", "receivable")] |
||||
|
elif self.payable_accounts_only: |
||||
|
domain += [("internal_type", "=", "payable")] |
||||
|
self.account_ids = self.env["account.account"].search(domain) |
||||
|
else: |
||||
|
self.account_ids = None |
||||
|
|
||||
|
@api.onchange("partner_ids") |
||||
|
def onchange_partner_ids(self): |
||||
|
"""Handle partners change.""" |
||||
|
if self.partner_ids: |
||||
|
self.receivable_accounts_only = self.payable_accounts_only = True |
||||
|
else: |
||||
|
self.receivable_accounts_only = self.payable_accounts_only = False |
||||
|
|
||||
|
@api.depends("company_id") |
||||
|
def _compute_unaffected_earnings_account(self): |
||||
|
account_type = self.env.ref("account.data_unaffected_earnings") |
||||
|
for record in self: |
||||
|
record.unaffected_earnings_account = self.env["account.account"].search( |
||||
|
[ |
||||
|
("user_type_id", "=", account_type.id), |
||||
|
("company_id", "=", record.company_id.id), |
||||
|
] |
||||
|
) |
||||
|
|
||||
|
unaffected_earnings_account = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
compute="_compute_unaffected_earnings_account", |
||||
|
store=True, |
||||
|
) |
||||
|
|
||||
|
def _print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
data = self._prepare_report_general_ledger() |
||||
|
if report_type == "xlsx": |
||||
|
report_name = "a_f_r.report_general_ledger_xlsx" |
||||
|
else: |
||||
|
report_name = "account_financial_report.general_ledger" |
||||
|
return ( |
||||
|
self.env["ir.actions.report"] |
||||
|
.search( |
||||
|
[("report_name", "=", report_name), ("report_type", "=", report_type)], |
||||
|
limit=1, |
||||
|
) |
||||
|
.report_action(self, data=data) |
||||
|
) |
||||
|
|
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-html" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-pdf" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "xlsx" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def _prepare_report_general_ledger(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
"wizard_id": self.id, |
||||
|
"date_from": self.date_from, |
||||
|
"date_to": self.date_to, |
||||
|
"only_posted_moves": self.target_move == "posted", |
||||
|
"hide_account_at_0": self.hide_account_at_0, |
||||
|
"foreign_currency": self.foreign_currency, |
||||
|
"show_analytic_tags": self.show_analytic_tags, |
||||
|
"company_id": self.company_id.id, |
||||
|
"account_ids": self.account_ids.ids, |
||||
|
"partner_ids": self.partner_ids.ids, |
||||
|
"show_partner_details": self.show_partner_details, |
||||
|
"cost_center_ids": self.cost_center_ids.ids, |
||||
|
"show_cost_center": self.show_cost_center, |
||||
|
"analytic_tag_ids": self.analytic_tag_ids.ids, |
||||
|
"journal_ids": self.account_journal_ids.ids, |
||||
|
"centralize": self.centralize, |
||||
|
"fy_start_date": self.fy_start_date, |
||||
|
"unaffected_earnings_account": self.unaffected_earnings_account.id, |
||||
|
"account_financial_report_lang": self.env.lang, |
||||
|
"domain": self._get_account_move_lines_domain(), |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
return self._print_report(report_type) |
||||
|
|
||||
|
def _get_atr_from_dict(self, obj_id, data, key): |
||||
|
try: |
||||
|
return data[obj_id][key] |
||||
|
except KeyError: |
||||
|
return data[str(obj_id)][key] |
@ -0,0 +1,183 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<!-- GENERAL LEDGER --> |
||||
|
<record id="general_ledger_wizard" model="ir.ui.view"> |
||||
|
<field name="name">General Ledger</field> |
||||
|
<field name="model">general.ledger.report.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group name="main_info"> |
||||
|
<field |
||||
|
name="company_id" |
||||
|
options="{'no_create': True}" |
||||
|
groups="base.group_multi_company" |
||||
|
/> |
||||
|
</group> |
||||
|
<div |
||||
|
attrs="{'invisible': [('not_only_one_unaffected_earnings_account', '=', True)]}" |
||||
|
> |
||||
|
<group name="filters"> |
||||
|
<group name="date_range"> |
||||
|
<field name="date_range_id" /> |
||||
|
<field name="date_from" /> |
||||
|
<field name="date_to" /> |
||||
|
<field name="fy_start_date" invisible="1" /> |
||||
|
</group> |
||||
|
<group name="other_filters"> |
||||
|
<field name="target_move" widget="radio" /> |
||||
|
<field name="centralize" /> |
||||
|
<field name="show_partner_details" /> |
||||
|
<field name="hide_account_at_0" /> |
||||
|
<field name="foreign_currency" /> |
||||
|
<field name="show_analytic_tags" /> |
||||
|
<field name="show_cost_center" /> |
||||
|
</group> |
||||
|
</group> |
||||
|
<notebook> |
||||
|
<page string="Filter accounts"> |
||||
|
<group name="account_filter" col="4"> |
||||
|
<label for="account_ids" colspan="4" /> |
||||
|
<field name="receivable_accounts_only" /> |
||||
|
<field name="payable_accounts_only" /> |
||||
|
<label for="account_code_from" string="From Code" /> |
||||
|
<div> |
||||
|
<div class="o_row"> |
||||
|
<field |
||||
|
name="account_code_from" |
||||
|
class="oe_inline" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
<span class="oe_inline">To</span> |
||||
|
<field |
||||
|
name="account_code_to" |
||||
|
class="oe_inline" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
<field |
||||
|
name="account_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
colspan="4" |
||||
|
/> |
||||
|
</group> |
||||
|
</page> |
||||
|
<page string="Filter partners"> |
||||
|
<field |
||||
|
name="partner_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</page> |
||||
|
<page |
||||
|
string="Filter analytic accounts" |
||||
|
groups="analytic.group_analytic_accounting" |
||||
|
> |
||||
|
<field |
||||
|
name="cost_center_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</page> |
||||
|
<page string="Filter analytic tags"> |
||||
|
<field |
||||
|
name="analytic_tag_ids" |
||||
|
widget="many2many_tags" |
||||
|
nolabel="1" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</page> |
||||
|
<page string="Additional Filtering"> |
||||
|
<style> |
||||
|
.o_domain_show_selection_button {display: none} |
||||
|
</style> |
||||
|
<field |
||||
|
name="domain" |
||||
|
widget="domain" |
||||
|
options="{'model': 'account.move.line', 'in_dialog': True}" |
||||
|
context="{'skip_search_count': 1}" |
||||
|
/> |
||||
|
</page> |
||||
|
</notebook> |
||||
|
</div> |
||||
|
<div |
||||
|
attrs="{'invisible': [('not_only_one_unaffected_earnings_account', '=', False)]}" |
||||
|
> |
||||
|
<field |
||||
|
name="not_only_one_unaffected_earnings_account" |
||||
|
invisible="1" |
||||
|
/> |
||||
|
<group /> |
||||
|
<h4> |
||||
|
General Ledger can be computed only if selected company have |
||||
|
only one unaffected earnings account. |
||||
|
</h4> |
||||
|
<group /> |
||||
|
</div> |
||||
|
<footer> |
||||
|
<div |
||||
|
attrs="{'invisible': [('not_only_one_unaffected_earnings_account', '=', True)]}" |
||||
|
> |
||||
|
<button |
||||
|
name="button_export_html" |
||||
|
string="View" |
||||
|
type="object" |
||||
|
default_focus="1" |
||||
|
class="oe_highlight" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_pdf" |
||||
|
string="Export PDF" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_xlsx" |
||||
|
string="Export XLSX" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</div> |
||||
|
<div |
||||
|
attrs="{'invisible': [('not_only_one_unaffected_earnings_account', '=', False)]}" |
||||
|
> |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</div> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record id="action_general_ledger_wizard" model="ir.actions.act_window"> |
||||
|
<field name="name">General Ledger</field> |
||||
|
<field name="res_model">general.ledger.report.wizard</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="general_ledger_wizard" /> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
<!--Add to res.partner action--> |
||||
|
<record |
||||
|
id="act_action_general_ledger_wizard_partner_relation" |
||||
|
model="ir.actions.act_window" |
||||
|
> |
||||
|
<field name="name">General Ledger</field> |
||||
|
<field name="res_model">general.ledger.report.wizard</field> |
||||
|
<field name="binding_model_id" ref="base.model_res_partner" /> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="general_ledger_wizard" /> |
||||
|
<field |
||||
|
name="context" |
||||
|
eval="{ |
||||
|
'default_receivable_accounts_only':1, |
||||
|
'default_payable_accounts_only':1, |
||||
|
}" |
||||
|
/> |
||||
|
<field name="groups_id" eval="[(4, ref('account.group_account_manager'))]" /> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,175 @@ |
|||||
|
# Copyright 2017 ACSONE SA/NV |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from odoo import _, api, fields, models |
||||
|
|
||||
|
|
||||
|
class JournalLedgerReportWizard(models.TransientModel): |
||||
|
"""Journal Ledger report wizard.""" |
||||
|
|
||||
|
_name = "journal.ledger.report.wizard" |
||||
|
_description = "Journal Ledger Report Wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name="res.company", |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
string="Company", |
||||
|
required=False, |
||||
|
ondelete="cascade", |
||||
|
) |
||||
|
date_range_id = fields.Many2one(comodel_name="date.range", string="Date range") |
||||
|
date_from = fields.Date(string="Start date", required=True) |
||||
|
date_to = fields.Date(string="End date", required=True) |
||||
|
journal_ids = fields.Many2many( |
||||
|
comodel_name="account.journal", string="Journals", required=False |
||||
|
) |
||||
|
move_target = fields.Selection( |
||||
|
selection="_get_move_targets", default="posted", required=True |
||||
|
) |
||||
|
foreign_currency = fields.Boolean() |
||||
|
sort_option = fields.Selection( |
||||
|
selection="_get_sort_options", |
||||
|
string="Sort entries by", |
||||
|
default="move_name", |
||||
|
required=True, |
||||
|
) |
||||
|
group_option = fields.Selection( |
||||
|
selection="_get_group_options", |
||||
|
string="Group entries by", |
||||
|
default="journal", |
||||
|
required=True, |
||||
|
) |
||||
|
with_account_name = fields.Boolean(default=False) |
||||
|
|
||||
|
@api.model |
||||
|
def _get_move_targets(self): |
||||
|
return [("all", _("All")), ("posted", _("Posted")), ("draft", _("Not Posted"))] |
||||
|
|
||||
|
@api.model |
||||
|
def _get_sort_options(self): |
||||
|
return [("move_name", _("Entry number")), ("date", _("Date"))] |
||||
|
|
||||
|
@api.model |
||||
|
def _get_group_options(self): |
||||
|
return [("journal", _("Journal")), ("none", _("No group"))] |
||||
|
|
||||
|
@api.onchange("date_range_id") |
||||
|
def onchange_date_range_id(self): |
||||
|
self.date_from = self.date_range_id.date_start |
||||
|
self.date_to = self.date_range_id.date_end |
||||
|
|
||||
|
@api.onchange("company_id") |
||||
|
def onchange_company_id(self): |
||||
|
"""Handle company change.""" |
||||
|
if ( |
||||
|
self.company_id |
||||
|
and self.date_range_id.company_id |
||||
|
and self.date_range_id.company_id != self.company_id |
||||
|
): |
||||
|
self.date_range_id = False |
||||
|
if self.company_id and self.journal_ids: |
||||
|
self.journal_ids = self.journal_ids.filtered( |
||||
|
lambda p: p.company_id == self.company_id or not p.company_id |
||||
|
) |
||||
|
res = {"domain": {"journal_ids": []}} |
||||
|
if not self.company_id: |
||||
|
return res |
||||
|
else: |
||||
|
res["domain"]["journal_ids"] += [("company_id", "=", self.company_id.id)] |
||||
|
return res |
||||
|
|
||||
|
def _print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
data = self._prepare_report_journal_ledger() |
||||
|
if report_type == "xlsx": |
||||
|
report_name = "a_f_r.report_journal_ledger_xlsx" |
||||
|
else: |
||||
|
report_name = "account_financial_report.journal_ledger" |
||||
|
return ( |
||||
|
self.env["ir.actions.report"] |
||||
|
.search( |
||||
|
[("report_name", "=", report_name), ("report_type", "=", report_type)], |
||||
|
limit=1, |
||||
|
) |
||||
|
.report_action(self, data=data) |
||||
|
) |
||||
|
|
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-html" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_pdf(self): |
||||
|
report_type = "qweb-pdf" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "xlsx" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def _prepare_report_journal_ledger(self): |
||||
|
self.ensure_one() |
||||
|
journals = self.journal_ids |
||||
|
if not journals: |
||||
|
# Not selecting a journal means that we'll display all journals |
||||
|
journals = self.env["account.journal"].search( |
||||
|
[("company_id", "=", self.company_id.id)] |
||||
|
) |
||||
|
return { |
||||
|
"wizard_id": self.id, |
||||
|
"date_from": self.date_from, |
||||
|
"date_to": self.date_to, |
||||
|
"move_target": self.move_target, |
||||
|
"foreign_currency": self.foreign_currency, |
||||
|
"company_id": self.company_id.id, |
||||
|
"journal_ids": journals.ids, |
||||
|
"sort_option": self.sort_option, |
||||
|
"group_option": self.group_option, |
||||
|
"with_account_name": self.with_account_name, |
||||
|
"account_financial_report_lang": self.env.lang, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
self.ensure_one() |
||||
|
return self._print_report(report_type) |
||||
|
|
||||
|
@api.model |
||||
|
def _get_ml_tax_description( |
||||
|
self, move_line_data, tax_line_data, move_line_taxes_data |
||||
|
): |
||||
|
taxes_description = "" |
||||
|
if move_line_data["tax_line_id"]: |
||||
|
taxes_description = tax_line_data["description"] or tax_line_data["name"] |
||||
|
elif move_line_taxes_data: |
||||
|
tax_names = [] |
||||
|
for tax_key in move_line_taxes_data: |
||||
|
tax = move_line_taxes_data[tax_key] |
||||
|
tax_names.append(tax["description"] or tax["name"]) |
||||
|
taxes_description = ",".join(tax_names) |
||||
|
return taxes_description |
||||
|
|
||||
|
@api.model |
||||
|
def _get_partner_name(self, partner_id, partner_data): |
||||
|
if str(partner_id) in partner_data.keys(): |
||||
|
return partner_data[str(partner_id)]["name"] |
||||
|
else: |
||||
|
return "" |
||||
|
|
||||
|
@api.model |
||||
|
def _get_atr_from_dict(self, obj_id, data, key): |
||||
|
try: |
||||
|
return data[obj_id][key] |
||||
|
except KeyError: |
||||
|
return data[str(obj_id)][key] |
||||
|
|
||||
|
@api.model |
||||
|
def _get_data_from_dict(self, obj_id, data): |
||||
|
if data: |
||||
|
if isinstance(list(data.keys())[0], int): |
||||
|
return data.get(obj_id, False) |
||||
|
else: |
||||
|
return data.get(obj_id(obj_id), False) |
||||
|
else: |
||||
|
return False |
@ -0,0 +1,74 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<!-- Copyright 2017 ACSONE SA/NV |
||||
|
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> |
||||
|
<odoo> |
||||
|
<record id="journal_ledger_wizard" model="ir.ui.view"> |
||||
|
<field name="name">Journal Ledger</field> |
||||
|
<field name="model">journal.ledger.report.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group> |
||||
|
<field name="company_id" groups="base.group_multi_company" /> |
||||
|
</group> |
||||
|
<separator string="Periods" /> |
||||
|
<group> |
||||
|
<group> |
||||
|
<field name="date_range_id" /> |
||||
|
<field name="date_from" /> |
||||
|
<field name="date_to" /> |
||||
|
</group> |
||||
|
<group /> |
||||
|
</group> |
||||
|
<separator string="Options" /> |
||||
|
<group name="options"> |
||||
|
<group> |
||||
|
<field |
||||
|
name="move_target" |
||||
|
widget="radio" |
||||
|
options="{'horizontal': true}" |
||||
|
/> |
||||
|
<field name="sort_option" /> |
||||
|
<field name="group_option" /> |
||||
|
<field name="foreign_currency" /> |
||||
|
<field name="with_account_name" /> |
||||
|
</group> |
||||
|
<group /> |
||||
|
</group> |
||||
|
<separator string="Journals" /> |
||||
|
<group> |
||||
|
<field name="journal_ids" widget="many2many_tags" /> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button |
||||
|
name="button_export_html" |
||||
|
string="View" |
||||
|
type="object" |
||||
|
default_focus="1" |
||||
|
class="oe_highlight" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_pdf" |
||||
|
string="Export PDF" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_xlsx" |
||||
|
string="Export XLSX" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record id="action_journal_ledger_wizard" model="ir.actions.act_window"> |
||||
|
<field name="name">Journal Ledger</field> |
||||
|
<field name="res_model">journal.ledger.report.wizard</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="journal_ledger_wizard" /> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,193 @@ |
|||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportWizard(models.TransientModel): |
||||
|
"""Open items report wizard.""" |
||||
|
|
||||
|
_name = "open.items.report.wizard" |
||||
|
_description = "Open Items Report Wizard" |
||||
|
_inherit = "account_financial_report_abstract_wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name="res.company", |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
required=False, |
||||
|
string="Company", |
||||
|
) |
||||
|
date_at = fields.Date(required=True, default=fields.Date.context_today) |
||||
|
date_from = fields.Date(string="Date From") |
||||
|
target_move = fields.Selection( |
||||
|
[("posted", "All Posted Entries"), ("all", "All Entries")], |
||||
|
string="Target Moves", |
||||
|
required=True, |
||||
|
default="posted", |
||||
|
) |
||||
|
account_ids = fields.Many2many( |
||||
|
comodel_name="account.account", |
||||
|
string="Filter accounts", |
||||
|
domain=[("reconcile", "=", True)], |
||||
|
required=True, |
||||
|
) |
||||
|
hide_account_at_0 = fields.Boolean( |
||||
|
string="Hide account ending balance at 0", |
||||
|
default=True, |
||||
|
help="Use this filter to hide an account or a partner " |
||||
|
"with an ending balance at 0. " |
||||
|
"If partners are filtered, " |
||||
|
"debits and credits totals will not match the trial balance.", |
||||
|
) |
||||
|
receivable_accounts_only = fields.Boolean() |
||||
|
payable_accounts_only = fields.Boolean() |
||||
|
partner_ids = fields.Many2many( |
||||
|
comodel_name="res.partner", |
||||
|
string="Filter partners", |
||||
|
default=lambda self: self._default_partners(), |
||||
|
) |
||||
|
foreign_currency = fields.Boolean( |
||||
|
string="Show foreign currency", |
||||
|
help="Display foreign currency for move lines, unless " |
||||
|
"account currency is not setup through chart of accounts " |
||||
|
"will display initial and final balance in that currency.", |
||||
|
default=lambda self: self._default_foreign_currency(), |
||||
|
) |
||||
|
show_partner_details = fields.Boolean( |
||||
|
string="Show Partner Details", |
||||
|
default=True, |
||||
|
) |
||||
|
account_code_from = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
string="Account Code From", |
||||
|
help="Starting account in a range", |
||||
|
) |
||||
|
account_code_to = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
string="Account Code To", |
||||
|
help="Ending account in a range", |
||||
|
) |
||||
|
|
||||
|
@api.onchange("account_code_from", "account_code_to") |
||||
|
def on_change_account_range(self): |
||||
|
if ( |
||||
|
self.account_code_from |
||||
|
and self.account_code_from.code.isdigit() |
||||
|
and self.account_code_to |
||||
|
and self.account_code_to.code.isdigit() |
||||
|
): |
||||
|
start_range = int(self.account_code_from.code) |
||||
|
end_range = int(self.account_code_to.code) |
||||
|
self.account_ids = self.env["account.account"].search( |
||||
|
[ |
||||
|
("code", "in", [x for x in range(start_range, end_range + 1)]), |
||||
|
("reconcile", "=", True), |
||||
|
] |
||||
|
) |
||||
|
if self.company_id: |
||||
|
self.account_ids = self.account_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
return { |
||||
|
"domain": { |
||||
|
"account_code_from": [("reconcile", "=", True)], |
||||
|
"account_code_to": [("reconcile", "=", True)], |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
def _default_foreign_currency(self): |
||||
|
return self.env.user.has_group("base.group_multi_currency") |
||||
|
|
||||
|
@api.onchange("company_id") |
||||
|
def onchange_company_id(self): |
||||
|
"""Handle company change.""" |
||||
|
if self.company_id and self.partner_ids: |
||||
|
self.partner_ids = self.partner_ids.filtered( |
||||
|
lambda p: p.company_id == self.company_id or not p.company_id |
||||
|
) |
||||
|
if self.company_id and self.account_ids: |
||||
|
if self.receivable_accounts_only or self.payable_accounts_only: |
||||
|
self.onchange_type_accounts_only() |
||||
|
else: |
||||
|
self.account_ids = self.account_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
res = {"domain": {"account_ids": [], "partner_ids": []}} |
||||
|
if not self.company_id: |
||||
|
return res |
||||
|
else: |
||||
|
res["domain"]["account_ids"] += [("company_id", "=", self.company_id.id)] |
||||
|
res["domain"]["partner_ids"] += self._get_partner_ids_domain() |
||||
|
return res |
||||
|
|
||||
|
@api.onchange("account_ids") |
||||
|
def onchange_account_ids(self): |
||||
|
return {"domain": {"account_ids": [("reconcile", "=", True)]}} |
||||
|
|
||||
|
@api.onchange("receivable_accounts_only", "payable_accounts_only") |
||||
|
def onchange_type_accounts_only(self): |
||||
|
"""Handle receivable/payable accounts only change.""" |
||||
|
domain = [("company_id", "=", self.company_id.id)] |
||||
|
if self.receivable_accounts_only or self.payable_accounts_only: |
||||
|
if self.receivable_accounts_only and self.payable_accounts_only: |
||||
|
domain += [("internal_type", "in", ("receivable", "payable"))] |
||||
|
elif self.receivable_accounts_only: |
||||
|
domain += [("internal_type", "=", "receivable")] |
||||
|
elif self.payable_accounts_only: |
||||
|
domain += [("internal_type", "=", "payable")] |
||||
|
self.account_ids = self.env["account.account"].search(domain) |
||||
|
else: |
||||
|
self.account_ids = None |
||||
|
|
||||
|
def _print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
data = self._prepare_report_open_items() |
||||
|
if report_type == "xlsx": |
||||
|
report_name = "a_f_r.report_open_items_xlsx" |
||||
|
else: |
||||
|
report_name = "account_financial_report.open_items" |
||||
|
return ( |
||||
|
self.env["ir.actions.report"] |
||||
|
.search( |
||||
|
[("report_name", "=", report_name), ("report_type", "=", report_type)], |
||||
|
limit=1, |
||||
|
) |
||||
|
.report_action(self, data=data) |
||||
|
) |
||||
|
|
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-html" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-pdf" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "xlsx" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def _prepare_report_open_items(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
"wizard_id": self.id, |
||||
|
"date_at": fields.Date.to_string(self.date_at), |
||||
|
"date_from": self.date_from or False, |
||||
|
"only_posted_moves": self.target_move == "posted", |
||||
|
"hide_account_at_0": self.hide_account_at_0, |
||||
|
"foreign_currency": self.foreign_currency, |
||||
|
"show_partner_details": self.show_partner_details, |
||||
|
"company_id": self.company_id.id, |
||||
|
"target_move": self.target_move, |
||||
|
"account_ids": self.account_ids.ids, |
||||
|
"partner_ids": self.partner_ids.ids or [], |
||||
|
"account_financial_report_lang": self.env.lang, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
return self._print_report(report_type) |
@ -0,0 +1,117 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<!-- OPEN ITEMS --> |
||||
|
<record id="open_items_wizard" model="ir.ui.view"> |
||||
|
<field name="name">Open Items</field> |
||||
|
<field name="model">open.items.report.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group name="main_info"> |
||||
|
<field |
||||
|
name="company_id" |
||||
|
options="{'no_create': True}" |
||||
|
groups="base.group_multi_company" |
||||
|
/> |
||||
|
</group> |
||||
|
<group name="filters"> |
||||
|
<group name="date_range"> |
||||
|
<field name="date_at" /> |
||||
|
<field name="date_from" /> |
||||
|
</group> |
||||
|
<group name="other_filters"> |
||||
|
<field name="target_move" widget="radio" /> |
||||
|
<field name="show_partner_details" /> |
||||
|
<field name="hide_account_at_0" /> |
||||
|
<field name="foreign_currency" /> |
||||
|
</group> |
||||
|
</group> |
||||
|
<group name="partner_filter" col="1"> |
||||
|
<label for="partner_ids" /> |
||||
|
<field |
||||
|
name="partner_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</group> |
||||
|
<group name="account_filter" col="4"> |
||||
|
<field name="receivable_accounts_only" /> |
||||
|
<field name="payable_accounts_only" /> |
||||
|
<label for="account_code_from" string="From Code" /> |
||||
|
<div> |
||||
|
<div class="o_row"> |
||||
|
<field |
||||
|
name="account_code_from" |
||||
|
class="oe_inline" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
<span class="oe_inline">To</span> |
||||
|
<field |
||||
|
name="account_code_to" |
||||
|
class="oe_inline" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
<field |
||||
|
name="account_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
colspan="4" |
||||
|
/> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button |
||||
|
name="button_export_html" |
||||
|
string="View" |
||||
|
type="object" |
||||
|
default_focus="1" |
||||
|
class="oe_highlight" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_pdf" |
||||
|
string="Export PDF" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_xlsx" |
||||
|
string="Export XLSX" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record id="action_open_items_wizard" model="ir.actions.act_window"> |
||||
|
<field name="name">Open Itemsr</field> |
||||
|
<field name="res_model">open.items.report.wizard</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="open_items_wizard" /> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
<!--Add to res.partner action--> |
||||
|
<record |
||||
|
id="act_action_open_items_wizard_partner_relation" |
||||
|
model="ir.actions.act_window" |
||||
|
> |
||||
|
<field name="name">Open Items Partner</field> |
||||
|
<field name="res_model">open.items.report.wizard</field> |
||||
|
<field name="binding_model_id" ref="base.model_res_partner" /> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="general_ledger_wizard" /> |
||||
|
<field |
||||
|
name="context" |
||||
|
eval="{ |
||||
|
'default_receivable_accounts_only':1, |
||||
|
'default_payable_accounts_only':1, |
||||
|
}" |
||||
|
/> |
||||
|
<field name="groups_id" eval="[(4, ref('account.group_account_manager'))]" /> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,301 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2017 Akretion - Alexis de Lattre |
||||
|
# Copyright 2018 ForgeFlow, S.L. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import _, api, fields, models |
||||
|
from odoo.exceptions import UserError, ValidationError |
||||
|
from odoo.tools import date_utils |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReportWizard(models.TransientModel): |
||||
|
"""Trial balance report wizard.""" |
||||
|
|
||||
|
_name = "trial.balance.report.wizard" |
||||
|
_description = "Trial Balance Report Wizard" |
||||
|
_inherit = "account_financial_report_abstract_wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name="res.company", |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
required=False, |
||||
|
string="Company", |
||||
|
) |
||||
|
date_range_id = fields.Many2one(comodel_name="date.range", string="Date range") |
||||
|
date_from = fields.Date(required=True) |
||||
|
date_to = fields.Date(required=True) |
||||
|
fy_start_date = fields.Date(compute="_compute_fy_start_date") |
||||
|
target_move = fields.Selection( |
||||
|
[("posted", "All Posted Entries"), ("all", "All Entries")], |
||||
|
string="Target Moves", |
||||
|
required=True, |
||||
|
default="posted", |
||||
|
) |
||||
|
hierarchy_on = fields.Selection( |
||||
|
[ |
||||
|
("computed", "Computed Accounts"), |
||||
|
("relation", "Child Accounts"), |
||||
|
("none", "No hierarchy"), |
||||
|
], |
||||
|
string="Hierarchy On", |
||||
|
required=True, |
||||
|
default="none", |
||||
|
help="""Computed Accounts: Use when the account group have codes |
||||
|
that represent prefixes of the actual accounts.\n |
||||
|
Child Accounts: Use when your account groups are hierarchical.\n |
||||
|
No hierarchy: Use to display just the accounts, without any grouping. |
||||
|
""", |
||||
|
) |
||||
|
limit_hierarchy_level = fields.Boolean("Limit hierarchy levels") |
||||
|
show_hierarchy_level = fields.Integer("Hierarchy Levels to display", default=1) |
||||
|
hide_parent_hierarchy_level = fields.Boolean( |
||||
|
"Do not display parent levels", default=False |
||||
|
) |
||||
|
account_ids = fields.Many2many( |
||||
|
comodel_name="account.account", string="Filter accounts" |
||||
|
) |
||||
|
hide_account_at_0 = fields.Boolean( |
||||
|
string="Hide accounts at 0", |
||||
|
default=True, |
||||
|
help="When this option is enabled, the trial balance will " |
||||
|
"not display accounts that have initial balance = " |
||||
|
"debit = credit = end balance = 0", |
||||
|
) |
||||
|
receivable_accounts_only = fields.Boolean() |
||||
|
payable_accounts_only = fields.Boolean() |
||||
|
show_partner_details = fields.Boolean() |
||||
|
partner_ids = fields.Many2many(comodel_name="res.partner", string="Filter partners") |
||||
|
journal_ids = fields.Many2many(comodel_name="account.journal") |
||||
|
|
||||
|
not_only_one_unaffected_earnings_account = fields.Boolean( |
||||
|
readonly=True, string="Not only one unaffected earnings account" |
||||
|
) |
||||
|
|
||||
|
foreign_currency = fields.Boolean( |
||||
|
string="Show foreign currency", |
||||
|
help="Display foreign currency for move lines, unless " |
||||
|
"account currency is not setup through chart of accounts " |
||||
|
"will display initial and final balance in that currency.", |
||||
|
) |
||||
|
account_code_from = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
string="Account Code From", |
||||
|
help="Starting account in a range", |
||||
|
) |
||||
|
account_code_to = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
string="Account Code To", |
||||
|
help="Ending account in a range", |
||||
|
) |
||||
|
|
||||
|
@api.onchange("account_code_from", "account_code_to") |
||||
|
def on_change_account_range(self): |
||||
|
if ( |
||||
|
self.account_code_from |
||||
|
and self.account_code_from.code.isdigit() |
||||
|
and self.account_code_to |
||||
|
and self.account_code_to.code.isdigit() |
||||
|
): |
||||
|
start_range = int(self.account_code_from.code) |
||||
|
end_range = int(self.account_code_to.code) |
||||
|
self.account_ids = self.env["account.account"].search( |
||||
|
[("code", "in", [x for x in range(start_range, end_range + 1)])] |
||||
|
) |
||||
|
if self.company_id: |
||||
|
self.account_ids = self.account_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
|
||||
|
@api.constrains("hierarchy_on", "show_hierarchy_level") |
||||
|
def _check_show_hierarchy_level(self): |
||||
|
for rec in self: |
||||
|
if rec.hierarchy_on != "none" and rec.show_hierarchy_level <= 0: |
||||
|
raise UserError( |
||||
|
_("The hierarchy level to filter on must be " "greater than 0.") |
||||
|
) |
||||
|
|
||||
|
@api.depends("date_from") |
||||
|
def _compute_fy_start_date(self): |
||||
|
for wiz in self: |
||||
|
if wiz.date_from: |
||||
|
date_from, date_to = date_utils.get_fiscal_year( |
||||
|
wiz.date_from, |
||||
|
day=self.company_id.fiscalyear_last_day, |
||||
|
month=int(self.company_id.fiscalyear_last_month), |
||||
|
) |
||||
|
wiz.fy_start_date = date_from |
||||
|
else: |
||||
|
wiz.fy_start_date = False |
||||
|
|
||||
|
@api.onchange("company_id") |
||||
|
def onchange_company_id(self): |
||||
|
"""Handle company change.""" |
||||
|
account_type = self.env.ref("account.data_unaffected_earnings") |
||||
|
count = self.env["account.account"].search_count( |
||||
|
[ |
||||
|
("user_type_id", "=", account_type.id), |
||||
|
("company_id", "=", self.company_id.id), |
||||
|
] |
||||
|
) |
||||
|
self.not_only_one_unaffected_earnings_account = count != 1 |
||||
|
if ( |
||||
|
self.company_id |
||||
|
and self.date_range_id.company_id |
||||
|
and self.date_range_id.company_id != self.company_id |
||||
|
): |
||||
|
self.date_range_id = False |
||||
|
if self.company_id and self.partner_ids: |
||||
|
self.partner_ids = self.partner_ids.filtered( |
||||
|
lambda p: p.company_id == self.company_id or not p.company_id |
||||
|
) |
||||
|
if self.company_id and self.journal_ids: |
||||
|
self.journal_ids = self.journal_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
if self.company_id and self.account_ids: |
||||
|
if self.receivable_accounts_only or self.payable_accounts_only: |
||||
|
self.onchange_type_accounts_only() |
||||
|
else: |
||||
|
self.account_ids = self.account_ids.filtered( |
||||
|
lambda a: a.company_id == self.company_id |
||||
|
) |
||||
|
res = { |
||||
|
"domain": { |
||||
|
"account_ids": [], |
||||
|
"partner_ids": [], |
||||
|
"date_range_id": [], |
||||
|
"journal_ids": [], |
||||
|
} |
||||
|
} |
||||
|
if not self.company_id: |
||||
|
return res |
||||
|
else: |
||||
|
res["domain"]["account_ids"] += [("company_id", "=", self.company_id.id)] |
||||
|
res["domain"]["partner_ids"] += self._get_partner_ids_domain() |
||||
|
res["domain"]["date_range_id"] += [ |
||||
|
"|", |
||||
|
("company_id", "=", self.company_id.id), |
||||
|
("company_id", "=", False), |
||||
|
] |
||||
|
res["domain"]["journal_ids"] += [("company_id", "=", self.company_id.id)] |
||||
|
return res |
||||
|
|
||||
|
@api.onchange("date_range_id") |
||||
|
def onchange_date_range_id(self): |
||||
|
"""Handle date range change.""" |
||||
|
self.date_from = self.date_range_id.date_start |
||||
|
self.date_to = self.date_range_id.date_end |
||||
|
|
||||
|
@api.constrains("company_id", "date_range_id") |
||||
|
def _check_company_id_date_range_id(self): |
||||
|
for rec in self.sudo(): |
||||
|
if ( |
||||
|
rec.company_id |
||||
|
and rec.date_range_id.company_id |
||||
|
and rec.company_id != rec.date_range_id.company_id |
||||
|
): |
||||
|
raise ValidationError( |
||||
|
_( |
||||
|
"The Company in the Trial Balance Report Wizard and in " |
||||
|
"Date Range must be the same." |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
@api.onchange("receivable_accounts_only", "payable_accounts_only") |
||||
|
def onchange_type_accounts_only(self): |
||||
|
"""Handle receivable/payable accounts only change.""" |
||||
|
if self.receivable_accounts_only or self.payable_accounts_only: |
||||
|
domain = [("company_id", "=", self.company_id.id)] |
||||
|
if self.receivable_accounts_only and self.payable_accounts_only: |
||||
|
domain += [("internal_type", "in", ("receivable", "payable"))] |
||||
|
elif self.receivable_accounts_only: |
||||
|
domain += [("internal_type", "=", "receivable")] |
||||
|
elif self.payable_accounts_only: |
||||
|
domain += [("internal_type", "=", "payable")] |
||||
|
self.account_ids = self.env["account.account"].search(domain) |
||||
|
else: |
||||
|
self.account_ids = None |
||||
|
|
||||
|
@api.onchange("show_partner_details") |
||||
|
def onchange_show_partner_details(self): |
||||
|
"""Handle partners change.""" |
||||
|
if self.show_partner_details: |
||||
|
self.receivable_accounts_only = self.payable_accounts_only = True |
||||
|
else: |
||||
|
self.receivable_accounts_only = self.payable_accounts_only = False |
||||
|
|
||||
|
@api.depends("company_id") |
||||
|
def _compute_unaffected_earnings_account(self): |
||||
|
account_type = self.env.ref("account.data_unaffected_earnings") |
||||
|
for record in self: |
||||
|
record.unaffected_earnings_account = self.env["account.account"].search( |
||||
|
[ |
||||
|
("user_type_id", "=", account_type.id), |
||||
|
("company_id", "=", record.company_id.id), |
||||
|
] |
||||
|
) |
||||
|
|
||||
|
unaffected_earnings_account = fields.Many2one( |
||||
|
comodel_name="account.account", |
||||
|
compute="_compute_unaffected_earnings_account", |
||||
|
store=True, |
||||
|
) |
||||
|
|
||||
|
def _print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
data = self._prepare_report_trial_balance() |
||||
|
if report_type == "xlsx": |
||||
|
report_name = "a_f_r.report_trial_balance_xlsx" |
||||
|
else: |
||||
|
report_name = "account_financial_report.trial_balance" |
||||
|
return ( |
||||
|
self.env["ir.actions.report"] |
||||
|
.search( |
||||
|
[("report_name", "=", report_name), ("report_type", "=", report_type)], |
||||
|
limit=1, |
||||
|
) |
||||
|
.report_action(self, data=data) |
||||
|
) |
||||
|
|
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-html" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-pdf" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "xlsx" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def _prepare_report_trial_balance(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
"wizard_id": self.id, |
||||
|
"date_from": self.date_from, |
||||
|
"date_to": self.date_to, |
||||
|
"only_posted_moves": self.target_move == "posted", |
||||
|
"hide_account_at_0": self.hide_account_at_0, |
||||
|
"foreign_currency": self.foreign_currency, |
||||
|
"company_id": self.company_id.id, |
||||
|
"account_ids": self.account_ids.ids or [], |
||||
|
"partner_ids": self.partner_ids.ids or [], |
||||
|
"journal_ids": self.journal_ids.ids or [], |
||||
|
"fy_start_date": self.fy_start_date, |
||||
|
"hierarchy_on": self.hierarchy_on, |
||||
|
"limit_hierarchy_level": self.limit_hierarchy_level, |
||||
|
"show_hierarchy_level": self.show_hierarchy_level, |
||||
|
"hide_parent_hierarchy_level": self.hide_parent_hierarchy_level, |
||||
|
"show_partner_details": self.show_partner_details, |
||||
|
"unaffected_earnings_account": self.unaffected_earnings_account.id, |
||||
|
"account_financial_report_lang": self.env.lang, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
return self._print_report(report_type) |
@ -0,0 +1,157 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<!-- TRIAL BALANCE --> |
||||
|
<record id="trial_balance_wizard" model="ir.ui.view"> |
||||
|
<field name="name">Trial Balance</field> |
||||
|
<field name="model">trial.balance.report.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form> |
||||
|
<group name="main_info"> |
||||
|
<field |
||||
|
name="company_id" |
||||
|
options="{'no_create': True}" |
||||
|
groups="base.group_multi_company" |
||||
|
/> |
||||
|
</group> |
||||
|
<div |
||||
|
attrs="{'invisible': [('not_only_one_unaffected_earnings_account', '=', True)]}" |
||||
|
> |
||||
|
<group name="filters"> |
||||
|
<group name="date_range"> |
||||
|
<field name="date_range_id" /> |
||||
|
<field name="date_from" /> |
||||
|
<field name="date_to" /> |
||||
|
<field name="fy_start_date" invisible="1" /> |
||||
|
</group> |
||||
|
<group name="other_filters"> |
||||
|
<field name="target_move" widget="radio" /> |
||||
|
<field name="hide_account_at_0" /> |
||||
|
<field name="show_partner_details" /> |
||||
|
<field |
||||
|
name="hierarchy_on" |
||||
|
widget="radio" |
||||
|
attrs="{'invisible':[('show_partner_details','=',True)]}" |
||||
|
/> |
||||
|
<field |
||||
|
name="limit_hierarchy_level" |
||||
|
attrs="{'invisible':['|', ('hierarchy_on','in',['none', 'computed']),('show_partner_details','=',True)]}" |
||||
|
/> |
||||
|
<field |
||||
|
name="show_hierarchy_level" |
||||
|
attrs="{'invisible':[('limit_hierarchy_level','=', False)]}" |
||||
|
/> |
||||
|
<field |
||||
|
name="hide_parent_hierarchy_level" |
||||
|
attrs="{'invisible':[('limit_hierarchy_level','=', False)]}" |
||||
|
/> |
||||
|
<field name="foreign_currency" /> |
||||
|
</group> |
||||
|
</group> |
||||
|
<group |
||||
|
name="partner_filter" |
||||
|
attrs="{'invisible':[('show_partner_details','!=',True)]}" |
||||
|
col="1" |
||||
|
> |
||||
|
<label for="partner_ids" /> |
||||
|
<field |
||||
|
name="partner_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</group> |
||||
|
<label for="journal_ids" /> |
||||
|
<field |
||||
|
name="journal_ids" |
||||
|
widget="many2many_tags" |
||||
|
nolabel="1" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
<group attrs="{'invisible':[('show_partner_details','!=',True)]}" /> |
||||
|
<div /> |
||||
|
<group name="account_filter" col="4"> |
||||
|
<label for="account_ids" colspan="4" /> |
||||
|
<field name="receivable_accounts_only" /> |
||||
|
<field name="payable_accounts_only" /> |
||||
|
<label for="account_code_from" string="From Code" /> |
||||
|
<div> |
||||
|
<div class="o_row"> |
||||
|
<field |
||||
|
name="account_code_from" |
||||
|
class="oe_inline" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
<span class="oe_inline">To</span> |
||||
|
<field |
||||
|
name="account_code_to" |
||||
|
class="oe_inline" |
||||
|
options="{'no_create': True}" |
||||
|
/> |
||||
|
</div> |
||||
|
</div> |
||||
|
<field |
||||
|
name="account_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
colspan="4" |
||||
|
/> |
||||
|
</group> |
||||
|
</div> |
||||
|
<div |
||||
|
attrs="{'invisible': [('not_only_one_unaffected_earnings_account', '=', False)]}" |
||||
|
> |
||||
|
<field |
||||
|
name="not_only_one_unaffected_earnings_account" |
||||
|
invisible="1" |
||||
|
/> |
||||
|
<group /> |
||||
|
<h4> |
||||
|
Trial Balance can be computed only if selected company have only |
||||
|
one unaffected earnings account. |
||||
|
</h4> |
||||
|
<group /> |
||||
|
</div> |
||||
|
<footer> |
||||
|
<div |
||||
|
attrs="{'invisible': [('not_only_one_unaffected_earnings_account', '=', True)]}" |
||||
|
> |
||||
|
<button |
||||
|
name="button_export_html" |
||||
|
string="View" |
||||
|
type="object" |
||||
|
default_focus="1" |
||||
|
class="oe_highlight" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_pdf" |
||||
|
string="Export PDF" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_xlsx" |
||||
|
string="Export XLSX" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</div> |
||||
|
<div |
||||
|
attrs="{'invisible': [('not_only_one_unaffected_earnings_account', '=', False)]}" |
||||
|
> |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</div> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record id="action_trial_balance_wizard" model="ir.actions.act_window"> |
||||
|
<field name="name">Trial Balance</field> |
||||
|
<field name="res_model">trial.balance.report.wizard</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="trial_balance_wizard" /> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -0,0 +1,121 @@ |
|||||
|
# Copyright 2018 Forest and Biomass Romania |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import _, api, fields, models |
||||
|
from odoo.exceptions import ValidationError |
||||
|
|
||||
|
|
||||
|
class VATReportWizard(models.TransientModel): |
||||
|
_name = "vat.report.wizard" |
||||
|
_description = "VAT Report Wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name="res.company", |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
required=False, |
||||
|
string="Company", |
||||
|
) |
||||
|
date_range_id = fields.Many2one(comodel_name="date.range", string="Date range") |
||||
|
date_from = fields.Date("Start Date", required=True) |
||||
|
date_to = fields.Date("End Date", required=True) |
||||
|
based_on = fields.Selection( |
||||
|
[("taxtags", "Tax Tags"), ("taxgroups", "Tax Groups")], |
||||
|
string="Based On", |
||||
|
required=True, |
||||
|
default="taxtags", |
||||
|
) |
||||
|
tax_detail = fields.Boolean("Detail Taxes") |
||||
|
target_move = fields.Selection( |
||||
|
[("posted", "All Posted Entries"), ("all", "All Entries")], |
||||
|
string="Target Moves", |
||||
|
required=True, |
||||
|
default="posted", |
||||
|
) |
||||
|
|
||||
|
@api.onchange("company_id") |
||||
|
def onchange_company_id(self): |
||||
|
if ( |
||||
|
self.company_id |
||||
|
and self.date_range_id.company_id |
||||
|
and self.date_range_id.company_id != self.company_id |
||||
|
): |
||||
|
self.date_range_id = False |
||||
|
res = {"domain": {"date_range_id": []}} |
||||
|
if not self.company_id: |
||||
|
return res |
||||
|
else: |
||||
|
res["domain"]["date_range_id"] += [ |
||||
|
"|", |
||||
|
("company_id", "=", self.company_id.id), |
||||
|
("company_id", "=", False), |
||||
|
] |
||||
|
return res |
||||
|
|
||||
|
@api.onchange("date_range_id") |
||||
|
def onchange_date_range_id(self): |
||||
|
"""Handle date range change.""" |
||||
|
self.date_from = self.date_range_id.date_start |
||||
|
self.date_to = self.date_range_id.date_end |
||||
|
|
||||
|
@api.constrains("company_id", "date_range_id") |
||||
|
def _check_company_id_date_range_id(self): |
||||
|
for rec in self.sudo(): |
||||
|
if ( |
||||
|
rec.company_id |
||||
|
and rec.date_range_id.company_id |
||||
|
and rec.company_id != rec.date_range_id.company_id |
||||
|
): |
||||
|
raise ValidationError( |
||||
|
_( |
||||
|
"The Company in the Vat Report Wizard and in " |
||||
|
"Date Range must be the same." |
||||
|
) |
||||
|
) |
||||
|
|
||||
|
def _print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
data = self._prepare_vat_report() |
||||
|
if report_type == "xlsx": |
||||
|
report_name = "a_f_r.report_vat_report_xlsx" |
||||
|
else: |
||||
|
report_name = "account_financial_report.vat_report" |
||||
|
return ( |
||||
|
self.env["ir.actions.report"] |
||||
|
.search( |
||||
|
[("report_name", "=", report_name), ("report_type", "=", report_type)], |
||||
|
limit=1, |
||||
|
) |
||||
|
.report_action(self, data=data) |
||||
|
) |
||||
|
|
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-html" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "qweb-pdf" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
report_type = "xlsx" |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
def _prepare_vat_report(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
"wizard_id": self.id, |
||||
|
"company_id": self.company_id.id, |
||||
|
"date_from": self.date_from, |
||||
|
"date_to": self.date_to, |
||||
|
"based_on": self.based_on, |
||||
|
"only_posted_moves": self.target_move == "posted", |
||||
|
"tax_detail": self.tax_detail, |
||||
|
"account_financial_report_lang": self.env.lang, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
return self._print_report(report_type) |
@ -0,0 +1,60 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8" ?> |
||||
|
<odoo> |
||||
|
<record id="vat_report_wizard" model="ir.ui.view"> |
||||
|
<field name="name">vat_report_wizard_view</field> |
||||
|
<field name="model">vat.report.wizard</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form string="VAT Report Options"> |
||||
|
<group name="main_info"> |
||||
|
<field |
||||
|
name="company_id" |
||||
|
options="{'no_create': True}" |
||||
|
groups="base.group_multi_company" |
||||
|
/> |
||||
|
</group> |
||||
|
<group name="filters"> |
||||
|
<group name="date_range"> |
||||
|
<field name="date_range_id" /> |
||||
|
<field name="date_from" /> |
||||
|
<field name="date_to" /> |
||||
|
</group> |
||||
|
</group> |
||||
|
<group name="other_filters"> |
||||
|
<field name="target_move" widget="radio" /> |
||||
|
<field name="based_on" widget="radio" /> |
||||
|
<field name="tax_detail" /> |
||||
|
</group> |
||||
|
<footer> |
||||
|
<button |
||||
|
name="button_export_html" |
||||
|
string="View" |
||||
|
type="object" |
||||
|
default_focus="1" |
||||
|
class="oe_highlight" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_pdf" |
||||
|
string="Export PDF" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button |
||||
|
name="button_export_xlsx" |
||||
|
string="Export XLSX" |
||||
|
type="object" |
||||
|
/> |
||||
|
or |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record id="action_vat_report_wizard" model="ir.actions.act_window"> |
||||
|
<field name="name">VAT Report</field> |
||||
|
<field name="res_model">vat.report.wizard</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="vat_report_wizard" /> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
</odoo> |
@ -1 +1,3 @@ |
|||||
# See https://github.com/OCA/odoo-community.org/blob/master/website/Contribution/CONTRIBUTING.rst#oca_dependencies-txt |
# See https://github.com/OCA/odoo-community.org/blob/master/website/Contribution/CONTRIBUTING.rst#oca_dependencies-txt |
||||
|
reporting-engine |
||||
|
server-ux |
@ -0,0 +1 @@ |
|||||
|
../../../../account_financial_report |
@ -0,0 +1,6 @@ |
|||||
|
import setuptools |
||||
|
|
||||
|
setuptools.setup( |
||||
|
setup_requires=['setuptools-odoo'], |
||||
|
odoo_addon=True, |
||||
|
) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue