1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # Author: Nicolas Bessi, Guewen Baconnier
5 # Copyright Camptocamp SA 2011
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ##############################################################################
22 from operator
import itemgetter
23 from itertools
import groupby
24 from datetime
import datetime
26 from openerp
.report
import report_sxw
27 from openerp
import pooler
28 from openerp
.tools
.translate
import _
29 from .common_reports
import CommonReportHeaderWebkit
30 from .webkit_parser_header_fix
import HeaderFooterTextWebKitParser
33 class GeneralLedgerWebkit(report_sxw
.rml_parse
, CommonReportHeaderWebkit
):
35 def __init__(self
, cursor
, uid
, name
, context
):
36 super(GeneralLedgerWebkit
, self
).__init
__(cursor
, uid
, name
, context
=context
)
37 self
.pool
= pooler
.get_pool(self
.cr
.dbname
)
40 company
= self
.pool
.get('res.users').browse(self
.cr
, uid
, uid
, context
=context
).company_id
41 header_report_name
= ' - '.join((_('GENERAL LEDGER'), company
.name
, company
.currency_id
.name
))
43 footer_date_time
= self
.formatLang(str(datetime
.today()), date_time
=True)
45 self
.localcontext
.update({
48 'report_name': _('General Ledger'),
49 'display_account': self
._get
_display
_account
,
50 'display_account_raw': self
._get
_display
_account
_raw
,
51 'filter_form': self
._get
_filter
,
52 'target_move': self
._get
_target
_move
,
53 'initial_balance': self
._get
_initial
_balance
,
54 'amount_currency': self
._get
_amount
_currency
,
55 'display_target_move': self
._get
_display
_target
_move
,
56 'accounts': self
._get
_accounts
_br
,
58 ('--header-font-name', 'Helvetica'),
59 ('--footer-font-name', 'Helvetica'),
60 ('--header-font-size', '10'),
61 ('--footer-font-size', '6'),
62 ('--header-left', header_report_name
),
63 ('--header-spacing', '2'),
64 ('--footer-left', footer_date_time
),
65 ('--footer-right', ' '.join((_('Page'), '[page]', _('of'), '[topage]'))),
70 def set_context(self
, objects
, data
, ids
, report_type
=None):
71 """Populate a ledger_lines attribute on each browse record that will be used
73 new_ids
= data
['form']['account_ids'] or data
['form']['chart_account_id']
75 # Account initial balance memoizer
76 init_balance_memoizer
= {}
79 main_filter
= self
._get
_form
_param
('filter', data
, default
='filter_no')
80 target_move
= self
._get
_form
_param
('target_move', data
, default
='all')
81 start_date
= self
._get
_form
_param
('date_from', data
)
82 stop_date
= self
._get
_form
_param
('date_to', data
)
83 do_centralize
= self
._get
_form
_param
('centralize', data
)
84 start_period
= self
.get_start_period_br(data
)
85 stop_period
= self
.get_end_period_br(data
)
86 fiscalyear
= self
.get_fiscalyear_br(data
)
87 chart_account
= self
._get
_chart
_account
_id
_br
(data
)
89 if main_filter
== 'filter_no':
90 start_period
= self
.get_first_fiscalyear_period(fiscalyear
)
91 stop_period
= self
.get_last_fiscalyear_period(fiscalyear
)
93 # computation of ledger lines
94 if main_filter
== 'filter_date':
101 initial_balance
= self
.is_initial_balance_enabled(main_filter
)
102 initial_balance_mode
= initial_balance
and self
._get
_initial
_balance
_mode
(start
) or False
104 # Retrieving accounts
105 accounts
= self
.get_all_accounts(new_ids
, exclude_type
=['view'])
106 if initial_balance_mode
== 'initial_balance':
107 init_balance_memoizer
= self
._compute
_initial
_balances
(accounts
, start
, fiscalyear
)
108 elif initial_balance_mode
== 'opening_balance':
109 init_balance_memoizer
= self
._read
_opening
_balance
(accounts
, start
)
111 ledger_lines_memoizer
= self
._compute
_account
_ledger
_lines
(accounts
, init_balance_memoizer
,
112 main_filter
, target_move
, start
, stop
)
114 for account
in self
.pool
.get('account.account').browse(self
.cursor
, self
.uid
, accounts
):
115 if do_centralize
and account
.centralized
and ledger_lines_memoizer
.get(account
.id):
116 account
.ledger_lines
= self
._centralize
_lines
(main_filter
, ledger_lines_memoizer
.get(account
.id, []))
118 account
.ledger_lines
= ledger_lines_memoizer
.get(account
.id, [])
119 account
.init_balance
= init_balance_memoizer
.get(account
.id, {})
121 objects
.append(account
)
123 self
.localcontext
.update({
124 'fiscalyear': fiscalyear
,
125 'start_date': start_date
,
126 'stop_date': stop_date
,
127 'start_period': start_period
,
128 'stop_period': stop_period
,
129 'chart_account': chart_account
,
130 'initial_balance_mode': initial_balance_mode
,
133 return super(GeneralLedgerWebkit
, self
).set_context(objects
, data
, new_ids
,
134 report_type
=report_type
)
136 def _centralize_lines(self
, filter, ledger_lines
, context
=None):
137 """ Group by period in filter mode 'period' or on one line in filter mode 'date'
138 ledger_lines parameter is a list of dict built by _get_ledger_lines"""
139 def group_lines(lines
):
142 sums
= reduce(lambda line
, memo
: dict((key
, value
+ memo
[key
]) for key
, value
143 in line
.iteritems() if key
in ('balance', 'debit', 'credit')), lines
)
146 'balance': sums
['balance'],
147 'debit': sums
['debit'],
148 'credit': sums
['credit'],
149 'lname': _('Centralized Entries'),
150 'account_id': lines
[0]['account_id'],
154 centralized_lines
= []
155 if filter == 'filter_date':
156 # by date we centralize all entries in only one line
157 centralized_lines
.append(group_lines(ledger_lines
))
160 # by period we centralize all entries in one line per period
161 period_obj
= self
.pool
.get('account.period')
162 # we need to sort the lines per period in order to use groupby
163 # unique ids of each used period id in lines
164 period_ids
= list(set([line
['lperiod_id'] for line
in ledger_lines
]))
165 # search on account.period in order to sort them by date_start
166 sorted_period_ids
= period_obj
.search(self
.cr
, self
.uid
,
167 [('id', 'in', period_ids
)],
168 order
='special desc, date_start',
170 sorted_ledger_lines
= sorted(ledger_lines
, key
=lambda x
: sorted_period_ids
.index(x
['lperiod_id']))
172 for period_id
, lines_per_period_iterator
in groupby(sorted_ledger_lines
, itemgetter('lperiod_id')):
173 lines_per_period
= list(lines_per_period_iterator
)
174 if not lines_per_period
:
176 group_per_period
= group_lines(lines_per_period
)
177 group_per_period
.update({
178 'lperiod_id': period_id
,
179 'period_code': lines_per_period
[0]['period_code'], # period code is anyway the same on each line per period
181 centralized_lines
.append(group_per_period
)
183 return centralized_lines
185 def _compute_account_ledger_lines(self
, accounts_ids
, init_balance_memoizer
, main_filter
,
186 target_move
, start
, stop
):
188 for acc_id
in accounts_ids
:
189 move_line_ids
= self
.get_move_lines_ids(acc_id
, main_filter
, start
, stop
, target_move
)
190 if not move_line_ids
:
194 lines
= self
._get
_ledger
_lines
(move_line_ids
, acc_id
)
198 def _get_ledger_lines(self
, move_line_ids
, account_id
):
199 if not move_line_ids
:
201 res
= self
._get
_move
_line
_datas
(move_line_ids
)
202 ## computing counter part is really heavy in term of ressouces consuption
203 ## looking for a king of SQL to help me improve it
204 move_ids
= [x
.get('move_id') for x
in res
]
205 counter_parts
= self
._get
_moves
_counterparts
(move_ids
, account_id
)
207 line
['counterparts'] = counter_parts
.get(line
.get('move_id'), '')
211 HeaderFooterTextWebKitParser('report.account.account_report_general_ledger_webkit',
213 'addons/account_financial_report_webkit/report/templates/account_report_general_ledger.mako',
214 parser
=GeneralLedgerWebkit
)