Add OCA Trial Balance report PDF and XLSX
parent
e763ce0631
commit
acbaa0f50a
|
@ -23,7 +23,8 @@ Known issues / Roadmap
|
|||
|
||||
Some reports are being worked on and will be available at some point:
|
||||
|
||||
- Trial Balance
|
||||
- Open Items (XLSX)
|
||||
- Aged Partner Balance (XLSX)
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
'wizard/aged_partner_balance_wizard_view.xml',
|
||||
'wizard/general_ledger_wizard_view.xml',
|
||||
'wizard/open_items_wizard_view.xml',
|
||||
'wizard/balance_common_wizard_view.xml',
|
||||
'wizard/trial_balance_wizard_view.xml',
|
||||
'menuitems.xml',
|
||||
'reports.xml',
|
||||
|
@ -33,6 +32,7 @@
|
|||
'report/templates/general_ledger.xml',
|
||||
'report/templates/layouts.xml',
|
||||
'report/templates/open_items.xml',
|
||||
'report/templates/trial_balance.xml',
|
||||
'view/account_view.xml'
|
||||
],
|
||||
'test': [
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
<menuitem
|
||||
parent="menu_oca_reports"
|
||||
action="action_account_trial_balance_wizard_view"
|
||||
id="menu_account_trial_balance_report"
|
||||
action="action_trial_balance_wizard"
|
||||
id="menu_trial_balance_wizard"
|
||||
sequence="20"
|
||||
/>
|
||||
|
||||
|
|
|
@ -9,3 +9,5 @@ from . import aged_partner_balance
|
|||
from . import general_ledger
|
||||
from . import general_ledger_xlsx
|
||||
from . import open_items
|
||||
from . import trial_balance
|
||||
from . import trial_balance_xlsx
|
||||
|
|
|
@ -40,7 +40,7 @@ class AbstractReportXslx(ReportXlsx):
|
|||
|
||||
report_name = self._get_report_name()
|
||||
filters = self._get_report_filters(report)
|
||||
self.columns = self._get_report_columns()
|
||||
self.columns = self._get_report_columns(report)
|
||||
|
||||
self.sheet = workbook.add_worksheet(report_name[:31])
|
||||
|
||||
|
@ -175,7 +175,7 @@ class AbstractReportXslx(ReportXlsx):
|
|||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def _get_report_columns(self):
|
||||
def _get_report_columns(self, report):
|
||||
"""
|
||||
Allow to define the report columns
|
||||
which will be used to generate report.
|
||||
|
|
|
@ -24,7 +24,7 @@ class GeneralLedgerXslx(abstract_report_xlsx.AbstractReportXslx):
|
|||
def _get_report_name(self):
|
||||
return _('General Ledger')
|
||||
|
||||
def _get_report_columns(self):
|
||||
def _get_report_columns(self, report):
|
||||
return {
|
||||
0: {'header': _('Date'), 'field': 'date', 'width': 11},
|
||||
1: {'header': _('Entry'), 'field': 'entry', 'width': 18},
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -12,6 +12,15 @@
|
|||
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"
|
||||
|
@ -52,6 +61,10 @@
|
|||
<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>
|
||||
|
@ -71,4 +84,13 @@
|
|||
<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>
|
||||
|
||||
</odoo>
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
from . import test_aged_partner_balance
|
||||
from . import test_general_ledger
|
||||
from . import test_open_items
|
||||
from . import test_trial_balance
|
||||
|
|
|
@ -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')
|
|
@ -4,6 +4,6 @@
|
|||
# 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 balance_common_wizard
|
||||
from . import general_ledger_wizard
|
||||
from . import open_items_wizard
|
||||
from . import trial_balance_wizard
|
||||
|
|
|
@ -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"?>
|
||||
<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">
|
||||
<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>
|
||||
</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="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_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="context">{'balance_common': 'trial_balance'}</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
|
Loading…
Reference in New Issue