jcoux
8 years ago
17 changed files with 788 additions and 148 deletions
-
3account_financial_report_qweb/README.rst
-
2account_financial_report_qweb/__openerp__.py
-
4account_financial_report_qweb/menuitems.xml
-
2account_financial_report_qweb/report/__init__.py
-
4account_financial_report_qweb/report/abstract_report_xlsx.py
-
2account_financial_report_qweb/report/general_ledger_xlsx.py
-
154account_financial_report_qweb/report/templates/trial_balance.xml
-
241account_financial_report_qweb/report/trial_balance.py
-
138account_financial_report_qweb/report/trial_balance_xlsx.py
-
22account_financial_report_qweb/reports.xml
-
1account_financial_report_qweb/tests/__init__.py
-
76account_financial_report_qweb/tests/test_trial_balance.py
-
2account_financial_report_qweb/wizard/__init__.py
-
62account_financial_report_qweb/wizard/balance_common_wizard.py
-
57account_financial_report_qweb/wizard/balance_common_wizard_view.xml
-
104account_financial_report_qweb/wizard/trial_balance_wizard.py
-
62account_financial_report_qweb/wizard/trial_balance_wizard_view.xml
@ -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,241 @@ |
|||||
|
# -*- 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 |
||||
|
** TrialBalanceAccount |
||||
|
*** TrialBalancePartner |
||||
|
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 TrialBalanceAccount(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 TrialPartnerAccount(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) |
||||
|
|
||||
|
@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({ |
||||
|
'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, |
||||
|
}) |
||||
|
self.general_ledger_id.compute_data_for_report() |
||||
|
|
||||
|
# Compute report data |
||||
|
self._inject_account_values() |
||||
|
if self.show_partner_details: |
||||
|
self._inject_partner_values() |
||||
|
|
||||
|
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,138 @@ |
|||||
|
# -*- 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) |
||||
|
|
||||
|
# Custom values needed to generate report |
||||
|
self.col_pos_initial_balance_label = 5 |
||||
|
self.col_count_final_balance_name = 5 |
||||
|
self.col_pos_final_balance_label = 5 |
||||
|
|
||||
|
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 lines |
||||
|
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,76 @@ |
|||||
|
# -*- 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 openerp.tests.common import TransactionCase |
||||
|
|
||||
|
|
||||
|
class TestTrialBalance(TransactionCase): |
||||
|
|
||||
|
def setUp(cls): |
||||
|
super(TestTrialBalance, cls).setUp() |
||||
|
env = cls.env |
||||
|
model = env['report_trial_balance_qweb'] |
||||
|
main_company = env.ref('base.main_company') |
||||
|
|
||||
|
cls.report = model.create({ |
||||
|
'date_from': time.strftime('%Y-01-01'), |
||||
|
'date_to': time.strftime('%Y-12-31'), |
||||
|
'company_id': main_company.id, |
||||
|
'fy_start_date': time.strftime('%Y-01-01'), |
||||
|
}) |
||||
|
|
||||
|
def test_01_compute_data(self): |
||||
|
"""Check if data are computed""" |
||||
|
self.report.compute_data_for_report() |
||||
|
self.assertGreaterEqual(len(self.report.account_ids), 1) |
||||
|
|
||||
|
def test_02_generation_report_qweb(self): |
||||
|
"""Check if report PDF/HTML is correctly generated""" |
||||
|
|
||||
|
report_name = 'account_financial_report_qweb.' \ |
||||
|
'report_trial_balance_qweb' |
||||
|
# Check if returned report action is correct |
||||
|
report_action = self.report.print_report(xlsx_report=False) |
||||
|
self.assertDictContainsSubset( |
||||
|
{ |
||||
|
'type': 'ir.actions.report.xml', |
||||
|
'report_name': report_name, |
||||
|
'report_type': 'qweb-pdf', |
||||
|
}, |
||||
|
report_action |
||||
|
) |
||||
|
|
||||
|
# Check if report template is correct |
||||
|
report_html = self.env['report'].get_html(self.report, report_name) |
||||
|
self.assertRegexpMatches(report_html, 'Trial Balance') |
||||
|
self.assertRegexpMatches(report_html, self.report.account_ids[0].name) |
||||
|
|
||||
|
def test_03_generation_report_xlsx(self): |
||||
|
"""Check if report XLSX is correctly generated""" |
||||
|
|
||||
|
report_name = 'account_financial_report_qweb.' \ |
||||
|
'report_trial_balance_xlsx' |
||||
|
# 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': report_name, |
||||
|
'report_type': 'xlsx', |
||||
|
}, |
||||
|
report_action |
||||
|
) |
||||
|
|
||||
|
# Check if report template is correct |
||||
|
action_name = 'account_financial_report_qweb.' \ |
||||
|
'action_report_trial_balance_xlsx' |
||||
|
report_xlsx = self.env.ref(action_name).render_report( |
||||
|
self.report.ids, |
||||
|
report_name, |
||||
|
{'report_type': u'xlsx'} |
||||
|
) |
||||
|
self.assertGreaterEqual(len(report_xlsx[0]), 1) |
||||
|
self.assertEqual(report_xlsx[1], 'xlsx') |
@ -1,62 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
# Author: Thomas Rehn, Guewen Baconnier |
|
||||
# Copyright 2016 initOS GmbH, camptocamp |
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|
||||
|
|
||||
from openerp import models, fields, api |
|
||||
|
|
||||
|
|
||||
class AccountBalanceCommonWizard(models.TransientModel): |
|
||||
"""Will launch some balance report wizards and pass required args""" |
|
||||
|
|
||||
_inherit = "account.common.account.report" |
|
||||
_name = "account.common.balance.report" |
|
||||
_description = "Common Balance Report" |
|
||||
|
|
||||
@api.model |
|
||||
def _get_account_ids(self): |
|
||||
context = self.env.context or {} |
|
||||
res = False |
|
||||
if context.get('active_model', False) == 'account.account' \ |
|
||||
and context.get('active_ids', False): |
|
||||
res = context['active_ids'] |
|
||||
return res |
|
||||
|
|
||||
account_ids = fields.Many2many( |
|
||||
comodel_name='account.account', |
|
||||
string='Filter on accounts', |
|
||||
help="Only selected accounts will be printed. Leave empty to " |
|
||||
"print all accounts.", |
|
||||
default=_get_account_ids |
|
||||
) |
|
||||
date_range_id = fields.Many2one( |
|
||||
comodel_name='date.range', |
|
||||
string='Date Range', |
|
||||
) |
|
||||
comparison_date_range_id = fields.Many2one( |
|
||||
comodel_name='date.range', |
|
||||
string='Date Range', |
|
||||
) |
|
||||
comparison_date_start = fields.Datetime( |
|
||||
string='Start Date' |
|
||||
) |
|
||||
comparison_date_end = fields.Datetime( |
|
||||
string='End Date' |
|
||||
) |
|
||||
partner_ids = fields.Many2many( |
|
||||
comodel_name='res.partner', |
|
||||
string='Filter on partner', |
|
||||
help="Only selected partners will be printed. " |
|
||||
"Leave empty to print all partners." |
|
||||
) |
|
||||
debit_credit = fields.Boolean( |
|
||||
string='Display Debit/Credit Columns', |
|
||||
help="This option allows you to get more details about the way your " |
|
||||
"balances are computed. Because it is space consuming, " |
|
||||
"we do not allow to use it while doing a comparison." |
|
||||
) |
|
||||
|
|
||||
def pre_print_report(self, cr, uid, ids, data, context=None): |
|
||||
data = super(AccountBalanceCommonWizard, self).pre_print_report( |
|
||||
cr, uid, ids, data, context) |
|
||||
return data |
|
@ -1,57 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<odoo> |
|
||||
|
|
||||
<record id="account_balance_common_wizard_view" model="ir.ui.view"> |
|
||||
<field name="name">Balance Common Wizard</field> |
|
||||
<field name="model">account.common.balance.report</field> |
|
||||
<field name="mode">primary</field> |
|
||||
<field name="inherit_id" ref="account.account_common_report_view"/> |
|
||||
<field name="arch" type="xml"> |
|
||||
<data> |
|
||||
<field name="company_id" position='replace'> |
|
||||
<group name="main_info"> |
|
||||
<field name="company_id" readonly="0"/> |
|
||||
</group> |
|
||||
</field> |
|
||||
<field name="target_move" position="after"> |
|
||||
<field name="date_range_id"/> |
|
||||
<newline/> |
|
||||
</field> |
|
||||
<field name="date_to" position="after"> |
|
||||
<newline/> |
|
||||
<field name="debit_credit"/> |
|
||||
</field> |
|
||||
<footer position="before"> |
|
||||
<notebook> |
|
||||
<page string="Accounts Filters" name="accounts"> |
|
||||
<separator string="Print only" colspan="4"/> |
|
||||
<field name="account_ids" colspan="4" nolabel="1" domain="[('type', 'in', ['receivable', 'payable'])]"> |
|
||||
<tree> |
|
||||
<field name="code"/> |
|
||||
<field name="name"/> |
|
||||
<field name="user_type_id"/> |
|
||||
<field name="company_id"/> |
|
||||
</tree> |
|
||||
</field> |
|
||||
</page> |
|
||||
<page string="Partners Filters" name="partners"> |
|
||||
<separator string="Print only" colspan="4"/> |
|
||||
<field name="partner_ids" colspan="4" nolabel="1"/> |
|
||||
</page> |
|
||||
<page string="Comparison" name="comparison"> |
|
||||
<group> |
|
||||
<field name="comparison_date_range_id"/> |
|
||||
<field name="comparison_date_start"/> |
|
||||
<field name="comparison_date_end"/> |
|
||||
</group> |
|
||||
</page> |
|
||||
</notebook> |
|
||||
</footer> |
|
||||
<field name="journal_ids" position="attributes"> |
|
||||
<attribute name="invisible">True</attribute> |
|
||||
</field> |
|
||||
</data> |
|
||||
</field> |
|
||||
</record> |
|
||||
|
|
||||
</odoo> |
|
@ -0,0 +1,104 @@ |
|||||
|
# -*- 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 |
||||
|
) |
||||
|
date_range_id = fields.Many2one(comodel_name='date.range', required=True) |
||||
|
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.', |
||||
|
default=False) |
||||
|
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', |
||||
|
) |
||||
|
|
||||
|
@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 _export(self, xlsx_report=False): |
||||
|
"""Default export is PDF.""" |
||||
|
model = self.env['report_trial_balance_qweb'] |
||||
|
report = model.create({ |
||||
|
'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, |
||||
|
}) |
||||
|
return report.print_report(xlsx_report) |
@ -1,36 +1,56 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
|
|
||||
<record id="account_trial_balance_wizard_view" model="ir.ui.view"> |
|
||||
<field name="name">Trial Balance Wizard</field> |
|
||||
<field name="model">account.common.balance.report</field> |
|
||||
<field name="mode">primary</field> |
|
||||
<field name="inherit_id" ref="account_balance_common_wizard_view"/> |
|
||||
|
<!-- 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"> |
<field name="arch" type="xml"> |
||||
<data> |
|
||||
<field name="company_id" position="before"> |
|
||||
<label nolabel="1" colspan="4" string="This report allows you to print or generate a pdf of your trial balance allowing you to quickly check the balance of each of your accounts in a single report"/> |
|
||||
</field> |
|
||||
<field name="debit_credit" position="attributes"> |
|
||||
<attribute name="invisible">True</attribute> |
|
||||
</field> |
|
||||
<page name="partners" position="attributes"> |
|
||||
<attribute name="invisible">True</attribute> |
|
||||
</page> |
|
||||
|
|
||||
</data> |
|
||||
|
<form> |
||||
|
<group name="main_info"> |
||||
|
<field name="company_id" groups="base.group_multi_company"/> |
||||
|
</group> |
||||
|
<group name="filters"> |
||||
|
<group name="date_ranger"> |
||||
|
<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" 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"/> |
||||
|
<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> |
</field> |
||||
</record> |
</record> |
||||
|
|
||||
<record id="action_account_trial_balance_wizard_view" model="ir.actions.act_window"> |
|
||||
|
<record id="action_trial_balance_wizard" model="ir.actions.act_window"> |
||||
<field name="name">Trial Balance</field> |
<field name="name">Trial Balance</field> |
||||
<field name="type">ir.actions.act_window</field> |
<field name="type">ir.actions.act_window</field> |
||||
<field name="res_model">account.common.balance.report</field> |
|
||||
|
<field name="res_model">trial.balance.report.wizard</field> |
||||
<field name="view_type">form</field> |
<field name="view_type">form</field> |
||||
<field name="view_mode">form</field> |
<field name="view_mode">form</field> |
||||
<field name="view_id" ref="account_trial_balance_wizard_view"/> |
|
||||
|
<field name="view_id" ref="trial_balance_wizard"/> |
||||
<field name="target">new</field> |
<field name="target">new</field> |
||||
<field name="context">{'balance_common': 'trial_balance'}</field> |
|
||||
</record> |
</record> |
||||
|
|
||||
</odoo> |
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue