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