Frédéric Clementi
8 years ago
committed by
GitHub
46 changed files with 8943 additions and 0 deletions
-
70account_financial_report_qweb/README.rst
-
8account_financial_report_qweb/__init__.py
-
44account_financial_report_qweb/__openerp__.py
-
1365account_financial_report_qweb/i18n/account_financial_report_qweb.pot
-
1365account_financial_report_qweb/i18n/fr.po
-
87account_financial_report_qweb/menuitems.xml
-
6account_financial_report_qweb/models/__init__.py
-
14account_financial_report_qweb/models/account.py
-
15account_financial_report_qweb/report/__init__.py
-
301account_financial_report_qweb/report/abstract_report_xlsx.py
-
607account_financial_report_qweb/report/aged_partner_balance.py
-
269account_financial_report_qweb/report/aged_partner_balance_xlsx.py
-
1151account_financial_report_qweb/report/general_ledger.py
-
149account_financial_report_qweb/report/general_ledger_xlsx.py
-
724account_financial_report_qweb/report/open_items.py
-
117account_financial_report_qweb/report/open_items_xlsx.py
-
327account_financial_report_qweb/report/templates/aged_partner_balance.xml
-
250account_financial_report_qweb/report/templates/general_ledger.xml
-
38account_financial_report_qweb/report/templates/layouts.xml
-
187account_financial_report_qweb/report/templates/open_items.xml
-
154account_financial_report_qweb/report/templates/trial_balance.xml
-
249account_financial_report_qweb/report/trial_balance.py
-
133account_financial_report_qweb/report/trial_balance_xlsx.py
-
114account_financial_report_qweb/reports.xml
-
BINaccount_financial_report_qweb/static/description/icon.png
-
95account_financial_report_qweb/static/src/css/report.css
-
9account_financial_report_qweb/tests/__init__.py
-
204account_financial_report_qweb/tests/abstract_test.py
-
42account_financial_report_qweb/tests/test_aged_partner_balance.py
-
52account_financial_report_qweb/tests/test_general_ledger.py
-
41account_financial_report_qweb/tests/test_open_items.py
-
54account_financial_report_qweb/tests/test_trial_balance.py
-
14account_financial_report_qweb/view/account_view.xml
-
9account_financial_report_qweb/wizard/__init__.py
-
81account_financial_report_qweb/wizard/aged_partner_balance_wizard.py
-
50account_financial_report_qweb/wizard/aged_partner_balance_wizard_view.xml
-
136account_financial_report_qweb/wizard/general_ledger_wizard.py
-
70account_financial_report_qweb/wizard/general_ledger_wizard_view.xml
-
87account_financial_report_qweb/wizard/open_items_wizard.py
-
50account_financial_report_qweb/wizard/open_items_wizard_view.xml
-
129account_financial_report_qweb/wizard/trial_balance_wizard.py
-
67account_financial_report_qweb/wizard/trial_balance_wizard_view.xml
-
1oca_dependencies.txt
-
1setup/account_financial_report_qweb/odoo_addons/__init__.py
-
1setup/account_financial_report_qweb/odoo_addons/account_financial_report_qweb
-
6setup/account_financial_report_qweb/setup.py
@ -0,0 +1,70 @@ |
|||||
|
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
||||
|
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
||||
|
:alt: License: AGPL-3 |
||||
|
|
||||
|
============================= |
||||
|
account_financial_report_qweb |
||||
|
============================= |
||||
|
|
||||
|
This module adds a set of financial reports. They are accessible under |
||||
|
Accunting / Reporting / OCA Reports. |
||||
|
|
||||
|
- General ledger |
||||
|
- Trial Balance |
||||
|
- Open Items |
||||
|
- Aged Partner Balance |
||||
|
|
||||
|
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
||||
|
:alt: Try me on Runbot |
||||
|
:target: https://runbot.odoo-community.org/runbot/91/9.0 |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
|
||||
|
Images |
||||
|
------ |
||||
|
|
||||
|
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_. |
||||
|
|
||||
|
Contributors |
||||
|
------------ |
||||
|
|
||||
|
* Jordi Ballestrer <jordi.ballestrer@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 <lorenzo.battistini@agilebg.com> |
||||
|
* Julien Coux <julien.coux@camptocamp.com> |
||||
|
|
||||
|
Much of the work in this module was done at a sprint in Sorrento, Italy in |
||||
|
April 2016. |
||||
|
|
||||
|
Maintainer |
||||
|
---------- |
||||
|
|
||||
|
.. image:: https://odoo-community.org/logo.png |
||||
|
:alt: Odoo Community Association |
||||
|
:target: https://odoo-community.org |
||||
|
|
||||
|
This module is maintained by the OCA. |
||||
|
|
||||
|
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. |
||||
|
|
||||
|
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +1,8 @@ |
|||||
|
# -*- coding: utf-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 wizard |
||||
|
from . import report |
@ -0,0 +1,44 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
{ |
||||
|
'name': 'QWeb Financial Reports', |
||||
|
'version': '9.0.1.0.0', |
||||
|
'category': 'Reporting', |
||||
|
'summary': 'OCA Financial Reports', |
||||
|
'author': 'Camptocamp SA,' |
||||
|
'initOS GmbH,' |
||||
|
'redCOR AG,' |
||||
|
'Odoo Community Association (OCA)', |
||||
|
"website": "https://odoo-community.org/", |
||||
|
'depends': [ |
||||
|
'account', |
||||
|
'account_full_reconcile', |
||||
|
'date_range', |
||||
|
'account_fiscal_year', |
||||
|
'report_xlsx', |
||||
|
'report', |
||||
|
], |
||||
|
'data': [ |
||||
|
'wizard/aged_partner_balance_wizard_view.xml', |
||||
|
'wizard/general_ledger_wizard_view.xml', |
||||
|
'wizard/open_items_wizard_view.xml', |
||||
|
'wizard/trial_balance_wizard_view.xml', |
||||
|
'menuitems.xml', |
||||
|
'reports.xml', |
||||
|
'report/templates/aged_partner_balance.xml', |
||||
|
'report/templates/general_ledger.xml', |
||||
|
'report/templates/layouts.xml', |
||||
|
'report/templates/open_items.xml', |
||||
|
'report/templates/trial_balance.xml', |
||||
|
'view/account_view.xml' |
||||
|
], |
||||
|
'test': [ |
||||
|
], |
||||
|
'installable': True, |
||||
|
'application': True, |
||||
|
'auto_install': False, |
||||
|
'license': 'AGPL-3', |
||||
|
} |
1365
account_financial_report_qweb/i18n/account_financial_report_qweb.pot
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1365
account_financial_report_qweb/i18n/fr.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,87 @@ |
|||||
|
<?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_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" |
||||
|
/> |
||||
|
|
||||
|
<!-- Hide odoo PDF reports menu --> |
||||
|
<menuitem |
||||
|
id="account.menu_finance_legal_statement" |
||||
|
name="PDF Reports" |
||||
|
parent="account.menu_finance_reports" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_general_ledger" |
||||
|
name="General Ledger" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
action="account.action_account_general_ledger_menu" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_general_Balance_report" |
||||
|
name="Trial Balance" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
action="account.action_account_balance_menu" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_account_report_bs" |
||||
|
name="Balance Sheet" |
||||
|
action="account.action_account_report_bs" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_account_report_pl" |
||||
|
name="Profit and Loss" |
||||
|
action="account.action_account_report_pl" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_aged_trial_balance" |
||||
|
name="Aged Partner Balance" |
||||
|
action="account.action_account_aged_balance_view" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,6 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Damien Crier |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import account |
@ -0,0 +1,14 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2011 Guewen Baconnier (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
from openerp 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,15 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2015 Yannick Vaucher (Camptocamp) |
||||
|
# © 2016 Damien Crier (Camptocamp) |
||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
|
||||
|
from . import abstract_report_xlsx |
||||
|
from . import aged_partner_balance |
||||
|
from . import aged_partner_balance_xlsx |
||||
|
from . import general_ledger |
||||
|
from . import general_ledger_xlsx |
||||
|
from . import open_items |
||||
|
from . import open_items_xlsx |
||||
|
from . import trial_balance |
||||
|
from . import trial_balance_xlsx |
@ -0,0 +1,301 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from openerp.addons.report_xlsx.report.report_xlsx import ReportXlsx |
||||
|
|
||||
|
|
||||
|
class AbstractReportXslx(ReportXlsx): |
||||
|
|
||||
|
def __init__(self, name, table, rml=False, parser=False, header=True, |
||||
|
store=False): |
||||
|
super(AbstractReportXslx, self).__init__( |
||||
|
name, table, rml, parser, header, store) |
||||
|
|
||||
|
# 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_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 generate_xlsx_report(self, workbook, data, objects): |
||||
|
report = objects |
||||
|
|
||||
|
self.row_pos = 0 |
||||
|
|
||||
|
self._define_formats(workbook) |
||||
|
|
||||
|
report_name = self._get_report_name() |
||||
|
filters = self._get_report_filters(report) |
||||
|
self.columns = self._get_report_columns(report) |
||||
|
|
||||
|
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) |
||||
|
|
||||
|
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_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'}) |
||||
|
self.format_header_amount.set_num_format('#,##0.00') |
||||
|
self.format_amount = workbook.add_format() |
||||
|
self.format_amount.set_num_format('#,##0.00') |
||||
|
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.iteritems(): |
||||
|
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_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.iteritems(): |
||||
|
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.iteritems(): |
||||
|
value = getattr(line_object, column['field']) |
||||
|
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 |
||||
|
) |
||||
|
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.iteritems(): |
||||
|
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 |
||||
|
) |
||||
|
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.iteritems(): |
||||
|
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 |
||||
|
) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
def _generate_report_content(self, workbook, report): |
||||
|
pass |
||||
|
|
||||
|
def _get_report_name(self): |
||||
|
""" |
||||
|
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_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,607 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from openerp 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_qweb' |
||||
|
|
||||
|
# 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_qweb') |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
account_ids = fields.One2many( |
||||
|
comodel_name='report_aged_partner_balance_qweb_account', |
||||
|
inverse_name='report_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReportAccount(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_aged_partner_balance_qweb_account' |
||||
|
_order = 'code ASC' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_aged_partner_balance_qweb', |
||||
|
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_qweb_partner', |
||||
|
inverse_name='report_account_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReportPartner(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_aged_partner_balance_qweb_partner' |
||||
|
|
||||
|
report_account_id = fields.Many2one( |
||||
|
comodel_name='report_aged_partner_balance_qweb_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_qweb_move_line', |
||||
|
inverse_name='report_partner_id' |
||||
|
) |
||||
|
line_ids = fields.One2many( |
||||
|
comodel_name='report_aged_partner_balance_qweb_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_qweb_partner"."partner_id" IS NOT NULL |
||||
|
THEN 0 |
||||
|
ELSE 1 |
||||
|
END, |
||||
|
"report_aged_partner_balance_qweb_partner"."name" |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceReportLine(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_aged_partner_balance_qweb_line' |
||||
|
|
||||
|
report_partner_id = fields.Many2one( |
||||
|
comodel_name='report_aged_partner_balance_qweb_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_qweb_move_line' |
||||
|
|
||||
|
report_partner_id = fields.Many2one( |
||||
|
comodel_name='report_aged_partner_balance_qweb_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_qweb' |
||||
|
|
||||
|
@api.multi |
||||
|
def print_report(self, xlsx_report=False): |
||||
|
self.ensure_one() |
||||
|
self.compute_data_for_report() |
||||
|
if xlsx_report: |
||||
|
report_name = 'account_financial_report_qweb.' \ |
||||
|
'report_aged_partner_balance_xlsx' |
||||
|
else: |
||||
|
report_name = 'account_financial_report_qweb.' \ |
||||
|
'report_aged_partner_balance_qweb' |
||||
|
return self.env['report'].get_action(records=self, |
||||
|
report_name=report_name) |
||||
|
|
||||
|
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_qweb'] |
||||
|
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.refresh() |
||||
|
|
||||
|
def _inject_account_values(self): |
||||
|
"""Inject report values for report_aged_partner_balance_qweb_account""" |
||||
|
query_inject_account = """ |
||||
|
INSERT INTO |
||||
|
report_aged_partner_balance_qweb_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_qweb_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_qweb_partner""" |
||||
|
query_inject_partner = """ |
||||
|
INSERT INTO |
||||
|
report_aged_partner_balance_qweb_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_qweb_partner rpo |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_account rao ON rpo.report_account_id = rao.id |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_qweb_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_qweb_line. |
||||
|
|
||||
|
The "only_empty_partner_line" value is used |
||||
|
to compute data without partner. |
||||
|
""" |
||||
|
query_inject_line = """ |
||||
|
WITH |
||||
|
date_range AS |
||||
|
( |
||||
|
SELECT |
||||
|
%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, |
||||
|
DATE %s - INTEGER '150' AS date_older |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_aged_partner_balance_qweb_line |
||||
|
( |
||||
|
report_partner_id, |
||||
|
partner, |
||||
|
amount_residual, |
||||
|
current, |
||||
|
age_30_days, |
||||
|
age_60_days, |
||||
|
age_90_days, |
||||
|
age_120_days, |
||||
|
older |
||||
|
) |
||||
|
SELECT |
||||
|
rp.id AS report_partner_id, |
||||
|
rp.name, |
||||
|
SUM(rlo.amount_residual) AS amount_residual, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN rlo.date_due > date_range.date_less_30_days |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS current, |
||||
|
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_30_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_60_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_90_days, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due > date_range.date_older |
||||
|
AND rlo.date_due <= date_range.date_less_120_days |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS age_120_days, |
||||
|
SUM( |
||||
|
CASE |
||||
|
WHEN rlo.date_due <= date_range.date_older |
||||
|
THEN rlo.amount_residual |
||||
|
END |
||||
|
) AS older |
||||
|
FROM |
||||
|
date_range, |
||||
|
report_open_items_qweb_move_line rlo |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_partner rpo ON rlo.report_partner_id = rpo.id |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_account rao ON rpo.report_account_id = rao.id |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_qweb_account ra ON rao.code = ra.code |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_qweb_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,) * 6 |
||||
|
query_inject_line_params += ( |
||||
|
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_qweb_move_line |
||||
|
|
||||
|
The "only_empty_partner_line" value is used |
||||
|
to compute data without partner. |
||||
|
""" |
||||
|
query_inject_move_line = """ |
||||
|
WITH |
||||
|
date_range AS |
||||
|
( |
||||
|
SELECT |
||||
|
%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, |
||||
|
DATE %s - INTEGER '150' AS date_older |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_aged_partner_balance_qweb_move_line |
||||
|
( |
||||
|
report_partner_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, |
||||
|
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_less_30_days |
||||
|
THEN rlo.amount_residual |
||||
|
END AS current, |
||||
|
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_30_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_60_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_90_days, |
||||
|
CASE |
||||
|
WHEN |
||||
|
rlo.date_due > date_range.date_older |
||||
|
AND rlo.date_due <= date_range.date_less_120_days |
||||
|
THEN rlo.amount_residual |
||||
|
END AS age_120_days, |
||||
|
CASE |
||||
|
WHEN rlo.date_due <= date_range.date_older |
||||
|
THEN rlo.amount_residual |
||||
|
END AS older |
||||
|
FROM |
||||
|
date_range, |
||||
|
report_open_items_qweb_move_line rlo |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_partner rpo ON rlo.report_partner_id = rpo.id |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_account rao ON rpo.report_account_id = rao.id |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_qweb_account ra ON rao.code = ra.code |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_qweb_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,) * 6 |
||||
|
query_inject_move_line_params += ( |
||||
|
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_qweb_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_qweb_line rl |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_qweb_partner rp |
||||
|
ON rl.report_partner_id = rp.id |
||||
|
INNER JOIN |
||||
|
report_aged_partner_balance_qweb_account ra |
||||
|
ON rp.report_account_id = ra.id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
GROUP BY |
||||
|
ra.id |
||||
|
) |
||||
|
UPDATE |
||||
|
report_aged_partner_balance_qweb_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,269 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import abstract_report_xlsx |
||||
|
from openerp.report import report_sxw |
||||
|
from openerp import _ |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalanceXslx(abstract_report_xlsx.AbstractReportXslx): |
||||
|
|
||||
|
def __init__(self, name, table, rml=False, parser=False, header=True, |
||||
|
store=False): |
||||
|
super(AgedPartnerBalanceXslx, self).__init__( |
||||
|
name, table, rml, parser, header, store) |
||||
|
|
||||
|
def _get_report_name(self): |
||||
|
return _('Aged Partner Balance') |
||||
|
|
||||
|
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}, |
||||
|
} |
||||
|
else: |
||||
|
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.iteritems(): |
||||
|
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 |
||||
|
|
||||
|
|
||||
|
AgedPartnerBalanceXslx( |
||||
|
'report.account_financial_report_qweb.report_aged_partner_balance_xlsx', |
||||
|
'report_aged_partner_balance_qweb', |
||||
|
parser=report_sxw.rml_parse |
||||
|
) |
1151
account_financial_report_qweb/report/general_ledger.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,149 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import abstract_report_xlsx |
||||
|
from openerp.report import report_sxw |
||||
|
from openerp import _ |
||||
|
|
||||
|
|
||||
|
class GeneralLedgerXslx(abstract_report_xlsx.AbstractReportXslx): |
||||
|
|
||||
|
def __init__(self, name, table, rml=False, parser=False, header=True, |
||||
|
store=False): |
||||
|
super(GeneralLedgerXslx, self).__init__( |
||||
|
name, table, rml, parser, header, store) |
||||
|
|
||||
|
def _get_report_name(self): |
||||
|
return _('General Ledger') |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
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': _('Cost center'), |
||||
|
'field': 'cost_center', |
||||
|
'width': 15}, |
||||
|
7: {'header': _('Rec.'), 'field': 'matching_number', 'width': 5}, |
||||
|
8: {'header': _('Debit'), |
||||
|
'field': 'debit', |
||||
|
'field_initial_balance': 'initial_debit', |
||||
|
'field_final_balance': 'final_debit', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
9: {'header': _('Credit'), |
||||
|
'field': 'credit', |
||||
|
'field_initial_balance': 'initial_credit', |
||||
|
'field_final_balance': 'final_credit', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
10: {'header': _('Cumul. Bal.'), |
||||
|
'field': 'cumul_balance', |
||||
|
'field_initial_balance': 'initial_balance', |
||||
|
'field_final_balance': 'final_balance', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
11: {'header': _('Cur.'), 'field': 'currency_name', 'width': 7}, |
||||
|
12: {'header': _('Amount cur.'), |
||||
|
'field': 'amount_currency', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
} |
||||
|
|
||||
|
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_balance_at_0 else _('Show')], |
||||
|
[_('Centralize filter'), |
||||
|
_('Yes') if report.centralize 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, _('Initial balance')) |
||||
|
|
||||
|
# 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, _('Initial balance')) |
||||
|
|
||||
|
# 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 General Ledger""" |
||||
|
if type_object == 'partner': |
||||
|
name = my_object.name |
||||
|
label = _('Partner ending balance') |
||||
|
elif type_object == 'account': |
||||
|
name = my_object.code + ' - ' + my_object.name |
||||
|
label = _('Ending balance') |
||||
|
super(GeneralLedgerXslx, self).write_ending_balance( |
||||
|
my_object, name, label |
||||
|
) |
||||
|
|
||||
|
|
||||
|
GeneralLedgerXslx( |
||||
|
'report.account_financial_report_qweb.report_general_ledger_xlsx', |
||||
|
'report_general_ledger_qweb', |
||||
|
parser=report_sxw.rml_parse |
||||
|
) |
@ -0,0 +1,724 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from openerp 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_qweb' |
||||
|
|
||||
|
# Filters fields, used for data computation |
||||
|
date_at = fields.Date() |
||||
|
only_posted_moves = fields.Boolean() |
||||
|
hide_account_balance_at_0 = 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') |
||||
|
|
||||
|
# Flag fields, used for report display |
||||
|
has_second_currency = fields.Boolean() |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
account_ids = fields.One2many( |
||||
|
comodel_name='report_open_items_qweb_account', |
||||
|
inverse_name='report_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportAccount(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_open_items_qweb_account' |
||||
|
_order = 'code ASC' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_open_items_qweb', |
||||
|
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() |
||||
|
final_amount_residual = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
partner_ids = fields.One2many( |
||||
|
comodel_name='report_open_items_qweb_partner', |
||||
|
inverse_name='report_account_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportPartner(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_open_items_qweb_partner' |
||||
|
|
||||
|
report_account_id = fields.Many2one( |
||||
|
comodel_name='report_open_items_qweb_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() |
||||
|
final_amount_residual = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
move_line_ids = fields.One2many( |
||||
|
comodel_name='report_open_items_qweb_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_qweb_partner"."partner_id" IS NOT NULL |
||||
|
THEN 0 |
||||
|
ELSE 1 |
||||
|
END, |
||||
|
"report_open_items_qweb_partner"."name" |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportMoveLine(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_open_items_qweb_move_line' |
||||
|
|
||||
|
report_partner_id = fields.Many2one( |
||||
|
comodel_name='report_open_items_qweb_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_name = fields.Char() |
||||
|
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_qweb' |
||||
|
|
||||
|
@api.multi |
||||
|
def print_report(self, xlsx_report=False): |
||||
|
self.ensure_one() |
||||
|
self.compute_data_for_report() |
||||
|
if xlsx_report: |
||||
|
report_name = 'account_financial_report_qweb.' \ |
||||
|
'report_open_items_xlsx' |
||||
|
else: |
||||
|
report_name = 'account_financial_report_qweb.' \ |
||||
|
'report_open_items_qweb' |
||||
|
return self.env['report'].get_action(records=self, |
||||
|
report_name=report_name) |
||||
|
|
||||
|
@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_balance_at_0: |
||||
|
self._clean_partners_and_accounts( |
||||
|
only_delete_account_balance_at_0=True |
||||
|
) |
||||
|
# Compute display flag |
||||
|
self._compute_has_second_currency() |
||||
|
# Refresh cache because all data are computed with SQL requests |
||||
|
self.refresh() |
||||
|
|
||||
|
def _inject_account_values(self): |
||||
|
"""Inject report values for report_open_items_qweb_account.""" |
||||
|
query_inject_account = """ |
||||
|
WITH |
||||
|
accounts AS |
||||
|
( |
||||
|
SELECT |
||||
|
a.id, |
||||
|
a.code, |
||||
|
a.name, |
||||
|
a.user_type_id |
||||
|
FROM |
||||
|
account_account a |
||||
|
INNER JOIN |
||||
|
account_move_line ml ON a.id = ml.account_id AND ml.date <= %s |
||||
|
""" |
||||
|
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.internal_type IN ('payable', 'receivable') |
||||
|
""" |
||||
|
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 |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_open_items_qweb_account |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
account_id, |
||||
|
code, |
||||
|
name |
||||
|
) |
||||
|
SELECT |
||||
|
%s AS report_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
a.id AS account_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_qweb_partner. """ |
||||
|
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_qweb_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_qweb_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 _inject_line_values(self, only_empty_partner_line=False): |
||||
|
""" Inject report values for report_open_items_qweb_move_line. |
||||
|
|
||||
|
The "only_empty_partner_line" value is used |
||||
|
to compute data without partner. |
||||
|
""" |
||||
|
query_inject_move_line = """ |
||||
|
WITH |
||||
|
move_lines_amount AS |
||||
|
( |
||||
|
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 |
||||
|
FROM |
||||
|
report_open_items_qweb_partner rp |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_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: |
||||
|
query_inject_move_line += """ |
||||
|
AND rp.partner_id = ml.partner_id |
||||
|
""" |
||||
|
elif only_empty_partner_line: |
||||
|
query_inject_move_line += """ |
||||
|
AND ml.partner_id IS NULL |
||||
|
""" |
||||
|
query_inject_move_line += """ |
||||
|
LEFT JOIN |
||||
|
account_partial_reconcile pr |
||||
|
ON ml.balance < 0 AND pr.credit_move_id = ml.id |
||||
|
OR ml.balance > 0 AND pr.debit_move_id = ml.id |
||||
|
LEFT JOIN |
||||
|
account_move_line ml_future |
||||
|
ON ( |
||||
|
ml.balance < 0 AND pr.debit_move_id = ml_future.id |
||||
|
OR 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.debit_move_id = ml_past.id |
||||
|
OR ml.balance > 0 AND pr.credit_move_id = ml_past.id |
||||
|
) |
||||
|
AND ml_past.date < %s |
||||
|
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 |
||||
|
) |
||||
|
|
||||
|
), |
||||
|
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 |
||||
|
FROM |
||||
|
move_lines_amount |
||||
|
GROUP BY |
||||
|
id, |
||||
|
balance, |
||||
|
amount_currency |
||||
|
) |
||||
|
INSERT INTO |
||||
|
report_open_items_qweb_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_name, |
||||
|
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.name AS currency_name, |
||||
|
ml.amount_currency, |
||||
|
ml2.amount_residual_currency |
||||
|
FROM |
||||
|
report_open_items_qweb_partner rp |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_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 a.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.env.uid, |
||||
|
self.id, |
||||
|
self.date_at,) |
||||
|
) |
||||
|
|
||||
|
def _compute_partners_and_accounts_cumul(self): |
||||
|
""" Compute cumulative amount for |
||||
|
report_open_items_qweb_partner and report_open_items_qweb_account. |
||||
|
""" |
||||
|
query_compute_partners_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_qweb_partner |
||||
|
SET |
||||
|
final_amount_residual = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rml.amount_residual) AS final_amount_residual |
||||
|
FROM |
||||
|
report_open_items_qweb_move_line rml |
||||
|
WHERE |
||||
|
rml.report_partner_id = report_open_items_qweb_partner.id |
||||
|
) |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
rp.id |
||||
|
FROM |
||||
|
report_open_items_qweb_account ra |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
WHERE |
||||
|
ra.report_id = %s |
||||
|
) |
||||
|
""" |
||||
|
params_compute_partners_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_partners_cumul, |
||||
|
params_compute_partners_cumul) |
||||
|
query_compute_accounts_cumul = """ |
||||
|
UPDATE |
||||
|
report_open_items_qweb_account |
||||
|
SET |
||||
|
final_amount_residual = |
||||
|
( |
||||
|
SELECT |
||||
|
SUM(rp.final_amount_residual) AS final_amount_residual |
||||
|
FROM |
||||
|
report_open_items_qweb_partner rp |
||||
|
WHERE |
||||
|
rp.report_account_id = report_open_items_qweb_account.id |
||||
|
) |
||||
|
WHERE |
||||
|
report_id = %s |
||||
|
""" |
||||
|
params_compute_accounts_cumul = (self.id,) |
||||
|
self.env.cr.execute(query_compute_accounts_cumul, |
||||
|
params_compute_accounts_cumul) |
||||
|
|
||||
|
def _clean_partners_and_accounts(self, |
||||
|
only_delete_account_balance_at_0=False): |
||||
|
""" Delete empty data for |
||||
|
report_open_items_qweb_partner and report_open_items_qweb_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_qweb_partner |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
DISTINCT rp.id |
||||
|
FROM |
||||
|
report_open_items_qweb_account ra |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_partner rp |
||||
|
ON ra.id = rp.report_account_id |
||||
|
LEFT JOIN |
||||
|
report_open_items_qweb_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_qweb_account |
||||
|
WHERE |
||||
|
id IN |
||||
|
( |
||||
|
SELECT |
||||
|
DISTINCT ra.id |
||||
|
FROM |
||||
|
report_open_items_qweb_account ra |
||||
|
LEFT JOIN |
||||
|
report_open_items_qweb_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) |
||||
|
|
||||
|
def _compute_has_second_currency(self): |
||||
|
""" Compute "has_second_currency" flag which will used for display.""" |
||||
|
query_update_has_second_currency = """ |
||||
|
UPDATE |
||||
|
report_open_items_qweb |
||||
|
SET |
||||
|
has_second_currency = |
||||
|
( |
||||
|
SELECT |
||||
|
TRUE |
||||
|
FROM |
||||
|
report_open_items_qweb_move_line l |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_partner p |
||||
|
ON l.report_partner_id = p.id |
||||
|
INNER JOIN |
||||
|
report_open_items_qweb_account a |
||||
|
ON p.report_account_id = a.id |
||||
|
WHERE |
||||
|
a.report_id = %s |
||||
|
AND l.currency_name IS NOT NULL |
||||
|
LIMIT 1 |
||||
|
) |
||||
|
WHERE id = %s |
||||
|
""" |
||||
|
params = (self.id,) * 2 |
||||
|
self.env.cr.execute(query_update_has_second_currency, params) |
@ -0,0 +1,117 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import abstract_report_xlsx |
||||
|
from openerp.report import report_sxw |
||||
|
from openerp import _ |
||||
|
|
||||
|
|
||||
|
class OpenItemsXslx(abstract_report_xlsx.AbstractReportXslx): |
||||
|
|
||||
|
def __init__(self, name, table, rml=False, parser=False, header=True, |
||||
|
store=False): |
||||
|
super(OpenItemsXslx, self).__init__( |
||||
|
name, table, rml, parser, header, store) |
||||
|
|
||||
|
def _get_report_name(self): |
||||
|
return _('Open Items') |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
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': _('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}, |
||||
|
9: {'header': _('Cur.'), 'field': 'currency_name', 'width': 7}, |
||||
|
10: {'header': _('Cur. Original'), |
||||
|
'field': 'amount_total_due_currency', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
11: {'header': _('Cur. Residual'), |
||||
|
'field': 'amount_residual_currency', |
||||
|
'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')], |
||||
|
[_('Account balance at 0 filter'), |
||||
|
_('Hide') if report.hide_account_balance_at_0 else _('Show')], |
||||
|
] |
||||
|
|
||||
|
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') |
||||
|
elif type_object == 'account': |
||||
|
name = my_object.code + ' - ' + my_object.name |
||||
|
label = _('Ending balance') |
||||
|
super(OpenItemsXslx, self).write_ending_balance(my_object, name, label) |
||||
|
|
||||
|
|
||||
|
OpenItemsXslx( |
||||
|
'report.account_financial_report_qweb.report_open_items_xlsx', |
||||
|
'report_open_items_qweb', |
||||
|
parser=report_sxw.rml_parse |
||||
|
) |
@ -0,0 +1,327 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_aged_partner_balance_qweb"> |
||||
|
<t t-call="report.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<!-- Saved flag fields into variables, used to define columns display --> |
||||
|
<t t-set="show_move_line_details" t-value="o.show_move_line_details"/> |
||||
|
|
||||
|
<t t-call="account_financial_report_qweb.internal_layout"> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title">Aged Partner Balance</t> |
||||
|
<t t-set="company_name" t-value="o.company_id.name"/> |
||||
|
|
||||
|
<div class="page"> |
||||
|
<!-- Display filters --> |
||||
|
<t t-call="account_financial_report_qweb.report_aged_partner_balance_qweb_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: 1141px !important;"> |
||||
|
<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: 1140px !important;"> |
||||
|
<!-- Display account header --> |
||||
|
<t t-call="account_financial_report_qweb.report_aged_partner_balance_qweb_lines_header"/> |
||||
|
|
||||
|
<t t-foreach="account.partner_ids" t-as="partner"> |
||||
|
|
||||
|
<!-- Display one line per partner --> |
||||
|
<t t-call="account_financial_report_qweb.report_aged_partner_balance_qweb_lines"/> |
||||
|
</t> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Display account footer --> |
||||
|
<t t-call="account_financial_report_qweb.report_aged_partner_balance_qweb_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_qweb.report_aged_partner_balance_qweb_move_lines"/> |
||||
|
|
||||
|
<!-- Display partner footer --> |
||||
|
<t t-call="account_financial_report_qweb.report_aged_partner_balance_qweb_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_qweb.report_aged_partner_balance_qweb_account_ending_cumul"/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_aged_partner_balance_qweb_filters"> |
||||
|
<div class="act_as_table data_table" style="width: 1140px !important;"> |
||||
|
<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="account_financial_report_qweb.report_aged_partner_balance_qweb_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: 370px;">Partner</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Residual</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Current</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Age ≤ 30 d.</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Age ≤ 60 d.</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Age ≤ 90 d.</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Age ≤ 120 d.</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Older</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_aged_partner_balance_qweb_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"/></div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.current"/></div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.age_30_days"/></div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.age_60_days"/></div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.age_90_days"/></div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.age_120_days"/></div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.older"/></div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_aged_partner_balance_qweb_move_lines"> |
||||
|
<div class="act_as_table data_table" style="width: 1140px !important;"> |
||||
|
<!-- 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: 60px;">Date</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell" style="width: 100px;">Entry</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell" style="width: 40px;">Journal</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell" style="width: 50px;">Account</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell" style="width: 120px;">Partner</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell" style="width: 220px;">Ref - Label</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 60px;">Due date</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell" style="width: 70px;">Residual</div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell" style="width: 70px;">Current</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell" style="width: 70px;">Age ≤ 30 d.</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell" style="width: 70px;">Age ≤ 60 d.</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell" style="width: 70px;">Age ≤ 90 d.</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell" style="width: 70px;">Age ≤ 120 d.</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell" style="width: 70px;">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 t-field="line.date"/></div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell left"><span t-field="line.entry"/></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"><span t-field="line.partner"/></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_residual--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.amount_residual"/></div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.current"/></div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.age_30_days"/></div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.age_60_days"/></div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.age_90_days"/></div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.age_120_days"/></div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.older"/></div> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_aged_partner_balance_qweb_partner_ending_cumul"> |
||||
|
<!-- Display ending balance line for partner --> |
||||
|
<div class="act_as_table list_table" style="width: 1141px !important;"> |
||||
|
<div class="act_as_row labels" style="font-weight: bold;"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell right" style="width: 590px;">Partner cumul aged balance</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 60px;"/> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="partner_cumul_line.amount_residual"/></div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="partner_cumul_line.current"/></div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="partner_cumul_line.age_30_days"/></div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="partner_cumul_line.age_60_days"/></div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="partner_cumul_line.age_90_days"/></div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="partner_cumul_line.age_120_days"/></div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="partner_cumul_line.older"/></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_aged_partner_balance_qweb_account_ending_cumul"> |
||||
|
<!-- Display ending balance line for account --> |
||||
|
<div class="act_as_table list_table" style="width: 1141px !important;"> |
||||
|
<div class="act_as_row labels" style="font-weight: bold;"> |
||||
|
<t t-if="not show_move_line_details"> |
||||
|
<!--## total--> |
||||
|
<div class="act_as_cell right" style="width: 370px;">Total</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.cumul_amount_residual"/></div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.cumul_current"/></div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.cumul_age_30_days"/></div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.cumul_age_60_days"/></div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.cumul_age_90_days"/></div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.cumul_age_120_days"/></div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.cumul_older"/></div> |
||||
|
</t> |
||||
|
<t t-if="show_move_line_details"> |
||||
|
<!--## total--> |
||||
|
<div class="act_as_cell right" style="width: 590px;">Total</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 60px;"/> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.cumul_amount_residual"/></div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.cumul_current"/></div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.cumul_age_30_days"/></div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.cumul_age_60_days"/></div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.cumul_age_90_days"/></div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.cumul_age_120_days"/></div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.cumul_older"/></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: 370px;">Percents</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"></div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.percent_current"/>%</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.percent_age_30_days"/>%</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.percent_age_60_days"/>%</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.percent_age_90_days"/>%</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.percent_age_120_days"/>%</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.percent_older"/>%</div> |
||||
|
</t> |
||||
|
<t t-if="show_move_line_details"> |
||||
|
<!--## total--> |
||||
|
<div class="act_as_cell right" style="width: 590px;">Percents</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 60px;"/> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"></div> |
||||
|
<!--## current--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.percent_current"/>%</div> |
||||
|
<!--## age_30_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.percent_age_30_days"/>%</div> |
||||
|
<!--## age_60_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.percent_age_60_days"/>%</div> |
||||
|
<!--## age_90_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.percent_age_90_days"/>%</div> |
||||
|
<!--## age_120_days--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.percent_age_120_days"/>%</div> |
||||
|
<!--## older--> |
||||
|
<div class="act_as_cell amount" style="width: 70px;"><span t-field="account.percent_older"/>%</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,250 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_general_ledger_qweb"> |
||||
|
<t t-call="report.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<!-- Saved flag fields into variables, used to define columns display --> |
||||
|
<t t-set="show_cost_center" t-value="o.show_cost_center"/> |
||||
|
<t t-set="has_second_currency" t-value="o.has_second_currency"/> |
||||
|
|
||||
|
<t t-call="account_financial_report_qweb.internal_layout"> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title">General Ledger</t> |
||||
|
<t t-set="company_name" t-value="o.company_id.name"/> |
||||
|
|
||||
|
<div class="page"> |
||||
|
<!-- Display filters --> |
||||
|
<t t-call="account_financial_report_qweb.report_general_ledger_qweb_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: 1141px !important;"> |
||||
|
<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-call="account_financial_report_qweb.report_general_ledger_qweb_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"> |
||||
|
<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_qweb.report_general_ledger_qweb_lines"> |
||||
|
<t t-set="account_or_partner_object" t-value="partner"/> |
||||
|
</t> |
||||
|
|
||||
|
<!-- Display partner footer --> |
||||
|
<t t-call="account_financial_report_qweb.report_general_ledger_qweb_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_qweb.report_general_ledger_qweb_ending_cumul"> |
||||
|
<t t-set="account_or_partner_object" t-value="account"/> |
||||
|
<t t-set="type" t-value='"account_type"'/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_general_ledger_qweb_filters"> |
||||
|
<div class="act_as_table data_table" style="width: 1140px !important;"> |
||||
|
<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> |
||||
|
<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_balance_at_0">Hide</t> |
||||
|
<t t-if="not o.hide_account_balance_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> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_general_ledger_qweb_lines"> |
||||
|
<div class="act_as_table data_table" style="width: 1140px !important;"> |
||||
|
|
||||
|
<!-- 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: 60px;">Date</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell" style="width: 100px;">Entry</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell" style="width: 40px;">Journal</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell" style="width: 50px;">Account</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell" style="width: 140px;">Partner</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell" style="width: 290px;">Ref - Label</div> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<!--## cost_center--> |
||||
|
<div class="act_as_cell" style="width: 100px;">Cost center</div> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell" style="width: 25px;">Rec.</div> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;">Debit</div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;">Credit</div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;">Cumul. Bal.</div> |
||||
|
<t t-if="has_second_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" style="width: 35px;">Cur.</div> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;">Amount cur.</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Display first line with initial balance --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<!--## date--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell amount">Initial balance</div> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<!--## cost_center--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount"><span t-field="account_or_partner_object.initial_debit"/></div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount"><span t-field="account_or_partner_object.initial_credit"/></div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount"><span t-field="account_or_partner_object.initial_balance"/></div> |
||||
|
<t t-if="has_second_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
</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"><span t-field="line.date"/></div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell left"><span t-field="line.entry"/></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"><span t-field="line.partner"/></div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell left"><span t-field="line.label"/></div> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<!--## cost_center--> |
||||
|
<div class="act_as_cell left"><span t-field="line.cost_center"/></div> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell"><span t-field="line.matching_number"/></div> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.debit"/></div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.credit"/></div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.cumul_balance"/></div> |
||||
|
<t t-if="has_second_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell"><span t-field="line.currency_name"/></div> |
||||
|
<t t-if="line.currency_name"> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.amount_currency"/></div> |
||||
|
</t> |
||||
|
<t t-if="not line.currency_name"> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_general_ledger_qweb_ending_cumul"> |
||||
|
<!-- Display ending balance line for account or partner --> |
||||
|
<div class="act_as_table list_table" style="width: 1141px !important;"> |
||||
|
<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: 380px;"><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: 290px;">Ending balance</div> |
||||
|
</t> |
||||
|
<t t-if='type == "partner_type"'> |
||||
|
<div class="act_as_cell first_column" style="width: 380px;"></div> |
||||
|
<div class="act_as_cell right" style="width: 290px;">Partner ending balance</div> |
||||
|
</t> |
||||
|
<t t-if="show_cost_center"> |
||||
|
<!--## cost_center--> |
||||
|
<div class="act_as_cell" style="width: 100px;"></div> |
||||
|
</t> |
||||
|
<!--## matching_number--> |
||||
|
<div class="act_as_cell" style="width: 25px;"></div> |
||||
|
<!--## debit--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;"><span t-field="account_or_partner_object.final_debit"/></div> |
||||
|
<!--## credit--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;"><span t-field="account_or_partner_object.final_credit"/></div> |
||||
|
<!--## balance cumulated--> |
||||
|
<div class="act_as_cell amount" style="width: 75px; padding-right: 1px;"><span t-field="account_or_partner_object.final_balance"/></div> |
||||
|
<t t-if="has_second_currency"> |
||||
|
<!--## currency_name + amount_currency--> |
||||
|
<div class="act_as_cell" style="width: 110px;"></div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,38 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="assets_specific" inherit_id="report.assets_common"> |
||||
|
<xpath expr="." position="inside"> |
||||
|
<link href="/account_financial_report_qweb/static/src/css/report.css" rel="stylesheet"/> |
||||
|
</xpath> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.internal_layout"> |
||||
|
<div class="header"> |
||||
|
<div class="row"> |
||||
|
<div class="col-xs-6"> |
||||
|
<span t-esc="title"/> |
||||
|
</div> |
||||
|
<div class="col-xs-6 text-right"> |
||||
|
<span t-esc="company_name"/> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<t t-raw="0" /> |
||||
|
<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,187 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_open_items_qweb"> |
||||
|
<t t-call="report.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<!-- Saved flag fields into variables, used to define columns display --> |
||||
|
<t t-set="has_second_currency" t-value="o.has_second_currency"/> |
||||
|
|
||||
|
<t t-call="account_financial_report_qweb.internal_layout"> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title">Open Items</t> |
||||
|
<t t-set="company_name" t-value="o.company_id.name"/> |
||||
|
|
||||
|
<div class="page"> |
||||
|
<!-- Display filters --> |
||||
|
<t t-call="account_financial_report_qweb.report_open_items_qweb_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: 1141px !important;"> |
||||
|
<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_qweb.report_open_items_qweb_lines"/> |
||||
|
|
||||
|
<!-- Display partner footer --> |
||||
|
<t t-call="account_financial_report_qweb.report_open_items_qweb_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_qweb.report_open_items_qweb_ending_cumul"> |
||||
|
<t t-set="account_or_partner_object" t-value="account"/> |
||||
|
<t t-set="type" t-value='"account_type"'/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
|
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_open_items_qweb_filters"> |
||||
|
<div class="act_as_table data_table" style="width: 1140px !important;"> |
||||
|
<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_balance_at_0">Hide</t> |
||||
|
<t t-if="not o.hide_account_balance_at_0">Show</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_open_items_qweb_lines"> |
||||
|
<div class="act_as_table data_table" style="width: 1140px !important;"> |
||||
|
<!-- 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: 60px;">Date</div> |
||||
|
<!--## move--> |
||||
|
<div class="act_as_cell" style="width: 100px;">Entry</div> |
||||
|
<!--## journal--> |
||||
|
<div class="act_as_cell" style="width: 40px;">Journal</div> |
||||
|
<!--## account code--> |
||||
|
<div class="act_as_cell" style="width: 50px;">Account</div> |
||||
|
<!--## partner--> |
||||
|
<div class="act_as_cell" style="width: 140px;">Partner</div> |
||||
|
<!--## ref - label--> |
||||
|
<div class="act_as_cell" style="width: 290px;">Ref - Label</div> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 60px;">Due date</div> |
||||
|
<!--## amount_total_due--> |
||||
|
<div class="act_as_cell" style="width: 75px;">Original</div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell" style="width: 75px;">Residual</div> |
||||
|
<t t-if="has_second_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell" style="width: 35px;">Cur.</div> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;">Cur. Original</div> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;">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"><span t-field="line.entry"/></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"><span t-field="line.partner"/></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"/></div> |
||||
|
<!--## amount_residual--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.amount_residual"/></div> |
||||
|
<t t-if="has_second_currency"> |
||||
|
<!--## currency_name--> |
||||
|
<div class="act_as_cell"><span t-field="line.currency_name"/></div> |
||||
|
<t t-if="line.currency_name"> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.amount_total_due_currency"/></div> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.amount_residual_currency"/></div> |
||||
|
</t> |
||||
|
<t t-if="not line.currency_name"> |
||||
|
<!--## amount_total_due_currency--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
<!--## amount_residual_currency--> |
||||
|
<div class="act_as_cell"></div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_open_items_qweb_ending_cumul"> |
||||
|
<!-- Display ending balance line for account or partner --> |
||||
|
<div class="act_as_table list_table" style="width: 1141px !important;"> |
||||
|
<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: 380px;"><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: 290px;">Ending balance</div> |
||||
|
</t> |
||||
|
<t t-if='type == "partner_type"'> |
||||
|
<div class="act_as_cell first_column" style="width: 380px;"></div> |
||||
|
<div class="act_as_cell right" style="width: 290px;">Partner ending balance</div> |
||||
|
</t> |
||||
|
<!--## date_due--> |
||||
|
<div class="act_as_cell" style="width: 60px;"></div> |
||||
|
<!--## amount_total_due--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;"></div> |
||||
|
<!--## amount_currency--> |
||||
|
<div class="act_as_cell amount" style="width: 75px;"><span t-field="account_or_partner_object.final_amount_residual"/></div> |
||||
|
<t t-if="has_second_currency"> |
||||
|
<!--## currency_name + amount_total_due_currency + amount_residual_currency --> |
||||
|
<div class="act_as_cell" style="width: 185px;"></div> |
||||
|
</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,154 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_trial_balance_qweb"> |
||||
|
<t t-call="report.html_container"> |
||||
|
<t t-foreach="docs" t-as="o"> |
||||
|
<!-- Saved flag fields into variables, used to define columns display --> |
||||
|
<t t-set="show_partner_details" t-value="o.show_partner_details"/> |
||||
|
|
||||
|
<t t-call="account_financial_report_qweb.internal_layout"> |
||||
|
<!-- Defines global variables used by internal layout --> |
||||
|
<t t-set="title">Trial Balance</t> |
||||
|
<t t-set="company_name" t-value="o.company_id.name"/> |
||||
|
|
||||
|
<div class="page"> |
||||
|
<!-- Display filters --> |
||||
|
<t t-call="account_financial_report_qweb.report_trial_balance_qweb_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: 1140px !important;"> |
||||
|
<!-- Display account header --> |
||||
|
<t t-call="account_financial_report_qweb.report_trial_balance_qweb_lines_header"/> |
||||
|
|
||||
|
<!-- Display each lines --> |
||||
|
<t t-foreach="o.account_ids" t-as="line"> |
||||
|
<!-- Display account lines --> |
||||
|
<t t-call="account_financial_report_qweb.report_trial_balance_qweb_line"/> |
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<!-- Display partner lines --> |
||||
|
<t t-if="show_partner_details"> |
||||
|
<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: 1141px !important;"> |
||||
|
<span t-field="account.code"/> - <span t-field="account.name"/> |
||||
|
</div> |
||||
|
|
||||
|
<div class="act_as_table data_table" style="width: 1140px !important;"> |
||||
|
<!-- Display account/partner header --> |
||||
|
<t t-call="account_financial_report_qweb.report_trial_balance_qweb_lines_header"/> |
||||
|
|
||||
|
<!-- Display each partners --> |
||||
|
<t t-foreach="account.partner_ids" t-as="line"> |
||||
|
<!-- Display partner line --> |
||||
|
<t t-call="account_financial_report_qweb.report_trial_balance_qweb_line"/> |
||||
|
</t> |
||||
|
</div> |
||||
|
|
||||
|
<!-- Display account footer --> |
||||
|
<t t-call="account_financial_report_qweb.report_trial_balance_qweb_account_footer"/> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
</t> |
||||
|
</div> |
||||
|
</t> |
||||
|
</t> |
||||
|
</t> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_trial_balance_qweb_filters"> |
||||
|
<div class="act_as_table data_table" style="width: 1140px !important;"> |
||||
|
<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> |
||||
|
<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_balance_at_0">Hide</t> |
||||
|
<t t-if="not o.hide_account_balance_at_0">Show</t> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_trial_balance_qweb_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: 100px;">Code</div> |
||||
|
<!--## Account--> |
||||
|
<div class="act_as_cell" style="width: 600px;">Account</div> |
||||
|
</t> |
||||
|
<t t-if="show_partner_details"> |
||||
|
<!--## Partner--> |
||||
|
/<div class="act_as_cell" style="width: 700px;">Partner</div> |
||||
|
</t> |
||||
|
<!--## Initial balance--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Initial balance</div> |
||||
|
<!--## Debit--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Debit</div> |
||||
|
<!--## Credit--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Credit</div> |
||||
|
<!--## Ending balance--> |
||||
|
<div class="act_as_cell" style="width: 110px;">Ending balance</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_trial_balance_qweb_line"> |
||||
|
<!-- # line --> |
||||
|
<div class="act_as_row lines"> |
||||
|
<t t-if="not show_partner_details"> |
||||
|
<!--## Code--> |
||||
|
<div class="act_as_cell left"><span t-field="line.code"/></div> |
||||
|
</t> |
||||
|
<!--## Account/Partner--> |
||||
|
<div class="act_as_cell left"><span t-field="line.name"/></div> |
||||
|
<!--## Initial balance--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.initial_balance"/></div> |
||||
|
<!--## Debit--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.debit"/></div> |
||||
|
<!--## Credit--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.credit"/></div> |
||||
|
<!--## Ending balance--> |
||||
|
<div class="act_as_cell amount"><span t-field="line.final_balance"/></div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<template id="account_financial_report_qweb.report_trial_balance_qweb_account_footer"> |
||||
|
<!-- Display account footer --> |
||||
|
<div class="act_as_table list_table" style="width: 1141px !important;"> |
||||
|
<div class="act_as_row labels" style="font-weight: bold;"> |
||||
|
<!--## Account--> |
||||
|
<div class="act_as_cell left" style="width: 700px;"><span t-field="account.code"/> - <span t-field="account.name"/></div> |
||||
|
<!--## Initial balance--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.initial_balance"/></div> |
||||
|
<!--## Debit--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.debit"/></div> |
||||
|
<!--## Credit--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.credit"/></div> |
||||
|
<!--## Ending balance--> |
||||
|
<div class="act_as_cell amount" style="width: 110px;"><span t-field="account.final_balance"/></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,249 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from openerp import models, fields, api |
||||
|
|
||||
|
|
||||
|
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_qweb' |
||||
|
|
||||
|
# 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_balance_at_0 = 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_partner_details = fields.Boolean() |
||||
|
|
||||
|
# General Ledger Report Data fields, |
||||
|
# used as base for compute the data reports |
||||
|
general_ledger_id = fields.Many2one( |
||||
|
comodel_name='report_general_ledger_qweb' |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
account_ids = fields.One2many( |
||||
|
comodel_name='report_trial_balance_qweb_account', |
||||
|
inverse_name='report_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReportAccount(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_trial_balance_qweb_account' |
||||
|
_order = 'code ASC' |
||||
|
|
||||
|
report_id = fields.Many2one( |
||||
|
comodel_name='report_trial_balance_qweb', |
||||
|
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() |
||||
|
|
||||
|
initial_balance = fields.Float(digits=(16, 2)) |
||||
|
debit = fields.Float(digits=(16, 2)) |
||||
|
credit = fields.Float(digits=(16, 2)) |
||||
|
final_balance = fields.Float(digits=(16, 2)) |
||||
|
|
||||
|
# Data fields, used to browse report data |
||||
|
partner_ids = fields.One2many( |
||||
|
comodel_name='report_trial_balance_qweb_partner', |
||||
|
inverse_name='report_account_id' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReportPartner(models.TransientModel): |
||||
|
|
||||
|
_name = 'report_trial_balance_qweb_partner' |
||||
|
|
||||
|
report_account_id = fields.Many2one( |
||||
|
comodel_name='report_trial_balance_qweb_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() |
||||
|
|
||||
|
initial_balance = fields.Float(digits=(16, 2)) |
||||
|
debit = fields.Float(digits=(16, 2)) |
||||
|
credit = fields.Float(digits=(16, 2)) |
||||
|
final_balance = 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_qweb_partner"."partner_id" IS NOT NULL |
||||
|
THEN 0 |
||||
|
ELSE 1 |
||||
|
END, |
||||
|
"report_trial_balance_qweb_partner"."name" |
||||
|
""" |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReportCompute(models.TransientModel): |
||||
|
""" Here, we just define methods. |
||||
|
For class fields, go more top at this file. |
||||
|
""" |
||||
|
|
||||
|
_inherit = 'report_trial_balance_qweb' |
||||
|
|
||||
|
@api.multi |
||||
|
def print_report(self, xlsx_report=False): |
||||
|
self.ensure_one() |
||||
|
self.compute_data_for_report() |
||||
|
if xlsx_report: |
||||
|
report_name = 'account_financial_report_qweb.' \ |
||||
|
'report_trial_balance_xlsx' |
||||
|
else: |
||||
|
report_name = 'account_financial_report_qweb.' \ |
||||
|
'report_trial_balance_qweb' |
||||
|
return self.env['report'].get_action(records=self, |
||||
|
report_name=report_name) |
||||
|
|
||||
|
def _prepare_report_general_ledger(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
'date_from': self.date_from, |
||||
|
'date_to': self.date_to, |
||||
|
'only_posted_moves': self.only_posted_moves, |
||||
|
'hide_account_balance_at_0': self.hide_account_balance_at_0, |
||||
|
'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)], |
||||
|
'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_qweb'] |
||||
|
self.general_ledger_id = model.create( |
||||
|
self._prepare_report_general_ledger() |
||||
|
) |
||||
|
self.general_ledger_id.compute_data_for_report() |
||||
|
|
||||
|
# Compute report data |
||||
|
self._inject_account_values() |
||||
|
if self.show_partner_details: |
||||
|
self._inject_partner_values() |
||||
|
# Refresh cache because all data are computed with SQL requests |
||||
|
self.refresh() |
||||
|
|
||||
|
def _inject_account_values(self): |
||||
|
"""Inject report values for report_trial_balance_qweb_account""" |
||||
|
query_inject_account = """ |
||||
|
INSERT INTO |
||||
|
report_trial_balance_qweb_account |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
account_id, |
||||
|
code, |
||||
|
name, |
||||
|
initial_balance, |
||||
|
debit, |
||||
|
credit, |
||||
|
final_balance |
||||
|
) |
||||
|
SELECT |
||||
|
%s AS report_id, |
||||
|
%s AS create_uid, |
||||
|
NOW() AS create_date, |
||||
|
rag.account_id, |
||||
|
rag.code, |
||||
|
rag.name, |
||||
|
rag.initial_balance AS initial_balance, |
||||
|
rag.final_debit - rag.initial_debit AS debit, |
||||
|
rag.final_credit - rag.initial_credit AS credit, |
||||
|
rag.final_balance AS final_balance |
||||
|
FROM |
||||
|
report_general_ledger_qweb_account rag |
||||
|
WHERE |
||||
|
rag.report_id = %s |
||||
|
""" |
||||
|
query_inject_account_params = ( |
||||
|
self.id, |
||||
|
self.env.uid, |
||||
|
self.general_ledger_id.id, |
||||
|
) |
||||
|
self.env.cr.execute(query_inject_account, query_inject_account_params) |
||||
|
|
||||
|
def _inject_partner_values(self): |
||||
|
"""Inject report values for report_trial_balance_qweb_partner""" |
||||
|
query_inject_partner = """ |
||||
|
INSERT INTO |
||||
|
report_trial_balance_qweb_partner |
||||
|
( |
||||
|
report_account_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
partner_id, |
||||
|
name, |
||||
|
initial_balance, |
||||
|
debit, |
||||
|
credit, |
||||
|
final_balance |
||||
|
) |
||||
|
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.final_debit - rpg.initial_debit AS debit, |
||||
|
rpg.final_credit - rpg.initial_credit AS credit, |
||||
|
rpg.final_balance AS final_balance |
||||
|
FROM |
||||
|
report_general_ledger_qweb_partner rpg |
||||
|
INNER JOIN |
||||
|
report_general_ledger_qweb_account rag ON rpg.report_account_id = rag.id |
||||
|
INNER JOIN |
||||
|
report_trial_balance_qweb_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) |
@ -0,0 +1,133 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from . import abstract_report_xlsx |
||||
|
from openerp.report import report_sxw |
||||
|
from openerp import _ |
||||
|
|
||||
|
|
||||
|
class TrialBalanceXslx(abstract_report_xlsx.AbstractReportXslx): |
||||
|
|
||||
|
def __init__(self, name, table, rml=False, parser=False, header=True, |
||||
|
store=False): |
||||
|
super(TrialBalanceXslx, self).__init__( |
||||
|
name, table, rml, parser, header, store) |
||||
|
|
||||
|
def _get_report_name(self): |
||||
|
return _('Trial Balance') |
||||
|
|
||||
|
def _get_report_columns(self, report): |
||||
|
if not report.show_partner_details: |
||||
|
return { |
||||
|
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': _('Ending balance'), |
||||
|
'field': 'final_balance', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
} |
||||
|
else: |
||||
|
return { |
||||
|
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': _('Ending balance'), |
||||
|
'field': 'final_balance', |
||||
|
'type': 'amount', |
||||
|
'width': 14}, |
||||
|
} |
||||
|
|
||||
|
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_balance_at_0 else _('Show')], |
||||
|
] |
||||
|
|
||||
|
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: |
||||
|
if not report.show_partner_details: |
||||
|
# Display account lines |
||||
|
self.write_line(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) |
||||
|
|
||||
|
# Display account footer line |
||||
|
self.write_account_footer(account, |
||||
|
account.code + ' - ' + account.name) |
||||
|
|
||||
|
# Line break |
||||
|
self.row_pos += 2 |
||||
|
|
||||
|
def write_account_footer(self, account, name_value): |
||||
|
"""Specific function to write account footer for Trial Balance""" |
||||
|
for col_pos, column in self.columns.iteritems(): |
||||
|
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) |
||||
|
self.row_pos += 1 |
||||
|
|
||||
|
|
||||
|
TrialBalanceXslx( |
||||
|
'report.account_financial_report_qweb.report_trial_balance_xlsx', |
||||
|
'report_trial_balance_qweb', |
||||
|
parser=report_sxw.rml_parse |
||||
|
) |
@ -0,0 +1,114 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<!-- PDF REPORTS --> |
||||
|
|
||||
|
<report |
||||
|
id="action_report_general_ledger_qweb" |
||||
|
model="report_general_ledger_qweb" |
||||
|
string="General Ledger" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report_qweb.report_general_ledger_qweb" |
||||
|
file="account_financial_report_qweb.report_general_ledger_qweb" |
||||
|
/> |
||||
|
|
||||
|
<report |
||||
|
id="action_report_trial_balance_qweb" |
||||
|
model="report_trial_balance_qweb" |
||||
|
string="Trial Balance" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report_qweb.report_trial_balance_qweb" |
||||
|
file="account_financial_report_qweb.report_trial_balance_qweb" |
||||
|
/> |
||||
|
|
||||
|
<report |
||||
|
id="action_report_open_items_qweb" |
||||
|
model="report_open_items_qweb" |
||||
|
string="Open Items" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report_qweb.report_open_items_qweb" |
||||
|
file="account_financial_report_qweb.report_open_items_qweb" |
||||
|
/> |
||||
|
|
||||
|
<report |
||||
|
id="action_report_aged_partner_balance_qweb" |
||||
|
model="report_aged_partner_balance_qweb" |
||||
|
string="Aged Partner Balance" |
||||
|
report_type="qweb-pdf" |
||||
|
name="account_financial_report_qweb.report_aged_partner_balance_qweb" |
||||
|
file="account_financial_report_qweb.report_aged_partner_balance_qweb" |
||||
|
/> |
||||
|
|
||||
|
<!-- 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.xml"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_trial_balance_qweb" model="ir.actions.report.xml"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_open_items_qweb" model="ir.actions.report.xml"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_aged_partner_balance_qweb" model="ir.actions.report.xml"> |
||||
|
<field name="paperformat_id" ref="report_qweb_paperformat"/> |
||||
|
</record> |
||||
|
|
||||
|
<!-- XLSX REPORTS --> |
||||
|
|
||||
|
<record id="action_report_general_ledger_xlsx" model="ir.actions.report.xml"> |
||||
|
<field name="name">General Ledger XLSX</field> |
||||
|
<field name="model">report_general_ledger_qweb</field> |
||||
|
<field name="type">ir.actions.report.xml</field> |
||||
|
<field name="report_name">account_financial_report_qweb.report_general_ledger_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="auto" eval="False"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_trial_balance_xlsx" model="ir.actions.report.xml"> |
||||
|
<field name="name">Trial Balance XLSX</field> |
||||
|
<field name="model">report_trial_balance_qweb</field> |
||||
|
<field name="type">ir.actions.report.xml</field> |
||||
|
<field name="report_name">account_financial_report_qweb.report_trial_balance_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="auto" eval="False"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_open_items_xlsx" model="ir.actions.report.xml"> |
||||
|
<field name="name">Open Items XLSX</field> |
||||
|
<field name="model">report_open_items_qweb</field> |
||||
|
<field name="type">ir.actions.report.xml</field> |
||||
|
<field name="report_name">account_financial_report_qweb.report_open_items_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="auto" eval="False"/> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_aged_partner_balance_xlsx" model="ir.actions.report.xml"> |
||||
|
<field name="name">Aged Partner Balance XLSX</field> |
||||
|
<field name="model">report_aged_partner_balance_qweb</field> |
||||
|
<field name="type">ir.actions.report.xml</field> |
||||
|
<field name="report_name">account_financial_report_qweb.report_aged_partner_balance_xlsx</field> |
||||
|
<field name="report_type">xlsx</field> |
||||
|
<field name="auto" eval="False"/> |
||||
|
</record> |
||||
|
|
||||
|
</odoo> |
After Width: 256 | Height: 256 | Size: 15 KiB |
@ -0,0 +1,95 @@ |
|||||
|
body, table, td, span, div { |
||||
|
font-family: Helvetica, Arial; |
||||
|
} |
||||
|
.act_as_table { |
||||
|
display: table !important; |
||||
|
} |
||||
|
.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; |
||||
|
table-layout: fixed !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:left; |
||||
|
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{ |
||||
|
padding-left: 5px; |
||||
|
/* 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; |
||||
|
} |
@ -0,0 +1,9 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2016 Julien Coux (Camptocamp) |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
||||
|
|
||||
|
from . import abstract_test |
||||
|
from . import test_aged_partner_balance |
||||
|
from . import test_general_ledger |
||||
|
from . import test_open_items |
||||
|
from . import test_trial_balance |
@ -0,0 +1,204 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from openerp.tests.common import TransactionCase |
||||
|
|
||||
|
|
||||
|
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.additional_filters = cls._getAdditionalFiltersToBeTested() |
||||
|
|
||||
|
cls.report = cls.model.create(cls.base_filters) |
||||
|
|
||||
|
def test_01_generation_report_qweb(self): |
||||
|
"""Check if report PDF/HTML is correctly generated""" |
||||
|
|
||||
|
# Check if returned report action is correct |
||||
|
report_action = self.report.print_report() |
||||
|
self.assertDictContainsSubset( |
||||
|
{ |
||||
|
'type': 'ir.actions.report.xml', |
||||
|
'report_name': self.qweb_report_name, |
||||
|
'report_type': 'qweb-pdf', |
||||
|
}, |
||||
|
report_action |
||||
|
) |
||||
|
|
||||
|
# Check if report template is correct |
||||
|
report_html = self.env['report'].get_html( |
||||
|
self.report, self.qweb_report_name |
||||
|
) |
||||
|
self.assertTrue(self.report_title.encode('utf8') in report_html) |
||||
|
self.assertTrue( |
||||
|
self.report.account_ids[0].name.encode('utf8') in report_html |
||||
|
) |
||||
|
|
||||
|
def test_02_generation_report_xlsx(self): |
||||
|
"""Check if report XLSX is correctly generated""" |
||||
|
|
||||
|
# Check if returned report action is correct |
||||
|
report_action = self.report.print_report(xlsx_report=True) |
||||
|
self.assertDictContainsSubset( |
||||
|
{ |
||||
|
'type': 'ir.actions.report.xml', |
||||
|
'report_name': self.xlsx_report_name, |
||||
|
'report_type': 'xlsx', |
||||
|
}, |
||||
|
report_action |
||||
|
) |
||||
|
|
||||
|
# Check if report template is correct |
||||
|
report_xlsx = self.env.ref(self.xlsx_action_name).render_report( |
||||
|
self.report.ids, |
||||
|
self.xlsx_report_name, |
||||
|
{'report_type': 'xlsx'} |
||||
|
) |
||||
|
self.assertGreaterEqual(len(report_xlsx[0]), 1) |
||||
|
self.assertEqual(report_xlsx[1], 'xlsx') |
||||
|
|
||||
|
def test_03_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) |
||||
|
current_filter.update({ |
||||
|
'filter_account_ids': |
||||
|
[(6, 0, report.account_ids[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.account_ids[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,42 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
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_qweb'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report_qweb.report_aged_partner_balance_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'account_financial_report_qweb.report_aged_partner_balance_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report_qweb.' \ |
||||
|
'action_report_aged_partner_balance_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Aged Partner Balance' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_at': time.strftime('%Y-12-31'), |
||||
|
'company_id': self.env.ref('base.main_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,52 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
from . import abstract_test |
||||
|
|
||||
|
|
||||
|
class TestGeneralLedger(abstract_test.AbstractTest): |
||||
|
""" |
||||
|
Technical tests for General Ledger Report. |
||||
|
""" |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_general_ledger_qweb'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report_qweb.report_general_ledger_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'account_financial_report_qweb.report_general_ledger_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report_qweb.' \ |
||||
|
'action_report_general_ledger_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'General Ledger' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_from': time.strftime('%Y-01-01'), |
||||
|
'date_to': time.strftime('%Y-12-31'), |
||||
|
'company_id': self.env.ref('base.main_company').id, |
||||
|
'fy_start_date': time.strftime('%Y-01-01'), |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
return [ |
||||
|
{'only_posted_moves': True}, |
||||
|
{'hide_account_balance_at_0': True}, |
||||
|
{'centralize': True}, |
||||
|
{'only_posted_moves': True, 'hide_account_balance_at_0': True}, |
||||
|
{'only_posted_moves': True, 'centralize': True}, |
||||
|
{'hide_account_balance_at_0': True, 'centralize': True}, |
||||
|
{ |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_balance_at_0': True, |
||||
|
'centralize': True |
||||
|
}, |
||||
|
] |
@ -0,0 +1,41 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
from . import abstract_test |
||||
|
|
||||
|
|
||||
|
class TestOpenItems(abstract_test.AbstractTest): |
||||
|
""" |
||||
|
Technical tests for Open Items Report. |
||||
|
""" |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_open_items_qweb'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report_qweb.report_open_items_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'account_financial_report_qweb.report_open_items_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report_qweb.action_report_open_items_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Open Items' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_at': time.strftime('%Y-12-31'), |
||||
|
'company_id': self.env.ref('base.main_company').id, |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
return [ |
||||
|
{'only_posted_moves': True}, |
||||
|
{'hide_account_balance_at_0': True}, |
||||
|
{'only_posted_moves': True, 'hide_account_balance_at_0': True}, |
||||
|
] |
@ -0,0 +1,54 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
from . import abstract_test |
||||
|
|
||||
|
|
||||
|
class TestTrialBalance(abstract_test.AbstractTest): |
||||
|
""" |
||||
|
Technical tests for Trial Balance Report. |
||||
|
""" |
||||
|
|
||||
|
def _getReportModel(self): |
||||
|
return self.env['report_trial_balance_qweb'] |
||||
|
|
||||
|
def _getQwebReportName(self): |
||||
|
return 'account_financial_report_qweb.report_trial_balance_qweb' |
||||
|
|
||||
|
def _getXlsxReportName(self): |
||||
|
return 'account_financial_report_qweb.report_trial_balance_xlsx' |
||||
|
|
||||
|
def _getXlsxReportActionName(self): |
||||
|
return 'account_financial_report_qweb.action_report_trial_balance_xlsx' |
||||
|
|
||||
|
def _getReportTitle(self): |
||||
|
return 'Trial Balance' |
||||
|
|
||||
|
def _getBaseFilters(self): |
||||
|
return { |
||||
|
'date_from': time.strftime('%Y-01-01'), |
||||
|
'date_to': time.strftime('%Y-12-31'), |
||||
|
'company_id': self.env.ref('base.main_company').id, |
||||
|
'fy_start_date': time.strftime('%Y-01-01'), |
||||
|
} |
||||
|
|
||||
|
def _getAdditionalFiltersToBeTested(self): |
||||
|
return [ |
||||
|
{'only_posted_moves': True}, |
||||
|
{'hide_account_balance_at_0': True}, |
||||
|
{'show_partner_details': True}, |
||||
|
{'only_posted_moves': True, 'hide_account_balance_at_0': True}, |
||||
|
{'only_posted_moves': True, 'show_partner_details': True}, |
||||
|
{'hide_account_balance_at_0': True, 'show_partner_details': True}, |
||||
|
{ |
||||
|
'only_posted_moves': True, |
||||
|
'hide_account_balance_at_0': True, |
||||
|
'show_partner_details': True |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
def _partner_test_is_possible(self, filters): |
||||
|
return 'show_partner_details' in filters |
@ -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 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
from . import aged_partner_balance_wizard |
||||
|
from . import general_ledger_wizard |
||||
|
from . import open_items_wizard |
||||
|
from . import trial_balance_wizard |
@ -0,0 +1,81 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# 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 datetime import datetime |
||||
|
from openerp import api, fields, models |
||||
|
|
||||
|
|
||||
|
class AgedPartnerBalance(models.TransientModel): |
||||
|
"""Aged partner balance report wizard.""" |
||||
|
|
||||
|
_name = 'aged.partner.balance.wizard' |
||||
|
_description = 'Aged Partner Balance Wizard' |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
string='Company' |
||||
|
) |
||||
|
date_at = fields.Date(required=True, |
||||
|
default=fields.Date.to_string(datetime.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('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 = [] |
||||
|
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_pdf(self): |
||||
|
self.ensure_one() |
||||
|
return self._export() |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
return self._export(xlsx_report=True) |
||||
|
|
||||
|
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, xlsx_report=False): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_aged_partner_balance_qweb'] |
||||
|
report = model.create(self._prepare_report_aged_partner_balance()) |
||||
|
return report.print_report(xlsx_report) |
@ -0,0 +1,50 @@ |
|||||
|
<?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> |
||||
|
<label for="partner_ids"/> |
||||
|
<field name="partner_ids" nolabel="1" options="{'no_create': True}"/> |
||||
|
<group/> |
||||
|
<label for="account_ids"/> |
||||
|
<group col="4"> |
||||
|
<field name="receivable_accounts_only"/> |
||||
|
<field name="payable_accounts_only"/> |
||||
|
</group> |
||||
|
<field name="account_ids" nolabel="1" options="{'no_create': True}"/> |
||||
|
<footer> |
||||
|
<button name="button_export_pdf" string="Export PDF" type="object" default_focus="1" class="oe_highlight"/> |
||||
|
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,136 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from openerp import models, fields, api |
||||
|
|
||||
|
|
||||
|
class GeneralLedgerReportWizard(models.TransientModel): |
||||
|
"""General ledger report wizard.""" |
||||
|
|
||||
|
_name = "general.ledger.report.wizard" |
||||
|
_description = "General Ledger Report Wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
string='Company' |
||||
|
) |
||||
|
date_range_id = fields.Many2one( |
||||
|
comodel_name='date.range', |
||||
|
required=True, |
||||
|
string='Date range' |
||||
|
) |
||||
|
date_from = fields.Date(required=True) |
||||
|
date_to = fields.Date(required=True) |
||||
|
fy_start_date = fields.Date(required=True) |
||||
|
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_balance_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.' |
||||
|
) |
||||
|
receivable_accounts_only = fields.Boolean() |
||||
|
payable_accounts_only = fields.Boolean() |
||||
|
partner_ids = fields.Many2many( |
||||
|
comodel_name='res.partner', |
||||
|
string='Filter partners', |
||||
|
) |
||||
|
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' |
||||
|
) |
||||
|
|
||||
|
@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 |
||||
|
|
||||
|
@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 |
||||
|
if self.date_from: |
||||
|
self.fy_start_date = self.env.user.company_id.find_daterange_fy( |
||||
|
fields.Date.from_string(self.date_range_id.date_start) |
||||
|
).date_start |
||||
|
|
||||
|
@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 = [] |
||||
|
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_pdf(self): |
||||
|
self.ensure_one() |
||||
|
return self._export() |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
return self._export(xlsx_report=True) |
||||
|
|
||||
|
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_balance_at_0': self.hide_account_balance_at_0, |
||||
|
'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)], |
||||
|
'centralize': self.centralize, |
||||
|
'fy_start_date': self.fy_start_date, |
||||
|
} |
||||
|
|
||||
|
def _export(self, xlsx_report=False): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_general_ledger_qweb'] |
||||
|
report = model.create(self._prepare_report_general_ledger()) |
||||
|
return report.print_report(xlsx_report) |
@ -0,0 +1,70 @@ |
|||||
|
<?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" domain="[('company_id','=',company_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_balance_at_0"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
<label for="cost_center_ids" groups="analytic.group_analytic_accounting"/> |
||||
|
<field name="cost_center_ids" nolabel="1" options="{'no_create': True}" groups="analytic.group_analytic_accounting"/> |
||||
|
<group/> |
||||
|
<label for="partner_ids"/> |
||||
|
<field name="partner_ids" nolabel="1" options="{'no_create': True}"/> |
||||
|
<group/> |
||||
|
<label for="account_ids"/> |
||||
|
<group col="4"> |
||||
|
<field name="receivable_accounts_only"/> |
||||
|
<field name="payable_accounts_only"/> |
||||
|
</group> |
||||
|
<field name="account_ids" nolabel="1" options="{'no_create': True}"/> |
||||
|
</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_pdf" string="Export PDF" type="object" default_focus="1" class="oe_highlight"/> |
||||
|
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" /> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,87 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Damien Crier |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from datetime import datetime |
||||
|
from openerp import models, fields, api |
||||
|
|
||||
|
|
||||
|
class OpenItemsReportWizard(models.TransientModel): |
||||
|
"""Open items report wizard.""" |
||||
|
|
||||
|
_name = "open.items.report.wizard" |
||||
|
_description = "Open Items Report Wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
string='Company' |
||||
|
) |
||||
|
date_at = fields.Date(required=True, |
||||
|
default=fields.Date.to_string(datetime.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', |
||||
|
) |
||||
|
hide_account_balance_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.' |
||||
|
) |
||||
|
receivable_accounts_only = fields.Boolean() |
||||
|
payable_accounts_only = fields.Boolean() |
||||
|
partner_ids = fields.Many2many( |
||||
|
comodel_name='res.partner', |
||||
|
string='Filter partners', |
||||
|
) |
||||
|
|
||||
|
@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 = [] |
||||
|
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_pdf(self): |
||||
|
self.ensure_one() |
||||
|
return self._export() |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
return self._export(xlsx_report=True) |
||||
|
|
||||
|
def _prepare_report_open_items(self): |
||||
|
self.ensure_one() |
||||
|
return { |
||||
|
'date_at': self.date_at, |
||||
|
'only_posted_moves': self.target_move == 'posted', |
||||
|
'hide_account_balance_at_0': self.hide_account_balance_at_0, |
||||
|
'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, xlsx_report=False): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_open_items_qweb'] |
||||
|
report = model.create(self._prepare_report_open_items()) |
||||
|
return report.print_report(xlsx_report) |
@ -0,0 +1,50 @@ |
|||||
|
<?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_balance_at_0"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
<label for="partner_ids"/> |
||||
|
<field name="partner_ids" nolabel="1" options="{'no_create': True}"/> |
||||
|
<group/> |
||||
|
<label for="account_ids"/> |
||||
|
<group col="4"> |
||||
|
<field name="receivable_accounts_only"/> |
||||
|
<field name="payable_accounts_only"/> |
||||
|
</group> |
||||
|
<field name="account_ids" nolabel="1" options="{'no_create': True}"/> |
||||
|
<footer> |
||||
|
<button name="button_export_pdf" string="Export PDF" type="object" default_focus="1" class="oe_highlight"/> |
||||
|
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" /> |
||||
|
|
||||
|
</odoo> |
@ -0,0 +1,129 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
from openerp import models, fields, api |
||||
|
|
||||
|
|
||||
|
class TrialBalanceReportWizard(models.TransientModel): |
||||
|
"""Trial balance report wizard.""" |
||||
|
|
||||
|
_name = "trial.balance.report.wizard" |
||||
|
_description = "Trial Balance Report Wizard" |
||||
|
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
string='Company' |
||||
|
) |
||||
|
date_range_id = fields.Many2one( |
||||
|
comodel_name='date.range', |
||||
|
required=True, |
||||
|
string='Date range' |
||||
|
) |
||||
|
date_from = fields.Date(required=True) |
||||
|
date_to = fields.Date(required=True) |
||||
|
fy_start_date = fields.Date(required=True) |
||||
|
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', |
||||
|
) |
||||
|
hide_account_balance_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.' |
||||
|
) |
||||
|
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', |
||||
|
) |
||||
|
|
||||
|
not_only_one_unaffected_earnings_account = fields.Boolean( |
||||
|
readonly=True, |
||||
|
string='Not only one unaffected earnings account' |
||||
|
) |
||||
|
|
||||
|
@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 |
||||
|
|
||||
|
@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 |
||||
|
if self.date_from: |
||||
|
self.fy_start_date = self.env.user.company_id.find_daterange_fy( |
||||
|
fields.Date.from_string(self.date_range_id.date_start) |
||||
|
).date_start |
||||
|
|
||||
|
@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 = [] |
||||
|
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_pdf(self): |
||||
|
self.ensure_one() |
||||
|
return self._export() |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
return self._export(xlsx_report=True) |
||||
|
|
||||
|
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_balance_at_0': self.hide_account_balance_at_0, |
||||
|
'company_id': self.company_id.id, |
||||
|
'filter_account_ids': [(6, 0, self.account_ids.ids)], |
||||
|
'filter_partner_ids': [(6, 0, self.partner_ids.ids)], |
||||
|
'fy_start_date': self.fy_start_date, |
||||
|
'show_partner_details': self.show_partner_details, |
||||
|
} |
||||
|
|
||||
|
def _export(self, xlsx_report=False): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_trial_balance_qweb'] |
||||
|
report = model.create(self._prepare_report_trial_balance()) |
||||
|
return report.print_report(xlsx_report) |
@ -0,0 +1,67 @@ |
|||||
|
<?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" domain="[('company_id','=',company_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_balance_at_0"/> |
||||
|
<field name="show_partner_details"/> |
||||
|
</group> |
||||
|
</group> |
||||
|
<label for="partner_ids" attrs="{'invisible':[('show_partner_details','!=',True)]}"/> |
||||
|
<field name="partner_ids" nolabel="1" options="{'no_create': True}" attrs="{'invisible':[('show_partner_details','!=',True)]}"/> |
||||
|
<group attrs="{'invisible':[('show_partner_details','!=',True)]}"/> |
||||
|
<label for="account_ids"/> |
||||
|
<group col="4"> |
||||
|
<field name="receivable_accounts_only"/> |
||||
|
<field name="payable_accounts_only"/> |
||||
|
</group> |
||||
|
<field name="account_ids" nolabel="1" options="{'no_create': True}"/> |
||||
|
</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_pdf" string="Export PDF" type="object" default_focus="1" class="oe_highlight"/> |
||||
|
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> |
@ -1,5 +1,6 @@ |
|||||
# list the OCA project dependencies, one per line |
# list the OCA project dependencies, one per line |
||||
# add a github url if you need a forked version |
# add a github url if you need a forked version |
||||
|
account-financial-tools |
||||
reporting-engine |
reporting-engine |
||||
server-tools |
server-tools |
||||
web |
web |
@ -0,0 +1 @@ |
|||||
|
__import__('pkg_resources').declare_namespace(__name__) |
@ -0,0 +1 @@ |
|||||
|
../../../account_financial_report_qweb |
@ -0,0 +1,6 @@ |
|||||
|
import setuptools |
||||
|
|
||||
|
setuptools.setup( |
||||
|
setup_requires=['setuptools-odoo'], |
||||
|
odoo_addon=True, |
||||
|
) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue