Browse Source

Merge pull request #102 from akretion/8.0-aged-open-invoices

8.0 Add "Aged Open Invoices" report in account_financial_report_webkit
pull/191/head
Pedro M. Baeza 9 years ago
parent
commit
89d386cde1
  1. 1
      account_financial_report_webkit/__openerp__.py
  2. 1
      account_financial_report_webkit/report/__init__.py
  3. 415
      account_financial_report_webkit/report/aged_open_invoices.py
  4. 4
      account_financial_report_webkit/report/aged_partner_balance.py
  5. 21
      account_financial_report_webkit/report/report.xml
  6. 177
      account_financial_report_webkit/report/templates/aged_open_invoices.mako
  7. 4
      account_financial_report_webkit/report/templates/aged_trial_webkit.mako
  8. 18
      account_financial_report_webkit/report_menus.xml
  9. 1
      account_financial_report_webkit/wizard/__init__.py
  10. 61
      account_financial_report_webkit/wizard/aged_open_invoices_wizard.py
  11. 72
      account_financial_report_webkit/wizard/aged_open_invoices_wizard.xml

1
account_financial_report_webkit/__openerp__.py

@ -189,6 +189,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_open_invoices_wizard.xml',
'wizard/aged_partner_balance_wizard.xml',
'wizard/print_journal_view.xml',
'report_menus.xml',

1
account_financial_report_webkit/report/__init__.py

@ -10,3 +10,4 @@ from . import partner_balance
from . import open_invoices
from . import print_journal
from . import aged_partner_balance
from . import aged_open_invoices

415
account_financial_report_webkit/report/aged_open_invoices.py

@ -0,0 +1,415 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Alexis de Lattre
# Author: Nicolas Bessi
# Copyright 2015 Akretion (www.akretion.com)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
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 = [_('Not Due')]
titles += [_(u'Overdue ≤ %s d.') % x[1] for x in RANGES[1:-1]]
titles.append(_('Overdue > %s d.') % RANGES[-1][0])
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 AccountAgedOpenInvoicesWebkit(PartnersOpenInvoicesWebkit):
"""Compute Aged Open Invoices 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(AccountAgedOpenInvoicesWebkit, 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 Open Invoices'),
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 Open Invoices'),
'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(AccountAgedOpenInvoicesWebkit, self).set_context(
objects,
data,
ids,
report_type=report_type
)
aged_open_inv = {}
# Stupid dict that we copy in parts of the main aged_open_inv dict
aged_dict = {}
for classif in self.localcontext['ranges']:
aged_dict[classif] = 0.0
for acc in self.objects:
aged_open_inv[acc.id] = aged_dict.copy()
aged_open_inv[acc.id]['balance'] = 0.0
for part_id, partner_lines in\
self.localcontext['ledger_lines'][acc.id].items():
aged_open_inv[acc.id][part_id] = aged_dict.copy()
aged_open_inv[acc.id][part_id]['balance'] = 0.0
aged_open_inv[acc.id][part_id]['lines'] = list(partner_lines)
for line in aged_open_inv[acc.id][part_id]['lines']:
line.update(aged_dict)
self.compute_aged_line(part_id, line, data)
aged_open_inv[acc.id][part_id]['balance'] +=\
line['balance']
aged_open_inv[acc.id]['balance'] += line['balance']
for classif in self.localcontext['ranges']:
aged_open_inv[acc.id][part_id][classif] +=\
line[classif]
aged_open_inv[acc.id][classif] +=\
line[classif]
self.localcontext.update({
'aged_open_inv': aged_open_inv,
})
return res
def compute_aged_line(self, partner_id, ledger_line, data):
"""Add classification to accounts browse records
contained in :attr:`objects` for a given partner
:param: partner_id: current partner
:param ledger_line: generated by parent
:class:`.open_invoices.PartnersOpenInvoicesWebkit`
:returns: dict of computed aged lines
eg {'balance': 1000.0,
'aged_lines': {(90, 120): 0.0, ...}
"""
end_date = self._get_end_date(data)
reconcile_lookup = self.get_reconcile_count_lookup([ledger_line])
compute_method = self.get_compute_method(reconcile_lookup,
partner_id,
ledger_line)
delay = compute_method(ledger_line, end_date, [ledger_line])
classification = self.classify_line(partner_id, delay)
ledger_line[classification] += ledger_line['balance']
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:`.AccountAgedOpenInvoicesWebkit`
"""
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 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_open_invoices_webkit',
'account.account',
'addons/account_financial_report_webkit/report/templates/\
aged_open_invoices_webkit.mako',
parser=AccountAgedOpenInvoicesWebkit,
)

4
account_financial_report_webkit/report/aged_partner_balance.py

@ -49,9 +49,9 @@ RANGES = make_ranges(120, 30)
def make_ranges_titles():
"""Generates title to be used by mako"""
titles = [_('Due')]
titles = [_('Not Due')]
titles += [_(u'Overdue ≤ %s d.') % x[1] for x in RANGES[1:-1]]
titles.append(_('Older'))
titles.append(_('Overdue > %s d.') % RANGES[-1][0])
return titles
# list of overdue ranges title

21
account_financial_report_webkit/report/report.xml

@ -108,6 +108,27 @@
<field eval="'ir.actions.report.xml,'+str(ref('account_financial_report_webkit.account_report_open_invoices_webkit'))" model="ir.actions.report.xml" name="res_id"/>
</record>
<record id="account_report_aged_open_invoices_webkit" model="ir.actions.report.xml">
<field name="report_type">webkit</field>
<field name="report_name">account.account_aged_open_invoices_webkit</field>
<field eval="[(6,0,[])]" name="groups_id"/>
<field eval="0" name="multi"/>
<field eval="0" name="auto"/>
<field eval="1" name="header"/>
<field name="model">account.account</field>
<field name="type">ir.actions.report.xml</field>
<field name="name">Aged Open Invoices Report</field>
<field name="report_rml">account_financial_report_webkit/report/templates/aged_open_invoices.mako</field>
<field name="report_file">account_financial_report_webkit/report/templates/aged_open_invoices.mako</field>
</record>
<record id="property_account_report_aged_open_invoices_webkit" model="ir.property">
<field name="name">account_report_aged_open_invoices_webkit</field>
<field name="fields_id" ref="report_webkit.field_ir_act_report_xml_webkit_header"/>
<field eval="'ir.header_webkit,'+str(ref('account_financial_report_webkit.financial_landscape_header'))" model="ir.header_webkit" name="value"/>
<field eval="'ir.actions.report.xml,'+str(ref('account_financial_report_webkit.account_report_aged_open_invoices_webkit'))" model="ir.actions.report.xml" name="res_id"/>
</record>
<record id="account_report_aged_trial_blanance_webkit" model="ir.actions.report.xml">
<field name="report_type">webkit</field>
<field name="report_name">account.account_aged_trial_balance_webkit</field>

177
account_financial_report_webkit/report/templates/aged_open_invoices.mako

@ -0,0 +1,177 @@
## -*- coding: utf-8 -*-
<!DOCTYPE html SYSTEM
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
.overflow_ellipsis {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.open_invoice_previous_line {
font-style: italic;
}
.percent_line {
font-style: italic;
}
.amount {
text-align:right;
}
.classif_title {
text-align:right;
}
.classif{
width: ${700/len(ranges)}px;
}
.total{
font-weight:bold;
}
${css}
</style>
</head>
<%!
def amount(text):
# replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers)
return text.replace('-', '&#8209;')
%>
<body>
<%setLang(user.lang)%>
<div class="act_as_table data_table">
<div class="act_as_row labels">
<div class="act_as_cell">${_('Chart of Account')}</div>
<div class="act_as_cell">${_('Fiscal Year')}</div>
<div class="act_as_cell">
%if filter_form(data) == 'filter_date':
${_('Dates Filter')}
%else:
${_('Periods Filter')}
%endif
</div>
<div class="act_as_cell">${_('Clearance Date')}</div>
<div class="act_as_cell">${_('Accounts Filter')}</div>
<div class="act_as_cell">${_('Target Moves')}</div>
</div>
<div class="act_as_row">
<div class="act_as_cell">${ chart_account.name }</div>
<div class="act_as_cell">${ fiscalyear.name if fiscalyear else '-' }</div>
<div class="act_as_cell">
${_('From:')}
%if filter_form(data) == 'filter_date':
${formatLang(start_date, date=True) if start_date else u'' }
%else:
${start_period.name if start_period else u''}
%endif
${_('To:')}
%if filter_form(data) == 'filter_date':
${ formatLang(stop_date, date=True) if stop_date else u'' }
%else:
${stop_period.name if stop_period else u'' }
%endif
</div>
<div class="act_as_cell">${ formatLang(date_until, date=True) }</div>
<div class="act_as_cell">
%if partner_ids:
${_('Custom Filter')}
%else:
${ display_partner_account(data) }
%endif
</div>
<div class="act_as_cell">${ display_target_move(data) }</div>
</div>
</div>
%for account in objects:
%if aged_open_inv[account.id] and partners_order[account.id]:
<div class="account_title bg" style="width: 1080px; margin-top: 20px; font-size: 12px;">${account.code} - ${account.name}</div>
%for partner_name, p_id, p_ref, p_name in partners_order[account.id]:
<div class="act_as_table list_table" style="margin-top: 5px;">
<div class="act_as_caption account_title">
${partner_name or _('No Partner')}
</div>
<div class="act_as_thead">
<div class="act_as_row labels">
## date
<div class="act_as_cell first_column" style="width: 60px;">${_('Date')}</div>
## move
<div class="act_as_cell" style="width: 100px;">${_('Entry')}</div>
## journal
<div class="act_as_cell" style="width: 70px;">${_('Journal')}</div>
## label
<div class="act_as_cell" style="width: 180px;">${_('Label')}</div>
## reconcile
<div class="act_as_cell" style="width: 80px;">${_('Rec.')}</div>
## maturity
<div class="act_as_cell" style="width: 60px;">${_('Due Date')}</div>
## balance
<div class="act_as_cell amount" style="width: 80px;">${_('Amount')}</div>
## Classifications
%for title in ranges_titles:
<div class="act_as_cell classif classif_title">${title}</div>
%endfor
</div>
</div>
<div class="act_as_tbody">
%for line in aged_open_inv[account.id][p_id].get('lines', []):
<div class="act_as_row lines ${line.get('is_from_previous_periods') and 'open_invoice_previous_line' or ''} ${line.get('is_clearance_line') and 'clearance_line' or ''}">
## date
<div class="act_as_cell first_column">${formatLang(line.get('ldate') or '', date=True)}</div>
## move
<div class="act_as_cell">${line.get('move_name') or ''}</div>
## journal
<div class="act_as_cell">${line.get('jcode') or ''}</div>
## label
<div class="act_as_cell">${line.get('lname')}</div>
## reconcile
<div class="act_as_cell">${line.get('rec_name') or ''}</div>
## maturity date
<div class="act_as_cell">${formatLang(line.get('date_maturity') or '', date=True)}</div>
## balance
<div class="act_as_cell amount">${formatLang(line.get('balance') or 0.0) | amount }</div>
## classifications
%for classif in ranges:
<div class="act_as_cell classif amount">
${formatLang(line.get(classif) or 0.0) | amount }
</div>
%endfor
</div>
%endfor # end of the loop on lines
<div class="act_as_row labels">
<div class="act_as_cell total">${_('Total Partner')}</div>
<div class="act_as_cell"></div>
<div class="act_as_cell"></div>
<div class="act_as_cell"></div>
<div class="act_as_cell"></div>
<div class="act_as_cell"></div>
<div class="act_as_cell amount classif total">${formatLang(aged_open_inv[account.id][p_id]['balance']) | amount}</div>
%for classif in ranges:
<div class="act_as_cell amount classif total">${formatLang(aged_open_inv[account.id][p_id][classif]) | amount }</div>
%endfor
</div>
</div>
%endfor # end of the loop on partners
<div class="act_as_row labels">
<div class="act_as_cell total account_title bg">${_('Total')}</div>
<div class="act_as_cell"></div>
<div class="act_as_cell"></div>
<div class="act_as_cell"></div>
<div class="act_as_cell"></div>
<div class="act_as_cell"></div>
<div class="act_as_cell amount classif total account_title bg">${formatLang(aged_open_inv[account.id]['balance']) | amount}</div>
%for classif in ranges:
<div class="act_as_cell amount classif total account_title bg">${formatLang(aged_open_inv[account.id][classif]) | amount }</div>
%endfor
</div>
%endif
%endfor # end of the loop on accounts
</body>
</html>

4
account_financial_report_webkit/report/templates/aged_trial_webkit.mako

@ -100,9 +100,9 @@
## partner
<div class="act_as_cell first_column" style="width: 60px;">${_('Partner')}</div>
## code
<div class="act_as_cell" style="width: 70px;">${_('code')}</div>
<div class="act_as_cell" style="width: 70px;">${_('Code')}</div>
## balance
<div class="act_as_cell classif_title" style="width: 70px;">${_('balance')}</div>
<div class="act_as_cell classif_title" style="width: 70px;">${_('Balance')}</div>
## Classifications
%for title in ranges_titles:
<div class="act_as_cell classif classif_title">${title}</div>

18
account_financial_report_webkit/report_menus.xml

@ -2,31 +2,35 @@
<openerp>
<data>
<menuitem icon="STOCK_PRINT" name="General Ledger"
<menuitem name="General Ledger"
parent="account.final_accounting_reports" action="action_account_general_ledger_menu_webkit"
groups="account.group_account_manager,account.group_account_user" id="account.menu_general_ledger"/>
<menuitem icon="STOCK_PRINT" name="Trial Balance"
<menuitem name="Trial Balance"
parent="account.final_accounting_reports" action="action_account_trial_balance_menu_webkit"
groups="account.group_account_manager,account.group_account_user" id="account.menu_general_Balance_report"/>
<menuitem icon="STOCK_PRINT" name="Partner Ledger"
<menuitem name="Partner Ledger"
parent="account.next_id_22" action="action_account_partners_ledger_menu_webkit"
groups="account.group_account_manager,account.group_account_user" id="account.menu_account_partner_ledger"/>
<menuitem icon="STOCK_PRINT" name="Partner Balance"
<menuitem name="Partner Balance"
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"/>
<menuitem icon="STOCK_PRINT" name="Aged Partner Balance"
<menuitem name="Aged Partner Balance"
parent="account.next_id_22" action="action_account_aged_trial_balance_menu_webkit"
groups="account.group_account_manager,account.group_account_user" id="account.menu_aged_trial_balance"/>
<menuitem icon="STOCK_PRINT" name="Open Invoices"
<menuitem name="Open Invoices"
parent="account.next_id_22" action="action_account_open_invoices_menu_webkit"
groups="account.group_account_manager,account.group_account_user" id="menu_account_open_invoices"/>
<menuitem icon="STOCK_PRINT" name="Journals"
<menuitem name="Aged Open Invoices"
parent="account.next_id_22" action="action_account_aged_open_invoice_menu_webkit"
groups="account.group_account_manager,account.group_account_user" id="menu_account_aged_open_invoices"/>
<menuitem name="Journals"
parent="account.menu_journals_report" action="action_account_print_journal_menu_webkit"
groups="account.group_account_manager,account.group_account_user" id="account.menu_account_print_journal"/>

1
account_financial_report_webkit/wizard/__init__.py

@ -26,5 +26,6 @@ from . import partners_ledger_wizard
from . import trial_balance_wizard
from . import partner_balance_wizard
from . import open_invoices_wizard
from . import aged_open_invoices_wizard
from . import print_journal
from . import aged_partner_balance_wizard

61
account_financial_report_webkit/wizard/aged_open_invoices_wizard.py

@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Author: Alexis de Lattre
# Copyright 2015 Akretion (www.akretion.com)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import orm
class AgedOpenInvoice(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 = "aged.open.invoices.webkit"
_description = "Aged open invoices"
_defaults = {
'filter': 'filter_date',
}
def onchange_fiscalyear(self, cr, uid, ids, fiscalyear=False,
period_id=False, date_to=False, until_date=False,
context=None):
res = super(AgedOpenInvoice, self).onchange_fiscalyear(
cr, uid, ids, fiscalyear=fiscalyear, period_id=period_id,
date_to=date_to, until_date=until_date, context=context
)
filters = self.onchange_filter(cr, uid, ids, filter='filter_period',
fiscalyear_id=fiscalyear,
context=context)
res['value'].update({
'period_from': filters['value']['period_from'],
'period_to': filters['value']['period_to'],
})
return res
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_open_invoices_webkit',
'datas': data}

72
account_financial_report_webkit/wizard/aged_open_invoices_wizard.xml

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="aged_open_invoice_webkit" model="ir.ui.view">
<field name="name">Aged Open Invoice Report</field>
<field name="model">aged.open.invoices.webkit</field>
<field name="inherit_id" ref="account.account_common_report_view"/>
<field name="arch" type="xml">
<data>
<xpath expr="/form/label[@string='']" position="replace">
<separator string="Aged Open Invoice" colspan="4"/>
<label nolabel="1"
colspan="4"
string="This report list partner open invoices and indicate when payment is (or was) supposed to be completed"/>
</xpath>
<field name="chart_account_id" position='attributes'>
<attribute name="colspan">4</attribute>
</field>
<xpath expr="//field[@name='target_move']" position="after">
<newline/>
<field name="result_selection" colspan="4"/>
</xpath>
<xpath expr="/form/notebook[1]" position="after">
<separator string="Clearance Analysis Options" colspan="4"/>
<newline/>
<field name="until_date"/>
</xpath>
<page name="filters" position="after">
<page string="Partners Filters" name="partners">
<separator string="Print only" colspan="4"/>
<field name="partner_ids" colspan="4" nolabel="1"/>
</page>
</page>
<page name="filters" position="attributes">
<attribute name="string">Time Filters</attribute>
</page>
<page name="journal_ids" position="attributes">
<attribute name="invisible">True</attribute>
</page>
<field name="fiscalyear_id" position="attributes">
<attribute name="on_change">onchange_fiscalyear(fiscalyear_id, period_to, date_to, until_date)</attribute>
</field>
<field name="date_to" position="attributes">
<attribute name="on_change">onchange_date_to(fiscalyear_id, period_to, date_to, until_date)</attribute>
</field>
<field name="period_to" position="attributes">
<attribute name="on_change">onchange_period_to(fiscalyear_id, period_to, date_to, until_date)</attribute>
</field>
<field name="period_from" position="attributes">
<attribute name="domain">[('fiscalyear_id', '=', fiscalyear_id), ('special', '=', False)]</attribute>
</field>
<field name="period_to" position="attributes">
<attribute name="domain">[('fiscalyear_id', '=', fiscalyear_id), ('special', '=', False)]</attribute>
</field>
</data>
</field>
</record>
<record id="action_account_aged_open_invoice_menu_webkit"
model="ir.actions.act_window">
<field name="name">Aged Open Invoice</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">aged.open.invoices.webkit</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="aged_open_invoice_webkit"/>
<field name="target">new</field>
</record>
</data>
</openerp>
Loading…
Cancel
Save