Browse Source

Add OCA Aged Partner Balance XLSX

pull/367/head
jcoux 9 years ago
committed by Jordi Ballester
parent
commit
e5d5df9cdc
  1. 4
      account_financial_report_qweb/README.rst
  2. 1
      account_financial_report_qweb/report/__init__.py
  3. 11
      account_financial_report_qweb/report/abstract_report_xlsx.py
  4. 10
      account_financial_report_qweb/report/aged_partner_balance.py
  5. 269
      account_financial_report_qweb/report/aged_partner_balance_xlsx.py
  6. 2
      account_financial_report_qweb/report/trial_balance_xlsx.py
  7. 9
      account_financial_report_qweb/reports.xml
  8. 27
      account_financial_report_qweb/tests/test_aged_partner_balance.py
  9. 9
      account_financial_report_qweb/wizard/aged_partner_balance_wizard.py
  10. 2
      account_financial_report_qweb/wizard/aged_partner_balance_wizard_view.xml

4
account_financial_report_qweb/README.rst

@ -21,10 +21,6 @@ Accunting / Reporting / OCA Reports.
Known issues / Roadmap
======================
Some reports are being worked on and will be available at some point:
- Aged Partner Balance (XLSX)
Bug Tracker
===========

1
account_financial_report_qweb/report/__init__.py

@ -6,6 +6,7 @@
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

11
account_financial_report_qweb/report/abstract_report_xlsx.py

@ -24,12 +24,14 @@ class AbstractReportXslx(ReportXlsx):
# 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
@ -59,14 +61,19 @@ class AbstractReportXslx(ReportXlsx):
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,
@ -88,6 +95,10 @@ class AbstractReportXslx(ReportXlsx):
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.

10
account_financial_report_qweb/report/aged_partner_balance.py

@ -185,11 +185,15 @@ class AgedPartnerBalanceReportCompute(models.TransientModel):
_inherit = 'report_aged_partner_balance_qweb'
@api.multi
def print_report(self):
def print_report(self, xlsx_report=False):
self.ensure_one()
self.compute_data_for_report()
report_name = 'account_financial_report_qweb.' \
'report_aged_partner_balance_qweb'
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)

269
account_financial_report_qweb/report/aged_partner_balance_xlsx.py

@ -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
)

2
account_financial_report_qweb/report/trial_balance_xlsx.py

@ -102,7 +102,7 @@ class TrialBalanceXslx(abstract_report_xlsx.AbstractReportXslx):
# Display partner lines
self.write_line(partner)
# Display account lines
# Display account footer line
self.write_account_footer(account,
account.code + ' - ' + account.name)

9
account_financial_report_qweb/reports.xml

@ -102,4 +102,13 @@
<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>

27
account_financial_report_qweb/tests/test_aged_partner_balance.py

@ -45,3 +45,30 @@ class TestAgedPartnerBalance(TransactionCase):
report_html = self.env['report'].get_html(self.report, report_name)
self.assertRegexpMatches(report_html, 'Aged Partner 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_aged_partner_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_aged_partner_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')

9
account_financial_report_qweb/wizard/aged_partner_balance_wizard.py

@ -57,7 +57,12 @@ class AgedPartnerBalance(models.TransientModel):
self.ensure_one()
return self._export()
def _export(self):
@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_aged_partner_balance_qweb']
report = model.create({
@ -68,4 +73,4 @@ class AgedPartnerBalance(models.TransientModel):
'filter_partner_ids': [(6, 0, self.partner_ids.ids)],
'show_move_line_details': self.show_move_line_details,
})
return report.print_report()
return report.print_report(xlsx_report)

2
account_financial_report_qweb/wizard/aged_partner_balance_wizard_view.xml

@ -31,6 +31,8 @@
<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>

Loading…
Cancel
Save