Nhomar Hernandez
12 years ago
56 changed files with 11714 additions and 0 deletions
-
23account_financial_report_webkit/__init__.py
-
132account_financial_report_webkit/__openerp__.py
-
45account_financial_report_webkit/account.py
-
89account_financial_report_webkit/account_move_line.py
-
23account_financial_report_webkit/account_move_line_view.xml
-
18account_financial_report_webkit/account_view.xml
-
409account_financial_report_webkit/data/financial_webkit_header.xml
-
1284account_financial_report_webkit/i18n/account_financial_report_webkit.pot
-
1238account_financial_report_webkit/i18n/de.po
-
1160account_financial_report_webkit/i18n/en_US.po
-
1160account_financial_report_webkit/i18n/fr.po
-
BINaccount_financial_report_webkit/images/ledger.png
-
11account_financial_report_webkit/report/__init__.py
-
272account_financial_report_webkit/report/common_balance_reports.py
-
275account_financial_report_webkit/report/common_partner_balance_reports.py
-
328account_financial_report_webkit/report/common_partner_reports.py
-
520account_financial_report_webkit/report/common_reports.py
-
211account_financial_report_webkit/report/general_ledger.py
-
238account_financial_report_webkit/report/open_invoices.py
-
90account_financial_report_webkit/report/partner_balance.py
-
199account_financial_report_webkit/report/partners_ledger.py
-
115account_financial_report_webkit/report/profit_loss.py
-
104account_financial_report_webkit/report/report.xml
-
232account_financial_report_webkit/report/templates/account_report_general_ledger.mako
-
85account_financial_report_webkit/report/templates/account_report_open_invoices.mako
-
290account_financial_report_webkit/report/templates/account_report_partner_balance.mako
-
281account_financial_report_webkit/report/templates/account_report_partners_ledger.mako
-
210account_financial_report_webkit/report/templates/account_report_profit_loss.mako
-
217account_financial_report_webkit/report/templates/account_report_trial_balance.mako
-
166account_financial_report_webkit/report/templates/grouped_by_curr_open_invoices_inclusion.mako.html
-
176account_financial_report_webkit/report/templates/open_invoices_inclusion.mako.html
-
82account_financial_report_webkit/report/trial_balance.py
-
235account_financial_report_webkit/report/webkit_parser_header_fix.py
-
26account_financial_report_webkit/report_menus.xml
-
3account_financial_report_webkit/tests/account_move_line.yml
-
65account_financial_report_webkit/tests/general_ledger.yml
-
60account_financial_report_webkit/tests/open_invoices.yml
-
67account_financial_report_webkit/tests/partner_balance.yml
-
60account_financial_report_webkit/tests/partner_ledger.yml
-
67account_financial_report_webkit/tests/trial_balance.yml
-
27account_financial_report_webkit/wizard/__init__.py
-
295account_financial_report_webkit/wizard/balance_common.py
-
11account_financial_report_webkit/wizard/balance_common_view.xml
-
132account_financial_report_webkit/wizard/general_ledger_wizard.py
-
89account_financial_report_webkit/wizard/general_ledger_wizard_view.xml
-
126account_financial_report_webkit/wizard/open_invoices_wizard.py
-
73account_financial_report_webkit/wizard/open_invoices_wizard_view.xml
-
64account_financial_report_webkit/wizard/partner_balance_wizard.py
-
85account_financial_report_webkit/wizard/partner_balance_wizard_view.xml
-
116account_financial_report_webkit/wizard/partners_ledger_wizard.py
-
69account_financial_report_webkit/wizard/partners_ledger_wizard_view.xml
-
166account_financial_report_webkit/wizard/profit_loss_wizard.py
-
72account_financial_report_webkit/wizard/profit_loss_wizard_view.xml
-
41account_financial_report_webkit/wizard/trial_balance_wizard.py
-
78account_financial_report_webkit/wizard/trial_balance_wizard_view.xml
-
4account_financial_report_webkit/wizard/wizard.xml
@ -0,0 +1,23 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi. Copyright 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/>. |
|||
# |
|||
############################################################################## |
|||
import account |
|||
from . import wizard |
|||
from . import report |
|||
from . import account_move_line |
@ -0,0 +1,132 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Authors: Nicolas Bessi, Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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/>. |
|||
# |
|||
############################################################################## |
|||
# TODO refactor helper in order to act more like mixin |
|||
# By using properties we will have a more simple signature in fuctions |
|||
{ |
|||
'name': 'Webkit based extended report financial report', |
|||
'description': """ |
|||
This module replace the following standard openerp financial reports : |
|||
- General ledger |
|||
- Trial Balance (simple or comparative view) |
|||
- Partner ledger |
|||
- Partner balance |
|||
- Open invoices report |
|||
|
|||
|
|||
Main improvements per report: |
|||
|
|||
* The General ledger: details of all entries posted in your books sorted by account. |
|||
- Filter by account in the wizard (no need to go to the Chart of account to do this anymore) |
|||
or by view account (the report will display all regular children account) ie: you can select all P&L accounts. |
|||
- The report will now print only account with movements OR with a balance not null. No more endless |
|||
report with accounts with no data. (field: display account is hidden) |
|||
- initial balance calculation on the fly if no open entry posted |
|||
- Thanks to a new checkbox in account form, you will have possibility to centralize any accounts you like. |
|||
Ie: you do not want to see all entries posted under the account ‘VAT on sales’; you will only see aggregated amounts by periods. |
|||
- Counterpart account displayed for each transaction (3 accounts max.) to ease searching. |
|||
- Better ergonomy on the wizard: important information at the top, filters in the middle, options |
|||
at the bottom or separate tab, more specific filtering on a other tabs. No more unique wizard layout |
|||
for all financial reports (ie: we have removed the journal tab for the GL report) |
|||
- improved report style |
|||
|
|||
* The partner ledger: details of entries relative to payable & receivable accounts posted in your books sorted by account and partner. |
|||
- Filter by partner now possible |
|||
- Now you can see accounts then Partner with subtotals for each account allowing you to check you data |
|||
with trial balance and partner balance for instance & accounts are ordered the same way than in the Chart of account |
|||
- period have been added (date only is uncompleted since date can be outside period) |
|||
- Reconciliation code added |
|||
- subtotal by account |
|||
- alpha sorting (same in partner balance) |
|||
|
|||
* Open invoice report : other version of the partner ledger showing unreconciled / partially reconcies entries |
|||
(added on the 20/01/2012) |
|||
- Possibility to print unreconciled transactions only at any date in the past (thanks to the brand-new field: |
|||
last_rec_date which calculated the last move line reconciled date). No more pain to get open invoices at the last closing date. |
|||
- no initial balance calculated because the report shows open invoices from previous years. |
|||
|
|||
* The Trial balance: list of account with balances |
|||
- you can either see the column : Initial balance , debit, credit , end balance or compare balances over 4 periods of your choice |
|||
- You can select the filter opening to get the opening trial balance only |
|||
- If you create a extra virtual charts (using consolidated account) of account for your P&L and your balance sheet, |
|||
you can print your statutory accounts (with comparision over years for ex.) |
|||
- If you compare 2 periods, you will get differences in value and % also |
|||
|
|||
* The Partner balance: list of account with balances |
|||
- subtotal by account & partner |
|||
- alpha sorting (same in partner balance) |
|||
|
|||
Limitations: |
|||
In order to run properly this module make sure you have installed the librairie ‘wkhtmltopdf’ |
|||
for the pdf rendering (this library path must be added to you company settings). |
|||
|
|||
Initial balances in these reports are based either on opening entry |
|||
posted in the opening period or calculated on the fly. So make sure, |
|||
your past accounting opening entries are in a opening period. |
|||
Initials balances are not calculated when using date filter (since a |
|||
date can be outside its logical period and IB could be different by |
|||
date Vs IB by period) The opening period is assumed to be the 01.01 of |
|||
the year with an opening flag and the first period of the year must |
|||
starts also the 01.01 |
|||
|
|||
Totals for amount in currencies are affective if the partner belong to |
|||
an account with a secondary currency. |
|||
|
|||
html headers and footers are deactivated for these reports because of |
|||
an issue of wkhtmltopdf : |
|||
http://code.google.com/p/wkhtmltopdf/issues/detail?id=656 Instead, the |
|||
header and footer are created as text with arguments passed to |
|||
wkhtmltopdf. The texts are defined inside the report classes. |
|||
|
|||
""", |
|||
'version': '1.0', |
|||
'author': 'Camptocamp', |
|||
'category': 'Finance', |
|||
'website': 'http://www.camptocamp.com', |
|||
'images': [ |
|||
'images/ledger.png',], |
|||
'depends': ['account', |
|||
'report_webkit'], |
|||
'init_xml': [], |
|||
'demo_xml' : [], |
|||
'update_xml': ['account_view.xml', |
|||
'account_move_line_view.xml', |
|||
'data/financial_webkit_header.xml', |
|||
'report/report.xml', |
|||
'wizard/wizard.xml', |
|||
'wizard/balance_common_view.xml', |
|||
'wizard/general_ledger_wizard_view.xml', |
|||
'wizard/partners_ledger_wizard_view.xml', |
|||
'wizard/trial_balance_wizard_view.xml', |
|||
'wizard/partner_balance_wizard_view.xml', |
|||
'wizard/open_invoices_wizard_view.xml', |
|||
'report_menus.xml', |
|||
# 'wizard/profit_loss_wizard_view.xml', |
|||
], |
|||
# tests order matter |
|||
'test': ['tests/general_ledger.yml', |
|||
'tests/partner_ledger.yml', |
|||
'tests/trial_balance.yml', |
|||
'tests/partner_balance.yml', |
|||
'tests/open_invoices.yml',], |
|||
#'tests/account_move_line.yml' |
|||
'active': False, |
|||
'installable': True, |
|||
} |
@ -0,0 +1,45 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
|||
# |
|||
# Author : Guewen Baconnier (Camptocamp) |
|||
# |
|||
# WARNING: This program as such is intended to be used by professional |
|||
# programmers who take the whole responsability of assessing all potential |
|||
# consequences resulting from its eventual inadequacies and bugs |
|||
# End users who are looking for a ready-to-use solution with commercial |
|||
# garantees and support are strongly adviced to contract a Free Software |
|||
# Service Company |
|||
# |
|||
# This program is Free Software; you can redistribute it and/or |
|||
# modify it under the terms of the GNU General Public License |
|||
# as published by the Free Software Foundation; either version 2 |
|||
# 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 General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License |
|||
# along with this program; if not, write to the Free Software |
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|||
# |
|||
############################################################################## |
|||
|
|||
from osv import osv, fields |
|||
|
|||
|
|||
class AccountAccount(osv.osv): |
|||
_inherit = 'account.account' |
|||
|
|||
_columns = { |
|||
'centralized': fields.boolean('Centralized', help="If flagged, no details will be displayed in the General Ledger report (the webkit one only), only centralized amounts per period.") |
|||
} |
|||
|
|||
_defaults = { |
|||
'centralized': False, |
|||
} |
|||
|
|||
AccountAccount() |
@ -0,0 +1,89 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi. |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU 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 General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from osv import fields, osv |
|||
from tools.translate import _ |
|||
|
|||
|
|||
class AccountMoveLine(osv.osv): |
|||
"""Overriding Account move line in order to add last_rec_date. |
|||
Last rec date is the date of the last reconciliation (full or partial) account move line""" |
|||
_inherit = 'account.move.line' |
|||
|
|||
def init(self, cr): |
|||
##We do not want to catch error as if sql is not run it will give invalid data |
|||
cr.execute("UPDATE account_move_line as acm " |
|||
" SET last_rec_date =" |
|||
" (SELECT date from account_move_line" |
|||
" WHERE reconcile_id = acm.reconcile_id" |
|||
" AND reconcile_id IS NOT NULL" |
|||
" ORDER BY date DESC LIMIT 1)" |
|||
" WHERE last_rec_date is null;") |
|||
|
|||
cr.execute("UPDATE account_move_line as acm " |
|||
" SET last_rec_date =" |
|||
" (SELECT date from account_move_line" |
|||
" WHERE reconcile_partial_id = acm.reconcile_partial_id" |
|||
" AND reconcile_partial_id IS NOT NULL" |
|||
" ORDER BY date DESC LIMIT 1)" |
|||
" WHERE last_rec_date is null;") |
|||
|
|||
|
|||
def _get_move_line_from_line_rec(self, cr, uid, ids, context=None): |
|||
moves = [] |
|||
for reconcile in self.pool.get('account.move.reconcile').browse(cr, uid, ids, context=context): |
|||
for move_line in reconcile.line_partial_ids: |
|||
moves.append(move_line.id) |
|||
for move_line in reconcile.line_id: |
|||
moves.append(move_line.id) |
|||
return list(set(moves)) |
|||
|
|||
def _get_last_rec_date(self, cursor, uid, ids, name, args, context=None): |
|||
if not isinstance(ids, list): |
|||
ids = [ids] |
|||
res = {} |
|||
for line in self.browse(cursor, uid, ids, context): |
|||
res[line.id] = {'last_rec_date': False} |
|||
rec = line.reconcile_id or line.reconcile_partial_id or False |
|||
if rec: |
|||
# we use cursor in order to gain some perfs |
|||
cursor.execute('SELECT date from account_move_line where' |
|||
' reconcile_id = %s OR reconcile_partial_id = %s' |
|||
' ORDER BY date DESC LIMIT 1 ', |
|||
(rec.id, rec.id)) |
|||
res_set = cursor.fetchone() |
|||
if res_set: |
|||
res[line.id] = {'last_rec_date': res_set[0]} |
|||
return res |
|||
|
|||
_columns = { |
|||
'last_rec_date': fields.function(_get_last_rec_date, |
|||
method=True, |
|||
string='Last reconciliation date', |
|||
store={'account.move.line': (lambda self, cr, uid, ids, c={}: ids, ['date'], 20), |
|||
'account.move.reconcile': (_get_move_line_from_line_rec, None ,20)}, |
|||
type='date', |
|||
multi='all', |
|||
help="the date of the last reconciliation (full or partial) account move line"), |
|||
|
|||
} |
|||
|
|||
AccountMoveLine() |
@ -0,0 +1,23 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record model="ir.ui.view" id="last_rec_date_form"> |
|||
<!-- must be unique in this module. --> |
|||
<field name="name">last_rec_date_form</field> |
|||
<field name="model">account.move.line</field> |
|||
<!--parent python entity --> |
|||
<field name="inherit_id" ref="account.view_move_line_form"/> |
|||
<!-- modulename.view --> |
|||
<field name="type">form</field> |
|||
<field name="arch" type="xml"> |
|||
<separator string="Internal Note" colspan="4" position="before"> |
|||
<separator string="Misc."/> |
|||
<newline/> |
|||
<group> |
|||
<field name="last_rec_date" readonly="1"/> |
|||
</group> |
|||
</separator> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<record id="view_account_form_webkit" model="ir.ui.view"> |
|||
<field name="name">account.account.form.webkit</field> |
|||
<field name="model">account.account</field> |
|||
<field name="inherit_id" ref="account.view_account_form"/> |
|||
<field name="type">form</field> |
|||
<field name="arch" type="xml"> |
|||
<data> |
|||
<field name="active" position="after"> |
|||
<field name="centralized" groups="base.group_extended"/> |
|||
</field> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,409 @@ |
|||
<?xml version="1.0" ?> |
|||
<openerp> |
|||
<data noupdate="1"> |
|||
<record id="financial_landscape_header" model="ir.header_webkit"> |
|||
<field name="footer_html"><![CDATA[ |
|||
<html> |
|||
<head> |
|||
<meta content="text/html; charset=UTF-8" http-equiv="content-type"/> |
|||
<script> |
|||
function subst() { |
|||
var vars={}; |
|||
var x=document.location.search.substring(1).split('&'); |
|||
for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);} |
|||
var x=['frompage','topage','page','webpage','section','subsection','subsubsection']; |
|||
for(var i in x) { |
|||
var y = document.getElementsByClassName(x[i]); |
|||
for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]]; |
|||
} |
|||
} |
|||
</script> |
|||
</head> |
|||
<% import datetime %> |
|||
<body style="border:0; margin: 0;" onload="subst()"> |
|||
<table style="border-top: 1px solid black; width: 1080px"> |
|||
<tr style="border-collapse:collapse;"> |
|||
<td style="text-align:left;font-size:10;width:350px;">${formatLang( str(datetime.datetime.today()), date_time=True)}</td> |
|||
<td style="text-align:center;font-size:10;width:350px;">${user.name}</td> |
|||
<td style="text-align:right;font-size:10;width:350px;">Page <span class="page"/></td> |
|||
<td style="text-align:left;font-size:10;width:30px"> of <span class="topage"/></td> |
|||
</tr> |
|||
</table> |
|||
</body> |
|||
</html>]]></field> |
|||
<field name="orientation">Landscape</field> |
|||
<field name="format">A4</field> |
|||
<field name="html"><![CDATA[ |
|||
<html> |
|||
<head> |
|||
<meta content="text/html; charset=UTF-8" http-equiv="content-type"/> |
|||
<script> |
|||
function subst() { |
|||
var vars={}; |
|||
var x=document.location.search.substring(1).split('&'); |
|||
for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);} |
|||
var x=['frompage','topage','page','webpage','section','subsection','subsubsection']; |
|||
for(var i in x) { |
|||
var y = document.getElementsByClassName(x[i]); |
|||
for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]]; |
|||
} |
|||
} |
|||
</script> |
|||
<style type="text/css"> |
|||
${css} |
|||
</style> |
|||
</head> |
|||
<body style="border:0; margin: 0;" onload="subst()"> |
|||
<table class="header" style="border-bottom: 0px solid black; width: 100%"> |
|||
<tr> |
|||
<td style="text-align:left; font-size:11px; font-weight: bold;"><span style="text-transform:uppercase; font-size:12px;">${report_name}</span> - ${company.partner_id.name | entity} - ${company.currency_id.name | entity}</td> |
|||
</tr> |
|||
</table> ${_debug or ''|n} </body> |
|||
</html>]]> |
|||
</field> |
|||
<field eval="0.0" name="margin_top"/> |
|||
<field name="css"><![CDATA[ |
|||
|
|||
body, table, td, span, div { |
|||
font-family: Helvetica, Arial; |
|||
} |
|||
|
|||
.act_as_table { |
|||
display: table; |
|||
} |
|||
.act_as_row { |
|||
display: table-row; |
|||
} |
|||
.act_as_cell { |
|||
display: table-cell; |
|||
} |
|||
.act_as_thead { |
|||
display: table-header-group; |
|||
} |
|||
.act_as_tbody { |
|||
display: table-row-group; |
|||
} |
|||
.act_as_tfoot { |
|||
display: table-footer-group; |
|||
} |
|||
.act_as_caption { |
|||
display: table-caption; |
|||
} |
|||
act_as_colgroup { |
|||
display: table-column-group; |
|||
} |
|||
|
|||
.list_table, .data_table { |
|||
width: 1080px; |
|||
table-layout: fixed |
|||
} |
|||
|
|||
.bg, .act_as_row.labels { |
|||
background-color:#F0F0F0; |
|||
} |
|||
|
|||
.list_table, .data_table, .list_table .act_as_row { |
|||
border-left:0px; |
|||
border-right:0px; |
|||
text-align:left; |
|||
font-size:9px; |
|||
padding-right:3px; |
|||
padding-left:3px; |
|||
padding-top:2px; |
|||
padding-bottom:2px; |
|||
border-collapse:collapse; |
|||
} |
|||
|
|||
.list_table .act_as_row.labels, .list_table .act_as_row.initial_balance, .list_table .act_as_row.lines { |
|||
border-color:gray; |
|||
border-bottom:1px solid lightGrey; |
|||
} |
|||
|
|||
.data_table .act_as_cell { |
|||
border: 1px solid lightGrey; |
|||
text-align: center; |
|||
} |
|||
|
|||
.data_table .act_as_cell, .list_table .act_as_cell { |
|||
word-wrap: break-word; |
|||
} |
|||
|
|||
.data_table .act_as_row.labels { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.initial_balance .act_as_cell { |
|||
font-style:italic; |
|||
} |
|||
|
|||
.account_title { |
|||
font-size:10px; |
|||
font-weight:bold; |
|||
page-break-after: avoid; |
|||
} |
|||
|
|||
.act_as_cell.amount { |
|||
word-wrap:normal; |
|||
text-align:right; |
|||
} |
|||
|
|||
.list_table .act_as_cell{ |
|||
padding-left: 5px; |
|||
/* border-right:1px solid lightGrey; uncomment to active column lines */ |
|||
} |
|||
.list_table .act_as_cell.first_column { |
|||
padding-left: 0px; |
|||
/* border-left:1px solid lightGrey; uncomment to active column lines */ |
|||
} |
|||
|
|||
.sep_left { |
|||
border-left: 1px solid lightGrey; |
|||
} |
|||
|
|||
.overflow_ellipsis { |
|||
text-overflow: ellipsis; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
.open_invoice_previous_line { |
|||
font-style: italic; |
|||
} |
|||
|
|||
.clearance_line { |
|||
font-style: italic; |
|||
} |
|||
|
|||
]]> |
|||
</field> |
|||
<field name="name">Financial Landscape Header</field> |
|||
</record> |
|||
|
|||
<record id="financial_portrait_header" model="ir.header_webkit"> |
|||
<field name="footer_html"><![CDATA[ |
|||
<html> |
|||
<head> |
|||
<meta content="text/html; charset=UTF-8" http-equiv="content-type"/> |
|||
<script> |
|||
function subst() { |
|||
var vars={}; |
|||
var x=document.location.search.substring(1).split('&'); |
|||
for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);} |
|||
var x=['frompage','topage','page','webpage','section','subsection','subsubsection']; |
|||
for(var i in x) { |
|||
var y = document.getElementsByClassName(x[i]); |
|||
for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]]; |
|||
} |
|||
} |
|||
</script> |
|||
</head> |
|||
<% import datetime %> |
|||
<body style="border:0; margin: 0;" onload="subst()"> |
|||
<table style="border-top: 1px solid black; width: 1080px"> |
|||
<tr style="border-collapse:collapse;"> |
|||
<td style="text-align:left;font-size:10;width:350px;">${formatLang( str(datetime.datetime.today()), date_time=True)}</td> |
|||
<td style="text-align:center;font-size:10;width:350px;">${user.name}</td> |
|||
<td style="text-align:right;font-size:10;width:350px;">Page <span class="page"/></td> |
|||
<td style="text-align:left;font-size:10;width:30px"> of <span class="topage"/></td> |
|||
</tr> |
|||
</table> |
|||
</body> |
|||
</html>]]></field> |
|||
<field name="orientation">Portrait</field> |
|||
<field name="format">A4</field> |
|||
<field name="html"><![CDATA[ |
|||
<html> |
|||
<head> |
|||
<meta content="text/html; charset=UTF-8" http-equiv="content-type"/> |
|||
<script> |
|||
function subst() { |
|||
var vars={}; |
|||
var x=document.location.search.substring(1).split('&'); |
|||
for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);} |
|||
var x=['frompage','topage','page','webpage','section','subsection','subsubsection']; |
|||
for(var i in x) { |
|||
var y = document.getElementsByClassName(x[i]); |
|||
for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]]; |
|||
} |
|||
} |
|||
</script> |
|||
<style type="text/css"> |
|||
${css} |
|||
</style> |
|||
</head> |
|||
<body style="border:0; margin: 0;" onload="subst()"> |
|||
<table class="header" style="border-bottom: 0px solid black; width: 100%"> |
|||
<tr> |
|||
<td style="text-align:left; font-size:11px; font-weight: bold;"><span style="text-transform:uppercase; font-size:12px;">${report_name}</span> - ${company.partner_id.name | entity} - ${company.currency_id.name | entity}</td> |
|||
</tr> |
|||
</table> ${_debug or ''|n} </body> |
|||
</html>]]> |
|||
</field> |
|||
<field eval="17.0" name="margin_top"/> |
|||
<field eval="15.0" name="margin_bottom"/> |
|||
<field name="css"><![CDATA[ |
|||
|
|||
body, table, td, span, div { |
|||
font-family: Helvetica, Arial; |
|||
} |
|||
|
|||
.act_as_table { |
|||
display: table; |
|||
} |
|||
.act_as_row { |
|||
display: table-row; |
|||
} |
|||
.act_as_cell { |
|||
display: table-cell; |
|||
} |
|||
.act_as_thead { |
|||
display: table-header-group; |
|||
} |
|||
.act_as_tbody { |
|||
display: table-row-group; |
|||
} |
|||
.act_as_tfoot { |
|||
display: table-footer-group; |
|||
} |
|||
.act_as_caption { |
|||
display: table-caption; |
|||
} |
|||
act_as_colgroup { |
|||
display: table-column-group; |
|||
} |
|||
|
|||
.list_table, .data_table { |
|||
width: 690px; |
|||
table-layout: fixed |
|||
} |
|||
|
|||
.bg, .act_as_row.labels { |
|||
background-color:#F0F0F0; |
|||
} |
|||
|
|||
.list_table, .data_table, .list_table .act_as_row { |
|||
border-left:0px; |
|||
border-right:0px; |
|||
text-align:left; |
|||
font-size:9px; |
|||
padding-right:3px; |
|||
padding-left:3px; |
|||
padding-top:2px; |
|||
padding-bottom:2px; |
|||
border-collapse:collapse; |
|||
} |
|||
|
|||
.list_table .act_as_row.labels, .list_table .act_as_row.initial_balance, .list_table .act_as_row.lines { |
|||
border-color:gray; |
|||
border-bottom:1px solid lightGrey; |
|||
} |
|||
|
|||
.data_table .act_as_cell { |
|||
border: 1px solid lightGrey; |
|||
text-align: center; |
|||
} |
|||
|
|||
.data_table .act_as_cell, .list_table .act_as_cell { |
|||
word-wrap: break-word; |
|||
} |
|||
|
|||
.data_table .act_as_row.labels { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.initial_balance .act_as_cell { |
|||
font-style:italic; |
|||
} |
|||
|
|||
.account_title { |
|||
font-size:10px; |
|||
font-weight:bold; |
|||
page-break-after: avoid; |
|||
} |
|||
|
|||
.act_as_cell.amount { |
|||
word-wrap:normal; |
|||
text-align:right; |
|||
} |
|||
|
|||
.list_table .act_as_cell{ |
|||
padding-left: 5px; |
|||
/* border-right:1px solid lightGrey; uncomment to active column lines */ |
|||
} |
|||
.list_table .act_as_cell.first_column { |
|||
padding-left: 0px; |
|||
/* border-left:1px solid lightGrey; uncomment to active column lines */ |
|||
} |
|||
|
|||
.sep_left { |
|||
border-left: 1px solid lightGrey; |
|||
} |
|||
|
|||
.account_level_1 { |
|||
text-transform: uppercase; |
|||
/*font-weight: bold;*/ |
|||
font-size: 15px; |
|||
background-color:#F0F0F0; |
|||
} |
|||
|
|||
/* |
|||
.account_level_1 .act_as_cell { |
|||
height: 30px; |
|||
vertical-align: bottom; |
|||
} |
|||
*/ |
|||
|
|||
.account_level_2 { |
|||
/*text-transform: uppercase; |
|||
font-weight: bold;*/ |
|||
font-size: 12px; |
|||
background-color:#F0F0F0; |
|||
} |
|||
|
|||
/* |
|||
.account_level_2 .act_as_cell { |
|||
height: 20px; |
|||
vertical-align: bottom; |
|||
} |
|||
|
|||
.account_level_3 { |
|||
text-transform: uppercase; |
|||
font-weight: bold; |
|||
font-size: 11px; |
|||
background-color:#FAFAFA; |
|||
} |
|||
|
|||
.account_level_4 { |
|||
font-weight: bold; |
|||
font-size: 11px; |
|||
} |
|||
*/ |
|||
|
|||
.account_level_5 { |
|||
|
|||
} |
|||
|
|||
.regular_account_type { |
|||
font-weight: normal; |
|||
} |
|||
|
|||
.view_account_type { |
|||
font-weight: bold; |
|||
|
|||
.account_level_consol { |
|||
font-weight: normal; |
|||
font-style: italic; |
|||
} |
|||
|
|||
.overflow_ellipsis { |
|||
text-overflow: ellipsis; |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
} |
|||
|
|||
]]> |
|||
</field> |
|||
<field name="name">Financial Portrait Header</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
1284
account_financial_report_webkit/i18n/account_financial_report_webkit.pot
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1238
account_financial_report_webkit/i18n/de.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1160
account_financial_report_webkit/i18n/en_US.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1160
account_financial_report_webkit/i18n/fr.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
After Width: 1553 | Height: 271 | Size: 54 KiB |
@ -0,0 +1,11 @@ |
|||
from . import common_reports |
|||
from . import common_partner_reports |
|||
from . import common_balance_reports |
|||
from . import common_partner_balance_reports |
|||
from . import general_ledger |
|||
from . import partners_ledger |
|||
from . import webkit_parser_header_fix |
|||
from . import trial_balance |
|||
from . import partner_balance |
|||
from . import open_invoices |
|||
#from . import account_report_profit_loss |
@ -0,0 +1,272 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# SQL inspired from OpenERP original code |
|||
# |
|||
# 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 operator import add |
|||
|
|||
from common_reports import CommonReportHeaderWebkit |
|||
|
|||
|
|||
class CommonBalanceReportHeaderWebkit(CommonReportHeaderWebkit): |
|||
"""Define common helper for balance (trial balance, P&L, BS oriented financial report""" |
|||
|
|||
def _get_numbers_display(self, data): |
|||
return self._get_form_param('numbers_display', data) |
|||
|
|||
@staticmethod |
|||
def find_key_by_value_in_list(dic, value): |
|||
return [key for key, val in dic.iteritems() if value in val][0] |
|||
|
|||
def _get_account_details(self, account_ids, target_move, fiscalyear, main_filter, start, stop, initial_balance_mode, context=None): |
|||
""" |
|||
Get details of accounts to display on the report |
|||
@param account_ids: ids of accounts to get details |
|||
@param target_move: selection filter for moves (all or posted) |
|||
@param fiscalyear: browse of the fiscalyear |
|||
@param main_filter: selection filter period / date or none |
|||
@param start: start date or start period browse instance |
|||
@param stop: stop date or stop period browse instance |
|||
@param initial_balance_mode: False: no calculation, 'opening_balance': from the opening period, 'initial_balance': computed from previous year / periods |
|||
@return: dict of list containing accounts details, keys are the account ids |
|||
""" |
|||
if context is None: |
|||
context = {} |
|||
|
|||
account_obj = self.pool.get('account.account') |
|||
period_obj = self.pool.get('account.period') |
|||
use_period_ids = main_filter in ('filter_no', 'filter_period', 'filter_opening') |
|||
|
|||
if use_period_ids: |
|||
if main_filter == 'filter_opening': |
|||
period_ids = [start.id] |
|||
else: |
|||
period_ids = period_obj.build_ctx_periods(self.cursor, self.uid, start.id, stop.id) |
|||
# never include the opening in the debit / credit amounts |
|||
period_ids = self.exclude_opening_periods(period_ids) |
|||
|
|||
init_balance = False |
|||
if initial_balance_mode == 'opening_balance': |
|||
init_balance = self._read_opening_balance(account_ids, start) |
|||
elif initial_balance_mode: |
|||
init_balance = self._compute_initial_balances(account_ids, start, fiscalyear) |
|||
|
|||
ctx = context.copy() |
|||
ctx.update({'state': target_move, |
|||
'all_fiscalyear': True}) |
|||
|
|||
if use_period_ids: |
|||
ctx.update({'periods': period_ids,}) |
|||
elif main_filter == 'filter_date': |
|||
ctx.update({'date_from': start, |
|||
'date_to': stop}) |
|||
|
|||
accounts = account_obj.read(self.cursor, self.uid, account_ids, ['type','code','name','debit','credit', 'balance', 'parent_id','level','child_id'], ctx) |
|||
|
|||
accounts_by_id = {} |
|||
for account in accounts: |
|||
if init_balance: |
|||
# sum for top level views accounts |
|||
child_ids = account_obj._get_children_and_consol(self.cursor, self.uid, account['id'], ctx) |
|||
if child_ids: |
|||
child_init_balances = [init_bal['init_balance'] for acnt_id, init_bal in init_balance.iteritems() if acnt_id in child_ids ] |
|||
top_init_balance = reduce(add, child_init_balances) |
|||
account['init_balance'] = top_init_balance |
|||
else: |
|||
account.update(init_balance[account['id']]) |
|||
account['balance'] = account['init_balance'] + account['debit'] - account['credit'] |
|||
accounts_by_id[account['id']] = account |
|||
return accounts_by_id |
|||
|
|||
def _get_comparison_details(self, data, account_ids, target_move, comparison_filter, index): |
|||
""" |
|||
|
|||
@param data: data of the wizard form |
|||
@param account_ids: ids of the accounts to get details |
|||
@param comparison_filter: selected filter on the form for the comparison (filter_no, filter_year, filter_period, filter_date) |
|||
@param index: index of the fields to get (ie. comp1_fiscalyear_id where 1 is the index) |
|||
@return: dict of account details (key = account id) |
|||
""" |
|||
fiscalyear = self._get_info(data, "comp%s_fiscalyear_id" % (index,), 'account.fiscalyear') |
|||
start_period = self._get_info(data, "comp%s_period_from" % (index,), 'account.period') |
|||
stop_period = self._get_info(data, "comp%s_period_to" % (index,), 'account.period') |
|||
start_date = self._get_form_param("comp%s_date_from" % (index,), data) |
|||
stop_date = self._get_form_param("comp%s_date_to" % (index,), data) |
|||
init_balance = self.is_initial_balance_enabled(comparison_filter) |
|||
|
|||
accounts_by_ids = {} |
|||
comp_params = {} |
|||
details_filter = comparison_filter |
|||
if comparison_filter != 'filter_no': |
|||
start_period, stop_period, start, stop = \ |
|||
self._get_start_stop_for_filter(comparison_filter, fiscalyear, start_date, stop_date, start_period, stop_period) |
|||
if comparison_filter == 'filter_year': |
|||
details_filter = 'filter_no' |
|||
|
|||
initial_balance_mode = init_balance and self._get_initial_balance_mode(start) or False |
|||
accounts_by_ids = self._get_account_details(account_ids, target_move, fiscalyear, details_filter, |
|||
start, stop, initial_balance_mode) |
|||
comp_params = { |
|||
'comparison_filter': comparison_filter, |
|||
'fiscalyear': fiscalyear, |
|||
'start': start, |
|||
'stop': stop, |
|||
'initial_balance': init_balance, |
|||
'initial_balance_mode': initial_balance_mode, |
|||
} |
|||
|
|||
return accounts_by_ids, comp_params |
|||
|
|||
def _get_diff(self, balance, previous_balance): |
|||
""" |
|||
@param balance: current balance |
|||
@param previous_balance: last balance |
|||
@return: dict of form {'diff': difference, 'percent_diff': diff in percentage} |
|||
""" |
|||
diff = balance - previous_balance |
|||
|
|||
obj_precision = self.pool.get('decimal.precision') |
|||
precision = obj_precision.precision_get(self.cursor, self.uid, 'Account') |
|||
# round previous balance with account precision to avoid big numbers if previous |
|||
# balance is 0.0000001 or a any very small number |
|||
if round(previous_balance, precision) == 0: |
|||
percent_diff = False |
|||
else: |
|||
percent_diff = round(diff / previous_balance * 100, precision) |
|||
|
|||
return {'diff': diff, 'percent_diff': percent_diff} |
|||
|
|||
def _comp_filters(self, data, comparison_number): |
|||
""" |
|||
@param data: data of the report |
|||
@param comparison_number: number of comparisons |
|||
@return: list of comparison filters, nb of comparisons used and comparison mode (no_comparison, single, multiple) |
|||
""" |
|||
comp_filters = [] |
|||
for index in range(comparison_number): |
|||
comp_filters.append(self._get_form_param("comp%s_filter" % (index,), data, default='filter_no')) |
|||
|
|||
nb_comparisons = len([comp_filter for comp_filter in comp_filters if comp_filter != 'filter_no']) |
|||
if not nb_comparisons: |
|||
comparison_mode = 'no_comparison' |
|||
elif nb_comparisons > 1: |
|||
comparison_mode = 'multiple' |
|||
else: |
|||
comparison_mode = 'single' |
|||
return comp_filters, nb_comparisons, comparison_mode |
|||
|
|||
def _get_start_stop_for_filter(self, main_filter, fiscalyear, start_date, stop_date, start_period, stop_period): |
|||
if main_filter in ('filter_no', 'filter_year'): |
|||
start_period = self.get_first_fiscalyear_period(fiscalyear) |
|||
stop_period = self.get_last_fiscalyear_period(fiscalyear) |
|||
elif main_filter == 'filter_opening': |
|||
opening_period = self._get_st_fiscalyear_period(fiscalyear, special=True) |
|||
start_period = stop_period = opening_period |
|||
if main_filter == 'filter_date': |
|||
start = start_date |
|||
stop = stop_date |
|||
else: |
|||
start = start_period |
|||
stop = stop_period |
|||
|
|||
return start_period, stop_period, start, stop |
|||
|
|||
def compute_balance_data(self, data, filter_report_type=None): |
|||
new_ids = data['form']['account_ids'] or data['form']['chart_account_id'] |
|||
max_comparison = self._get_form_param('max_comparison', data, default=0) |
|||
main_filter = self._get_form_param('filter', data, default='filter_no') |
|||
|
|||
comp_filters, nb_comparisons, comparison_mode = self._comp_filters(data, max_comparison) |
|||
|
|||
fiscalyear = self.get_fiscalyear_br(data) |
|||
|
|||
start_period = self.get_start_period_br(data) |
|||
stop_period = self.get_end_period_br(data) |
|||
|
|||
target_move = self._get_form_param('target_move', data, default='all') |
|||
start_date = self._get_form_param('date_from', data) |
|||
stop_date = self._get_form_param('date_to', data) |
|||
chart_account = self._get_chart_account_id_br(data) |
|||
|
|||
start_period, stop_period, start, stop = \ |
|||
self._get_start_stop_for_filter(main_filter, fiscalyear, start_date, stop_date, start_period, stop_period) |
|||
|
|||
init_balance = self.is_initial_balance_enabled(main_filter) |
|||
initial_balance_mode = init_balance and self._get_initial_balance_mode(start) or False |
|||
|
|||
# Retrieving accounts |
|||
account_ids = self.get_all_accounts(new_ids, only_type=filter_report_type) |
|||
|
|||
# get details for each accounts, total of debit / credit / balance |
|||
accounts_by_ids = self._get_account_details(account_ids, target_move, fiscalyear, main_filter, start, stop, initial_balance_mode) |
|||
|
|||
comparison_params = [] |
|||
comp_accounts_by_ids = [] |
|||
for index in range(max_comparison): |
|||
if comp_filters[index] != 'filter_no': |
|||
comparison_result, comp_params = self._get_comparison_details(data, account_ids, target_move, comp_filters[index], index) |
|||
comparison_params.append(comp_params) |
|||
comp_accounts_by_ids.append(comparison_result) |
|||
|
|||
to_display = dict.fromkeys(account_ids, True) |
|||
objects = [] |
|||
for account in self.pool.get('account.account').browse(self.cursor, self.uid, account_ids): |
|||
if not account.parent_id: # hide top level account |
|||
continue |
|||
if account.type == 'consolidation': |
|||
to_display.update(dict([(a.id, False) for a in account.child_consol_ids])) |
|||
elif account.type == 'view': |
|||
to_display.update(dict([(a.id, True) for a in account.child_id])) |
|||
account.debit = accounts_by_ids[account.id]['debit'] |
|||
account.credit = accounts_by_ids[account.id]['credit'] |
|||
account.balance = accounts_by_ids[account.id]['balance'] |
|||
account.init_balance = accounts_by_ids[account.id].get('init_balance', 0.0) |
|||
|
|||
display_account = False # if any amount is != 0 in comparisons, we have to display the whole account |
|||
comp_accounts = [] |
|||
for comp_account_by_id in comp_accounts_by_ids: |
|||
values = comp_account_by_id.get(account.id) |
|||
values.update(self._get_diff(account.balance, values['balance'])) |
|||
display_account = any((values.get('credit', 0.0), values.get('debit', 0.0), values.get('balance', 0.0), values.get('init_balance', 0.0))) |
|||
comp_accounts.append(values) |
|||
account.comparisons = comp_accounts |
|||
# we have to display the account if a comparison as an amount or if we have an amount in the main column |
|||
# we set it as a property to let the data in the report if someone want to use it in a custom report |
|||
display_account = display_account or any((account.debit, account.credit, account.balance, account.init_balance)) |
|||
to_display.update({account.id: display_account and to_display[account.id]}) |
|||
objects.append(account) |
|||
|
|||
for account in objects: |
|||
account.to_display = to_display[account.id] |
|||
|
|||
context_report_values = { |
|||
'fiscalyear': fiscalyear, |
|||
'start_date': start_date, |
|||
'stop_date': stop_date, |
|||
'start_period': start_period, |
|||
'stop_period': stop_period, |
|||
'chart_account': chart_account, |
|||
'comparison_mode': comparison_mode, |
|||
'nb_comparison': nb_comparisons, |
|||
'initial_balance': init_balance, |
|||
'initial_balance_mode': initial_balance_mode, |
|||
'comp_params': comparison_params, |
|||
} |
|||
return objects, new_ids, context_report_values |
@ -0,0 +1,275 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# SQL inspired from OpenERP original code |
|||
# |
|||
# 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 collections import defaultdict |
|||
from operator import add |
|||
|
|||
from common_balance_reports import CommonBalanceReportHeaderWebkit |
|||
from common_partner_reports import CommonPartnersReportHeaderWebkit |
|||
|
|||
|
|||
class CommonPartnerBalanceReportHeaderWebkit(CommonBalanceReportHeaderWebkit, CommonPartnersReportHeaderWebkit): |
|||
"""Define common helper for balance (trial balance, P&L, BS oriented financial report""" |
|||
|
|||
def _get_account_partners_details(self, account_by_ids, main_filter, target_move, start, |
|||
stop, initial_balance_mode, partner_filter_ids=False): |
|||
res = {} |
|||
filter_from = False |
|||
if main_filter in ('filter_period', 'filter_no', 'filter_opening'): |
|||
filter_from = 'period' |
|||
elif main_filter == 'filter_date': |
|||
filter_from = 'date' |
|||
|
|||
partners_init_balances_by_ids = {} |
|||
for account_id, account_details in account_by_ids.iteritems(): |
|||
partners_init_balances_by_ids.update(self._get_partners_initial_balances(account_id, |
|||
start, |
|||
initial_balance_mode, |
|||
partner_filter_ids=partner_filter_ids, |
|||
exclude_reconcile=False)) # we'll never exclude reconciled entries in the legal reports |
|||
opening_mode = 'exclude_opening' |
|||
if main_filter == 'filter_opening': |
|||
opening_mode = 'include_opening' |
|||
# get credit and debit for partner |
|||
details = self._get_partners_totals_account(filter_from, |
|||
account_id, |
|||
start, |
|||
stop, |
|||
target_move, |
|||
partner_filter_ids=partner_filter_ids, |
|||
mode=opening_mode) |
|||
|
|||
# merge initial balances in partner details |
|||
if partners_init_balances_by_ids.get(account_id): |
|||
for partner_id, initial_balances in partners_init_balances_by_ids[account_id].iteritems(): |
|||
if initial_balances.get('init_balance'): |
|||
details[partner_id].update({'init_balance': initial_balances['init_balance']}) |
|||
|
|||
# compute balance for the partner |
|||
for partner_id, partner_details in details.iteritems(): |
|||
details[partner_id]['balance'] = details[partner_id].get('init_balance', 0.0) +\ |
|||
details[partner_id].get('debit', 0.0) -\ |
|||
details[partner_id].get('credit', 0.0) |
|||
res[account_id] = details |
|||
|
|||
return res |
|||
|
|||
def _get_partners_initial_balances(self, account_ids, start_period, initial_balance_mode, partner_filter_ids=None, exclude_reconcile=False): |
|||
# we get the initial balance from the opening period (opening_balance) when the opening period is included in the start period and |
|||
# when there is at least one entry in the opening period. Otherwise we compute it from previous periods |
|||
if initial_balance_mode == 'opening_balance': |
|||
opening_period_selected = self.get_included_opening_period(start_period) |
|||
res = self._compute_partners_initial_balances(account_ids, start_period, partner_filter_ids, force_period_ids=opening_period_selected, exclude_reconcile=exclude_reconcile) |
|||
elif initial_balance_mode == 'initial_balance': |
|||
res = self._compute_partners_initial_balances(account_ids, start_period, partner_filter_ids, exclude_reconcile=exclude_reconcile) |
|||
else: |
|||
res = {} |
|||
return res |
|||
|
|||
def _get_partners_totals_account(self, filter_from, account_id, start, stop, target_move, partner_filter_ids=None, mode='exclude_opening'): |
|||
final_res = defaultdict(dict) |
|||
|
|||
sql_select = """ |
|||
SELECT account_move_line.partner_id, |
|||
sum(account_move_line.debit) AS debit, |
|||
sum(account_move_line.credit) AS credit |
|||
FROM account_move_line""" |
|||
sql_joins = '' |
|||
sql_where = "WHERE account_move_line.account_id = %(account_id)s AND account_move_line.state = 'valid' " |
|||
sql_conditions, search_params = getattr(self, '_get_query_params_from_'+filter_from+'s')(start, stop, mode=mode) |
|||
sql_where += sql_conditions |
|||
|
|||
if partner_filter_ids: |
|||
sql_where += " AND account_move_line.partner_id in %(partner_ids)s" |
|||
search_params.update({'partner_ids': tuple(partner_filter_ids),}) |
|||
|
|||
if target_move == 'posted': |
|||
sql_joins += "INNER JOIN account_move ON account_move_line.move_id = account_move.id" |
|||
sql_where += " AND account_move.state = %(target_move)s" |
|||
search_params.update({'target_move': target_move,}) |
|||
|
|||
sql_groupby = "GROUP BY account_move_line.partner_id" |
|||
|
|||
search_params.update({'account_id': account_id,}) |
|||
query = ' '.join((sql_select, sql_joins, sql_where, sql_groupby)) |
|||
|
|||
self.cursor.execute(query, search_params) |
|||
res = self.cursor.dictfetchall() |
|||
if res: |
|||
for row in res: |
|||
final_res[row['partner_id']] = row |
|||
return final_res |
|||
|
|||
def _get_filter_type(self, result_selection): |
|||
filter_type = ('payable', 'receivable') |
|||
if result_selection == 'customer': |
|||
filter_type = ('receivable',) |
|||
if result_selection == 'supplier': |
|||
filter_type = ('payable',) |
|||
return filter_type |
|||
|
|||
def _get_partners_comparison_details(self, data, account_ids, target_move, comparison_filter, index, partner_filter_ids=False): |
|||
""" |
|||
|
|||
@param data: data of the wizard form |
|||
@param account_ids: ids of the accounts to get details |
|||
@param comparison_filter: selected filter on the form for the comparison (filter_no, filter_year, filter_period, filter_date) |
|||
@param index: index of the fields to get (ie. comp1_fiscalyear_id where 1 is the index) |
|||
@param partner_filter_ids: list of ids of partners to select |
|||
@return: dict of account details (key = account id) |
|||
""" |
|||
fiscalyear = self._get_info(data, "comp%s_fiscalyear_id" % (index,), 'account.fiscalyear') |
|||
start_period = self._get_info(data, "comp%s_period_from" % (index,), 'account.period') |
|||
stop_period = self._get_info(data, "comp%s_period_to" % (index,), 'account.period') |
|||
start_date = self._get_form_param("comp%s_date_from" % (index,), data) |
|||
stop_date = self._get_form_param("comp%s_date_to" % (index,), data) |
|||
init_balance = self.is_initial_balance_enabled(comparison_filter) |
|||
|
|||
comp_params = {} |
|||
accounts_details_by_ids = defaultdict(dict) |
|||
if comparison_filter != 'filter_no': |
|||
start_period, stop_period, start, stop = \ |
|||
self._get_start_stop_for_filter(comparison_filter, fiscalyear, start_date, stop_date, start_period, stop_period) |
|||
details_filter = comparison_filter |
|||
if comparison_filter == 'filter_year': |
|||
details_filter = 'filter_no' |
|||
|
|||
initial_balance_mode = init_balance and self._get_initial_balance_mode(start) or False |
|||
|
|||
accounts_by_ids = self._get_account_details(account_ids, target_move, fiscalyear, details_filter, start, stop, initial_balance_mode) |
|||
|
|||
partner_details_by_ids = self._get_account_partners_details(accounts_by_ids, details_filter, |
|||
target_move, start, stop, initial_balance_mode, |
|||
partner_filter_ids=partner_filter_ids) |
|||
|
|||
for account_id in account_ids: |
|||
accounts_details_by_ids[account_id]['account'] = accounts_by_ids[account_id] |
|||
accounts_details_by_ids[account_id]['partners_amounts'] = partner_details_by_ids[account_id] |
|||
|
|||
comp_params = { |
|||
'comparison_filter': comparison_filter, |
|||
'fiscalyear': fiscalyear, |
|||
'start': start, |
|||
'stop': stop, |
|||
'initial_balance_mode': initial_balance_mode, |
|||
} |
|||
|
|||
return accounts_details_by_ids, comp_params |
|||
|
|||
def compute_partner_balance_data(self, data, filter_report_type=None): |
|||
new_ids = data['form']['account_ids'] or data['form']['chart_account_id'] |
|||
max_comparison = self._get_form_param('max_comparison', data, default=0) |
|||
main_filter = self._get_form_param('filter', data, default='filter_no') |
|||
|
|||
comp_filters, nb_comparisons, comparison_mode = self._comp_filters(data, max_comparison) |
|||
|
|||
fiscalyear = self.get_fiscalyear_br(data) |
|||
|
|||
start_period = self.get_start_period_br(data) |
|||
stop_period = self.get_end_period_br(data) |
|||
target_move = self._get_form_param('target_move', data, default='all') |
|||
start_date = self._get_form_param('date_from', data) |
|||
stop_date = self._get_form_param('date_to', data) |
|||
chart_account = self._get_chart_account_id_br(data) |
|||
result_selection = self._get_form_param('result_selection', data) |
|||
partner_ids = self._get_form_param('partner_ids', data) |
|||
|
|||
filter_type = self._get_filter_type(result_selection) |
|||
|
|||
start_period, stop_period, start, stop = \ |
|||
self._get_start_stop_for_filter(main_filter, fiscalyear, start_date, stop_date, start_period, stop_period) |
|||
|
|||
initial_balance = self.is_initial_balance_enabled(main_filter) |
|||
initial_balance_mode = initial_balance and self._get_initial_balance_mode(start) or False |
|||
|
|||
# Retrieving accounts |
|||
account_ids = self.get_all_accounts(new_ids, only_type=filter_type, |
|||
filter_report_type=filter_report_type) |
|||
|
|||
# get details for each accounts, total of debit / credit / balance |
|||
accounts_by_ids = self._get_account_details(account_ids, target_move, fiscalyear, main_filter, start, stop, initial_balance_mode) |
|||
|
|||
partner_details_by_ids = self._get_account_partners_details(accounts_by_ids, |
|||
main_filter, |
|||
target_move, |
|||
start, |
|||
stop, |
|||
initial_balance_mode, |
|||
partner_filter_ids=partner_ids) |
|||
|
|||
comparison_params = [] |
|||
comp_accounts_by_ids = [] |
|||
for index in range(max_comparison): |
|||
if comp_filters[index] != 'filter_no': |
|||
comparison_result, comp_params = self._get_partners_comparison_details(data, account_ids, |
|||
target_move, comp_filters[index], |
|||
index, partner_filter_ids=partner_ids) |
|||
comparison_params.append(comp_params) |
|||
comp_accounts_by_ids.append(comparison_result) |
|||
objects = [] |
|||
|
|||
for account in self.pool.get('account.account').browse(self.cursor, self.uid, account_ids): |
|||
if not account.parent_id: # hide top level account |
|||
continue |
|||
account.debit = accounts_by_ids[account.id]['debit'] |
|||
account.credit = accounts_by_ids[account.id]['credit'] |
|||
account.balance = accounts_by_ids[account.id]['balance'] |
|||
account.init_balance = accounts_by_ids[account.id].get('init_balance', 0.0) |
|||
account.partners_amounts = partner_details_by_ids[account.id] |
|||
comp_accounts = [] |
|||
for comp_account_by_id in comp_accounts_by_ids: |
|||
values = comp_account_by_id.get(account.id) |
|||
|
|||
values['account'].update(self._get_diff(account.balance, values['account'].get('balance', 0.0))) |
|||
comp_accounts.append(values) |
|||
|
|||
for partner_id, partner_values in values['partners_amounts'].copy().iteritems(): |
|||
base_partner_balance = account.partners_amounts[partner_id]['balance'] if \ |
|||
account.partners_amounts.get(partner_id) else 0.0 |
|||
partner_values.update(self._get_diff(base_partner_balance, |
|||
partner_values.get('balance', 0.0))) |
|||
values['partners_amounts'][partner_id].update(partner_values) |
|||
|
|||
account.comparisons = comp_accounts |
|||
|
|||
all_partner_ids = reduce(add, [comp['partners_amounts'].keys() for comp in comp_accounts], |
|||
account.partners_amounts.keys()) |
|||
|
|||
account.partners_order = self._order_partners(all_partner_ids) |
|||
|
|||
objects.append(account) |
|||
|
|||
context_report_values = { |
|||
'fiscalyear': fiscalyear, |
|||
'start_date': start_date, |
|||
'stop_date': stop_date, |
|||
'start_period': start_period, |
|||
'stop_period': stop_period, |
|||
'chart_account': chart_account, |
|||
'comparison_mode': comparison_mode, |
|||
'nb_comparison': nb_comparisons, |
|||
'comp_params': comparison_params, |
|||
'initial_balance_mode': initial_balance_mode, |
|||
'compute_diff': self._get_diff, |
|||
} |
|||
|
|||
return objects, new_ids, context_report_values |
@ -0,0 +1,328 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi, Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# SQL inspired from OpenERP original code |
|||
# |
|||
# 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/>. |
|||
# |
|||
############################################################################## |
|||
# TODO refactor helper in order to act more like mixin |
|||
# By using properties we will have a more simple signature in fuctions |
|||
|
|||
from collections import defaultdict |
|||
from datetime import datetime |
|||
|
|||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT |
|||
from common_reports import CommonReportHeaderWebkit |
|||
|
|||
|
|||
class CommonPartnersReportHeaderWebkit(CommonReportHeaderWebkit): |
|||
"""Define common helper for partner oriented financial report""" |
|||
|
|||
####################Account move line retrieval helper ########################## |
|||
def get_partners_move_lines_ids(self, account_id, main_filter, start, stop, target_move, |
|||
exclude_reconcile=False, |
|||
partner_filter=False): |
|||
filter_from = False |
|||
if main_filter in ('filter_period', 'filter_no'): |
|||
filter_from = 'period' |
|||
elif main_filter == 'filter_date': |
|||
filter_from = 'date' |
|||
if filter_from: |
|||
return self._get_partners_move_line_ids(filter_from, |
|||
account_id, |
|||
start, |
|||
stop, |
|||
target_move, |
|||
exclude_reconcile=exclude_reconcile, |
|||
partner_filter=partner_filter) |
|||
|
|||
def _get_first_special_period(self): |
|||
""" |
|||
Returns the browse record of the period with the `special` flag, which |
|||
is the special period of the first fiscal year used in the accounting. |
|||
|
|||
i.e. it searches the first fiscal year with at least one journal entry, |
|||
and it returns the id of the first period for which `special` is True |
|||
in this fiscal year. |
|||
|
|||
It is used for example in the partners reports, where we have to include |
|||
the first, and only the first opening period. |
|||
|
|||
:return: browse record of the first special period. |
|||
""" |
|||
move_line_obj = self.pool.get('account.move.line') |
|||
first_entry_id = move_line_obj.search( |
|||
self.cr, self.uid, [], order='date ASC', limit=1) |
|||
# it means there is no entry at all, that's unlikely to happen, but |
|||
# it may so |
|||
if not first_entry_id: |
|||
return |
|||
first_entry = move_line_obj.browse(self.cr, self.uid, first_entry_id[0]) |
|||
fiscalyear = first_entry.period_id.fiscalyear_id |
|||
special_periods = [period for period in fiscalyear.period_ids if period.special] |
|||
# so, we have no opening period on the first year, nothing to return |
|||
if not special_periods: |
|||
return |
|||
return min(special_periods, |
|||
key=lambda p: datetime.strptime(p.date_start, DEFAULT_SERVER_DATE_FORMAT)) |
|||
|
|||
def _get_period_range_from_start_period(self, start_period, include_opening=False, |
|||
fiscalyear=False, |
|||
stop_at_previous_opening=False): |
|||
"""We retrieve all periods before start period""" |
|||
periods = super(CommonPartnersReportHeaderWebkit, self).\ |
|||
_get_period_range_from_start_period( |
|||
start_period, |
|||
include_opening=include_opening, |
|||
fiscalyear=fiscalyear, |
|||
stop_at_previous_opening=stop_at_previous_opening) |
|||
first_special = self._get_first_special_period() |
|||
if first_special and first_special.id not in periods: |
|||
periods.append(first_special.id) |
|||
return periods |
|||
|
|||
def _get_query_params_from_periods(self, period_start, period_stop, mode='exclude_opening'): |
|||
""" |
|||
Build the part of the sql "where clause" which filters on the selected |
|||
periods. |
|||
|
|||
:param browse_record period_start: first period of the report to print |
|||
:param browse_record period_stop: last period of the report to print |
|||
:param str mode: deprecated |
|||
""" |
|||
# we do not want opening period so we exclude opening |
|||
periods = self.pool.get('account.period').build_ctx_periods( |
|||
self.cr, self.uid, period_start.id, period_stop.id) |
|||
if not periods: |
|||
return [] |
|||
|
|||
periods = self.exclude_opening_periods(periods) |
|||
|
|||
search_params = {'period_ids': tuple(periods), |
|||
'date_stop': period_stop.date_stop} |
|||
|
|||
sql_conditions = " AND account_move_line.period_id in %(period_ids)s" |
|||
|
|||
return sql_conditions, search_params |
|||
|
|||
def _get_query_params_from_dates(self, date_start, date_stop, **args): |
|||
""" |
|||
Build the part of the sql where clause based on the dates to print. |
|||
|
|||
:param str date_start: start date of the report to print |
|||
:param str date_stop: end date of the report to print |
|||
""" |
|||
|
|||
periods = self._get_opening_periods() |
|||
if not periods: |
|||
periods = (-1,) |
|||
|
|||
search_params = {'period_ids': tuple(periods), |
|||
'date_start': date_start, |
|||
'date_stop': date_stop} |
|||
|
|||
sql_conditions = " AND account_move_line.period_id not in %(period_ids)s" \ |
|||
" AND account_move_line.date between date(%(date_start)s) and date((%(date_stop)s))" |
|||
|
|||
return sql_conditions, search_params |
|||
|
|||
def _get_partners_move_line_ids(self, filter_from, account_id, start, stop, |
|||
target_move, opening_mode='exclude_opening', |
|||
exclude_reconcile=False, partner_filter=None): |
|||
""" |
|||
|
|||
:param str filter_from: "periods" or "dates" |
|||
:param int account_id: id of the account where to search move lines |
|||
:param str or browse_record start: start date or start period |
|||
:param str or browse_record stop: stop date or stop period |
|||
:param str target_move: 'posted' or 'all' |
|||
:param opening_mode: deprecated |
|||
:param boolean exclude_reconcile: wether the reconciled entries are |
|||
filtred or not |
|||
:param list partner_filter: list of partner ids, will filter on their |
|||
move lines |
|||
""" |
|||
|
|||
final_res = defaultdict(list) |
|||
|
|||
sql_select = "SELECT account_move_line.id, account_move_line.partner_id FROM account_move_line" |
|||
sql_joins = '' |
|||
sql_where = " WHERE account_move_line.account_id = %(account_ids)s " \ |
|||
" AND account_move_line.state = 'valid' " |
|||
|
|||
sql_conditions, search_params = getattr(self, '_get_query_params_from_'+filter_from+'s')(start, stop) |
|||
|
|||
sql_where += sql_conditions |
|||
|
|||
if exclude_reconcile: |
|||
sql_where += (" AND ((account_move_line.reconcile_id IS NULL)" |
|||
" OR (account_move_line.reconcile_id IS NOT NULL AND account_move_line.last_rec_date > date(%(date_stop)s)))") |
|||
|
|||
if partner_filter: |
|||
sql_where += " AND account_move_line.partner_id in %(partner_ids)s" |
|||
|
|||
if target_move == 'posted': |
|||
sql_joins += "INNER JOIN account_move ON account_move_line.move_id = account_move.id" |
|||
sql_where += " AND account_move.state = %(target_move)s" |
|||
search_params.update({'target_move': target_move,}) |
|||
|
|||
search_params.update({ |
|||
'account_ids': account_id, |
|||
'partner_ids': tuple(partner_filter), |
|||
}) |
|||
|
|||
sql = ' '.join((sql_select, sql_joins, sql_where)) |
|||
self.cursor.execute(sql, search_params) |
|||
res = self.cursor.dictfetchall() |
|||
if res: |
|||
for row in res: |
|||
final_res[row['partner_id']].append(row['id']) |
|||
return final_res |
|||
|
|||
def _get_clearance_move_line_ids(self, move_line_ids, date_stop, date_until): |
|||
if not move_line_ids: |
|||
return [] |
|||
move_line_obj = self.pool.get('account.move.line') |
|||
# we do not use orm in order to gain perfo |
|||
# In this case I have to test the effective gain over an itteration |
|||
# Actually ORM does not allows distinct behavior |
|||
sql = "Select distinct reconcile_id from account_move_line where id in %s" |
|||
self.cursor.execute(sql, (tuple(move_line_ids),)) |
|||
rec_ids = self.cursor.fetchall() |
|||
if rec_ids: |
|||
rec_ids = [x[0] for x in rec_ids] |
|||
l_ids = move_line_obj.search(self.cursor, |
|||
self.uid, |
|||
[('reconcile_id', 'in', rec_ids), |
|||
('date', '>=', date_stop), |
|||
('date', '<=', date_until)]) |
|||
return l_ids |
|||
else: |
|||
return [] |
|||
|
|||
####################Initial Partner Balance helper ######################## |
|||
|
|||
def _tree_move_line_ids(self, move_lines_data, key=None): |
|||
""" |
|||
move_lines_data must be a list of dict which contains at least keys : |
|||
- account_id |
|||
- partner_id |
|||
- other keys with values of the line |
|||
- if param key is defined, only this key will be inserted in the tree |
|||
returns a tree like |
|||
res[account_id.1][partner_id.1][move_line.1, |
|||
move_line.2] |
|||
[partner_id.2][move_line.3] |
|||
res[account_id.2][partner_id.1][move_line.4] |
|||
""" |
|||
res = defaultdict(dict) |
|||
for row in move_lines_data[:]: |
|||
account_id = row.pop('account_id') |
|||
partner_id = row.pop('partner_id') |
|||
if key: |
|||
res[account_id].setdefault(partner_id, []).append(row[key]) |
|||
else: |
|||
res[account_id][partner_id] = row |
|||
return res |
|||
|
|||
def _partners_initial_balance_line_ids(self, account_ids, start_period, partner_filter, exclude_reconcile=False, force_period_ids=False, date_stop=None): |
|||
# take ALL previous periods |
|||
period_ids = force_period_ids \ |
|||
if force_period_ids \ |
|||
else self._get_period_range_from_start_period(start_period, fiscalyear=False, include_opening=False) |
|||
|
|||
if not period_ids: |
|||
period_ids = [-1] |
|||
search_param = {'date_start': start_period.date_start, |
|||
'period_ids': tuple(period_ids), |
|||
'account_ids': tuple(account_ids),} |
|||
sql = ("SELECT ml.id, ml.account_id, ml.partner_id " |
|||
"FROM account_move_line ml " |
|||
"INNER JOIN account_account a " |
|||
"ON a.id = ml.account_id " |
|||
"WHERE ml.period_id in %(period_ids)s " |
|||
"AND ml.account_id in %(account_ids)s ") |
|||
if exclude_reconcile: |
|||
if not date_stop: |
|||
raise Exception("Missing \"date_stop\" to compute the open invoices.") |
|||
search_param.update({'date_stop': date_stop}) |
|||
sql += ("AND ((ml.reconcile_id IS NULL)" |
|||
"OR (ml.reconcile_id IS NOT NULL AND ml.last_rec_date > date(%(date_stop)s))) ") |
|||
if partner_filter: |
|||
sql += "AND ml.partner_id in %(partner_ids)s " |
|||
search_param.update({'partner_ids': tuple(partner_filter)}) |
|||
|
|||
self.cursor.execute(sql, search_param) |
|||
return self.cursor.dictfetchall() |
|||
|
|||
def _compute_partners_initial_balances(self, account_ids, start_period, partner_filter=None, exclude_reconcile=False, force_period_ids=False): |
|||
"""We compute initial balance. |
|||
If form is filtered by date all initial balance are equal to 0 |
|||
This function will sum pear and apple in currency amount if account as no secondary currency""" |
|||
if isinstance(account_ids, (int, long)): |
|||
account_ids = [account_ids] |
|||
move_line_ids = self._partners_initial_balance_line_ids(account_ids, start_period, partner_filter, |
|||
exclude_reconcile=exclude_reconcile, |
|||
force_period_ids=force_period_ids) |
|||
if not move_line_ids: |
|||
move_line_ids = [{'id': -1}] |
|||
sql = ("SELECT ml.account_id, ml.partner_id," |
|||
" sum(ml.debit) as debit, sum(ml.credit) as credit," |
|||
" sum(ml.debit-ml.credit) as init_balance," |
|||
" CASE WHEN a.currency_id ISNULL THEN 0.0 ELSE sum(ml.amount_currency) END as init_balance_currency, " |
|||
" c.name as currency_name " |
|||
"FROM account_move_line ml " |
|||
"INNER JOIN account_account a " |
|||
"ON a.id = ml.account_id " |
|||
"LEFT JOIN res_currency c " |
|||
"ON c.id = a.currency_id " |
|||
"WHERE ml.id in %(move_line_ids)s " |
|||
"GROUP BY ml.account_id, ml.partner_id, a.currency_id, c.name") |
|||
search_param = {'move_line_ids': tuple([move_line['id'] for move_line in move_line_ids])} |
|||
self.cursor.execute(sql, search_param) |
|||
res = self.cursor.dictfetchall() |
|||
return self._tree_move_line_ids(res) |
|||
|
|||
####################Partner specific helper ################################ |
|||
def _order_partners(self, *args): |
|||
"""We get the partner linked to all current accounts that are used. |
|||
We also use ensure that partner are ordered by name |
|||
args must be list""" |
|||
res = [] |
|||
partner_ids = [] |
|||
for arg in args: |
|||
if arg: |
|||
partner_ids += arg |
|||
if not partner_ids: |
|||
return [] |
|||
|
|||
existing_partner_ids = [partner_id for partner_id in partner_ids if partner_id] |
|||
if existing_partner_ids: |
|||
# We may use orm here as the performance optimization is not that big |
|||
sql = ("SELECT name|| ' ' ||CASE WHEN ref IS NOT NULL THEN '('||ref||')' ELSE '' END, id, ref, name" |
|||
" FROM res_partner WHERE id IN %s ORDER BY LOWER(name), ref") |
|||
self.cursor.execute(sql, (tuple(set(existing_partner_ids)),)) |
|||
res = self.cursor.fetchall() |
|||
|
|||
# move lines without partners, set None for empty partner |
|||
if not all(partner_ids): |
|||
res.append((None, None, None, None)) |
|||
|
|||
if not res: |
|||
return [] |
|||
return res |
|||
|
@ -0,0 +1,520 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi, Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# SQL inspired from OpenERP original code |
|||
# |
|||
# 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/>. |
|||
# |
|||
############################################################################## |
|||
# TODO refactor helper in order to act more like mixin |
|||
# By using properties we will have a more simple signature in fuctions |
|||
|
|||
import logging |
|||
|
|||
from openerp.addons.account.report.common_report_header import common_report_header |
|||
from osv import osv |
|||
from tools.translate import _ |
|||
|
|||
|
|||
_logger = logging.getLogger('financial.reports.webkit') |
|||
|
|||
class CommonReportHeaderWebkit(common_report_header): |
|||
"""Define common helper for financial report""" |
|||
|
|||
####################From getter helper ##################################### |
|||
def get_start_period_br(self, data): |
|||
return self._get_info(data,'period_from', 'account.period') |
|||
|
|||
def get_end_period_br(self, data): |
|||
return self._get_info(data,'period_to', 'account.period') |
|||
|
|||
def get_fiscalyear_br(self, data): |
|||
return self._get_info(data,'fiscalyear_id', 'account.fiscalyear') |
|||
|
|||
def _get_chart_account_id_br(self, data): |
|||
return self._get_info(data, 'chart_account_id', 'account.account') |
|||
|
|||
def _get_accounts_br(self, data): |
|||
return self._get_info(data, 'account_ids', 'account.account') |
|||
|
|||
def _get_info(self, data, field, model): |
|||
info = data.get('form', {}).get(field) |
|||
if info: |
|||
return self.pool.get(model).browse(self.cursor, self.uid, info) |
|||
return False |
|||
|
|||
def _get_display_account(self, data): |
|||
val = self._get_form_param('display_account', data) |
|||
if val == 'bal_all': |
|||
return _('All accounts') |
|||
elif val == 'bal_mix': |
|||
return _('With transactions or non zero balance') |
|||
else: |
|||
return val |
|||
|
|||
def _get_display_partner_account(self, data): |
|||
val = self._get_form_param('result_selection', data) |
|||
if val == 'customer': |
|||
return _('Receivable Accounts') |
|||
elif val == 'supplier': |
|||
return _('Payable Accounts') |
|||
elif val == 'customer_supplier': |
|||
return _('Receivable and Payable Accounts') |
|||
else: |
|||
return val |
|||
|
|||
def _get_display_target_move(self, data): |
|||
val = self._get_form_param('target_move', data) |
|||
if val == 'posted': |
|||
return _('All Posted Entries') |
|||
elif val == 'all': |
|||
return _('All Entries') |
|||
else: |
|||
return val |
|||
|
|||
def _get_display_account_raw(self, data): |
|||
return self._get_form_param('display_account', data) |
|||
|
|||
def _get_filter(self, data): |
|||
return self._get_form_param('filter', data) |
|||
|
|||
def _get_target_move(self, data): |
|||
return self._get_form_param('target_move', data) |
|||
|
|||
def _get_initial_balance(self, data): |
|||
return self._get_form_param('initial_balance', data) |
|||
|
|||
def _get_amount_currency(self, data): |
|||
return self._get_form_param('amount_currency', data) |
|||
|
|||
def _get_date_from(self, data): |
|||
return self._get_form_param('date_from', data) |
|||
|
|||
def _get_date_to(self, data): |
|||
return self._get_form_param('date_to', data) |
|||
|
|||
def _get_form_param(self, param, data, default=False): |
|||
return data.get('form', {}).get(param, default) |
|||
|
|||
|
|||
|
|||
####################Account and account line filter helper ################# |
|||
|
|||
def sort_accounts_with_structure(self, root_account_ids, account_ids, context=None): |
|||
"""Sort accounts by code respecting their structure""" |
|||
|
|||
def recursive_sort_by_code(accounts, parent): |
|||
sorted_accounts = [] |
|||
# add all accounts with same parent |
|||
level_accounts = [account for account in accounts |
|||
if account['parent_id'] and account['parent_id'][0] == parent['id']] |
|||
# add consolidation children of parent, as they are logically on the same level |
|||
if parent.get('child_consol_ids'): |
|||
level_accounts.extend([account for account in accounts |
|||
if account['id'] in parent['child_consol_ids']]) |
|||
# stop recursion if no children found |
|||
if not level_accounts: |
|||
return [] |
|||
|
|||
level_accounts = sorted(level_accounts, key=lambda a: a['code']) |
|||
|
|||
for level_account in level_accounts: |
|||
sorted_accounts.append(level_account['id']) |
|||
sorted_accounts.extend(recursive_sort_by_code(accounts, parent=level_account)) |
|||
return sorted_accounts |
|||
|
|||
if not account_ids: |
|||
return [] |
|||
|
|||
accounts_data = self.pool.get('account.account').read(self.cr, self.uid, |
|||
account_ids, |
|||
['id', 'parent_id', 'level', 'code', 'child_consol_ids'], |
|||
context=context) |
|||
|
|||
sorted_accounts = [] |
|||
|
|||
root_accounts_data = [account_data for account_data in accounts_data |
|||
if account_data['id'] in root_account_ids] |
|||
for root_account_data in root_accounts_data: |
|||
sorted_accounts.append(root_account_data['id']) |
|||
sorted_accounts.extend(recursive_sort_by_code(accounts_data, root_account_data)) |
|||
|
|||
# fallback to unsorted accounts when sort failed |
|||
# sort fails when the levels are miscalculated by account.account |
|||
# check lp:783670 |
|||
if len(sorted_accounts) != len(account_ids): |
|||
_logger.warn('Webkit financial reports: Sort of accounts failed.') |
|||
sorted_accounts = account_ids |
|||
|
|||
return sorted_accounts |
|||
|
|||
def get_all_accounts(self, account_ids, exclude_type=None, only_type=None, filter_report_type=None, context=None): |
|||
"""Get all account passed in params with their childrens |
|||
|
|||
@param exclude_type: list of types to exclude (view, receivable, payable, consolidation, other) |
|||
@param only_type: list of types to filter on (view, receivable, payable, consolidation, other) |
|||
@param filter_report_type: list of report type to filter on |
|||
""" |
|||
context = context or {} |
|||
accounts = [] |
|||
if not isinstance(account_ids, list): |
|||
account_ids = [account_ids] |
|||
acc_obj = self.pool.get('account.account') |
|||
for account_id in account_ids: |
|||
accounts.append(account_id) |
|||
accounts += acc_obj._get_children_and_consol(self.cursor, self.uid, account_id, context=context) |
|||
res_ids = list(set(accounts)) |
|||
res_ids = self.sort_accounts_with_structure(account_ids, res_ids, context=context) |
|||
|
|||
if exclude_type or only_type or filter_report_type: |
|||
sql_filters = {'ids': tuple(res_ids)} |
|||
sql_select = "SELECT a.id FROM account_account a" |
|||
sql_join = "" |
|||
sql_where = "WHERE a.id IN %(ids)s" |
|||
if exclude_type: |
|||
sql_where += " AND a.type not in %(exclude_type)s" |
|||
sql_filters.update({'exclude_type': tuple(exclude_type)}) |
|||
if only_type: |
|||
sql_where += " AND a.type IN %(only_type)s" |
|||
sql_filters.update({'only_type': tuple(only_type)}) |
|||
if filter_report_type: |
|||
sql_join += "INNER JOIN account_account_type t" \ |
|||
" ON t.id = a.user_type" |
|||
sql_join += " AND t.report_type IN %(report_type)s" |
|||
sql_filters.update({'report_type': tuple(filter_report_type)}) |
|||
|
|||
sql = ' '.join((sql_select, sql_join, sql_where)) |
|||
self.cursor.execute(sql, sql_filters) |
|||
fetch_only_ids = self.cursor.fetchall() |
|||
if not fetch_only_ids: |
|||
return [] |
|||
only_ids = [only_id[0] for only_id in fetch_only_ids] |
|||
# keep sorting but filter ids |
|||
res_ids = [res_id for res_id in res_ids if res_id in only_ids] |
|||
return res_ids |
|||
|
|||
####################Periods and fiscal years helper ####################### |
|||
|
|||
def _get_opening_periods(self): |
|||
"""Return the list of all journal that can be use to create opening entries |
|||
We actually filter on this instead of opening period as older version of OpenERP |
|||
did not have this notion""" |
|||
return self.pool.get('account.period').search(self.cursor, self.uid, [('special', '=', True)]) |
|||
|
|||
def exclude_opening_periods(self, period_ids): |
|||
period_obj = self.pool.get('account.period') |
|||
return period_obj.search(self.cr, self.uid, [['special', '=', False], ['id', 'in', period_ids]]) |
|||
|
|||
def get_included_opening_period(self, period): |
|||
"""Return the opening included in normal period we use the assumption |
|||
that there is only one opening period per fiscal year""" |
|||
period_obj = self.pool.get('account.period') |
|||
return period_obj.search(self.cursor, self.uid, |
|||
[('special', '=', True), |
|||
('date_start', '>=', period.date_start), |
|||
('date_stop', '<=', period.date_stop)], |
|||
limit=1) |
|||
|
|||
def periods_contains_move_lines(self, period_ids): |
|||
if not period_ids: |
|||
return False |
|||
mv_line_obj = self.pool.get('account.move.line') |
|||
if isinstance(period_ids, (int, long)): |
|||
period_ids = [period_ids] |
|||
return mv_line_obj.search(self.cursor, self.uid, [('period_id', 'in', period_ids)], limit=1) and True or False |
|||
|
|||
def _get_period_range_from_periods(self, start_period, stop_period, mode=None): |
|||
""" |
|||
Deprecated. We have to use now the build_ctx_periods of period_obj otherwise we'll have |
|||
inconsistencies, because build_ctx_periods does never filter on the the special |
|||
""" |
|||
period_obj = self.pool.get('account.period') |
|||
search_period = [('date_start', '>=', start_period.date_start), |
|||
('date_stop', '<=', stop_period.date_stop)] |
|||
|
|||
if mode == 'exclude_opening': |
|||
search_period += [('special', '=', False)] |
|||
res = period_obj.search(self.cursor, self.uid, search_period) |
|||
return res |
|||
|
|||
def _get_period_range_from_start_period(self, start_period, include_opening=False, |
|||
fiscalyear=False, stop_at_previous_opening=False): |
|||
"""We retrieve all periods before start period""" |
|||
opening_period_id = False |
|||
past_limit = [] |
|||
period_obj = self.pool.get('account.period') |
|||
mv_line_obj = self.pool.get('account.move.line') |
|||
# We look for previous opening period |
|||
if stop_at_previous_opening: |
|||
opening_search = [('special', '=', True), |
|||
('date_stop', '<', start_period.date_start)] |
|||
if fiscalyear: |
|||
opening_search.append(('fiscalyear_id', '=', fiscalyear.id)) |
|||
|
|||
opening_periods = period_obj.search(self.cursor, self.uid, opening_search, |
|||
order='date_stop desc') |
|||
for opening_period in opening_periods: |
|||
validation_res = mv_line_obj.search(self.cursor, |
|||
self.uid, |
|||
[('period_id', '=', opening_period)], |
|||
limit=1) |
|||
if validation_res: |
|||
opening_period_id = opening_period |
|||
break |
|||
if opening_period_id: |
|||
#we also look for overlapping periods |
|||
opening_period_br = period_obj.browse(self.cursor, self.uid, opening_period_id) |
|||
past_limit = [('date_start', '>=', opening_period_br.date_stop)] |
|||
|
|||
periods_search = [('date_stop', '<=', start_period.date_stop)] |
|||
periods_search += past_limit |
|||
|
|||
if not include_opening: |
|||
periods_search += [('special', '=', False)] |
|||
|
|||
if fiscalyear : |
|||
periods_search.append(('fiscalyear_id', '=', fiscalyear.id)) |
|||
periods = period_obj.search(self.cursor, self.uid, periods_search) |
|||
if include_opening and opening_period_id: |
|||
periods.append(opening_period_id) |
|||
periods = list(set(periods)) |
|||
if start_period.id in periods: |
|||
periods.remove(start_period.id) |
|||
return periods |
|||
|
|||
def get_first_fiscalyear_period(self, fiscalyear): |
|||
return self._get_st_fiscalyear_period(fiscalyear) |
|||
|
|||
def get_last_fiscalyear_period(self, fiscalyear): |
|||
return self._get_st_fiscalyear_period(fiscalyear, order='DESC') |
|||
|
|||
def _get_st_fiscalyear_period(self, fiscalyear, special=False, order='ASC'): |
|||
period_obj = self.pool.get('account.period') |
|||
p_id = period_obj.search(self.cursor, |
|||
self.uid, |
|||
[('special','=', special), |
|||
('fiscalyear_id', '=', fiscalyear.id)], |
|||
limit=1, |
|||
order='date_start %s' % (order,)) |
|||
if not p_id: |
|||
raise osv.except_osv(_('No period found'),'') |
|||
return period_obj.browse(self.cursor, self.uid, p_id[0]) |
|||
|
|||
####################Initial Balance helper ################################# |
|||
|
|||
def _compute_init_balance(self, account_id=None, period_ids=None, mode='computed', default_values=False): |
|||
if not isinstance(period_ids, list): |
|||
period_ids = [period_ids] |
|||
res = {} |
|||
|
|||
if not default_values: |
|||
if not account_id or not period_ids: |
|||
raise Exception('Missing account or period_ids') |
|||
try: |
|||
self.cursor.execute("SELECT sum(debit) AS debit, " |
|||
" sum(credit) AS credit, " |
|||
" sum(debit)-sum(credit) AS balance, " |
|||
" sum(amount_currency) AS curr_balance" |
|||
" FROM account_move_line" |
|||
" WHERE period_id in %s" |
|||
" AND account_id = %s", (tuple(period_ids), account_id)) |
|||
res = self.cursor.dictfetchone() |
|||
|
|||
except Exception, exc: |
|||
self.cursor.rollback() |
|||
raise |
|||
|
|||
return {'debit': res.get('debit') or 0.0, |
|||
'credit': res.get('credit') or 0.0, |
|||
'init_balance': res.get('balance') or 0.0, |
|||
'init_balance_currency': res.get('curr_balance') or 0.0, |
|||
'state': mode} |
|||
|
|||
def _read_opening_balance(self, account_ids, start_period): |
|||
""" Read opening balances from the opening balance |
|||
""" |
|||
opening_period_selected = self.get_included_opening_period(start_period) |
|||
if not opening_period_selected: |
|||
raise osv.except_osv( |
|||
_('Error'), |
|||
_('No opening period found to compute the opening balances.\n' |
|||
'You have to configure a period on the first of January' |
|||
' with the special flag.')) |
|||
|
|||
res = {} |
|||
for account_id in account_ids: |
|||
res[account_id] = self._compute_init_balance(account_id, opening_period_selected, mode='read') |
|||
return res |
|||
|
|||
def _compute_initial_balances(self, account_ids, start_period, fiscalyear): |
|||
"""We compute initial balance. |
|||
If form is filtered by date all initial balance are equal to 0 |
|||
This function will sum pear and apple in currency amount if account as no secondary currency""" |
|||
# if opening period is included in start period we do not need to compute init balance |
|||
# we just read it from opening entries |
|||
res = {} |
|||
# PNL and Balance accounts are not computed the same way look for attached doc |
|||
# We include opening period in pnl account in order to see if opening entries |
|||
# were created by error on this account |
|||
pnl_periods_ids = self._get_period_range_from_start_period(start_period, fiscalyear=fiscalyear, |
|||
include_opening=True) |
|||
bs_period_ids = self._get_period_range_from_start_period(start_period, include_opening=True, |
|||
stop_at_previous_opening=True) |
|||
opening_period_selected = self.get_included_opening_period(start_period) |
|||
|
|||
for acc in self.pool.get('account.account').browse(self.cursor, self.uid, account_ids): |
|||
res[acc.id] = self._compute_init_balance(default_values=True) |
|||
if acc.user_type.close_method == 'none': |
|||
# we compute the initial balance for close_method == none only when we print a GL |
|||
# during the year, when the opening period is not included in the period selection! |
|||
if pnl_periods_ids and not opening_period_selected: |
|||
res[acc.id] = self._compute_init_balance(acc.id, pnl_periods_ids) |
|||
else: |
|||
res[acc.id] = self._compute_init_balance(acc.id, bs_period_ids) |
|||
return res |
|||
|
|||
####################Account move retrieval helper ########################## |
|||
def _get_move_ids_from_periods(self, account_id, period_start, period_stop, target_move): |
|||
move_line_obj = self.pool.get('account.move.line') |
|||
period_obj = self.pool.get('account.period') |
|||
periods = period_obj.build_ctx_periods(self.cursor, self.uid, period_start.id, period_stop.id) |
|||
if not periods: |
|||
return [] |
|||
search = [('period_id', 'in', periods), ('account_id', '=', account_id)] |
|||
if target_move == 'posted': |
|||
search += [('move_id.state', '=', 'posted')] |
|||
return move_line_obj.search(self.cursor, self.uid, search) |
|||
|
|||
def _get_move_ids_from_dates(self, account_id, date_start, date_stop, target_move, mode='include_opening'): |
|||
# TODO imporve perfomance by setting opening period as a property |
|||
move_line_obj = self.pool.get('account.move.line') |
|||
search_period = [('date', '>=', date_start), |
|||
('date', '<=', date_stop), |
|||
('account_id', '=', account_id)] |
|||
|
|||
# actually not used because OpenERP itself always include the opening when we |
|||
# get the periods from january to december |
|||
if mode == 'exclude_opening': |
|||
opening = self._get_opening_periods() |
|||
if opening: |
|||
search_period += ['period_id', 'not in', opening] |
|||
|
|||
if target_move == 'posted': |
|||
search_period += [('move_id.state', '=', 'posted')] |
|||
|
|||
return move_line_obj.search(self.cursor, self.uid, search_period) |
|||
|
|||
def get_move_lines_ids(self, account_id, main_filter, start, stop, target_move, mode='include_opening'): |
|||
"""Get account move lines base on form data""" |
|||
if mode not in ('include_opening', 'exclude_opening'): |
|||
raise osv.except_osv(_('Invalid query mode'), _('Must be in include_opening, exclude_opening')) |
|||
|
|||
if main_filter in ('filter_period', 'filter_no'): |
|||
return self._get_move_ids_from_periods(account_id, start, stop, target_move) |
|||
|
|||
elif main_filter == 'filter_date': |
|||
return self._get_move_ids_from_dates(account_id, start, stop, target_move) |
|||
else: |
|||
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'): |
|||
if not move_line_ids: |
|||
return [] |
|||
if not isinstance(move_line_ids, list): |
|||
move_line_ids = [move_line_ids] |
|||
monster =""" |
|||
SELECT l.id AS id, |
|||
l.date AS ldate, |
|||
j.code AS jcode , |
|||
l.currency_id, |
|||
l.account_id, |
|||
l.amount_currency, |
|||
l.ref AS lref, |
|||
l.name AS lname, |
|||
COALESCE(l.debit, 0.0) - COALESCE(l.credit, 0.0) AS balance, |
|||
l.debit, |
|||
l.credit, |
|||
l.period_id AS lperiod_id, |
|||
per.code as period_code, |
|||
per.special AS peropen, |
|||
l.partner_id AS lpartner_id, |
|||
p.name AS partner_name, |
|||
m.name AS move_name, |
|||
COALESCE(partialrec.name, fullrec.name, '') AS rec_name, |
|||
m.id AS move_id, |
|||
c.name AS currency_code, |
|||
i.id AS invoice_id, |
|||
i.type AS invoice_type, |
|||
i.number AS invoice_number, |
|||
l.date_maturity |
|||
FROM account_move_line l |
|||
JOIN account_move m on (l.move_id=m.id) |
|||
LEFT JOIN res_currency c on (l.currency_id=c.id) |
|||
LEFT JOIN account_move_reconcile partialrec on (l.reconcile_partial_id = partialrec.id) |
|||
LEFT JOIN account_move_reconcile fullrec on (l.reconcile_id = fullrec.id) |
|||
LEFT JOIN res_partner p on (l.partner_id=p.id) |
|||
LEFT JOIN account_invoice i on (m.id =i.move_id) |
|||
LEFT JOIN account_period per on (per.id=l.period_id) |
|||
JOIN account_journal j on (l.journal_id=j.id) |
|||
WHERE l.id in %s""" |
|||
monster += (" ORDER BY %s" % (order,)) |
|||
try: |
|||
self.cursor.execute(monster, (tuple(move_line_ids),)) |
|||
res= self.cursor.dictfetchall() |
|||
except Exception, exc: |
|||
self.cursor.rollback() |
|||
raise |
|||
return res or [] |
|||
|
|||
def _get_moves_counterparts(self, move_ids, account_id, limit=3): |
|||
if not move_ids: |
|||
return {} |
|||
if not isinstance(move_ids, list): |
|||
move_ids = [move_ids] |
|||
sql = """ |
|||
SELECT account_move.id, |
|||
array_to_string( |
|||
ARRAY(SELECT DISTINCT a.code |
|||
FROM account_move_line m2 |
|||
LEFT JOIN account_account a ON (m2.account_id=a.id) |
|||
WHERE m2.move_id =account_move_line.move_id |
|||
AND m2.account_id<>%s limit %s) , ', ') |
|||
|
|||
FROM account_move |
|||
JOIN account_move_line on (account_move_line.move_id = account_move.id) |
|||
JOIN account_account on (account_move_line.account_id = account_account.id) |
|||
WHERE move_id in %s""" |
|||
|
|||
try: |
|||
self.cursor.execute(sql, (account_id, limit, tuple(move_ids))) |
|||
res= self.cursor.fetchall() |
|||
except Exception, exc: |
|||
self.cursor.rollback() |
|||
raise |
|||
return res and dict(res) or {} |
|||
|
|||
def is_initial_balance_enabled(self, main_filter): |
|||
if main_filter not in ('filter_no', 'filter_year', 'filter_period'): |
|||
return False |
|||
return True |
|||
|
|||
def _get_initial_balance_mode(self, start_period): |
|||
opening_period_selected = self.get_included_opening_period(start_period) |
|||
opening_move_lines = self.periods_contains_move_lines(opening_period_selected) |
|||
if opening_move_lines: |
|||
return 'opening_balance' |
|||
else: |
|||
return 'initial_balance' |
@ -0,0 +1,211 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi, Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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 report import report_sxw |
|||
from tools.translate import _ |
|||
import pooler |
|||
from operator import itemgetter |
|||
from itertools import groupby |
|||
from datetime import datetime |
|||
|
|||
from common_reports import CommonReportHeaderWebkit |
|||
from webkit_parser_header_fix import HeaderFooterTextWebKitParser |
|||
|
|||
class GeneralLedgerWebkit(report_sxw.rml_parse, CommonReportHeaderWebkit): |
|||
|
|||
def __init__(self, cursor, uid, name, context): |
|||
super(GeneralLedgerWebkit, 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((_('GENERAL LEDGER'), company.name, company.currency_id.name)) |
|||
|
|||
footer_date_time = self.formatLang(str(datetime.today()), date_time=True) |
|||
|
|||
self.localcontext.update({ |
|||
'cr': cursor, |
|||
'uid': uid, |
|||
'report_name': _('General Ledger'), |
|||
'display_account': self._get_display_account, |
|||
'display_account_raw': self._get_display_account_raw, |
|||
'filter_form': self._get_filter, |
|||
'target_move': self._get_target_move, |
|||
'initial_balance': self._get_initial_balance, |
|||
'amount_currency': self._get_amount_currency, |
|||
'display_target_move': self._get_display_target_move, |
|||
'accounts': self._get_accounts_br, |
|||
'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 set_context(self, objects, data, ids, report_type=None): |
|||
"""Populate a ledger_lines attribute on each browse record that will be used |
|||
by mako template""" |
|||
new_ids = data['form']['account_ids'] or data['form']['chart_account_id'] |
|||
|
|||
# Account initial balance memoizer |
|||
init_balance_memoizer = {} |
|||
|
|||
# Reading form |
|||
main_filter = self._get_form_param('filter', data, default='filter_no') |
|||
target_move = self._get_form_param('target_move', data, default='all') |
|||
start_date = self._get_form_param('date_from', data) |
|||
stop_date = self._get_form_param('date_to', data) |
|||
do_centralize = self._get_form_param('centralize', data) |
|||
start_period = self.get_start_period_br(data) |
|||
stop_period = self.get_end_period_br(data) |
|||
fiscalyear = self.get_fiscalyear_br(data) |
|||
chart_account = self._get_chart_account_id_br(data) |
|||
|
|||
if main_filter == 'filter_no': |
|||
start_period = self.get_first_fiscalyear_period(fiscalyear) |
|||
stop_period = self.get_last_fiscalyear_period(fiscalyear) |
|||
|
|||
# computation of ledger lines |
|||
if main_filter == 'filter_date': |
|||
start = start_date |
|||
stop = stop_date |
|||
else: |
|||
start = start_period |
|||
stop = stop_period |
|||
|
|||
initial_balance = self.is_initial_balance_enabled(main_filter) |
|||
initial_balance_mode = initial_balance and self._get_initial_balance_mode(start) or False |
|||
|
|||
# Retrieving accounts |
|||
accounts = self.get_all_accounts(new_ids, exclude_type=['view']) |
|||
if initial_balance_mode == 'initial_balance': |
|||
init_balance_memoizer = self._compute_initial_balances(accounts, start, fiscalyear) |
|||
|
|||
ledger_lines_memoizer = self._compute_account_ledger_lines(accounts, init_balance_memoizer, |
|||
main_filter, target_move, start, stop) |
|||
objects = [] |
|||
for account in self.pool.get('account.account').browse(self.cursor, self.uid, accounts): |
|||
if do_centralize and account.centralized and ledger_lines_memoizer.get(account.id): |
|||
account.ledger_lines = self._centralize_lines(main_filter, ledger_lines_memoizer.get(account.id, [])) |
|||
else: |
|||
account.ledger_lines = ledger_lines_memoizer.get(account.id, []) |
|||
account.init_balance = init_balance_memoizer.get(account.id, {}) |
|||
|
|||
objects.append(account) |
|||
|
|||
self.localcontext.update({ |
|||
'fiscalyear': fiscalyear, |
|||
'start_date': start_date, |
|||
'stop_date': stop_date, |
|||
'start_period': start_period, |
|||
'stop_period': stop_period, |
|||
'chart_account': chart_account, |
|||
'initial_balance_mode': initial_balance_mode, |
|||
}) |
|||
|
|||
return super(GeneralLedgerWebkit, self).set_context(objects, data, new_ids, |
|||
report_type=report_type) |
|||
|
|||
def _centralize_lines(self, filter, ledger_lines, context=None): |
|||
""" Group by period in filter mode 'period' or on one line in filter mode 'date' |
|||
ledger_lines parameter is a list of dict built by _get_ledger_lines""" |
|||
def group_lines(lines): |
|||
if not lines: |
|||
return {} |
|||
sums = reduce(lambda line, memo: dict((key, value + memo[key]) for key, value |
|||
in line.iteritems() if key in ('balance', 'debit', 'credit')), lines) |
|||
|
|||
res_lines = { |
|||
'balance': sums['balance'], |
|||
'debit': sums['debit'], |
|||
'credit': sums['credit'], |
|||
'lname': _('Centralized Entries'), |
|||
'account_id': lines[0]['account_id'], |
|||
} |
|||
return res_lines |
|||
|
|||
centralized_lines = [] |
|||
if filter == 'filter_date': |
|||
# by date we centralize all entries in only one line |
|||
centralized_lines.append(group_lines(ledger_lines)) |
|||
|
|||
else: # by period |
|||
# by period we centralize all entries in one line per period |
|||
period_obj = self.pool.get('account.period') |
|||
# we need to sort the lines per period in order to use groupby |
|||
# unique ids of each used period id in lines |
|||
period_ids = list(set([line['lperiod_id'] for line in ledger_lines ])) |
|||
# search on account.period in order to sort them by date_start |
|||
sorted_period_ids = period_obj.search(self.cr, self.uid, |
|||
[('id', 'in', period_ids)], |
|||
order='special desc, date_start', |
|||
context=context) |
|||
sorted_ledger_lines = sorted(ledger_lines, key=lambda x: sorted_period_ids.index(x['lperiod_id'])) |
|||
|
|||
for period_id, lines_per_period_iterator in groupby(sorted_ledger_lines, itemgetter('lperiod_id')): |
|||
lines_per_period = list(lines_per_period_iterator) |
|||
if not lines_per_period: |
|||
continue |
|||
group_per_period = group_lines(lines_per_period) |
|||
group_per_period.update({ |
|||
'lperiod_id': period_id, |
|||
'period_code': lines_per_period[0]['period_code'], # period code is anyway the same on each line per period |
|||
}) |
|||
centralized_lines.append(group_per_period) |
|||
|
|||
return centralized_lines |
|||
|
|||
def _compute_account_ledger_lines(self, accounts_ids, init_balance_memoizer, main_filter, |
|||
target_move, start, stop): |
|||
res = {} |
|||
for acc_id in accounts_ids: |
|||
move_line_ids = self.get_move_lines_ids(acc_id, main_filter, start, stop, target_move) |
|||
if not move_line_ids: |
|||
res[acc_id] = [] |
|||
continue |
|||
|
|||
lines = self._get_ledger_lines(move_line_ids, acc_id) |
|||
res[acc_id] = lines |
|||
return res |
|||
|
|||
def _get_ledger_lines(self, move_line_ids, account_id): |
|||
if not move_line_ids: |
|||
return [] |
|||
res = self._get_move_line_datas(move_line_ids) |
|||
## computing counter part is really heavy in term of ressouces consuption |
|||
## looking for a king of SQL to help me improve it |
|||
move_ids = [x.get('move_id') for x in res] |
|||
counter_parts = self._get_moves_counterparts(move_ids, account_id) |
|||
for line in res: |
|||
line['counterparts'] = counter_parts.get(line.get('move_id'), '') |
|||
return res |
|||
|
|||
|
|||
HeaderFooterTextWebKitParser('report.account.account_report_general_ledger_webkit', |
|||
'account.account', |
|||
'addons/account_financial_report_webkit/report/templates/account_report_general_ledger.mako', |
|||
parser=GeneralLedgerWebkit) |
@ -0,0 +1,238 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi, Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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/>. |
|||
# |
|||
############################################################################## |
|||
import pooler |
|||
|
|||
from collections import defaultdict |
|||
from report import report_sxw |
|||
from datetime import datetime |
|||
from itertools import groupby |
|||
from operator import itemgetter |
|||
from mako.template import Template |
|||
|
|||
from tools.translate import _ |
|||
|
|||
from openerp.osv import osv |
|||
from common_partner_reports import CommonPartnersReportHeaderWebkit |
|||
from webkit_parser_header_fix import HeaderFooterTextWebKitParser |
|||
from openerp.addons.report_webkit import report_helper |
|||
import addons |
|||
|
|||
|
|||
def get_mako_template(obj, *args): |
|||
template_path = addons.get_module_resource(*args) |
|||
return Template(filename=template_path, input_encoding='utf-8') |
|||
|
|||
report_helper.WebKitHelper.get_mako_template = get_mako_template |
|||
|
|||
class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit): |
|||
|
|||
def __init__(self, cursor, uid, name, context): |
|||
super(PartnersOpenInvoicesWebkit, 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((_('OPEN INVOICES REPORT'), company.name, company.currency_id.name)) |
|||
|
|||
footer_date_time = self.formatLang(str(datetime.today()), date_time=True) |
|||
|
|||
self.localcontext.update({ |
|||
'cr': cursor, |
|||
'uid': uid, |
|||
'report_name':_('Open Invoices Report'), |
|||
'display_account_raw': self._get_display_account_raw, |
|||
'filter_form': self._get_filter, |
|||
'target_move': self._get_target_move, |
|||
'amount_currency': self._get_amount_currency, |
|||
'display_partner_account': self._get_display_partner_account, |
|||
'display_target_move': self._get_display_target_move, |
|||
'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 _group_lines_by_currency(self, account_br): |
|||
account_br.grouped_ledger_lines = {} |
|||
if not account_br.ledger_lines: |
|||
return |
|||
for part_id, plane_lines in account_br.ledger_lines.items(): |
|||
account_br.grouped_ledger_lines[part_id] = [] |
|||
plane_lines.sort(key=itemgetter('currency_code')) |
|||
for curr, lines in groupby(plane_lines, key=itemgetter('currency_code')): |
|||
tmp = [x for x in lines] |
|||
account_br.grouped_ledger_lines[part_id].append((curr, tmp)) #I want to reiter many times |
|||
|
|||
def set_context(self, objects, data, ids, report_type=None): |
|||
"""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 |
|||
main_filter = self._get_form_param('filter', data, default='filter_no') |
|||
target_move = self._get_form_param('target_move', data, default='all') |
|||
start_date = self._get_form_param('date_from', data) |
|||
stop_date = self._get_form_param('date_to', data) |
|||
start_period = self.get_start_period_br(data) |
|||
stop_period = self.get_end_period_br(data) |
|||
fiscalyear = self.get_fiscalyear_br(data) |
|||
partner_ids = self._get_form_param('partner_ids', data) |
|||
result_selection = self._get_form_param('result_selection', data) |
|||
date_until = self._get_form_param('until_date', data) |
|||
chart_account = self._get_chart_account_id_br(data) |
|||
group_by_currency = self._get_form_param('group_by_currency', data) |
|||
|
|||
if main_filter == 'filter_no' and fiscalyear: |
|||
start_period = self.get_first_fiscalyear_period(fiscalyear) |
|||
stop_period = self.get_last_fiscalyear_period(fiscalyear) |
|||
|
|||
# Retrieving accounts |
|||
filter_type = ('payable', 'receivable') |
|||
if result_selection == 'customer': |
|||
filter_type = ('receivable',) |
|||
if result_selection == 'supplier': |
|||
filter_type = ('payable',) |
|||
|
|||
account_ids = self.get_all_accounts(new_ids, exclude_type=['view'], only_type=filter_type) |
|||
|
|||
if not account_ids: |
|||
raise osv.except_osv(_('Error'), _('No accounts to print.')) |
|||
|
|||
# computation of ledeger lines |
|||
if main_filter == 'filter_date': |
|||
start = start_date |
|||
stop = stop_date |
|||
else: |
|||
start = start_period |
|||
stop = stop_period |
|||
ledger_lines_memoizer = self._compute_open_transactions_lines(account_ids, |
|||
main_filter, |
|||
target_move, |
|||
start, |
|||
stop, |
|||
date_until, |
|||
partner_filter=partner_ids) |
|||
objects = [] |
|||
for account in self.pool.get('account.account').browse(self.cursor, self.uid, account_ids): |
|||
account.ledger_lines = ledger_lines_memoizer.get(account.id, {}) |
|||
account.init_balance = init_balance_memoizer.get(account.id, {}) |
|||
## we have to compute partner order based on inital balance |
|||
## and ledger line as we may have partner with init bal |
|||
## that are not in ledger line and vice versa |
|||
ledg_lines_pids = ledger_lines_memoizer.get(account.id, {}).keys() |
|||
non_null_init_balances = dict([(ib, amounts) for ib, amounts in account.init_balance.iteritems() |
|||
if amounts['init_balance'] or amounts['init_balance_currency']]) |
|||
init_bal_lines_pids = non_null_init_balances.keys() |
|||
|
|||
account.partners_order = self._order_partners(ledg_lines_pids, init_bal_lines_pids) |
|||
account.ledger_lines = ledger_lines_memoizer.get(account.id, {}) |
|||
if group_by_currency: |
|||
self._group_lines_by_currency(account) |
|||
objects.append(account) |
|||
|
|||
self.localcontext.update({ |
|||
'fiscalyear': fiscalyear, |
|||
'start_date': start_date, |
|||
'stop_date': stop_date, |
|||
'start_period': start_period, |
|||
'stop_period': stop_period, |
|||
'date_until': date_until, |
|||
'partner_ids': partner_ids, |
|||
'chart_account': chart_account, |
|||
}) |
|||
|
|||
return super(PartnersOpenInvoicesWebkit, self).set_context(objects, data, new_ids, |
|||
report_type=report_type) |
|||
|
|||
def _compute_open_transactions_lines(self, accounts_ids, main_filter, target_move, start, stop, date_until=False, partner_filter=False): |
|||
res = defaultdict(dict) |
|||
|
|||
## we check if until date and date stop have the same value |
|||
if main_filter in ('filter_period', 'filter_no'): |
|||
date_stop = stop.date_stop |
|||
date_until_match = (date_stop == date_until) |
|||
|
|||
elif main_filter == 'filter_date': |
|||
date_stop = stop |
|||
date_until_match = (stop == date_until) |
|||
|
|||
else: |
|||
raise osv.except_osv(_('Unsuported filter'), |
|||
_('Filter has to be in filter date, period, or none')) |
|||
|
|||
initial_move_lines_per_account = {} |
|||
if main_filter in ('filter_period', 'filter_no'): |
|||
initial_move_lines_per_account = self._tree_move_line_ids( |
|||
self._partners_initial_balance_line_ids(accounts_ids, |
|||
start, |
|||
partner_filter, |
|||
exclude_reconcile=True, |
|||
force_period_ids=False, |
|||
date_stop=date_stop), key='id') |
|||
|
|||
for account_id in accounts_ids: |
|||
initial_move_lines_ids_per_partner = initial_move_lines_per_account.get(account_id, {}) |
|||
|
|||
# We get the move line ids of the account |
|||
move_line_ids_per_partner = self.get_partners_move_lines_ids(account_id, |
|||
main_filter, |
|||
start, |
|||
stop, |
|||
target_move, |
|||
exclude_reconcile=True, |
|||
partner_filter=partner_filter) |
|||
|
|||
if not initial_move_lines_ids_per_partner and not move_line_ids_per_partner: |
|||
continue |
|||
for partner_id in list(set(initial_move_lines_ids_per_partner.keys() + move_line_ids_per_partner.keys())): |
|||
partner_line_ids = (move_line_ids_per_partner.get(partner_id, []) + |
|||
initial_move_lines_ids_per_partner.get(partner_id, [])) |
|||
|
|||
clearance_line_ids = [] |
|||
if date_until and not date_until_match and partner_line_ids: |
|||
clearance_line_ids = self._get_clearance_move_line_ids(partner_line_ids, date_stop, date_until) |
|||
partner_line_ids += clearance_line_ids |
|||
|
|||
lines = self._get_move_line_datas(list(set(partner_line_ids))) |
|||
for line in lines: |
|||
if line['id'] in initial_move_lines_ids_per_partner.get(partner_id, []): |
|||
line['is_from_previous_periods'] = True |
|||
if line['id'] in clearance_line_ids: |
|||
line['is_clearance_line'] = True |
|||
|
|||
res[account_id][partner_id] = lines |
|||
return res |
|||
|
|||
|
|||
HeaderFooterTextWebKitParser('report.account.account_report_open_invoices_webkit', |
|||
'account.account', |
|||
'addons/account_financial_report_webkit/report/templates/account_report_open_invoices.mako', |
|||
parser=PartnersOpenInvoicesWebkit) |
@ -0,0 +1,90 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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 report import report_sxw |
|||
from tools.translate import _ |
|||
import pooler |
|||
from datetime import datetime |
|||
|
|||
from common_partner_balance_reports import CommonPartnerBalanceReportHeaderWebkit |
|||
from webkit_parser_header_fix import HeaderFooterTextWebKitParser |
|||
|
|||
|
|||
class PartnerBalanceWebkit(report_sxw.rml_parse, CommonPartnerBalanceReportHeaderWebkit): |
|||
|
|||
def __init__(self, cursor, uid, name, context): |
|||
super(PartnerBalanceWebkit, 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((_('PARTNER BALANCE'), company.name, company.currency_id.name)) |
|||
|
|||
footer_date_time = self.formatLang(str(datetime.today()), date_time=True) |
|||
|
|||
self.localcontext.update({ |
|||
'cr': cursor, |
|||
'uid': uid, |
|||
'report_name': _('Partner Balance'), |
|||
'display_account': self._get_display_account, |
|||
'display_account_raw': self._get_display_account_raw, |
|||
'filter_form': self._get_filter, |
|||
'target_move': self._get_target_move, |
|||
'display_target_move': self._get_display_target_move, |
|||
'display_partner_account': self._get_display_partner_account, |
|||
'accounts': self._get_accounts_br, |
|||
'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_initial_balance_mode(self, start_period): |
|||
""" Force computing of initial balance for the partner balance, |
|||
because we cannot use the entries generated by |
|||
OpenERP in the opening period. |
|||
|
|||
OpenERP allows to reconcile move lines between different partners, |
|||
so the generated entries in the opening period are unreliable. |
|||
""" |
|||
return 'initial_balance' |
|||
|
|||
def set_context(self, objects, data, ids, report_type=None): |
|||
"""Populate a ledger_lines attribute on each browse record that will be used |
|||
by mako template""" |
|||
objects, new_ids, context_report_values = self.compute_partner_balance_data(data) |
|||
|
|||
self.localcontext.update(context_report_values) |
|||
return super(PartnerBalanceWebkit, self).set_context(objects, data, new_ids, |
|||
report_type=report_type) |
|||
|
|||
HeaderFooterTextWebKitParser('report.account.account_report_partner_balance_webkit', |
|||
'account.account', |
|||
'addons/account_financial_report_webkit/report/templates/account_report_partner_balance.mako', |
|||
parser=PartnerBalanceWebkit) |
@ -0,0 +1,199 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi, Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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/>. |
|||
# |
|||
############################################################################## |
|||
import pooler |
|||
|
|||
from collections import defaultdict |
|||
from report import report_sxw |
|||
from osv import osv |
|||
from tools.translate import _ |
|||
from datetime import datetime |
|||
|
|||
from common_partner_reports import CommonPartnersReportHeaderWebkit |
|||
from webkit_parser_header_fix import HeaderFooterTextWebKitParser |
|||
|
|||
|
|||
class PartnersLedgerWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit): |
|||
|
|||
def __init__(self, cursor, uid, name, context): |
|||
super(PartnersLedgerWebkit, 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((_('PARTNER LEDGER'), company.name, company.currency_id.name)) |
|||
|
|||
footer_date_time = self.formatLang(str(datetime.today()), date_time=True) |
|||
|
|||
self.localcontext.update({ |
|||
'cr': cursor, |
|||
'uid': uid, |
|||
'report_name':_('Partner Ledger'), |
|||
'display_account_raw': self._get_display_account_raw, |
|||
'filter_form': self._get_filter, |
|||
'target_move': self._get_target_move, |
|||
'initial_balance': self._get_initial_balance, |
|||
'amount_currency': self._get_amount_currency, |
|||
'display_partner_account': self._get_display_partner_account, |
|||
'display_target_move': self._get_display_target_move, |
|||
'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_initial_balance_mode(self, start_period): |
|||
""" Force computing of initial balance for the partner ledger, |
|||
because we cannot use the entries generated by |
|||
OpenERP in the opening period. |
|||
|
|||
OpenERP allows to reconcile move lines between different partners, |
|||
so the generated entries in the opening period are unreliable. |
|||
""" |
|||
return 'initial_balance' |
|||
|
|||
def set_context(self, objects, data, ids, report_type=None): |
|||
"""Populate a ledger_lines attribute on each browse record that will be used |
|||
by mako template""" |
|||
new_ids = data['form']['chart_account_id'] |
|||
|
|||
# account partner memoizer |
|||
# Reading form |
|||
main_filter = self._get_form_param('filter', data, default='filter_no') |
|||
target_move = self._get_form_param('target_move', data, default='all') |
|||
start_date = self._get_form_param('date_from', data) |
|||
stop_date = self._get_form_param('date_to', data) |
|||
start_period = self.get_start_period_br(data) |
|||
stop_period = self.get_end_period_br(data) |
|||
fiscalyear = self.get_fiscalyear_br(data) |
|||
partner_ids = self._get_form_param('partner_ids', data) |
|||
result_selection = self._get_form_param('result_selection', data) |
|||
chart_account = self._get_chart_account_id_br(data) |
|||
|
|||
if main_filter == 'filter_no' and fiscalyear: |
|||
start_period = self.get_first_fiscalyear_period(fiscalyear) |
|||
stop_period = self.get_last_fiscalyear_period(fiscalyear) |
|||
|
|||
# Retrieving accounts |
|||
filter_type = ('payable', 'receivable') |
|||
if result_selection == 'customer': |
|||
filter_type = ('receivable',) |
|||
if result_selection == 'supplier': |
|||
filter_type = ('payable',) |
|||
|
|||
accounts = self.get_all_accounts(new_ids, exclude_type=['view'], |
|||
only_type=filter_type) |
|||
|
|||
if not accounts: |
|||
raise osv.except_osv(_('Error'), _('No accounts to print.')) |
|||
|
|||
if main_filter == 'filter_date': |
|||
start = start_date |
|||
stop = stop_date |
|||
else: |
|||
start = start_period |
|||
stop = stop_period |
|||
|
|||
# when the opening period is included in the selected range of periods and |
|||
# the opening period contains move lines, we must not compute the initial balance from previous periods |
|||
# but only display the move lines of the opening period |
|||
# we identify them as : |
|||
# - 'initial_balance' means compute the sums of move lines from previous periods |
|||
# - 'opening_balance' means display the move lines of the opening period |
|||
init_balance = main_filter in ('filter_no', 'filter_period') |
|||
initial_balance_mode = init_balance and self._get_initial_balance_mode(start) or False |
|||
|
|||
initial_balance_lines = {} |
|||
if initial_balance_mode == 'initial_balance': |
|||
initial_balance_lines = self._compute_partners_initial_balances(accounts, |
|||
start_period, |
|||
partner_filter=partner_ids, |
|||
exclude_reconcile=False) |
|||
|
|||
ledger_lines = self._compute_partner_ledger_lines(accounts, |
|||
main_filter, |
|||
target_move, |
|||
start, |
|||
stop, |
|||
partner_filter=partner_ids) |
|||
objects = [] |
|||
for account in self.pool.get('account.account').browse(self.cursor, self.uid, accounts): |
|||
account.ledger_lines = ledger_lines.get(account.id, {}) |
|||
account.init_balance = initial_balance_lines.get(account.id, {}) |
|||
## we have to compute partner order based on inital balance |
|||
## and ledger line as we may have partner with init bal |
|||
## that are not in ledger line and vice versa |
|||
ledg_lines_pids = ledger_lines.get(account.id, {}).keys() |
|||
if initial_balance_mode: |
|||
non_null_init_balances = dict([(ib, amounts) for ib, amounts in account.init_balance.iteritems() |
|||
if amounts['init_balance'] or amounts['init_balance_currency']]) |
|||
init_bal_lines_pids = non_null_init_balances.keys() |
|||
else: |
|||
account.init_balance = {} |
|||
init_bal_lines_pids = [] |
|||
|
|||
account.partners_order = self._order_partners(ledg_lines_pids, init_bal_lines_pids) |
|||
objects.append(account) |
|||
|
|||
self.localcontext.update({ |
|||
'fiscalyear': fiscalyear, |
|||
'start_date': start_date, |
|||
'stop_date': stop_date, |
|||
'start_period': start_period, |
|||
'stop_period': stop_period, |
|||
'partner_ids': partner_ids, |
|||
'chart_account': chart_account, |
|||
'initial_balance_mode': initial_balance_mode, |
|||
}) |
|||
|
|||
return super(PartnersLedgerWebkit, self).set_context(objects, data, new_ids, |
|||
report_type=report_type) |
|||
|
|||
def _compute_partner_ledger_lines(self, accounts_ids, main_filter, target_move, start, stop, partner_filter=False): |
|||
res = defaultdict(dict) |
|||
|
|||
for acc_id in accounts_ids: |
|||
move_line_ids = self.get_partners_move_lines_ids(acc_id, |
|||
main_filter, |
|||
start, |
|||
stop, |
|||
target_move, |
|||
exclude_reconcile=False, |
|||
partner_filter=partner_filter) |
|||
if not move_line_ids: |
|||
continue |
|||
for partner_id in move_line_ids: |
|||
partner_line_ids = move_line_ids.get(partner_id, []) |
|||
lines = self._get_move_line_datas(list(set(partner_line_ids))) |
|||
res[acc_id][partner_id] = lines |
|||
return res |
|||
|
|||
|
|||
HeaderFooterTextWebKitParser('report.account.account_report_partners_ledger_webkit', |
|||
'account.account', |
|||
'addons/account_financial_report_webkit/report/templates/account_report_partners_ledger.mako', |
|||
parser=PartnersLedgerWebkit) |
@ -0,0 +1,115 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import pooler |
|||
|
|||
from report import report_sxw |
|||
from tools.translate import _ |
|||
from datetime import datetime |
|||
from common_balance_reports import CommonBalanceReportHeaderWebkit |
|||
from webkit_parser_header_fix import HeaderFooterTextWebKitParser |
|||
|
|||
|
|||
class ProfitLossWebkit(report_sxw.rml_parse, CommonBalanceReportHeaderWebkit): |
|||
|
|||
def __init__(self, cursor, uid, name, context): |
|||
super(ProfitLossWebkit, 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((_('PROFIT AND LOSS'), company.name, company.currency_id.name)) |
|||
|
|||
footer_date_time = self.formatLang(str(datetime.today()), date_time=True) |
|||
|
|||
self.localcontext.update({ |
|||
'cr': cursor, |
|||
'uid': uid, |
|||
'report_name': _('Profit and Loss'), |
|||
'display_account': self._get_display_account, |
|||
'display_account_raw': self._get_display_account_raw, |
|||
'filter_form': self._get_filter, |
|||
'target_move': self._get_target_move, |
|||
'display_target_move': self._get_display_target_move, |
|||
'accounts': self._get_accounts_br, |
|||
'numbers_display': self._get_numbers_display, |
|||
'level_print': self._get_level_print, |
|||
'level_bold': self._get_level_bold, |
|||
'level_italic': self._get_level_italic, |
|||
'level_size': self._get_level_size, |
|||
'level_underline': self._get_level_underline, |
|||
'level_uppercase': self._get_level_uppercase, |
|||
'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_level_print(self, data, level): |
|||
return self._get_form_param("level%s_print" % (level,), data) |
|||
|
|||
def _get_level_bold(self, data, level): |
|||
return self._get_form_param("level%s_bold" % (level,), data) |
|||
|
|||
def _get_level_italic(self, data, level): |
|||
return self._get_form_param("level%s_italic" % (level,), data) |
|||
|
|||
def _get_level_size(self, data, level): |
|||
return self._get_form_param("level%s_size" % (level,), data) |
|||
|
|||
def _get_level_underline(self, data, level): |
|||
return self._get_form_param("level%s_underline" % (level,), data) |
|||
|
|||
def _get_level_uppercase(self, data, level): |
|||
return self._get_form_param("level%s_uppercase" % (level,), data) |
|||
|
|||
def _update_levels(self, objects): |
|||
# start leveling from 0 |
|||
levels = [account['current']['level'] for account in objects] |
|||
min_level = min(levels) |
|||
|
|||
for account in objects: |
|||
account['current']['level'] -= min_level |
|||
return objects |
|||
|
|||
def set_context(self, objects, data, ids, report_type=None): |
|||
"""Populate a ledger_lines attribute on each browse record that will be used |
|||
by mako template""" |
|||
objects, new_ids, context_report_values = self.compute_balance_data(data, filter_report_type=['expense', 'income']) |
|||
|
|||
objects = self._update_levels(objects) |
|||
|
|||
self.localcontext.update(context_report_values) |
|||
|
|||
return super(ProfitLossWebkit, self).set_context(objects, data, new_ids, |
|||
report_type=report_type) |
|||
|
|||
HeaderFooterTextWebKitParser('report.account.account_report_profit_loss_webkit', |
|||
'account.account', |
|||
'addons/account_financial_report_webkit/report/templates/account_report_profit_loss.mako', |
|||
parser=ProfitLossWebkit) |
@ -0,0 +1,104 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<!-- we do not use report tag has we can not set header ref --> |
|||
<record id="account_report_general_ledger_webkit" model="ir.actions.report.xml"> |
|||
<field name="report_type">webkit</field> |
|||
<field name="report_name">account.account_report_general_ledger_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">General Ledger Webkit</field> |
|||
<field name="report_rml">account_financial_report_webkit/report/templates/account_report_general_ledger.mako</field> |
|||
<field name="report_file">account_financial_report_webkit/report/templates/account_report_general_ledger.mako</field> |
|||
<field name="webkit_header" ref="financial_landscape_header"/> |
|||
</record> |
|||
<!-- waiting the fix |
|||
<report auto="False" |
|||
id="account_report_partner_ledger_webkit" |
|||
model="account.account" |
|||
name="account.account_report_partner_ledger_webkit" |
|||
file="account_financial_report_webkit/report/templates/account_report_partner_ledger.mako" |
|||
string="General Ledger Webkit" |
|||
report_type="webkit"/> --> |
|||
|
|||
<!-- we do not use report tag has we can not set header ref --> |
|||
<record id="account_report_partners_ledger_webkit" model="ir.actions.report.xml"> |
|||
<field name="report_type">webkit</field> |
|||
<field name="report_name">account.account_report_partners_ledger_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">Partner Ledger Webkit</field> |
|||
<field name="report_rml">account_financial_report_webkit/report/templates/account_report_partners_ledger.mako</field> |
|||
<field name="report_file">account_financial_report_webkit/report/templates/account_report_partners_ledger.mako</field> |
|||
<field name="webkit_header" ref="financial_landscape_header"/> |
|||
</record> |
|||
|
|||
<record id="account_report_trial_balance_webkit" model="ir.actions.report.xml"> |
|||
<field name="report_type">webkit</field> |
|||
<field name="report_name">account.account_report_trial_balance_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">Trial Balance Webkit</field> |
|||
<field name="report_rml">account_financial_report_webkit/report/templates/account_report_trial_balance.mako</field> |
|||
<field name="report_file">account_financial_report_webkit/report/templates/account_report_trial_balance.mako</field> |
|||
<field name="webkit_header" ref="financial_portrait_header"/> |
|||
</record> |
|||
|
|||
<record id="account_report_partner_balance_webkit" model="ir.actions.report.xml"> |
|||
<field name="report_type">webkit</field> |
|||
<field name="report_name">account.account_report_partner_balance_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">Partner Balance Webkit</field> |
|||
<field name="report_rml">account_financial_report_webkit/report/templates/account_report_partner_balance.mako</field> |
|||
<field name="report_file">account_financial_report_webkit/report/templates/account_report_partner_balance.mako</field> |
|||
<field name="webkit_header" ref="financial_portrait_header"/> |
|||
</record> |
|||
|
|||
<record id="account_report_open_invoices_webkit" model="ir.actions.report.xml"> |
|||
<field name="report_type">webkit</field> |
|||
<field name="report_name">account.account_report_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">Open Invoices Report</field> |
|||
<field name="report_rml">account_financial_report_webkit/report/templates/account_report_open_invoices.mako</field> |
|||
<field name="report_file">account_financial_report_webkit/report/templates/account_report_open_invoices.mako</field> |
|||
<field name="webkit_header" ref="financial_landscape_header"/> |
|||
</record> |
|||
|
|||
<!--<record id="account_report_profit_loss_webkit" model="ir.actions.report.xml">--> |
|||
<!--<field name="report_type">webkit</field>--> |
|||
<!--<field name="report_name">account.account_report_profit_loss_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">Profit and Loss Webkit</field>--> |
|||
<!--<field name="report_rml">account_financial_report_webkit/report/templates/account_report_profit_loss.mako</field>--> |
|||
<!--<field name="report_file">account_financial_report_webkit/report/templates/account_report_profit_loss.mako</field>--> |
|||
<!--<field name="webkit_header" ref="financial_portrait_header"/>--> |
|||
<!--</record>--> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,232 @@ |
|||
<!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; |
|||
} |
|||
${css} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
<%! |
|||
def amount(text): |
|||
return text.replace('-', '‑') # replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers) |
|||
%> |
|||
|
|||
<%setLang(user.context_lang)%> |
|||
|
|||
<% |
|||
initial_balance_text = {'initial_balance': _('Computed'), 'opening_balance': _('Opening Entries'), False: _('No')} |
|||
%> |
|||
|
|||
<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">${_('Accounts Filter')}</div> |
|||
<div class="act_as_cell">${_('Target Moves')}</div> |
|||
<div class="act_as_cell">${_('Initial Balance')}</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"> |
|||
%if accounts(data): |
|||
${', '.join([account.code for account in accounts(data)])} |
|||
%else: |
|||
${_('All')} |
|||
%endif |
|||
|
|||
</div> |
|||
<div class="act_as_cell">${ display_target_move(data) }</div> |
|||
<div class="act_as_cell">${ initial_balance_text[initial_balance_mode] }</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- we use div with css instead of table for tabular data because div do not cut rows at half at page breaks --> |
|||
%for account in objects: |
|||
<% |
|||
display_initial_balance = account.init_balance and (account.init_balance.get('debit', 0.0) != 0.0 or account.init_balance.get('credit', 0.0) != 0.0) |
|||
display_ledger_lines = account.ledger_lines |
|||
%> |
|||
%if display_account_raw(data) == 'all' or (display_ledger_lines or display_initial_balance): |
|||
<% |
|||
cumul_debit = 0.0 |
|||
cumul_credit = 0.0 |
|||
cumul_balance = 0.0 |
|||
cumul_balance_curr = 0.0 |
|||
%> |
|||
<div class="act_as_table list_table" style="margin-top: 10px;"> |
|||
|
|||
<div class="act_as_caption account_title"> |
|||
${account.code} - ${account.name} |
|||
</div> |
|||
<div class="act_as_thead"> |
|||
<div class="act_as_row labels"> |
|||
## date |
|||
<div class="act_as_cell first_column" style="width: 50px;">${_('Date')}</div> |
|||
## period |
|||
<div class="act_as_cell" style="width: 50px;">${_('Period')}</div> |
|||
## move |
|||
<div class="act_as_cell" style="width: 60px;">${_('Entry')}</div> |
|||
## journal |
|||
<div class="act_as_cell" style="width: 70px;">${_('Journal')}</div> |
|||
## account code |
|||
<div class="act_as_cell" style="width: 65px;">${_('Account')}</div> |
|||
## partner |
|||
<div class="act_as_cell" style="width: 120px;">${_('Partner')}</div> |
|||
## label |
|||
<div class="act_as_cell" style="width: 200px;">${_('Label')}</div> |
|||
## counterpart |
|||
<div class="act_as_cell" style="width: 100px;">${_('Counter part')}</div> |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 75px;">${_('Debit')}</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 75px;">${_('Credit')}</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="width: 75px;">${_('Cumul. Bal.')}</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
<div class="act_as_cell amount sep_left" style="width: 75px;">${_('Curr. Balance')}</div> |
|||
## curency code |
|||
<div class="act_as_cell amount" style="width: 30px; text-align: right;">${_('Curr.')}</div> |
|||
%endif |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="act_as_tbody"> |
|||
%if display_initial_balance: |
|||
<% |
|||
cumul_debit = account.init_balance.get('debit') or 0.0 |
|||
cumul_credit = account.init_balance.get('credit') or 0.0 |
|||
cumul_balance = account.init_balance.get('init_balance') or 0.0 |
|||
cumul_balance_curr = account.init_balance.get('init_balance_currency') or 0.0 |
|||
%> |
|||
<div class="act_as_row initial_balance"> |
|||
## date |
|||
<div class="act_as_cell first_column"></div> |
|||
## period |
|||
<div class="act_as_cell"></div> |
|||
## move |
|||
<div class="act_as_cell"></div> |
|||
## journal |
|||
<div class="act_as_cell"></div> |
|||
## account code |
|||
<div class="act_as_cell"></div> |
|||
## partner |
|||
<div class="act_as_cell"></div> |
|||
## label |
|||
<div class="act_as_cell">${_('Initial Balance')}</div> |
|||
## counterpart |
|||
<div class="act_as_cell"></div> |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(account.init_balance.get('debit')) | amount}</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(account.init_balance.get('credit')) | amount}</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${formatLang(cumul_balance) | amount }</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
<div class="act_as_cell amount sep_left">${formatLang(cumul_balance_curr) | amount }</div> |
|||
## curency code |
|||
<div class="act_as_cell amount"></div> |
|||
%endif |
|||
|
|||
</div> |
|||
%endif |
|||
%for line in account.ledger_lines: |
|||
<% |
|||
cumul_debit += line.get('debit') or 0.0 |
|||
cumul_credit += line.get('credit') or 0.0 |
|||
cumul_balance_curr += line.get('amount_currency') or 0.0 |
|||
cumul_balance += line.get('balance') or 0.0 |
|||
label_elements = [line.get('lname') or ''] |
|||
if line.get('invoice_number'): |
|||
label_elements.append("(%s)" % (line['invoice_number'],)) |
|||
label = ' '.join(label_elements) |
|||
%> |
|||
|
|||
<div class="act_as_row lines"> |
|||
## date |
|||
<div class="act_as_cell first_column">${formatLang(line.get('ldate') or '', date=True)}</div> |
|||
## period |
|||
<div class="act_as_cell">${line.get('period_code') or ''}</div> |
|||
## move |
|||
<div class="act_as_cell">${line.get('move_name') or ''}</div> |
|||
## journal |
|||
<div class="act_as_cell">${line.get('jcode') or ''}</div> |
|||
## account code |
|||
<div class="act_as_cell">${account.code}</div> |
|||
## partner |
|||
<div class="act_as_cell overflow_ellipsis">${line.get('partner_name') or ''}</div> |
|||
## label |
|||
<div class="act_as_cell">${label}</div> |
|||
## counterpart |
|||
<div class="act_as_cell">${line.get('counterparts') or ''}</div> |
|||
## debit |
|||
<div class="act_as_cell amount">${ formatLang(line.get('debit', 0.0)) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${ formatLang(line.get('credit', 0.0)) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${ formatLang(cumul_balance) | amount }</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
<div class="act_as_cell amount sep_left">${formatLang(line.get('amount_currency') or 0.0) | amount }</div> |
|||
## curency code |
|||
<div class="act_as_cell amount" style="text-align: right;">${line.get('currency_code') or ''}</div> |
|||
%endif |
|||
</div> |
|||
%endfor |
|||
</div> |
|||
<div class="act_as_table list_table"> |
|||
<div class="act_as_row labels" style="font-weight: bold;"> |
|||
## date |
|||
<div class="act_as_cell first_column" style="width: 350px;">${account.code} - ${account.name}</div> |
|||
<div class="act_as_cell" style="width: 365px;">${_("Cumulated Balance on Account")}</div> |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 75px;">${ formatLang(cumul_debit) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 75px;">${ formatLang(cumul_credit) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="width: 75px; padding-right: 1px;">${ formatLang(cumul_balance) | amount }</div> |
|||
%if amount_currency(data): |
|||
%if account.currency_id: |
|||
## currency balance |
|||
<div class="act_as_cell amount sep_left" style="width: 75px;">${formatLang(cumul_balance_curr) | amount }</div> |
|||
%else: |
|||
<div class="act_as_cell amount sep_left" style="width: 75px;">-</div> |
|||
%endif |
|||
## curency code |
|||
<div class="act_as_cell amount" style="width: 30px; text-align: right;"></div> |
|||
%endif |
|||
</div> |
|||
</div> |
|||
</div> |
|||
%endif |
|||
%endfor |
|||
</body> |
|||
</html> |
@ -0,0 +1,85 @@ |
|||
<!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; |
|||
} |
|||
|
|||
.clearance_line { |
|||
font-style: italic; |
|||
} |
|||
${css} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
|
|||
<% import addons %> |
|||
<% template1 = helper.get_mako_template('account_financial_report_webkit','report', 'templates', 'open_invoices_inclusion.mako.html') %> |
|||
<% context.lookup.put_template('open_invoices_inclusion.mako.html', template1) %> |
|||
<% template2 = helper.get_mako_template('account_financial_report_webkit','report', 'templates', 'grouped_by_curr_open_invoices_inclusion.mako.html') %> |
|||
<% context.lookup.put_template('grouped_by_curr_open_invoices_inclusion.mako.html', template2) %> |
|||
<%setLang(user.context_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 acc in objects: |
|||
%if hasattr(acc, 'grouped_ledger_lines'): |
|||
<% fl = formatLang %> |
|||
<%include file="grouped_by_curr_open_invoices_inclusion.mako.html" args="account=acc,formatLang=fl"/> |
|||
%else: |
|||
<% fl = formatLang %> |
|||
<%include file="open_invoices_inclusion.mako.html" args="account=acc,formatLang=fl"/> |
|||
%endif |
|||
%endfor |
|||
</body> |
|||
</html> |
@ -0,0 +1,290 @@ |
|||
<!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"> |
|||
${css} |
|||
|
|||
.list_table .act_as_row { |
|||
margin-top: 10px; |
|||
margin-bottom: 10px; |
|||
font-size:10px; |
|||
} |
|||
|
|||
.account_line { |
|||
font-weight: bold; |
|||
font-size: 15px; |
|||
background-color:#F0F0F0; |
|||
} |
|||
|
|||
.account_line .act_as_cell { |
|||
height: 30px; |
|||
vertical-align: bottom; |
|||
} |
|||
|
|||
</style> |
|||
</head> |
|||
<body> |
|||
<%! |
|||
def amount(text): |
|||
return text.replace('-', '‑') # replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers) |
|||
|
|||
def display_line(all_comparison_lines): |
|||
return any([line.get('balance') for line in all_comparison_lines]) |
|||
%> |
|||
|
|||
<%setLang(user.context_lang)%> |
|||
|
|||
<% |
|||
initial_balance_text = {'initial_balance': _('Computed'), 'opening_balance': _('Opening Entries'), False: _('No')} |
|||
%> |
|||
|
|||
<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">${_('Accounts Filter')}</div> |
|||
<div class="act_as_cell">${_('Partners Filter')}</div> |
|||
<div class="act_as_cell">${_('Target Moves')}</div> |
|||
<div class="act_as_cell">${_('Initial Balance')}</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"> |
|||
%if accounts(data): |
|||
${', '.join([account.code for account in accounts(data)])} |
|||
%else: |
|||
${_('All')} |
|||
%endif |
|||
</div> |
|||
<div class="act_as_cell">${display_partner_account(data)}</div> |
|||
<div class="act_as_cell">${ display_target_move(data) }</div> |
|||
<div class="act_as_cell">${ initial_balance_text[initial_balance_mode] }</div> |
|||
</div> |
|||
</div> |
|||
|
|||
%for index, params in enumerate(comp_params): |
|||
<div class="act_as_table data_table"> |
|||
<div class="act_as_row"> |
|||
<div class="act_as_cell">${_('Comparison %s') % (index + 1,)} (${"C%s" % (index + 1,)})</div> |
|||
<div class="act_as_cell"> |
|||
%if params['comparison_filter'] == 'filter_date': |
|||
${_('Dates Filter:')} ${formatLang(params['start'], date=True) } - ${formatLang(params['stop'], date=True) } |
|||
%elif params['comparison_filter'] == 'filter_period': |
|||
${_('Periods Filter:')} ${params['start'].name} - ${params['stop'].name} |
|||
%else: |
|||
${_('Fiscal Year :')} ${params['fiscalyear'].name} |
|||
%endif |
|||
</div> |
|||
<div class="act_as_cell">${ _('Initial Balance:')} ${ initial_balance_text[params['initial_balance_mode']] }</div> |
|||
</div> |
|||
</div> |
|||
%endfor |
|||
|
|||
%for current_account in objects: |
|||
<% |
|||
partners_order = current_account.partners_order |
|||
|
|||
# do not display accounts without partners |
|||
if not partners_order: |
|||
continue |
|||
|
|||
comparisons = current_account.comparisons |
|||
|
|||
# in multiple columns mode, we do not want to print accounts without any rows |
|||
if comparison_mode in ('single', 'multiple'): |
|||
all_comparison_lines = [comp['partners_amounts'][partner_id[1]] |
|||
for partner_id in partners_order |
|||
for comp in comparisons] |
|||
if not display_line(all_comparison_lines): |
|||
continue |
|||
|
|||
current_partner_amounts = current_account.partners_amounts |
|||
|
|||
total_initial_balance = 0.0 |
|||
total_debit = 0.0 |
|||
total_credit = 0.0 |
|||
total_balance = 0.0 |
|||
if comparison_mode in ('single', 'multiple'): |
|||
comparison_total = {} |
|||
for i, comp in enumerate(comparisons): |
|||
comparison_total[i] = {'balance': 0.0} |
|||
%> |
|||
|
|||
<div class="account_title bg" style="margin-top: 20px; font-size: 12px; width: 690px;">${current_account.code} - ${current_account.name}</div> |
|||
|
|||
<div class="act_as_table list_table"> |
|||
|
|||
<div class="act_as_thead"> |
|||
<div class="act_as_row labels"> |
|||
## account name |
|||
<div class="act_as_cell" style="width: 80px;">${_('Account / Partner Name')}</div> |
|||
## code |
|||
<div class="act_as_cell first_column" style="width: 20px;">${_('Code / Ref')}</div> |
|||
%if comparison_mode == 'no_comparison': |
|||
%if initial_balance_mode: |
|||
## initial balance |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Initial Balance')}</div> |
|||
%endif |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Debit')}</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Credit')}</div> |
|||
%endif |
|||
## balance |
|||
<div class="act_as_cell amount" style="width: 30px;"> |
|||
%if comparison_mode == 'no_comparison' or not fiscalyear: |
|||
${_('Balance')} |
|||
%else: |
|||
${_('Balance %s') % (fiscalyear.name,)} |
|||
%endif |
|||
</div> |
|||
%if comparison_mode in ('single', 'multiple'): |
|||
%for index in range(nb_comparison): |
|||
<div class="act_as_cell amount" style="width: 30px;"> |
|||
%if comp_params[index]['comparison_filter'] == 'filter_year' and comp_params[index].get('fiscalyear', False): |
|||
${_('Balance %s') % (comp_params[index]['fiscalyear'].name,)} |
|||
%else: |
|||
${_('Balance C%s') % (index + 1,)} |
|||
%endif |
|||
</div> |
|||
%if comparison_mode == 'single': ## no diff in multiple comparisons because it shows too data |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Difference')}</div> |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('% Difference')}</div> |
|||
%endif |
|||
%endfor |
|||
%endif |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="act_as_tbody"> |
|||
|
|||
%for (partner_code_name, partner_id, partner_ref, partner_name) in partners_order: |
|||
<% |
|||
partner = current_partner_amounts.get(partner_id, {}) |
|||
|
|||
# in single mode, we have to display all the partners |
|||
# even if their balance is 0.0 because the initial balance |
|||
# should match with the previous year closings |
|||
|
|||
# in multiple columns mode, we do not want to print partners |
|||
# which have a balance at 0.0 in each comparison column |
|||
if comparison_mode in ('single', 'multiple'): |
|||
all_comparison_lines = [comp['partners_amounts'][partner_id] |
|||
for comp in comparisons |
|||
if comp['partners_amounts'].get(partner_id)] |
|||
if not display_line(all_comparison_lines): |
|||
continue |
|||
|
|||
total_initial_balance += partner.get('init_balance', 0.0) |
|||
total_debit += partner.get('debit', 0.0) |
|||
total_credit += partner.get('credit', 0.0) |
|||
total_balance += partner.get('balance', 0.0) |
|||
%> |
|||
<div class="act_as_row lines"> |
|||
<div class="act_as_cell">${partner_name if partner_name else _('Unallocated') }</div> |
|||
<div class="act_as_cell first_column">${partner_ref if partner_ref else ''}</div> |
|||
%if comparison_mode == 'no_comparison': |
|||
%if initial_balance_mode: |
|||
<div class="act_as_cell amount">${formatLang(partner.get('init_balance', 0.0)) | amount}</div> |
|||
%endif |
|||
<div class="act_as_cell amount">${formatLang(partner.get('debit', 0.0)) | amount}</div> |
|||
<div class="act_as_cell amount">${formatLang(partner.get('credit', 0.0)) | amount}</div> |
|||
%endif |
|||
<div class="act_as_cell amount">${formatLang(partner['balance'] if partner else 0.0) | amount}</div> |
|||
|
|||
%if comparison_mode in ('single', 'multiple'): |
|||
%for i, comp in enumerate(comparisons): |
|||
<% |
|||
comp_partners = comp['partners_amounts'] |
|||
balance = diff = percent_diff = 0 |
|||
if comp_partners.get(partner_id): |
|||
balance = comp_partners[partner_id]['balance'] |
|||
diff = comp_partners[partner_id]['diff'] |
|||
percent_diff = comp_partners[partner_id]['percent_diff'] |
|||
comparison_total[i]['balance'] += balance |
|||
%> |
|||
<div class="act_as_cell amount">${formatLang(balance) | amount}</div> |
|||
%if comparison_mode == 'single': ## no diff in multiple comparisons because it shows too data |
|||
<div class="act_as_cell amount">${formatLang(diff) | amount}</div> |
|||
<div class="act_as_cell amount"> |
|||
%if percent_diff is False: |
|||
${ '-' } |
|||
%else: |
|||
${int(round(percent_diff)) | amount} % |
|||
%endif |
|||
</div> |
|||
%endif |
|||
%endfor |
|||
%endif |
|||
</div> |
|||
%endfor |
|||
|
|||
</div> |
|||
<div class="act_as_tfoot" style="margin-top:5px;"> |
|||
<div class="act_as_row labels" style="font-weight: bold; font-size: 11x;"> |
|||
## account name |
|||
<div class="act_as_cell">${current_account.name}</div> |
|||
## code |
|||
<div class="act_as_cell first_column">${current_account.code}</div> |
|||
%if comparison_mode == 'no_comparison': |
|||
%if initial_balance_mode: |
|||
## opening balance |
|||
<div class="act_as_cell amount">${formatLang(total_initial_balance) | amount}</div> |
|||
%endif |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(total_debit) | amount}</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(total_credit and total_credit * -1 or 0.0) | amount}</div> |
|||
%endif |
|||
## balance |
|||
<div class="act_as_cell amount">${formatLang(total_balance) | amount}</div> |
|||
|
|||
%if comparison_mode in ('single', 'multiple'): |
|||
%for i, comp in enumerate(comparisons): |
|||
<% |
|||
comp_account = comp['account'] |
|||
diffs = compute_diff(total_balance, comparison_total[i]['balance']) |
|||
%> |
|||
<div class="act_as_cell amount">${formatLang(comparison_total[i]['balance']) | amount}</div> |
|||
%if comparison_mode == 'single': ## no diff in multiple comparisons because it shows too data |
|||
<div class="act_as_cell amount">${formatLang(diffs['diff']) | amount}</div> |
|||
<div class="act_as_cell amount"> |
|||
%if diffs['percent_diff'] is False: |
|||
${ '-' } |
|||
%else: |
|||
${int(round(diffs['percent_diff'])) | amount} % |
|||
%endif |
|||
</div> |
|||
%endif |
|||
%endfor |
|||
%endif |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
%endfor |
|||
|
|||
</body> |
|||
</html> |
@ -0,0 +1,281 @@ |
|||
<!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; |
|||
} |
|||
|
|||
${css} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
<%! |
|||
def amount(text): |
|||
return text.replace('-', '‑') # replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers) |
|||
%> |
|||
|
|||
<%setLang(user.context_lang)%> |
|||
|
|||
<% |
|||
initial_balance_text = {'initial_balance': _('Computed'), 'opening_balance': _('Opening Entries'), False: _('No')} |
|||
%> |
|||
|
|||
<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">${_('Accounts Filter')}</div> |
|||
<div class="act_as_cell">${_('Target Moves')}</div> |
|||
<div class="act_as_cell">${_('Initial Balance')}</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"> |
|||
%if partner_ids: |
|||
${_('Custom Filter')} |
|||
%else: |
|||
${ display_partner_account(data) } |
|||
%endif |
|||
</div> |
|||
<div class="act_as_cell">${ display_target_move(data) }</div> |
|||
<div class="act_as_cell">${ initial_balance_text[initial_balance_mode] }</div> |
|||
</div> |
|||
</div> |
|||
|
|||
%for account in objects: |
|||
%if account.ledger_lines or account.init_balance: |
|||
<% |
|||
if not account.partners_order: |
|||
continue |
|||
account_total_debit = 0.0 |
|||
account_total_credit = 0.0 |
|||
account_balance_cumul = 0.0 |
|||
account_balance_cumul_curr = 0.0 |
|||
%> |
|||
|
|||
<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 account.partners_order: |
|||
<% |
|||
total_debit = 0.0 |
|||
total_credit = 0.0 |
|||
cumul_balance = 0.0 |
|||
cumul_balance_curr = 0.0 |
|||
|
|||
part_cumul_balance = 0.0 |
|||
part_cumul_balance_curr = 0.0 |
|||
%> |
|||
<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: 50px;">${_('Date')}</div> |
|||
## period |
|||
<div class="act_as_cell" style="width: 70px;">${_('Period')}</div> |
|||
## move |
|||
<div class="act_as_cell" style="width: 70px;">${_('Entry')}</div> |
|||
## journal |
|||
<div class="act_as_cell" style="width: 70px;">${_('Journal')}</div> |
|||
## partner |
|||
<div class="act_as_cell" style="width: 60px;">${_('Partner')}</div> |
|||
## label |
|||
<div class="act_as_cell" style="width: 310px;">${_('Label')}</div> |
|||
## reconcile |
|||
<div class="act_as_cell" style="width: 80px;">${_('Rec.')}</div> |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Debit')}</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Credit')}</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Cumul. Bal.')}</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
<div class="act_as_cell amount sep_left" style="width: 80px;">${_('Curr. Balance')}</div> |
|||
## curency code |
|||
<div class="act_as_cell amount" style="width: 30px; text-align: right;">${_('Curr.')}</div> |
|||
%endif |
|||
</div> |
|||
</div> |
|||
<div class="act_as_tbody"> |
|||
<% |
|||
total_debit = account.init_balance.get(p_id, {}).get('debit') or 0.0 |
|||
total_credit = account.init_balance.get(p_id, {}).get('credit') or 0.0 |
|||
%> |
|||
%if initial_balance_mode and (total_debit or total_credit): |
|||
<% |
|||
part_cumul_balance = account.init_balance.get(p_id, {}).get('init_balance') or 0.0 |
|||
part_cumul_balance_curr = account.init_balance.get(p_id, {}).get('init_balance_currency') or 0.0 |
|||
balance_forward_currency = account.init_balance.get(p_id, {}).get('currency_name') or '' |
|||
|
|||
cumul_balance += part_cumul_balance |
|||
cumul_balance_curr += part_cumul_balance_curr |
|||
%> |
|||
<div class="act_as_row initial_balance"> |
|||
## date |
|||
<div class="act_as_cell first_column"></div> |
|||
## period |
|||
<div class="act_as_cell"></div> |
|||
## move |
|||
<div class="act_as_cell"></div> |
|||
## journal |
|||
<div class="act_as_cell"></div> |
|||
## partner |
|||
<div class="act_as_cell"></div> |
|||
## label |
|||
<div class="act_as_cell" >${_('Initial Balance')}</div> |
|||
## reconcile |
|||
<div class="act_as_cell"></div> |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(total_debit) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(total_credit) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${formatLang(part_cumul_balance) | amount }</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
<div class="act_as_cell sep_left amount">${formatLang(part_cumul_balance_curr) | amount }</div> |
|||
## curency code |
|||
<div class="act_as_cell">${balance_forward_currency}</div> |
|||
%endif |
|||
|
|||
</div> |
|||
%endif |
|||
|
|||
%for line in account.ledger_lines.get(p_id, []): |
|||
<% |
|||
total_debit += line.get('debit') or 0.0 |
|||
total_credit += line.get('credit') or 0.0 |
|||
|
|||
label_elements = [line.get('lname') or ''] |
|||
if line.get('invoice_number'): |
|||
label_elements.append("(%s)" % (line['invoice_number'],)) |
|||
label = ' '.join(label_elements) |
|||
%> |
|||
<div class="act_as_row lines"> |
|||
## date |
|||
<div class="act_as_cell first_column">${formatLang(line.get('ldate') or '', date=True)}</div> |
|||
## period |
|||
<div class="act_as_cell">${line.get('period_code') or ''}</div> |
|||
## move |
|||
<div class="act_as_cell">${line.get('move_name') or ''}</div> |
|||
## journal |
|||
<div class="act_as_cell">${line.get('jcode') or ''}</div> |
|||
## partner |
|||
<div class="act_as_cell overflow_ellipsis">${line.get('partner_name') or ''}</div> |
|||
## label |
|||
<div class="act_as_cell">${label}</div> |
|||
## reconcile |
|||
<div class="act_as_cell">${line.get('rec_name') or ''}</div> |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(line.get('debit') or 0.0) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(line.get('credit') or 0.0) | amount }</div> |
|||
## balance cumulated |
|||
<% cumul_balance += line.get('balance') or 0.0 %> |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${formatLang(cumul_balance) | amount }</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
<div class="act_as_cell sep_left amount">${formatLang(line.get('amount_currency') or 0.0) | amount }</div> |
|||
## curency code |
|||
<div class="act_as_cell" style="text-align: right; ">${line.get('currency_code') or ''}</div> |
|||
%endif |
|||
</div> |
|||
%endfor |
|||
<div class="act_as_row lines labels"> |
|||
## date |
|||
<div class="act_as_cell first_column"></div> |
|||
## period |
|||
<div class="act_as_cell"></div> |
|||
## move |
|||
<div class="act_as_cell"></div> |
|||
## journal |
|||
<div class="act_as_cell"></div> |
|||
## partner |
|||
<div class="act_as_cell"></div> |
|||
## label |
|||
<div class="act_as_cell">${_('Cumulated Balance on Partner')}</div> |
|||
## reconcile |
|||
<div class="act_as_cell"></div> |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(total_debit) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(total_credit) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${formatLang(cumul_balance) | amount }</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
%if account.currency_id: |
|||
<div class="act_as_cell amount sep_left">${formatLang(cumul_balance_curr) | amount }</div> |
|||
%else: |
|||
<div class="act_as_cell sep_left amount">${ u'-' }</div> |
|||
%endif |
|||
## currency code |
|||
<div class="act_as_cell" style="text-align: right; padding-right: 1px;">${ account.currency_id.name if account.currency_id else u'' }</div> |
|||
%endif |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<% |
|||
account_total_debit += total_debit |
|||
account_total_credit += total_credit |
|||
account_balance_cumul += cumul_balance |
|||
account_balance_cumul_curr += cumul_balance_curr |
|||
%> |
|||
%endfor |
|||
|
|||
<div class="act_as_table list_table" style="margin-top:5px;"> |
|||
<div class="act_as_row labels" style="font-weight: bold; font-size: 12px;"> |
|||
<div class="act_as_cell first_column" style="width: 320px;">${account.code} - ${account.name}</div> |
|||
## label |
|||
<div class="act_as_cell" style="width: 390px;">${_("Cumulated Balance on Account")}</div> |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 80px;">${ formatLang(account_total_debit) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 80px;">${ formatLang(account_total_credit) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="width: 80px; padding-right: 1px;">${ formatLang(account_balance_cumul) | amount }</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
%if account.currency_id: |
|||
<div class="act_as_cell amount sep_left" style="width: 80px;">${ formatLang(account_balance_cumul_curr) | amount }</div> |
|||
%else: |
|||
<div class="act_as_cell amount sep_left" style="width: 80px;">${ u'-' }</div> |
|||
%endif |
|||
## curency code |
|||
<div class="act_as_cell amount" style="width: 30px; text-align: right; padding-right: 1px;">${ account.currency_id.name if account.currency_id else u'' }</div> |
|||
%endif |
|||
</div> |
|||
</div> |
|||
</div> |
|||
%endif |
|||
%endfor |
|||
</body> |
|||
</html> |
@ -0,0 +1,210 @@ |
|||
<!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"> |
|||
${css} |
|||
|
|||
.list_table .act_as_row { |
|||
margin-top: 10px; |
|||
margin-bottom: 10px; |
|||
font-size:10px; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
<%! |
|||
|
|||
def amount(text): |
|||
return text.replace('-', '‑') # replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers) |
|||
%> |
|||
|
|||
<%def name="format_amount(amount, display_option=None)"> |
|||
<% |
|||
output = amount |
|||
if display_option == 'normal': |
|||
output = amount |
|||
elif display_option == 'round': |
|||
output = u"%.0f" % round(amount) |
|||
elif display_option == 'kilo': |
|||
if amount: |
|||
output = u"%.2fK" % (amount / 1000,) |
|||
%> |
|||
${output} |
|||
</%def> |
|||
|
|||
<%setLang(user.context_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')} |
|||
%else: |
|||
${_('Periods')} |
|||
%endif |
|||
</div> |
|||
<div class="act_as_cell">${_('Displayed Accounts')}</div> |
|||
<div class="act_as_cell">${_('Target Moves')}</div> |
|||
<div class="act_as_cell">${_('Initial Balance')}</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"> |
|||
%if accounts(data): |
|||
${', '.join([account.code for account in accounts(data)])} |
|||
%else: |
|||
${_('All')} |
|||
%endif |
|||
</div> |
|||
<div class="act_as_cell">${ display_target_move(data) }</div> |
|||
<div class="act_as_cell">${ _('Yes') if initial_balance else _('No') }</div> |
|||
</div> |
|||
</div> |
|||
|
|||
%for index, params in enumerate(comp_params): |
|||
<div class="act_as_table data_table"> |
|||
<div class="act_as_row"> |
|||
<div class="act_as_cell">${_('Comparison %s') % (index + 1,)} (${"C%s" % (index + 1,)})</div> |
|||
<div class="act_as_cell"> |
|||
%if params['comparison_filter'] == 'filter_date': |
|||
${_('Dates : ')} ${formatLang(params['start'], date=True) } - ${formatLang(params['stop'], date=True) } |
|||
%elif params['comparison_filter'] == 'filter_period': |
|||
${_('Periods : ')} ${params['start'].name} - ${params['stop'].name} |
|||
%else: |
|||
${_('Fiscal Year : ')} ${params['fiscalyear'].name} |
|||
%endif |
|||
</div> |
|||
<div class="act_as_cell">${_('Initial Balance:')} ${ _('Yes') if params['initial_balance'] else _('No') }</div> |
|||
</div> |
|||
</div> |
|||
%endfor |
|||
|
|||
<div class="act_as_table list_table" style="margin-top: 20px;"> |
|||
|
|||
<div class="act_as_thead"> |
|||
<div class="act_as_row labels"> |
|||
## account name |
|||
<div class="act_as_cell" style="width: 80px;">${_('Account')}</div> |
|||
%if comparison_mode == 'no_comparison': |
|||
%if initial_balance: |
|||
## initial balance |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Initial Balance')}</div> |
|||
%endif |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Debit')}</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Credit')}</div> |
|||
%endif |
|||
## balance |
|||
<div class="act_as_cell amount" style="width: 30px;"> |
|||
%if comparison_mode == 'no_comparison' or not fiscalyear: |
|||
${_('Balance')} |
|||
%else: |
|||
${_('Balance %s') % (fiscalyear.name,)} |
|||
%endif |
|||
</div> |
|||
%if comparison_mode in ('single', 'multiple'): |
|||
%for index in range(nb_comparison): |
|||
<div class="act_as_cell amount" style="width: 30px;"> |
|||
%if comp_params[index]['comparison_filter'] == 'filter_year' and comp_params[index].get('fiscalyear', False): |
|||
${_('Balance %s') % (comp_params[index]['fiscalyear'].name,)} |
|||
%else: |
|||
${_('Balance C%s') % (index + 1,)} |
|||
%endif |
|||
</div> |
|||
%if comparison_mode == 'single': ## no diff in multiple comparisons because it shows too data |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Difference')}</div> |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('% Difference')}</div> |
|||
%endif |
|||
%endfor |
|||
%endif |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="act_as_tbody"> |
|||
%for account_at in objects: |
|||
<% |
|||
current_account = account_at['current'] |
|||
level = current_account['level'] |
|||
%> |
|||
%if level_print(data, level): ## how to manage levels? |
|||
<% |
|||
styles = [] |
|||
if level_bold(data, level): |
|||
styles.append('font-weight: bold;') |
|||
else: |
|||
styles.append('font-weight: normal;') |
|||
|
|||
if level_italic(data, level): |
|||
styles.append('font-style: italic;') |
|||
else: |
|||
styles.append('font-style: normal;') |
|||
|
|||
if level_underline(data, level): |
|||
styles.append('text-decoration: underline;') |
|||
else: |
|||
styles.append('text-decoration: none;') |
|||
|
|||
if level_uppercase(data, level): |
|||
styles.append('text-transform: uppercase;') |
|||
else: |
|||
styles.append('font-decoration: none;') |
|||
|
|||
styles.append("font-size: %spx;" % (level_size(data, level),)) |
|||
|
|||
%> |
|||
<div class="act_as_row lines ${"account_level_%s" % (current_account['level'])}" styles="${' '.join(styles)}"> |
|||
## account name |
|||
<div class="act_as_cell" style="padding-left: ${current_account.get('level', 0) * 5}px; ${' '.join(styles)}">${current_account['name']}</div> |
|||
%if comparison_mode == 'no_comparison': |
|||
%if initial_balance: |
|||
## opening balance |
|||
<div class="act_as_cell amount" style="${' '.join(styles)}">${format_amount(current_account['init_balance'], numbers_display(data)) | amount}</div> |
|||
%endif |
|||
## debit |
|||
<div class="act_as_cell amount" style="${' '.join(styles)}">${format_amount(current_account['debit'], numbers_display(data)) | amount}</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="${' '.join(styles)}">${format_amount(current_account['credit'] * -1, numbers_display(data)) if current_account['credit'] else 0.0 | amount}</div> |
|||
%endif |
|||
## balance |
|||
<div class="act_as_cell amount" style="${' '.join(styles)}">${format_amount(current_account['balance'], numbers_display(data)) | amount}</div> |
|||
|
|||
%if comparison_mode in ('single', 'multiple'): |
|||
%for comp_account in account_at['comparisons']: |
|||
<div class="act_as_cell amount" style="${' '.join(styles)}">${format_amount(comp_account['balance'], numbers_display(data)) | amount}</div> |
|||
%if comparison_mode == 'single': ## no diff in multiple comparisons because it shows too data |
|||
<div class="act_as_cell amount" style="${' '.join(styles)}">${format_amount(comp_account['diff'], numbers_display(data)) | amount}</div> |
|||
<div class="act_as_cell amount" style="${' '.join(styles)}"> |
|||
%if comp_account['percent_diff'] is False: |
|||
${ '-' } |
|||
%else: |
|||
${comp_account['percent_diff'] | amount} % |
|||
%endif |
|||
</div> |
|||
%endif |
|||
%endfor |
|||
%endif |
|||
</div> |
|||
%endif |
|||
%endfor |
|||
</div> |
|||
</div> |
|||
</body> |
|||
</html> |
@ -0,0 +1,217 @@ |
|||
<!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"> |
|||
.account_level_1 { |
|||
text-transform: uppercase; |
|||
font-size: 15px; |
|||
background-color:#F0F0F0; |
|||
} |
|||
|
|||
.account_level_2 { |
|||
font-size: 12px; |
|||
background-color:#F0F0F0; |
|||
} |
|||
|
|||
.regular_account_type { |
|||
font-weight: normal; |
|||
} |
|||
|
|||
.view_account_type { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.account_level_consol { |
|||
font-weight: normal; |
|||
font-style: italic; |
|||
} |
|||
|
|||
${css} |
|||
|
|||
.list_table .act_as_row { |
|||
margin-top: 10px; |
|||
margin-bottom: 10px; |
|||
font-size:10px; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
<%! |
|||
def amount(text): |
|||
return text.replace('-', '‑') # replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers) |
|||
%> |
|||
|
|||
<%setLang(user.context_lang)%> |
|||
|
|||
<% |
|||
initial_balance_text = {'initial_balance': _('Computed'), 'opening_balance': _('Opening Entries'), False: _('No')} |
|||
%> |
|||
|
|||
<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">${_('Accounts Filter')}</div> |
|||
<div class="act_as_cell">${_('Target Moves')}</div> |
|||
<div class="act_as_cell">${_('Initial Balance')}</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"> |
|||
%if accounts(data): |
|||
${', '.join([account.code for account in accounts(data)])} |
|||
%else: |
|||
${_('All')} |
|||
%endif |
|||
</div> |
|||
<div class="act_as_cell">${ display_target_move(data) }</div> |
|||
<div class="act_as_cell">${ initial_balance_text[initial_balance_mode] }</div> |
|||
</div> |
|||
</div> |
|||
|
|||
%for index, params in enumerate(comp_params): |
|||
<div class="act_as_table data_table"> |
|||
<div class="act_as_row"> |
|||
<div class="act_as_cell">${_('Comparison %s') % (index + 1,)} (${"C%s" % (index + 1,)})</div> |
|||
<div class="act_as_cell"> |
|||
%if params['comparison_filter'] == 'filter_date': |
|||
${_('Dates Filter:')} ${formatLang(params['start'], date=True) } - ${formatLang(params['stop'], date=True) } |
|||
%elif params['comparison_filter'] == 'filter_period': |
|||
${_('Periods Filter:')} ${params['start'].name} - ${params['stop'].name} |
|||
%else: |
|||
${_('Fiscal Year :')} ${params['fiscalyear'].name} |
|||
%endif |
|||
</div> |
|||
<div class="act_as_cell">${_('Initial Balance:')} ${ initial_balance_text[params['initial_balance_mode']] }</div> |
|||
</div> |
|||
</div> |
|||
%endfor |
|||
|
|||
<div class="act_as_table list_table" style="margin-top: 20px;"> |
|||
|
|||
<div class="act_as_thead"> |
|||
<div class="act_as_row labels"> |
|||
## code |
|||
<div class="act_as_cell first_column" style="width: 20px;">${_('Code')}</div> |
|||
## account name |
|||
<div class="act_as_cell" style="width: 80px;">${_('Account')}</div> |
|||
%if comparison_mode == 'no_comparison': |
|||
%if initial_balance_mode: |
|||
## initial balance |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Initial Balance')}</div> |
|||
%endif |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Debit')}</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Credit')}</div> |
|||
%endif |
|||
## balance |
|||
<div class="act_as_cell amount" style="width: 30px;"> |
|||
%if comparison_mode == 'no_comparison' or not fiscalyear: |
|||
${_('Balance')} |
|||
%else: |
|||
${_('Balance %s') % (fiscalyear.name,)} |
|||
%endif |
|||
</div> |
|||
%if comparison_mode in ('single', 'multiple'): |
|||
%for index in range(nb_comparison): |
|||
<div class="act_as_cell amount" style="width: 30px;"> |
|||
%if comp_params[index]['comparison_filter'] == 'filter_year' and comp_params[index].get('fiscalyear', False): |
|||
${_('Balance %s') % (comp_params[index]['fiscalyear'].name,)} |
|||
%else: |
|||
${_('Balance C%s') % (index + 1,)} |
|||
%endif |
|||
</div> |
|||
%if comparison_mode == 'single': ## no diff in multiple comparisons because it shows too data |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('Difference')}</div> |
|||
<div class="act_as_cell amount" style="width: 30px;">${_('% Difference')}</div> |
|||
%endif |
|||
%endfor |
|||
%endif |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="act_as_tbody"> |
|||
<% |
|||
last_child_consol_ids = [] |
|||
last_level = False |
|||
%> |
|||
%for current_account in objects: |
|||
<% |
|||
if not current_account.to_display: |
|||
continue |
|||
|
|||
comparisons = current_account.comparisons |
|||
|
|||
if current_account.id in last_child_consol_ids: |
|||
# current account is a consolidation child of the last account: use the level of last account |
|||
level = last_level |
|||
level_class = "account_level_consol" |
|||
else: |
|||
# current account is a not a consolidation child: use its own level |
|||
level = current_account.level or 0 |
|||
level_class = "account_level_%s" % (level,) |
|||
last_child_consol_ids = [child_consol_id.id for child_consol_id in current_account.child_consol_ids] |
|||
last_level = current_account.level |
|||
%> |
|||
<div class="act_as_row lines ${level_class} ${"%s_account_type" % (current_account.type,)}"> |
|||
## code |
|||
<div class="act_as_cell first_column">${current_account.code}</div> |
|||
## account name |
|||
<div class="act_as_cell" style="padding-left: ${level * 5}px;">${current_account.name}</div> |
|||
%if comparison_mode == 'no_comparison': |
|||
%if initial_balance_mode: |
|||
## opening balance |
|||
<div class="act_as_cell amount">${formatLang(current_account.init_balance) | amount}</div> |
|||
%endif |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(current_account.debit) | amount}</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(current_account.credit) | amount}</div> |
|||
%endif |
|||
## balance |
|||
<div class="act_as_cell amount">${formatLang(current_account.balance) | amount}</div> |
|||
|
|||
%if comparison_mode in ('single', 'multiple'): |
|||
%for comp_account in comparisons: |
|||
<div class="act_as_cell amount">${formatLang(comp_account['balance']) | amount}</div> |
|||
%if comparison_mode == 'single': ## no diff in multiple comparisons because it shows too data |
|||
<div class="act_as_cell amount">${formatLang(comp_account['diff']) | amount}</div> |
|||
<div class="act_as_cell amount"> |
|||
%if comp_account['percent_diff'] is False: |
|||
${ '-' } |
|||
%else: |
|||
${int(round(comp_account['percent_diff'])) | amount} % |
|||
%endif |
|||
</div> |
|||
%endif |
|||
%endfor |
|||
%endif |
|||
</div> |
|||
%endfor |
|||
</div> |
|||
</div> |
|||
</body> |
|||
</html> |
@ -0,0 +1,166 @@ |
|||
<%page args="account, formatLang" /> |
|||
%if account.grouped_ledger_lines and account.partners_order: |
|||
<% |
|||
account_total_debit = 0.0 |
|||
account_total_credit = 0.0 |
|||
account_balance_cumul = 0.0 |
|||
account_balance_cumul_curr = 0.0 |
|||
%> |
|||
%for partner_name, p_id, p_ref, p_name in account.partners_order: |
|||
<div class="account_title bg" style="width: 1080px; margin-top: |
|||
20px; font-size: 12px;">${account.code} - ${account.name} -- ${partner_name or _('No Partner')} </div> |
|||
|
|||
|
|||
|
|||
%for curr, grouped_lines in account.grouped_ledger_lines.get(p_id, []): |
|||
<% |
|||
total_debit = 0.0 |
|||
total_credit = 0.0 |
|||
cumul_balance = 0.0 |
|||
cumul_balance_curr = 0.0 |
|||
|
|||
part_cumul_balance = 0.0 |
|||
part_cumul_balance_curr = 0.0 |
|||
%> |
|||
<div class="act_as_table list_table" style="margin-top: 5px;"> |
|||
<div class="act_as_caption account_title"> |
|||
<b>${curr or company.currency_id.name}</b> |
|||
</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> |
|||
## period |
|||
<div class="act_as_cell" style="width: 70px;">${_('Period')}</div> |
|||
## move |
|||
<div class="act_as_cell" style="width: 70px;">${_('Entry')}</div> |
|||
## journal |
|||
<div class="act_as_cell" style="width: 70px;">${_('Journal')}</div> |
|||
## label |
|||
<div class="act_as_cell" style="width: 255px;">${_('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> |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Debit')}</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Credit')}</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Cumul. Bal.')}</div> |
|||
## currency balance |
|||
<div class="act_as_cell amount sep_left" style="width: 80px;">${_('Curr. Balance')}</div> |
|||
## curency code |
|||
<div class="act_as_cell amount" style="width: 30px; text-align: right;">${_('Curr.')}</div> |
|||
</div> |
|||
</div> |
|||
<div class="act_as_tbody"> |
|||
<% |
|||
total_debit = 0.0 |
|||
total_credit = 0.0 |
|||
%> |
|||
<%! |
|||
def amount(text): |
|||
return text.replace('-', '‑') # replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers) |
|||
%> |
|||
%for line in grouped_lines: |
|||
<% |
|||
total_debit += line.get('debit') or 0.0 |
|||
total_credit += line.get('credit') or 0.0 |
|||
|
|||
label_elements = [line.get('lname') or ''] |
|||
if line.get('invoice_number'): |
|||
label_elements.append("(%s)" % (line['invoice_number'],)) |
|||
label = ' '.join(label_elements) |
|||
%> |
|||
<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> |
|||
## period |
|||
<div class="act_as_cell">${line.get('period_code') or ''}</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">${label}</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> |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(line.get('debit') or 0.0) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(line.get('credit') or 0.0) | amount }</div> |
|||
## balance cumulated |
|||
<% cumul_balance += line.get('balance') or 0.0 %> |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${formatLang(cumul_balance) | amount }</div> |
|||
## currency balance |
|||
<div class="act_as_cell sep_left amount">${formatLang(line.get('amount_currency') or 0.0) | amount }</div> |
|||
## curency code |
|||
<div class="act_as_cell" style="text-align: right; ">${line.get('currency_code') or ''}</div> |
|||
</div> |
|||
%endfor |
|||
<div class="act_as_row lines labels"> |
|||
## date |
|||
<div class="act_as_cell first_column"></div> |
|||
## period |
|||
<div class="act_as_cell"></div> |
|||
## move |
|||
<div class="act_as_cell"></div> |
|||
## journal |
|||
<div class="act_as_cell"></div> |
|||
## label |
|||
<div class="act_as_cell">${_('Cumulated Balance on Partner')}</div> |
|||
## reconcile |
|||
<div class="act_as_cell"></div> |
|||
## maturity date |
|||
<div class="act_as_cell"></div> |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(total_debit) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(total_credit) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${formatLang(cumul_balance) | amount }</div> |
|||
%if account.currency_id: |
|||
## currency balance |
|||
<div class="act_as_cell sep_left amount" style="padding-right: 1px;">${formatLang(cumul_balance_curr) | amount }</div> |
|||
%else: |
|||
<div class="act_as_cell sep_left amount" style="padding-right: 1px;">${ u'-' }</div> |
|||
%endif |
|||
## curency code |
|||
<div class="act_as_cell" style="text-align: right; ">${ account.currency_id.name if account.currency_id else u'' }</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<% |
|||
account_total_debit += total_debit |
|||
account_total_credit += total_credit |
|||
account_balance_cumul += cumul_balance |
|||
account_balance_cumul_curr += cumul_balance_curr |
|||
%> |
|||
%endfor |
|||
%endfor |
|||
<div class="act_as_table list_table" style="margin-top:5px;"> |
|||
<div class="act_as_row labels" style="font-weight: bold; font-size: 12px;"> |
|||
<div class="act_as_cell first_column" style="width: 330px;">${account.code} - ${account.name}</div> |
|||
## label |
|||
<div class="act_as_cell" style="width: 395px;">${_("Cumulated Balance on Account")}</div> |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 80px;">${ formatLang(account_total_debit) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 80px;">${ formatLang(account_total_credit) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="width: 80px; ">${ formatLang(account_balance_cumul) | amount }</div> |
|||
## currency balance cumulated |
|||
%if account.currency_id: |
|||
<div class="act_as_cell amount sep_left" style="width: 80px;">${ formatLang(account_balance_cumul_curr) | amount }</div> |
|||
%else: |
|||
<div class="act_as_cell amount sep_left" style="width: 80px; padding-right: 1px;">${ u'-' }</div> |
|||
%endif |
|||
## curency code |
|||
<div class="act_as_cell amount" style="width: 30px; text-align: right;">${ account.currency_id.name if account.currency_id else u'' }</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
%endif |
@ -0,0 +1,176 @@ |
|||
<%page args="account, formatLang" /> |
|||
%if account.ledger_lines and account.partners_order: |
|||
<% |
|||
account_total_debit = 0.0 |
|||
account_total_credit = 0.0 |
|||
account_balance_cumul = 0.0 |
|||
account_balance_cumul_curr = 0.0 |
|||
%> |
|||
|
|||
<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 account.partners_order: |
|||
<% |
|||
total_debit = 0.0 |
|||
total_credit = 0.0 |
|||
cumul_balance = 0.0 |
|||
cumul_balance_curr = 0.0 |
|||
|
|||
part_cumul_balance = 0.0 |
|||
part_cumul_balance_curr = 0.0 |
|||
%> |
|||
<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> |
|||
## period |
|||
<div class="act_as_cell" style="width: 70px;">${_('Period')}</div> |
|||
## move |
|||
<div class="act_as_cell" style="width: 70px;">${_('Entry')}</div> |
|||
## journal |
|||
<div class="act_as_cell" style="width: 70px;">${_('Journal')}</div> |
|||
## partner |
|||
<div class="act_as_cell" style="width: 60px;">${_('Partner')}</div> |
|||
## label |
|||
<div class="act_as_cell" style="width: 255px;">${_('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> |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Debit')}</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Credit')}</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="width: 80px;">${_('Cumul. Bal.')}</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
<div class="act_as_cell amount sep_left" style="width: 80px;">${_('Curr. Balance')}</div> |
|||
## curency code |
|||
<div class="act_as_cell amount" style="width: 30px; text-align: right;">${_('Curr.')}</div> |
|||
%endif |
|||
</div> |
|||
</div> |
|||
<div class="act_as_tbody"> |
|||
<% |
|||
total_debit = 0.0 |
|||
total_credit = 0.0 |
|||
%> |
|||
<%! |
|||
def amount(text): |
|||
return text.replace('-', '‑') # replace by a non-breaking hyphen (it will not word-wrap between hyphen and numbers) |
|||
%> |
|||
%for line in account.ledger_lines.get(p_id, []): |
|||
<% |
|||
total_debit += line.get('debit') or 0.0 |
|||
total_credit += line.get('credit') or 0.0 |
|||
|
|||
label_elements = [line.get('lname') or ''] |
|||
if line.get('invoice_number'): |
|||
label_elements.append("(%s)" % (line['invoice_number'],)) |
|||
label = ' '.join(label_elements) |
|||
%> |
|||
<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> |
|||
## period |
|||
<div class="act_as_cell">${line.get('period_code') or ''}</div> |
|||
## move |
|||
<div class="act_as_cell">${line.get('move_name') or ''}</div> |
|||
## journal |
|||
<div class="act_as_cell">${line.get('jcode') or ''}</div> |
|||
## partner |
|||
<div class="act_as_cell overflow_ellipsis">${line.get('partner_name') or ''}</div> |
|||
## label |
|||
<div class="act_as_cell">${label}</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> |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(line.get('debit') or 0.0) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(line.get('credit') or 0.0) | amount }</div> |
|||
## balance cumulated |
|||
<% cumul_balance += line.get('balance') or 0.0 %> |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${formatLang(cumul_balance) | amount }</div> |
|||
%if amount_currency(data): |
|||
## currency balance |
|||
<div class="act_as_cell sep_left amount">${formatLang(line.get('amount_currency') or 0.0) | amount }</div> |
|||
## curency code |
|||
<div class="act_as_cell" style="text-align: right; ">${line.get('currency_code') or ''}</div> |
|||
%endif |
|||
</div> |
|||
%endfor |
|||
<div class="act_as_row lines labels"> |
|||
## date |
|||
<div class="act_as_cell first_column"></div> |
|||
## period |
|||
<div class="act_as_cell"></div> |
|||
## move |
|||
<div class="act_as_cell"></div> |
|||
## journal |
|||
<div class="act_as_cell"></div> |
|||
## partner |
|||
<div class="act_as_cell"></div> |
|||
## label |
|||
<div class="act_as_cell">${_('Cumulated Balance on Partner')}</div> |
|||
## reconcile |
|||
<div class="act_as_cell"></div> |
|||
## maturity date |
|||
<div class="act_as_cell"></div> |
|||
## debit |
|||
<div class="act_as_cell amount">${formatLang(total_debit) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount">${formatLang(total_credit) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="padding-right: 1px;">${formatLang(cumul_balance) | amount }</div> |
|||
%if amount_currency(data): |
|||
%if account.currency_id: |
|||
## currency balance |
|||
<div class="act_as_cell sep_left amount" style="padding-right: 1px;">${formatLang(cumul_balance_curr) | amount }</div> |
|||
%else: |
|||
<div class="act_as_cell sep_left amount" style="padding-right: 1px;">${ u'-' }</div> |
|||
%endif |
|||
## curency code |
|||
<div class="act_as_cell" style="text-align: right; ">${ account.currency_id.name if account.currency_id else u'' }</div> |
|||
%endif |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<% |
|||
account_total_debit += total_debit |
|||
account_total_credit += total_credit |
|||
account_balance_cumul += cumul_balance |
|||
account_balance_cumul_curr += cumul_balance_curr |
|||
%> |
|||
%endfor |
|||
<div class="act_as_table list_table" style="margin-top:5px;"> |
|||
<div class="act_as_row labels" style="font-weight: bold; font-size: 12px;"> |
|||
<div class="act_as_cell first_column" style="width: 330px;">${account.code} - ${account.name}</div> |
|||
## label |
|||
<div class="act_as_cell" style="width: 395px;">${_("Cumulated Balance on Account")}</div> |
|||
## debit |
|||
<div class="act_as_cell amount" style="width: 80px;">${ formatLang(account_total_debit) | amount }</div> |
|||
## credit |
|||
<div class="act_as_cell amount" style="width: 80px;">${ formatLang(account_total_credit) | amount }</div> |
|||
## balance cumulated |
|||
<div class="act_as_cell amount" style="width: 80px; ">${ formatLang(account_balance_cumul) | amount }</div> |
|||
%if amount_currency(data): |
|||
## currency balance cumulated |
|||
%if account.currency_id: |
|||
<div class="act_as_cell amount sep_left" style="width: 80px;">${ formatLang(account_balance_cumul_curr) | amount }</div> |
|||
%else: |
|||
<div class="act_as_cell amount sep_left" style="width: 80px; padding-right: 1px;">${ u'-' }</div> |
|||
%endif |
|||
## curency code |
|||
<div class="act_as_cell amount" style="width: 30px; text-align: right;">${ account.currency_id.name if account.currency_id else u'' }</div> |
|||
%endif |
|||
</div> |
|||
</div> |
|||
</div> |
|||
%endif |
@ -0,0 +1,82 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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 report import report_sxw |
|||
from tools.translate import _ |
|||
import pooler |
|||
from datetime import datetime |
|||
|
|||
from common_balance_reports import CommonBalanceReportHeaderWebkit |
|||
from webkit_parser_header_fix import HeaderFooterTextWebKitParser |
|||
|
|||
def sign(number): |
|||
return cmp(number, 0) |
|||
|
|||
class TrialBalanceWebkit(report_sxw.rml_parse, CommonBalanceReportHeaderWebkit): |
|||
|
|||
def __init__(self, cursor, uid, name, context): |
|||
super(TrialBalanceWebkit, 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((_('TRIAL BALANCE'), company.name, company.currency_id.name)) |
|||
|
|||
footer_date_time = self.formatLang(str(datetime.today()), date_time=True) |
|||
|
|||
self.localcontext.update({ |
|||
'cr': cursor, |
|||
'uid': uid, |
|||
'report_name': _('Trial Balance'), |
|||
'display_account': self._get_display_account, |
|||
'display_account_raw': self._get_display_account_raw, |
|||
'filter_form': self._get_filter, |
|||
'target_move': self._get_target_move, |
|||
'display_target_move': self._get_display_target_move, |
|||
'accounts': self._get_accounts_br, |
|||
'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 set_context(self, objects, data, ids, report_type=None): |
|||
"""Populate a ledger_lines attribute on each browse record that will be used |
|||
by mako template""" |
|||
objects, new_ids, context_report_values = self.compute_balance_data(data) |
|||
|
|||
self.localcontext.update(context_report_values) |
|||
|
|||
return super(TrialBalanceWebkit, self).set_context(objects, data, new_ids, |
|||
report_type=report_type) |
|||
|
|||
HeaderFooterTextWebKitParser('report.account.account_report_trial_balance_webkit', |
|||
'account.account', |
|||
'addons/account_financial_report_webkit/report/templates/account_report_trial_balance.mako', |
|||
parser=TrialBalanceWebkit) |
@ -0,0 +1,235 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
|||
# |
|||
# Author : Guewen Baconnier (Camptocamp) |
|||
# |
|||
# WARNING: This program as such is intended to be used by professional |
|||
# programmers who take the whole responsability of assessing all potential |
|||
# consequences resulting from its eventual inadequacies and bugs |
|||
# End users who are looking for a ready-to-use solution with commercial |
|||
# garantees and support are strongly adviced to contract a Free Software |
|||
# Service Company |
|||
# |
|||
# This program is Free Software; you can redistribute it and/or |
|||
# modify it under the terms of the GNU General Public License |
|||
# as published by the Free Software Foundation; either version 2 |
|||
# 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 General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License |
|||
# along with this program; if not, write to the Free Software |
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|||
# |
|||
############################################################################## |
|||
import os |
|||
import subprocess |
|||
import tempfile |
|||
import time |
|||
import pooler |
|||
import tools |
|||
import logging |
|||
import openerp.addons |
|||
|
|||
|
|||
from mako import exceptions |
|||
from osv.osv import except_osv |
|||
from tools.translate import _ |
|||
from openerp.addons.report_webkit import webkit_report |
|||
from openerp.addons.report_webkit.webkit_report import mako_template |
|||
from openerp.addons.report_webkit.report_helper import WebKitHelper |
|||
|
|||
_logger = logging.getLogger('financial.reports.webkit') |
|||
|
|||
# Class used only as a workaround to bug : |
|||
# http://code.google.com/p/wkhtmltopdf/issues/detail?id=656 |
|||
|
|||
# html headers and footers do not work on big files (hundreds of pages) so we replace them by |
|||
# text headers and footers passed as arguments to wkhtmltopdf |
|||
# this class has to be removed once the bug is fixed |
|||
|
|||
# in your report class, to print headers and footers as text, you have to add them in the localcontext with a key 'additional_args' |
|||
# for instance : |
|||
# header_report_name = _('PARTNER LEDGER') |
|||
# footer_date_time = self.formatLang(str(datetime.today()), date_time=True) |
|||
# self.localcontext.update({ |
|||
# 'additional_args': [ |
|||
# ('--header-font-name', 'Helvetica'), |
|||
# ('--footer-font-name', 'Helvetica'), |
|||
# ('--header-font-size', '10'), |
|||
# ('--footer-font-size', '7'), |
|||
# ('--header-left', header_report_name), |
|||
# ('--footer-left', footer_date_time), |
|||
# ('--footer-right', ' '.join((_('Page'), '[page]', _('of'), '[topage]'))), |
|||
# ('--footer-line',), |
|||
# ], |
|||
# }) |
|||
|
|||
|
|||
class HeaderFooterTextWebKitParser(webkit_report.WebKitParser): |
|||
|
|||
def generate_pdf(self, comm_path, report_xml, header, footer, html_list, webkit_header=False): |
|||
"""Call webkit in order to generate pdf""" |
|||
if not webkit_header: |
|||
webkit_header = report_xml.webkit_header |
|||
tmp_dir = tempfile.gettempdir() |
|||
out_filename = tempfile.mktemp(suffix=".pdf", prefix="webkit.tmp.") |
|||
files = [] |
|||
file_to_del = [out_filename] |
|||
if comm_path: |
|||
command = [comm_path] |
|||
else: |
|||
command = ['wkhtmltopdf'] |
|||
|
|||
command.append('--quiet') |
|||
# default to UTF-8 encoding. Use <meta charset="latin-1"> to override. |
|||
command.extend(['--encoding', 'utf-8']) |
|||
|
|||
if webkit_header.margin_top : |
|||
command.extend(['--margin-top', str(webkit_header.margin_top).replace(',', '.')]) |
|||
if webkit_header.margin_bottom : |
|||
command.extend(['--margin-bottom', str(webkit_header.margin_bottom).replace(',', '.')]) |
|||
if webkit_header.margin_left : |
|||
command.extend(['--margin-left', str(webkit_header.margin_left).replace(',', '.')]) |
|||
if webkit_header.margin_right : |
|||
command.extend(['--margin-right', str(webkit_header.margin_right).replace(',', '.')]) |
|||
if webkit_header.orientation : |
|||
command.extend(['--orientation', str(webkit_header.orientation).replace(',', '.')]) |
|||
if webkit_header.format : |
|||
command.extend(['--page-size', str(webkit_header.format).replace(',', '.')]) |
|||
|
|||
if self.parser_instance.localcontext.get('additional_args', False): |
|||
for arg in self.parser_instance.localcontext['additional_args']: |
|||
command.extend(arg) |
|||
|
|||
count = 0 |
|||
for html in html_list : |
|||
html_file = file(os.path.join(tmp_dir, str(time.time()) + str(count) +'.body.html'), 'w') |
|||
count += 1 |
|||
html_file.write(html) |
|||
html_file.close() |
|||
file_to_del.append(html_file.name) |
|||
command.append(html_file.name) |
|||
command.append(out_filename) |
|||
stderr_fd, stderr_path = tempfile.mkstemp(text=True) |
|||
file_to_del.append(stderr_path) |
|||
try: |
|||
status = subprocess.call(command, stderr=stderr_fd) |
|||
os.close(stderr_fd) # force flush |
|||
stderr_fd = None # avoid closing again in finally |
|||
fobj = open(stderr_path, 'r') |
|||
error_message = fobj.read() |
|||
fobj.close() |
|||
if not error_message: |
|||
error_message = _('No diagnosis message was provided') |
|||
else: |
|||
error_message = _('The following diagnosis message was provided:\n') + error_message |
|||
if status: |
|||
raise except_osv(_('Webkit error' ), |
|||
_("The command 'wkhtmltopdf' failed with error code = %s. Message: %s") % (status, error_message)) |
|||
pdf_file = open(out_filename, 'rb') |
|||
pdf = pdf_file.read() |
|||
pdf_file.close() |
|||
finally: |
|||
if stderr_fd is not None: |
|||
os.close(stderr_fd) |
|||
for f_to_del in file_to_del: |
|||
try: |
|||
os.unlink(f_to_del) |
|||
except (OSError, IOError), exc: |
|||
_logger.error('cannot remove file %s: %s', f_to_del, exc) |
|||
return pdf |
|||
|
|||
# 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 = [] |
|||
if report_xml.report_type != 'webkit': |
|||
return super(HeaderFooterTextWebKitParser,self).create_single_pdf(cursor, uid, ids, data, report_xml, context=context) |
|||
|
|||
self.parser_instance = self.parser(cursor, |
|||
uid, |
|||
self.name2, |
|||
context=context) |
|||
|
|||
self.pool = pooler.get_pool(cursor.dbname) |
|||
objs = self.getObjects(cursor, uid, ids, context) |
|||
self.parser_instance.set_context(objs, data, ids, report_xml.report_type) |
|||
|
|||
template = False |
|||
|
|||
if report_xml.report_file : |
|||
path =openerp.addons.get_module_resource(report_xml.report_file) |
|||
if os.path.exists(path) : |
|||
template = file(path).read() |
|||
if not template and report_xml.report_webkit_data : |
|||
template = report_xml.report_webkit_data |
|||
if not template : |
|||
raise except_osv(_('Error!'), _('Webkit Report template not found !')) |
|||
header = report_xml.webkit_header.html |
|||
footer = report_xml.webkit_header.footer_html |
|||
if not header and report_xml.header: |
|||
raise except_osv( |
|||
_('No header defined for this Webkit report!'), |
|||
_('Please set a header in company settings') |
|||
) |
|||
|
|||
css = report_xml.webkit_header.css |
|||
if not css : |
|||
css = '' |
|||
user = self.pool.get('res.users').browse(cursor, uid, uid) |
|||
|
|||
#default_filters=['unicode', 'entity'] can be used to set global filter |
|||
body_mako_tpl = mako_template(template) |
|||
helper = WebKitHelper(cursor, uid, report_xml.id, context) |
|||
if report_xml.precise_mode: |
|||
for obj in objs: |
|||
self.parser_instance.localcontext['objects'] = [obj] |
|||
try : |
|||
html = body_mako_tpl.render(helper=helper, |
|||
css=css, |
|||
_=self.translate_call, |
|||
**self.parser_instance.localcontext) |
|||
htmls.append(html) |
|||
except Exception, e: |
|||
msg = exceptions.text_error_template().render() |
|||
_logger.error(msg) |
|||
raise except_osv(_('Webkit render'), msg) |
|||
else: |
|||
try : |
|||
html = body_mako_tpl.render(helper=helper, |
|||
css=css, |
|||
_=self.translate_call, |
|||
**self.parser_instance.localcontext) |
|||
htmls.append(html) |
|||
except Exception, e: |
|||
msg = exceptions.text_error_template().render() |
|||
_logger.error(msg) |
|||
raise except_osv(_('Webkit render'), msg) |
|||
|
|||
# NO html footer and header because we write them as text with wkhtmltopdf |
|||
head = foot = False |
|||
|
|||
if report_xml.webkit_debug : |
|||
try : |
|||
deb = body_mako_tpl.render(helper=helper, |
|||
css=css, |
|||
_debug=tools.ustr("\n".join(htmls)), |
|||
_=self.translate_call, |
|||
**self.parser_instance.localcontext) |
|||
except Exception, e: |
|||
msg = exceptions.text_error_template().render() |
|||
_logger.error(msg) |
|||
raise except_osv(_('Webkit render'), msg) |
|||
return (deb, 'html') |
|||
bin = self.get_lib(cursor, uid) |
|||
pdf = self.generate_pdf(bin, report_xml, head, foot, htmls) |
|||
return (pdf, 'pdf') |
@ -0,0 +1,26 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<menuitem icon="STOCK_PRINT" 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" |
|||
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" |
|||
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" |
|||
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="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"/> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,3 @@ |
|||
- |
|||
In order to test the last_rec_date behavior we will create a move and reconcile it |
|||
- |
@ -0,0 +1,65 @@ |
|||
- |
|||
In order to test the PDF General Ledger webkit wizard I will print report with default setting |
|||
- |
|||
!python {model: account.account}: | |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0')} |
|||
ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')}) |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF General Ledger webkit wizard I will print report with posted move |
|||
- |
|||
!python {model: account.account}: | |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'target_move': 'posted'} |
|||
ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')}) |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF General Ledger webkit wizard I will print report with transactions or non zero balance |
|||
- |
|||
!python {model: account.account}: | |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'display_account': 'bal_mix'} |
|||
ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')}) |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF General Ledger webkit wizard I will print report with inital balance and currency ammount |
|||
- |
|||
!python {model: account.account}: | |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'amount_currency': 1} |
|||
ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')}) |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
#Filter by date |
|||
- |
|||
In order to test the PDF General Ledger webkit wizard I will print report with inital balance and currency ammount and I filter by date of the first tree month |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'),'amount_currency': 1, 'chart_account_id': 1, 'date_from': '%s-01-01' %(datetime.now().year), |
|||
'date_to':'%s-04-01' %(datetime.now().year), 'display_account': 'bal_all', 'filter': 'filter_date',} |
|||
ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')}) |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF General Ledger webkit wizard I will print report with inital balance and currency ammount and I filter by date of the first tree month |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'),'amount_currency': 1, 'chart_account_id': 1, 'date_from': '%s-01-01' %(datetime.now().year), |
|||
'date_to':'%s-04-01' %(datetime.now().year), 'display_account': 'bal_all', 'filter': 'filter_date',} |
|||
ctx.update({'model': 'account.account','active_ids':[ref('account.chart0')],'active_id':ref('account.chart0')}) |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_general_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
# I still have to parse report content but for this I need accounting data on multiple exercises and faor all fiscal year |
@ -0,0 +1,60 @@ |
|||
- |
|||
In order to test the PDF Open Invoices 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_open_invoices_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Open Invoices 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_open_invoices_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Open Invoices 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_agrolait'), ref('base.res_partner_asus')]} |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_open_invoices_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Open Invoices 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_open_invoices_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Open Invoices 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_open_invoices_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
@ -0,0 +1,67 @@ |
|||
- |
|||
In order to test the PDF Partner Balance 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')} |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_partner_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Balance webkit wizard I will print report as if we print it from an account |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0')} |
|||
ctx.update({'model': 'account.account','active_ids':[ref('account.assets_view'), ref('account.liabilities_view')],'active_id': ref('account.assets_view')}) |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_partner_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Balance webkit wizard I will print report with filters on period |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'), |
|||
'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_partner_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Balance 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'), |
|||
'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_partner_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Balance webkit wizard I will print report with one comparison filtered by year |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'), |
|||
'comp0_filter': 'filter_year', 'comp0_fiscalyear_id': ref('account.data_fiscalyear')} |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_partner_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Balance webkit wizard I will print report with all comparisons filtered by year, period and date |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'), |
|||
'comp0_filter': 'filter_year', 'comp0_fiscalyear_id': ref('account.data_fiscalyear'), |
|||
'comp1_filter': 'filter_period', 'comp1_period_from': ref('account.period_1'), 'comp1_period_to': ref('account.period_12'), |
|||
'comp2_filter': 'filter_date', 'comp2_date_from': '%s-01-01' %(datetime.now().year), 'comp2_date_to': '%s-12-31' %(datetime.now().year) |
|||
} |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_partner_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
@ -0,0 +1,60 @@ |
|||
- |
|||
In order to test the PDF Partner Ledger 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_partners_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Ledger 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_partners_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Ledger 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_agrolait'), ref('base.res_partner_asus')]} |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_partners_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Ledger 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_partners_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Partner Ledger 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_partners_ledger_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
@ -0,0 +1,67 @@ |
|||
- |
|||
In order to test the PDF Trial Balance 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')} |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Trial Balance webkit wizard I will print report as if we print it from an account |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0')} |
|||
ctx.update({'model': 'account.account','active_ids':[ref('account.assets_view'), ref('account.liabilities_view')],'active_id': ref('account.assets_view')}) |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Trial Balance webkit wizard I will print report with filters on period |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'), |
|||
'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_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Trial Balance 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'), |
|||
'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_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Trial Balance webkit wizard I will print report with one comparison filtered by year |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'), |
|||
'comp0_filter': 'filter_year', 'comp0_fiscalyear_id': ref('account.data_fiscalyear')} |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
|||
|
|||
- |
|||
In order to test the PDF Trial Balance webkit wizard I will print report with all comparisons filtered by year, period and date |
|||
- |
|||
!python {model: account.account}: | |
|||
from datetime import datetime |
|||
ctx={} |
|||
data_dict = {'chart_account_id':ref('account.chart0'), 'fiscalyear_id': ref('account.data_fiscalyear'), |
|||
'comp0_filter': 'filter_year', 'comp0_fiscalyear_id': ref('account.data_fiscalyear'), |
|||
'comp1_filter': 'filter_period', 'comp1_period_from': ref('account.period_1'), 'comp1_period_to': ref('account.period_12'), |
|||
'comp2_filter': 'filter_date', 'comp2_date_from': '%s-01-01' %(datetime.now().year), 'comp2_date_to': '%s-12-31' %(datetime.now().year) |
|||
} |
|||
from tools import test_reports |
|||
test_reports.try_report_action(cr, uid, 'action_account_trial_balance_menu_webkit',wiz_data=data_dict, context=ctx, our_module='account_financial_report_webkit') |
@ -0,0 +1,27 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi. Copyright 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 . import balance_common |
|||
from . import general_ledger_wizard |
|||
from . import partners_ledger_wizard |
|||
from . import trial_balance_wizard |
|||
from . import partner_balance_wizard |
|||
from . import open_invoices_wizard |
|||
#from . import account_report_profit_loss_wizard |
@ -0,0 +1,295 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
|||
# |
|||
# Author : Guewen Baconnier (Camptocamp) |
|||
# |
|||
# WARNING: This program as such is intended to be used by professional |
|||
# programmers who take the whole responsability of assessing all potential |
|||
# consequences resulting from its eventual inadequacies and bugs |
|||
# End users who are looking for a ready-to-use solution with commercial |
|||
# garantees and support are strongly adviced to contract a Free Software |
|||
# Service Company |
|||
# |
|||
# This program is Free Software; you can redistribute it and/or |
|||
# modify it under the terms of the GNU General Public License |
|||
# as published by the Free Software Foundation; either version 2 |
|||
# 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 General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License |
|||
# along with this program; if not, write to the Free Software |
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|||
# |
|||
############################################################################## |
|||
|
|||
import time |
|||
|
|||
from osv import fields, osv |
|||
from lxml import etree |
|||
from tools.translate import _ |
|||
from datetime import datetime |
|||
|
|||
def previous_year_date(date, nb_prev=1): |
|||
if not date: |
|||
return False |
|||
parsed_date = datetime.strptime(date, '%Y-%m-%d') |
|||
previous_date = datetime(year=parsed_date.year - nb_prev, |
|||
month=parsed_date.month, |
|||
day=parsed_date.day) |
|||
return previous_date |
|||
|
|||
class AccountBalanceCommonWizard(osv.osv_memory): |
|||
"""Will launch trial balance report and pass required args""" |
|||
|
|||
_inherit = "account.common.account.report" |
|||
_name = "account.common.balance.report" |
|||
_description = "Common Balance Report" |
|||
|
|||
# an update module should be done if changed |
|||
# in order to create fields in db |
|||
COMPARISON_LEVEL = 3 |
|||
|
|||
COMPARE_SELECTION = [('filter_no', 'No Comparison'), |
|||
('filter_year', 'Fiscal Year'), |
|||
('filter_date', 'Date'), |
|||
('filter_period', 'Periods'), |
|||
('filter_opening', 'Opening Only')] |
|||
|
|||
M2O_DYNAMIC_FIELDS = [f % index for f in ["comp%s_fiscalyear_id", |
|||
"comp%s_period_from", |
|||
"comp%s_period_to",] |
|||
for index in range(COMPARISON_LEVEL)] |
|||
SIMPLE_DYNAMIC_FIELDS = [f % index for f in ["comp%s_filter", |
|||
"comp%s_date_from", |
|||
"comp%s_date_to"] |
|||
for index in range(COMPARISON_LEVEL)] |
|||
DYNAMIC_FIELDS = M2O_DYNAMIC_FIELDS + SIMPLE_DYNAMIC_FIELDS |
|||
|
|||
def _get_account_ids(self, cr, uid, context=None): |
|||
res = False |
|||
if context.get('active_model', False) == 'account.account' and context.get('active_ids', False): |
|||
res = context['active_ids'] |
|||
return res |
|||
|
|||
_columns = { |
|||
'account_ids': fields.many2many('account.account', string='Filter on accounts', |
|||
help="Only selected accounts will be printed. Leave empty to print all accounts."), |
|||
'filter': fields.selection([('filter_no', 'No Filters'), |
|||
('filter_date', 'Date'), |
|||
('filter_period', 'Periods'), |
|||
('filter_opening', 'Opening Only')], "Filter by", required=True, help='Filter by date : no opening balance will be displayed. (opening balance can only be calculated based on period to be correct).'), |
|||
} |
|||
|
|||
for index in range(COMPARISON_LEVEL): |
|||
_columns.update( |
|||
{"comp%s_filter" % (index,): fields.selection(COMPARE_SELECTION, string='Compare By', required=True), |
|||
"comp%s_fiscalyear_id" % (index,): fields.many2one('account.fiscalyear', 'Fiscal Year'), |
|||
"comp%s_period_from" % (index,): fields.many2one('account.period', 'Start Period'), |
|||
"comp%s_period_to" % (index,): fields.many2one('account.period', 'End Period'), |
|||
"comp%s_date_from" % (index,): fields.date("Start Date"), |
|||
"comp%s_date_to" % (index,): fields.date("End Date"),}) |
|||
|
|||
_defaults = { |
|||
'account_ids': _get_account_ids, |
|||
} |
|||
|
|||
def _check_fiscalyear(self, cr, uid, ids, context=None): |
|||
obj = self.read(cr, uid, ids[0], ['fiscalyear_id', 'filter'], context=context) |
|||
if not obj['fiscalyear_id'] and obj['filter'] == 'filter_no': |
|||
return False |
|||
return True |
|||
|
|||
_constraints = [ |
|||
(_check_fiscalyear, 'When no Fiscal year is selected, you must choose to filter by periods or by date.', ['filter']), |
|||
] |
|||
|
|||
def default_get(self, cr, uid, fields, context=None): |
|||
""" |
|||
To get default values for the object. |
|||
|
|||
@param self: The object pointer. |
|||
@param cr: A database cursor |
|||
@param uid: ID of the user currently logged in |
|||
@param fields: List of fields for which we want default values |
|||
@param context: A standard dictionary |
|||
|
|||
@return: A dictionary which of fields with values. |
|||
|
|||
""" |
|||
res = super(AccountBalanceCommonWizard, self).default_get(cr, uid, fields, context=context) |
|||
for index in range(self.COMPARISON_LEVEL): |
|||
field = "comp%s_filter" % (index,) |
|||
if not res.get(field, False): |
|||
res[field] = 'filter_no' |
|||
return res |
|||
|
|||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): |
|||
res = super(AccountBalanceCommonWizard, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu) |
|||
|
|||
res['fields'].update(self.fields_get(cr, uid, |
|||
allfields=self.DYNAMIC_FIELDS, |
|||
context=context, write_access=True)) |
|||
|
|||
eview = etree.fromstring(res['arch']) |
|||
placeholder = eview.xpath("//page[@name='placeholder']") |
|||
if placeholder: |
|||
placeholder = placeholder[0] |
|||
for index in range(self.COMPARISON_LEVEL): |
|||
page = etree.Element('page', {'name': "comp%s" % (index,), 'string': _("Comparison %s") % (index+1,)}) |
|||
page.append(etree.Element('field', {'name': "comp%s_filter" % (index,), |
|||
'colspan': '4', |
|||
'on_change': "onchange_comp_filter(%(index)s, filter, comp%(index)s_filter, fiscalyear_id, date_from, date_to)" % {'index': index}})) |
|||
page.append(etree.Element('field', {'name': "comp%s_fiscalyear_id" % (index,), |
|||
'colspan': '4', |
|||
'attrs': "{'required': [('comp%(index)s_filter','in',('filter_year','filter_opening'))], 'readonly':[('comp%(index)s_filter','not in',('filter_year','filter_opening'))]}" % {'index': index}})) |
|||
page.append(etree.Element('separator', {'string': _('Dates'), 'colspan':'4'})) |
|||
page.append(etree.Element('field', {'name': "comp%s_date_from" % (index,), 'colspan':'4', |
|||
'attrs': "{'required': [('comp%(index)s_filter','=','filter_date')], 'readonly':[('comp%(index)s_filter','!=','filter_date')]}" % {'index': index}})) |
|||
page.append(etree.Element('field', {'name': "comp%s_date_to" % (index,), 'colspan':'4', |
|||
'attrs': "{'required': [('comp%(index)s_filter','=','filter_date')], 'readonly':[('comp%(index)s_filter','!=','filter_date')]}" % {'index': index}})) |
|||
page.append(etree.Element('separator', {'string': _('Periods'), 'colspan':'4'})) |
|||
page.append(etree.Element('field', {'name': "comp%s_period_from" % (index,), |
|||
'colspan': '4', |
|||
'attrs': "{'required': [('comp%(index)s_filter','=','filter_period')], 'readonly':[('comp%(index)s_filter','!=','filter_period')]}" % {'index': index}, |
|||
'domain': "[('special', '=', False)]"})) |
|||
page.append(etree.Element('field', {'name': "comp%s_period_to" % (index,), |
|||
'colspan': '4', |
|||
'attrs': "{'required': [('comp%(index)s_filter','=','filter_period')], 'readonly':[('comp%(index)s_filter','!=','filter_period')]}" % {'index': index}, |
|||
'domain': "[('special', '=', False)]"})) |
|||
|
|||
placeholder.addprevious(page) |
|||
placeholder.getparent().remove(placeholder) |
|||
res['arch'] = etree.tostring(eview) |
|||
return res |
|||
|
|||
def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): |
|||
res = {} |
|||
if filter == 'filter_no': |
|||
res['value'] = {'period_from': False, 'period_to': False, 'date_from': False ,'date_to': False} |
|||
if filter == 'filter_date': |
|||
if fiscalyear_id: |
|||
fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context) |
|||
date_from = fyear.date_start |
|||
date_to = fyear.date_stop > time.strftime('%Y-%m-%d') and time.strftime('%Y-%m-%d') or fyear.date_stop |
|||
else: |
|||
date_from, date_to = time.strftime('%Y-01-01'), time.strftime('%Y-%m-%d') |
|||
res['value'] = {'period_from': False, 'period_to': False, 'date_from': date_from, 'date_to': date_to} |
|||
if filter == 'filter_period' and fiscalyear_id: |
|||
start_period = end_period = False |
|||
cr.execute(''' |
|||
SELECT * FROM (SELECT p.id |
|||
FROM account_period p |
|||
LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id) |
|||
WHERE f.id = %s |
|||
AND COALESCE(p.special, FALSE) = FALSE |
|||
ORDER BY p.date_start ASC |
|||
LIMIT 1) AS period_start |
|||
UNION ALL |
|||
SELECT * FROM (SELECT p.id |
|||
FROM account_period p |
|||
LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id) |
|||
WHERE f.id = %s |
|||
AND p.date_start < NOW() |
|||
AND COALESCE(p.special, FALSE) = FALSE |
|||
ORDER BY p.date_stop DESC |
|||
LIMIT 1) AS period_stop''', (fiscalyear_id, fiscalyear_id)) |
|||
periods = [i[0] for i in cr.fetchall()] |
|||
if periods: |
|||
start_period = end_period = periods[0] |
|||
if len(periods) > 1: |
|||
end_period = periods[1] |
|||
res['value'] = {'period_from': start_period, 'period_to': end_period, 'date_from': False, 'date_to': False} |
|||
return res |
|||
|
|||
def onchange_comp_filter(self, cr, uid, ids, index, main_filter='filter_no', comp_filter='filter_no', fiscalyear_id=False, start_date=False, stop_date=False, context=None): |
|||
res = {} |
|||
fy_obj = self.pool.get('account.fiscalyear') |
|||
last_fiscalyear_id = False |
|||
if fiscalyear_id: |
|||
fiscalyear = fy_obj.browse(cr, uid, fiscalyear_id, context=context) |
|||
last_fiscalyear_ids = fy_obj.search(cr, uid, [('date_stop', '<', fiscalyear.date_start)], |
|||
limit=self.COMPARISON_LEVEL, order='date_start desc', context=context) |
|||
if last_fiscalyear_ids: |
|||
if len(last_fiscalyear_ids) > index: |
|||
last_fiscalyear_id = last_fiscalyear_ids[index] # first element for the comparison 1, second element for the comparison 2 |
|||
|
|||
fy_id_field = "comp%s_fiscalyear_id" % (index,) |
|||
period_from_field = "comp%s_period_from" % (index,) |
|||
period_to_field = "comp%s_period_to" % (index,) |
|||
date_from_field = "comp%s_date_from" % (index,) |
|||
date_to_field = "comp%s_date_to" % (index,) |
|||
|
|||
if comp_filter == 'filter_no': |
|||
res['value'] = {fy_id_field: False, period_from_field: False, period_to_field: False, date_from_field: False ,date_to_field: False} |
|||
if comp_filter in ('filter_year', 'filter_opening'): |
|||
res['value'] = {fy_id_field: last_fiscalyear_id, period_from_field: False, period_to_field: False, date_from_field: False ,date_to_field: False} |
|||
if comp_filter == 'filter_date': |
|||
dates = {} |
|||
if main_filter == 'filter_date': |
|||
dates = { |
|||
'date_start': previous_year_date(start_date, index + 1).strftime('%Y-%m-%d'), |
|||
'date_stop': previous_year_date(stop_date, index + 1).strftime('%Y-%m-%d'),} |
|||
elif last_fiscalyear_id: |
|||
dates = fy_obj.read(cr, uid, last_fiscalyear_id, ['date_start', 'date_stop'], context=context) |
|||
|
|||
res['value'] = {fy_id_field: False, period_from_field: False, period_to_field: False, date_from_field: dates.get('date_start', False), date_to_field: dates.get('date_stop', False)} |
|||
if comp_filter == 'filter_period' and last_fiscalyear_id: |
|||
start_period = end_period = False |
|||
cr.execute(''' |
|||
SELECT * FROM (SELECT p.id |
|||
FROM account_period p |
|||
LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id) |
|||
WHERE f.id = %(fiscalyear)s |
|||
AND COALESCE(p.special, FALSE) = FALSE |
|||
ORDER BY p.date_start ASC |
|||
LIMIT 1) AS period_start |
|||
UNION ALL |
|||
SELECT * FROM (SELECT p.id |
|||
FROM account_period p |
|||
LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id) |
|||
WHERE f.id = %(fiscalyear)s |
|||
AND p.date_start < NOW() |
|||
AND COALESCE(p.special, FALSE) = FALSE |
|||
ORDER BY p.date_stop DESC |
|||
LIMIT 1) AS period_stop''', {'fiscalyear': last_fiscalyear_id}) |
|||
periods = [i[0] for i in cr.fetchall()] |
|||
if periods and len(periods) > 1: |
|||
start_period = end_period = periods[0] |
|||
if len(periods) > 1: |
|||
end_period = periods[1] |
|||
res['value'] = {fy_id_field: False, |
|||
period_from_field: start_period, |
|||
period_to_field: end_period, |
|||
date_from_field: False, |
|||
date_to_field: False} |
|||
return res |
|||
|
|||
def pre_print_report(self, cr, uid, ids, data, context=None): |
|||
data = super(AccountBalanceCommonWizard, self).pre_print_report( |
|||
cr, uid, ids, data, context) |
|||
if context is None: |
|||
context = {} |
|||
|
|||
# will be used to attach the report on the main account |
|||
data['ids'] = [data['form']['chart_account_id']] |
|||
|
|||
fields_to_read = ['account_ids',] |
|||
fields_to_read += self.DYNAMIC_FIELDS |
|||
vals = self.read(cr, uid, ids, fields_to_read, context=context)[0] |
|||
|
|||
# extract the id from the m2o tuple (id, name) |
|||
for field in self.M2O_DYNAMIC_FIELDS: |
|||
if isinstance(vals[field], tuple): |
|||
vals[field] = vals[field][0] |
|||
|
|||
vals['max_comparison'] = self.COMPARISON_LEVEL |
|||
data['form'].update(vals) |
|||
return data |
|||
|
|||
AccountBalanceCommonWizard() |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<!-- inheriting views from more than 2 differents inherited models like |
|||
trial.balance.webkit -> account.common.balance.report -> account.common.account.report |
|||
is not supported so we have to copy paste the same view for trial balance, balance sheet, profit & loss |
|||
--> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,132 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi, Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import time |
|||
|
|||
from osv import fields, osv |
|||
|
|||
|
|||
class AccountReportGeneralLedgerWizard(osv.osv_memory): |
|||
"""Will launch general ledger report and pass requiered args""" |
|||
|
|||
|
|||
_inherit = "account.common.account.report" |
|||
_name = "general.ledger.webkit" |
|||
_description = "General Ledger Report" |
|||
|
|||
def _get_account_ids(self, cr, uid, context=None): |
|||
res = False |
|||
if context.get('active_model', False) == 'account.account' and context.get('active_ids', False): |
|||
res = context['active_ids'] |
|||
return res |
|||
|
|||
_columns = { |
|||
'amount_currency': fields.boolean("With Currency", |
|||
help="It adds the currency column"), |
|||
|
|||
'display_account': fields.selection([('bal_all', 'All'), |
|||
('bal_mix', 'With transactions or non zero balance')], |
|||
'Display accounts', |
|||
required=True), |
|||
'account_ids': fields.many2many('account.account', string='Filter on accounts', |
|||
help="""Only selected accounts will be printed. Leave empty to print all accounts."""), |
|||
'centralize': fields.boolean('Activate Centralization', help='Uncheck to display all the details of centralized accounts.') |
|||
} |
|||
_defaults = { |
|||
'amount_currency': False, |
|||
'display_account': 'bal_mix', |
|||
'account_ids': _get_account_ids, |
|||
'centralize': True, |
|||
} |
|||
|
|||
def _check_fiscalyear(self, cr, uid, ids, context=None): |
|||
obj = self.read(cr, uid, ids[0], ['fiscalyear_id', 'filter'], context=context) |
|||
if not obj['fiscalyear_id'] and obj['filter'] == 'filter_no': |
|||
return False |
|||
return True |
|||
|
|||
_constraints = [ |
|||
(_check_fiscalyear, 'When no Fiscal year is selected, you must choose to filter by periods or by date.', ['filter']), |
|||
] |
|||
|
|||
def pre_print_report(self, cr, uid, ids, data, context=None): |
|||
data = super(AccountReportGeneralLedgerWizard, self).pre_print_report(cr, uid, ids, data, context) |
|||
if context is None: |
|||
context = {} |
|||
# will be used to attach the report on the main account |
|||
data['ids'] = [data['form']['chart_account_id']] |
|||
vals = self.read(cr, uid, ids, |
|||
['amount_currency', |
|||
'display_account', |
|||
'account_ids', |
|||
'centralize'], |
|||
context=context)[0] |
|||
data['form'].update(vals) |
|||
return data |
|||
|
|||
def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): |
|||
res = {} |
|||
if filter == 'filter_no': |
|||
res['value'] = {'period_from': False, 'period_to': False, 'date_from': False ,'date_to': False} |
|||
if filter == 'filter_date': |
|||
if fiscalyear_id: |
|||
fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context) |
|||
date_from = fyear.date_start |
|||
date_to = fyear.date_stop > time.strftime('%Y-%m-%d') and time.strftime('%Y-%m-%d') or fyear.date_stop |
|||
else: |
|||
date_from, date_to = time.strftime('%Y-01-01'), time.strftime('%Y-%m-%d') |
|||
res['value'] = {'period_from': False, 'period_to': False, 'date_from': date_from, 'date_to': date_to} |
|||
if filter == 'filter_period' and fiscalyear_id: |
|||
start_period = end_period = False |
|||
cr.execute(''' |
|||
SELECT * FROM (SELECT p.id |
|||
FROM account_period p |
|||
LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id) |
|||
WHERE f.id = %s |
|||
AND COALESCE(p.special, FALSE) = FALSE |
|||
ORDER BY p.date_start ASC |
|||
LIMIT 1) AS period_start |
|||
UNION ALL |
|||
SELECT * FROM (SELECT p.id |
|||
FROM account_period p |
|||
LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id) |
|||
WHERE f.id = %s |
|||
AND p.date_start < NOW() |
|||
AND COALESCE(p.special, FALSE) = FALSE |
|||
ORDER BY p.date_stop DESC |
|||
LIMIT 1) AS period_stop''', (fiscalyear_id, fiscalyear_id)) |
|||
periods = [i[0] for i in cr.fetchall()] |
|||
if periods: |
|||
start_period = end_period = periods[0] |
|||
if len(periods) > 1: |
|||
end_period = periods[1] |
|||
res['value'] = {'period_from': start_period, 'period_to': end_period, 'date_from': False, 'date_to': False} |
|||
return res |
|||
|
|||
def _print_report(self, cursor, uid, ids, data, context=None): |
|||
context = context or {} |
|||
# we update form with display account value |
|||
data = self.pre_print_report(cursor, uid, ids, data, context=context) |
|||
return {'type': 'ir.actions.report.xml', |
|||
'report_name': 'account.account_report_general_ledger_webkit', |
|||
'datas': data} |
|||
|
|||
AccountReportGeneralLedgerWizard() |
@ -0,0 +1,89 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="account_report_general_ledger_view_webkit" model="ir.ui.view"> |
|||
<field name="name">General Ledger</field> |
|||
<field name="model">general.ledger.webkit</field> |
|||
<field name="type">form</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="General Ledger" colspan="4"/> |
|||
<label nolabel="1" colspan="4" string="This report allows you to print or generate a pdf of your general ledger with details of all your account journals"/> |
|||
</xpath> |
|||
<field name="chart_account_id" position='attributes'> |
|||
<attribute name="colspan">4</attribute> |
|||
</field> |
|||
<form position="inside"> |
|||
<field name="display_account" invisible="True"/> |
|||
</form> |
|||
<page name="filters" position="after"> |
|||
<page string="Accounts Filters" name="accounts"> |
|||
<separator string="Print only" colspan="4"/> |
|||
<field name="account_ids" colspan="4" nolabel="1"> |
|||
<tree> |
|||
<field name="code"/> |
|||
<field name="name"/> |
|||
<field name="type"/> |
|||
<field name="company_id"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page string="Layout Options" name="layout_options"> |
|||
<field name="amount_currency"/> |
|||
<field name="centralize"/> |
|||
</page> |
|||
</page> |
|||
<page name="journal_ids" position="attributes"> |
|||
<attribute name="invisible">True</attribute> |
|||
</page> |
|||
<page name="filters" position="attributes"> |
|||
<attribute name="string">Time Filters</attribute> |
|||
</page> |
|||
<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="account_report_general_ledger_view_inherit" model="ir.ui.view"> |
|||
<field name="name">General Ledger</field> |
|||
<field name="model">general.ledger.webkit</field> |
|||
<field name="type">form</field> |
|||
<field name="inherit_id" ref="account.account_report_general_ledger_view"/> |
|||
<field name="arch" type="xml"> |
|||
<field name="fiscalyear_id" position="replace"> |
|||
<field name="fiscalyear_id" on_change="onchange_fiscalyear(fiscalyear_id)"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_account_general_ledger_menu_webkit" model="ir.actions.act_window"> |
|||
<field name="name">General Ledger</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">general.ledger.webkit</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="view_id" ref="account_report_general_ledger_view_webkit"/> |
|||
<field name="target">new</field> |
|||
</record> |
|||
|
|||
<record model="ir.values" id="action_account_general_ledger_values_webkit"> |
|||
<field name="model_id" ref="account.model_account_account"/> |
|||
<field name="object" eval="1"/> |
|||
<field name="name">General Ledger</field> |
|||
<field name="key2">client_print_multi</field> |
|||
<field name="value" |
|||
eval="'ir.actions.act_window,' +str(ref('action_account_general_ledger_menu_webkit'))"/> |
|||
<field name="key">action</field> |
|||
<field name="model">account.account</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,126 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright Camptocamp SA 2012 |
|||
# |
|||
# 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 osv import fields, osv |
|||
|
|||
|
|||
class AccountReportOpenInvoicesWizard(osv.osv_memory): |
|||
"""Will launch partner ledger report and pass required args""" |
|||
|
|||
_inherit = "partners.ledger.webkit" |
|||
_name = "open.invoices.webkit" |
|||
_description = "Open Invoices Report" |
|||
|
|||
_columns = { |
|||
'group_by_currency':fields.boolean('Group Partner by currency'), |
|||
'until_date': fields.date("Clearance date", |
|||
required=True, |
|||
help="""The clearance date is essentially a tool used for debtors provisionning calculation. |
|||
|
|||
By default, this date is equal to the the end date (ie: 31/12/2011 if you select fy 2011). |
|||
|
|||
By amending the clearance date, you will be, for instance, able to answer the question : 'based on my last year end debtors open invoices, which invoices are still unpaid today (today is my clearance date)?' |
|||
""")} |
|||
|
|||
def _check_until_date(self, cr, uid, ids, context=None): |
|||
def get_key_id(obj, field): |
|||
return obj.get(field) and obj[field][0] or False |
|||
|
|||
obj = self.read(cr, uid, ids[0], ['fiscalyear_id', 'period_to', 'date_to', 'until_date'], context=context) |
|||
min_date = self.default_until_date(cr, uid, ids, |
|||
get_key_id(obj, 'fiscalyear_id'), |
|||
get_key_id(obj, 'period_to'), |
|||
obj['date_to'], |
|||
context=context) |
|||
if min_date and obj['until_date'] < min_date: |
|||
return False |
|||
return True |
|||
|
|||
_constraints = [ |
|||
(_check_until_date, 'Clearance date must be the very last date of the last period or later.', ['until_date']), |
|||
] |
|||
|
|||
def default_until_date(self, cursor, uid, ids, fiscalyear_id=False, period_id=False, date_to=False, context=None): |
|||
res_date = False |
|||
# first priority: period or date filters |
|||
if period_id: |
|||
res_date = self.pool.get('account.period').read(cursor, uid, period_id, ['date_stop'], context=context)['date_stop'] |
|||
elif date_to: |
|||
res_date = date_to |
|||
elif fiscalyear_id: |
|||
res_date = self.pool.get('account.fiscalyear').read(cursor, uid, fiscalyear_id, ['date_stop'], context=context)['date_stop'] |
|||
return res_date |
|||
|
|||
def onchange_fiscalyear(self, cursor, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None): |
|||
res = {'value': {}} |
|||
res['value']['until_date'] = self.default_until_date(cursor, uid, ids, |
|||
fiscalyear_id=fiscalyear, |
|||
period_id=period_id, |
|||
date_to=date_to, |
|||
context=context) |
|||
return res |
|||
|
|||
def onchange_date_to(self, cursor, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None): |
|||
res = {'value': {}} |
|||
res['value']['until_date'] = self.default_until_date(cursor, uid, ids, |
|||
fiscalyear_id=fiscalyear, |
|||
period_id=period_id, |
|||
date_to=date_to, |
|||
context=context) |
|||
return res |
|||
|
|||
def onchange_period_to(self, cursor, uid, ids, fiscalyear=False, period_id=False, date_to=False, until_date=False, context=None): |
|||
res = {'value': {}} |
|||
res['value']['until_date'] = self.default_until_date(cursor, uid, ids, |
|||
fiscalyear_id=fiscalyear, |
|||
period_id=period_id, |
|||
date_to=date_to, |
|||
context=context) |
|||
return res |
|||
|
|||
def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): |
|||
res = super(AccountReportOpenInvoicesWizard, self).onchange_filter(cr, uid, ids, filter=filter, fiscalyear_id=fiscalyear_id, context=context) |
|||
if res.get('value', False): |
|||
res['value']['until_date'] = self.default_until_date(cr, uid, ids, |
|||
fiscalyear_id=fiscalyear_id, |
|||
period_id=res['value'].get('period_to', False), |
|||
date_to=res['value'].get('date_to', False), |
|||
context=context) |
|||
return res |
|||
|
|||
def pre_print_report(self, cr, uid, ids, data, context=None): |
|||
data = super(AccountReportOpenInvoicesWizard, self).pre_print_report(cr, uid, ids, data, context) |
|||
if context is None: |
|||
context = {} |
|||
vals = self.read(cr, uid, ids, |
|||
['until_date', 'group_by_currency'], |
|||
context=context)[0] |
|||
data['form'].update(vals) |
|||
return data |
|||
|
|||
def _print_report(self, cursor, uid, ids, data, context=None): |
|||
context = context or {} |
|||
# we update form with display account value |
|||
data = self.pre_print_report(cursor, uid, ids, data, context=context) |
|||
return {'type': 'ir.actions.report.xml', |
|||
'report_name': 'account.account_report_open_invoices_webkit', |
|||
'datas': data} |
|||
|
|||
AccountReportOpenInvoicesWizard() |
@ -0,0 +1,73 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="account_open_invoices_view_webkit" model="ir.ui.view"> |
|||
<field name="name">Open Invoices Report</field> |
|||
<field name="model">open.invoices.webkit</field> |
|||
<field name="type">form</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="Open Invoices" colspan="4"/> |
|||
<label nolabel="1" colspan="4" string="This report allows you to print or generate a pdf of your open invoices per partner with details of all your payable/receivable account. Exclude full reconciled journal items."/> |
|||
</xpath> |
|||
<field name="chart_account_id" position='attributes'> |
|||
<attribute name="colspan">4</attribute> |
|||
</field> |
|||
<xpath expr="//field[@name='target_move']" position="after"> |
|||
<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 string="Layout Options" name="layout_options"> |
|||
<field name="amount_currency"/> |
|||
<field name="group_by_currency"/> |
|||
</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_open_invoices_menu_webkit" model="ir.actions.act_window"> |
|||
<field name="name">Open Invoices Report</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">open.invoices.webkit</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="view_id" ref="account_open_invoices_view_webkit"/> |
|||
<field name="target">new</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,64 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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 osv import fields, osv |
|||
|
|||
|
|||
class AccountPartnerBalanceWizard(osv.osv_memory): |
|||
"""Will launch partner balance report and pass required args""" |
|||
|
|||
_inherit = "account.common.balance.report" |
|||
_name = "partner.balance.webkit" |
|||
_description = "Partner Balance Report" |
|||
|
|||
_columns = { |
|||
'result_selection': fields.selection([('customer','Receivable Accounts'), |
|||
('supplier','Payable Accounts'), |
|||
('customer_supplier','Receivable and Payable Accounts')], |
|||
"Partner's", required=True), |
|||
'partner_ids': fields.many2many('res.partner', string='Filter on partner', |
|||
help="Only selected partners will be printed. Leave empty to print all partners."), |
|||
} |
|||
|
|||
_defaults = { |
|||
'result_selection': 'customer_supplier', |
|||
} |
|||
|
|||
def pre_print_report(self, cr, uid, ids, data, context=None): |
|||
data = super(AccountPartnerBalanceWizard, self).pre_print_report(cr, uid, ids, data, context) |
|||
if context is None: |
|||
context = {} |
|||
vals = self.read(cr, uid, ids, |
|||
['result_selection', 'partner_ids'], |
|||
context=context)[0] |
|||
data['form'].update(vals) |
|||
return data |
|||
|
|||
def _print_report(self, cursor, uid, ids, data, context=None): |
|||
context = context or {} |
|||
# we update form with display account value |
|||
data = self.pre_print_report(cursor, uid, ids, data, context=context) |
|||
|
|||
return {'type': 'ir.actions.report.xml', |
|||
'report_name': 'account.account_report_partner_balance_webkit', |
|||
'datas': data} |
|||
|
|||
AccountPartnerBalanceWizard() |
@ -0,0 +1,85 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<!-- inheriting views from more than 2 differents inherited models like |
|||
partner.balance.webkit -> account.common.balance.report -> account.common.account.report |
|||
is not supported so we have to copy paste the same view for partner balance, balance sheet, profit & loss |
|||
--> |
|||
<record id="account_partner_balance_view_webkit" model="ir.ui.view"> |
|||
<field name="name">Partner Balance</field> |
|||
<field name="model">partner.balance.webkit</field> |
|||
<field name="type">form</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="Partner Balance" colspan="4"/> |
|||
<label nolabel="1" colspan="4" string="This report is an analysis done by a partner, It is a PDF report containing one line per partner representing the cumulative credit balance"/> |
|||
</xpath> |
|||
<field name="chart_account_id" position='attributes'> |
|||
<attribute name="colspan">4</attribute> |
|||
</field> |
|||
<field name="target_move" position="after"> |
|||
<field name="result_selection" colspan="4"/> |
|||
</field> |
|||
<page name="filters" position="after"> |
|||
<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="type"/> |
|||
<field name="company_id"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page string="Partners Filters" name="accounts"> |
|||
<separator string="Print only" colspan="4"/> |
|||
<field name="partner_ids" colspan="4" nolabel="1"/> |
|||
</page> |
|||
<page name="placeholder"/> |
|||
</page> |
|||
<page name="journal_ids" position="attributes"> |
|||
<attribute name="invisible">True</attribute> |
|||
</page> |
|||
<page name="filters" position="attributes"> |
|||
<attribute name="string">Time Filters</attribute> |
|||
</page> |
|||
<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> |
|||
<field name="fiscalyear_id" position="attributes"> |
|||
<attribute name="attrs">{'required': [('filter', '=', 'filter_opening')]}</attribute> |
|||
</field> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_account_partner_balance_menu_webkit" model="ir.actions.act_window"> |
|||
<field name="name">Partner Balance</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">partner.balance.webkit</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="view_id" ref="account_partner_balance_view_webkit"/> |
|||
<field name="target">new</field> |
|||
</record> |
|||
|
|||
<record model="ir.values" id="action_account_partner_balance_values_webkit"> |
|||
<field name="model_id" ref="account.model_account_account"/> |
|||
<field name="object" eval="1"/> |
|||
<field name="name">Partner Balance</field> |
|||
<field name="key2">client_print_multi</field> |
|||
<field name="value" |
|||
eval="'ir.actions.act_window,' +str(ref('action_account_partner_balance_menu_webkit'))"/> |
|||
<field name="key">action</field> |
|||
<field name="model">account.account</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,116 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Nicolas Bessi, Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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/>. |
|||
# |
|||
############################################################################## |
|||
import time |
|||
|
|||
from osv import fields, osv |
|||
|
|||
|
|||
class AccountReportPartnersLedgerWizard(osv.osv_memory): |
|||
"""Will launch partner ledger report and pass required args""" |
|||
|
|||
_inherit = "account.common.partner.report" |
|||
_name = "partners.ledger.webkit" |
|||
_description = "Partner Ledger Report" |
|||
|
|||
_columns = { |
|||
'amount_currency': fields.boolean("With Currency", |
|||
help="It adds the currency column"), |
|||
'partner_ids': fields.many2many('res.partner', string='Filter on partner', |
|||
help="Only selected partners will be printed. Leave empty to print all partners."), |
|||
'filter': fields.selection([('filter_no', 'No Filters'), |
|||
('filter_date', 'Date'), |
|||
('filter_period', 'Periods')], "Filter by", required=True, help='Filter by date : no opening balance will be displayed. (opening balance can only be calculated based on period to be correct).'), |
|||
} |
|||
_defaults = { |
|||
'amount_currency': False, |
|||
'result_selection': 'customer_supplier', |
|||
} |
|||
|
|||
def _check_fiscalyear(self, cr, uid, ids, context=None): |
|||
obj = self.read(cr, uid, ids[0], ['fiscalyear_id', 'filter'], context=context) |
|||
if not obj['fiscalyear_id'] and obj['filter'] == 'filter_no': |
|||
return False |
|||
return True |
|||
|
|||
_constraints = [ |
|||
(_check_fiscalyear, 'When no Fiscal year is selected, you must choose to filter by periods or by date.', ['filter']), |
|||
] |
|||
|
|||
def onchange_filter(self, cr, uid, ids, filter='filter_no', fiscalyear_id=False, context=None): |
|||
res = {} |
|||
if filter == 'filter_no': |
|||
res['value'] = {'period_from': False, 'period_to': False, 'date_from': False ,'date_to': False} |
|||
if filter == 'filter_date': |
|||
if fiscalyear_id: |
|||
fyear = self.pool.get('account.fiscalyear').browse(cr, uid, fiscalyear_id, context=context) |
|||
date_from = fyear.date_start |
|||
date_to = fyear.date_stop > time.strftime('%Y-%m-%d') and time.strftime('%Y-%m-%d') or fyear.date_stop |
|||
else: |
|||
date_from, date_to = time.strftime('%Y-01-01'), time.strftime('%Y-%m-%d') |
|||
res['value'] = {'period_from': False, 'period_to': False, 'date_from': date_from, 'date_to': date_to} |
|||
if filter == 'filter_period' and fiscalyear_id: |
|||
start_period = end_period = False |
|||
cr.execute(''' |
|||
SELECT * FROM (SELECT p.id |
|||
FROM account_period p |
|||
LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id) |
|||
WHERE f.id = %s |
|||
AND COALESCE(p.special, FALSE) = FALSE |
|||
ORDER BY p.date_start ASC |
|||
LIMIT 1) AS period_start |
|||
UNION ALL |
|||
SELECT * FROM (SELECT p.id |
|||
FROM account_period p |
|||
LEFT JOIN account_fiscalyear f ON (p.fiscalyear_id = f.id) |
|||
WHERE f.id = %s |
|||
AND p.date_start < NOW() |
|||
AND COALESCE(p.special, FALSE) = FALSE |
|||
ORDER BY p.date_stop DESC |
|||
LIMIT 1) AS period_stop''', (fiscalyear_id, fiscalyear_id)) |
|||
periods = [i[0] for i in cr.fetchall()] |
|||
if periods: |
|||
start_period = end_period = periods[0] |
|||
if len(periods) > 1: |
|||
end_period = periods[1] |
|||
res['value'] = {'period_from': start_period, 'period_to': end_period, 'date_from': False, 'date_to': False} |
|||
return res |
|||
|
|||
def pre_print_report(self, cr, uid, ids, data, context=None): |
|||
data = super(AccountReportPartnersLedgerWizard, self).pre_print_report(cr, uid, ids, data, context) |
|||
if context is None: |
|||
context = {} |
|||
# will be used to attach the report on the main account |
|||
data['ids'] = [data['form']['chart_account_id']] |
|||
vals = self.read(cr, uid, ids, |
|||
['amount_currency', 'partner_ids',], |
|||
context=context)[0] |
|||
data['form'].update(vals) |
|||
return data |
|||
|
|||
def _print_report(self, cursor, uid, ids, data, context=None): |
|||
context = context or {} |
|||
# we update form with display account value |
|||
data = self.pre_print_report(cursor, uid, ids, data, context=context) |
|||
return {'type': 'ir.actions.report.xml', |
|||
'report_name': 'account.account_report_partners_ledger_webkit', |
|||
'datas': data} |
|||
|
|||
AccountReportPartnersLedgerWizard() |
@ -0,0 +1,69 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="account_partner_ledger_view_webkit" model="ir.ui.view"> |
|||
<field name="name">Partner Ledger</field> |
|||
<field name="model">partners.ledger.webkit</field> |
|||
<field name="type">form</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="Partner Ledger" colspan="4"/> |
|||
<label nolabel="1" colspan="4" string="This report allows you to print or generate a pdf of your partner ledger with details of all your payable/receivable account"/> |
|||
</xpath> |
|||
<field name="chart_account_id" position='attributes'> |
|||
<attribute name="colspan">4</attribute> |
|||
</field> |
|||
<xpath expr="//field[@name='target_move']" position="after"> |
|||
<field name="result_selection" colspan="4"/> |
|||
</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 string="Layout Options" name="layout_options"> |
|||
<field name="amount_currency"/> |
|||
</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="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_partners_ledger_menu_webkit" model="ir.actions.act_window"> |
|||
<field name="name">Partner Ledger</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">partners.ledger.webkit</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="view_id" ref="account_partner_ledger_view_webkit"/> |
|||
<field name="target">new</field> |
|||
</record> |
|||
|
|||
<record model="ir.values" id="action_account_partners_ledger_values_webkit"> |
|||
<field name="model_id" ref="account.model_account_account"/> |
|||
<field name="object" eval="1"/> |
|||
<field name="name">Partner Ledger</field> |
|||
<field name="key2">client_print_multi</field> |
|||
<field name="value" |
|||
eval="'ir.actions.act_window,' +str(ref('action_account_partners_ledger_menu_webkit'))"/> |
|||
<field name="key">action</field> |
|||
<field name="model">account.account</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,166 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Copyright (c) 2011 Camptocamp SA (http://www.camptocamp.com) |
|||
# |
|||
# Author : Guewen Baconnier (Camptocamp) |
|||
# |
|||
# WARNING: This program as such is intended to be used by professional |
|||
# programmers who take the whole responsability of assessing all potential |
|||
# consequences resulting from its eventual inadequacies and bugs |
|||
# End users who are looking for a ready-to-use solution with commercial |
|||
# garantees and support are strongly adviced to contract a Free Software |
|||
# Service Company |
|||
# |
|||
# This program is Free Software; you can redistribute it and/or |
|||
# modify it under the terms of the GNU General Public License |
|||
# as published by the Free Software Foundation; either version 2 |
|||
# 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 General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU General Public License |
|||
# along with this program; if not, write to the Free Software |
|||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|||
# |
|||
############################################################################## |
|||
|
|||
from lxml import etree |
|||
from tools.translate import _ |
|||
from osv import fields, osv |
|||
|
|||
LEVEL_STYLES = 6 |
|||
|
|||
DEFAULT_STYLES = { |
|||
'print': [True, True, True, True, True, True], |
|||
'size': [12, 11, 10, 9, 9, 9], |
|||
'bold': [True, True, True, False, False, False], |
|||
'italic': [False, False, False, False, False, False], |
|||
'underline': [False, False, False, False, False, False], |
|||
'uppercase': [True, True, False, False, False, False], |
|||
} |
|||
|
|||
class AccountProfitAndLossLedgerWizard(osv.osv_memory): |
|||
"""Will launch trial balance report and pass required args""" |
|||
|
|||
_inherit = "account.common.balance.report" |
|||
_name = "profit.loss.webkit" |
|||
_description = "Profit and Loss Report" |
|||
|
|||
_columns = { |
|||
'numbers_display': fields.selection([('normal', 'Normal'), ('round', 'Round (No decimal)'), ('kilo', 'Kilo')], 'Numbers Display', required=True) |
|||
} |
|||
|
|||
_defaults = { |
|||
'numbers_display': 'normal', |
|||
} |
|||
|
|||
def view_init(self, cr, uid, fields_list, context=None): |
|||
""" |
|||
Creates view dynamically and adding fields at runtime. |
|||
@param self: The object pointer. |
|||
@param cr: A database cursor |
|||
@param uid: ID of the user currently logged in |
|||
@param context: A standard dictionary |
|||
@return: New arch of view with new columns. |
|||
""" |
|||
res = super(AccountProfitAndLossLedgerWizard, self).view_init(cr, uid, fields_list, context=context) |
|||
for index in range(LEVEL_STYLES): |
|||
# create columns for each comparison page |
|||
self._columns.update({ |
|||
"level%s_print" % (index,): |
|||
fields.boolean('Print'), |
|||
"level%s_size" % (index,): |
|||
fields.integer('Size', required=True), |
|||
"level%s_bold" % (index,): |
|||
fields.boolean('Bold'), |
|||
"level%s_italic" % (index,): |
|||
fields.boolean('Italic'), |
|||
"level%s_underline" % (index,): |
|||
fields.boolean('Underline'), |
|||
"level%s_uppercase" % (index,): |
|||
fields.boolean('Uppercase'), |
|||
}) |
|||
return res |
|||
|
|||
def default_get(self, cr, uid, fields, context=None): |
|||
""" |
|||
To get default values for the object. |
|||
|
|||
@param self: The object pointer. |
|||
@param cr: A database cursor |
|||
@param uid: ID of the user currently logged in |
|||
@param fields: List of fields for which we want default values |
|||
@param context: A standard dictionary |
|||
|
|||
@return: A dictionary which of fields with values. |
|||
|
|||
""" |
|||
res = super(AccountProfitAndLossLedgerWizard, self).default_get(cr, uid, fields, context=context) |
|||
|
|||
for key, values in DEFAULT_STYLES.iteritems(): |
|||
for index in range(LEVEL_STYLES): |
|||
field = "level%s_%s" % (index, key) |
|||
if not res.get(field, False): |
|||
res[field] = values[index] |
|||
return res |
|||
|
|||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): |
|||
res = super(AccountProfitAndLossLedgerWizard, self).fields_view_get(cr, uid, view_id, view_type, context=context, toolbar=toolbar, submenu=submenu) |
|||
|
|||
eview = etree.fromstring(res['arch']) |
|||
placeholder = eview.xpath("//group[@name='levels']") |
|||
if placeholder: |
|||
placeholder = placeholder[0] |
|||
for index in range(LEVEL_STYLES): |
|||
# add fields |
|||
res['fields']["level%s_print" % (index,)] = {'string': "Print", 'type': 'boolean'} |
|||
res['fields']["level%s_size" % (index,)] = {'string': "Size", 'type': 'integer', 'required': True} |
|||
res['fields']["level%s_bold" % (index,)] = {'string': "Bold", 'type': 'boolean',} |
|||
res['fields']["level%s_italic" % (index,)] = {'string': "Italic", 'type': 'boolean',} |
|||
res['fields']["level%s_underline" % (index,)] = {'string': "Underline", 'type': 'boolean',} |
|||
res['fields']["level%s_uppercase" % (index,)] = {'string': "Uppercase", 'type': 'boolean'} |
|||
|
|||
common_attrs = "{'readonly': [('level%(index)s_print', '=', False)]}" % {'index': index} |
|||
group = etree.Element('group', {'name': "group_level_%s" % (index,), 'colspan':'4', 'col': '10'}) |
|||
group.append(etree.Element('separator', {'string': _('Level %s') % (index+1,), 'colspan':'2'})) |
|||
group.append(etree.Element('field', {'name': "level%s_print" % (index,), 'colspan': '8'})) |
|||
group.append(etree.Element('field', {'name': "level%s_size" % (index,), 'attrs': common_attrs})) |
|||
group.append(etree.Element('field', {'name': "level%s_bold" % (index,), 'attrs': common_attrs})) |
|||
group.append(etree.Element('field', {'name': "level%s_italic" % (index,), 'attrs': common_attrs})) |
|||
group.append(etree.Element('field', {'name': "level%s_underline" % (index,), 'attrs': common_attrs})) |
|||
group.append(etree.Element('field', {'name': "level%s_uppercase" % (index,), 'attrs': common_attrs})) |
|||
|
|||
placeholder.append(group) |
|||
res['arch'] = etree.tostring(eview) |
|||
return res |
|||
|
|||
def _print_report(self, cursor, uid, ids, data, context=None): |
|||
context = context or {} |
|||
# we update form with display account value |
|||
data = self.pre_print_report(cursor, uid, ids, data, context=context) |
|||
|
|||
fields_to_read = ['numbers_display',] |
|||
|
|||
# comparison fields |
|||
for index in range(LEVEL_STYLES): |
|||
fields_to_read.extend([ |
|||
"level%s_print" % (index,), |
|||
"level%s_size" % (index,), |
|||
"level%s_bold" % (index,), |
|||
"level%s_italic" % (index,), |
|||
"level%s_underline" % (index,), |
|||
"level%s_uppercase" % (index,), |
|||
]) |
|||
|
|||
vals = self.read(cursor, uid, ids, fields_to_read,context=context)[0] |
|||
|
|||
data['form'].update(vals) |
|||
return {'type': 'ir.actions.report.xml', |
|||
'report_name': 'account.account_report_profit_loss_webkit', |
|||
'datas': data} |
|||
|
|||
AccountProfitAndLossLedgerWizard() |
@ -0,0 +1,72 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="account_profit_loss_view_webkit" model="ir.ui.view"> |
|||
<field name="name">Profit and Loss Webkit</field> |
|||
<field name="model">profit.loss.webkit</field> |
|||
<field name="type">form</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="Profit and Loss" colspan="4"/> |
|||
<label nolabel="1" colspan="4" string="The Profit and Loss report gives you an overview of your company profit and loss in a single document"/> |
|||
</xpath> |
|||
<field name="chart_account_id" position='attributes'> |
|||
<attribute name="colspan">4</attribute> |
|||
</field> |
|||
<page name="filters" position="after"> |
|||
<page string="Display Options" name="display"> |
|||
<field name="numbers_display" colspan="4"/> |
|||
<group name="levels" colspan="4"/> |
|||
</page> |
|||
<page string="Accounts Filters" name="accounts"> |
|||
<separator string="Print only" colspan="4"/> |
|||
<field name="account_ids" colspan="4" nolabel="1" domain="[('type', '=', 'view'), ('user_type.report_type', 'in', ('expense', 'income'))]"> |
|||
<tree> |
|||
<field name="code"/> |
|||
<field name="name"/> |
|||
<field name="type"/> |
|||
<field name="company_id"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page name="placeholder"/> |
|||
</page> |
|||
<page name="journal_ids" position="attributes"> |
|||
<attribute name="invisible">True</attribute> |
|||
</page> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_account_profit_loss_menu_webkit" model="ir.actions.act_window"> |
|||
<field name="name">Profit and Loss Webkit</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">profit.loss.webkit</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="view_id" ref="account_profit_loss_view_webkit"/> |
|||
<field name="target">new</field> |
|||
</record> |
|||
|
|||
<!-- Profit & Loss report has not been tested, work in progress --> |
|||
|
|||
<!--<record model="ir.values" id="action_account_profit_loss_values_webkit">--> |
|||
<!--<field name="model_id" ref="account.model_account_account"/>--> |
|||
<!--<field name="object" eval="1"/>--> |
|||
<!--<field name="name">Profit and Loss Webkit</field>--> |
|||
<!--<field name="key2">client_print_multi</field>--> |
|||
<!--<field name="value"--> |
|||
<!--eval="'ir.actions.act_window,' +str(ref('action_account_profit_loss_menu_webkit'))"/>--> |
|||
<!--<field name="key">action</field>--> |
|||
<!--<field name="model">account.account</field>--> |
|||
<!--</record>--> |
|||
|
|||
<!--<menuitem icon="STOCK_PRINT" name="Profit and Loss Webkit"--> |
|||
<!--parent="account.final_accounting_reports" action="action_account_profit_loss_menu_webkit"--> |
|||
<!--groups="account.group_account_manager,account.group_account_user" id="menu_profit_loss_webkit"/>--> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,41 @@ |
|||
# -*- encoding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Author: Guewen Baconnier |
|||
# Copyright Camptocamp SA 2011 |
|||
# |
|||
# 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 osv import osv |
|||
|
|||
|
|||
class AccountTrialBalanceWizard(osv.osv_memory): |
|||
"""Will launch trial balance report and pass required args""" |
|||
|
|||
_inherit = "account.common.balance.report" |
|||
_name = "trial.balance.webkit" |
|||
_description = "Trial Balance Report" |
|||
|
|||
def _print_report(self, cursor, uid, ids, data, context=None): |
|||
context = context or {} |
|||
# we update form with display account value |
|||
data = self.pre_print_report(cursor, uid, ids, data, context=context) |
|||
|
|||
return {'type': 'ir.actions.report.xml', |
|||
'report_name': 'account.account_report_trial_balance_webkit', |
|||
'datas': data} |
|||
|
|||
AccountTrialBalanceWizard() |
@ -0,0 +1,78 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<!-- inheriting views from more than 2 differents inherited models like |
|||
trial.balance.webkit -> account.common.balance.report -> account.common.account.report |
|||
is not supported so we have to copy paste the same view for trial balance, balance sheet, profit & loss |
|||
--> |
|||
<record id="account_trial_balance_view_webkit" model="ir.ui.view"> |
|||
<field name="name">Trial Balance</field> |
|||
<field name="model">trial.balance.webkit</field> |
|||
<field name="type">form</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="Trial Balance" colspan="4"/> |
|||
<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"/> |
|||
</xpath> |
|||
<field name="chart_account_id" position='attributes'> |
|||
<attribute name="colspan">4</attribute> |
|||
</field> |
|||
<page name="filters" position="after"> |
|||
<page string="Accounts Filters" name="accounts"> |
|||
<separator string="Print only" colspan="4"/> |
|||
<field name="account_ids" colspan="4" nolabel="1" domain="[('type', '=', 'view')]"> |
|||
<tree> |
|||
<field name="code"/> |
|||
<field name="name"/> |
|||
<field name="type"/> |
|||
<field name="company_id"/> |
|||
</tree> |
|||
</field> |
|||
</page> |
|||
<page name="placeholder"/> |
|||
</page> |
|||
<page name="journal_ids" position="attributes"> |
|||
<attribute name="invisible">True</attribute> |
|||
</page> |
|||
<page name="filters" position="attributes"> |
|||
<attribute name="string">Time Filters</attribute> |
|||
</page> |
|||
<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> |
|||
<field name="fiscalyear_id" position="attributes"> |
|||
<attribute name="attrs">{'required': [('filter', '=', 'filter_opening')]}</attribute> |
|||
</field> |
|||
</data> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_account_trial_balance_menu_webkit" model="ir.actions.act_window"> |
|||
<field name="name">Trial Balance</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">trial.balance.webkit</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">form</field> |
|||
<field name="view_id" ref="account_trial_balance_view_webkit"/> |
|||
<field name="target">new</field> |
|||
</record> |
|||
|
|||
<record model="ir.values" id="action_account_trial_balance_values_webkit"> |
|||
<field name="model_id" ref="account.model_account_account"/> |
|||
<field name="object" eval="1"/> |
|||
<field name="name">Trial Balance</field> |
|||
<field name="key2">client_print_multi</field> |
|||
<field name="value" |
|||
eval="'ir.actions.act_window,' +str(ref('action_account_trial_balance_menu_webkit'))"/> |
|||
<field name="key">action</field> |
|||
<field name="model">account.account</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,4 @@ |
|||
<?xml version="1.0" ?> |
|||
<openerp> |
|||
<data> </data> |
|||
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue