Browse Source
Merge pull request #559 from eLBati/12.0-mig-account_financial_report-2
Merge pull request #559 from eLBati/12.0-mig-account_financial_report-2
[12.0] mig account_financial_reportpull/579/head
Pedro M. Baeza
5 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
86 changed files with 45893 additions and 0 deletions
-
133account_financial_report/README.rst
-
8account_financial_report/__init__.py
-
50account_financial_report/__manifest__.py
-
2535account_financial_report/i18n/account_financial_report.pot
-
2584account_financial_report/i18n/ar.po
-
2553account_financial_report/i18n/ca.po
-
2630account_financial_report/i18n/de.po
-
2607account_financial_report/i18n/es.po
-
2557account_financial_report/i18n/fr.po
-
2559account_financial_report/i18n/hr_HR.po
-
2570account_financial_report/i18n/it.po
-
2627account_financial_report/i18n/nl.po
-
2555account_financial_report/i18n/nl_NL.po
-
2557account_financial_report/i18n/pt.po
-
2598account_financial_report/i18n/ro.po
-
53account_financial_report/menuitems.xml
-
3account_financial_report/models/__init__.py
-
13account_financial_report/models/account.py
-
46account_financial_report/models/account_group.py
-
30account_financial_report/models/account_move_line.py
-
20account_financial_report/readme/CONTRIBUTORS.rst
-
16account_financial_report/readme/DESCRIPTION.rst
-
19account_financial_report/readme/HISTORY.rst
-
19account_financial_report/report/__init__.py
-
23account_financial_report/report/abstract_report.py
-
440account_financial_report/report/abstract_report_xlsx.py
-
633account_financial_report/report/aged_partner_balance.py
-
257account_financial_report/report/aged_partner_balance_xlsx.py
-
1765account_financial_report/report/general_ledger.py
-
183account_financial_report/report/general_ledger_xlsx.py
-
818account_financial_report/report/journal_ledger.py
-
250account_financial_report/report/journal_ledger_xlsx.py
-
957account_financial_report/report/open_items.py
-
119account_financial_report/report/open_items_xlsx.py
-
563account_financial_report/report/templates/aged_partner_balance.xml
-
558account_financial_report/report/templates/general_ledger.xml
-
465account_financial_report/report/templates/journal_ledger.xml
-
26account_financial_report/report/templates/layouts.xml
-
271account_financial_report/report/templates/open_items.xml
-
688account_financial_report/report/templates/trial_balance.xml
-
167account_financial_report/report/templates/vat_report.xml
-
589account_financial_report/report/trial_balance.py
-
192account_financial_report/report/trial_balance_xlsx.py
-
356account_financial_report/report/vat_report.py
-
52account_financial_report/report/vat_report_xlsx.py
-
210account_financial_report/reports.xml
-
BINaccount_financial_report/static/description/icon.png
-
485account_financial_report/static/description/index.html
-
103account_financial_report/static/src/css/report.css
-
114account_financial_report/static/src/js/account_financial_report_backend.js
-
86account_financial_report/static/src/js/account_financial_report_widgets.js
-
13account_financial_report/tests/__init__.py
-
399account_financial_report/tests/abstract_test.py
-
78account_financial_report/tests/abstract_test_foreign_currency.py
-
75account_financial_report/tests/abstract_test_tax_report.py
-
41account_financial_report/tests/test_aged_partner_balance.py
-
553account_financial_report/tests/test_general_ledger.py
-
364account_financial_report/tests/test_journal_ledger.py
-
61account_financial_report/tests/test_open_items.py
-
643account_financial_report/tests/test_trial_balance.py
-
300account_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
-
58account_financial_report/view/report_template.xml
-
11account_financial_report/view/report_trial_balance.xml
-
9account_financial_report/view/report_vat_report.xml
-
7account_financial_report/wizard/__init__.py
-
32account_financial_report/wizard/abstract_wizard.py
-
127account_financial_report/wizard/aged_partner_balance_wizard.py
-
59account_financial_report/wizard/aged_partner_balance_wizard_view.xml
-
259account_financial_report/wizard/general_ledger_wizard.py
-
101account_financial_report/wizard/general_ledger_wizard_view.xml
-
160account_financial_report/wizard/journal_ledger_wizard.py
-
66account_financial_report/wizard/journal_ledger_wizard_view.xml
-
146account_financial_report/wizard/open_items_wizard.py
-
74account_financial_report/wizard/open_items_wizard_view.xml
-
243account_financial_report/wizard/trial_balance_wizard.py
-
91account_financial_report/wizard/trial_balance_wizard_view.xml
-
109account_financial_report/wizard/vat_report_wizard.py
-
44account_financial_report/wizard/vat_report_wizard_view.xml
-
1oca_dependencies.txt
-
1setup/account_financial_report/odoo/addons/account_financial_report
-
6setup/account_financial_report/setup.py
@ -0,0 +1,133 @@ |
|||||
|
========================= |
||||
|
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/12.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-12-0/account-financial-reporting-12-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/12.0 |
||||
|
:alt: Try me on Runbot |
||||
|
|
||||
|
|badge1| |badge2| |badge3| |badge4| |badge5| |
||||
|
|
||||
|
This module adds a set of financial reports. They are accessible under |
||||
|
Accounting / Reporting / OCA 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: |
||||
|
|
||||
|
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:%2012.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 |
||||
|
* Eficent |
||||
|
|
||||
|
Contributors |
||||
|
~~~~~~~~~~~~ |
||||
|
|
||||
|
* Jordi Ballester <jordi.ballester@eficient.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@eficent.com> |
||||
|
|
||||
|
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/12.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,8 @@ |
|||||
|
|
||||
|
# 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,50 @@ |
|||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
{ |
||||
|
'name': 'Account Financial Reports', |
||||
|
'version': '12.0.1.0.0', |
||||
|
'category': 'Reporting', |
||||
|
'summary': 'OCA Financial Reports', |
||||
|
'author': 'Camptocamp SA,' |
||||
|
'initOS GmbH,' |
||||
|
'redCOR AG,' |
||||
|
'Eficent,' |
||||
|
'Odoo Community Association (OCA)', |
||||
|
"website": "https://odoo-community.org/", |
||||
|
'depends': [ |
||||
|
'account', |
||||
|
'date_range', |
||||
|
'report_xlsx', |
||||
|
], |
||||
|
'data': [ |
||||
|
'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', |
||||
|
} |
2535
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
2584
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
2553
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
2630
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
2607
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
2557
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
2559
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
2570
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
2627
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
2555
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
2557
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
2598
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,53 @@ |
|||||
|
<?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,3 @@ |
|||||
|
from . import account |
||||
|
from . import account_group |
||||
|
from . import account_move_line |
@ -0,0 +1,13 @@ |
|||||
|
# © 2011 Guewen Baconnier (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
from odoo import models, fields |
||||
|
|
||||
|
|
||||
|
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,46 @@ |
|||||
|
# © 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', |
||||
|
store=True) |
||||
|
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) |
||||
|
|
||||
|
@api.multi |
||||
|
@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.multi |
||||
|
@api.depends('code_prefix', '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 if group.code_prefix 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,30 @@ |
|||||
|
# 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' |
||||
|
|
||||
|
@api.model_cr |
||||
|
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)""") |
@ -0,0 +1,20 @@ |
|||||
|
* Jordi Ballester <jordi.ballester@eficient.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@eficent.com> |
||||
|
|
||||
|
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 |
||||
|
Accounting / Reporting / OCA 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,19 @@ |
|||||
|
# © 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 |
||||
|
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,23 @@ |
|||||
|
# Copyright 2018 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import models |
||||
|
from psycopg2.extensions import AsIs |
||||
|
|
||||
|
|
||||
|
class AbstractReport(models.AbstractModel): |
||||
|
_name = 'account_financial_report_abstract' |
||||
|
_description = 'Abstract Report' |
||||
|
|
||||
|
def _transient_clean_rows_older_than(self, seconds): |
||||
|
assert self._transient, \ |
||||
|
"Model %s is not transient, it cannot be vacuumed!" % self._name |
||||
|
# Never delete rows used in last 5 minutes |
||||
|
seconds = max(seconds, 300) |
||||
|
query = ( |
||||
|
"DELETE FROM %s" |
||||
|
" WHERE COALESCE(" |
||||
|
"write_date, create_date, (now() at time zone 'UTC'))" |
||||
|
"::timestamp < ((now() at time zone 'UTC') - interval %s)" |
||||
|
) |
||||
|
self.env.cr.execute(query, (AsIs(self._table), "%s seconds" % seconds)) |
@ -0,0 +1,440 @@ |
|||||
|
|
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
from odoo import models, fields |
||||
|
import datetime |
||||
|
|
||||
|
|
||||
|
class AbstractReportXslx(models.AbstractModel): |
||||
|
_name = 'report.account_financial_report.abstract_report_xlsx' |
||||
|
_inherit = 'report.report_xlsx.abstract' |
||||
|
|
||||
|
def __init__(self, pool, cr): |
||||
|
# main sheet which will contains report |
||||
|
self.sheet = None |
||||
|
|
||||
|
# columns of the report |
||||
|
self.columns = None |
||||
|
|
||||
|
# row_pos must be incremented at each writing lines |
||||
|
self.row_pos = None |
||||
|
|
||||
|
# Formats |
||||
|
self.format_right = None |
||||
|
self.format_left = None |
||||
|
self.format_right_bold_italic = None |
||||
|
self.format_bold = None |
||||
|
self.format_header_left = None |
||||
|
self.format_header_center = None |
||||
|
self.format_header_right = None |
||||
|
self.format_header_amount = None |
||||
|
self.format_amount = None |
||||
|
self.format_percent_bold_italic = None |
||||
|
|
||||
|
def get_workbook_options(self): |
||||
|
return {'constant_memory': True} |
||||
|
|
||||
|
def generate_xlsx_report(self, workbook, data, objects): |
||||
|
report = objects |
||||
|
|
||||
|
self.row_pos = 0 |
||||
|
|
||||
|
self._define_formats(workbook) |
||||
|
|
||||
|
report_name = self._get_report_name(report) |
||||
|
report_footer = self._get_report_footer() |
||||
|
filters = self._get_report_filters(report) |
||||
|
self.columns = self._get_report_columns(report) |
||||
|
self.workbook = workbook |
||||
|
self.sheet = workbook.add_worksheet(report_name[:31]) |
||||
|
|
||||
|
self._set_column_width() |
||||
|
|
||||
|
self._write_report_title(report_name) |
||||
|
|
||||
|
self._write_filters(filters) |
||||
|
|
||||
|
self._generate_report_content(workbook, report) |
||||
|
|
||||
|
self._write_report_footer(report_footer) |
||||
|
|
||||
|
def _define_formats(self, workbook): |
||||
|
""" 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 |
||||
|
""" |
||||
|
self.format_bold = workbook.add_format({'bold': True}) |
||||
|
self.format_right = workbook.add_format({'align': 'right'}) |
||||
|
self.format_left = workbook.add_format({'align': 'left'}) |
||||
|
self.format_right_bold_italic = workbook.add_format( |
||||
|
{'align': 'right', 'bold': True, 'italic': True} |
||||
|
) |
||||
|
self.format_header_left = workbook.add_format( |
||||
|
{'bold': True, |
||||
|
'border': True, |
||||
|
'bg_color': '#FFFFCC'}) |
||||
|
self.format_header_center = workbook.add_format( |
||||
|
{'bold': True, |
||||
|
'align': 'center', |
||||
|
'border': True, |
||||
|
'bg_color': '#FFFFCC'}) |
||||
|
self.format_header_right = workbook.add_format( |
||||
|
{'bold': True, |
||||
|
'align': 'right', |
||||
|
'border': True, |
||||
|
'bg_color': '#FFFFCC'}) |
||||
|
self.format_header_amount = workbook.add_format( |
||||
|
{'bold': True, |
||||
|
'border': True, |
||||
|
'bg_color': '#FFFFCC'}) |
||||
|
currency_id = self.env['res.company']._get_user_currency() |
||||
|
self.format_header_amount.set_num_format( |
||||
|
'#,##0.'+'0'*currency_id.decimal_places) |
||||
|
self.format_amount = workbook.add_format() |
||||
|
self.format_amount.set_num_format( |
||||
|
'#,##0.'+'0'*currency_id.decimal_places) |
||||
|
self.format_amount_bold = workbook.add_format({'bold': True}) |
||||
|
self.format_amount_bold.set_num_format( |
||||
|
'#,##0.' + '0' * currency_id.decimal_places) |
||||
|
self.format_percent_bold_italic = workbook.add_format( |
||||
|
{'bold': True, 'italic': True} |
||||
|
) |
||||
|
self.format_percent_bold_italic.set_num_format('#,##0.00%') |
||||
|
|
||||
|
def _set_column_width(self): |
||||
|
"""Set width for all defined columns. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
for position, column in self.columns.items(): |
||||
|
self.sheet.set_column(position, position, column['width']) |
||||
|
|
||||
|
def _write_report_title(self, title): |
||||
|
"""Write report title on current line using all defined columns width. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
self.sheet.merge_range( |
||||
|
self.row_pos, 0, self.row_pos, len(self.columns) - 1, |
||||
|
title, self.format_bold |
||||
|
) |
||||
|
self.row_pos += 3 |
||||
|
|
||||
|
def _write_report_footer(self, footer): |
||||
|
"""Write report footer . |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
if footer: |
||||
|
self.row_pos += 1 |
||||
|
self.sheet.merge_range( |
||||
|
self.row_pos, 0, self.row_pos, len(self.columns) - 1, |
||||
|
footer, self.format_left |
||||
|
) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
def _write_filters(self, filters): |
||||
|
"""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: |
||||
|
self.sheet.merge_range( |
||||
|
self.row_pos, col_name, |
||||
|
self.row_pos, col_name + col_count_filter_name - 1, |
||||
|
title, self.format_header_left) |
||||
|
self.sheet.merge_range( |
||||
|
self.row_pos, col_value, |
||||
|
self.row_pos, col_value + col_count_filter_value - 1, |
||||
|
value) |
||||
|
self.row_pos += 1 |
||||
|
self.row_pos += 2 |
||||
|
|
||||
|
def write_array_title(self, title): |
||||
|
"""Write array title on current line using all defined columns width. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
self.sheet.merge_range( |
||||
|
self.row_pos, 0, self.row_pos, len(self.columns) - 1, |
||||
|
title, self.format_bold |
||||
|
) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
def write_array_header(self): |
||||
|
"""Write array header on current line using all defined columns name. |
||||
|
Columns are defined with `_get_report_columns` method. |
||||
|
""" |
||||
|
for col_pos, column in self.columns.items(): |
||||
|
self.sheet.write(self.row_pos, col_pos, column['header'], |
||||
|
self.format_header_center) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
def write_line(self, line_object): |
||||
|
"""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 self.columns.items(): |
||||
|
value = getattr(line_object, column['field']) |
||||
|
if isinstance(value, datetime.date): |
||||
|
value = fields.Date.to_string(value) |
||||
|
cell_type = column.get('type', 'string') |
||||
|
if cell_type == 'many2one': |
||||
|
self.sheet.write_string( |
||||
|
self.row_pos, col_pos, value.name or '', self.format_right) |
||||
|
elif cell_type == 'string': |
||||
|
if hasattr(line_object, 'account_group_id') and \ |
||||
|
line_object.account_group_id: |
||||
|
self.sheet.write_string(self.row_pos, col_pos, value or '', |
||||
|
self.format_bold) |
||||
|
else: |
||||
|
self.sheet.write_string(self.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 = self.format_amount_bold |
||||
|
else: |
||||
|
cell_format = self.format_amount |
||||
|
self.sheet.write_number( |
||||
|
self.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) |
||||
|
self.sheet.write_number( |
||||
|
self.row_pos, col_pos, float(value), format_amt |
||||
|
) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
def write_initial_balance(self, my_object, label): |
||||
|
"""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() |
||||
|
self.sheet.write(self.row_pos, col_pos_label, label, self.format_right) |
||||
|
for col_pos, column in self.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': |
||||
|
self.sheet.write_string(self.row_pos, col_pos, value or '') |
||||
|
elif cell_type == 'amount': |
||||
|
self.sheet.write_number( |
||||
|
self.row_pos, col_pos, float(value), self.format_amount |
||||
|
) |
||||
|
elif cell_type == 'amount_currency': |
||||
|
if my_object.currency_id: |
||||
|
format_amt = self._get_currency_amt_format( |
||||
|
my_object) |
||||
|
self.sheet.write_number( |
||||
|
self.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: |
||||
|
self.sheet.write_string( |
||||
|
self.row_pos, col_pos, |
||||
|
value.name or '', |
||||
|
self.format_right |
||||
|
) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
def write_ending_balance(self, my_object, name, label): |
||||
|
"""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(self.columns)): |
||||
|
self.sheet.write(self.row_pos, i, '', self.format_header_right) |
||||
|
row_count_name = self._get_col_count_final_balance_name() |
||||
|
col_pos_label = self._get_col_pos_final_balance_label() |
||||
|
self.sheet.merge_range( |
||||
|
self.row_pos, 0, self.row_pos, row_count_name - 1, name, |
||||
|
self.format_header_left |
||||
|
) |
||||
|
self.sheet.write(self.row_pos, col_pos_label, label, |
||||
|
self.format_header_right) |
||||
|
for col_pos, column in self.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': |
||||
|
self.sheet.write_string(self.row_pos, col_pos, value or '', |
||||
|
self.format_header_right) |
||||
|
elif cell_type == 'amount': |
||||
|
self.sheet.write_number( |
||||
|
self.row_pos, col_pos, float(value), |
||||
|
self.format_header_amount |
||||
|
) |
||||
|
elif cell_type == 'amount_currency': |
||||
|
if my_object.currency_id: |
||||
|
format_amt = self._get_currency_amt_header_format( |
||||
|
my_object) |
||||
|
self.sheet.write_number( |
||||
|
self.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: |
||||
|
self.sheet.write_string( |
||||
|
self.row_pos, col_pos, |
||||
|
value.name or '', |
||||
|
self.format_header_right |
||||
|
) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
def _get_currency_amt_format(self, line_object): |
||||
|
""" Return amount format specific for each currency. """ |
||||
|
if hasattr(line_object, 'account_group_id') and \ |
||||
|
line_object.account_group_id: |
||||
|
format_amt = getattr(self, 'format_amount_bold') |
||||
|
field_prefix = 'format_amount_bold' |
||||
|
else: |
||||
|
format_amt = getattr(self, 'format_amount') |
||||
|
field_prefix = 'format_amount' |
||||
|
if line_object.currency_id: |
||||
|
field_name = \ |
||||
|
'%s_%s' % (field_prefix, line_object.currency_id.name) |
||||
|
if hasattr(self, field_name): |
||||
|
format_amt = getattr(self, field_name) |
||||
|
else: |
||||
|
format_amt = self.workbook.add_format() |
||||
|
setattr(self, '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(self, line_object): |
||||
|
""" Return amount header format for each currency. """ |
||||
|
format_amt = getattr(self, '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 = self.workbook.add_format( |
||||
|
{'bold': True, |
||||
|
'border': True, |
||||
|
'bg_color': '#FFFFCC'}) |
||||
|
setattr(self, '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): |
||||
|
""" |
||||
|
Allow to fetch report content to be displayed. |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _get_report_complete_name(self, report, prefix): |
||||
|
if report.company_id: |
||||
|
suffix = ' - %s - %s' % ( |
||||
|
report.company_id.name, report.company_id.currency_id.name) |
||||
|
return prefix + suffix |
||||
|
return prefix |
||||
|
|
||||
|
def _get_report_name(self, report): |
||||
|
""" |
||||
|
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,633 @@ |
|||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import models, fields, api |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReport(models.TransientModel): |
||||
|
""" Here, we just define class fields. |
||||
|
For methods, go more bottom at this file. |
||||
|
|
||||
|
The class hierarchy is : |
||||
|
* AgedPartnerBalanceReport |
||||
|
** AgedPartnerBalanceReportAccount |
||||
|
*** AgedPartnerBalanceReportPartner |
||||
|
**** AgedPartnerBalanceReportLine |
||||
|
**** AgedPartnerBalanceReportMoveLine |
||||
|
If "show_move_line_details" is selected |
||||
|
""" |
||||
|
|
||||
|
_name = 'report_aged_partner_balance' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
# Filters fields, used for data computation |
||||
|
date_at = fields.Date() |
||||
|
only_posted_moves = fields.Boolean() |
||||
|
company_id = fields.Many2one(comodel_name='res.company') |
||||
|
filter_account_ids = fields.Many2many(comodel_name='account.account') |
||||
|
filter_partner_ids = fields.Many2many(comodel_name='res.partner') |
||||
|
show_move_line_details = fields.Boolean() |
||||
|
|
||||
|
# Open Items Report Data fields, used as base for compute the data reports |
||||
|
open_items_id = fields.Many2one(comodel_name='report_open_items') |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
account_ids = fields.One2many( |
||||
|
comodel_name='report_aged_partner_balance_account', |
||||
|
inverse_name='report_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReportAccount(models.TransientModel): |
||||
|
_name = 'report_aged_partner_balance_account' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
_order = 'code ASC' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_aged_partner_balance', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
account_id = fields.Many2one( |
||||
|
'account.account', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
code = fields.Char() |
||||
|
name = fields.Char() |
||||
|
|
||||
|
cumul_amount_residual = fields.Float(digits=(16, 2)) |
||||
|
cumul_current = fields.Float(digits=(16, 2)) |
||||
|
cumul_age_30_days = fields.Float(digits=(16, 2)) |
||||
|
cumul_age_60_days = fields.Float(digits=(16, 2)) |
||||
|
cumul_age_90_days = fields.Float(digits=(16, 2)) |
||||
|
cumul_age_120_days = fields.Float(digits=(16, 2)) |
||||
|
cumul_older = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
percent_current = fields.Float(digits=(16, 2)) |
||||
|
percent_age_30_days = fields.Float(digits=(16, 2)) |
||||
|
percent_age_60_days = fields.Float(digits=(16, 2)) |
||||
|
percent_age_90_days = fields.Float(digits=(16, 2)) |
||||
|
percent_age_120_days = fields.Float(digits=(16, 2)) |
||||
|
percent_older = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
partner_ids = fields.One2many( |
||||
|
comodel_name='report_aged_partner_balance_partner', |
||||
|
inverse_name='report_account_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReportPartner(models.TransientModel): |
||||
|
_name = 'report_aged_partner_balance_partner' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
report_account_id = fields.Many2one( |
||||
|
comodel_name='report_aged_partner_balance_account', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
partner_id = fields.Many2one( |
||||
|
'res.partner', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
name = fields.Char() |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
move_line_ids = fields.One2many( |
||||
|
comodel_name='report_aged_partner_balance_move_line', |
||||
|
inverse_name='report_partner_id' |
||||
|
) |
||||
|
line_ids = fields.One2many( |
||||
|
comodel_name='report_aged_partner_balance_line', |
||||
|
inverse_name='report_partner_id' |
||||
|
) |
||||
|
|
||||
|
@api.model |
||||
|
def _generate_order_by(self, order_spec, query): |
||||
|
"""Custom order to display "No partner allocated" at last position.""" |
||||
|
return """ |
||||
|
ORDER BY |
||||
|
CASE |
||||
|
WHEN |
||||
|
"report_aged_partner_balance_partner"."partner_id" IS NOT NULL |
||||
|
THEN 0 |
||||
|
ELSE 1 |
||||
|
END, |
||||
|
"report_aged_partner_balance_partner"."name" |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReportLine(models.TransientModel): |
||||
|
_name = 'report_aged_partner_balance_line' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
report_partner_id = fields.Many2one( |
||||
|
comodel_name='report_aged_partner_balance_partner', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
partner = fields.Char() |
||||
|
amount_residual = fields.Float(digits=(16, 2)) |
||||
|
current = fields.Float(digits=(16, 2)) |
||||
|
age_30_days = fields.Float(digits=(16, 2)) |
||||
|
age_60_days = fields.Float(digits=(16, 2)) |
||||
|
age_90_days = fields.Float(digits=(16, 2)) |
||||
|
age_120_days = fields.Float(digits=(16, 2)) |
||||
|
older = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReportMoveLine(models.TransientModel): |
||||
|
_name = 'report_aged_partner_balance_move_line' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
report_partner_id = fields.Many2one( |
||||
|
comodel_name='report_aged_partner_balance_partner', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
move_line_id = fields.Many2one('account.move.line') |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
date = fields.Date() |
||||
|
date_due = fields.Date() |
||||
|
entry = fields.Char() |
||||
|
journal = fields.Char() |
||||
|
account = fields.Char() |
||||
|
partner = fields.Char() |
||||
|
label = fields.Char() |
||||
|
|
||||
|
amount_residual = fields.Float(digits=(16, 2)) |
||||
|
current = fields.Float(digits=(16, 2)) |
||||
|
age_30_days = fields.Float(digits=(16, 2)) |
||||
|
age_60_days = fields.Float(digits=(16, 2)) |
||||
|
age_90_days = fields.Float(digits=(16, 2)) |
||||
|
age_120_days = fields.Float(digits=(16, 2)) |
||||
|
older = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReportCompute(models.TransientModel): |
||||
|
""" Here, we just define methods. |
||||
|
For class fields, go more top at this file. |
||||
|
""" |
||||
|
|
||||
|
_inherit = 'report_aged_partner_balance' |
||||
|
|
||||
|
@api.multi |
||||
|
def print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
if report_type == 'xlsx': |
||||
|
report_name = 'a_f_r.report_aged_partner_balance_xlsx' |
||||
|
else: |
||||
|
report_name = 'account_financial_report.' \ |
||||
|
'report_aged_partner_balance_qweb' |
||||
|
report = self.env['ir.actions.report'].search( |
||||
|
[('report_name', '=', report_name), |
||||
|
('report_type', '=', report_type)], limit=1) |
||||
|
return report.report_action(self, config=False) |
||||
|
|
||||
|
def _get_html(self): |
||||
|
result = {} |
||||
|
rcontext = {} |
||||
|
context = dict(self.env.context) |
||||
|
report = self.browse(context.get('active_id')) |
||||
|
if report: |
||||
|
rcontext['o'] = report |
||||
|
result['html'] = self.env.ref( |
||||
|
'account_financial_report.report_aged_partner_balance').render( |
||||
|
rcontext) |
||||
|
return result |
||||
|
|
||||
|
@api.model |
||||
|
def get_html(self, given_context=None): |
||||
|
return self._get_html() |
||||
|
|
||||
|
def _prepare_report_open_items(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
'date_at': self.date_at, |
||||
|
'only_posted_moves': self.only_posted_moves, |
||||
|
'company_id': self.company_id.id, |
||||
|
'filter_account_ids': [(6, 0, self.filter_account_ids.ids)], |
||||
|
'filter_partner_ids': [(6, 0, self.filter_partner_ids.ids)], |
||||
|
} |
||||
|
|
||||
|
@api.multi |
||||
|
def compute_data_for_report(self): |
||||
|
self.ensure_one() |
||||
|
# Compute Open Items Report Data. |
||||
|
# The data of Aged Partner Balance Report |
||||
|
# are based on Open Items Report data. |
||||
|
model = self.env['report_open_items'] |
||||
|
self.open_items_id = model.create(self._prepare_report_open_items()) |
||||
|
self.open_items_id.compute_data_for_report() |
||||
|
|
||||
|
# Compute report data |
||||
|
self._inject_account_values() |
||||
|
self._inject_partner_values() |
||||
|
self._inject_line_values() |
||||
|
self._inject_line_values(only_empty_partner_line=True) |
||||
|
if self.show_move_line_details: |
||||
|
self._inject_move_line_values() |
||||
|
self._inject_move_line_values(only_empty_partner_line=True) |
||||
|
self._compute_accounts_cumul() |
||||
|
# Refresh cache because all data are computed with SQL requests |
||||
|
self.invalidate_cache() |
||||
|
|
||||
|
def _inject_account_values(self): |
||||
|
"""Inject report values for report_aged_partner_balance_account""" |
||||
|
query_inject_account = """ |
||||
|
INSERT INTO |
||||
|
report_aged_partner_balance_account |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
account_id, |
||||
|
code, |
||||
|
name |
||||
|
) |
||||
|
SELECT |
||||
|
%s AS report_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
rao.account_id, |
||||
|
rao.code, |
||||
|
rao.name |
||||
|
FROM |
||||
|
report_open_items_account rao |
||||
|
WHERE |
||||
|
rao.report_id = %s |
||||
|
""" |
||||
|
query_inject_account_params = ( |
||||
|
self.id, |
||||
|
self.env.uid, |
||||
|
self.open_items_id.id, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_account, query_inject_account_params) |
||||
|
|
||||
|
def _inject_partner_values(self): |
||||
|
"""Inject report values for report_aged_partner_balance_partner""" |
||||
|
query_inject_partner = """ |
||||
|
INSERT INTO |
||||
|
report_aged_partner_balance_partner |
||||
|
( |
||||
|
report_account_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
partner_id, |
||||
|
name |
||||
|
) |
||||
|
SELECT |
||||
|
ra.id AS report_account_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
rpo.partner_id, |
||||
|
rpo.name |
||||
|
FROM |
||||
|
report_open_items_partner rpo |
||||
|
INNER JOIN |
||||
|
report_open_items_account rao ON rpo.report_account_id = rao.id |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_account ra ON rao.code = ra.code |
||||
|
WHERE |
||||
|
rao.report_id = %s |
||||
|
AND ra.report_id = %s |
||||
|
""" |
||||
|
query_inject_partner_params = ( |
||||
|
self.env.uid, |
||||
|
self.open_items_id.id, |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_partner, query_inject_partner_params) |
||||
|
|
||||
|
def _inject_line_values(self, only_empty_partner_line=False): |
||||
|
""" Inject report values for report_aged_partner_balance_line. |
||||
|
|
||||
|
The "only_empty_partner_line" value is used |
||||
|
to compute data without partner. |
||||
|
""" |
||||
|
query_inject_line = """ |
||||
|
WITH |
||||
|
date_range AS |
||||
|
( |
||||
|
SELECT |
||||
|
DATE %s AS date_current, |
||||
|
DATE %s - INTEGER '30' AS date_less_30_days, |
||||
|
DATE %s - INTEGER '60' AS date_less_60_days, |
||||
|
DATE %s - INTEGER '90' AS date_less_90_days, |
||||
|
DATE %s - INTEGER '120' AS date_less_120_days |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_aged_partner_balance_line |
||||
|
( |
||||
|
report_partner_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
partner, |
||||
|
amount_residual, |
||||
|
current, |
||||
|
age_30_days, |
||||
|
age_60_days, |
||||
|
age_90_days, |
||||
|
age_120_days, |
||||
|
older |
||||
|
) |
||||
|
SELECT |
||||
|
rp.id AS report_partner_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
rp.name, |
||||
|
SUM(rlo.amount_residual) AS amount_residual, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN rlo.date_due >= date_range.date_current |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS current, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due >= date_range.date_less_30_days |
||||
|
AND rlo.date_due < date_range.date_current |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS age_30_days, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due >= date_range.date_less_60_days |
||||
|
AND rlo.date_due < date_range.date_less_30_days |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS age_60_days, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due >= date_range.date_less_90_days |
||||
|
AND rlo.date_due < date_range.date_less_60_days |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS age_90_days, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due >= date_range.date_less_120_days |
||||
|
AND rlo.date_due < date_range.date_less_90_days |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS age_120_days, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN rlo.date_due < date_range.date_less_120_days |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS older |
||||
|
FROM |
||||
|
date_range, |
||||
|
report_open_items_move_line rlo |
||||
|
INNER JOIN |
||||
|
report_open_items_partner rpo ON rlo.report_partner_id = rpo.id |
||||
|
INNER JOIN |
||||
|
report_open_items_account rao ON rpo.report_account_id = rao.id |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_account ra ON rao.code = ra.code |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_partner rp |
||||
|
ON |
||||
|
ra.id = rp.report_account_id |
||||
|
""" |
||||
|
if not only_empty_partner_line: |
||||
|
query_inject_line += """ |
||||
|
AND rpo.partner_id = rp.partner_id |
||||
|
""" |
||||
|
elif only_empty_partner_line: |
||||
|
query_inject_line += """ |
||||
|
AND rpo.partner_id IS NULL |
||||
|
AND rp.partner_id IS NULL |
||||
|
""" |
||||
|
query_inject_line += """ |
||||
|
WHERE |
||||
|
rao.report_id = %s |
||||
|
AND ra.report_id = %s |
||||
|
GROUP BY |
||||
|
rp.id |
||||
|
""" |
||||
|
query_inject_line_params = (self.date_at,) * 5 |
||||
|
query_inject_line_params += ( |
||||
|
self.env.uid, |
||||
|
self.open_items_id.id, |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_line, query_inject_line_params) |
||||
|
|
||||
|
def _inject_move_line_values(self, only_empty_partner_line=False): |
||||
|
""" Inject report values for report_aged_partner_balance_move_line |
||||
|
|
||||
|
The "only_empty_partner_line" value is used |
||||
|
to compute data without partner. |
||||
|
""" |
||||
|
query_inject_move_line = """ |
||||
|
WITH |
||||
|
date_range AS |
||||
|
( |
||||
|
SELECT |
||||
|
DATE %s AS date_current, |
||||
|
DATE %s - INTEGER '30' AS date_less_30_days, |
||||
|
DATE %s - INTEGER '60' AS date_less_60_days, |
||||
|
DATE %s - INTEGER '90' AS date_less_90_days, |
||||
|
DATE %s - INTEGER '120' AS date_less_120_days |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_aged_partner_balance_move_line |
||||
|
( |
||||
|
report_partner_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
move_line_id, |
||||
|
date, |
||||
|
date_due, |
||||
|
entry, |
||||
|
journal, |
||||
|
account, |
||||
|
partner, |
||||
|
label, |
||||
|
amount_residual, |
||||
|
current, |
||||
|
age_30_days, |
||||
|
age_60_days, |
||||
|
age_90_days, |
||||
|
age_120_days, |
||||
|
older |
||||
|
) |
||||
|
SELECT |
||||
|
rp.id AS report_partner_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
rlo.move_line_id, |
||||
|
rlo.date, |
||||
|
rlo.date_due, |
||||
|
rlo.entry, |
||||
|
rlo.journal, |
||||
|
rlo.account, |
||||
|
rlo.partner, |
||||
|
rlo.label, |
||||
|
rlo.amount_residual AS amount_residual, |
||||
|
CASE |
||||
|
WHEN rlo.date_due >= date_range.date_current |
||||
|
THEN rlo.amount_residual |
||||
|
END AS current, |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due >= date_range.date_less_30_days |
||||
|
AND rlo.date_due < date_range.date_current |
||||
|
THEN rlo.amount_residual |
||||
|
END AS age_30_days, |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due >= date_range.date_less_60_days |
||||
|
AND rlo.date_due < date_range.date_less_30_days |
||||
|
THEN rlo.amount_residual |
||||
|
END AS age_60_days, |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due >= date_range.date_less_90_days |
||||
|
AND rlo.date_due < date_range.date_less_60_days |
||||
|
THEN rlo.amount_residual |
||||
|
END AS age_90_days, |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due >= date_range.date_less_120_days |
||||
|
AND rlo.date_due < date_range.date_less_90_days |
||||
|
THEN rlo.amount_residual |
||||
|
END AS age_120_days, |
||||
|
CASE |
||||
|
WHEN rlo.date_due < date_range.date_less_120_days |
||||
|
THEN rlo.amount_residual |
||||
|
END AS older |
||||
|
FROM |
||||
|
date_range, |
||||
|
report_open_items_move_line rlo |
||||
|
INNER JOIN |
||||
|
report_open_items_partner rpo ON rlo.report_partner_id = rpo.id |
||||
|
INNER JOIN |
||||
|
report_open_items_account rao ON rpo.report_account_id = rao.id |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_account ra ON rao.code = ra.code |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_partner rp |
||||
|
ON |
||||
|
ra.id = rp.report_account_id |
||||
|
""" |
||||
|
if not only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
AND rpo.partner_id = rp.partner_id |
||||
|
""" |
||||
|
elif only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
AND rpo.partner_id IS NULL |
||||
|
AND rp.partner_id IS NULL |
||||
|
""" |
||||
|
query_inject_move_line += """ |
||||
|
WHERE |
||||
|
rao.report_id = %s |
||||
|
AND ra.report_id = %s |
||||
|
""" |
||||
|
query_inject_move_line_params = (self.date_at,) * 5 |
||||
|
query_inject_move_line_params += ( |
||||
|
self.env.uid, |
||||
|
self.open_items_id.id, |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_move_line, |
||||
|
query_inject_move_line_params) |
||||
|
|
||||
|
def _compute_accounts_cumul(self): |
||||
|
""" Compute cumulative amount for |
||||
|
report_aged_partner_balance_account. |
||||
|
""" |
||||
|
query_compute_accounts_cumul = """ |
||||
|
WITH |
||||
|
cumuls AS |
||||
|
( |
||||
|
SELECT |
||||
|
ra.id AS report_account_id, |
||||
|
SUM(rl.amount_residual) AS cumul_amount_residual, |
||||
|
SUM(rl.current) AS cumul_current, |
||||
|
SUM(rl.age_30_days) AS cumul_age_30_days, |
||||
|
SUM(rl.age_60_days) AS cumul_age_60_days, |
||||
|
SUM(rl.age_90_days) AS cumul_age_90_days, |
||||
|
SUM(rl.age_120_days) AS cumul_age_120_days, |
||||
|
SUM(rl.older) AS cumul_older |
||||
|
FROM |
||||
|
report_aged_partner_balance_line rl |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_partner rp |
||||
|
ON rl.report_partner_id = rp.id |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_account ra |
||||
|
ON rp.report_account_id = ra.id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
GROUP BY |
||||
|
ra.id |
||||
|
) |
||||
|
UPDATE |
||||
|
report_aged_partner_balance_account |
||||
|
SET |
||||
|
cumul_amount_residual = c.cumul_amount_residual, |
||||
|
cumul_current = c.cumul_current, |
||||
|
cumul_age_30_days = c.cumul_age_30_days, |
||||
|
cumul_age_60_days = c.cumul_age_60_days, |
||||
|
cumul_age_90_days = c.cumul_age_90_days, |
||||
|
cumul_age_120_days = c.cumul_age_120_days, |
||||
|
cumul_older = c.cumul_older, |
||||
|
percent_current = |
||||
|
CASE |
||||
|
WHEN c.cumul_amount_residual != 0 |
||||
|
THEN 100 * c.cumul_current / c.cumul_amount_residual |
||||
|
END, |
||||
|
percent_age_30_days = |
||||
|
CASE |
||||
|
WHEN c.cumul_amount_residual != 0 |
||||
|
THEN 100 * c.cumul_age_30_days / c.cumul_amount_residual |
||||
|
END, |
||||
|
percent_age_60_days = |
||||
|
CASE |
||||
|
WHEN c.cumul_amount_residual != 0 |
||||
|
THEN 100 * c.cumul_age_60_days / c.cumul_amount_residual |
||||
|
END, |
||||
|
percent_age_90_days = |
||||
|
CASE |
||||
|
WHEN c.cumul_amount_residual != 0 |
||||
|
THEN 100 * c.cumul_age_90_days / c.cumul_amount_residual |
||||
|
END, |
||||
|
percent_age_120_days = |
||||
|
CASE |
||||
|
WHEN c.cumul_amount_residual != 0 |
||||
|
THEN 100 * c.cumul_age_120_days / c.cumul_amount_residual |
||||
|
END, |
||||
|
percent_older = |
||||
|
CASE |
||||
|
WHEN c.cumul_amount_residual != 0 |
||||
|
THEN 100 * c.cumul_older / c.cumul_amount_residual |
||||
|
END |
||||
|
FROM |
||||
|
cumuls c |
||||
|
WHERE |
||||
|
id = c.report_account_id |
||||
|
""" |
||||
|
params_compute_accounts_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_accounts_cumul, |
||||
|
params_compute_accounts_cumul) |
@ -0,0 +1,257 @@ |
|||||
|
|
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# 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' |
||||
|
_inherit = 'report.account_financial_report.abstract_report_xlsx' |
||||
|
|
||||
|
def _get_report_name(self, report): |
||||
|
report_name = _('Aged Partner Balance') |
||||
|
return self._get_report_complete_name(report, report_name) |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
if not report.show_move_line_details: |
||||
|
return { |
||||
|
0: {'header': _('Partner'), 'field': 'partner', 'width': 70}, |
||||
|
1: {'header': _('Residual'), |
||||
|
'field': 'amount_residual', |
||||
|
'field_footer_total': 'cumul_amount_residual', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
2: {'header': _('Current'), |
||||
|
'field': 'current', |
||||
|
'field_footer_total': 'cumul_current', |
||||
|
'field_footer_percent': 'percent_current', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
3: {'header': _(u'Age ≤ 30 d.'), |
||||
|
'field': 'age_30_days', |
||||
|
'field_footer_total': 'cumul_age_30_days', |
||||
|
'field_footer_percent': 'percent_age_30_days', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
4: {'header': _(u'Age ≤ 60 d.'), |
||||
|
'field': 'age_60_days', |
||||
|
'field_footer_total': 'cumul_age_60_days', |
||||
|
'field_footer_percent': 'percent_age_60_days', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
5: {'header': _(u'Age ≤ 90 d.'), |
||||
|
'field': 'age_90_days', |
||||
|
'field_footer_total': 'cumul_age_90_days', |
||||
|
'field_footer_percent': 'percent_age_90_days', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
6: {'header': _(u'Age ≤ 120 d.'), |
||||
|
'field': 'age_120_days', |
||||
|
'field_footer_total': 'cumul_age_120_days', |
||||
|
'field_footer_percent': 'percent_age_120_days', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
7: {'header': _('Older'), |
||||
|
'field': 'older', |
||||
|
'field_footer_total': 'cumul_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': 'label', 'width': 40}, |
||||
|
6: {'header': _('Due date'), 'field': 'date_due', 'width': 11}, |
||||
|
7: {'header': _('Residual'), |
||||
|
'field': 'amount_residual', |
||||
|
'field_footer_total': 'cumul_amount_residual', |
||||
|
'field_final_balance': 'amount_residual', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
8: {'header': _('Current'), |
||||
|
'field': 'current', |
||||
|
'field_footer_total': 'cumul_current', |
||||
|
'field_footer_percent': 'percent_current', |
||||
|
'field_final_balance': 'current', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
9: {'header': _(u'Age ≤ 30 d.'), |
||||
|
'field': 'age_30_days', |
||||
|
'field_footer_total': 'cumul_age_30_days', |
||||
|
'field_footer_percent': 'percent_age_30_days', |
||||
|
'field_final_balance': 'age_30_days', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
10: {'header': _(u'Age ≤ 60 d.'), |
||||
|
'field': 'age_60_days', |
||||
|
'field_footer_total': 'cumul_age_60_days', |
||||
|
'field_footer_percent': 'percent_age_60_days', |
||||
|
'field_final_balance': 'age_60_days', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
11: {'header': _(u'Age ≤ 90 d.'), |
||||
|
'field': 'age_90_days', |
||||
|
'field_footer_total': 'cumul_age_90_days', |
||||
|
'field_footer_percent': 'percent_age_90_days', |
||||
|
'field_final_balance': 'age_90_days', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
12: {'header': _(u'Age ≤ 120 d.'), |
||||
|
'field': 'age_120_days', |
||||
|
'field_footer_total': 'cumul_age_120_days', |
||||
|
'field_footer_percent': 'percent_age_120_days', |
||||
|
'field_final_balance': 'age_120_days', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
13: {'header': _('Older'), |
||||
|
'field': 'older', |
||||
|
'field_footer_total': 'cumul_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], |
||||
|
[_('Target moves filter'), |
||||
|
_('All posted entries') if report.only_posted_moves 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): |
||||
|
if not report.show_move_line_details: |
||||
|
# For each account |
||||
|
for account in report.account_ids: |
||||
|
# Write account title |
||||
|
self.write_array_title(account.code + ' - ' + account.name) |
||||
|
|
||||
|
# Display array header for partners lines |
||||
|
self.write_array_header() |
||||
|
|
||||
|
# Display partner lines |
||||
|
for partner in account.partner_ids: |
||||
|
self.write_line(partner.line_ids) |
||||
|
|
||||
|
# Display account lines |
||||
|
self.write_account_footer(report, |
||||
|
account, |
||||
|
_('Total'), |
||||
|
'field_footer_total', |
||||
|
self.format_header_right, |
||||
|
self.format_header_amount, |
||||
|
False) |
||||
|
self.write_account_footer(report, |
||||
|
account, |
||||
|
_('Percents'), |
||||
|
'field_footer_percent', |
||||
|
self.format_right_bold_italic, |
||||
|
self.format_percent_bold_italic, |
||||
|
True) |
||||
|
|
||||
|
# 2 lines break |
||||
|
self.row_pos += 2 |
||||
|
else: |
||||
|
# For each account |
||||
|
for account in report.account_ids: |
||||
|
# Write account title |
||||
|
self.write_array_title(account.code + ' - ' + account.name) |
||||
|
|
||||
|
# For each partner |
||||
|
for partner in account.partner_ids: |
||||
|
# Write partner title |
||||
|
self.write_array_title(partner.name) |
||||
|
|
||||
|
# Display array header for move lines |
||||
|
self.write_array_header() |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in partner.move_line_ids: |
||||
|
self.write_line(line) |
||||
|
|
||||
|
# Display ending balance line for partner |
||||
|
self.write_ending_balance(partner.line_ids) |
||||
|
|
||||
|
# Line break |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
# Display account lines |
||||
|
self.write_account_footer(report, |
||||
|
account, |
||||
|
_('Total'), |
||||
|
'field_footer_total', |
||||
|
self.format_header_right, |
||||
|
self.format_header_amount, |
||||
|
False) |
||||
|
self.write_account_footer(report, |
||||
|
account, |
||||
|
_('Percents'), |
||||
|
'field_footer_percent', |
||||
|
self.format_right_bold_italic, |
||||
|
self.format_percent_bold_italic, |
||||
|
True) |
||||
|
|
||||
|
# 2 lines break |
||||
|
self.row_pos += 2 |
||||
|
|
||||
|
def write_ending_balance(self, my_object): |
||||
|
""" |
||||
|
Specific function to write ending partner balance |
||||
|
for Aged Partner Balance |
||||
|
""" |
||||
|
name = None |
||||
|
label = _('Partner cumul aged balance') |
||||
|
super(AgedPartnerBalanceXslx, self).write_ending_balance( |
||||
|
my_object, name, label |
||||
|
) |
||||
|
|
||||
|
def write_account_footer(self, report, account, label, field_name, |
||||
|
string_format, amount_format, amount_is_percent): |
||||
|
""" |
||||
|
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 self.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 = getattr(account, column[field_name]) |
||||
|
cell_type = column.get('type', 'string') |
||||
|
if cell_type == 'string' or col_pos == col_pos_footer_label: |
||||
|
self.sheet.write_string(self.row_pos, col_pos, value or '', |
||||
|
string_format) |
||||
|
elif cell_type == 'amount': |
||||
|
number = float(value) |
||||
|
if amount_is_percent: |
||||
|
number /= 100 |
||||
|
self.sheet.write_number(self.row_pos, col_pos, |
||||
|
number, |
||||
|
amount_format) |
||||
|
else: |
||||
|
self.sheet.write_string(self.row_pos, col_pos, '', |
||||
|
string_format) |
||||
|
|
||||
|
self.row_pos += 1 |
1765
account_financial_report/report/general_ledger.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,183 @@ |
|||||
|
|
||||
|
# 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 _, models |
||||
|
|
||||
|
|
||||
|
class GeneralLedgerXslx(models.AbstractModel): |
||||
|
_name = 'report.a_f_r.report_general_ledger_xlsx' |
||||
|
_inherit = 'report.account_financial_report.abstract_report_xlsx' |
||||
|
|
||||
|
def _get_report_name(self, report): |
||||
|
report_name = _('General Ledger') |
||||
|
return self._get_report_complete_name(report, report_name) |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
res = { |
||||
|
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': _('Taxes'), |
||||
|
'field': 'taxes_description', |
||||
|
'width': 15}, |
||||
|
5: {'header': _('Partner'), 'field': 'partner', 'width': 25}, |
||||
|
6: {'header': _('Ref - Label'), 'field': 'label', 'width': 40}, |
||||
|
7: {'header': _('Cost center'), |
||||
|
'field': 'cost_center', |
||||
|
'width': 15}, |
||||
|
8: {'header': _('Tags'), |
||||
|
'field': 'tags', |
||||
|
'width': 10}, |
||||
|
9: {'header': _('Rec.'), 'field': 'matching_number', 'width': 5}, |
||||
|
10: {'header': _('Debit'), |
||||
|
'field': 'debit', |
||||
|
'field_initial_balance': 'initial_debit', |
||||
|
'field_final_balance': 'final_debit', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
11: {'header': _('Credit'), |
||||
|
'field': 'credit', |
||||
|
'field_initial_balance': 'initial_credit', |
||||
|
'field_final_balance': 'final_credit', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
12: {'header': _('Cumul. Bal.'), |
||||
|
'field': 'cumul_balance', |
||||
|
'field_initial_balance': 'initial_balance', |
||||
|
'field_final_balance': 'final_balance', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
} |
||||
|
if report.foreign_currency: |
||||
|
foreign_currency = { |
||||
|
13: {'header': _('Cur.'), |
||||
|
'field': 'currency_id', |
||||
|
'field_currency_balance': 'currency_id', |
||||
|
'type': 'many2one', 'width': 7}, |
||||
|
14: {'header': _('Amount cur.'), |
||||
|
'field': 'amount_currency', |
||||
|
'field_initial_balance': |
||||
|
'initial_balance_foreign_currency', |
||||
|
'field_final_balance': |
||||
|
'final_balance_foreign_currency', |
||||
|
'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.only_posted_moves |
||||
|
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 |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report): |
||||
|
# For each account |
||||
|
for account in report.account_ids: |
||||
|
# Write account title |
||||
|
self.write_array_title(account.code + ' - ' + account.name) |
||||
|
|
||||
|
if not account.partner_ids: |
||||
|
# Display array header for move lines |
||||
|
self.write_array_header() |
||||
|
|
||||
|
# Display initial balance line for account |
||||
|
self.write_initial_balance(account) |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in account.move_line_ids: |
||||
|
self.write_line(line) |
||||
|
|
||||
|
else: |
||||
|
# For each partner |
||||
|
for partner in account.partner_ids: |
||||
|
# Write partner title |
||||
|
self.write_array_title(partner.name) |
||||
|
|
||||
|
# Display array header for move lines |
||||
|
self.write_array_header() |
||||
|
|
||||
|
# Display initial balance line for partner |
||||
|
self.write_initial_balance(partner) |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in partner.move_line_ids: |
||||
|
self.write_line(line) |
||||
|
|
||||
|
# Display ending balance line for partner |
||||
|
self.write_ending_balance(partner) |
||||
|
|
||||
|
# Line break |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
# Display ending balance line for account |
||||
|
self.write_ending_balance(account) |
||||
|
|
||||
|
# 2 lines break |
||||
|
self.row_pos += 2 |
||||
|
|
||||
|
def write_initial_balance(self, my_object): |
||||
|
"""Specific function to write initial balance for General Ledger""" |
||||
|
if 'partner' in my_object._name: |
||||
|
label = _('Partner Initial balance') |
||||
|
my_object.currency_id = my_object.report_account_id.currency_id |
||||
|
elif 'account' in my_object._name: |
||||
|
label = _('Initial balance') |
||||
|
super(GeneralLedgerXslx, self).write_initial_balance( |
||||
|
my_object, label |
||||
|
) |
||||
|
|
||||
|
def write_ending_balance(self, my_object): |
||||
|
"""Specific function to write ending balance for General Ledger""" |
||||
|
if 'partner' in my_object._name: |
||||
|
name = my_object.name |
||||
|
label = _('Partner ending balance') |
||||
|
elif 'account' in my_object._name: |
||||
|
name = my_object.code + ' - ' + my_object.name |
||||
|
label = _('Ending balance') |
||||
|
super(GeneralLedgerXslx, self).write_ending_balance( |
||||
|
my_object, name, label |
||||
|
) |
@ -0,0 +1,818 @@ |
|||||
|
# Copyright 2017 ACSONE SA/NV |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from odoo import models, fields, api |
||||
|
|
||||
|
DIGITS = (16, 2) |
||||
|
|
||||
|
|
||||
|
class ReportJournalLedger(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_journal_ledger' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
date_from = fields.Date( |
||||
|
required=True |
||||
|
) |
||||
|
date_to = fields.Date( |
||||
|
required=True |
||||
|
) |
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
required=True, |
||||
|
ondelete='cascade' |
||||
|
) |
||||
|
move_target = fields.Selection( |
||||
|
selection='_get_move_targets', |
||||
|
default='all', |
||||
|
required=True, |
||||
|
) |
||||
|
sort_option = fields.Selection( |
||||
|
selection='_get_sort_options', |
||||
|
default='move_name', |
||||
|
required=True, |
||||
|
) |
||||
|
group_option = fields.Selection( |
||||
|
selection='_get_group_options', |
||||
|
default='journal', |
||||
|
required=True, |
||||
|
) |
||||
|
journal_ids = fields.Many2many( |
||||
|
comodel_name='account.journal', |
||||
|
required=True, |
||||
|
) |
||||
|
report_journal_ledger_ids = fields.One2many( |
||||
|
comodel_name='report_journal_ledger_journal', |
||||
|
inverse_name='report_id', |
||||
|
) |
||||
|
report_move_ids = fields.One2many( |
||||
|
comodel_name='report_journal_ledger_move', |
||||
|
inverse_name='report_id', |
||||
|
) |
||||
|
report_move_line_ids = fields.One2many( |
||||
|
comodel_name='report_journal_ledger_move_line', |
||||
|
inverse_name='report_id', |
||||
|
) |
||||
|
report_journal_ledger_tax_line_ids = fields.One2many( |
||||
|
comodel_name='report_journal_ledger_journal_tax_line', |
||||
|
inverse_name='report_id', |
||||
|
) |
||||
|
report_tax_line_ids = fields.One2many( |
||||
|
comodel_name='report_journal_ledger_report_tax_line', |
||||
|
inverse_name='report_id', |
||||
|
) |
||||
|
foreign_currency = fields.Boolean() |
||||
|
with_account_name = fields.Boolean() |
||||
|
|
||||
|
@api.model |
||||
|
def _get_move_targets(self): |
||||
|
return self.env['journal.ledger.report.wizard']._get_move_targets() |
||||
|
|
||||
|
@api.model |
||||
|
def _get_sort_options(self): |
||||
|
return self.env['journal.ledger.report.wizard']._get_sort_options() |
||||
|
|
||||
|
@api.model |
||||
|
def _get_group_options(self): |
||||
|
return self.env['journal.ledger.report.wizard']._get_group_options() |
||||
|
|
||||
|
@api.multi |
||||
|
def compute_data_for_report(self): |
||||
|
self.ensure_one() |
||||
|
self._inject_journal_values() |
||||
|
self._inject_move_values() |
||||
|
self._inject_move_line_values() |
||||
|
self._inject_journal_tax_values() |
||||
|
self._update_journal_report_total_values() |
||||
|
|
||||
|
if self.group_option == 'none': |
||||
|
self._inject_report_tax_values() |
||||
|
|
||||
|
# Refresh cache because all data are computed with SQL requests |
||||
|
self.invalidate_cache() |
||||
|
|
||||
|
@api.multi |
||||
|
def _inject_journal_values(self): |
||||
|
self.ensure_one() |
||||
|
sql = """ |
||||
|
DELETE |
||||
|
FROM report_journal_ledger_journal |
||||
|
WHERE report_id = %s |
||||
|
""" |
||||
|
params = ( |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(sql, params) |
||||
|
sql = """ |
||||
|
INSERT INTO report_journal_ledger_journal ( |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
report_id, |
||||
|
journal_id, |
||||
|
name, |
||||
|
code, |
||||
|
company_id, |
||||
|
currency_id |
||||
|
) |
||||
|
SELECT |
||||
|
%s as create_uid, |
||||
|
NOW() as create_date, |
||||
|
%s as report_id, |
||||
|
aj.id as journal_id, |
||||
|
aj.name as name, |
||||
|
aj.code as code, |
||||
|
aj.company_id as company_id, |
||||
|
COALESCE(aj.currency_id, company.currency_id) as currency_id |
||||
|
FROM |
||||
|
account_journal aj |
||||
|
LEFT JOIN |
||||
|
res_company company on (company.id = aj.company_id) |
||||
|
WHERE |
||||
|
aj.id in %s |
||||
|
AND |
||||
|
aj.company_id = %s |
||||
|
ORDER BY |
||||
|
aj.name |
||||
|
""" |
||||
|
params = ( |
||||
|
self.env.uid, |
||||
|
self.id, |
||||
|
tuple(self.journal_ids.ids), |
||||
|
self.company_id.id, |
||||
|
) |
||||
|
self.env.cr.execute(sql, params) |
||||
|
|
||||
|
@api.multi |
||||
|
def _inject_move_values(self): |
||||
|
self.ensure_one() |
||||
|
sql = """ |
||||
|
DELETE |
||||
|
FROM report_journal_ledger_move |
||||
|
WHERE report_id = %s |
||||
|
""" |
||||
|
params = ( |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(sql, params) |
||||
|
sql = self._get_inject_move_insert() |
||||
|
sql += self._get_inject_move_select() |
||||
|
sql += self._get_inject_move_where_clause() |
||||
|
sql += self._get_inject_move_order_by() |
||||
|
params = self._get_inject_move_params() |
||||
|
self.env.cr.execute(sql, params) |
||||
|
|
||||
|
@api.multi |
||||
|
def _get_inject_move_insert(self): |
||||
|
return """ |
||||
|
INSERT INTO report_journal_ledger_move ( |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
report_id, |
||||
|
report_journal_ledger_id, |
||||
|
move_id, |
||||
|
name, |
||||
|
company_id |
||||
|
) |
||||
|
""" |
||||
|
|
||||
|
@api.multi |
||||
|
def _get_inject_move_select(self): |
||||
|
return """ |
||||
|
SELECT |
||||
|
%s as create_uid, |
||||
|
NOW() as create_date, |
||||
|
rjqj.report_id as report_id, |
||||
|
rjqj.id as report_journal_ledger_id, |
||||
|
am.id as move_id, |
||||
|
am.name as name, |
||||
|
am.company_id as company_id |
||||
|
FROM |
||||
|
account_move am |
||||
|
INNER JOIN |
||||
|
report_journal_ledger_journal rjqj |
||||
|
on (rjqj.journal_id = am.journal_id) |
||||
|
""" |
||||
|
|
||||
|
@api.multi |
||||
|
def _get_inject_move_where_clause(self): |
||||
|
self.ensure_one() |
||||
|
where_clause = """ |
||||
|
WHERE |
||||
|
rjqj.report_id = %s |
||||
|
AND |
||||
|
am.date >= %s |
||||
|
AND |
||||
|
am.date <= %s |
||||
|
""" |
||||
|
if self.move_target != 'all': |
||||
|
where_clause += """ |
||||
|
AND |
||||
|
am.state = %s |
||||
|
""" |
||||
|
return where_clause |
||||
|
|
||||
|
@api.multi |
||||
|
def _get_inject_move_order_by(self): |
||||
|
self.ensure_one() |
||||
|
order_by = """ |
||||
|
ORDER BY |
||||
|
""" |
||||
|
if self.sort_option == 'move_name': |
||||
|
order_by += " am.name" |
||||
|
elif self.sort_option == 'date': |
||||
|
order_by += " am.date, am.name" |
||||
|
return order_by |
||||
|
|
||||
|
@api.multi |
||||
|
def _get_inject_move_params(self): |
||||
|
params = [ |
||||
|
self.env.uid, |
||||
|
self.id, |
||||
|
self.date_from, |
||||
|
self.date_to |
||||
|
] |
||||
|
|
||||
|
if self.move_target != 'all': |
||||
|
params.append(self.move_target) |
||||
|
|
||||
|
return tuple(params) |
||||
|
|
||||
|
@api.multi |
||||
|
def _inject_move_line_values(self): |
||||
|
self.ensure_one() |
||||
|
sql = """ |
||||
|
DELETE |
||||
|
FROM report_journal_ledger_move_line |
||||
|
WHERE report_id = %s |
||||
|
""" |
||||
|
params = ( |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(sql, params) |
||||
|
sql = """ |
||||
|
INSERT INTO report_journal_ledger_move_line ( |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
report_id, |
||||
|
report_journal_ledger_id, |
||||
|
report_move_id, |
||||
|
move_line_id, |
||||
|
account_id, |
||||
|
account, |
||||
|
account_code, |
||||
|
account_type, |
||||
|
partner_id, |
||||
|
partner, |
||||
|
date, |
||||
|
entry, |
||||
|
label, |
||||
|
debit, |
||||
|
credit, |
||||
|
company_currency_id, |
||||
|
amount_currency, |
||||
|
currency_id, |
||||
|
currency_name, |
||||
|
tax_id, |
||||
|
taxes_description, |
||||
|
company_id |
||||
|
) |
||||
|
SELECT |
||||
|
%s as create_uid, |
||||
|
NOW() as create_date, |
||||
|
rjqm.report_id as report_id, |
||||
|
rjqm.report_journal_ledger_id as report_journal_ledger_id, |
||||
|
rjqm.id as report_move_id, |
||||
|
aml.id as move_line_id, |
||||
|
aml.account_id as account_id, |
||||
|
aa.name as account, |
||||
|
aa.code as account_code, |
||||
|
aa.internal_type as account_type, |
||||
|
aml.partner_id as partner_id, |
||||
|
p.name as partner, |
||||
|
aml.date as date, |
||||
|
rjqm.name as entry, |
||||
|
aml.name as label, |
||||
|
aml.debit as debit, |
||||
|
aml.credit as credit, |
||||
|
aml.company_currency_id as currency_id, |
||||
|
aml.amount_currency as amount_currency, |
||||
|
aml.currency_id as currency_id, |
||||
|
currency.name as currency_name, |
||||
|
aml.tax_line_id as tax_id, |
||||
|
CASE |
||||
|
WHEN |
||||
|
aml.tax_line_id is not null |
||||
|
THEN |
||||
|
COALESCE(at.description, at.name) |
||||
|
WHEN |
||||
|
aml.tax_line_id is null |
||||
|
THEN |
||||
|
(SELECT |
||||
|
array_to_string( |
||||
|
array_agg(COALESCE(at.description, at.name) |
||||
|
), ', ') |
||||
|
FROM |
||||
|
account_move_line_account_tax_rel aml_at_rel |
||||
|
LEFT JOIN |
||||
|
account_tax at on (at.id = aml_at_rel.account_tax_id) |
||||
|
WHERE |
||||
|
aml_at_rel.account_move_line_id = aml.id) |
||||
|
ELSE |
||||
|
'' |
||||
|
END as taxes_description, |
||||
|
aml.company_id as company_id |
||||
|
FROM |
||||
|
account_move_line aml |
||||
|
INNER JOIN |
||||
|
report_journal_ledger_move rjqm |
||||
|
on (rjqm.move_id = aml.move_id) |
||||
|
LEFT JOIN |
||||
|
account_account aa |
||||
|
on (aa.id = aml.account_id) |
||||
|
LEFT JOIN |
||||
|
res_partner p |
||||
|
on (p.id = aml.partner_id) |
||||
|
LEFT JOIN |
||||
|
account_tax at |
||||
|
on (at.id = aml.tax_line_id) |
||||
|
LEFT JOIN |
||||
|
res_currency currency |
||||
|
on (currency.id = aml.currency_id) |
||||
|
WHERE |
||||
|
rjqm.report_id = %s |
||||
|
""" |
||||
|
params = ( |
||||
|
self.env.uid, |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(sql, params) |
||||
|
|
||||
|
@api.multi |
||||
|
def _inject_report_tax_values(self): |
||||
|
self.ensure_one() |
||||
|
sql_distinct_tax_id = """ |
||||
|
SELECT |
||||
|
distinct(jrqjtl.tax_id) |
||||
|
FROM |
||||
|
report_journal_ledger_journal_tax_line jrqjtl |
||||
|
WHERE |
||||
|
jrqjtl.report_id = %s |
||||
|
""" |
||||
|
self.env.cr.execute(sql_distinct_tax_id, (self.id,)) |
||||
|
rows = self.env.cr.fetchall() |
||||
|
tax_ids = set([row[0] for row in rows]) |
||||
|
|
||||
|
sql = """ |
||||
|
INSERT INTO report_journal_ledger_report_tax_line ( |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
report_id, |
||||
|
tax_id, |
||||
|
tax_name, |
||||
|
tax_code, |
||||
|
base_debit, |
||||
|
base_credit, |
||||
|
tax_debit, |
||||
|
tax_credit |
||||
|
) |
||||
|
SELECT |
||||
|
%s as create_uid, |
||||
|
NOW() as create_date, |
||||
|
%s as report_id, |
||||
|
%s as tax_id, |
||||
|
at.name as tax_name, |
||||
|
at.description as tax_code, |
||||
|
( |
||||
|
SELECT sum(base_debit) |
||||
|
FROM report_journal_ledger_journal_tax_line jrqjtl2 |
||||
|
WHERE jrqjtl2.report_id = %s |
||||
|
AND jrqjtl2.tax_id = %s |
||||
|
) as base_debit, |
||||
|
( |
||||
|
SELECT sum(base_credit) |
||||
|
FROM report_journal_ledger_journal_tax_line jrqjtl2 |
||||
|
WHERE jrqjtl2.report_id = %s |
||||
|
AND jrqjtl2.tax_id = %s |
||||
|
) as base_credit, |
||||
|
( |
||||
|
SELECT sum(tax_debit) |
||||
|
FROM report_journal_ledger_journal_tax_line jrqjtl2 |
||||
|
WHERE jrqjtl2.report_id = %s |
||||
|
AND jrqjtl2.tax_id = %s |
||||
|
) as tax_debit, |
||||
|
( |
||||
|
SELECT sum(tax_credit) |
||||
|
FROM report_journal_ledger_journal_tax_line jrqjtl2 |
||||
|
WHERE jrqjtl2.report_id = %s |
||||
|
AND jrqjtl2.tax_id = %s |
||||
|
) as tax_credit |
||||
|
FROM |
||||
|
report_journal_ledger_journal_tax_line jrqjtl |
||||
|
LEFT JOIN |
||||
|
account_tax at |
||||
|
on (at.id = jrqjtl.tax_id) |
||||
|
WHERE |
||||
|
jrqjtl.report_id = %s |
||||
|
AND |
||||
|
jrqjtl.tax_id = %s |
||||
|
""" |
||||
|
|
||||
|
for tax_id in tax_ids: |
||||
|
params = ( |
||||
|
self.env.uid, |
||||
|
self.id, |
||||
|
tax_id, |
||||
|
self.id, |
||||
|
tax_id, |
||||
|
self.id, |
||||
|
tax_id, |
||||
|
self.id, |
||||
|
tax_id, |
||||
|
self.id, |
||||
|
tax_id, |
||||
|
self.id, |
||||
|
tax_id, |
||||
|
) |
||||
|
self.env.cr.execute(sql, params) |
||||
|
|
||||
|
@api.multi |
||||
|
def _inject_journal_tax_values(self): |
||||
|
self.ensure_one() |
||||
|
sql = """ |
||||
|
DELETE |
||||
|
FROM report_journal_ledger_journal_tax_line |
||||
|
WHERE report_id = %s |
||||
|
""" |
||||
|
params = ( |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(sql, params) |
||||
|
sql_distinct_tax_id = """ |
||||
|
SELECT |
||||
|
distinct(jrqml.tax_id) |
||||
|
FROM |
||||
|
report_journal_ledger_move_line jrqml |
||||
|
WHERE |
||||
|
jrqml.report_journal_ledger_id = %s |
||||
|
""" |
||||
|
|
||||
|
tax_ids_by_journal_id = {} |
||||
|
for report_journal in self.report_journal_ledger_ids: |
||||
|
if report_journal.id not in tax_ids_by_journal_id: |
||||
|
tax_ids_by_journal_id[report_journal.id] = [] |
||||
|
self.env.cr.execute(sql_distinct_tax_id, (report_journal.id,)) |
||||
|
rows = self.env.cr.fetchall() |
||||
|
tax_ids_by_journal_id[report_journal.id].extend([ |
||||
|
row[0] for row in rows if row[0] |
||||
|
]) |
||||
|
|
||||
|
sql = """ |
||||
|
INSERT INTO report_journal_ledger_journal_tax_line ( |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
report_id, |
||||
|
report_journal_ledger_id, |
||||
|
tax_id, |
||||
|
tax_name, |
||||
|
tax_code, |
||||
|
base_debit, |
||||
|
base_credit, |
||||
|
tax_debit, |
||||
|
tax_credit |
||||
|
) |
||||
|
SELECT |
||||
|
%s as create_uid, |
||||
|
NOW() as create_date, |
||||
|
%s as report_id, |
||||
|
%s as report_journal_ledger_id, |
||||
|
%s as tax_id, |
||||
|
at.name as tax_name, |
||||
|
at.description as tax_code, |
||||
|
( |
||||
|
SELECT sum(debit) |
||||
|
FROM report_journal_ledger_move_line jrqml2 |
||||
|
WHERE jrqml2.report_journal_ledger_id = %s |
||||
|
AND ( |
||||
|
SELECT |
||||
|
count(*) |
||||
|
FROM |
||||
|
account_move_line_account_tax_rel aml_at_rel |
||||
|
WHERE |
||||
|
aml_at_rel.account_move_line_id = |
||||
|
jrqml2.move_line_id |
||||
|
AND |
||||
|
aml_at_rel.account_tax_id = %s |
||||
|
) > 0 |
||||
|
) as base_debit, |
||||
|
( |
||||
|
SELECT sum(credit) |
||||
|
FROM report_journal_ledger_move_line jrqml2 |
||||
|
WHERE jrqml2.report_journal_ledger_id = %s |
||||
|
AND ( |
||||
|
SELECT |
||||
|
count(*) |
||||
|
FROM |
||||
|
account_move_line_account_tax_rel aml_at_rel |
||||
|
WHERE |
||||
|
aml_at_rel.account_move_line_id = |
||||
|
jrqml2.move_line_id |
||||
|
AND |
||||
|
aml_at_rel.account_tax_id = %s |
||||
|
) > 0 |
||||
|
) as base_credit, |
||||
|
( |
||||
|
SELECT sum(debit) |
||||
|
FROM report_journal_ledger_move_line jrqml2 |
||||
|
WHERE jrqml2.report_journal_ledger_id = %s |
||||
|
AND jrqml2.tax_id = %s |
||||
|
) as tax_debit, |
||||
|
( |
||||
|
SELECT sum(credit) |
||||
|
FROM report_journal_ledger_move_line jrqml2 |
||||
|
WHERE jrqml2.report_journal_ledger_id = %s |
||||
|
AND jrqml2.tax_id = %s |
||||
|
) as tax_credit |
||||
|
FROM |
||||
|
report_journal_ledger_journal rjqj |
||||
|
LEFT JOIN |
||||
|
account_tax at |
||||
|
on (at.id = %s) |
||||
|
WHERE |
||||
|
rjqj.id = %s |
||||
|
""" |
||||
|
|
||||
|
for report_journal_ledger_id in tax_ids_by_journal_id: |
||||
|
tax_ids = tax_ids_by_journal_id[report_journal_ledger_id] |
||||
|
for tax_id in tax_ids: |
||||
|
params = ( |
||||
|
self.env.uid, |
||||
|
self.id, |
||||
|
report_journal_ledger_id, |
||||
|
tax_id, |
||||
|
report_journal_ledger_id, |
||||
|
tax_id, |
||||
|
report_journal_ledger_id, |
||||
|
tax_id, |
||||
|
report_journal_ledger_id, |
||||
|
tax_id, |
||||
|
report_journal_ledger_id, |
||||
|
tax_id, |
||||
|
tax_id, |
||||
|
report_journal_ledger_id, |
||||
|
) |
||||
|
self.env.cr.execute(sql, params) |
||||
|
|
||||
|
@api.multi |
||||
|
def _update_journal_report_total_values(self): |
||||
|
self.ensure_one() |
||||
|
sql = """ |
||||
|
UPDATE |
||||
|
report_journal_ledger_journal rjqj |
||||
|
SET |
||||
|
debit = ( |
||||
|
SELECT sum(rjqml.debit) |
||||
|
FROM report_journal_ledger_move_line rjqml |
||||
|
WHERE rjqml.report_journal_ledger_id = rjqj.id |
||||
|
), |
||||
|
credit = ( |
||||
|
SELECT sum(rjqml.credit) |
||||
|
FROM report_journal_ledger_move_line rjqml |
||||
|
WHERE rjqml.report_journal_ledger_id = rjqj.id |
||||
|
) |
||||
|
WHERE |
||||
|
rjqj.report_id = %s |
||||
|
""" |
||||
|
self.env.cr.execute(sql, (self.id,)) |
||||
|
|
||||
|
@api.multi |
||||
|
def print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
if report_type == 'xlsx': |
||||
|
report_name = 'a_f_r.report_journal_ledger_xlsx' |
||||
|
else: |
||||
|
report_name = 'account_financial_report.' \ |
||||
|
'report_journal_ledger_qweb' |
||||
|
return self.env['ir.actions.report'].search( |
||||
|
[('report_name', '=', report_name), |
||||
|
('report_type', '=', report_type)], |
||||
|
limit=1).report_action(self, config=False) |
||||
|
|
||||
|
def _get_html(self): |
||||
|
result = {} |
||||
|
rcontext = {} |
||||
|
context = dict(self.env.context) |
||||
|
report = self.browse(context.get('active_id')) |
||||
|
if report: |
||||
|
rcontext['o'] = report |
||||
|
result['html'] = self.env.ref( |
||||
|
'account_financial_report.report_journal_ledger').render( |
||||
|
rcontext) |
||||
|
return result |
||||
|
|
||||
|
@api.model |
||||
|
def get_html(self, given_context=None): |
||||
|
return self._get_html() |
||||
|
|
||||
|
|
||||
|
class ReportJournalLedgerJournal(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_journal_ledger_journal' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
name = fields.Char( |
||||
|
required=True, |
||||
|
) |
||||
|
code = fields.Char() |
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_journal_ledger', |
||||
|
required=True, |
||||
|
ondelete='cascade' |
||||
|
) |
||||
|
journal_id = fields.Many2one( |
||||
|
comodel_name='account.journal', |
||||
|
required=True, |
||||
|
ondelete='cascade', |
||||
|
) |
||||
|
report_move_ids = fields.One2many( |
||||
|
comodel_name='report_journal_ledger_move', |
||||
|
inverse_name='report_journal_ledger_id', |
||||
|
) |
||||
|
report_tax_line_ids = fields.One2many( |
||||
|
comodel_name='report_journal_ledger_journal_tax_line', |
||||
|
inverse_name='report_journal_ledger_id', |
||||
|
) |
||||
|
debit = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
) |
||||
|
credit = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
) |
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
required=True, |
||||
|
ondelete='cascade' |
||||
|
) |
||||
|
currency_id = fields.Many2one( |
||||
|
comodel_name='res.currency', |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class ReportJournalLedgerMove(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_journal_ledger_move' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_journal_ledger', |
||||
|
required=True, |
||||
|
ondelete='cascade' |
||||
|
) |
||||
|
report_journal_ledger_id = fields.Many2one( |
||||
|
comodel_name='report_journal_ledger_journal', |
||||
|
required=True, |
||||
|
ondelete='cascade', |
||||
|
) |
||||
|
move_id = fields.Many2one( |
||||
|
comodel_name='account.move', |
||||
|
required=True, |
||||
|
ondelete='cascade', |
||||
|
) |
||||
|
report_move_line_ids = fields.One2many( |
||||
|
comodel_name='report_journal_ledger_move_line', |
||||
|
inverse_name='report_move_id', |
||||
|
) |
||||
|
name = fields.Char() |
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
required=True, |
||||
|
ondelete='cascade' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class ReportJournalLedgerMoveLine(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_journal_ledger_move_line' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
_order = 'partner_id desc, account_id desc' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_journal_ledger', |
||||
|
required=True, |
||||
|
ondelete='cascade' |
||||
|
) |
||||
|
report_journal_ledger_id = fields.Many2one( |
||||
|
comodel_name='report_journal_ledger_journal', |
||||
|
required=True, |
||||
|
ondelete='cascade', |
||||
|
) |
||||
|
report_move_id = fields.Many2one( |
||||
|
comodel_name='report_journal_ledger_move', |
||||
|
required=True, |
||||
|
ondelete='cascade', |
||||
|
) |
||||
|
move_line_id = fields.Many2one( |
||||
|
comodel_name='account.move.line', |
||||
|
required=True, |
||||
|
ondelete='cascade', |
||||
|
) |
||||
|
account_id = fields.Many2one( |
||||
|
comodel_name='account.account', |
||||
|
string='Account ID', |
||||
|
) |
||||
|
account = fields.Char() |
||||
|
account_code = fields.Char() |
||||
|
account_type = fields.Char() |
||||
|
partner = fields.Char() |
||||
|
partner_id = fields.Many2one( |
||||
|
comodel_name='res.partner', |
||||
|
string='Partner ID', |
||||
|
) |
||||
|
date = fields.Date() |
||||
|
entry = fields.Char() |
||||
|
label = fields.Char() |
||||
|
debit = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
) |
||||
|
credit = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
) |
||||
|
company_currency_id = fields.Many2one( |
||||
|
comodel_name='res.currency', |
||||
|
) |
||||
|
amount_currency = fields.Monetary( |
||||
|
currency_field='currency_id', |
||||
|
) |
||||
|
currency_id = fields.Many2one( |
||||
|
comodel_name='res.currency', |
||||
|
) |
||||
|
currency_name = fields.Char() |
||||
|
taxes_description = fields.Char() |
||||
|
tax_id = fields.Many2one( |
||||
|
comodel_name='account.tax' |
||||
|
) |
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
required=True, |
||||
|
ondelete='cascade' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class ReportJournalLedgerReportTaxLine(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_journal_ledger_report_tax_line' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
_order = 'tax_code' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_journal_ledger', |
||||
|
required=True, |
||||
|
ondelete='cascade' |
||||
|
) |
||||
|
tax_id = fields.Many2one( |
||||
|
comodel_name='account.tax' |
||||
|
) |
||||
|
tax_name = fields.Char() |
||||
|
tax_code = fields.Char() |
||||
|
base_debit = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
) |
||||
|
base_credit = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
) |
||||
|
base_balance = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
compute='_compute_base_balance', |
||||
|
) |
||||
|
tax_debit = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
) |
||||
|
tax_credit = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
) |
||||
|
tax_balance = fields.Float( |
||||
|
digits=DIGITS, |
||||
|
compute='_compute_tax_balance' |
||||
|
) |
||||
|
|
||||
|
@api.multi |
||||
|
def _compute_base_balance(self): |
||||
|
for rec in self: |
||||
|
rec.base_balance = rec.base_debit - rec.base_credit |
||||
|
|
||||
|
@api.multi |
||||
|
def _compute_tax_balance(self): |
||||
|
for rec in self: |
||||
|
rec.tax_balance = rec.tax_debit - rec.tax_credit |
||||
|
|
||||
|
|
||||
|
class ReportJournalLedgerJournalTaxLine(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_journal_ledger_journal_tax_line' |
||||
|
_inherit = 'report_journal_ledger_report_tax_line' |
||||
|
_order = 'tax_code' |
||||
|
|
||||
|
report_journal_ledger_id = fields.Many2one( |
||||
|
comodel_name='report_journal_ledger_journal', |
||||
|
required=True, |
||||
|
ondelete='cascade', |
||||
|
) |
@ -0,0 +1,250 @@ |
|||||
|
# 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 _, models |
||||
|
|
||||
|
|
||||
|
class JournalLedgerXslx(models.AbstractModel): |
||||
|
_name = 'report.a_f_r.report_journal_ledger_xlsx' |
||||
|
_inherit = 'report.account_financial_report.abstract_report_xlsx' |
||||
|
|
||||
|
def _get_report_name(self, report): |
||||
|
report_name = _('Journal Ledger') |
||||
|
return self._get_report_complete_name(report, 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', |
||||
|
'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_id', |
||||
|
'type': 'many2one', |
||||
|
'width': 14 |
||||
|
}, |
||||
|
{ |
||||
|
'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([ |
||||
|
"%s - %s" % (report_journal.code, report_journal.name) |
||||
|
for report_journal in report.report_journal_ledger_ids |
||||
|
]) |
||||
|
|
||||
|
] |
||||
|
] |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report): |
||||
|
group_option = report.group_option |
||||
|
if group_option == 'journal': |
||||
|
for report_journal in report.report_journal_ledger_ids: |
||||
|
self._generate_journal_content(workbook, report_journal) |
||||
|
elif group_option == 'none': |
||||
|
self._generate_no_group_content(workbook, report) |
||||
|
|
||||
|
def _generate_no_group_content(self, workbook, report): |
||||
|
self._generate_moves_content( |
||||
|
workbook, report, "Report", report.report_move_ids) |
||||
|
self._generate_no_group_taxes_summary(workbook, report) |
||||
|
|
||||
|
def _generate_journal_content(self, workbook, report_journal): |
||||
|
sheet_name = "%s (%s) - %s" % ( |
||||
|
report_journal.code, |
||||
|
report_journal.currency_id.name, |
||||
|
report_journal.name, |
||||
|
) |
||||
|
self._generate_moves_content( |
||||
|
workbook, report_journal.report_id, sheet_name, |
||||
|
report_journal.report_move_ids) |
||||
|
self._generate_journal_taxes_summary(workbook, report_journal) |
||||
|
|
||||
|
def _generate_no_group_taxes_summary(self, workbook, report): |
||||
|
self._generate_taxes_summary( |
||||
|
workbook, report, "Tax Report", report.report_tax_line_ids) |
||||
|
|
||||
|
def _generate_journal_taxes_summary(self, workbook, report_journal): |
||||
|
sheet_name = "Tax - %s (%s) - %s" % ( |
||||
|
report_journal.code, |
||||
|
report_journal.currency_id.name, |
||||
|
report_journal.name, |
||||
|
) |
||||
|
report = report_journal.report_id |
||||
|
self._generate_taxes_summary( |
||||
|
workbook, report, sheet_name, report_journal.report_tax_line_ids) |
||||
|
|
||||
|
def _generate_moves_content(self, workbook, report, sheet_name, moves): |
||||
|
self.workbook = workbook |
||||
|
self.sheet = workbook.add_worksheet(sheet_name) |
||||
|
self._set_column_width() |
||||
|
|
||||
|
self.row_pos = 1 |
||||
|
|
||||
|
self.write_array_title(sheet_name) |
||||
|
self.row_pos += 2 |
||||
|
|
||||
|
self.write_array_header() |
||||
|
for move in moves: |
||||
|
for line in move.report_move_line_ids: |
||||
|
self.write_line(line) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
def _generate_taxes_summary(self, workbook, report, sheet_name, tax_lines): |
||||
|
self.workbook = workbook |
||||
|
self.sheet = workbook.add_worksheet(sheet_name) |
||||
|
|
||||
|
self.row_pos = 1 |
||||
|
self.write_array_title(sheet_name) |
||||
|
self.row_pos += 2 |
@ -0,0 +1,957 @@ |
|||||
|
|
||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import models, fields, api, _ |
||||
|
|
||||
|
|
||||
|
class OpenItemsReport(models.TransientModel): |
||||
|
""" Here, we just define class fields. |
||||
|
For methods, go more bottom at this file. |
||||
|
|
||||
|
The class hierarchy is : |
||||
|
* OpenItemsReport |
||||
|
** OpenItemsReportAccount |
||||
|
*** OpenItemsReportPartner |
||||
|
**** OpenItemsReportMoveLine |
||||
|
""" |
||||
|
|
||||
|
_name = 'report_open_items' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
# Filters fields, used for data computation |
||||
|
date_at = fields.Date() |
||||
|
only_posted_moves = fields.Boolean() |
||||
|
hide_account_at_0 = fields.Boolean() |
||||
|
foreign_currency = fields.Boolean() |
||||
|
company_id = fields.Many2one(comodel_name='res.company') |
||||
|
filter_account_ids = fields.Many2many(comodel_name='account.account') |
||||
|
filter_partner_ids = fields.Many2many(comodel_name='res.partner') |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
account_ids = fields.One2many( |
||||
|
comodel_name='report_open_items_account', |
||||
|
inverse_name='report_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportAccount(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_open_items_account' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
_order = 'code ASC' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_open_items', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
account_id = fields.Many2one( |
||||
|
'account.account', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
code = fields.Char() |
||||
|
name = fields.Char() |
||||
|
currency_id = fields.Many2one('res.currency') |
||||
|
final_amount_residual = fields.Float(digits=(16, 2)) |
||||
|
final_amount_total_due = fields.Float(digits=(16, 2)) |
||||
|
final_amount_residual_currency = fields.Float(digits=(16, 2)) |
||||
|
final_amount_total_due_currency = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
partner_ids = fields.One2many( |
||||
|
comodel_name='report_open_items_partner', |
||||
|
inverse_name='report_account_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportPartner(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_open_items_partner' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
report_account_id = fields.Many2one( |
||||
|
comodel_name='report_open_items_account', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
partner_id = fields.Many2one( |
||||
|
'res.partner', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
name = fields.Char() |
||||
|
currency_id = fields.Many2one('res.currency') |
||||
|
final_amount_residual = fields.Float(digits=(16, 2)) |
||||
|
final_amount_total_due = fields.Float(digits=(16, 2)) |
||||
|
final_amount_residual_currency = fields.Float(digits=(16, 2)) |
||||
|
final_amount_total_due_currency = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
move_line_ids = fields.One2many( |
||||
|
comodel_name='report_open_items_move_line', |
||||
|
inverse_name='report_partner_id' |
||||
|
) |
||||
|
|
||||
|
@api.model |
||||
|
def _generate_order_by(self, order_spec, query): |
||||
|
"""Custom order to display "No partner allocated" at last position.""" |
||||
|
return """ |
||||
|
ORDER BY |
||||
|
CASE |
||||
|
WHEN "report_open_items_partner"."partner_id" IS NOT NULL |
||||
|
THEN 0 |
||||
|
ELSE 1 |
||||
|
END, |
||||
|
"report_open_items_partner"."name" |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportMoveLine(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_open_items_move_line' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
report_partner_id = fields.Many2one( |
||||
|
comodel_name='report_open_items_partner', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
move_line_id = fields.Many2one('account.move.line') |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
date = fields.Date() |
||||
|
date_due = fields.Date() |
||||
|
entry = fields.Char() |
||||
|
journal = fields.Char() |
||||
|
account = fields.Char() |
||||
|
partner = fields.Char() |
||||
|
label = fields.Char() |
||||
|
amount_total_due = fields.Float(digits=(16, 2)) |
||||
|
amount_residual = fields.Float(digits=(16, 2)) |
||||
|
currency_id = fields.Many2one('res.currency') |
||||
|
amount_total_due_currency = fields.Float(digits=(16, 2)) |
||||
|
amount_residual_currency = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportCompute(models.TransientModel): |
||||
|
""" Here, we just define methods. |
||||
|
For class fields, go more top at this file. |
||||
|
""" |
||||
|
|
||||
|
_inherit = 'report_open_items' |
||||
|
|
||||
|
@api.multi |
||||
|
def print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
if report_type == 'xlsx': |
||||
|
report_name = 'a_f_r.report_open_items_xlsx' |
||||
|
else: |
||||
|
report_name = 'account_financial_report.' \ |
||||
|
'report_open_items_qweb' |
||||
|
return self.env['ir.actions.report'].search( |
||||
|
[('report_name', '=', report_name), |
||||
|
('report_type', '=', report_type)], |
||||
|
limit=1).report_action(self, config=False) |
||||
|
|
||||
|
def _get_html(self): |
||||
|
result = {} |
||||
|
rcontext = {} |
||||
|
context = dict(self.env.context) |
||||
|
report = self.browse(context.get('active_id')) |
||||
|
if report: |
||||
|
rcontext['o'] = report |
||||
|
result['html'] = self.env.ref( |
||||
|
'account_financial_report.report_open_items').render( |
||||
|
rcontext) |
||||
|
return result |
||||
|
|
||||
|
@api.model |
||||
|
def get_html(self, given_context=None): |
||||
|
return self._get_html() |
||||
|
|
||||
|
@api.multi |
||||
|
def compute_data_for_report(self): |
||||
|
self.ensure_one() |
||||
|
# Compute report data |
||||
|
self._inject_account_values() |
||||
|
self._inject_partner_values() |
||||
|
self._inject_line_values() |
||||
|
self._inject_line_values(only_empty_partner_line=True) |
||||
|
self._clean_partners_and_accounts() |
||||
|
self._compute_partners_and_accounts_cumul() |
||||
|
if self.hide_account_at_0: |
||||
|
self._clean_partners_and_accounts( |
||||
|
only_delete_account_balance_at_0=True |
||||
|
) |
||||
|
# Refresh cache because all data are computed with SQL requests |
||||
|
self.invalidate_cache() |
||||
|
|
||||
|
def _inject_account_values(self): |
||||
|
"""Inject report values for report_open_items_account.""" |
||||
|
query_inject_account = """ |
||||
|
WITH |
||||
|
accounts AS |
||||
|
( |
||||
|
SELECT |
||||
|
a.id, |
||||
|
a.code, |
||||
|
a.name, |
||||
|
a.user_type_id, |
||||
|
c.id as currency_id |
||||
|
FROM |
||||
|
account_account a |
||||
|
INNER JOIN |
||||
|
account_move_line ml ON a.id = ml.account_id AND ml.date <= %s |
||||
|
LEFT JOIN |
||||
|
res_currency c ON a.currency_id = c.id |
||||
|
""" |
||||
|
if self.filter_partner_ids: |
||||
|
query_inject_account += """ |
||||
|
INNER JOIN |
||||
|
res_partner p ON ml.partner_id = p.id |
||||
|
""" |
||||
|
if self.only_posted_moves: |
||||
|
query_inject_account += """ |
||||
|
INNER JOIN |
||||
|
account_move m ON ml.move_id = m.id AND m.state = 'posted' |
||||
|
""" |
||||
|
query_inject_account += """ |
||||
|
WHERE |
||||
|
a.company_id = %s |
||||
|
AND a.reconcile IS true |
||||
|
""" |
||||
|
if self.filter_account_ids: |
||||
|
query_inject_account += """ |
||||
|
AND |
||||
|
a.id IN %s |
||||
|
""" |
||||
|
if self.filter_partner_ids: |
||||
|
query_inject_account += """ |
||||
|
AND |
||||
|
p.id IN %s |
||||
|
""" |
||||
|
query_inject_account += """ |
||||
|
GROUP BY |
||||
|
a.id, c.id |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_open_items_account |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
account_id, |
||||
|
currency_id, |
||||
|
code, |
||||
|
name |
||||
|
) |
||||
|
SELECT |
||||
|
%s AS report_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
a.id AS account_id, |
||||
|
a.currency_id, |
||||
|
a.code, |
||||
|
a.name |
||||
|
FROM |
||||
|
accounts a |
||||
|
""" |
||||
|
query_inject_account_params = ( |
||||
|
self.date_at, |
||||
|
self.company_id.id, |
||||
|
) |
||||
|
if self.filter_account_ids: |
||||
|
query_inject_account_params += ( |
||||
|
tuple(self.filter_account_ids.ids), |
||||
|
) |
||||
|
if self.filter_partner_ids: |
||||
|
query_inject_account_params += ( |
||||
|
tuple(self.filter_partner_ids.ids), |
||||
|
) |
||||
|
query_inject_account_params += ( |
||||
|
self.id, |
||||
|
self.env.uid, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_account, query_inject_account_params) |
||||
|
|
||||
|
def _inject_partner_values(self): |
||||
|
""" Inject report values for report_open_items_partner. """ |
||||
|
# pylint: disable=sql-injection |
||||
|
query_inject_partner = """ |
||||
|
WITH |
||||
|
accounts_partners AS |
||||
|
( |
||||
|
SELECT |
||||
|
ra.id AS report_account_id, |
||||
|
a.id AS account_id, |
||||
|
at.include_initial_balance AS include_initial_balance, |
||||
|
p.id AS partner_id, |
||||
|
COALESCE( |
||||
|
CASE |
||||
|
WHEN |
||||
|
NULLIF(p.name, '') IS NOT NULL |
||||
|
AND NULLIF(p.ref, '') IS NOT NULL |
||||
|
THEN p.name || ' (' || p.ref || ')' |
||||
|
ELSE p.name |
||||
|
END, |
||||
|
'""" + _('No partner allocated') + """' |
||||
|
) AS partner_name |
||||
|
FROM |
||||
|
report_open_items_account ra |
||||
|
INNER JOIN |
||||
|
account_account a ON ra.account_id = a.id |
||||
|
INNER JOIN |
||||
|
account_account_type at ON a.user_type_id = at.id |
||||
|
INNER JOIN |
||||
|
account_move_line ml ON a.id = ml.account_id AND ml.date <= %s |
||||
|
""" |
||||
|
if self.only_posted_moves: |
||||
|
query_inject_partner += """ |
||||
|
INNER JOIN |
||||
|
account_move m ON ml.move_id = m.id AND m.state = 'posted' |
||||
|
""" |
||||
|
query_inject_partner += """ |
||||
|
LEFT JOIN |
||||
|
res_partner p ON ml.partner_id = p.id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
""" |
||||
|
if self.filter_partner_ids: |
||||
|
query_inject_partner += """ |
||||
|
AND |
||||
|
p.id IN %s |
||||
|
""" |
||||
|
query_inject_partner += """ |
||||
|
GROUP BY |
||||
|
ra.id, |
||||
|
a.id, |
||||
|
p.id, |
||||
|
at.include_initial_balance |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_open_items_partner |
||||
|
( |
||||
|
report_account_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
partner_id, |
||||
|
name |
||||
|
) |
||||
|
SELECT |
||||
|
ap.report_account_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
ap.partner_id, |
||||
|
ap.partner_name |
||||
|
FROM |
||||
|
accounts_partners ap |
||||
|
""" |
||||
|
query_inject_partner_params = ( |
||||
|
self.date_at, |
||||
|
self.id, |
||||
|
) |
||||
|
if self.filter_partner_ids: |
||||
|
query_inject_partner_params += ( |
||||
|
tuple(self.filter_partner_ids.ids), |
||||
|
) |
||||
|
query_inject_partner_params += ( |
||||
|
self.env.uid, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_partner, query_inject_partner_params) |
||||
|
|
||||
|
def _get_line_sub_query_move_lines(self, |
||||
|
only_empty_partner_line=False, |
||||
|
positive_balance=True): |
||||
|
""" Return subquery used to compute sum amounts on lines """ |
||||
|
sub_query = """ |
||||
|
SELECT |
||||
|
ml.id, |
||||
|
ml.balance, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN ml_past.id IS NOT NULL |
||||
|
THEN pr.amount |
||||
|
ELSE NULL |
||||
|
END |
||||
|
) AS partial_amount, |
||||
|
ml.amount_currency, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN ml_past.id IS NOT NULL |
||||
|
THEN pr.amount_currency |
||||
|
ELSE NULL |
||||
|
END |
||||
|
) AS partial_amount_currency, |
||||
|
ml.currency_id |
||||
|
FROM |
||||
|
report_open_items_partner rp |
||||
|
INNER JOIN |
||||
|
report_open_items_account ra |
||||
|
ON rp.report_account_id = ra.id |
||||
|
INNER JOIN |
||||
|
account_move_line ml |
||||
|
ON ra.account_id = ml.account_id |
||||
|
""" |
||||
|
if not only_empty_partner_line: |
||||
|
sub_query += """ |
||||
|
AND rp.partner_id = ml.partner_id |
||||
|
""" |
||||
|
elif only_empty_partner_line: |
||||
|
sub_query += """ |
||||
|
AND ml.partner_id IS NULL |
||||
|
""" |
||||
|
if not positive_balance: |
||||
|
sub_query += """ |
||||
|
LEFT JOIN |
||||
|
account_partial_reconcile pr |
||||
|
ON ml.balance < 0 AND pr.credit_move_id = ml.id |
||||
|
LEFT JOIN |
||||
|
account_move_line ml_future |
||||
|
ON ml.balance < 0 AND pr.debit_move_id = ml_future.id |
||||
|
AND ml_future.date > %s |
||||
|
LEFT JOIN |
||||
|
account_move_line ml_past |
||||
|
ON ml.balance < 0 AND pr.debit_move_id = ml_past.id |
||||
|
AND ml_past.date <= %s |
||||
|
""" |
||||
|
else: |
||||
|
sub_query += """ |
||||
|
LEFT JOIN |
||||
|
account_partial_reconcile pr |
||||
|
ON ml.balance > 0 AND pr.debit_move_id = ml.id |
||||
|
LEFT JOIN |
||||
|
account_move_line ml_future |
||||
|
ON ml.balance > 0 AND pr.credit_move_id = ml_future.id |
||||
|
AND ml_future.date > %s |
||||
|
LEFT JOIN |
||||
|
account_move_line ml_past |
||||
|
ON ml.balance > 0 AND pr.credit_move_id = ml_past.id |
||||
|
AND ml_past.date <= %s |
||||
|
""" |
||||
|
sub_query += """ |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
GROUP BY |
||||
|
ml.id, |
||||
|
ml.balance, |
||||
|
ml.amount_currency |
||||
|
HAVING |
||||
|
( |
||||
|
ml.full_reconcile_id IS NULL |
||||
|
OR MAX(ml_future.id) IS NOT NULL |
||||
|
) |
||||
|
""" |
||||
|
return sub_query |
||||
|
|
||||
|
def _inject_line_values(self, only_empty_partner_line=False): |
||||
|
""" Inject report values for report_open_items_move_line. |
||||
|
|
||||
|
The "only_empty_partner_line" value is used |
||||
|
to compute data without partner. |
||||
|
""" |
||||
|
query_inject_move_line = """ |
||||
|
WITH |
||||
|
move_lines_amount AS |
||||
|
( |
||||
|
""" |
||||
|
query_inject_move_line += self._get_line_sub_query_move_lines( |
||||
|
only_empty_partner_line=only_empty_partner_line, |
||||
|
positive_balance=True |
||||
|
) |
||||
|
query_inject_move_line += """ |
||||
|
UNION |
||||
|
""" |
||||
|
query_inject_move_line += self._get_line_sub_query_move_lines( |
||||
|
only_empty_partner_line=only_empty_partner_line, |
||||
|
positive_balance=False |
||||
|
) |
||||
|
query_inject_move_line += """ |
||||
|
), |
||||
|
move_lines AS |
||||
|
( |
||||
|
SELECT |
||||
|
id, |
||||
|
CASE |
||||
|
WHEN SUM(partial_amount) > 0 |
||||
|
THEN |
||||
|
CASE |
||||
|
WHEN balance > 0 |
||||
|
THEN balance - SUM(partial_amount) |
||||
|
ELSE balance + SUM(partial_amount) |
||||
|
END |
||||
|
ELSE balance |
||||
|
END AS amount_residual, |
||||
|
CASE |
||||
|
WHEN SUM(partial_amount_currency) > 0 |
||||
|
THEN |
||||
|
CASE |
||||
|
WHEN amount_currency > 0 |
||||
|
THEN amount_currency - SUM(partial_amount_currency) |
||||
|
ELSE amount_currency + SUM(partial_amount_currency) |
||||
|
END |
||||
|
ELSE amount_currency |
||||
|
END AS amount_residual_currency, |
||||
|
currency_id |
||||
|
FROM |
||||
|
move_lines_amount |
||||
|
GROUP BY |
||||
|
id, |
||||
|
balance, |
||||
|
amount_currency, |
||||
|
currency_id |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_open_items_move_line |
||||
|
( |
||||
|
report_partner_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
move_line_id, |
||||
|
date, |
||||
|
date_due, |
||||
|
entry, |
||||
|
journal, |
||||
|
account, |
||||
|
partner, |
||||
|
label, |
||||
|
amount_total_due, |
||||
|
amount_residual, |
||||
|
currency_id, |
||||
|
amount_total_due_currency, |
||||
|
amount_residual_currency |
||||
|
) |
||||
|
SELECT |
||||
|
rp.id AS report_partner_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
ml.id AS move_line_id, |
||||
|
ml.date, |
||||
|
ml.date_maturity, |
||||
|
m.name AS entry, |
||||
|
j.code AS journal, |
||||
|
a.code AS account, |
||||
|
""" |
||||
|
if not only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
CASE |
||||
|
WHEN |
||||
|
NULLIF(p.name, '') IS NOT NULL |
||||
|
AND NULLIF(p.ref, '') IS NOT NULL |
||||
|
THEN p.name || ' (' || p.ref || ')' |
||||
|
ELSE p.name |
||||
|
END AS partner, |
||||
|
""" |
||||
|
elif only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
'""" + _('No partner allocated') + """' AS partner, |
||||
|
""" |
||||
|
query_inject_move_line += """ |
||||
|
CONCAT_WS(' - ', NULLIF(ml.ref, ''), NULLIF(ml.name, '')) AS label, |
||||
|
ml.balance, |
||||
|
ml2.amount_residual, |
||||
|
c.id AS currency_id, |
||||
|
ml.amount_currency, |
||||
|
ml2.amount_residual_currency |
||||
|
FROM |
||||
|
report_open_items_partner rp |
||||
|
INNER JOIN |
||||
|
report_open_items_account ra ON rp.report_account_id = ra.id |
||||
|
INNER JOIN |
||||
|
account_move_line ml ON ra.account_id = ml.account_id |
||||
|
INNER JOIN |
||||
|
move_lines ml2 |
||||
|
ON ml.id = ml2.id |
||||
|
AND ml2.amount_residual IS NOT NULL |
||||
|
AND ml2.amount_residual != 0 |
||||
|
INNER JOIN |
||||
|
account_move m ON ml.move_id = m.id |
||||
|
INNER JOIN |
||||
|
account_journal j ON ml.journal_id = j.id |
||||
|
INNER JOIN |
||||
|
account_account a ON ml.account_id = a.id |
||||
|
""" |
||||
|
if not only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
INNER JOIN |
||||
|
res_partner p |
||||
|
ON ml.partner_id = p.id AND rp.partner_id = p.id |
||||
|
""" |
||||
|
query_inject_move_line += """ |
||||
|
LEFT JOIN |
||||
|
account_full_reconcile fr ON ml.full_reconcile_id = fr.id |
||||
|
LEFT JOIN |
||||
|
res_currency c ON ml2.currency_id = c.id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
AND |
||||
|
ml.date <= %s |
||||
|
""" |
||||
|
if self.only_posted_moves: |
||||
|
query_inject_move_line += """ |
||||
|
AND |
||||
|
m.state = 'posted' |
||||
|
""" |
||||
|
if only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
AND |
||||
|
ml.partner_id IS NULL |
||||
|
AND |
||||
|
rp.partner_id IS NULL |
||||
|
""" |
||||
|
if not only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
ORDER BY |
||||
|
a.code, p.name, ml.date, ml.id |
||||
|
""" |
||||
|
elif only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
ORDER BY |
||||
|
a.code, ml.date, ml.id |
||||
|
""" |
||||
|
self.env.cr.execute( |
||||
|
query_inject_move_line, |
||||
|
(self.date_at, |
||||
|
self.date_at, |
||||
|
self.id, |
||||
|
self.date_at, |
||||
|
self.date_at, |
||||
|
self.id, |
||||
|
self.env.uid, |
||||
|
self.id, |
||||
|
self.date_at,) |
||||
|
) |
||||
|
|
||||
|
def _compute_partners_and_accounts_cumul(self): |
||||
|
""" Compute cumulative amount for |
||||
|
report_open_items_partner and report_open_items_account. |
||||
|
""" |
||||
|
self._compute_partner_cumul() |
||||
|
self._compute_account_cumul() |
||||
|
|
||||
|
def _compute_partner_cumul(self): |
||||
|
query_computer_partner_residual_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_partner |
||||
|
SET |
||||
|
final_amount_residual = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rml.amount_residual) AS final_amount_residual |
||||
|
FROM |
||||
|
report_open_items_move_line rml |
||||
|
WHERE |
||||
|
rml.report_partner_id = report_open_items_partner.id |
||||
|
) |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
rp.id |
||||
|
FROM |
||||
|
report_open_items_account ra |
||||
|
INNER JOIN |
||||
|
report_open_items_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
) |
||||
|
""" |
||||
|
params_compute_partners_residual_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_computer_partner_residual_cumul, |
||||
|
params_compute_partners_residual_cumul) |
||||
|
|
||||
|
query_compute_partners_due_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_partner |
||||
|
SET |
||||
|
final_amount_total_due = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rml.amount_total_due) AS final_amount_total_due |
||||
|
FROM |
||||
|
report_open_items_move_line rml |
||||
|
WHERE |
||||
|
rml.report_partner_id = report_open_items_partner.id |
||||
|
) |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
rp.id |
||||
|
FROM |
||||
|
report_open_items_account ra |
||||
|
INNER JOIN |
||||
|
report_open_items_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
) |
||||
|
""" |
||||
|
params_compute_partner_due_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_partners_due_cumul, |
||||
|
params_compute_partner_due_cumul) |
||||
|
|
||||
|
# Manage currency in partner |
||||
|
query_compute_partners_cur_id_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_partner |
||||
|
SET |
||||
|
currency_id = |
||||
|
( |
||||
|
SELECT |
||||
|
MAX(currency_id) as currency_id |
||||
|
FROM |
||||
|
report_open_items_move_line rml |
||||
|
WHERE |
||||
|
rml.report_partner_id = report_open_items_partner.id |
||||
|
) |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
rp.id |
||||
|
FROM |
||||
|
report_open_items_account ra |
||||
|
INNER JOIN |
||||
|
report_open_items_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
WHERE |
||||
|
ra.report_id = %s AND ra.currency_id IS NOT NULL |
||||
|
) |
||||
|
""" |
||||
|
params_compute_partners_cur_id_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_partners_cur_id_cumul, |
||||
|
params_compute_partners_cur_id_cumul) |
||||
|
|
||||
|
query_compute_partners_cur_residual_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_partner |
||||
|
SET |
||||
|
final_amount_residual_currency = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rml.amount_residual_currency) |
||||
|
AS final_amount_residual_currency |
||||
|
FROM |
||||
|
report_open_items_move_line rml |
||||
|
WHERE |
||||
|
rml.report_partner_id = report_open_items_partner.id |
||||
|
) |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
rp.id |
||||
|
FROM |
||||
|
report_open_items_account ra |
||||
|
INNER JOIN |
||||
|
report_open_items_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
WHERE |
||||
|
ra.report_id = %s AND ra.currency_id IS NOT NULL |
||||
|
) |
||||
|
""" |
||||
|
params_compute_partners_cur_residual_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_partners_cur_residual_cumul, |
||||
|
params_compute_partners_cur_residual_cumul) |
||||
|
|
||||
|
query_compute_partners_cur_due_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_partner |
||||
|
SET |
||||
|
final_amount_total_due_currency = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rml.amount_total_due_currency) |
||||
|
AS final_amount_total_due_currency |
||||
|
FROM |
||||
|
report_open_items_move_line rml |
||||
|
WHERE |
||||
|
rml.report_partner_id = report_open_items_partner.id |
||||
|
) |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
rp.id |
||||
|
FROM |
||||
|
report_open_items_account ra |
||||
|
INNER JOIN |
||||
|
report_open_items_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
WHERE |
||||
|
ra.report_id = %s AND ra.currency_id IS NOT NULL |
||||
|
) |
||||
|
""" |
||||
|
params_compute_partners_cur_due_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_partners_cur_due_cumul, |
||||
|
params_compute_partners_cur_due_cumul) |
||||
|
|
||||
|
def _compute_account_cumul(self): |
||||
|
query_compute_accounts_residual_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_account |
||||
|
SET |
||||
|
final_amount_residual = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rp.final_amount_residual) AS final_amount_residual |
||||
|
FROM |
||||
|
report_open_items_partner rp |
||||
|
WHERE |
||||
|
rp.report_account_id = report_open_items_account.id |
||||
|
) |
||||
|
WHERE |
||||
|
report_id = %s |
||||
|
""" |
||||
|
params_compute_accounts_residual_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_accounts_residual_cumul, |
||||
|
params_compute_accounts_residual_cumul) |
||||
|
|
||||
|
query_compute_accounts_cur_residual_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_account |
||||
|
SET |
||||
|
final_amount_residual_currency = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rp.final_amount_residual_currency) |
||||
|
AS final_amount_residual_currency |
||||
|
FROM |
||||
|
report_open_items_partner rp |
||||
|
WHERE |
||||
|
rp.report_account_id = report_open_items_account.id |
||||
|
) |
||||
|
WHERE |
||||
|
report_id = %s |
||||
|
""" |
||||
|
params_compute_accounts_cur_residual_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_accounts_cur_residual_cumul, |
||||
|
params_compute_accounts_cur_residual_cumul) |
||||
|
|
||||
|
query_compute_accounts_due_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_account |
||||
|
SET |
||||
|
final_amount_total_due = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rp.final_amount_total_due) AS final_amount_total_due |
||||
|
FROM |
||||
|
report_open_items_partner rp |
||||
|
WHERE |
||||
|
rp.report_account_id = report_open_items_account.id |
||||
|
) |
||||
|
WHERE |
||||
|
report_id = %s |
||||
|
""" |
||||
|
params_compute_accounts_due_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_accounts_due_cumul, |
||||
|
params_compute_accounts_due_cumul) |
||||
|
|
||||
|
query_compute_accounts_cur_due_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_account |
||||
|
SET |
||||
|
final_amount_total_due_currency = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rp.final_amount_total_due_currency) |
||||
|
AS final_amount_total_due_currency |
||||
|
FROM |
||||
|
report_open_items_partner rp |
||||
|
WHERE |
||||
|
rp.report_account_id = report_open_items_account.id |
||||
|
) |
||||
|
WHERE |
||||
|
report_id = %s |
||||
|
""" |
||||
|
params_compute_accounts_cur_due_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_accounts_cur_due_cumul, |
||||
|
params_compute_accounts_cur_due_cumul) |
||||
|
|
||||
|
def _clean_partners_and_accounts(self, |
||||
|
only_delete_account_balance_at_0=False): |
||||
|
""" Delete empty data for |
||||
|
report_open_items_partner and report_open_items_account. |
||||
|
|
||||
|
The "only_delete_account_balance_at_0" value is used |
||||
|
to delete also the data with cumulative amounts at 0. |
||||
|
""" |
||||
|
query_clean_partners = """ |
||||
|
DELETE FROM |
||||
|
report_open_items_partner |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
DISTINCT rp.id |
||||
|
FROM |
||||
|
report_open_items_account ra |
||||
|
INNER JOIN |
||||
|
report_open_items_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
LEFT JOIN |
||||
|
report_open_items_move_line rml |
||||
|
ON rp.id = rml.report_partner_id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
""" |
||||
|
if not only_delete_account_balance_at_0: |
||||
|
query_clean_partners += """ |
||||
|
AND rml.id IS NULL |
||||
|
""" |
||||
|
elif only_delete_account_balance_at_0: |
||||
|
query_clean_partners += """ |
||||
|
AND ( |
||||
|
rp.final_amount_residual IS NULL |
||||
|
OR rp.final_amount_residual = 0 |
||||
|
) |
||||
|
""" |
||||
|
query_clean_partners += """ |
||||
|
) |
||||
|
""" |
||||
|
params_clean_partners = (self.id,) |
||||
|
self.env.cr.execute(query_clean_partners, params_clean_partners) |
||||
|
query_clean_accounts = """ |
||||
|
DELETE FROM |
||||
|
report_open_items_account |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
DISTINCT ra.id |
||||
|
FROM |
||||
|
report_open_items_account ra |
||||
|
LEFT JOIN |
||||
|
report_open_items_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
""" |
||||
|
if not only_delete_account_balance_at_0: |
||||
|
query_clean_accounts += """ |
||||
|
AND rp.id IS NULL |
||||
|
""" |
||||
|
elif only_delete_account_balance_at_0: |
||||
|
query_clean_accounts += """ |
||||
|
AND ( |
||||
|
ra.final_amount_residual IS NULL |
||||
|
OR ra.final_amount_residual = 0 |
||||
|
) |
||||
|
""" |
||||
|
query_clean_accounts += """ |
||||
|
) |
||||
|
""" |
||||
|
params_clean_accounts = (self.id,) |
||||
|
self.env.cr.execute(query_clean_accounts, params_clean_accounts) |
@ -0,0 +1,119 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# 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' |
||||
|
_inherit = 'report.account_financial_report.abstract_report_xlsx' |
||||
|
|
||||
|
def _get_report_name(self, report): |
||||
|
report_name = _('Open Items') |
||||
|
return self._get_report_complete_name(report, report_name) |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
res = { |
||||
|
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': 'label', 'width': 40}, |
||||
|
6: {'header': _('Due date'), 'field': 'date_due', 'width': 11}, |
||||
|
7: {'header': _('Original'), |
||||
|
'field': 'amount_total_due', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
8: {'header': _('Residual'), |
||||
|
'field': 'amount_residual', |
||||
|
'field_final_balance': 'final_amount_residual', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
} |
||||
|
if report.foreign_currency: |
||||
|
foreign_currency = { |
||||
|
9: {'header': _('Cur.'), 'field': 'currency_id', |
||||
|
'field_currency_balance': 'currency_id', |
||||
|
'type': 'many2one', 'width': 7}, |
||||
|
10: {'header': _('Cur. Original'), |
||||
|
'field': 'amount_total_due_currency', |
||||
|
'field_final_balance': |
||||
|
'final_amount_total_due_currency', |
||||
|
'type': 'amount_currency', |
||||
|
'width': 14}, |
||||
|
11: {'header': _('Cur. Residual'), |
||||
|
'field': 'amount_residual_currency', |
||||
|
'field_final_balance': |
||||
|
'final_amount_residual_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], |
||||
|
[_('Target moves filter'), |
||||
|
_('All posted entries') if report.only_posted_moves 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): |
||||
|
# For each account |
||||
|
for account in report.account_ids: |
||||
|
# Write account title |
||||
|
self.write_array_title(account.code + ' - ' + account.name) |
||||
|
|
||||
|
# For each partner |
||||
|
for partner in account.partner_ids: |
||||
|
# Write partner title |
||||
|
self.write_array_title(partner.name) |
||||
|
|
||||
|
# Display array header for move lines |
||||
|
self.write_array_header() |
||||
|
|
||||
|
# Display account move lines |
||||
|
for line in partner.move_line_ids: |
||||
|
self.write_line(line) |
||||
|
|
||||
|
# Display ending balance line for partner |
||||
|
self.write_ending_balance(partner, 'partner') |
||||
|
|
||||
|
# Line break |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
# Display ending balance line for account |
||||
|
self.write_ending_balance(account, 'account') |
||||
|
|
||||
|
# 2 lines break |
||||
|
self.row_pos += 2 |
||||
|
|
||||
|
def write_ending_balance(self, my_object, type_object): |
||||
|
"""Specific function to write ending balance for Open Items""" |
||||
|
if type_object == 'partner': |
||||
|
name = my_object.name |
||||
|
label = _('Partner ending balance') |
||||
|
my_object.currency_id = my_object.report_account_id.currency_id |
||||
|
elif type_object == 'account': |
||||
|
name = my_object.code + ' - ' + my_object.name |
||||
|
label = _('Ending balance') |
||||
|
super(OpenItemsXslx, self).write_ending_balance(my_object, name, label) |
@ -0,0 +1,563 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="report_aged_partner_balance_qweb"> |
||||
|
<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="o.show_move_line_details"/> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title">Aged Partner Balance - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t> |
||||
|
<t t-set="company_name" t-value="o.company_id.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_aged_partner_balance_filters"/> |
||||
|
|
||||
|
<t t-foreach="o.account_ids" 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-field="account.code"/> |
||||
|
- |
||||
|
<span t-field="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.partner_ids" 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.partner_ids" t-as="partner"> |
||||
|
<div class="page_break"> |
||||
|
<!-- Display partner header --> |
||||
|
<div class="act_as_caption account_title"> |
||||
|
<span t-field="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.line_ids"/> |
||||
|
</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-field="o.date_at"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.only_posted_moves">All posted entries</t> |
||||
|
<t t-if="not o.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 lines --> |
||||
|
<t t-foreach="partner.line_ids" t-as="line"> |
||||
|
<!-- # lines --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-field="line.partner"/> |
||||
|
</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.current" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.age_30_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.age_60_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.age_90_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.age_120_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.older" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</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_line_ids" 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.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.date_due" 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.amount_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.age_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.age_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.age_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.age_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-field="partner_cumul_line.amount_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-field="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-field="partner_cumul_line.age_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-field="partner_cumul_line.age_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-field="partner_cumul_line.age_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-field="partner_cumul_line.age_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-field="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-field="account.cumul_amount_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-field="account.cumul_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-field="account.cumul_age_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-field="account.cumul_age_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-field="account.cumul_age_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-field="account.cumul_age_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-field="account.cumul_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-field="account.cumul_amount_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-field="account.cumul_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-field="account.cumul_age_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-field="account.cumul_age_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-field="account.cumul_age_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-field="account.cumul_age_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-field="account.cumul_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-field="account.percent_current"/>% |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_age_30_days"/>% |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_age_60_days"/>% |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_age_90_days"/>% |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_age_120_days"/> |
||||
|
% |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="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-field="account.percent_current"/>% |
||||
|
</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_age_30_days"/>% |
||||
|
</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_age_60_days"/>% |
||||
|
</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_age_90_days"/>% |
||||
|
</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_age_120_days"/>% |
||||
|
</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_older"/>% |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,558 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="report_general_ledger_qweb"> |
||||
|
<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="show_analytic_tags" t-value="o.show_analytic_tags"/> |
||||
|
<t t-set="show_cost_center" t-value="o.show_cost_center"/> |
||||
|
<t t-set="foreign_currency" t-value="o.foreign_currency"/> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title">General Ledger - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t> |
||||
|
<t t-set="company_name" t-value="o.company_id.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_general_ledger_filters"/> |
||||
|
<t t-foreach="o.account_ids" 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-field="account.code"/> - <span t-field="account.name"/> |
||||
|
</div> |
||||
|
|
||||
|
<t t-if="not account.partner_ids"> |
||||
|
<!-- 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> |
||||
|
</t> |
||||
|
|
||||
|
<t t-if="account.partner_ids"> |
||||
|
<!-- Display account partners --> |
||||
|
<t t-foreach="account.partner_ids" 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-field="partner.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> |
||||
|
</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> |
||||
|
</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-field="o.date_from"/> To: <span t-field="o.date_to"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.only_posted_moves">All posted entries</t> |
||||
|
<t t-if="not o.only_posted_moves">All entries</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.hide_account_at_0">Hide</t> |
||||
|
<t t-if="not o.hide_account_at_0">Show</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.centralize">Yes</t> |
||||
|
<t t-if="not o.centralize">No</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.show_analytic_tags">Yes</t> |
||||
|
<t t-if="not o.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: 22.9%;">Ref - |
||||
|
Label</div> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<!--## cost_center--> |
||||
|
<div class="act_as_cell" style="width: 8.03%;">Cost |
||||
|
center</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: 6.02%;">Debit</div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount" style="width: 6.02%;">Credit</div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount" style="width: 6.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"></div> |
||||
|
</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_or_partner_object.account_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d')), |
||||
|
('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.initial_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_or_partner_object.report_account_id.account_id.id), |
||||
|
('partner_id', '=', account_or_partner_object.partner_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d')), |
||||
|
('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.initial_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_or_partner_object.account_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d')), |
||||
|
('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.initial_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_or_partner_object.report_account_id.account_id.id), |
||||
|
('partner_id', '=', account_or_partner_object.partner_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d')), |
||||
|
('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.initial_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_or_partner_object.account_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d'))]"/> |
||||
|
<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.initial_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_or_partner_object.report_account_id.account_id.id), |
||||
|
('partner_id', '=', account_or_partner_object.partner_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d'))]"/> |
||||
|
<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.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t t-if="account.account_id.currency_id.id"> |
||||
|
<div class="act_as_cell amount" style="width: 2.08%;"> |
||||
|
<span t-field="account.account_id.currency_id.display_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_or_partner_object.account_id.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.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account.account_id.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account_or_partner_object.report_account_id.account_id.id), |
||||
|
('partner_id', '=', account_or_partner_object.partner_id.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.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account.account_id.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not account.account_id.currency_id.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_line_ids" 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> |
||||
|
<a t-att-data-active-id="line.move_line_id.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> |
||||
|
</span> |
||||
|
</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_line_id.move_id.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> |
||||
|
</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.move_line_id.move_id.journal_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
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"> |
||||
|
<t t-set="res_model" t-value="'account.account'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.move_line_id.account_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;"> |
||||
|
<t t-raw="line.account"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## taxes--> |
||||
|
<div class="act_as_cell left"><span t-field="line.taxes_description"/></div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'res.partner'"/> |
||||
|
<span t-if="line.partner"> |
||||
|
<a t-att-data-active-id="line.move_line_id.partner_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
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"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.move_line_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;"> |
||||
|
<t t-raw="line.label"/></a> |
||||
|
</span> |
||||
|
</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.cost_center"> |
||||
|
<a t-att-data-active-id="line.move_line_id.analytic_account_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;"><t t-raw="line.cost_center"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="show_analytic_tags"> |
||||
|
<!--## analytic tags--> |
||||
|
<div class="act_as_cell left"><span t-field="line.tags"/></div> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-set="res_model" t-value="'account.full.reconcile'"/> |
||||
|
<span t-if="line.matching_number"> |
||||
|
<a t-att-data-active-id="line.move_line_id.full_reconcile_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;"><t t-raw="line.matching_number"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.move_line_id.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> |
||||
|
</div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.move_line_id.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> |
||||
|
</div> |
||||
|
|
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-set="res_model" t-value="'account.move.line'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.move_line_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action_monetary" |
||||
|
style="color: black;"> |
||||
|
<t t-raw="line.cumul_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t t-if="line.currency_id.id"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell amount" style="width: 2.08%;"> |
||||
|
<span t-field="line.currency_id.display_name"/> |
||||
|
</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.move_line_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
style="color: black;"> |
||||
|
<t t-raw="line.amount_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not line.currency_id.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-field="account_or_partner_object.code"/> - <span t-field="account_or_partner_object.name"/></div> |
||||
|
<div class="act_as_cell right" |
||||
|
style="width: 22.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: 22.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%;"></div> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell" style="width: 2.41%;"/> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount" style="width: 6.02%;"> |
||||
|
<span t-field="account_or_partner_object.final_debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount" style="width: 6.02%;"> |
||||
|
<span t-field="account_or_partner_object.final_credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount" style="width: 6.02%;"> |
||||
|
<span t-field="account_or_partner_object.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## currency_name + amount_currency--> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t t-if="account.account_id.currency_id.id"> |
||||
|
<div class="act_as_cell amount" style="width: 2.08%;"> |
||||
|
<span t-field="account.account_id.currency_id.display_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_or_partner_object.account_id.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.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account_or_partner_object.account_id.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account_or_partner_object.report_account_id.account_id.id), |
||||
|
('partner_id', '=', account_or_partner_object.partner_id.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.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account_or_partner_object.report_account_id.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not account.account_id.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,465 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="report_journal_ledger_qweb"> |
||||
|
<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="o.foreign_currency"/> |
||||
|
<t t-set="display_account_name" t-value="o.with_account_name"/> |
||||
|
<t t-set="title">Journal Ledger - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t> |
||||
|
<t t-set="company_name" t-value="o.company_id.name"/> |
||||
|
<div class="page"> |
||||
|
<div class="row"> |
||||
|
<h4 class="mt0" t-esc="title or 'Odoo Report'" style="text-align: center;"/> |
||||
|
</div> |
||||
|
<t t-if="o.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="o.group_option == 'journal'"> |
||||
|
<t t-foreach="o.report_journal_ledger_ids" 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="o.report_move_ids" 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-field="journal.name"/> (<span t-field="journal.currency_id.display_name"/>) - <span t-field="o.date_from"/> to <span t-field="o.date_to"/> - <span t-field="o.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_move_ids" 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-field="journal.debit"/></b> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="credit"> |
||||
|
<b><span t-field="journal.credit"/></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_line_ids" t-as="move_line"> |
||||
|
<div class="act_as_row lines"> |
||||
|
<t t-set="current_partner" t-value="move_line.partner_id"/> |
||||
|
<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"> |
||||
|
<span t-if="display_move_info" t-field="move_line.entry"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" |
||||
|
name="date"> |
||||
|
<span t-if="display_move_info" t-field="move_line.date"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" |
||||
|
name="account"> |
||||
|
<span t-field="move_line.account_code"/> |
||||
|
<span t-if="display_account_name"> |
||||
|
- <span t-field="move_line.account"/> |
||||
|
</span> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" |
||||
|
name="partner"> |
||||
|
<span t-if="display_partner" t-field="move_line.partner"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" |
||||
|
name="label"> |
||||
|
<span t-field="move_line.label"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" |
||||
|
name="taxes"> |
||||
|
<span t-field="move_line.taxes_description"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="debit"> |
||||
|
<t t-if="move_line.debit"> |
||||
|
<span t-field="move_line.debit"/> |
||||
|
</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="credit"> |
||||
|
<t t-if="move_line.credit"> |
||||
|
<span t-field="move_line.credit"/> |
||||
|
</t> |
||||
|
</div> |
||||
|
<t t-if="display_currency"> |
||||
|
<div class="act_as_cell" |
||||
|
name="currency_name"> |
||||
|
<t t-if="move_line.currency_name"> |
||||
|
<span t-field="move_line.currency_name"/> |
||||
|
</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="amount_currency"> |
||||
|
<t t-if="move_line.amount_currency"> |
||||
|
<span t-field="move_line.amount_currency"/> |
||||
|
</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.report_tax_line_ids" t-as="tax_line"> |
||||
|
<div class="act_as_row lines"> |
||||
|
<div class="act_as_cell left" |
||||
|
name="tax_name"> |
||||
|
<span t-field="tax_line.tax_name"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" |
||||
|
name="tax_code"> |
||||
|
<span t-field="tax_line.tax_code"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="base_debit"> |
||||
|
<span t-field="tax_line.base_debit"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="base_credit"> |
||||
|
<span t-field="tax_line.base_credit"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="base_balance"> |
||||
|
<span t-field="tax_line.base_balance"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="tax_debit"> |
||||
|
<span t-field="tax_line.tax_debit"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="tax_credit"> |
||||
|
<span t-field="tax_line.tax_credit"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="tax_balance"> |
||||
|
<span t-field="tax_line.tax_balance"/> |
||||
|
</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="o.report_tax_line_ids" t-as="tax_line"> |
||||
|
<div class="act_as_row lines"> |
||||
|
<div class="act_as_cell left" |
||||
|
name="tax_name"> |
||||
|
<span t-field="tax_line.tax_name"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell left" |
||||
|
name="tax_code"> |
||||
|
<span t-field="tax_line.tax_code"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="base_debit"> |
||||
|
<span t-field="tax_line.base_debit"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="base_credit"> |
||||
|
<span t-field="tax_line.base_credit"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="base_balance"> |
||||
|
<span t-field="tax_line.base_balance"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="tax_debit"> |
||||
|
<span t-field="tax_line.tax_debit"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="tax_credit"> |
||||
|
<span t-field="tax_line.tax_credit"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" |
||||
|
name="tax_balance"> |
||||
|
<span t-field="tax_line.tax_balance"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,26 @@ |
|||||
|
<?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-xs-6 custom_footer"> |
||||
|
<span t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')"/> |
||||
|
</div> |
||||
|
<div class="col-xs-6 text-right custom_footer"> |
||||
|
<ul class="list-inline"> |
||||
|
<li><span class="page"/></li> |
||||
|
<li>/</li> |
||||
|
<li><span class="topage"/></li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,271 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="account_financial_report.report_open_items_qweb"> |
||||
|
<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="o.foreign_currency"/> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title">Open Items - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t> |
||||
|
<t t-set="company_name" t-value="o.company_id.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="o.account_ids" 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-field="account.code"/> |
||||
|
- |
||||
|
<span t-field="account.name"/> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Display account partners --> |
||||
|
<t t-foreach="account.partner_ids" t-as="partner"> |
||||
|
<div class="page_break"> |
||||
|
<!-- Display partner header --> |
||||
|
<div class="act_as_caption account_title"> |
||||
|
<span t-field="partner.name"/> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Display partner move lines --> |
||||
|
<t t-call="account_financial_report.report_open_items_lines"/> |
||||
|
|
||||
|
<!-- Display partner footer --> |
||||
|
<t t-call="account_financial_report.report_open_items_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-call="account_financial_report.report_open_items_ending_cumul"> |
||||
|
<t t-set="account_or_partner_object" t-value="account"/> |
||||
|
<t t-set="type" t-value='"account_type"'/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</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-field="o.date_at"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.only_posted_moves">All posted entries</t> |
||||
|
<t t-if="not o.only_posted_moves">All entries</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.hide_account_at_0">Hide</t> |
||||
|
<t t-if="not o.hide_account_at_0">Show</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report.report_open_items_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: 4.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: 25.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> |
||||
|
|
||||
|
<!-- Display each lines --> |
||||
|
<t t-foreach="partner.move_line_ids" t-as="line"> |
||||
|
<!-- # lines or centralized lines --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-field="line.date"/> |
||||
|
</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_line_id.move_id.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> |
||||
|
</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-field="line.journal"/> |
||||
|
</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-field="line.account"/> |
||||
|
</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-set="res_model" t-value="'res.partner'"/> |
||||
|
<span t-if="line.partner"> |
||||
|
<a t-att-data-active-id="line.move_line_id.partner_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
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 t-field="line.label"/> |
||||
|
</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<span t-field="line.date_due"/> |
||||
|
</div> |
||||
|
<!--## amount_total_due--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.amount_total_due" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="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.id"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.currency_id.display_name"/> |
||||
|
</div> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.amount_total_due_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<span t-field="line.amount_residual_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not line.currency_id.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> |
||||
|
</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-field="account_or_partner_object.code"/> |
||||
|
- |
||||
|
<span t-field="account_or_partner_object.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%;"> |
||||
|
<span t-field="account_or_partner_object.final_amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## amount_total_due_currency + amount_residual_currency --> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t t-if="account_or_partner_object.currency_id.id"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell amount" style="width: 2.25%;"> |
||||
|
<span t-field="account_or_partner_object.currency_id.display_name"/> |
||||
|
</div> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 6.57%;"> |
||||
|
<span t-field="account_or_partner_object.final_amount_total_due_currency" t-options="{'widget': 'monetary', 'display_currency': account_or_partner_object.currency_id}"/> |
||||
|
</div> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 6.57%;"> |
||||
|
<span t-field="account_or_partner_object.final_amount_residual_currency" t-options="{'widget': 'monetary', 'display_currency': account_or_partner_object.currency_id}"/> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not account_or_partner_object.currency_id.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> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,688 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="account_financial_report.report_trial_balance_qweb"> |
||||
|
<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_trial_balance_base"/> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report.report_trial_balance_base"> |
||||
|
<!-- Saved flag fields into variables, used to define columns display --> |
||||
|
<t t-set="show_partner_details" t-value="o.show_partner_details"/> |
||||
|
<t t-set="foreign_currency" t-value="o.foreign_currency"/> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title">Trial Balance - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t> |
||||
|
<t t-set="company_name" t-value="o.company_id.name"/> |
||||
|
<t t-set="res_company" t-value="o.company_id"/> |
||||
|
<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_trial_balance_filters"/> |
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;"/> |
||||
|
|
||||
|
<!-- Display account lines --> |
||||
|
<t t-if="not show_partner_details"> |
||||
|
<div class="act_as_table data_table" style="width: 100%;"> |
||||
|
<!-- Display account header --> |
||||
|
<t t-call="account_financial_report.report_trial_balance_lines_header"/> |
||||
|
|
||||
|
<!-- Display each lines --> |
||||
|
<t t-foreach="o.account_ids.filtered(lambda a: not a.hide_line)" t-as="line"> |
||||
|
<t t-set="type" t-value='"account_type"'/> |
||||
|
<!-- Adapt --> |
||||
|
<t t-set="style" t-value="'font-size:8px;'"/> |
||||
|
<t t-set="padding" t-value="line.level * 4"/> |
||||
|
<t t-if="o.hide_account_at_0"> |
||||
|
<t t-set="style" t-value="'font-size: 14px;'"/> |
||||
|
</t> |
||||
|
<t t-if="o.hierarchy_on != 'none'"> |
||||
|
<t t-set="style" t-value="'font-size: ' + str(14 - line.level) + 'px; margin-left: ' + str(line.level * 4) + 'px;'"/> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="style" t-value="style + 'font-weight: bold; color: blue;'"/> |
||||
|
</t> |
||||
|
|
||||
|
<!-- Display account lines --> |
||||
|
<t t-call="account_financial_report.report_trial_balance_line"/> |
||||
|
<!-- Adapt style --> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<!-- Display partner lines --> |
||||
|
<t t-if="show_partner_details"> |
||||
|
<t t-set="padding" t-value="0"/> |
||||
|
<t t-foreach="o.account_ids" t-as="account"> |
||||
|
<div class="page_break"> |
||||
|
<t t-set="style" t-value="'font-size:8px;'"/> |
||||
|
<t t-set="padding" t-value="account.level * 4"/> |
||||
|
<t t-set="style" t-value="'font-size: ' + str(14 - account.level) + 'px; margin-left: ' + str(account.level * 4) + 'px;'"/> |
||||
|
|
||||
|
<!-- Display account header --> |
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;"/> |
||||
|
<div class="act_as_caption account_title" |
||||
|
style="width: 100%;"> |
||||
|
<t t-set="res_model" t-value="'account.account'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="account.account_id.id" |
||||
|
t-att-data-res-model="res_model" |
||||
|
class="o_account_financial_reports_web_action" |
||||
|
t-att-style="style"> |
||||
|
<t t-raw="account.code"/> - <t t-raw="account.name"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="act_as_table data_table" |
||||
|
style="width: 100%;"> |
||||
|
<!-- Display account/partner header --> |
||||
|
<t t-call="account_financial_report.report_trial_balance_lines_header"/> |
||||
|
|
||||
|
<!-- Adapt style --> |
||||
|
<t t-set="padding" t-value="padding+4"/> |
||||
|
|
||||
|
<!-- Display each partners --> |
||||
|
<t t-foreach="account.partner_ids" t-as="line"> |
||||
|
<t t-set="type" t-value='"partner_type"'/> |
||||
|
<!-- Display partner line --> |
||||
|
<t t-call="account_financial_report.report_trial_balance_line"/> |
||||
|
</t> |
||||
|
<t t-set="padding" t-value="padding-4"/> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Display account footer --> |
||||
|
<t t-set="type" t-value='"account_type"'/> |
||||
|
<t t-call="account_financial_report.report_trial_balance_account_footer"/> |
||||
|
|
||||
|
</div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
<template id="account_financial_report.report_trial_balance_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 at 0 filter</div> |
||||
|
<div class="act_as_cell">Limit hierarchy levels</div> |
||||
|
</div> |
||||
|
<div class="act_as_row"> |
||||
|
<div class="act_as_cell"> |
||||
|
From: <span t-field="o.date_from"/> To: <span t-field="o.date_to"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.only_posted_moves">All posted entries</t> |
||||
|
<t t-if="not o.only_posted_moves">All entries</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.hide_account_at_0">Hide</t> |
||||
|
<t t-if="not o.hide_account_at_0">Show</t> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<t t-if="o.limit_hierarchy_level"> |
||||
|
Level <span t-field="o.show_hierarchy_level"/> |
||||
|
</t> |
||||
|
<t t-if="not o.limit_hierarchy_level"> |
||||
|
No limit |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report.report_trial_balance_lines_header"> |
||||
|
<!-- Display table headers for lines --> |
||||
|
<div class="act_as_thead"> |
||||
|
<div class="act_as_row labels"> |
||||
|
<t t-if="not show_partner_details"> |
||||
|
<!--## Code--> |
||||
|
<div class="act_as_cell" style="width: 8.86%;">Code</div> |
||||
|
<!--## Account--> |
||||
|
<div class="act_as_cell" style="width: 37.58%;">Account |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="show_partner_details"> |
||||
|
<!--## Partner--> |
||||
|
<div class="act_as_cell" style="width: 46.44%;">Partner |
||||
|
</div> |
||||
|
</t> |
||||
|
<!--## Initial balance--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">Initial |
||||
|
balance</div> |
||||
|
<!--## Debit--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">Debit</div> |
||||
|
<!--## Credit--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">Credit</div> |
||||
|
<!--## Period balance--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">Period balance</div> |
||||
|
<!--## Ending balance--> |
||||
|
<div class="act_as_cell" style="width: 9.64%;">Ending balance</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" style="width: 4.43%;">Cur.</div> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell" style="width: 8.86%;">Initial blance cur.</div> |
||||
|
<div class="act_as_cell" style="width: 8.86%;">Ending blance cur.</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report.report_trial_balance_line"> |
||||
|
<!-- # line --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<t t-if="not show_partner_details"> |
||||
|
<!--## Code--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="res_model" t-value="'account.account'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.account_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="line.code"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="res_model" t-value="'account.group'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.account_group_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="line.code"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<!--## Account/Partner--> |
||||
|
<div class="act_as_cell left"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t t-set="account_or_partner_line" t-value="line"/> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="res_model" t-value="'account.account'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.account_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="line.name"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="res_model" t-value="'account.group'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.account_group_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="line.name"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="account_or_partner_line" t-value="line.report_account_id"/> |
||||
|
<t t-set="res_model" t-value="'res.partner'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="line.partner_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="line.name"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## Initial balance--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.account_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d'))]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', 'in', line.compute_account_ids.ids), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d'))]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.report_account_id.account_id.id), |
||||
|
('partner_id', '=', line.partner_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d'))]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## Debit--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.account_id.id), |
||||
|
('date', '>=', line.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', 'in', line.compute_account_ids.ids), |
||||
|
('date', '>=', line.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.report_account_id.account_id.id), |
||||
|
('partner_id', '=', line.partner_id.id), |
||||
|
('date', '>=', line.report_account_id.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_account_id.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" 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-if="type == 'account_type'"> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.account_id.id), |
||||
|
('date', '>=', line.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', 'in', line.compute_account_ids.ids), |
||||
|
('date', '>=', line.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.report_account_id.account_id.id), |
||||
|
('partner_id', '=', line.partner_id.id), |
||||
|
('date', '>=', line.report_account_id.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_account_id.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## Period balance--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.account_id.id), |
||||
|
('date', '>=', line.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_id.date_to.strftime('%Y-%m-%d'))]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.period_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', 'in', line.compute_account_ids.ids), |
||||
|
('date', '>=', line.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_id.date_to.strftime('%Y-%m-%d'))]"/> |
||||
|
<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="line.period_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.report_account_id.account_id.id), |
||||
|
('partner_id', '=', line.partner_id.id), |
||||
|
('date', '>=', line.report_account_id.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', line.report_account_id.report_id.date_to.strftime('%Y-%m-%d'))]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.period_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## Ending balance--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.account_id.id)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', 'in', line.compute_account_ids.ids)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.report_account_id.account_id.id), |
||||
|
('partner_id', '=', line.partner_id.id)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t t-if="account_or_partner_line.currency_id"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" style="width: 4.43%;"> |
||||
|
<span t-field="account_or_partner_line.currency_id.display_name"/> |
||||
|
</div> |
||||
|
<!--## Initial balance cur.--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.account_id.id)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', 'in', line.compute_account_ids.ids)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.report_account_id.account_id.id), |
||||
|
('partner_id', '=', line.partner_id.id)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': line.report_account_id.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
<!--## Ending balance cur.--> |
||||
|
<div class="act_as_cell amount"> |
||||
|
<t t-if="type == 'account_type'"> |
||||
|
<t t-if="line.account_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.account_id.id)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
<t t-if="line.account_group_id"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', 'in', line.compute_account_ids.ids)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</t> |
||||
|
<t t-if="type == 'partner_type'"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', line.report_account_id.account_id.id), |
||||
|
('partner_id', '=', line.partner_id.id)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="line.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': line.report_account_id.currency_id}"/></a> |
||||
|
</span> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not account_or_partner_line.currency_id.id"> |
||||
|
<!--## balance_currency--> |
||||
|
<div class="act_as_cell"/> |
||||
|
<div class="act_as_cell"/> |
||||
|
<div class="act_as_cell"/> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report.report_trial_balance_account_footer"> |
||||
|
<!-- Display account footer --> |
||||
|
<div class="act_as_table list_table" style="width: 100%;"> |
||||
|
<div class="act_as_row labels" style="font-weight: bold;"> |
||||
|
<!--## Account--> |
||||
|
<div class="act_as_cell left" style="width: 61.44%;"> |
||||
|
<t t-set="res_model" t-value="'account.account'"/> |
||||
|
<span> |
||||
|
<a t-att-data-active-id="account.account_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="account.code"/> - <t t-att-style="style" t-raw="account.name"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## Initial balance--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account.account_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d'))]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="account.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## Debit--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account.account_id.id), |
||||
|
('date', '>=', account.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', account.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="account.debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## Credit--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account.account_id.id), |
||||
|
('date', '>=', account.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', account.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="account.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## Period Balance --> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account.account_id.id), |
||||
|
('date', '>=', account.report_id.date_from.strftime('%Y-%m-%d')), |
||||
|
('date', '<=', account.report_id.date_to.strftime('%Y-%m-%d')), |
||||
|
('period_balance', '<>', 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" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="account.period_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<!--## Ending balance--> |
||||
|
<div class="act_as_cell amount" style="width: 9.64%;"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account.account_id.id)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style" > |
||||
|
<t t-att-style="style" t-raw="account.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<t t-if="foreign_currency"> |
||||
|
<t t-if="account.currency_id.id"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" style="width: 4.43%;"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account.account_id.id)]"/> |
||||
|
<span t-field="account.currency_id.display_name"/> |
||||
|
</div> |
||||
|
<!--## balance_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 8.86%;"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account.account_id.id), |
||||
|
('date', '<', o.date_from.strftime('%Y-%m-%d'))]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style"> |
||||
|
<t t-att-style="style" t-raw="account.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account.account_id.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
<div class="act_as_cell amount" style="width: 8.86%;"> |
||||
|
<t t-set="domain" |
||||
|
t-value="[('account_id', '=', account.account_id.id)]"/> |
||||
|
<span> |
||||
|
<a t-att-data-domain="domain" |
||||
|
t-att-data-res-model="'account.move.line'" |
||||
|
class="o_account_financial_reports_web_action_monetary_multi" |
||||
|
t-att-style="style" > |
||||
|
<t t-att-style="style" t-raw="account.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account.account_id.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
</t> |
||||
|
<t t-if="not account.currency_id.id"> |
||||
|
<div class="act_as_cell" style="width: 4.43%;"/> |
||||
|
<div class="act_as_cell" style="width: 8.86%;"/> |
||||
|
<div class="act_as_cell" style="width: 8.86%;"/> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,167 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="account_financial_report.report_vat_report_qweb"> |
||||
|
<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="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t> |
||||
|
<t t-set="company_name" t-value="o.company_id.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="o.taxtags_ids" t-as="tag"> |
||||
|
<div class="act_as_row lines" style="font-weight: bold;"> |
||||
|
<t t-if="tag.taxtag_id"> |
||||
|
<t t-set="res_model" t-value="'account.account.tag'"/> |
||||
|
<t t-set="res_id" t-value="tag.taxtag_id.id"/> |
||||
|
</t> |
||||
|
<t t-if="tag.taxgroup_id"> |
||||
|
<t t-set="res_model" t-value="'account.tax.group'"/> |
||||
|
<t t-set="res_id" t-value="tag.taxgroup_id.id"/> |
||||
|
</t> |
||||
|
<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.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.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.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.tax" |
||||
|
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a> |
||||
|
</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<t t-if="o.tax_detail"> |
||||
|
<t t-foreach="tag.tax_ids" t-as="tax"> |
||||
|
<t t-set="res_model" t-value="'account.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-field="o.date_from"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<span t-field="o.date_to"/> |
||||
|
</div> |
||||
|
<div class="act_as_cell"> |
||||
|
<span t-field="o.based_on"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</odoo> |
@ -0,0 +1,589 @@ |
|||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# © 2018 Forest and Biomass Romania SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import models, fields, api |
||||
|
from odoo.tools import float_is_zero |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReport(models.TransientModel): |
||||
|
""" Here, we just define class fields. |
||||
|
For methods, go more bottom at this file. |
||||
|
|
||||
|
The class hierarchy is : |
||||
|
* TrialBalanceReport |
||||
|
*** TrialBalanceReportAccount |
||||
|
**** TrialBalanceReportPartner |
||||
|
If "show_partner_details" is selected |
||||
|
""" |
||||
|
|
||||
|
_name = 'report_trial_balance' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
# Filters fields, used for data computation |
||||
|
date_from = fields.Date() |
||||
|
date_to = fields.Date() |
||||
|
fy_start_date = fields.Date() |
||||
|
only_posted_moves = fields.Boolean() |
||||
|
hide_account_at_0 = fields.Boolean() |
||||
|
foreign_currency = fields.Boolean() |
||||
|
company_id = fields.Many2one(comodel_name='res.company') |
||||
|
filter_account_ids = fields.Many2many(comodel_name='account.account') |
||||
|
filter_partner_ids = fields.Many2many(comodel_name='res.partner') |
||||
|
filter_journal_ids = fields.Many2many(comodel_name='account.journal') |
||||
|
show_partner_details = fields.Boolean() |
||||
|
hierarchy_on = fields.Selection( |
||||
|
[('computed', 'Computed Accounts'), |
||||
|
('relation', 'Child Accounts'), |
||||
|
('none', 'No hierarchy')], |
||||
|
string='Hierarchy On', |
||||
|
required=True, |
||||
|
default='computed', |
||||
|
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) |
||||
|
# General Ledger Report Data fields, |
||||
|
# used as base for compute the data reports |
||||
|
general_ledger_id = fields.Many2one( |
||||
|
comodel_name='report_general_ledger' |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
account_ids = fields.One2many( |
||||
|
comodel_name='report_trial_balance_account', |
||||
|
inverse_name='report_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReportAccount(models.TransientModel): |
||||
|
_name = 'report_trial_balance_account' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
_order = 'sequence, code ASC, name' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_trial_balance', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
hide_line = fields.Boolean(compute='_compute_hide_line') |
||||
|
# Data fields, used to keep link with real object. |
||||
|
# Sequence is a Char later built with 'parent_path' for groups |
||||
|
# and parent_path + account code for accounts |
||||
|
sequence = fields.Char(index=True, default='1') |
||||
|
level = fields.Integer(index=True, default=1) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
account_id = fields.Many2one( |
||||
|
'account.account', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
account_group_id = fields.Many2one( |
||||
|
'account.group', |
||||
|
index=True |
||||
|
) |
||||
|
parent_id = fields.Many2one( |
||||
|
'account.group', |
||||
|
index=True |
||||
|
) |
||||
|
child_account_ids = fields.Char( |
||||
|
string="Child accounts") |
||||
|
compute_account_ids = fields.Many2many( |
||||
|
'account.account', |
||||
|
string="Compute accounts", store=True) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
code = fields.Char() |
||||
|
name = fields.Char() |
||||
|
|
||||
|
currency_id = fields.Many2one('res.currency') |
||||
|
initial_balance = fields.Float(digits=(16, 2)) |
||||
|
initial_balance_foreign_currency = fields.Float(digits=(16, 2)) |
||||
|
debit = fields.Float(digits=(16, 2)) |
||||
|
credit = fields.Float(digits=(16, 2)) |
||||
|
period_balance = fields.Float(digits=(16, 2)) |
||||
|
final_balance = fields.Float(digits=(16, 2)) |
||||
|
final_balance_foreign_currency = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
partner_ids = fields.One2many( |
||||
|
comodel_name='report_trial_balance_partner', |
||||
|
inverse_name='report_account_id' |
||||
|
) |
||||
|
|
||||
|
@api.depends( |
||||
|
'currency_id', |
||||
|
'report_id', |
||||
|
'report_id.hide_account_at_0', |
||||
|
'report_id.limit_hierarchy_level', |
||||
|
'report_id.show_hierarchy_level', |
||||
|
'initial_balance', |
||||
|
'final_balance', |
||||
|
'debit', |
||||
|
'credit', |
||||
|
) |
||||
|
def _compute_hide_line(self): |
||||
|
for rec in self: |
||||
|
report = rec.report_id |
||||
|
r = (rec.currency_id or report.company_id.currency_id).rounding |
||||
|
if report.hide_account_at_0 and ( |
||||
|
float_is_zero(rec.initial_balance, precision_rounding=r) |
||||
|
and float_is_zero(rec.final_balance, precision_rounding=r) |
||||
|
and float_is_zero(rec.debit, precision_rounding=r) |
||||
|
and float_is_zero(rec.credit, precision_rounding=r)): |
||||
|
rec.hide_line = True |
||||
|
elif report.limit_hierarchy_level and report.show_hierarchy_level: |
||||
|
if report.hide_parent_hierarchy_level: |
||||
|
distinct_level = rec.level != report.show_hierarchy_level |
||||
|
if rec.account_group_id and distinct_level: |
||||
|
rec.hide_line = True |
||||
|
elif rec.level and distinct_level: |
||||
|
rec.hide_line = True |
||||
|
elif not report.hide_parent_hierarchy_level and \ |
||||
|
rec.level > report.show_hierarchy_level: |
||||
|
rec.hide_line = True |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReportPartner(models.TransientModel): |
||||
|
_name = 'report_trial_balance_partner' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
|
||||
|
report_account_id = fields.Many2one( |
||||
|
comodel_name='report_trial_balance_account', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
partner_id = fields.Many2one( |
||||
|
'res.partner', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
name = fields.Char() |
||||
|
|
||||
|
currency_id = fields.Many2one('res.currency') |
||||
|
initial_balance = fields.Float(digits=(16, 2)) |
||||
|
initial_balance_foreign_currency = fields.Float(digits=(16, 2)) |
||||
|
debit = fields.Float(digits=(16, 2)) |
||||
|
credit = fields.Float(digits=(16, 2)) |
||||
|
period_balance = fields.Float(digits=(16, 2)) |
||||
|
final_balance = fields.Float(digits=(16, 2)) |
||||
|
final_balance_foreign_currency = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
@api.model |
||||
|
def _generate_order_by(self, order_spec, query): |
||||
|
"""Custom order to display "No partner allocated" at last position.""" |
||||
|
return """ |
||||
|
ORDER BY |
||||
|
CASE |
||||
|
WHEN "report_trial_balance_partner"."partner_id" IS NOT NULL |
||||
|
THEN 0 |
||||
|
ELSE 1 |
||||
|
END, |
||||
|
"report_trial_balance_partner"."name" |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReportCompute(models.TransientModel): |
||||
|
""" Here, we just define methods. |
||||
|
For class fields, go more top at this file. |
||||
|
""" |
||||
|
|
||||
|
_inherit = 'report_trial_balance' |
||||
|
|
||||
|
@api.multi |
||||
|
def print_report(self, report_type): |
||||
|
self.ensure_one() |
||||
|
if report_type == 'xlsx': |
||||
|
report_name = 'a_f_r.report_trial_balance_xlsx' |
||||
|
else: |
||||
|
report_name = 'account_financial_report.' \ |
||||
|
'report_trial_balance_qweb' |
||||
|
return self.env['ir.actions.report'].search( |
||||
|
[('report_name', '=', report_name), |
||||
|
('report_type', '=', report_type)], |
||||
|
limit=1).report_action(self, config=False) |
||||
|
|
||||
|
def _get_html(self): |
||||
|
result = {} |
||||
|
rcontext = {} |
||||
|
context = dict(self.env.context) |
||||
|
report = self.browse(context.get('active_id')) |
||||
|
if report: |
||||
|
rcontext['o'] = report |
||||
|
result['html'] = self.env.ref( |
||||
|
'account_financial_report.report_trial_balance').render( |
||||
|
rcontext) |
||||
|
return result |
||||
|
|
||||
|
@api.model |
||||
|
def get_html(self, given_context=None): |
||||
|
return self._get_html() |
||||
|
|
||||
|
def _prepare_report_general_ledger(self, account_ids): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
'date_from': self.date_from, |
||||
|
'date_to': self.date_to, |
||||
|
'only_posted_moves': self.only_posted_moves, |
||||
|
# This is postprocessed later with a computed field |
||||
|
'hide_account_at_0': False, |
||||
|
'foreign_currency': self.foreign_currency, |
||||
|
'company_id': self.company_id.id, |
||||
|
'filter_account_ids': [(6, 0, account_ids.ids)], |
||||
|
'filter_partner_ids': [(6, 0, self.filter_partner_ids.ids)], |
||||
|
'filter_journal_ids': [(6, 0, self.filter_journal_ids.ids)], |
||||
|
'fy_start_date': self.fy_start_date, |
||||
|
} |
||||
|
|
||||
|
@api.multi |
||||
|
def compute_data_for_report(self): |
||||
|
self.ensure_one() |
||||
|
# Compute General Ledger Report Data. |
||||
|
# The data of Trial Balance Report |
||||
|
# are based on General Ledger Report data. |
||||
|
model = self.env['report_general_ledger'] |
||||
|
if self.filter_account_ids: |
||||
|
account_ids = self.filter_account_ids |
||||
|
else: |
||||
|
account_ids = self.env['account.account'].search( |
||||
|
[('company_id', '=', self.company_id.id)]) |
||||
|
self.general_ledger_id = model.create( |
||||
|
self._prepare_report_general_ledger(account_ids) |
||||
|
) |
||||
|
self.general_ledger_id.compute_data_for_report( |
||||
|
with_line_details=False, with_partners=self.show_partner_details |
||||
|
) |
||||
|
|
||||
|
# Compute report data |
||||
|
self._inject_account_values(account_ids) |
||||
|
if self.show_partner_details: |
||||
|
self._inject_partner_values() |
||||
|
if not self.filter_account_ids: |
||||
|
if self.hierarchy_on != 'none': |
||||
|
self._inject_account_group_values() |
||||
|
if self.hierarchy_on == 'computed': |
||||
|
self._update_account_group_computed_values() |
||||
|
else: |
||||
|
self._update_account_group_child_values() |
||||
|
self._update_account_sequence() |
||||
|
self._add_account_group_account_values() |
||||
|
self.refresh() |
||||
|
if not self.filter_account_ids and self.hierarchy_on != 'none': |
||||
|
self._compute_group_accounts() |
||||
|
else: |
||||
|
for line in self.account_ids: |
||||
|
line.write({'level': 0}) |
||||
|
|
||||
|
def _inject_account_values(self, account_ids): |
||||
|
"""Inject report values for report_trial_balance_account""" |
||||
|
query_inject_account = """ |
||||
|
INSERT INTO |
||||
|
report_trial_balance_account |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
account_id, |
||||
|
parent_id, |
||||
|
code, |
||||
|
name, |
||||
|
initial_balance, |
||||
|
debit, |
||||
|
credit, |
||||
|
period_balance, |
||||
|
final_balance, |
||||
|
currency_id, |
||||
|
initial_balance_foreign_currency, |
||||
|
final_balance_foreign_currency |
||||
|
) |
||||
|
SELECT |
||||
|
%s AS report_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
acc.id, |
||||
|
acc.group_id, |
||||
|
acc.code, |
||||
|
acc.name, |
||||
|
coalesce(rag.initial_balance, 0) AS initial_balance, |
||||
|
coalesce(rag.final_debit - rag.initial_debit, 0) AS debit, |
||||
|
coalesce(rag.final_credit - rag.initial_credit, 0) AS credit, |
||||
|
coalesce(rag.final_balance - rag.initial_balance, 0) AS period_balance, |
||||
|
coalesce(rag.final_balance, 0) AS final_balance, |
||||
|
rag.currency_id AS currency_id, |
||||
|
coalesce(rag.initial_balance_foreign_currency, 0) |
||||
|
AS initial_balance_foreign_currency, |
||||
|
coalesce(rag.final_balance_foreign_currency, 0) |
||||
|
AS final_balance_foreign_currency |
||||
|
FROM |
||||
|
account_account acc |
||||
|
LEFT OUTER JOIN report_general_ledger_account AS rag |
||||
|
ON rag.account_id = acc.id AND rag.report_id = %s |
||||
|
WHERE |
||||
|
acc.id in %s |
||||
|
""" |
||||
|
query_inject_account_params = ( |
||||
|
self.id, |
||||
|
self.env.uid, |
||||
|
self.general_ledger_id.id, |
||||
|
account_ids._ids, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_account, query_inject_account_params) |
||||
|
|
||||
|
def _inject_partner_values(self): |
||||
|
"""Inject report values for report_trial_balance_partner""" |
||||
|
query_inject_partner = """ |
||||
|
INSERT INTO |
||||
|
report_trial_balance_partner |
||||
|
( |
||||
|
report_account_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
partner_id, |
||||
|
name, |
||||
|
initial_balance, |
||||
|
initial_balance_foreign_currency, |
||||
|
debit, |
||||
|
credit, |
||||
|
period_balance, |
||||
|
final_balance, |
||||
|
final_balance_foreign_currency |
||||
|
) |
||||
|
SELECT |
||||
|
ra.id AS report_account_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
rpg.partner_id, |
||||
|
rpg.name, |
||||
|
rpg.initial_balance AS initial_balance, |
||||
|
rpg.initial_balance_foreign_currency AS initial_balance_foreign_currency, |
||||
|
rpg.final_debit - rpg.initial_debit AS debit, |
||||
|
rpg.final_credit - rpg.initial_credit AS credit, |
||||
|
rpg.final_balance - rpg.initial_balance AS period_balance, |
||||
|
rpg.final_balance AS final_balance, |
||||
|
rpg.final_balance_foreign_currency AS final_balance_foreign_currency |
||||
|
FROM |
||||
|
report_general_ledger_partner rpg |
||||
|
INNER JOIN |
||||
|
report_general_ledger_account rag ON rpg.report_account_id = rag.id |
||||
|
INNER JOIN |
||||
|
report_trial_balance_account ra ON rag.code = ra.code |
||||
|
WHERE |
||||
|
rag.report_id = %s |
||||
|
AND ra.report_id = %s |
||||
|
""" |
||||
|
query_inject_partner_params = ( |
||||
|
self.env.uid, |
||||
|
self.general_ledger_id.id, |
||||
|
self.id, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_partner, query_inject_partner_params) |
||||
|
|
||||
|
def _inject_account_group_values(self): |
||||
|
"""Inject report values for report_trial_balance_account""" |
||||
|
query_inject_account_group = """ |
||||
|
INSERT INTO |
||||
|
report_trial_balance_account |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
account_group_id, |
||||
|
parent_id, |
||||
|
code, |
||||
|
name, |
||||
|
sequence, |
||||
|
level |
||||
|
) |
||||
|
SELECT |
||||
|
%s AS report_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
accgroup.id, |
||||
|
accgroup.parent_id, |
||||
|
coalesce(accgroup.code_prefix, accgroup.name), |
||||
|
accgroup.name, |
||||
|
accgroup.parent_path, |
||||
|
accgroup.level |
||||
|
FROM |
||||
|
account_group accgroup""" |
||||
|
query_inject_account_params = ( |
||||
|
self.id, |
||||
|
self.env.uid, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_account_group, |
||||
|
query_inject_account_params) |
||||
|
|
||||
|
def _update_account_group_child_values(self): |
||||
|
"""Compute values for report_trial_balance_account group in child.""" |
||||
|
query_update_account_group = """ |
||||
|
WITH computed AS (WITH RECURSIVE cte AS ( |
||||
|
SELECT account_group_id, code, account_group_id AS parent_id, |
||||
|
initial_balance, initial_balance_foreign_currency, debit, credit, |
||||
|
period_balance, final_balance, final_balance_foreign_currency |
||||
|
FROM report_trial_balance_account |
||||
|
WHERE report_id = %s |
||||
|
GROUP BY report_trial_balance_account.id |
||||
|
|
||||
|
UNION ALL |
||||
|
SELECT c.account_group_id, c.code, p.account_group_id, |
||||
|
p.initial_balance, p.initial_balance_foreign_currency, p.debit, p.credit, |
||||
|
p.period_balance, p.final_balance, p.final_balance_foreign_currency |
||||
|
FROM cte c |
||||
|
JOIN report_trial_balance_account p USING (parent_id) |
||||
|
WHERE p.report_id = %s |
||||
|
) |
||||
|
SELECT account_group_id, code, |
||||
|
sum(initial_balance) AS initial_balance, |
||||
|
sum(initial_balance_foreign_currency) AS initial_balance_foreign_currency, |
||||
|
sum(debit) AS debit, |
||||
|
sum(credit) AS credit, |
||||
|
sum(debit) - sum(credit) AS period_balance, |
||||
|
sum(final_balance) AS final_balance, |
||||
|
sum(final_balance_foreign_currency) AS final_balance_foreign_currency |
||||
|
FROM cte |
||||
|
GROUP BY cte.account_group_id, cte.code |
||||
|
ORDER BY account_group_id |
||||
|
) |
||||
|
UPDATE report_trial_balance_account |
||||
|
SET initial_balance = computed.initial_balance, |
||||
|
initial_balance_foreign_currency = |
||||
|
computed.initial_balance_foreign_currency, |
||||
|
debit = computed.debit, |
||||
|
credit = computed.credit, |
||||
|
period_balance = computed.period_balance, |
||||
|
final_balance = computed.final_balance, |
||||
|
final_balance_foreign_currency = |
||||
|
computed.final_balance_foreign_currency |
||||
|
FROM computed |
||||
|
WHERE report_trial_balance_account.account_group_id = computed.account_group_id |
||||
|
AND report_trial_balance_account.report_id = %s |
||||
|
""" |
||||
|
query_update_account_params = (self.id, self.id, self.id,) |
||||
|
self.env.cr.execute(query_update_account_group, |
||||
|
query_update_account_params) |
||||
|
|
||||
|
def _add_account_group_account_values(self): |
||||
|
"""Compute values for report_trial_balance_account group in child.""" |
||||
|
query_update_account_group = """ |
||||
|
DROP AGGREGATE IF EXISTS array_concat_agg(anyarray); |
||||
|
CREATE AGGREGATE array_concat_agg(anyarray) ( |
||||
|
SFUNC = array_cat, |
||||
|
STYPE = anyarray |
||||
|
); |
||||
|
WITH aggr AS(WITH computed AS (WITH RECURSIVE cte AS ( |
||||
|
SELECT account_group_id, account_group_id AS parent_id, |
||||
|
ARRAY[account_id]::int[] as child_account_ids |
||||
|
FROM report_trial_balance_account |
||||
|
WHERE report_id = %s |
||||
|
GROUP BY report_trial_balance_account.id |
||||
|
|
||||
|
UNION ALL |
||||
|
SELECT c.account_group_id, p.account_group_id, ARRAY[p.account_id]::int[] |
||||
|
FROM cte c |
||||
|
JOIN report_trial_balance_account p USING (parent_id) |
||||
|
WHERE p.report_id = %s |
||||
|
) |
||||
|
SELECT account_group_id, |
||||
|
array_concat_agg(DISTINCT child_account_ids)::int[] as child_account_ids |
||||
|
FROM cte |
||||
|
GROUP BY cte.account_group_id, cte.child_account_ids |
||||
|
ORDER BY account_group_id |
||||
|
) |
||||
|
SELECT account_group_id, |
||||
|
array_concat_agg(DISTINCT child_account_ids)::int[] |
||||
|
AS child_account_ids from computed |
||||
|
GROUP BY account_group_id) |
||||
|
UPDATE report_trial_balance_account |
||||
|
SET child_account_ids = aggr.child_account_ids |
||||
|
FROM aggr |
||||
|
WHERE report_trial_balance_account.account_group_id = aggr.account_group_id |
||||
|
AND report_trial_balance_account.report_id = %s |
||||
|
""" |
||||
|
query_update_account_params = (self.id, self.id, self.id,) |
||||
|
self.env.cr.execute(query_update_account_group, |
||||
|
query_update_account_params) |
||||
|
|
||||
|
def _update_account_group_computed_values(self): |
||||
|
"""Compute values for report_trial_balance_account group in compute.""" |
||||
|
query_update_account_group = """ |
||||
|
WITH RECURSIVE accgroup AS |
||||
|
(SELECT |
||||
|
accgroup.id, |
||||
|
sum(coalesce(ra.initial_balance, 0)) as initial_balance, |
||||
|
sum(coalesce(ra.initial_balance_foreign_currency, 0)) |
||||
|
as initial_balance_foreign_currency, |
||||
|
sum(coalesce(ra.debit, 0)) as debit, |
||||
|
sum(coalesce(ra.credit, 0)) as credit, |
||||
|
sum(coalesce(ra.debit, 0)) - sum(coalesce(ra.credit, 0)) as period_balance, |
||||
|
sum(coalesce(ra.final_balance, 0)) as final_balance, |
||||
|
sum(coalesce(ra.final_balance_foreign_currency, 0)) |
||||
|
as final_balance_foreign_currency |
||||
|
FROM |
||||
|
account_group accgroup |
||||
|
LEFT OUTER JOIN account_account AS acc |
||||
|
ON strpos(acc.code, accgroup.code_prefix) = 1 |
||||
|
LEFT OUTER JOIN report_trial_balance_account AS ra |
||||
|
ON ra.account_id = acc.id |
||||
|
WHERE ra.report_id = %s |
||||
|
GROUP BY accgroup.id |
||||
|
) |
||||
|
UPDATE report_trial_balance_account |
||||
|
SET initial_balance = accgroup.initial_balance, |
||||
|
initial_balance_foreign_currency = |
||||
|
accgroup.initial_balance_foreign_currency, |
||||
|
debit = accgroup.debit, |
||||
|
credit = accgroup.credit, |
||||
|
period_balance = accgroup.period_balance, |
||||
|
final_balance = accgroup.final_balance, |
||||
|
final_balance_foreign_currency = |
||||
|
accgroup.final_balance_foreign_currency |
||||
|
|
||||
|
FROM accgroup |
||||
|
WHERE report_trial_balance_account.account_group_id = accgroup.id |
||||
|
""" |
||||
|
query_update_account_params = (self.id,) |
||||
|
self.env.cr.execute(query_update_account_group, |
||||
|
query_update_account_params) |
||||
|
|
||||
|
def _update_account_sequence(self): |
||||
|
"""Compute sequence, level for report_trial_balance_account account.""" |
||||
|
query_update_account_group = """ |
||||
|
UPDATE report_trial_balance_account |
||||
|
SET sequence = CONCAT(newline.sequence, newline.code), |
||||
|
level = newline.level + 1 |
||||
|
FROM report_trial_balance_account as newline |
||||
|
WHERE newline.account_group_id = report_trial_balance_account.parent_id |
||||
|
AND report_trial_balance_account.report_id = newline.report_id |
||||
|
AND report_trial_balance_account.account_id is not null |
||||
|
AND report_trial_balance_account.report_id = %s""" |
||||
|
query_update_account_params = (self.id,) |
||||
|
self.env.cr.execute(query_update_account_group, |
||||
|
query_update_account_params) |
||||
|
|
||||
|
def _compute_group_accounts(self): |
||||
|
groups = self.account_ids.filtered( |
||||
|
lambda a: a.account_group_id is not False) |
||||
|
for group in groups: |
||||
|
if self.hierarchy_on == 'computed': |
||||
|
group.compute_account_ids = \ |
||||
|
group.account_group_id.compute_account_ids |
||||
|
else: |
||||
|
if group.child_account_ids: |
||||
|
chacc = group.child_account_ids.replace( |
||||
|
'}', '').replace('{', '').split(',') |
||||
|
if 'NULL' in chacc: |
||||
|
chacc.remove('NULL') |
||||
|
if chacc: |
||||
|
group.compute_account_ids = [ |
||||
|
(6, 0, [int(g) for g in chacc])] |
@ -0,0 +1,192 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# 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' |
||||
|
_inherit = 'report.account_financial_report.abstract_report_xlsx' |
||||
|
|
||||
|
def _get_report_name(self, report): |
||||
|
report_name = _('Trial Balance') |
||||
|
return self._get_report_complete_name(report, 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': 'period_balance', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
6: {'header': _('Ending balance'), |
||||
|
'field': 'final_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_balance_foreign_currency', |
||||
|
'type': 'amount_currency', |
||||
|
'width': 14}, |
||||
|
9: {'header': _('Ending balance'), |
||||
|
'field': 'final_balance_foreign_currency', |
||||
|
'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': 'period_balance', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
5: {'header': _('Ending balance'), |
||||
|
'field': 'final_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_balance_foreign_currency', |
||||
|
'type': 'amount_currency', |
||||
|
'width': 14}, |
||||
|
8: {'header': _('Ending balance'), |
||||
|
'field': 'final_balance_foreign_currency', |
||||
|
'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.only_posted_moves 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): |
||||
|
|
||||
|
if not report.show_partner_details: |
||||
|
# Display array header for account lines |
||||
|
self.write_array_header() |
||||
|
|
||||
|
# For each account |
||||
|
for account in report.account_ids.filtered(lambda a: not a.hide_line): |
||||
|
if not report.show_partner_details: |
||||
|
# Display account lines |
||||
|
self.write_line(account, 'account') |
||||
|
|
||||
|
else: |
||||
|
# Write account title |
||||
|
self.write_array_title(account.code + ' - ' + account.name) |
||||
|
|
||||
|
# Display array header for partner lines |
||||
|
self.write_array_header() |
||||
|
|
||||
|
# For each partner |
||||
|
for partner in account.partner_ids: |
||||
|
# Display partner lines |
||||
|
self.write_line(partner, 'partner') |
||||
|
|
||||
|
# Display account footer line |
||||
|
self.write_account_footer(account, |
||||
|
account.code + ' - ' + account.name) |
||||
|
|
||||
|
# Line break |
||||
|
self.row_pos += 2 |
||||
|
|
||||
|
def write_line(self, line_object, type_object): |
||||
|
"""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) |
||||
|
|
||||
|
def write_account_footer(self, account, name_value): |
||||
|
"""Specific function to write account footer for Trial Balance""" |
||||
|
format_amt = self._get_currency_amt_header_format(account) |
||||
|
for col_pos, column in self.columns.items(): |
||||
|
if column['field'] == 'name': |
||||
|
value = name_value |
||||
|
else: |
||||
|
value = getattr(account, column['field']) |
||||
|
cell_type = column.get('type', 'string') |
||||
|
if cell_type == 'string': |
||||
|
self.sheet.write_string(self.row_pos, col_pos, value or '', |
||||
|
self.format_header_left) |
||||
|
elif cell_type == 'amount': |
||||
|
self.sheet.write_number(self.row_pos, col_pos, float(value), |
||||
|
self.format_header_amount) |
||||
|
elif cell_type == 'many2one': |
||||
|
self.sheet.write_string( |
||||
|
self.row_pos, col_pos, value.name or '', |
||||
|
self.format_header_right) |
||||
|
elif cell_type == 'amount_currency' and account.currency_id: |
||||
|
self.sheet.write_number( |
||||
|
self.row_pos, col_pos, float(value), |
||||
|
format_amt) |
||||
|
else: |
||||
|
self.sheet.write_string( |
||||
|
self.row_pos, col_pos, '', |
||||
|
self.format_header_right) |
||||
|
self.row_pos += 1 |
@ -0,0 +1,356 @@ |
|||||
|
# 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 |
||||
|
|
||||
|
|
||||
|
class VATReport(models.TransientModel): |
||||
|
_name = "report_vat_report" |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
""" Here, we just define class fields. |
||||
|
For methods, go more bottom at this file. |
||||
|
|
||||
|
The class hierarchy is : |
||||
|
* VATReport |
||||
|
** VATReportTaxTags |
||||
|
*** VATReportTax |
||||
|
""" |
||||
|
|
||||
|
# Filters fields, used for data computation |
||||
|
company_id = fields.Many2one(comodel_name='res.company') |
||||
|
date_from = fields.Date() |
||||
|
date_to = fields.Date() |
||||
|
based_on = fields.Selection([('taxtags', 'Tax Tags'), |
||||
|
('taxgroups', 'Tax Groups')], |
||||
|
string='Based On', |
||||
|
required=True, |
||||
|
default='taxtags') |
||||
|
tax_detail = fields.Boolean('Tax Detail') |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
taxtags_ids = fields.One2many( |
||||
|
comodel_name='report_vat_report_taxtag', |
||||
|
inverse_name='report_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class VATReportTaxTags(models.TransientModel): |
||||
|
_name = 'report_vat_report_taxtag' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
_order = 'code ASC' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_vat_report', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
taxtag_id = fields.Many2one( |
||||
|
'account.account.tag', |
||||
|
index=True |
||||
|
) |
||||
|
taxgroup_id = fields.Many2one( |
||||
|
'account.tax.group', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
code = fields.Char() |
||||
|
name = fields.Char() |
||||
|
net = fields.Float(digits=(16, 2)) |
||||
|
tax = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
tax_ids = fields.One2many( |
||||
|
comodel_name='report_vat_report_tax', |
||||
|
inverse_name='report_tax_id', |
||||
|
string='Taxes' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class VATReportTax(models.TransientModel): |
||||
|
_name = 'report_vat_report_tax' |
||||
|
_inherit = 'account_financial_report_abstract' |
||||
|
_order = 'name ASC' |
||||
|
|
||||
|
report_tax_id = fields.Many2one( |
||||
|
comodel_name='report_vat_report_taxtag', |
||||
|
ondelete='cascade', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
tax_id = fields.Many2one( |
||||
|
'account.tax', |
||||
|
index=True, |
||||
|
string='Tax ID', |
||||
|
) |
||||
|
|
||||
|
# Data fields, used for report display |
||||
|
code = fields.Char() |
||||
|
name = fields.Char() |
||||
|
net = fields.Float(digits=(16, 2)) |
||||
|
tax = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
|
||||
|
class VATReportCompute(models.TransientModel): |
||||
|
""" Here, we just define methods. |
||||
|
For class fields, go more top at this file. |
||||
|
""" |
||||
|
|
||||
|
_inherit = 'report_vat_report' |
||||
|
|
||||
|
@api.multi |
||||
|
def print_report(self, report_type='qweb'): |
||||
|
self.ensure_one() |
||||
|
if report_type == 'xlsx': |
||||
|
report_name = 'a_f_r.report_vat_report_xlsx' |
||||
|
else: |
||||
|
report_name = 'account_financial_report.report_vat_report_qweb' |
||||
|
context = dict(self.env.context) |
||||
|
action = self.env['ir.actions.report'].search( |
||||
|
[('report_name', '=', report_name), |
||||
|
('report_type', '=', report_type)], limit=1) |
||||
|
return action.with_context(context).report_action(self, config=False) |
||||
|
|
||||
|
def _get_html(self): |
||||
|
result = {} |
||||
|
rcontext = {} |
||||
|
context = dict(self.env.context) |
||||
|
report = self.browse(context.get('active_id')) |
||||
|
if report: |
||||
|
rcontext['o'] = report |
||||
|
result['html'] = self.env.ref( |
||||
|
'account_financial_report.report_vat_report').render( |
||||
|
rcontext) |
||||
|
return result |
||||
|
|
||||
|
@api.model |
||||
|
def get_html(self, given_context=None): |
||||
|
return self.with_context(given_context)._get_html() |
||||
|
|
||||
|
@api.multi |
||||
|
def compute_data_for_report(self): |
||||
|
self.ensure_one() |
||||
|
# Compute report data |
||||
|
if self.based_on == 'taxtags': |
||||
|
self._inject_taxtags_values() |
||||
|
self._inject_tax_taxtags_values() |
||||
|
elif self.based_on == 'taxgroups': |
||||
|
self._inject_taxgroups_values() |
||||
|
self._inject_tax_taxgroups_values() |
||||
|
# Refresh cache because all data are computed with SQL requests |
||||
|
self.refresh() |
||||
|
|
||||
|
def _inject_taxtags_values(self): |
||||
|
"""Inject report values for report_vat_report_taxtags.""" |
||||
|
query_inject_taxtags = """ |
||||
|
WITH |
||||
|
taxtags AS |
||||
|
(SELECT coalesce(regexp_replace(tag.name, |
||||
|
'[^0-9\\.]+', '', 'g'), ' ') AS code, |
||||
|
tag.name, tag.id, |
||||
|
coalesce(sum(movetax.tax_base_amount), 0.00) AS net, |
||||
|
coalesce(sum(movetax.balance), 0.00) AS tax |
||||
|
FROM |
||||
|
account_account_tag AS tag |
||||
|
INNER JOIN account_tax_account_tag AS taxtag |
||||
|
ON tag.id = taxtag.account_account_tag_id |
||||
|
INNER JOIN account_tax AS tax |
||||
|
ON tax.id = taxtag.account_tax_id |
||||
|
INNER JOIN account_move_line AS movetax |
||||
|
ON movetax.tax_line_id = tax.id |
||||
|
INNER JOIN account_move AS move |
||||
|
ON move.id = movetax.move_id |
||||
|
WHERE tag.id is not null AND movetax.tax_exigible |
||||
|
AND move.company_id = %s AND move.date >= %s |
||||
|
AND move.date <= %s AND move.state = 'posted' |
||||
|
GROUP BY tag.id |
||||
|
ORDER BY code, tag.name |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_vat_report_taxtag |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
taxtag_id, |
||||
|
code, |
||||
|
name, |
||||
|
net, tax |
||||
|
) |
||||
|
SELECT |
||||
|
%s AS report_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
tag.id, |
||||
|
tag.code, |
||||
|
tag.name, |
||||
|
abs(tag.net), |
||||
|
abs(tag.tax) |
||||
|
FROM |
||||
|
taxtags tag |
||||
|
""" |
||||
|
query_inject_taxtags_params = (self.company_id.id, self.date_from, |
||||
|
self.date_to, self.id, self.env.uid) |
||||
|
self.env.cr.execute(query_inject_taxtags, query_inject_taxtags_params) |
||||
|
|
||||
|
def _inject_taxgroups_values(self): |
||||
|
"""Inject report values for report_vat_report_taxtags.""" |
||||
|
query_inject_taxgroups = """ |
||||
|
WITH |
||||
|
taxgroups AS |
||||
|
(SELECT coalesce(taxgroup.sequence, 0) AS code, |
||||
|
taxgroup.name, taxgroup.id, |
||||
|
coalesce(sum(movetax.tax_base_amount), 0.00) AS net, |
||||
|
coalesce(sum(movetax.balance), 0.00) AS tax |
||||
|
FROM |
||||
|
account_tax_group AS taxgroup |
||||
|
INNER JOIN account_tax AS tax |
||||
|
ON tax.tax_group_id = taxgroup.id |
||||
|
INNER JOIN account_move_line AS movetax |
||||
|
ON movetax.tax_line_id = tax.id |
||||
|
INNER JOIN account_move AS move |
||||
|
ON move.id = movetax.move_id |
||||
|
WHERE taxgroup.id is not null AND movetax.tax_exigible |
||||
|
AND move.company_id = %s AND move.date >= %s |
||||
|
AND move.date <= %s AND move.state = 'posted' |
||||
|
GROUP BY taxgroup.id |
||||
|
ORDER BY code, taxgroup.name |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_vat_report_taxtag |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
taxgroup_id, |
||||
|
code, |
||||
|
name, |
||||
|
net, tax |
||||
|
) |
||||
|
SELECT |
||||
|
%s AS report_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
groups.id, |
||||
|
groups.code, |
||||
|
groups.name, |
||||
|
abs(groups.net), |
||||
|
abs(groups.tax) |
||||
|
FROM |
||||
|
taxgroups groups |
||||
|
""" |
||||
|
query_inject_taxgroups_params = (self.company_id.id, self.date_from, |
||||
|
self.date_to, self.id, self.env.uid) |
||||
|
self.env.cr.execute(query_inject_taxgroups, |
||||
|
query_inject_taxgroups_params) |
||||
|
|
||||
|
def _inject_tax_taxtags_values(self): |
||||
|
""" Inject report values for report_vat_report_tax. """ |
||||
|
# pylint: disable=sql-injection |
||||
|
query_inject_tax = """ |
||||
|
WITH |
||||
|
taxtags_tax AS |
||||
|
( |
||||
|
SELECT |
||||
|
tag.id AS report_tax_id, ' ' AS code, |
||||
|
tax.name, tax.id, |
||||
|
coalesce(sum(movetax.tax_base_amount), 0.00) AS net, |
||||
|
coalesce(sum(movetax.balance), 0.00) AS tax |
||||
|
FROM |
||||
|
report_vat_report_taxtag AS tag |
||||
|
INNER JOIN account_tax_account_tag AS taxtag |
||||
|
ON tag.taxtag_id = taxtag.account_account_tag_id |
||||
|
INNER JOIN account_tax AS tax |
||||
|
ON tax.id = taxtag.account_tax_id |
||||
|
INNER JOIN account_move_line AS movetax |
||||
|
ON movetax.tax_line_id = tax.id |
||||
|
INNER JOIN account_move AS move |
||||
|
ON move.id = movetax.move_id |
||||
|
WHERE tag.id is not null AND movetax.tax_exigible |
||||
|
AND tag.report_id = %s AND move.company_id = %s |
||||
|
AND move.date >= %s AND move.date <= %s |
||||
|
AND move.state = 'posted' |
||||
|
GROUP BY tag.id, tax.id |
||||
|
ORDER BY tax.name |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_vat_report_tax |
||||
|
( |
||||
|
report_tax_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
tax_id, |
||||
|
name, |
||||
|
net, |
||||
|
tax |
||||
|
) |
||||
|
SELECT |
||||
|
tt.report_tax_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
tt.id, |
||||
|
tt.name, |
||||
|
abs(tt.net), |
||||
|
abs(tt.tax) |
||||
|
FROM |
||||
|
taxtags_tax tt |
||||
|
""" |
||||
|
query_inject_tax_params = (self.id, self.company_id.id, self.date_from, |
||||
|
self.date_to, self.env.uid) |
||||
|
self.env.cr.execute(query_inject_tax, query_inject_tax_params) |
||||
|
|
||||
|
def _inject_tax_taxgroups_values(self): |
||||
|
""" Inject report values for report_vat_report_tax. """ |
||||
|
# pylint: disable=sql-injection |
||||
|
query_inject_tax = """ |
||||
|
WITH |
||||
|
taxtags_tax AS |
||||
|
( |
||||
|
SELECT |
||||
|
taxtag.id AS report_tax_id, ' ' AS code, |
||||
|
tax.name, tax.id, |
||||
|
coalesce(sum(movetax.tax_base_amount), 0.00) AS net, |
||||
|
coalesce(sum(movetax.balance), 0.00) AS tax |
||||
|
FROM |
||||
|
report_vat_report_taxtag AS taxtag |
||||
|
INNER JOIN account_tax AS tax |
||||
|
ON tax.tax_group_id = taxtag.taxgroup_id |
||||
|
INNER JOIN account_move_line AS movetax |
||||
|
ON movetax.tax_line_id = tax.id |
||||
|
INNER JOIN account_move AS move |
||||
|
ON move.id = movetax.move_id |
||||
|
WHERE taxtag.id is not null AND movetax.tax_exigible |
||||
|
AND taxtag.report_id = %s AND move.company_id = %s |
||||
|
AND move.date >= %s AND move.date <= %s |
||||
|
AND move.state = 'posted' |
||||
|
GROUP BY taxtag.id, tax.id |
||||
|
ORDER BY tax.name |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_vat_report_tax |
||||
|
( |
||||
|
report_tax_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
tax_id, |
||||
|
name, |
||||
|
net, |
||||
|
tax |
||||
|
) |
||||
|
SELECT |
||||
|
tt.report_tax_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
tt.id, |
||||
|
tt.name, |
||||
|
abs(tt.net), |
||||
|
abs(tt.tax) |
||||
|
FROM |
||||
|
taxtags_tax tt |
||||
|
""" |
||||
|
query_inject_tax_params = (self.id, self.company_id.id, self.date_from, |
||||
|
self.date_to, self.env.uid) |
||||
|
self.env.cr.execute(query_inject_tax, query_inject_tax_params) |
@ -0,0 +1,52 @@ |
|||||
|
# Copyright 2018 Forest and Biomass Romania |
||||
|
# 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' |
||||
|
_inherit = 'report.account_financial_report.abstract_report_xlsx' |
||||
|
|
||||
|
def _get_report_name(self, report): |
||||
|
report_name = _('VAT Report') |
||||
|
return self._get_report_complete_name(report, 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], |
||||
|
[_('Date to'), report.date_to], |
||||
|
[_('Based on'), report.based_on], |
||||
|
] |
||||
|
|
||||
|
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): |
||||
|
# For each taxtag |
||||
|
self.write_array_header() |
||||
|
for taxtag in report.taxtags_ids: |
||||
|
# Write taxtag line |
||||
|
self.write_line(taxtag) |
||||
|
|
||||
|
# For each tax if detail taxes |
||||
|
if report.tax_detail: |
||||
|
for tax in taxtag.tax_ids: |
||||
|
self.write_line(tax) |
@ -0,0 +1,210 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<!-- PDF/HMTL REPORTS --> |
||||
|
|
||||
|
<!-- General Ledger --> |
||||
|
<report |
||||
|
id="action_report_general_ledger_qweb" |
||||
|
model="report_general_ledger" |
||||
|
string="General Ledger" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report.report_general_ledger_qweb" |
||||
|
file="account_financial_report.report_general_ledger_qweb" |
||||
|
/> |
||||
|
<report |
||||
|
id="action_report_general_ledger_html" |
||||
|
model="report_general_ledger" |
||||
|
string="General Ledger" |
||||
|
report_type="qweb-html" |
||||
|
name="account_financial_report.report_general_ledger_qweb" |
||||
|
file="account_financial_report.report_general_ledger_html" |
||||
|
/> |
||||
|
|
||||
|
<!-- Journal Ledger --> |
||||
|
<report |
||||
|
id="action_report_journal_ledger_qweb" |
||||
|
model="report_journal_ledger" |
||||
|
string="Journal Ledger" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report.report_journal_ledger_qweb" |
||||
|
file="account_financial_report.report_journal_ledger_qweb" |
||||
|
/> |
||||
|
<report |
||||
|
id="action_report_journal_ledger_html" |
||||
|
model="report_journal_ledger" |
||||
|
string="Journal Ledger" |
||||
|
report_type="qweb-html" |
||||
|
name="account_financial_report.report_journal_ledger_qweb" |
||||
|
file="account_financial_report.report_journal_ledger_html" |
||||
|
/> |
||||
|
|
||||
|
<!-- Trial Balance --> |
||||
|
<report |
||||
|
id="action_report_trial_balance_qweb" |
||||
|
model="report_trial_balance" |
||||
|
string="Trial Balance" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report.report_trial_balance_qweb" |
||||
|
file="account_financial_report.report_trial_balance_qweb" |
||||
|
/> |
||||
|
<report |
||||
|
id="action_report_trial_balance_html" |
||||
|
model="report_trial_balance" |
||||
|
string="Trial Balance" |
||||
|
report_type="qweb-html" |
||||
|
name="account_financial_report.report_trial_balance_qweb" |
||||
|
file="account_financial_report.report_trial_balance_html" |
||||
|
/> |
||||
|
|
||||
|
<!-- Open Items --> |
||||
|
<report |
||||
|
id="action_report_open_items_qweb" |
||||
|
model="report_open_items" |
||||
|
string="Open Items" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report.report_open_items_qweb" |
||||
|
file="account_financial_report.report_open_items_qweb" |
||||
|
/> |
||||
|
<report |
||||
|
id="action_report_open_items_html" |
||||
|
model="report_open_items" |
||||
|
string="Open Items" |
||||
|
report_type="qweb-html" |
||||
|
name="account_financial_report.report_open_items_qweb" |
||||
|
file="account_financial_report.report_open_items_html" |
||||
|
/> |
||||
|
|
||||
|
<!-- Aged Partner Balance --> |
||||
|
<report |
||||
|
id="action_report_aged_partner_balance_qweb" |
||||
|
model="report_aged_partner_balance" |
||||
|
string="Aged Partner Balance" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report.report_aged_partner_balance_qweb" |
||||
|
file="account_financial_report.report_aged_partner_balance_qweb" |
||||
|
/> |
||||
|
<report |
||||
|
id="action_report_aged_partner_balance_html" |
||||
|
model="report_aged_partner_balance" |
||||
|
string="Aged Partner Balance" |
||||
|
report_type="qweb-html" |
||||
|
name="account_financial_report.report_aged_partner_balance_qweb" |
||||
|
file="account_financial_report.report_aged_partner_balance_html" |
||||
|
/> |
||||
|
|
||||
|
<!-- VAT Report --> |
||||
|
<report |
||||
|
id="action_report_vat_report_qweb" |
||||
|
model="report_vat_report" |
||||
|
string="VAT Report" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report.report_vat_report_qweb" |
||||
|
file="account_financial_report.report_vat_report_qweb" |
||||
|
/> |
||||
|
<report |
||||
|
id="action_report_vat_report_html" |
||||
|
model="report_vat_report" |
||||
|
string="VAT Report" |
||||
|
report_type="qweb-html" |
||||
|
name="account_financial_report.report_vat_report_qweb" |
||||
|
file="account_financial_report.report_vat_report_html" |
||||
|
/> |
||||
|
|
||||
|
<!-- 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> |
||||
|
|
||||
|
<record id="action_report_general_ledger_qweb" model="ir.actions.report"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_trial_balance_qweb" model="ir.actions.report"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_open_items_qweb" model="ir.actions.report"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_aged_partner_balance_qweb" |
||||
|
model="ir.actions.report"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_vat_report_qweb" |
||||
|
model="ir.actions.report"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<!-- XLSX REPORTS --> |
||||
|
|
||||
|
<record id="action_report_general_ledger_xlsx" model="ir.actions.report"> |
||||
|
<field name="name">General Ledger XLSX</field> |
||||
|
<field name="model">report_general_ledger</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">report_journal_ledger</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">report_trial_balance</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">report_open_items</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">report_aged_partner_balance</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">report_vat_report</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> |
After Width: 256 | Height: 256 | Size: 15 KiB |
@ -0,0 +1,485 @@ |
|||||
|
<?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 0.14: 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/12.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-12-0/account-financial-reporting-12-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/12.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 |
||||
|
Accounting / Reporting / OCA 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="#changelog" id="id4">Changelog</a><ul> |
||||
|
<li><a class="reference internal" href="#id1" id="id5">11.0.2.5.0 (2019-04-26)</a></li> |
||||
|
<li><a class="reference internal" href="#id2" id="id6">11.0.2.4.1 (2019-01-08)</a></li> |
||||
|
<li><a class="reference internal" href="#id3" id="id7">11.0.2.3.1 (2018-11-29)</a></li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
<li><a class="reference internal" href="#bug-tracker" id="id8">Bug Tracker</a></li> |
||||
|
<li><a class="reference internal" href="#credits" id="id9">Credits</a><ul> |
||||
|
<li><a class="reference internal" href="#authors" id="id10">Authors</a></li> |
||||
|
<li><a class="reference internal" href="#contributors" id="id11">Contributors</a></li> |
||||
|
<li><a class="reference internal" href="#maintainers" id="id12">Maintainers</a></li> |
||||
|
</ul> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="changelog"> |
||||
|
<h1><a class="toc-backref" href="#id4">Changelog</a></h1> |
||||
|
<div class="section" id="id1"> |
||||
|
<h2><a class="toc-backref" href="#id5">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="#id6">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="#id7">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="#id8">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:%2012.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="#id9">Credits</a></h1> |
||||
|
<div class="section" id="authors"> |
||||
|
<h2><a class="toc-backref" href="#id10">Authors</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>Camptocamp SA</li> |
||||
|
<li>initOS GmbH</li> |
||||
|
<li>redCOR AG</li> |
||||
|
<li>Eficent</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="section" id="contributors"> |
||||
|
<h2><a class="toc-backref" href="#id11">Contributors</a></h2> |
||||
|
<ul class="simple"> |
||||
|
<li>Jordi Ballester <<a class="reference external" href="mailto:jordi.ballester@eficient.com">jordi.ballester@eficient.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@eficent.com">miquel.raich@eficent.com</a>></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="#id12">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/12.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,103 @@ |
|||||
|
.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,114 @@ |
|||||
|
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,86 @@ |
|||||
|
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,13 @@ |
|||||
|
|
||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
|
||||
|
from . import abstract_test |
||||
|
from . import abstract_test_tax_report |
||||
|
from . import abstract_test_foreign_currency |
||||
|
from . import test_aged_partner_balance |
||||
|
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,399 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import logging |
||||
|
|
||||
|
from odoo.tests import common |
||||
|
from odoo.tools import test_reports |
||||
|
|
||||
|
_logger = logging.getLogger(__name__) |
||||
|
|
||||
|
|
||||
|
class AbstractTest(common.TransactionCase): |
||||
|
"""Common technical tests for all reports.""" |
||||
|
at_install = False |
||||
|
post_install = True |
||||
|
|
||||
|
accounts = {} |
||||
|
|
||||
|
def with_context(self, *args, **kwargs): |
||||
|
context = dict(args[0] if args else self.env.context, **kwargs) |
||||
|
self.env = self.env(context=context) |
||||
|
return self |
||||
|
|
||||
|
def _chart_template_create(self): |
||||
|
transfer_account_id = self.env['account.account.template'].create({ |
||||
|
'code': '000', |
||||
|
'name': 'Liquidity Transfers', |
||||
|
'reconcile': True, |
||||
|
'user_type_id': self.ref( |
||||
|
"account.data_account_type_current_assets"), |
||||
|
}) |
||||
|
self.chart = self.env['account.chart.template'].create({ |
||||
|
'name': 'Test COA', |
||||
|
'code_digits': 4, |
||||
|
'bank_account_code_prefix': 1014, |
||||
|
'cash_account_code_prefix': 1014, |
||||
|
'currency_id': self.ref('base.USD'), |
||||
|
'transfer_account_code_prefix': '000', |
||||
|
}) |
||||
|
transfer_account_id.update({ |
||||
|
'chart_template_id': self.chart.id, |
||||
|
}) |
||||
|
self.env['ir.model.data'].create({ |
||||
|
'res_id': transfer_account_id.id, |
||||
|
'model': transfer_account_id._name, |
||||
|
'name': 'Liquidity Transfers', |
||||
|
}) |
||||
|
act = self.env['account.account.template'].create({ |
||||
|
'code': '001', |
||||
|
'name': 'Expenses', |
||||
|
'user_type_id': self.ref("account.data_account_type_expenses"), |
||||
|
'chart_template_id': self.chart.id, |
||||
|
'reconcile': True, |
||||
|
}) |
||||
|
self.env['ir.model.data'].create({ |
||||
|
'res_id': act.id, |
||||
|
'model': act._name, |
||||
|
'name': 'expenses', |
||||
|
}) |
||||
|
act = self.env['account.account.template'].create({ |
||||
|
'code': '002', |
||||
|
'name': 'Product Sales', |
||||
|
'user_type_id': self.ref("account.data_account_type_revenue"), |
||||
|
'chart_template_id': self.chart.id, |
||||
|
'reconcile': True, |
||||
|
}) |
||||
|
self.env['ir.model.data'].create({ |
||||
|
'res_id': act.id, |
||||
|
'model': act._name, |
||||
|
'name': 'sales', |
||||
|
}) |
||||
|
act = self.env['account.account.template'].create({ |
||||
|
'code': '003', |
||||
|
'name': 'Account Receivable', |
||||
|
'user_type_id': self.ref("account.data_account_type_receivable"), |
||||
|
'chart_template_id': self.chart.id, |
||||
|
'reconcile': True, |
||||
|
}) |
||||
|
self.env['ir.model.data'].create({ |
||||
|
'res_id': act.id, |
||||
|
'model': act._name, |
||||
|
'name': 'receivable', |
||||
|
}) |
||||
|
act = self.env['account.account.template'].create({ |
||||
|
'code': '004', |
||||
|
'name': 'Account Payable', |
||||
|
'user_type_id': self.ref("account.data_account_type_payable"), |
||||
|
'chart_template_id': self.chart.id, |
||||
|
'reconcile': True, |
||||
|
}) |
||||
|
self.env['ir.model.data'].create({ |
||||
|
'res_id': act.id, |
||||
|
'model': act._name, |
||||
|
'name': 'payable', |
||||
|
}) |
||||
|
|
||||
|
def _add_chart_of_accounts(self): |
||||
|
self.company = self.env['res.company'].create({ |
||||
|
'name': 'Spanish test company', |
||||
|
}) |
||||
|
self.env.ref('base.group_multi_company').write({ |
||||
|
'users': [(4, self.env.uid)], |
||||
|
}) |
||||
|
self.env.user.write({ |
||||
|
'company_ids': [(4, self.company.id)], |
||||
|
'company_id': self.company.id, |
||||
|
}) |
||||
|
self.with_context( |
||||
|
company_id=self.company.id, force_company=self.company.id) |
||||
|
self.chart.try_loading_for_current_company() |
||||
|
self.revenue = self.env['account.account'].search( |
||||
|
[('user_type_id', '=', self.ref( |
||||
|
"account.data_account_type_revenue"))], limit=1) |
||||
|
self.expense = self.env['account.account'].search( |
||||
|
[('user_type_id', '=', self.ref( |
||||
|
"account.data_account_type_expenses"))], limit=1) |
||||
|
self.receivable = self.env['account.account'].search( |
||||
|
[('user_type_id', '=', self.ref( |
||||
|
"account.data_account_type_receivable"))], limit=1) |
||||
|
self.payable = self.env['account.account'].search( |
||||
|
[('user_type_id', '=', self.ref( |
||||
|
"account.data_account_type_payable"))], limit=1) |
||||
|
return True |
||||
|
|
||||
|
def _journals_create(self): |
||||
|
self.journal_sale = self.env['account.journal'].create({ |
||||
|
'company_id': self.company.id, |
||||
|
'name': 'Test journal for sale', |
||||
|
'type': 'sale', |
||||
|
'code': 'TSALE', |
||||
|
'default_debit_account_id': self.revenue.id, |
||||
|
'default_credit_account_id': self.revenue.id, |
||||
|
}) |
||||
|
self.journal_purchase = self.env['account.journal'].create({ |
||||
|
'company_id': self.company.id, |
||||
|
'name': 'Test journal for purchase', |
||||
|
'type': 'purchase', |
||||
|
'code': 'TPUR', |
||||
|
'default_debit_account_id': self.expense.id, |
||||
|
'default_credit_account_id': self.expense.id, |
||||
|
}) |
||||
|
return True |
||||
|
|
||||
|
def _invoice_create(self): |
||||
|
self.partner = self.env['res.partner'].create({ |
||||
|
'name': 'Test partner', |
||||
|
'company_id': self.company.id, |
||||
|
'property_account_receivable_id': self.receivable.id, |
||||
|
'property_account_payable_id': self.payable.id, |
||||
|
}) |
||||
|
|
||||
|
# customer invoice |
||||
|
customer_invoice_lines = [(0, False, { |
||||
|
'name': 'Test description #1', |
||||
|
'account_id': self.revenue.id, |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 100.0, |
||||
|
}), (0, False, { |
||||
|
'name': 'Test description #2', |
||||
|
'account_id': self.revenue.id, |
||||
|
'quantity': 2.0, |
||||
|
'price_unit': 25.0, |
||||
|
})] |
||||
|
self.invoice_out = self.env['account.invoice'].create({ |
||||
|
'partner_id': self.partner.id, |
||||
|
'type': 'out_invoice', |
||||
|
'invoice_line_ids': customer_invoice_lines, |
||||
|
'account_id': self.partner.property_account_receivable_id.id, |
||||
|
'journal_id': self.journal_sale.id, |
||||
|
}) |
||||
|
self.invoice_out.action_invoice_open() |
||||
|
|
||||
|
# vendor bill |
||||
|
vendor_invoice_lines = [(0, False, { |
||||
|
'name': 'Test description #1', |
||||
|
'account_id': self.revenue.id, |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 100.0, |
||||
|
}), (0, False, { |
||||
|
'name': 'Test description #2', |
||||
|
'account_id': self.revenue.id, |
||||
|
'quantity': 2.0, |
||||
|
'price_unit': 25.0, |
||||
|
})] |
||||
|
self.invoice_in = self.env['account.invoice'].create({ |
||||
|
'partner_id': self.partner.id, |
||||
|
'type': 'in_invoice', |
||||
|
'invoice_line_ids': vendor_invoice_lines, |
||||
|
'account_id': self.partner.property_account_payable_id.id, |
||||
|
'journal_id': self.journal_purchase.id, |
||||
|
}) |
||||
|
self.invoice_in.action_invoice_open() |
||||
|
|
||||
|
def setUp(self): |
||||
|
super(AbstractTest, self).setUp() |
||||
|
|
||||
|
self.with_context() |
||||
|
self._chart_template_create() |
||||
|
self._add_chart_of_accounts() |
||||
|
self._journals_create() |
||||
|
self._invoice_create() |
||||
|
|
||||
|
self.model = self._getReportModel() |
||||
|
|
||||
|
self.qweb_report_name = self._getQwebReportName() |
||||
|
self.xlsx_report_name = self._getXlsxReportName() |
||||
|
self.xlsx_action_name = self._getXlsxReportActionName() |
||||
|
|
||||
|
self.report_title = self._getReportTitle() |
||||
|
|
||||
|
self.base_filters = self._getBaseFilters() |
||||
|
self.additional_filters = self._getAdditionalFiltersToBeTested() |
||||
|
|
||||
|
self.report = self.model.create(self.base_filters) |
||||
|
self.report.compute_data_for_report() |
||||
|
|
||||
|
def test_html(self): |
||||
|
test_reports.try_report(self.env.cr, self.env.uid, |
||||
|
self.qweb_report_name, |
||||
|
[self.report.id], |
||||
|
report_type='qweb-html') |
||||
|
|
||||
|
def test_qweb(self): |
||||
|
test_reports.try_report(self.env.cr, self.env.uid, |
||||
|
self.qweb_report_name, |
||||
|
[self.report.id], |
||||
|
report_type='qweb-pdf') |
||||
|
|
||||
|
def test_xlsx(self): |
||||
|
test_reports.try_report(self.env.cr, self.env.uid, |
||||
|
self.xlsx_report_name, |
||||
|
[self.report.id], |
||||
|
report_type='xlsx') |
||||
|
|
||||
|
def test_print(self): |
||||
|
self.report.print_report('qweb') |
||||
|
self.report.print_report('xlsx') |
||||
|
|
||||
|
def test_02_generation_report_html(self): |
||||
|
"""Check if report HTML is correctly generated""" |
||||
|
|
||||
|
# Check if returned report action is correct |
||||
|
report_type = 'qweb-html' |
||||
|
report_action = self.report.print_report(report_type) |
||||
|
self.assertDictContainsSubset( |
||||
|
{ |
||||
|
'type': 'ir.actions.report', |
||||
|
'report_name': self.qweb_report_name, |
||||
|
'report_type': 'qweb-html', |
||||
|
}, |
||||
|
report_action |
||||
|
) |
||||
|
|
||||
|
# Check if report template is correct |
||||
|
report = self.env['ir.actions.report'].search( |
||||
|
[('report_name', '=', self.qweb_report_name), |
||||
|
('report_type', '=', report_type)], limit=1) |
||||
|
self.assertEqual(report.report_type, 'qweb-html') |
||||
|
|
||||
|
rep = report.render(self.report.ids, {}) |
||||
|
|
||||
|
self.assertTrue(self.report_title.encode('utf8') in rep[0]) |
||||
|
self.assertTrue( |
||||
|
self.report.account_ids[0].name.encode('utf8') in rep[0] |
||||
|
) |
||||
|
|
||||
|
def test_04_compute_data(self): |
||||
|
"""Check that the SQL queries work with all filters options""" |
||||
|
|
||||
|
for filters in [{}] + self.additional_filters: |
||||
|
current_filter = self.base_filters.copy() |
||||
|
current_filter.update(filters) |
||||
|
|
||||
|
report = self.model.create(current_filter) |
||||
|
report.compute_data_for_report() |
||||
|
|
||||
|
self.assertGreaterEqual(len(report.account_ids), 1) |
||||
|
|
||||
|
# Same filters with only one account |
||||
|
current_filter = self.base_filters.copy() |
||||
|
current_filter.update(filters) |
||||
|
report_accounts = report.account_ids.filtered('account_id') |
||||
|
current_filter.update({ |
||||
|
'filter_account_ids': |
||||
|
[(6, 0, report_accounts[0].account_id.ids)], |
||||
|
}) |
||||
|
|
||||
|
report2 = self.model.create(current_filter) |
||||
|
report2.compute_data_for_report() |
||||
|
|
||||
|
self.assertEqual(len(report2.account_ids), 1) |
||||
|
self.assertEqual(report2.account_ids.name, |
||||
|
report_accounts[0].name) |
||||
|
|
||||
|
if self._partner_test_is_possible(filters): |
||||
|
# Same filters with only one partner |
||||
|
report_partner_ids = report.account_ids.mapped('partner_ids') |
||||
|
partner_ids = report_partner_ids.mapped('partner_id') |
||||
|
|
||||
|
current_filter = self.base_filters.copy() |
||||
|
current_filter.update(filters) |
||||
|
current_filter.update({ |
||||
|
'filter_partner_ids': [(6, 0, partner_ids[0].ids)], |
||||
|
}) |
||||
|
|
||||
|
report3 = self.model.create(current_filter) |
||||
|
report3.compute_data_for_report() |
||||
|
|
||||
|
self.assertGreaterEqual(len(report3.account_ids), 1) |
||||
|
|
||||
|
report_partner_ids3 = report3.account_ids.mapped('partner_ids') |
||||
|
partner_ids3 = report_partner_ids3.mapped('partner_id') |
||||
|
|
||||
|
self.assertEqual(len(partner_ids3), 1) |
||||
|
self.assertEqual( |
||||
|
partner_ids3.name, |
||||
|
partner_ids[0].name |
||||
|
) |
||||
|
|
||||
|
# Same filters with only one partner and one account |
||||
|
report_partner_ids = report3.account_ids.mapped('partner_ids') |
||||
|
report_account_id = report_partner_ids.filtered( |
||||
|
lambda p: p.partner_id |
||||
|
)[0].report_account_id |
||||
|
|
||||
|
current_filter = self.base_filters.copy() |
||||
|
current_filter.update(filters) |
||||
|
current_filter.update({ |
||||
|
'filter_account_ids': |
||||
|
[(6, 0, report_account_id.account_id.ids)], |
||||
|
'filter_partner_ids': [(6, 0, partner_ids[0].ids)], |
||||
|
}) |
||||
|
|
||||
|
report4 = self.model.create(current_filter) |
||||
|
report4.compute_data_for_report() |
||||
|
|
||||
|
self.assertEqual(len(report4.account_ids), 1) |
||||
|
self.assertEqual(report4.account_ids.name, |
||||
|
report_account_id.account_id.name) |
||||
|
|
||||
|
report_partner_ids4 = report4.account_ids.mapped('partner_ids') |
||||
|
partner_ids4 = report_partner_ids4.mapped('partner_id') |
||||
|
|
||||
|
self.assertEqual(len(partner_ids4), 1) |
||||
|
self.assertEqual( |
||||
|
partner_ids4.name, |
||||
|
partner_ids[0].name |
||||
|
) |
||||
|
|
||||
|
def _partner_test_is_possible(self, filters): |
||||
|
""" |
||||
|
:return: |
||||
|
a boolean to indicate if partner test is possible |
||||
|
with current filters |
||||
|
""" |
||||
|
return True |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
""" |
||||
|
:return: the report model name |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
""" |
||||
|
:return: the qweb report name |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
""" |
||||
|
:return: the xlsx report name |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
""" |
||||
|
:return: the xlsx report action name |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
""" |
||||
|
:return: the report title displayed into the report |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
""" |
||||
|
:return: the minimum required filters to generate report |
||||
|
""" |
||||
|
raise NotImplementedError() |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
""" |
||||
|
:return: the additional filters to generate report variants |
||||
|
""" |
||||
|
raise NotImplementedError() |
@ -0,0 +1,78 @@ |
|||||
|
# Copyright 2018 Forest and Biomass Romania |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import logging |
||||
|
from . import abstract_test |
||||
|
|
||||
|
_logger = logging.getLogger(__name__) |
||||
|
|
||||
|
|
||||
|
class AbstractTestForeignCurrency(abstract_test.AbstractTest): |
||||
|
"""Common technical tests for all reports.""" |
||||
|
|
||||
|
def _chart_template_create(self): |
||||
|
super(AbstractTestForeignCurrency, self)._chart_template_create() |
||||
|
# Account for foreign payments |
||||
|
self.account_type_other = self.env['account.account.type'].create( |
||||
|
{'name': 'foreign expenses', |
||||
|
'type': 'other', |
||||
|
}) |
||||
|
act = self.env['account.account.template'].create({ |
||||
|
'code': '0012', |
||||
|
'name': 'Foreign Expenses', |
||||
|
'user_type_id': self.account_type_other.id, |
||||
|
'chart_template_id': self.chart.id, |
||||
|
'currency_id': self.env.ref('base.EUR').id, |
||||
|
}) |
||||
|
self.env['ir.model.data'].create({ |
||||
|
'res_id': act.id, |
||||
|
'model': act._name, |
||||
|
'name': 'foreign expenses', |
||||
|
}) |
||||
|
return True |
||||
|
|
||||
|
def _add_chart_of_accounts(self): |
||||
|
super(AbstractTestForeignCurrency, self)._add_chart_of_accounts() |
||||
|
self.foreign_expense = self.env['account.account'].search( |
||||
|
[('currency_id', '=', self.env.ref('base.EUR').id)], limit=1) |
||||
|
self.foreign_currency_id = self.foreign_expense.currency_id |
||||
|
return True |
||||
|
|
||||
|
def _journals_create(self): |
||||
|
super(AbstractTestForeignCurrency, self)._journals_create() |
||||
|
self.journal_foreign_purchases = self.env['account.journal'].create({ |
||||
|
'company_id': self.company.id, |
||||
|
'name': 'Test journal for purchase', |
||||
|
'type': 'purchase', |
||||
|
'code': 'TFORPUR', |
||||
|
'default_debit_account_id': self.foreign_expense.id, |
||||
|
'default_credit_account_id': self.foreign_expense.id, |
||||
|
'currency_id': self.foreign_currency_id.id, |
||||
|
}) |
||||
|
return True |
||||
|
|
||||
|
def _invoice_create(self): |
||||
|
super(AbstractTestForeignCurrency, self)._invoice_create() |
||||
|
# vendor bill foreign currency |
||||
|
foreign_vendor_invoice_lines = [(0, False, { |
||||
|
'name': 'Test description #1', |
||||
|
'account_id': self.revenue.id, |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 100.0, |
||||
|
'currency_id': self.foreign_currency_id.id, |
||||
|
}), (0, False, { |
||||
|
'name': 'Test description #2', |
||||
|
'account_id': self.revenue.id, |
||||
|
'quantity': 2.0, |
||||
|
'price_unit': 25.0, |
||||
|
'currency_id': self.foreign_currency_id.id, |
||||
|
})] |
||||
|
self.foreign_invoice_in = self.env['account.invoice'].create({ |
||||
|
'partner_id': self.partner.id, |
||||
|
'type': 'in_invoice', |
||||
|
'invoice_line_ids': foreign_vendor_invoice_lines, |
||||
|
'account_id': self.partner.property_account_payable_id.id, |
||||
|
'journal_id': self.journal_foreign_purchases.id, |
||||
|
}) |
||||
|
self.foreign_invoice_in.action_invoice_open() |
||||
|
return True |
@ -0,0 +1,75 @@ |
|||||
|
# Copyright 2018 Forest and Biomass Romania |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import logging |
||||
|
from odoo.tests.common import TransactionCase |
||||
|
from odoo.tools import test_reports |
||||
|
|
||||
|
_logger = logging.getLogger(__name__) |
||||
|
|
||||
|
|
||||
|
class AbstractTest(TransactionCase): |
||||
|
"""Common technical tests for all reports.""" |
||||
|
|
||||
|
def setUp(cls): |
||||
|
super(AbstractTest, cls).setUp() |
||||
|
|
||||
|
cls.model = cls._getReportModel() |
||||
|
|
||||
|
cls.qweb_report_name = cls._getQwebReportName() |
||||
|
cls.xlsx_report_name = cls._getXlsxReportName() |
||||
|
cls.xlsx_action_name = cls._getXlsxReportActionName() |
||||
|
|
||||
|
cls.report_title = cls._getReportTitle() |
||||
|
|
||||
|
cls.base_filters = cls._getBaseFilters() |
||||
|
|
||||
|
cls.report = cls.model.create(cls.base_filters) |
||||
|
cls.report.compute_data_for_report() |
||||
|
|
||||
|
def test_html(self): |
||||
|
test_reports.try_report(self.env.cr, self.env.uid, |
||||
|
self.qweb_report_name, |
||||
|
[self.report.id], |
||||
|
report_type='qweb-html') |
||||
|
|
||||
|
def test_qweb(self): |
||||
|
test_reports.try_report(self.env.cr, self.env.uid, |
||||
|
self.qweb_report_name, |
||||
|
[self.report.id], |
||||
|
report_type='qweb-pdf') |
||||
|
|
||||
|
def test_xlsx(self): |
||||
|
test_reports.try_report(self.env.cr, self.env.uid, |
||||
|
self.xlsx_report_name, |
||||
|
[self.report.id], |
||||
|
report_type='xlsx') |
||||
|
|
||||
|
def test_print(self): |
||||
|
self.report.print_report('qweb') |
||||
|
self.report.print_report('xlsx') |
||||
|
|
||||
|
def test_generation_report_html(self): |
||||
|
"""Check if report HTML is correctly generated""" |
||||
|
|
||||
|
# Check if returned report action is correct |
||||
|
report_type = 'qweb-html' |
||||
|
report_action = self.report.print_report(report_type) |
||||
|
self.assertDictContainsSubset( |
||||
|
{ |
||||
|
'type': 'ir.actions.report', |
||||
|
'report_name': self.qweb_report_name, |
||||
|
'report_type': 'qweb-html', |
||||
|
}, |
||||
|
report_action |
||||
|
) |
||||
|
|
||||
|
# Check if report template is correct |
||||
|
report = self.env['ir.actions.report'].search( |
||||
|
[('report_name', '=', self.qweb_report_name), |
||||
|
('report_type', '=', report_type)], limit=1) |
||||
|
self.assertEqual(report.report_type, 'qweb-html') |
||||
|
|
||||
|
rep = report.render(self.report.ids, {}) |
||||
|
|
||||
|
self.assertTrue(self.report_title.encode('utf8') in rep[0]) |
@ -0,0 +1,41 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from datetime import date |
||||
|
from . import abstract_test |
||||
|
|
||||
|
|
||||
|
class TestAgedPartnerBalance(abstract_test.AbstractTest): |
||||
|
""" |
||||
|
Technical tests for Aged Partner Balance Report. |
||||
|
""" |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_aged_partner_balance'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report.report_aged_partner_balance_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'a_f_r.report_aged_partner_balance_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report.' \ |
||||
|
'action_report_aged_partner_balance_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Odoo' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_at': date(date.today().year, 12, 31), |
||||
|
'company_id': self.company.id, |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
return [ |
||||
|
{'only_posted_moves': True}, |
||||
|
{'show_move_line_details': True}, |
||||
|
{'only_posted_moves': True, 'show_move_line_details': True}, |
||||
|
] |
@ -0,0 +1,553 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
|
||||
|
from odoo.tests import common |
||||
|
from odoo import fields |
||||
|
from datetime import date |
||||
|
from . import abstract_test_foreign_currency as a_t_f_c |
||||
|
|
||||
|
|
||||
|
class TestGeneralLedger(a_t_f_c.AbstractTestForeignCurrency): |
||||
|
""" |
||||
|
Technical tests for General Ledger Report. |
||||
|
""" |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_general_ledger'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report.report_general_ledger_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'a_f_r.report_general_ledger_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report.' \ |
||||
|
'action_report_general_ledger_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Odoo' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_from': date(date.today().year, 1, 1), |
||||
|
'date_to': date(date.today().year, 12, 31), |
||||
|
'company_id': self.company.id, |
||||
|
'fy_start_date': date(date.today().year, 1, 1), |
||||
|
'foreign_currency': True, |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
|
||||
|
additional_filters = [ |
||||
|
{'only_posted_moves': True}, |
||||
|
{'hide_account_at_0': True}, |
||||
|
{'centralize': True}, |
||||
|
{'only_posted_moves': True, 'hide_account_at_0': True}, |
||||
|
{'only_posted_moves': True, 'centralize': True}, |
||||
|
{'hide_account_at_0': True, 'centralize': True}, |
||||
|
{ |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_at_0': True, |
||||
|
'centralize': True |
||||
|
}, |
||||
|
] |
||||
|
# Add `show_analytic_tags` filter on each cases |
||||
|
additional_filters_with_show_tags = [] |
||||
|
for additional_filter in additional_filters: |
||||
|
additional_filter['show_analytic_tags'] = True |
||||
|
additional_filters_with_show_tags.append( |
||||
|
additional_filter |
||||
|
) |
||||
|
additional_filters += additional_filters_with_show_tags |
||||
|
# Add `filter_analytic_tag_ids` filter on each cases |
||||
|
analytic_tag = self.env['account.analytic.tag'].create({ |
||||
|
'name': 'TEST tag' |
||||
|
}) |
||||
|
# Define all move lines on this tag |
||||
|
# (this test just check with the all filters, all works technically) |
||||
|
move_lines = self.env['account.move.line'].search([]) |
||||
|
move_lines.write({ |
||||
|
'analytic_tag_ids': [(6, False, analytic_tag.ids)], |
||||
|
}) |
||||
|
additional_filters_with_filter_tags = [] |
||||
|
for additional_filter in additional_filters: |
||||
|
additional_filter['filter_analytic_tag_ids'] = [ |
||||
|
(6, False, analytic_tag.ids) |
||||
|
] |
||||
|
additional_filters_with_filter_tags.append( |
||||
|
additional_filter |
||||
|
) |
||||
|
additional_filters += additional_filters_with_filter_tags |
||||
|
return additional_filters |
||||
|
|
||||
|
|
||||
|
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) |
||||
|
|
||||
|
def _add_move( |
||||
|
self, |
||||
|
date, |
||||
|
receivable_debit, |
||||
|
receivable_credit, |
||||
|
income_debit, |
||||
|
income_credit, |
||||
|
unaffected_debit=0, |
||||
|
unaffected_credit=0 |
||||
|
): |
||||
|
move_name = 'expense accrual' |
||||
|
journal = self.env['account.journal'].search([], limit=1) |
||||
|
partner = self.env.ref('base.res_partner_12') |
||||
|
move_vals = { |
||||
|
'journal_id': journal.id, |
||||
|
'name': move_name, |
||||
|
'date': date, |
||||
|
'line_ids': [ |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': receivable_debit, |
||||
|
'credit': receivable_credit, |
||||
|
'account_id': self.receivable_account.id, |
||||
|
'partner_id': partner.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': income_debit, |
||||
|
'credit': income_credit, |
||||
|
'account_id': self.income_account.id, |
||||
|
'partner_id': partner.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'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.post() |
||||
|
|
||||
|
def _get_report_lines(self, with_partners=False): |
||||
|
company = self.env.ref('base.main_company') |
||||
|
general_ledger = self.env['report_general_ledger'].create({ |
||||
|
'date_from': self.fy_date_start, |
||||
|
'date_to': self.fy_date_end, |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_at_0': False, |
||||
|
'company_id': company.id, |
||||
|
'fy_start_date': self.fy_date_start, |
||||
|
}) |
||||
|
general_ledger.compute_data_for_report( |
||||
|
with_line_details=True, with_partners=with_partners |
||||
|
) |
||||
|
lines = {} |
||||
|
report_account_model = self.env['report_general_ledger_account'] |
||||
|
lines['receivable'] = report_account_model.search([ |
||||
|
('report_id', '=', general_ledger.id), |
||||
|
('account_id', '=', self.receivable_account.id), |
||||
|
]) |
||||
|
lines['income'] = report_account_model.search([ |
||||
|
('report_id', '=', general_ledger.id), |
||||
|
('account_id', '=', self.income_account.id), |
||||
|
]) |
||||
|
lines['unaffected'] = report_account_model.search([ |
||||
|
('report_id', '=', general_ledger.id), |
||||
|
('account_id', '=', self.unaffected_account.id), |
||||
|
]) |
||||
|
if with_partners: |
||||
|
report_partner_model = self.env[ |
||||
|
'report_general_ledger_partner' |
||||
|
] |
||||
|
lines['partner_receivable'] = report_partner_model.search([ |
||||
|
('report_account_id', '=', lines['receivable'].id), |
||||
|
('partner_id', '=', self.env.ref('base.res_partner_12').id), |
||||
|
]) |
||||
|
return lines |
||||
|
|
||||
|
def test_01_account_balance(self): |
||||
|
# Generate the general ledger line |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['receivable']), 0) |
||||
|
self.assertEqual(len(lines['income']), 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 |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 0) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_debit, 1000) |
||||
|
self.assertEqual(lines['receivable'].initial_credit, 0) |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_debit, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_credit, 0) |
||||
|
self.assertEqual(lines['receivable'].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 general ledger line |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_debit, 1000) |
||||
|
self.assertEqual(lines['receivable'].initial_credit, 0) |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_debit, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_credit, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_balance, 0) |
||||
|
|
||||
|
self.assertEqual(lines['income'].initial_debit, 0) |
||||
|
self.assertEqual(lines['income'].initial_credit, 0) |
||||
|
self.assertEqual(lines['income'].initial_balance, 0) |
||||
|
self.assertEqual(lines['income'].final_debit, 1000) |
||||
|
self.assertEqual(lines['income'].final_credit, 0) |
||||
|
self.assertEqual(lines['income'].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 general ledger line |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_debit, 1000) |
||||
|
self.assertEqual(lines['receivable'].initial_credit, 0) |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_debit, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_credit, 2000) |
||||
|
self.assertEqual(lines['receivable'].final_balance, -1000) |
||||
|
|
||||
|
self.assertEqual(lines['income'].initial_debit, 0) |
||||
|
self.assertEqual(lines['income'].initial_credit, 0) |
||||
|
self.assertEqual(lines['income'].initial_balance, 0) |
||||
|
self.assertEqual(lines['income'].final_debit, 2000) |
||||
|
self.assertEqual(lines['income'].final_credit, 0) |
||||
|
self.assertEqual(lines['income'].final_balance, 2000) |
||||
|
|
||||
|
def test_02_partner_balance(self): |
||||
|
# Generate the general ledger line |
||||
|
lines = self._get_report_lines(with_partners=True) |
||||
|
self.assertEqual(len(lines['partner_receivable']), 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 |
||||
|
lines = self._get_report_lines(with_partners=True) |
||||
|
self.assertEqual(len(lines['partner_receivable']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['partner_receivable'].initial_debit, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].initial_credit, 0) |
||||
|
self.assertEqual(lines['partner_receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].final_debit, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].final_credit, 0) |
||||
|
self.assertEqual(lines['partner_receivable'].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 general ledger line |
||||
|
lines = self._get_report_lines(with_partners=True) |
||||
|
self.assertEqual(len(lines['partner_receivable']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['partner_receivable'].initial_debit, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].initial_credit, 0) |
||||
|
self.assertEqual(lines['partner_receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].final_debit, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].final_credit, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].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 general ledger line |
||||
|
lines = self._get_report_lines(with_partners=True) |
||||
|
self.assertEqual(len(lines['partner_receivable']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['partner_receivable'].initial_debit, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].initial_credit, 0) |
||||
|
self.assertEqual(lines['partner_receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].final_debit, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].final_credit, 2000) |
||||
|
self.assertEqual(lines['partner_receivable'].final_balance, -1000) |
||||
|
|
||||
|
def test_03_unaffected_account_balance(self): |
||||
|
# Generate the general ledger line |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['unaffected']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['unaffected'].initial_debit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_credit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_balance, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_debit, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_credit, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_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 |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['unaffected']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['unaffected'].initial_debit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_credit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].initial_balance, -1000) |
||||
|
self.assertEqual(lines['unaffected'].final_debit, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_credit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].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=0, |
||||
|
income_debit=0, |
||||
|
income_credit=1000, |
||||
|
unaffected_debit=1000, |
||||
|
unaffected_credit=0 |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['unaffected']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['unaffected'].initial_debit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_credit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].initial_balance, -1000) |
||||
|
self.assertEqual(lines['unaffected'].final_debit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].final_credit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].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=3000, |
||||
|
receivable_credit=0, |
||||
|
income_debit=0, |
||||
|
income_credit=0, |
||||
|
unaffected_debit=0, |
||||
|
unaffected_credit=3000 |
||||
|
) |
||||
|
|
||||
|
# Re Generate the general ledger line |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['unaffected']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['unaffected'].initial_debit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_credit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].initial_balance, -1000) |
||||
|
self.assertEqual(lines['unaffected'].final_debit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].final_credit, 4000) |
||||
|
self.assertEqual(lines['unaffected'].final_balance, -3000) |
||||
|
|
||||
|
def test_04_unaffected_account_balance_2_years(self): |
||||
|
# Generate the general ledger line |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['unaffected']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['unaffected'].initial_debit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_credit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_balance, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_debit, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_credit, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_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 |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['unaffected']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['unaffected'].initial_debit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].initial_credit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['unaffected'].final_debit, 1000) |
||||
|
self.assertEqual(lines['unaffected'].final_credit, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_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 |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['unaffected']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['unaffected'].initial_debit, 500) |
||||
|
self.assertEqual(lines['unaffected'].initial_credit, 0) |
||||
|
self.assertEqual(lines['unaffected'].initial_balance, 500) |
||||
|
self.assertEqual(lines['unaffected'].final_debit, 500) |
||||
|
self.assertEqual(lines['unaffected'].final_credit, 0) |
||||
|
self.assertEqual(lines['unaffected'].final_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,364 @@ |
|||||
|
# Copyright 2017 ACSONE SA/NV |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from datetime import datetime, date |
||||
|
from dateutil.relativedelta import relativedelta |
||||
|
|
||||
|
from odoo.fields import Date |
||||
|
from odoo.tests.common import TransactionCase |
||||
|
|
||||
|
from . import abstract_test_foreign_currency as a_t_f_c |
||||
|
|
||||
|
|
||||
|
class TestJournalLedger(a_t_f_c.AbstractTestForeignCurrency): |
||||
|
""" |
||||
|
Technical tests for General Ledger Report. |
||||
|
""" |
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_journal_ledger'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report.report_journal_ledger_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'a_f_r.report_journal_ledger_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report.' \ |
||||
|
'action_report_journal_ledger_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Odoo' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_from': date(date.today().year, 1, 1), |
||||
|
'date_to': date(date.today().year, 12, 31), |
||||
|
'company_id': self.company.id, |
||||
|
'journal_ids': [(6, 0, self.journal_sale.ids)] |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
return [ |
||||
|
{'move_target': "All", |
||||
|
'sort_option': "Date", |
||||
|
'group_option': "Journal", |
||||
|
'with_account_name': True, |
||||
|
'foreign_currency': True}, |
||||
|
] |
||||
|
|
||||
|
def test_02_generation_report_html(self): |
||||
|
"""Check if report HTML is correctly generated""" |
||||
|
|
||||
|
# Check if returned report action is correct |
||||
|
report_type = 'qweb-html' |
||||
|
report_action = self.report.print_report(report_type) |
||||
|
self.assertDictContainsSubset( |
||||
|
{ |
||||
|
'type': 'ir.actions.report', |
||||
|
'report_name': self.qweb_report_name, |
||||
|
'report_type': 'qweb-html', |
||||
|
}, |
||||
|
report_action |
||||
|
) |
||||
|
|
||||
|
# Check if report template is correct |
||||
|
report = self.env['ir.actions.report'].search( |
||||
|
[('report_name', '=', self.qweb_report_name), |
||||
|
('report_type', '=', report_type)], limit=1) |
||||
|
self.assertEqual(report.report_type, 'qweb-html') |
||||
|
|
||||
|
rep = report.render(self.report.ids, {}) |
||||
|
|
||||
|
self.assertTrue(self.report_title.encode('utf8') in rep[0]) |
||||
|
self.assertTrue( |
||||
|
self.report.journal_ids[0].name.encode('utf8') in rep[0] |
||||
|
) |
||||
|
|
||||
|
def test_04_compute_data(self): |
||||
|
return True |
||||
|
|
||||
|
|
||||
|
class TestJournalReport(TransactionCase): |
||||
|
|
||||
|
def setUp(self): |
||||
|
super(TestJournalReport, self).setUp() |
||||
|
self.AccountObj = self.env['account.account'] |
||||
|
self.InvoiceObj = self.env['account.invoice'] |
||||
|
self.JournalObj = self.env['account.journal'] |
||||
|
self.JournalReportObj = self.env['journal.ledger.report.wizard'] |
||||
|
self.MoveObj = self.env['account.move'] |
||||
|
self.ReportJournalLedger = self.env['report_journal_ledger'] |
||||
|
self.TaxObj = self.env['account.tax'] |
||||
|
|
||||
|
self.company = self.env.ref('base.main_company') |
||||
|
|
||||
|
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.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': 'sale', |
||||
|
'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, report, expected_debit, expected_credit): |
||||
|
self.assertEqual( |
||||
|
expected_debit, |
||||
|
sum([journal.debit for journal in |
||||
|
report.report_journal_ledger_ids]) |
||||
|
) |
||||
|
|
||||
|
self.assertEqual( |
||||
|
expected_credit, |
||||
|
sum([journal.credit for journal in |
||||
|
report.report_journal_ledger_ids]) |
||||
|
) |
||||
|
|
||||
|
def check_report_journal_debit_credit_taxes( |
||||
|
self, report, |
||||
|
expected_base_debit, expected_base_credit, |
||||
|
expected_tax_debit, expected_tax_credit): |
||||
|
|
||||
|
self.assertEqual( |
||||
|
expected_base_debit, |
||||
|
sum([ |
||||
|
journal.base_debit |
||||
|
for journal in report.report_journal_ledger_tax_line_ids |
||||
|
]) |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_base_credit, |
||||
|
sum([ |
||||
|
journal.base_credit |
||||
|
for journal in report.report_journal_ledger_tax_line_ids |
||||
|
]) |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_tax_debit, |
||||
|
sum([ |
||||
|
journal.tax_debit |
||||
|
for journal in report.report_journal_ledger_tax_line_ids |
||||
|
]) |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_tax_credit, |
||||
|
sum([ |
||||
|
journal.tax_credit |
||||
|
for journal in report.report_journal_ledger_tax_line_ids |
||||
|
]) |
||||
|
) |
||||
|
|
||||
|
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) |
||||
|
|
||||
|
report = self.ReportJournalLedger.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)] |
||||
|
}) |
||||
|
report.compute_data_for_report() |
||||
|
|
||||
|
self.check_report_journal_debit_credit(report, 100, 100) |
||||
|
|
||||
|
move3 = self._add_move( |
||||
|
today_date, self.journal_sale, |
||||
|
0, 100, 100, 0) |
||||
|
|
||||
|
report.compute_data_for_report() |
||||
|
self.check_report_journal_debit_credit(report, 200, 200) |
||||
|
|
||||
|
report.move_target = 'posted' |
||||
|
report.compute_data_for_report() |
||||
|
self.check_report_journal_debit_credit(report, 0, 0) |
||||
|
|
||||
|
move1.post() |
||||
|
report.compute_data_for_report() |
||||
|
self.check_report_journal_debit_credit(report, 100, 100) |
||||
|
|
||||
|
move2.post() |
||||
|
report.compute_data_for_report() |
||||
|
self.check_report_journal_debit_credit(report, 100, 100) |
||||
|
|
||||
|
move3.post() |
||||
|
report.compute_data_for_report() |
||||
|
self.check_report_journal_debit_credit(report, 200, 200) |
||||
|
|
||||
|
report.date_from = self.previous_fy_date_start |
||||
|
report.compute_data_for_report() |
||||
|
self.check_report_journal_debit_credit(report, 300, 300) |
||||
|
|
||||
|
def test_02_test_taxes_out_invoice(self): |
||||
|
invoice_values = { |
||||
|
'journal_id': self.journal_sale.id, |
||||
|
'partner_id': self.partner_2.id, |
||||
|
'type': 'out_invoice', |
||||
|
'invoice_line_ids': [ |
||||
|
(0, 0, { |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 100, |
||||
|
'account_id': self.receivable_account.id, |
||||
|
'name': "Test", |
||||
|
'invoice_line_tax_ids': [(6, 0, [self.tax_15_s.id])], |
||||
|
}), |
||||
|
(0, 0, { |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 100, |
||||
|
'account_id': self.receivable_account.id, |
||||
|
'name': "Test", |
||||
|
'invoice_line_tax_ids': [(6, 0, [ |
||||
|
self.tax_15_s.id, self.tax_20_s.id |
||||
|
])], |
||||
|
}) |
||||
|
] |
||||
|
} |
||||
|
invoice = self.InvoiceObj.create(invoice_values) |
||||
|
invoice.action_invoice_open() |
||||
|
|
||||
|
report = self.ReportJournalLedger.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)] |
||||
|
}) |
||||
|
report.compute_data_for_report() |
||||
|
|
||||
|
self.check_report_journal_debit_credit(report, 250, 250) |
||||
|
self.check_report_journal_debit_credit_taxes(report, 0, 300, 0, 50) |
||||
|
|
||||
|
def test_03_test_taxes_in_invoice(self): |
||||
|
invoice_values = { |
||||
|
'journal_id': self.journal_sale.id, |
||||
|
'partner_id': self.partner_2.id, |
||||
|
'type': 'in_invoice', |
||||
|
'invoice_line_ids': [ |
||||
|
(0, 0, { |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 100, |
||||
|
'account_id': self.payable_account.id, |
||||
|
'name': "Test", |
||||
|
'invoice_line_tax_ids': [(6, 0, [self.tax_15_p.id])], |
||||
|
}), |
||||
|
(0, 0, { |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 100, |
||||
|
'account_id': self.payable_account.id, |
||||
|
'name': "Test", |
||||
|
'invoice_line_tax_ids': [(6, 0, [ |
||||
|
self.tax_15_p.id, self.tax_20_p.id |
||||
|
])], |
||||
|
}) |
||||
|
] |
||||
|
} |
||||
|
invoice = self.InvoiceObj.create(invoice_values) |
||||
|
invoice.action_invoice_open() |
||||
|
|
||||
|
report = self.ReportJournalLedger.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)] |
||||
|
}) |
||||
|
report.compute_data_for_report() |
||||
|
|
||||
|
self.check_report_journal_debit_credit(report, 250, 250) |
||||
|
self.check_report_journal_debit_credit_taxes(report, 300, 0, 50, 0) |
@ -0,0 +1,61 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from datetime import date |
||||
|
from . import abstract_test_foreign_currency as a_t_f_c |
||||
|
|
||||
|
|
||||
|
class TestOpenItems(a_t_f_c.AbstractTestForeignCurrency): |
||||
|
""" |
||||
|
Technical tests for Open Items Report. |
||||
|
""" |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_open_items'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report.report_open_items_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'a_f_r.report_open_items_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report.action_report_open_items_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Odoo' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_at': date(date.today().year, 12, 31), |
||||
|
'company_id': self.company.id, |
||||
|
'foreign_currency': True, |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
return [ |
||||
|
{'only_posted_moves': True}, |
||||
|
{'hide_account_at_0': True}, |
||||
|
{'only_posted_moves': True, 'hide_account_at_0': True}, |
||||
|
] |
||||
|
|
||||
|
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,643 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from datetime import date |
||||
|
from odoo.tests import common |
||||
|
from . import abstract_test_foreign_currency as a_t_f_c |
||||
|
|
||||
|
|
||||
|
class TestTrialBalance(a_t_f_c.AbstractTestForeignCurrency): |
||||
|
""" |
||||
|
Technical tests for Trial Balance Report. |
||||
|
""" |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_trial_balance'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report.report_trial_balance_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'a_f_r.report_trial_balance_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report.action_report_trial_balance_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Odoo' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_from': date(date.today().year, 1, 1), |
||||
|
'date_to': date(date.today().year, 12, 31), |
||||
|
'company_id': self.company.id, |
||||
|
'fy_start_date': date(date.today().year, 1, 1), |
||||
|
'foreign_currency': True, |
||||
|
'show_partner_details': True, |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
return [ |
||||
|
{'only_posted_moves': True}, |
||||
|
{'hide_account_at_0': True}, |
||||
|
{'show_partner_details': True}, |
||||
|
{'hierarchy_on': 'computed'}, |
||||
|
{'hierarchy_on': 'relation'}, |
||||
|
{'only_posted_moves': True, 'hide_account_at_0': True, |
||||
|
'hierarchy_on': 'computed'}, |
||||
|
{'only_posted_moves': True, 'hide_account_at_0': True, |
||||
|
'hierarchy_on': 'relation'}, |
||||
|
{'only_posted_moves': True, 'hide_account_at_0': True}, |
||||
|
{'only_posted_moves': True, 'show_partner_details': True}, |
||||
|
{'hide_account_at_0': True, 'show_partner_details': True}, |
||||
|
{ |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_at_0': True, |
||||
|
'show_partner_details': True |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
def _partner_test_is_possible(self, filters): |
||||
|
return 'show_partner_details' in filters |
||||
|
|
||||
|
|
||||
|
class TestTrialBalanceReport(common.TransactionCase): |
||||
|
|
||||
|
def setUp(self): |
||||
|
super(TestTrialBalanceReport, self).setUp() |
||||
|
group_obj = self.env['account.group'] |
||||
|
acc_obj = self.env['account.account'] |
||||
|
self.group1 = group_obj.create( |
||||
|
{'code_prefix': '1', |
||||
|
'name': 'Group 1'}) |
||||
|
self.group11 = group_obj.create( |
||||
|
{'code_prefix': '11', |
||||
|
'name': 'Group 11', |
||||
|
'parent_id': self.group1.id}) |
||||
|
self.group2 = group_obj.create( |
||||
|
{'code_prefix': '2', |
||||
|
'name': 'Group 2'}) |
||||
|
self.account100 = acc_obj.create( |
||||
|
{'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 = acc_obj.create( |
||||
|
{'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 = acc_obj.create( |
||||
|
{'code': '300', |
||||
|
'name': 'Account 300', |
||||
|
'user_type_id': self.env.ref( |
||||
|
'account.data_account_type_other_income').id}) |
||||
|
self.account301 = acc_obj.create( |
||||
|
{'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' |
||||
|
|
||||
|
def _add_move( |
||||
|
self, |
||||
|
date, |
||||
|
receivable_debit, |
||||
|
receivable_credit, |
||||
|
income_debit, |
||||
|
income_credit, |
||||
|
unaffected_debit=0, |
||||
|
unaffected_credit=0 |
||||
|
): |
||||
|
move_name = 'expense accrual' |
||||
|
journal = self.env['account.journal'].search([], limit=1) |
||||
|
partner = self.env.ref('base.res_partner_12') |
||||
|
move_vals = { |
||||
|
'journal_id': journal.id, |
||||
|
'name': move_name, |
||||
|
'date': date, |
||||
|
'line_ids': [ |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': receivable_debit, |
||||
|
'credit': receivable_credit, |
||||
|
'partner_id': partner.id, |
||||
|
'account_id': self.account100.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': income_debit, |
||||
|
'credit': income_credit, |
||||
|
'partner_id': partner.id, |
||||
|
'account_id': self.account200.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': unaffected_debit, |
||||
|
'credit': unaffected_credit, |
||||
|
'partner_id': partner.id, |
||||
|
'account_id': self.account110.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': receivable_debit, |
||||
|
'credit': receivable_credit, |
||||
|
'partner_id': partner.id, |
||||
|
'account_id': self.account300.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': receivable_credit, |
||||
|
'credit': receivable_debit, |
||||
|
'partner_id': partner.id, |
||||
|
'account_id': self.account301.id}) |
||||
|
]} |
||||
|
move = self.env['account.move'].create(move_vals) |
||||
|
move.post() |
||||
|
|
||||
|
def _get_report_lines(self, with_partners=False, hierarchy_on='computed'): |
||||
|
company = self.env.ref('base.main_company') |
||||
|
trial_balance = self.env['report_trial_balance'].create({ |
||||
|
'date_from': self.date_start, |
||||
|
'date_to': self.date_end, |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_at_0': False, |
||||
|
'hierarchy_on': hierarchy_on, |
||||
|
'company_id': company.id, |
||||
|
'fy_start_date': self.fy_date_start, |
||||
|
'show_partner_details': with_partners, |
||||
|
}) |
||||
|
trial_balance.compute_data_for_report() |
||||
|
lines = {} |
||||
|
report_account_model = self.env['report_trial_balance_account'] |
||||
|
lines['receivable'] = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
('account_id', '=', self.account100.id), |
||||
|
]) |
||||
|
lines['income'] = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
('account_id', '=', self.account200.id), |
||||
|
]) |
||||
|
lines['unaffected'] = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
('account_id', '=', self.account110.id), |
||||
|
]) |
||||
|
lines['group1'] = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
('account_group_id', '=', self.group1.id), |
||||
|
]) |
||||
|
lines['group2'] = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
('account_group_id', '=', self.group2.id), |
||||
|
]) |
||||
|
if with_partners: |
||||
|
report_partner_model = self.env[ |
||||
|
'report_trial_balance_partner' |
||||
|
] |
||||
|
lines['partner_receivable'] = report_partner_model.search([ |
||||
|
('report_account_id', '=', lines['receivable'].id), |
||||
|
('partner_id', '=', self.env.ref('base.res_partner_12').id), |
||||
|
]) |
||||
|
return lines |
||||
|
|
||||
|
def test_00_account_group(self): |
||||
|
self.assertGreaterEqual(len(self.group1.compute_account_ids), 19) |
||||
|
self.assertGreaterEqual(len(self.group2.compute_account_ids), 9) |
||||
|
|
||||
|
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 |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# 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 |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].debit, 0) |
||||
|
self.assertEqual(lines['receivable'].credit, 0) |
||||
|
self.assertEqual(lines['receivable'].final_balance, 1000) |
||||
|
|
||||
|
self.assertEqual(lines['group1'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['group1'].debit, 0) |
||||
|
self.assertEqual(lines['group1'].credit, 0) |
||||
|
self.assertEqual(lines['group1'].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 |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].debit, 0) |
||||
|
self.assertEqual(lines['receivable'].credit, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_balance, 0) |
||||
|
|
||||
|
self.assertEqual(lines['income'].initial_balance, 0) |
||||
|
self.assertEqual(lines['income'].debit, 1000) |
||||
|
self.assertEqual(lines['income'].credit, 0) |
||||
|
self.assertEqual(lines['income'].final_balance, 1000) |
||||
|
|
||||
|
self.assertEqual(lines['group1'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['group1'].debit, 0) |
||||
|
self.assertEqual(lines['group1'].credit, 1000) |
||||
|
self.assertEqual(lines['group1'].final_balance, 0) |
||||
|
|
||||
|
self.assertEqual(lines['group2'].initial_balance, 0) |
||||
|
self.assertEqual(lines['group2'].debit, 1000) |
||||
|
self.assertEqual(lines['group2'].credit, 0) |
||||
|
self.assertEqual(lines['group2'].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 |
||||
|
lines = self._get_report_lines() |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].debit, 0) |
||||
|
self.assertEqual(lines['receivable'].credit, 2000) |
||||
|
self.assertEqual(lines['receivable'].final_balance, -1000) |
||||
|
|
||||
|
self.assertEqual(lines['income'].initial_balance, 0) |
||||
|
self.assertEqual(lines['income'].debit, 2000) |
||||
|
self.assertEqual(lines['income'].credit, 0) |
||||
|
self.assertEqual(lines['income'].final_balance, 2000) |
||||
|
|
||||
|
self.assertEqual(lines['group1'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['group1'].debit, 0) |
||||
|
self.assertEqual(lines['group1'].credit, 2000) |
||||
|
self.assertEqual(lines['group1'].final_balance, -1000) |
||||
|
|
||||
|
self.assertEqual(lines['group2'].initial_balance, 0) |
||||
|
self.assertEqual(lines['group2'].debit, 2000) |
||||
|
self.assertEqual(lines['group2'].credit, 0) |
||||
|
self.assertEqual(lines['group2'].final_balance, 2000) |
||||
|
self.assertEqual(len(lines['group2'].compute_account_ids), 9) |
||||
|
|
||||
|
def test_02_account_balance_hierarchy(self): |
||||
|
# Generate the general ledger line |
||||
|
lines = self._get_report_lines(hierarchy_on='relation') |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# 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 |
||||
|
lines = self._get_report_lines(hierarchy_on='relation') |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].debit, 0) |
||||
|
self.assertEqual(lines['receivable'].credit, 0) |
||||
|
self.assertEqual(lines['receivable'].final_balance, 1000) |
||||
|
|
||||
|
self.assertEqual(lines['group1'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['group1'].debit, 0) |
||||
|
self.assertEqual(lines['group1'].credit, 0) |
||||
|
self.assertEqual(lines['group1'].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 |
||||
|
lines = self._get_report_lines(hierarchy_on='relation') |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].debit, 0) |
||||
|
self.assertEqual(lines['receivable'].credit, 1000) |
||||
|
self.assertEqual(lines['receivable'].final_balance, 0) |
||||
|
|
||||
|
self.assertEqual(lines['income'].initial_balance, 0) |
||||
|
self.assertEqual(lines['income'].debit, 1000) |
||||
|
self.assertEqual(lines['income'].credit, 0) |
||||
|
self.assertEqual(lines['income'].final_balance, 1000) |
||||
|
|
||||
|
self.assertEqual(lines['group1'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['group1'].debit, 0) |
||||
|
self.assertEqual(lines['group1'].credit, 1000) |
||||
|
self.assertEqual(lines['group1'].final_balance, 0) |
||||
|
|
||||
|
self.assertEqual(lines['group2'].initial_balance, 0) |
||||
|
self.assertEqual(lines['group2'].debit, 2000) |
||||
|
self.assertEqual(lines['group2'].credit, 0) |
||||
|
self.assertEqual(lines['group2'].final_balance, 2000) |
||||
|
self.assertEqual(len(lines['group2'].compute_account_ids), 2) |
||||
|
# 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 |
||||
|
lines = self._get_report_lines(hierarchy_on='relation') |
||||
|
self.assertEqual(len(lines['receivable']), 1) |
||||
|
self.assertEqual(len(lines['income']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['receivable'].debit, 0) |
||||
|
self.assertEqual(lines['receivable'].credit, 2000) |
||||
|
self.assertEqual(lines['receivable'].final_balance, -1000) |
||||
|
|
||||
|
self.assertEqual(lines['income'].initial_balance, 0) |
||||
|
self.assertEqual(lines['income'].debit, 2000) |
||||
|
self.assertEqual(lines['income'].credit, 0) |
||||
|
self.assertEqual(lines['income'].final_balance, 2000) |
||||
|
|
||||
|
self.assertEqual(lines['group1'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['group1'].debit, 0) |
||||
|
self.assertEqual(lines['group1'].credit, 2000) |
||||
|
self.assertEqual(lines['group1'].final_balance, -1000) |
||||
|
|
||||
|
self.assertEqual(lines['group2'].initial_balance, 0) |
||||
|
self.assertEqual(lines['group2'].debit, 4000) |
||||
|
self.assertEqual(lines['group2'].credit, 0) |
||||
|
self.assertEqual(lines['group2'].final_balance, 4000) |
||||
|
|
||||
|
def test_03_partner_balance(self): |
||||
|
# Generate the trial balance line |
||||
|
lines = self._get_report_lines(with_partners=True) |
||||
|
self.assertEqual(len(lines['partner_receivable']), 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 trial balance line |
||||
|
lines = self._get_report_lines(with_partners=True) |
||||
|
self.assertEqual(len(lines['partner_receivable']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['partner_receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].debit, 0) |
||||
|
self.assertEqual(lines['partner_receivable'].credit, 0) |
||||
|
self.assertEqual(lines['partner_receivable'].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 |
||||
|
lines = self._get_report_lines(with_partners=True) |
||||
|
self.assertEqual(len(lines['partner_receivable']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['partner_receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].debit, 0) |
||||
|
self.assertEqual(lines['partner_receivable'].credit, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].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 |
||||
|
lines = self._get_report_lines(with_partners=True) |
||||
|
self.assertEqual(len(lines['partner_receivable']), 1) |
||||
|
|
||||
|
# Check the initial and final balance |
||||
|
self.assertEqual(lines['partner_receivable'].initial_balance, 1000) |
||||
|
self.assertEqual(lines['partner_receivable'].debit, 0) |
||||
|
self.assertEqual(lines['partner_receivable'].credit, 2000) |
||||
|
self.assertEqual(lines['partner_receivable'].final_balance, -1000) |
||||
|
|
||||
|
def test_04_undistributed_pl(self): |
||||
|
# Add a P&L Move in the previous FY |
||||
|
move_name = 'current year pl move' |
||||
|
journal = self.env['account.journal'].search([], limit=1) |
||||
|
move_vals = { |
||||
|
'journal_id': journal.id, |
||||
|
'name': move_name, |
||||
|
'date': self.previous_fy_date_end, |
||||
|
'line_ids': [ |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': 0.0, |
||||
|
'credit': 1000.0, |
||||
|
'account_id': self.account300.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': 1000.0, |
||||
|
'credit': 0.0, |
||||
|
'account_id': self.account100.id}) |
||||
|
]} |
||||
|
move = self.env['account.move'].create(move_vals) |
||||
|
move.post() |
||||
|
# Generate the trial balance line |
||||
|
report_account_model = self.env['report_trial_balance_account'] |
||||
|
company = self.env.ref('base.main_company') |
||||
|
trial_balance = self.env['report_trial_balance'].create({ |
||||
|
'date_from': self.date_start, |
||||
|
'date_to': self.date_end, |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_at_0': False, |
||||
|
'hierarchy_on': 'none', |
||||
|
'company_id': company.id, |
||||
|
'fy_start_date': self.fy_date_start, |
||||
|
}) |
||||
|
trial_balance.compute_data_for_report() |
||||
|
|
||||
|
unaffected_balance_lines = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
('account_id', '=', self.account110.id), |
||||
|
]) |
||||
|
self.assertEqual(len(unaffected_balance_lines), 1) |
||||
|
self.assertEqual(unaffected_balance_lines[0].initial_balance, -1000) |
||||
|
self.assertEqual(unaffected_balance_lines[0].debit, 0) |
||||
|
self.assertEqual(unaffected_balance_lines[0].credit, 0) |
||||
|
self.assertEqual(unaffected_balance_lines[0].final_balance, -1000) |
||||
|
# Add a P&L Move to the current FY |
||||
|
move_name = 'current year pl move' |
||||
|
journal = self.env['account.journal'].search([], limit=1) |
||||
|
move_vals = { |
||||
|
'journal_id': journal.id, |
||||
|
'name': move_name, |
||||
|
'date': self.date_start, |
||||
|
'line_ids': [ |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': 0.0, |
||||
|
'credit': 1000.0, |
||||
|
'account_id': self.account300.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': 1000.0, |
||||
|
'credit': 0.0, |
||||
|
'account_id': self.account100.id}) |
||||
|
]} |
||||
|
move = self.env['account.move'].create(move_vals) |
||||
|
move.post() |
||||
|
# Re Generate the trial balance line |
||||
|
trial_balance = self.env['report_trial_balance'].create({ |
||||
|
'date_from': self.date_start, |
||||
|
'date_to': self.date_end, |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_at_0': False, |
||||
|
'hierarchy_on': 'none', |
||||
|
'company_id': company.id, |
||||
|
'fy_start_date': self.fy_date_start, |
||||
|
}) |
||||
|
trial_balance.compute_data_for_report() |
||||
|
unaffected_balance_lines = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
('account_id', '=', self.account110.id), |
||||
|
]) |
||||
|
# The unaffected earnings account is not affected by a journal entry |
||||
|
# made to the P&L in the current fiscal year. |
||||
|
self.assertEqual(len(unaffected_balance_lines), 1) |
||||
|
self.assertEqual(unaffected_balance_lines[0].initial_balance, -1000) |
||||
|
self.assertEqual(unaffected_balance_lines[0].debit, 0) |
||||
|
self.assertEqual(unaffected_balance_lines[0].credit, 0) |
||||
|
self.assertEqual(unaffected_balance_lines[0].final_balance, -1000) |
||||
|
# Add a Move including Unaffected Earnings to the current FY |
||||
|
move_name = 'current year unaffected earnings move' |
||||
|
journal = self.env['account.journal'].search([], limit=1) |
||||
|
move_vals = { |
||||
|
'journal_id': journal.id, |
||||
|
'name': move_name, |
||||
|
'date': self.date_start, |
||||
|
'line_ids': [ |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': 0.0, |
||||
|
'credit': 1000.0, |
||||
|
'account_id': self.account110.id}), |
||||
|
(0, 0, { |
||||
|
'name': move_name, |
||||
|
'debit': 1000.0, |
||||
|
'credit': 0.0, |
||||
|
'account_id': self.account100.id}) |
||||
|
]} |
||||
|
move = self.env['account.move'].create(move_vals) |
||||
|
move.post() |
||||
|
# Re Generate the trial balance line |
||||
|
trial_balance = self.env['report_trial_balance'].create({ |
||||
|
'date_from': self.date_start, |
||||
|
'date_to': self.date_end, |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_at_0': False, |
||||
|
'hierarchy_on': 'none', |
||||
|
'company_id': company.id, |
||||
|
'fy_start_date': self.fy_date_start, |
||||
|
}) |
||||
|
trial_balance.compute_data_for_report() |
||||
|
# The unaffected earnings account affected by a journal entry |
||||
|
# made to the unaffected earnings in the current fiscal year. |
||||
|
unaffected_balance_lines = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
('account_id', '=', self.account110.id), |
||||
|
]) |
||||
|
self.assertEqual(len(unaffected_balance_lines), 1) |
||||
|
self.assertEqual(unaffected_balance_lines[0].initial_balance, -1000) |
||||
|
self.assertEqual(unaffected_balance_lines[0].debit, 0) |
||||
|
self.assertEqual(unaffected_balance_lines[0].credit, 1000) |
||||
|
self.assertEqual(unaffected_balance_lines[0].final_balance, -2000) |
||||
|
# The totals for the Trial Balance are zero |
||||
|
all_lines = report_account_model.search([ |
||||
|
('report_id', '=', trial_balance.id), |
||||
|
]) |
||||
|
self.assertEqual(sum(all_lines.mapped('initial_balance')), 0) |
||||
|
self.assertEqual(sum(all_lines.mapped('final_balance')), 0) |
||||
|
self.assertEqual(sum(all_lines.mapped('debit')), |
||||
|
sum(all_lines.mapped('credit'))) |
@ -0,0 +1,300 @@ |
|||||
|
# Copyright 2018 Forest and Biomass Romania |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
from datetime import date |
||||
|
from odoo.tests import common |
||||
|
from . import abstract_test_tax_report |
||||
|
|
||||
|
|
||||
|
class TestVAT(abstract_test_tax_report.AbstractTest): |
||||
|
""" |
||||
|
Technical tests for VAT Report. |
||||
|
""" |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_vat_report'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report.report_vat_report_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'a_f_r.report_vat_report_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report.action_report_vat_report_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Odoo' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_from': date(date.today().year, 1, 1), |
||||
|
'date_to': date(date.today().year, 12, 31), |
||||
|
'company_id': self.env.user.company_id.id, |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
return [ |
||||
|
{'based_on': 'taxtags'}, |
||||
|
{'based_on': 'taxgroups'}, |
||||
|
{'tax_details': True}, |
||||
|
{'based_on': 'taxtags', 'tax_details': True}, |
||||
|
{'based_on': 'taxgroups', 'tax_details': True}, |
||||
|
] |
||||
|
|
||||
|
|
||||
|
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' |
||||
|
}) |
||||
|
self.tax_tag_02 = self.env['account.account.tag'].create({ |
||||
|
'name': 'Tag 02', |
||||
|
'applicability': 'taxes' |
||||
|
}) |
||||
|
self.tax_tag_03 = self.env['account.account.tag'].create({ |
||||
|
'name': 'Tag 03', |
||||
|
'applicability': 'taxes' |
||||
|
}) |
||||
|
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', |
||||
|
'account_id': self.tax_account.id, |
||||
|
'company_id': self.company.id, |
||||
|
'refund_account_id': self.tax_account.id, |
||||
|
'tax_group_id': self.tax_group_10.id, |
||||
|
'tag_ids': [(6, 0, [self.tax_tag_01.id, self.tax_tag_02.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', |
||||
|
'tax_exigibility': 'on_payment', |
||||
|
'account_id': self.tax_account.id, |
||||
|
'company_id': self.company.id, |
||||
|
'refund_account_id': self.tax_account.id, |
||||
|
'cash_basis_account_id': self.tax_account.id, |
||||
|
'tax_group_id': self.tax_group_20.id, |
||||
|
'tag_ids': [(6, 0, [self.tax_tag_02.id, self.tax_tag_03.id])] |
||||
|
}) |
||||
|
|
||||
|
invoice = self.env['account.invoice'].create({ |
||||
|
'partner_id': self.env.ref('base.res_partner_2').id, |
||||
|
'account_id': self.receivable_account.id, |
||||
|
'company_id': self.company.id, |
||||
|
'date_invoice': time.strftime('%Y-%m-03'), |
||||
|
'type': 'out_invoice', |
||||
|
}) |
||||
|
|
||||
|
self.env['account.invoice.line'].create({ |
||||
|
'product_id': self.env.ref('product.product_product_4').id, |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 100.0, |
||||
|
'invoice_id': invoice.id, |
||||
|
'name': 'product', |
||||
|
'account_id': self.income_account.id, |
||||
|
'invoice_line_tax_ids': [(6, 0, [self.tax_10.id])], |
||||
|
}) |
||||
|
invoice.compute_taxes() |
||||
|
invoice.action_invoice_open() |
||||
|
|
||||
|
self.cbinvoice = self.env['account.invoice'].create({ |
||||
|
'partner_id': self.env.ref('base.res_partner_2').id, |
||||
|
'account_id': self.receivable_account.id, |
||||
|
'company_id': self.company.id, |
||||
|
'date_invoice': time.strftime('%Y-%m-05'), |
||||
|
'type': 'out_invoice', |
||||
|
}) |
||||
|
|
||||
|
self.env['account.invoice.line'].create({ |
||||
|
'product_id': self.env.ref('product.product_product_4').id, |
||||
|
'quantity': 1.0, |
||||
|
'price_unit': 500.0, |
||||
|
'invoice_id': self.cbinvoice.id, |
||||
|
'name': 'product', |
||||
|
'account_id': self.income_account.id, |
||||
|
'invoice_line_tax_ids': [(6, 0, [self.tax_20.id])], |
||||
|
}) |
||||
|
self.cbinvoice.compute_taxes() |
||||
|
self.cbinvoice.action_invoice_open() |
||||
|
|
||||
|
def _get_report_lines(self): |
||||
|
self.cbinvoice.pay_and_reconcile( |
||||
|
self.bank_journal.id, 300, date( |
||||
|
date.today().year, date.today().month, 10)) |
||||
|
vat_report = self.env['report_vat_report'].create({ |
||||
|
'date_from': self.date_from, |
||||
|
'date_to': self.date_to, |
||||
|
'company_id': self.company.id, |
||||
|
'based_on': 'taxtags', |
||||
|
'tax_detail': True, |
||||
|
}) |
||||
|
vat_report.compute_data_for_report() |
||||
|
lines = {} |
||||
|
vat_taxtag_model = self.env['report_vat_report_taxtag'] |
||||
|
lines['tag_01'] = vat_taxtag_model.search([ |
||||
|
('report_id', '=', vat_report.id), |
||||
|
('taxtag_id', '=', self.tax_tag_01.id), |
||||
|
]) |
||||
|
lines['tag_02'] = vat_taxtag_model.search([ |
||||
|
('report_id', '=', vat_report.id), |
||||
|
('taxtag_id', '=', self.tax_tag_02.id), |
||||
|
]) |
||||
|
lines['tag_03'] = vat_taxtag_model.search([ |
||||
|
('report_id', '=', vat_report.id), |
||||
|
('taxtag_id', '=', self.tax_tag_03.id), |
||||
|
]) |
||||
|
vat_tax_model = self.env['report_vat_report_tax'] |
||||
|
lines['tax_10'] = vat_tax_model.search([ |
||||
|
('report_tax_id', '=', lines['tag_02'].id), |
||||
|
('tax_id', '=', self.tax_10.id), |
||||
|
]) |
||||
|
lines['tax_20'] = vat_tax_model.search([ |
||||
|
('report_tax_id', '=', lines['tag_02'].id), |
||||
|
('tax_id', '=', self.tax_20.id), |
||||
|
]) |
||||
|
vat_report['based_on'] = 'taxgroups' |
||||
|
vat_report.compute_data_for_report() |
||||
|
lines['group_10'] = vat_taxtag_model.search([ |
||||
|
('report_id', '=', vat_report.id), |
||||
|
('taxgroup_id', '=', self.tax_group_10.id), |
||||
|
]) |
||||
|
lines['group_20'] = vat_taxtag_model.search([ |
||||
|
('report_id', '=', vat_report.id), |
||||
|
('taxgroup_id', '=', self.tax_group_20.id), |
||||
|
]) |
||||
|
vat_tax_model = self.env['report_vat_report_tax'] |
||||
|
lines['tax_group_10'] = vat_tax_model.search([ |
||||
|
('report_tax_id', '=', lines['group_10'].id), |
||||
|
('tax_id', '=', self.tax_10.id), |
||||
|
]) |
||||
|
lines['tax_group_20'] = vat_tax_model.search([ |
||||
|
('report_tax_id', '=', lines['group_20'].id), |
||||
|
('tax_id', '=', self.tax_20.id), |
||||
|
]) |
||||
|
return lines |
||||
|
|
||||
|
def test_01_compute(self): |
||||
|
# Generate the vat lines |
||||
|
lines = self._get_report_lines() |
||||
|
|
||||
|
# Check report based on taxtags |
||||
|
self.assertEqual(len(lines['tag_01']), 1) |
||||
|
self.assertEqual(len(lines['tag_02']), 1) |
||||
|
self.assertEqual(len(lines['tag_03']), 1) |
||||
|
self.assertEqual(len(lines['tax_10']), 1) |
||||
|
self.assertEqual(len(lines['tax_20']), 1) |
||||
|
self.assertEqual(lines['tag_01'].net, 100) |
||||
|
self.assertEqual(lines['tag_01'].tax, 10) |
||||
|
self.assertEqual(lines['tag_02'].net, 350) |
||||
|
self.assertEqual(lines['tag_02'].tax, 60) |
||||
|
self.assertEqual(lines['tag_03'].net, 250) |
||||
|
self.assertEqual(lines['tag_03'].tax, 50) |
||||
|
self.assertEqual(lines['tax_10'].net, 100) |
||||
|
self.assertEqual(lines['tax_10'].tax, 10) |
||||
|
self.assertEqual(lines['tax_20'].net, 250) |
||||
|
self.assertEqual(lines['tax_20'].tax, 50) |
||||
|
|
||||
|
# Check report based on taxgroups |
||||
|
self.assertEqual(len(lines['group_10']), 1) |
||||
|
self.assertEqual(len(lines['group_20']), 1) |
||||
|
self.assertEqual(len(lines['tax_group_10']), 1) |
||||
|
self.assertEqual(len(lines['tax_group_20']), 1) |
||||
|
self.assertEqual(lines['group_10'].net, 100) |
||||
|
self.assertEqual(lines['group_10'].tax, 10) |
||||
|
self.assertEqual(lines['group_20'].net, 250) |
||||
|
self.assertEqual(lines['group_20'].tax, 50) |
||||
|
self.assertEqual(lines['tax_group_10'].net, 100) |
||||
|
self.assertEqual(lines['tax_group_10'].tax, 10) |
||||
|
self.assertEqual(lines['tax_group_20'].net, 250) |
||||
|
self.assertEqual(lines['tax_group_20'].tax, 50) |
||||
|
|
||||
|
def test_get_report_html(self): |
||||
|
vat_report = self.env['report_vat_report'].create({ |
||||
|
'date_from': self.date_from, |
||||
|
'date_to': self.date_to, |
||||
|
'company_id': self.company.id, |
||||
|
'tax_detail': True, |
||||
|
}) |
||||
|
vat_report.compute_data_for_report() |
||||
|
vat_report.get_html(given_context={}) |
||||
|
|
||||
|
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,58 @@ |
|||||
|
<?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="{'active_model': '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="{'active_model': '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="{'active_model': '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="{'active_model': '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="{'active_model': '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="{'active_model': 'report_vat_report'}" /> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,11 @@ |
|||||
|
<?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,32 @@ |
|||||
|
# 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,127 @@ |
|||||
|
# 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 |
||||
|
from odoo.tools.safe_eval import safe_eval |
||||
|
from odoo.tools import pycompat |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceWizard(models.TransientModel): |
||||
|
"""Aged partner balance report wizard.""" |
||||
|
|
||||
|
_name = 'aged.partner.balance.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) |
||||
|
target_move = fields.Selection([('posted', 'All Posted Entries'), |
||||
|
('all', 'All Entries')], |
||||
|
string='Target Moves', |
||||
|
required=True, |
||||
|
default='all') |
||||
|
account_ids = fields.Many2many( |
||||
|
comodel_name='account.account', |
||||
|
string='Filter accounts', |
||||
|
) |
||||
|
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() |
||||
|
|
||||
|
@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('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.multi |
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
action = self.env.ref( |
||||
|
'account_financial_report.action_report_aged_partner_balance') |
||||
|
vals = action.read()[0] |
||||
|
context1 = vals.get('context', {}) |
||||
|
if isinstance(context1, pycompat.string_types): |
||||
|
context1 = safe_eval(context1) |
||||
|
model = self.env['report_aged_partner_balance'] |
||||
|
report = model.create(self._prepare_report_aged_partner_balance()) |
||||
|
report.compute_data_for_report() |
||||
|
|
||||
|
context1['active_id'] = report.id |
||||
|
context1['active_ids'] = report.ids |
||||
|
vals['context'] = context1 |
||||
|
return vals |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'qweb-pdf' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
|
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 { |
||||
|
'date_at': self.date_at, |
||||
|
'only_posted_moves': self.target_move == 'posted', |
||||
|
'company_id': self.company_id.id, |
||||
|
'filter_account_ids': [(6, 0, self.account_ids.ids)], |
||||
|
'filter_partner_ids': [(6, 0, self.partner_ids.ids)], |
||||
|
'show_move_line_details': self.show_move_line_details, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_aged_partner_balance'] |
||||
|
report = model.create(self._prepare_report_aged_partner_balance()) |
||||
|
report.compute_data_for_report() |
||||
|
return report.print_report(report_type) |
@ -0,0 +1,59 @@ |
|||||
|
<?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.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"/> |
||||
|
</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"/> |
||||
|
<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> |
||||
|
|
||||
|
<act_window id="action_aged_partner_balance_wizard" |
||||
|
name="Aged Partner Balance" |
||||
|
res_model="aged.partner.balance.wizard" |
||||
|
view_type="form" |
||||
|
view_mode="form" |
||||
|
view_id="aged_partner_balance_wizard" |
||||
|
target="new" /> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,259 @@ |
|||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Author: Jordi Ballester |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2017 Akretion - Alexis de Lattre |
||||
|
# Copyright 2017 Eficent Business and IT Consulting Services, S.L. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
|
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.tools.safe_eval import safe_eval |
||||
|
from odoo.tools import pycompat |
||||
|
from odoo.exceptions import ValidationError |
||||
|
import time |
||||
|
|
||||
|
|
||||
|
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='all') |
||||
|
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(), |
||||
|
) |
||||
|
|
||||
|
def _init_date_from(self): |
||||
|
"""set start date to begin of current year if fiscal year running""" |
||||
|
today = fields.Date.context_today(self) |
||||
|
cur_month = fields.Date.from_string(today).month |
||||
|
cur_day = fields.Date.from_string(today).day |
||||
|
last_fsc_month = self.env.user.company_id.fiscalyear_last_month |
||||
|
last_fsc_day = self.env.user.company_id.fiscalyear_last_day |
||||
|
|
||||
|
if cur_month < last_fsc_month \ |
||||
|
or cur_month == last_fsc_month and cur_day <= last_fsc_day: |
||||
|
return time.strftime('%Y-01-01') |
||||
|
|
||||
|
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.filtered('date_from'): |
||||
|
date = fields.Datetime.from_string(wiz.date_from) |
||||
|
res = self.company_id.compute_fiscalyear_dates(date) |
||||
|
wiz.fy_start_date = fields.Date.to_string(res['date_from']) |
||||
|
|
||||
|
@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.multi |
||||
|
@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.multi |
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
action = self.env.ref( |
||||
|
'account_financial_report.action_report_general_ledger') |
||||
|
action_data = action.read()[0] |
||||
|
context1 = action_data.get('context', {}) |
||||
|
if isinstance(context1, pycompat.string_types): |
||||
|
context1 = safe_eval(context1) |
||||
|
model = self.env['report_general_ledger'] |
||||
|
report = model.create(self._prepare_report_general_ledger()) |
||||
|
report.compute_data_for_report() |
||||
|
context1['active_id'] = report.id |
||||
|
context1['active_ids'] = report.ids |
||||
|
action_data['context'] = context1 |
||||
|
return action_data |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'qweb-pdf' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
|
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 { |
||||
|
'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, |
||||
|
'filter_account_ids': [(6, 0, self.account_ids.ids)], |
||||
|
'filter_partner_ids': [(6, 0, self.partner_ids.ids)], |
||||
|
'filter_cost_center_ids': [(6, 0, self.cost_center_ids.ids)], |
||||
|
'filter_analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)], |
||||
|
'filter_journal_ids': [(6, 0, self.account_journal_ids.ids)], |
||||
|
'centralize': self.centralize, |
||||
|
'fy_start_date': self.fy_start_date, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_general_ledger'] |
||||
|
report = model.create(self._prepare_report_general_ledger()) |
||||
|
report.compute_data_for_report() |
||||
|
return report.print_report(report_type) |
@ -0,0 +1,101 @@ |
|||||
|
<?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="hide_account_at_0"/> |
||||
|
<field name="foreign_currency"/> |
||||
|
<field name="show_analytic_tags"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
<notebook> |
||||
|
<page string="Filter accounts"> |
||||
|
<group col="4"> |
||||
|
<field name="receivable_accounts_only"/> |
||||
|
<field name="payable_accounts_only"/> |
||||
|
</group> |
||||
|
<field name="account_ids" |
||||
|
nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}"/> |
||||
|
</page> |
||||
|
<page string="Filter partners"> |
||||
|
<field name="partner_ids" nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}"/> |
||||
|
</page> |
||||
|
<page string="Filter cost centers" groups="analytic.group_analytic_accounting"> |
||||
|
<field name="cost_center_ids" nolabel="1" |
||||
|
options="{'no_create': True}" |
||||
|
groups="analytic.group_analytic_accounting"/> |
||||
|
</page> |
||||
|
<page string="Filter analytic tags"> |
||||
|
<field name="analytic_tag_ids" widget="many2many_tags" nolabel="1" options="{'no_create': True}"/> |
||||
|
</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> |
||||
|
|
||||
|
<act_window id="action_general_ledger_wizard" |
||||
|
name="General Ledger" |
||||
|
res_model="general.ledger.report.wizard" |
||||
|
view_type="form" |
||||
|
view_mode="form" |
||||
|
view_id="general_ledger_wizard" |
||||
|
target="new" /> |
||||
|
|
||||
|
<!--Add to res.partner action--> |
||||
|
<act_window id="act_action_general_ledger_wizard_partner_relation" |
||||
|
name="General Ledger" |
||||
|
res_model="general.ledger.report.wizard" |
||||
|
src_model="res.partner" |
||||
|
view_mode="form" |
||||
|
context="{ |
||||
|
'default_receivable_accounts_only':1, |
||||
|
'default_payable_accounts_only':1, |
||||
|
}" |
||||
|
key2="client_action_multi" |
||||
|
target="new" /> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,160 @@ |
|||||
|
# Copyright 2017 ACSONE SA/NV |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.tools.safe_eval import safe_eval |
||||
|
from odoo.tools import pycompat |
||||
|
|
||||
|
|
||||
|
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='all', |
||||
|
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 |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
action = self.env.ref( |
||||
|
'account_financial_report.action_report_journal_ledger') |
||||
|
vals = action.read()[0] |
||||
|
context1 = vals.get('context', {}) |
||||
|
if isinstance(context1, pycompat.string_types): |
||||
|
context1 = safe_eval(context1) |
||||
|
model = self.env['report_journal_ledger'] |
||||
|
report = model.create(self._prepare_report_journal_ledger()) |
||||
|
report.compute_data_for_report() |
||||
|
context1['active_id'] = report.id |
||||
|
context1['active_ids'] = report.ids |
||||
|
vals['context'] = context1 |
||||
|
return vals |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'qweb-pdf' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'xlsx' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
|
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 { |
||||
|
'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': [(6, 0, journals.ids)], |
||||
|
'sort_option': self.sort_option, |
||||
|
'group_option': self.group_option, |
||||
|
'with_account_name': self.with_account_name, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
self.ensure_one() |
||||
|
model = self.env['report_journal_ledger'] |
||||
|
report = model.create(self._prepare_report_journal_ledger()) |
||||
|
report.compute_data_for_report() |
||||
|
return report.print_report(report_type) |
@ -0,0 +1,66 @@ |
|||||
|
<?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> |
||||
|
|
||||
|
<act_window id="action_journal_ledger_wizard" |
||||
|
name="Journal Ledger" |
||||
|
res_model="journal.ledger.report.wizard" |
||||
|
view_type="form" |
||||
|
view_mode="form" |
||||
|
view_id="journal_ledger_wizard" |
||||
|
target="new" /> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,146 @@ |
|||||
|
# 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 models, fields, api |
||||
|
from odoo.tools.safe_eval import safe_eval |
||||
|
from odoo.tools import pycompat |
||||
|
|
||||
|
|
||||
|
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) |
||||
|
target_move = fields.Selection([('posted', 'All Posted Entries'), |
||||
|
('all', 'All Entries')], |
||||
|
string='Target Moves', |
||||
|
required=True, |
||||
|
default='all') |
||||
|
account_ids = fields.Many2many( |
||||
|
comodel_name='account.account', |
||||
|
string='Filter accounts', |
||||
|
domain=[('reconcile', '=', 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(), |
||||
|
) |
||||
|
|
||||
|
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('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.multi |
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
action = self.env.ref( |
||||
|
'account_financial_report.action_report_open_items') |
||||
|
vals = action.read()[0] |
||||
|
context1 = vals.get('context', {}) |
||||
|
if isinstance(context1, pycompat.string_types): |
||||
|
context1 = safe_eval(context1) |
||||
|
model = self.env['report_open_items'] |
||||
|
report = model.create(self._prepare_report_open_items()) |
||||
|
report.compute_data_for_report() |
||||
|
|
||||
|
context1['active_id'] = report.id |
||||
|
context1['active_ids'] = report.ids |
||||
|
vals['context'] = context1 |
||||
|
return vals |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'qweb-pdf' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
|
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 { |
||||
|
'date_at': self.date_at, |
||||
|
'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, |
||||
|
'filter_account_ids': [(6, 0, self.account_ids.ids)], |
||||
|
'filter_partner_ids': [(6, 0, self.partner_ids.ids)], |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_open_items'] |
||||
|
report = model.create(self._prepare_report_open_items()) |
||||
|
report.compute_data_for_report() |
||||
|
return report.print_report(report_type) |
@ -0,0 +1,74 @@ |
|||||
|
<?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"/> |
||||
|
</group> |
||||
|
<group name="other_filters"> |
||||
|
<field name="target_move" widget="radio"/> |
||||
|
<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"/> |
||||
|
<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> |
||||
|
|
||||
|
<act_window id="action_open_items_wizard" |
||||
|
name="Open Items" |
||||
|
res_model="open.items.report.wizard" |
||||
|
view_type="form" |
||||
|
view_mode="form" |
||||
|
view_id="open_items_wizard" |
||||
|
target="new" /> |
||||
|
|
||||
|
<!--Add to res.partner action--> |
||||
|
<act_window id="act_action_open_items_wizard_partner_relation" |
||||
|
name="Open Items Partner" |
||||
|
res_model="open.items.report.wizard" |
||||
|
src_model="res.partner" |
||||
|
view_mode="form" |
||||
|
context="{ |
||||
|
'default_receivable_accounts_only':1, |
||||
|
'default_payable_accounts_only':1, |
||||
|
}" |
||||
|
key2="client_action_multi" |
||||
|
target="new" /> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,243 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# Copyright 2017 Akretion - Alexis de Lattre |
||||
|
# Copyright 2018 Eficent Business and IT Consuting Services, S.L. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.tools.safe_eval import safe_eval |
||||
|
from odoo.tools import pycompat |
||||
|
from odoo.exceptions import UserError, ValidationError |
||||
|
|
||||
|
|
||||
|
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='all') |
||||
|
hierarchy_on = fields.Selection( |
||||
|
[('computed', 'Computed Accounts'), |
||||
|
('relation', 'Child Accounts'), |
||||
|
('none', 'No hierarchy')], |
||||
|
string='Hierarchy On', |
||||
|
required=True, |
||||
|
default='computed', |
||||
|
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.' |
||||
|
) |
||||
|
|
||||
|
@api.multi |
||||
|
@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.filtered('date_from'): |
||||
|
date = fields.Datetime.from_string(wiz.date_from) |
||||
|
res = self.company_id.compute_fiscalyear_dates(date) |
||||
|
wiz.fy_start_date = fields.Date.to_string(res['date_from']) |
||||
|
|
||||
|
@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.multi |
||||
|
@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.multi |
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
action = self.env.ref( |
||||
|
'account_financial_report.action_report_trial_balance') |
||||
|
vals = action.read()[0] |
||||
|
context1 = vals.get('context', {}) |
||||
|
if isinstance(context1, pycompat.string_types): |
||||
|
context1 = safe_eval(context1) |
||||
|
model = self.env['report_trial_balance'] |
||||
|
report = model.create(self._prepare_report_trial_balance()) |
||||
|
report.compute_data_for_report() |
||||
|
|
||||
|
context1['active_id'] = report.id |
||||
|
context1['active_ids'] = report.ids |
||||
|
vals['context'] = context1 |
||||
|
return vals |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'qweb-pdf' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
|
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 { |
||||
|
'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, |
||||
|
'filter_account_ids': [(6, 0, self.account_ids.ids)], |
||||
|
'filter_partner_ids': [(6, 0, self.partner_ids.ids)], |
||||
|
'filter_journal_ids': [(6, 0, self.journal_ids.ids)], |
||||
|
'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, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_trial_balance'] |
||||
|
report = model.create(self._prepare_report_trial_balance()) |
||||
|
report.compute_data_for_report() |
||||
|
return report.print_report(report_type) |
@ -0,0 +1,91 @@ |
|||||
|
<?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','=','none'),('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"/> |
||||
|
<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> |
||||
|
|
||||
|
<act_window id="action_trial_balance_wizard" |
||||
|
name="Trial Balance" |
||||
|
res_model="trial.balance.report.wizard" |
||||
|
view_type="form" |
||||
|
view_mode="form" |
||||
|
view_id="trial_balance_wizard" |
||||
|
target="new" /> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,109 @@ |
|||||
|
# 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.tools.safe_eval import safe_eval |
||||
|
from odoo.tools import pycompat |
||||
|
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') |
||||
|
|
||||
|
@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.multi |
||||
|
@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.')) |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_html(self): |
||||
|
self.ensure_one() |
||||
|
action = self.env.ref( |
||||
|
'account_financial_report.action_report_vat_report') |
||||
|
vals = action.read()[0] |
||||
|
context1 = vals.get('context', {}) |
||||
|
if isinstance(context1, pycompat.string_types): |
||||
|
context1 = safe_eval(context1) |
||||
|
model = self.env['report_vat_report'] |
||||
|
report = model.create(self._prepare_vat_report()) |
||||
|
report.compute_data_for_report() |
||||
|
context1['active_id'] = report.id |
||||
|
context1['active_ids'] = report.ids |
||||
|
vals['context'] = context1 |
||||
|
return vals |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'qweb-pdf' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
|
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 { |
||||
|
'company_id': self.company_id.id, |
||||
|
'date_from': self.date_from, |
||||
|
'date_to': self.date_to, |
||||
|
'based_on': self.based_on, |
||||
|
'tax_detail': self.tax_detail, |
||||
|
} |
||||
|
|
||||
|
def _export(self, report_type): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_vat_report'] |
||||
|
report = model.create(self._prepare_vat_report()) |
||||
|
report.compute_data_for_report() |
||||
|
return report.print_report(report_type) |
@ -0,0 +1,44 @@ |
|||||
|
<?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 name="other_filters"> |
||||
|
<field name="based_on" widget="radio"/> |
||||
|
<field name="tax_detail"/> |
||||
|
</group> |
||||
|
</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> |
||||
|
|
||||
|
<act_window id="action_vat_report_wizard" |
||||
|
name="VAT Report" |
||||
|
res_model="vat.report.wizard" |
||||
|
view_type="form" |
||||
|
view_mode="form" |
||||
|
view_id="vat_report_wizard" |
||||
|
target="new" /> |
||||
|
</odoo> |
@ -1 +1,2 @@ |
|||||
server-ux |
server-ux |
||||
|
reporting-engine |
@ -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