Merge pull request #559 from eLBati/12.0-mig-account_financial_report-2
[12.0] mig account_financial_reportpull/579/head
commit
7d63e28ab1
|
@ -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',
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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>
|
Binary file not shown.
After Width: | Height: | 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
|
||||
reporting-engine
|
|
@ -0,0 +1 @@
|
|||
../../../../account_financial_report
|
|
@ -0,0 +1,6 @@
|
|||
import setuptools
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['setuptools-odoo'],
|
||||
odoo_addon=True,
|
||||
)
|
Loading…
Reference in New Issue