diff --git a/account_financial_report_webkit/__openerp__.py b/account_financial_report_webkit/__openerp__.py
index 32bfc466..40bfc53b 100644
--- a/account_financial_report_webkit/__openerp__.py
+++ b/account_financial_report_webkit/__openerp__.py
@@ -30,7 +30,7 @@ This module adds or replaces the following standard OpenERP financial reports:
- Partner ledger
- Partner balance
- Open invoices report
-
+ - Aged Partner Balance
Main improvements per report:
-----------------------------
@@ -100,6 +100,47 @@ The Partner balance: list of account with balances
* Subtotal by account and partner
* Alphabetical sorting (same as in partner balance)
+
+Aged Partner Balance: Summary of aged open amount per partner
+
+This report is an accounting tool helping in various tasks.
+You can credit control or partner balance provisions computation for instance.
+
+The aged balance report allows you to print balances per partner
+like the trial balance but add an extra information :
+
+* It will split balances into due amounts
+ (due date not reached à the end date of the report) and overdue amounts
+ Overdue data are also split by period.
+* For each partner following columns will be displayed:
+
+ * Total balance (all figures must match with same date partner balance report).
+ This column equals the sum of all following columns)
+
+ * Due
+ * Overdue <= 30 days
+ * Overdue <= 60 days
+ * Overdue <= 90 days
+ * Overdue <= 120 days
+ * Older
+
+Hypothesis / Contraints of aged partner balance
+
+* Overdues columns will be by default be based on 30 days range fix number of days.
+ This can be changed by changes the RANGES constraint
+* All data will be displayed in company currency
+* When partial payments, the payment must appear in the same colums than the invoice
+ (Except if multiple payment terms)
+* Data granularity: partner (will not display figures at invoices level)
+* The report aggregate data per account with sub-totals
+* Initial balance must be calculated the same way that
+ the partner balance / Ignoring the opening entry
+ in special period (idem open invoice report)
+* Only accounts with internal type payable or receivable are considered
+ (idem open invoice report)
+* If maturity date is null then use move line date
+
+
Limitations:
------------
@@ -126,7 +167,7 @@ an issue in wkhtmltopdf
the header and footer are created as text with arguments passed to
wkhtmltopdf. The texts are defined inside the report classes.
""",
- 'version': '1.0.2',
+ 'version': '1.1.0',
'author': 'Camptocamp',
'license': 'AGPL-3',
'category': 'Finance',
@@ -147,6 +188,7 @@ wkhtmltopdf. The texts are defined inside the report classes.
'wizard/trial_balance_wizard_view.xml',
'wizard/partner_balance_wizard_view.xml',
'wizard/open_invoices_wizard_view.xml',
+ 'wizard/aged_partner_balance_wizard.xml',
'wizard/print_journal_view.xml',
'report_menus.xml',
],
@@ -155,7 +197,8 @@ wkhtmltopdf. The texts are defined inside the report classes.
'tests/partner_ledger.yml',
'tests/trial_balance.yml',
'tests/partner_balance.yml',
- 'tests/open_invoices.yml',],
+ 'tests/open_invoices.yml',
+ 'tests/aged_trial_balance.yml'],
#'tests/account_move_line.yml'
'active': False,
'installable': True,
diff --git a/account_financial_report_webkit/report/__init__.py b/account_financial_report_webkit/report/__init__.py
index f8bc59fb..e597e39d 100644
--- a/account_financial_report_webkit/report/__init__.py
+++ b/account_financial_report_webkit/report/__init__.py
@@ -9,3 +9,4 @@ from . import trial_balance
from . import partner_balance
from . import open_invoices
from . import print_journal
+from . import aged_partner_balance
diff --git a/account_financial_report_webkit/report/aged_partner_balance.py b/account_financial_report_webkit/report/aged_partner_balance.py
new file mode 100644
index 00000000..ef81d326
--- /dev/null
+++ b/account_financial_report_webkit/report/aged_partner_balance.py
@@ -0,0 +1,403 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Nicolas Bessi
+# Copyright 2014 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+from __future__ import division
+from datetime import datetime
+
+from openerp import pooler
+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
+from openerp.tools.translate import _
+from .open_invoices import PartnersOpenInvoicesWebkit
+from .webkit_parser_header_fix import HeaderFooterTextWebKitParser
+
+
+def make_ranges(top, offset):
+ """Return sorted days ranges
+
+ :param top: maximum overdue day
+ :param offset: offset for ranges
+
+ :returns: list of sorted ranges tuples in days
+ eg. [(-100000, 0), (0, offset), (offset, n*offset), ... (top, 100000)]
+ """
+ ranges = [(n, min(n + offset, top)) for n in xrange(0, top, offset)]
+ ranges.insert(0, (-100000000000, 0))
+ ranges.append((top, 100000000000))
+ return ranges
+
+#list of overdue ranges
+RANGES = make_ranges(120, 30)
+
+
+def make_ranges_titles():
+ """Generates title to be used by mako"""
+ titles = [_('Due')]
+ titles += [_(u'Overdue ≤ %s d.') % x[1] for x in RANGES[1:-1]]
+ titles.append(_('Older'))
+ return titles
+
+#list of overdue ranges title
+RANGES_TITLES = make_ranges_titles()
+#list of payable journal types
+REC_PAY_TYPE = ('purchase', 'sale')
+#list of refund payable type
+REFUND_TYPE = ('purchase_refund', 'sale_refund')
+INV_TYPE = REC_PAY_TYPE + REFUND_TYPE
+
+
+class AccountAgedTrialBalanceWebkit(PartnersOpenInvoicesWebkit):
+ """Compute Aged Partner Balance based on result of Open Invoices"""
+
+ def __init__(self, cursor, uid, name, context=None):
+ """Constructor, refer to :class:`openerp.report.report_sxw.rml_parse`"""
+ super(AccountAgedTrialBalanceWebkit, self).__init__(cursor, uid, name,
+ context=context)
+ self.pool = pooler.get_pool(self.cr.dbname)
+ self.cursor = self.cr
+ company = self.pool.get('res.users').browse(self.cr, uid, uid,
+ context=context).company_id
+
+ header_report_name = ' - '.join((_('Aged Partner Balance'),
+ company.currency_id.name))
+
+ footer_date_time = self.formatLang(str(datetime.today()),
+ date_time=True)
+
+ self.localcontext.update({
+ 'cr': cursor,
+ 'uid': uid,
+ 'company': company,
+ 'ranges': self._get_ranges(),
+ 'ranges_titles': self._get_ranges_titles(),
+ 'report_name': _('Aged Partner Balance'),
+ 'additional_args': [
+ ('--header-font-name', 'Helvetica'),
+ ('--footer-font-name', 'Helvetica'),
+ ('--header-font-size', '10'),
+ ('--footer-font-size', '6'),
+ ('--header-left', header_report_name),
+ ('--header-spacing', '2'),
+ ('--footer-left', footer_date_time),
+ ('--footer-right', ' '.join((_('Page'), '[page]', _('of'), '[topage]'))),
+ ('--footer-line',),
+ ],
+ })
+
+ def _get_ranges(self):
+ """:returns: :cons:`RANGES`"""
+ return RANGES
+
+ def _get_ranges_titles(self):
+ """:returns: :cons: `RANGES_TITLES`"""
+ return RANGES_TITLES
+
+ def set_context(self, objects, data, ids, report_type=None):
+ """Populate aged_lines, aged_balance, aged_percents attributes
+
+ on each account browse record that will be used by mako template
+ The browse record are store in :attr:`objects`
+
+ The computation are based on the ledger_lines attribute set on account
+ contained by :attr:`objects`
+
+ :attr:`objects` values were previously set by parent class
+ :class: `.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :returns: parent :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+ call to set_context
+
+ """
+ res = super(AccountAgedTrialBalanceWebkit, self).set_context(
+ objects,
+ data,
+ ids,
+ report_type=report_type
+ )
+
+ for acc in self.objects:
+ acc.aged_lines = {}
+ acc.agged_totals = {}
+ acc.agged_percents = {}
+ for part_id, partner_lines in acc.ledger_lines.items():
+ aged_lines = self.compute_aged_lines(part_id,
+ partner_lines,
+ data)
+ if aged_lines:
+ acc.aged_lines[part_id] = aged_lines
+ acc.aged_totals = totals = self.compute_totals(acc.aged_lines.values())
+ acc.aged_percents = self.compute_percents(totals)
+ #Free some memory
+ del(acc.ledger_lines)
+ return res
+
+ def compute_aged_lines(self, partner_id, ledger_lines, data):
+ """Add property aged_lines to accounts browse records
+
+ contained in :attr:`objects` for a given partner
+
+ :param: partner_id: current partner
+ :param ledger_lines: generated by parent
+ :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :returns: dict of computed aged lines
+ eg {'balance': 1000.0,
+ 'aged_lines': {(90, 120): 0.0, ...}
+
+ """
+ lines_to_age = self.filter_lines(partner_id, ledger_lines)
+ res = {}
+ end_date = self._get_end_date(data)
+ aged_lines = dict.fromkeys(RANGES, 0.0)
+ reconcile_lookup = self.get_reconcile_count_lookup(lines_to_age)
+ res['aged_lines'] = aged_lines
+ for line in lines_to_age:
+ compute_method = self.get_compute_method(reconcile_lookup,
+ partner_id,
+ line)
+ delay = compute_method(line, end_date, ledger_lines)
+ classification = self.classify_line(partner_id, delay)
+ aged_lines[classification] += line['debit'] - line['credit']
+ self.compute_balance(res, aged_lines)
+ return res
+
+ def _get_end_date(self, data):
+ """Retrieve end date to be used to compute delay.
+
+ :param data: data dict send to report contains form dict
+
+ :returns: end date to be used to compute overdue delay
+
+ """
+ end_date = None
+ date_to = data['form']['date_to']
+ period_to_id = data['form']['period_to']
+ fiscal_to_id = data['form']['fiscalyear_id']
+ if date_to:
+ end_date = date_to
+ elif period_to_id:
+ period_to = self.pool['account.period'].browse(self.cr,
+ self.uid,
+ period_to_id)
+ end_date = period_to.date_stop
+ elif fiscal_to_id:
+ fiscal_to = self.pool['account.fiscalyear'].browse(self.cr,
+ self.uid,
+ fiscal_to_id)
+ end_date = fiscal_to.date_stop
+ else:
+ raise ValueError('End date and end period not available')
+ return end_date
+
+ def _compute_delay_from_key(self, key, line, end_date):
+ """Compute overdue delay delta in days for line using attribute in key
+
+ delta = end_date - date of key
+
+ :param line: current ledger line
+ :param key: date key to be used to compute delta
+ :param end_date: end_date computed for wizard data
+
+ :returns: delta in days
+ """
+ from_date = datetime.strptime(line[key], DEFAULT_SERVER_DATE_FORMAT)
+ end_date = datetime.strptime(end_date, DEFAULT_SERVER_DATE_FORMAT)
+ delta = end_date - from_date
+ return delta.days
+
+ def compute_delay_from_maturity(self, line, end_date, ledger_lines):
+ """Compute overdue delay delta in days for line using attribute in key
+
+ delta = end_date - maturity date
+
+ :param line: current ledger line
+ :param end_date: end_date computed for wizard data
+ :param ledger_lines: generated by parent
+ :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :returns: delta in days
+ """
+ return self._compute_delay_from_key('date_maturity',
+ line,
+ end_date)
+
+ def compute_delay_from_date(self, line, end_date, ledger_lines):
+ """Compute overdue delay delta in days for line using attribute in key
+
+ delta = end_date - date
+
+ :param line: current ledger line
+ :param end_date: end_date computed for wizard data
+ :param ledger_lines: generated by parent
+ :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :returns: delta in days
+ """
+ return self._compute_delay_from_key('ldate',
+ line,
+ end_date)
+
+ def compute_delay_from_partial_rec(self, line, end_date, ledger_lines):
+ """Compute overdue delay delta in days for the case where move line
+
+ is related to a partial reconcile with more than one reconcile line
+
+ :param line: current ledger line
+ :param end_date: end_date computed for wizard data
+ :param ledger_lines: generated by parent
+ :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :returns: delta in days
+ """
+ sale_lines = [x for x in ledger_lines if x['jtype'] in REC_PAY_TYPE and
+ line['rec_id'] == x['rec_id']]
+ refund_lines = [x for x in ledger_lines if x['jtype'] in REFUND_TYPE and
+ line['rec_id'] == x['rec_id']]
+ if len(sale_lines) == 1:
+ reference_line = sale_lines[0]
+ elif len(refund_lines) == 1:
+ reference_line = refund_lines[0]
+ else:
+ reference_line = line
+ key = 'date_maturity' if reference_line.get('date_maturity') else 'ldate'
+ return self._compute_delay_from_key(key,
+ reference_line,
+ end_date)
+
+ def get_compute_method(self, reconcile_lookup, partner_id, line):
+ """Get the function that should compute the delay for a given line
+
+ :param reconcile_lookup: dict of reconcile group by id and count
+ {rec_id: count of line related to reconcile}
+ :param partner_id: current partner_id
+ :param line: current ledger line generated by parent
+ :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :returns: function bounded to :class:`.AccountAgedTrialBalanceWebkit`
+
+ """
+ if reconcile_lookup.get(line['rec_id'], 0.0) > 1:
+ return self.compute_delay_from_partial_rec
+ elif line['jtype'] in INV_TYPE and line.get('date_maturity'):
+ return self.compute_delay_from_maturity
+ else:
+ return self.compute_delay_from_date
+
+ def line_is_valid(self, partner_id, line):
+ """Predicate hook that allows to filter line to be treated
+
+ :param partner_id: current partner_id
+ :param line: current ledger line generated by parent
+ :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :returns: boolean True if line is allowed
+ """
+ return True
+
+ def filter_lines(self, partner_id, lines):
+ """Filter ledger lines that have to be treated
+
+ :param partner_id: current partner_id
+ :param lines: ledger_lines related to current partner
+ and generated by parent
+ :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :returns: list of allowed lines
+
+ """
+ return [x for x in lines if self.line_is_valid(partner_id, x)]
+
+ def classify_line(self, partner_id, overdue_days):
+ """Return the overdue range for a given delay
+
+ We loop from smaller range to higher
+ This should be the most effective solution as generaly
+ customer tend to have one or two month of delay
+
+ :param overdue_days: delay in days
+ :param partner_id: current partner_id
+
+ :returns: the correct range in :const:`RANGES`
+
+ """
+ for drange in RANGES:
+ if overdue_days <= drange[1]:
+ return drange
+ return drange
+
+ def compute_balance(self, res, aged_lines):
+ """Compute the total balance of aged line
+ for given account"""
+ res['balance'] = sum(aged_lines.values())
+
+ def compute_totals(self, aged_lines):
+ """Compute the totals for an account
+
+ :param aged_lines: dict of aged line taken from the
+ property added to account record
+
+ :returns: dict of total {'balance':1000.00, (30, 60): 3000,...}
+
+ """
+ totals = {}
+ totals['balance'] = sum(x.get('balance', 0.0) for
+ x in aged_lines)
+ aged_ranges = [x.get('aged_lines', {}) for x in aged_lines]
+ for drange in RANGES:
+ totals[drange] = sum(x.get(drange, 0.0) for x in aged_ranges)
+ return totals
+
+ def compute_percents(self, totals):
+ percents = {}
+ base = totals['balance'] or 1.0
+ for drange in RANGES:
+ percents[drange] = (totals[drange] / base) * 100.0
+ return percents
+
+ def get_reconcile_count_lookup(self, lines):
+ """Compute an lookup dict
+
+ It contains has partial reconcile id as key and the count of lines
+ related to the reconcile id
+
+ :param: a list of ledger lines generated by parent
+ :class:`.open_invoices.PartnersOpenInvoicesWebkit`
+
+ :retuns: lookup dict {ṛec_id: count}
+
+ """
+ # possible bang if l_ids is really long.
+ # We have the same weakness in common_report ...
+ # but it seems not really possible for a partner
+ # So I'll keep that option.
+ l_ids = tuple(x['id'] for x in lines)
+ sql = ("SELECT reconcile_partial_id, COUNT(*) FROM account_move_line"
+ " WHERE reconcile_partial_id IS NOT NULL"
+ " AND id in %s"
+ " GROUP BY reconcile_partial_id")
+ self.cr.execute(sql, (l_ids,))
+ res = self.cr.fetchall()
+ return dict((x[0], x[1]) for x in res)
+
+HeaderFooterTextWebKitParser(
+ 'report.account.account_aged_trial_balance_webkit',
+ 'account.account',
+ 'addons/account_financial_report_webkit/report/templates/aged_trial_webkit.mako',
+ parser=AccountAgedTrialBalanceWebkit,
+)
diff --git a/account_financial_report_webkit/report/common_reports.py b/account_financial_report_webkit/report/common_reports.py
index 3a0a2a15..617cc97e 100644
--- a/account_financial_report_webkit/report/common_reports.py
+++ b/account_financial_report_webkit/report/common_reports.py
@@ -30,7 +30,7 @@ from openerp.addons.account.report.common_report_header import common_report_hea
_logger = logging.getLogger('financial.reports.webkit')
-
+MAX_MONSTER_SLICE = 50000
class CommonReportHeaderWebkit(common_report_header):
"""Define common helper for financial report"""
@@ -433,6 +433,14 @@ class CommonReportHeaderWebkit(common_report_header):
raise osv.except_osv(_('No valid filter'), _('Please set a valid time filter'))
def _get_move_line_datas(self, move_line_ids, order='per.special DESC, l.date ASC, per.date_start ASC, m.name ASC'):
+ # Possible bang if move_line_ids is too long
+ # We can not slice here as we have to do the sort.
+ # If slice has to be done it means that we have to reorder in python
+ # after all is finished. That quite crapy...
+ # We have a defective desing here (mea culpa) that should be fixed
+ #
+ # TODO improve that by making a better domain or if not possible
+ # by using python sort
if not move_line_ids:
return []
if not isinstance(move_line_ids, list):
@@ -441,6 +449,7 @@ class CommonReportHeaderWebkit(common_report_header):
SELECT l.id AS id,
l.date AS ldate,
j.code AS jcode ,
+ j.type AS jtype,
l.currency_id,
l.account_id,
l.amount_currency,
@@ -455,7 +464,8 @@ SELECT l.id AS id,
l.partner_id AS lpartner_id,
p.name AS partner_name,
m.name AS move_name,
- COALESCE(partialrec.name, fullrec.name, '') AS rec_name,
+ COALESCE(partialrec.name, fullrec.name, '') AS rec_name,
+ COALESCE(partialrec.id, fullrec.id, NULL) AS rec_id,
m.id AS move_id,
c.name AS currency_code,
i.id AS invoice_id,
diff --git a/account_financial_report_webkit/report/open_invoices.py b/account_financial_report_webkit/report/open_invoices.py
index 237f9e4f..cce03dec 100644
--- a/account_financial_report_webkit/report/open_invoices.py
+++ b/account_financial_report_webkit/report/open_invoices.py
@@ -93,7 +93,6 @@ class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeade
"""Populate a ledger_lines attribute on each browse record that will be used
by mako template"""
new_ids = data['form']['chart_account_id']
-
# Account initial balance memoizer
init_balance_memoizer = {}
# Reading form
diff --git a/account_financial_report_webkit/report/report.xml b/account_financial_report_webkit/report/report.xml
index 6fa33a25..41278e3a 100644
--- a/account_financial_report_webkit/report/report.xml
+++ b/account_financial_report_webkit/report/report.xml
@@ -14,23 +14,16 @@
General Ledger Webkitaccount_financial_report_webkit/report/templates/account_report_general_ledger.makoaccount_financial_report_webkit/report/templates/account_report_general_ledger.mako
-
+
+
account_report_general_ledger_webkit
-
-
-
+
+
webkitaccount.account_report_partners_ledger_webkit
@@ -44,6 +37,7 @@
account_financial_report_webkit/report/templates/account_report_partners_ledger.makoaccount_financial_report_webkit/report/templates/account_report_partners_ledger.mako
+
account_report_partners_ledger_webkit
@@ -64,6 +58,7 @@
account_financial_report_webkit/report/templates/account_report_trial_balance.makoaccount_financial_report_webkit/report/templates/account_report_trial_balance.mako
+
account_report_trial_balance_webkit
@@ -84,6 +79,7 @@
account_financial_report_webkit/report/templates/account_report_partner_balance.makoaccount_financial_report_webkit/report/templates/account_report_partner_balance.mako
+
account_report_partner_balance_webkit
@@ -104,6 +100,7 @@
account_financial_report_webkit/report/templates/account_report_open_invoices.makoaccount_financial_report_webkit/report/templates/account_report_open_invoices.mako
+
account_report_open_invoices_webkit
@@ -111,6 +108,31 @@
+
+ webkit
+ account.account_aged_trial_balance_webkit
+
+
+
+
+ account.account
+ ir.actions.report.xml
+ Aged Partner Balance
+ account_financial_report_webkit/report/templates/aged_trial_webkit.mako
+ account_financial_report_webkit/report/templates/aged_trial_webkit.mako
+
+
+
+ account_aged_trial_balance_webkit
+
+
+
+
+
webkitaccount.account_report_print_journal_webkit
@@ -124,6 +146,7 @@
account_financial_report_webkit/report/templates/account_report_print_journal.makoaccount_financial_report_webkit/report/templates/account_report_print_journal.mako
+
account_report_print_journal_webkit
diff --git a/account_financial_report_webkit/report/templates/aged_trial_webkit.mako b/account_financial_report_webkit/report/templates/aged_trial_webkit.mako
new file mode 100644
index 00000000..d021e252
--- /dev/null
+++ b/account_financial_report_webkit/report/templates/aged_trial_webkit.mako
@@ -0,0 +1,155 @@
+## -*- coding: utf-8 -*-
+
+
+
+
+
+
+ <%!
+ def amount(text):
+ # replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers)
+ return text.replace('-', '‑')
+ %>
+
+ <%setLang(user.lang)%>
+
+
diff --git a/account_financial_report_webkit/report/webkit_parser_header_fix.py b/account_financial_report_webkit/report/webkit_parser_header_fix.py
index a6c24698..9f8b9fb8 100644
--- a/account_financial_report_webkit/report/webkit_parser_header_fix.py
+++ b/account_financial_report_webkit/report/webkit_parser_header_fix.py
@@ -160,7 +160,6 @@ class HeaderFooterTextWebKitParser(webkit_report.WebKitParser):
# override needed to keep the attachments' storing procedure
def create_single_pdf(self, cursor, uid, ids, data, report_xml, context=None):
"""generate the PDF"""
-
if context is None:
context={}
htmls = []
diff --git a/account_financial_report_webkit/report_menus.xml b/account_financial_report_webkit/report_menus.xml
index 22b86f8b..c287bd38 100644
--- a/account_financial_report_webkit/report_menus.xml
+++ b/account_financial_report_webkit/report_menus.xml
@@ -18,6 +18,10 @@
parent="account.next_id_22" action="action_account_partner_balance_menu_webkit"
groups="account.group_account_manager,account.group_account_user" id="account.menu_account_partner_balance_report"/>
+
+
diff --git a/account_financial_report_webkit/tests/aged_trial_balance.yml b/account_financial_report_webkit/tests/aged_trial_balance.yml
new file mode 100644
index 00000000..fa311429
--- /dev/null
+++ b/account_financial_report_webkit/tests/aged_trial_balance.yml
@@ -0,0 +1,60 @@
+-
+ In order to test the PDF Aged Partner Balance Report webkit wizard I will print report with default setting
+-
+ !python {model: account.account}: |
+ from datetime import datetime
+ ctx={}
+ data_dict = {'chart_account_id':ref('account.chart0'), 'until_date': '%s-12-31' %(datetime.now().year)}
+ from tools import test_reports
+ test_reports.try_report_action(cr, uid, 'action_account_aged_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit')
+
+-
+ In order to test the PDF Aged Partner Balance Report webkit wizard I will print report with filters and currency
+-
+ !python {model: account.account}: |
+ from datetime import datetime
+ ctx={}
+ data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'),
+ 'until_date': '%s-12-31' %(datetime.now().year), 'target_move': 'posted',
+ 'amount_currency': True, 'result_selection': 'customer_supplier'}
+ from tools import test_reports
+ test_reports.try_report_action(cr, uid, 'action_account_aged_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit')
+
+-
+ In order to test the PDF Aged Partner Balance Report webkit wizard I will print report with filters on partners
+-
+ !python {model: account.account}: |
+ from datetime import datetime
+ ctx={}
+ data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'),
+ 'until_date': '%s-12-31' %(datetime.now().year), 'target_move': 'posted',
+ 'amount_currency': True, 'result_selection': 'customer_supplier',
+ 'partner_ids': [ref('base.res_partner_2'), ref('base.res_partner_1')]}
+ from tools import test_reports
+ test_reports.try_report_action(cr, uid, 'action_account_aged_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit')
+
+-
+ In order to test the PDF Aged Partner Balance Report webkit wizard I will print report with filters on periods
+-
+ !python {model: account.account}: |
+ from datetime import datetime
+ ctx={}
+ data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'),
+ 'until_date': '%s-12-31' %(datetime.now().year), 'target_move': 'posted',
+ 'amount_currency': True, 'result_selection': 'customer_supplier',
+ 'filter': 'filter_period', 'period_from': ref('account.period_1'), 'period_to': ref('account.period_12')}
+ from tools import test_reports
+ test_reports.try_report_action(cr, uid, 'action_account_aged_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit')
+
+-
+ In order to test the PDF Aged Partner Balance Report webkit wizard I will print report with filters on dates
+-
+ !python {model: account.account}: |
+ from datetime import datetime
+ ctx={}
+ data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'),
+ 'until_date': '%s-12-31' %(datetime.now().year), 'target_move': 'posted',
+ 'amount_currency': True, 'result_selection': 'customer_supplier',
+ 'filter': 'filter_date', 'date_from': '%s-01-01' %(datetime.now().year), 'date_to': '%s-12-31' %(datetime.now().year)}
+ from tools import test_reports
+ test_reports.try_report_action(cr, uid, 'action_account_aged_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit')
diff --git a/account_financial_report_webkit/wizard/__init__.py b/account_financial_report_webkit/wizard/__init__.py
index bf2cc01c..e261be6f 100644
--- a/account_financial_report_webkit/wizard/__init__.py
+++ b/account_financial_report_webkit/wizard/__init__.py
@@ -27,3 +27,4 @@ from . import trial_balance_wizard
from . import partner_balance_wizard
from . import open_invoices_wizard
from . import print_journal
+from . import aged_partner_balance_wizard
diff --git a/account_financial_report_webkit/wizard/aged_partner_balance_wizard.py b/account_financial_report_webkit/wizard/aged_partner_balance_wizard.py
new file mode 100644
index 00000000..a3126489
--- /dev/null
+++ b/account_financial_report_webkit/wizard/aged_partner_balance_wizard.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Nicolas Bessi
+# Copyright 2014 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+from openerp.osv import orm
+
+
+class AccountAgedTrialBalance(orm.TransientModel):
+ """Will launch age partner balance report.
+ This report is based on Open Invoice Report
+ and share a lot of knowledge with him
+ """
+
+ _inherit = "open.invoices.webkit"
+ _name = "account.aged.trial.balance.webkit"
+ _description = "Aged partner balanced"
+
+ def _print_report(self, cr, uid, ids, data, context=None):
+ # we update form with display account value
+ data = self.pre_print_report(cr, uid, ids, data, context=context)
+ return {'type': 'ir.actions.report.xml',
+ 'report_name': 'account.account_aged_trial_balance_webkit',
+ 'datas': data}
diff --git a/account_financial_report_webkit/wizard/aged_partner_balance_wizard.xml b/account_financial_report_webkit/wizard/aged_partner_balance_wizard.xml
new file mode 100644
index 00000000..2d0d7273
--- /dev/null
+++ b/account_financial_report_webkit/wizard/aged_partner_balance_wizard.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+ Aged Partner Balance Report
+ account.aged.trial.balance.webkit
+
+
+
+
+
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Time Filters
+
+
+ True
+
+
+ onchange_fiscalyear(fiscalyear_id, period_to, date_to, until_date)
+
+
+ onchange_date_to(fiscalyear_id, period_to, date_to, until_date)
+
+
+ onchange_period_to(fiscalyear_id, period_to, date_to, until_date)
+
+
+ [('fiscalyear_id', '=', fiscalyear_id), ('special', '=', False)]
+
+
+ [('fiscalyear_id', '=', fiscalyear_id), ('special', '=', False)]
+
+
+
+
+
+
+ Aged partner balance
+ ir.actions.act_window
+ account.aged.trial.balance.webkit
+ form
+ form
+
+ new
+
+
+