[MODULE] +v1.1.0 from https://www.odoo.com/apps/7.0/account_financial_report_webkit/
[burette/account_financial_report_webkit.git] / report / open_invoices.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 # Author: Nicolas Bessi, Guewen Baconnier
5 # Copyright Camptocamp SA 2011
6 #
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.
11 #
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.
16 #
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/>.
19 #
20 ##############################################################################
21
22 from collections import defaultdict
23 from datetime import datetime
24 from itertools import groupby
25 from operator import itemgetter
26 from mako.template import Template
27
28
29 import openerp.addons
30 from openerp import pooler
31 from openerp.osv import osv
32 from openerp.report import report_sxw
33 from openerp.tools.translate import _
34 from openerp.addons.report_webkit import report_helper
35 from .common_partner_reports import CommonPartnersReportHeaderWebkit
36 from .webkit_parser_header_fix import HeaderFooterTextWebKitParser
37
38
39 def get_mako_template(obj, *args):
40 template_path = openerp.addons.get_module_resource(*args)
41 return Template(filename=template_path, input_encoding='utf-8')
42
43 report_helper.WebKitHelper.get_mako_template = get_mako_template
44
45
46 class PartnersOpenInvoicesWebkit(report_sxw.rml_parse, CommonPartnersReportHeaderWebkit):
47
48 def __init__(self, cursor, uid, name, context):
49 super(PartnersOpenInvoicesWebkit, self).__init__(cursor, uid, name, context=context)
50 self.pool = pooler.get_pool(self.cr.dbname)
51 self.cursor = self.cr
52
53 company = self.pool.get('res.users').browse(self.cr, uid, uid, context=context).company_id
54 header_report_name = ' - '.join((_('OPEN INVOICES REPORT'), company.name, company.currency_id.name))
55
56 footer_date_time = self.formatLang(str(datetime.today()), date_time=True)
57
58 self.localcontext.update({
59 'cr': cursor,
60 'uid': uid,
61 'report_name': _('Open Invoices Report'),
62 'display_account_raw': self._get_display_account_raw,
63 'filter_form': self._get_filter,
64 'target_move': self._get_target_move,
65 'amount_currency': self._get_amount_currency,
66 'display_partner_account': self._get_display_partner_account,
67 'display_target_move': self._get_display_target_move,
68 'additional_args': [
69 ('--header-font-name', 'Helvetica'),
70 ('--footer-font-name', 'Helvetica'),
71 ('--header-font-size', '10'),
72 ('--footer-font-size', '6'),
73 ('--header-left', header_report_name),
74 ('--header-spacing', '2'),
75 ('--footer-left', footer_date_time),
76 ('--footer-right', ' '.join((_('Page'), '[page]', _('of'), '[topage]'))),
77 ('--footer-line',),
78 ],
79 })
80
81 def _group_lines_by_currency(self, account_br):
82 account_br.grouped_ledger_lines = {}
83 if not account_br.ledger_lines:
84 return
85 for part_id, plane_lines in account_br.ledger_lines.items():
86 account_br.grouped_ledger_lines[part_id] = []
87 plane_lines.sort(key=itemgetter('currency_code'))
88 for curr, lines in groupby(plane_lines, key=itemgetter('currency_code')):
89 tmp = [x for x in lines]
90 account_br.grouped_ledger_lines[part_id].append((curr, tmp)) # I want to reiter many times
91
92 def set_context(self, objects, data, ids, report_type=None):
93 """Populate a ledger_lines attribute on each browse record that will be used
94 by mako template"""
95 new_ids = data['form']['chart_account_id']
96 # Account initial balance memoizer
97 init_balance_memoizer = {}
98 # Reading form
99 main_filter = self._get_form_param('filter', data, default='filter_no')
100 target_move = self._get_form_param('target_move', data, default='all')
101 start_date = self._get_form_param('date_from', data)
102 stop_date = self._get_form_param('date_to', data)
103 start_period = self.get_start_period_br(data)
104 stop_period = self.get_end_period_br(data)
105 fiscalyear = self.get_fiscalyear_br(data)
106 partner_ids = self._get_form_param('partner_ids', data)
107 result_selection = self._get_form_param('result_selection', data)
108 date_until = self._get_form_param('until_date', data)
109 chart_account = self._get_chart_account_id_br(data)
110 group_by_currency = self._get_form_param('group_by_currency', data)
111
112 if main_filter == 'filter_no' and fiscalyear:
113 start_period = self.get_first_fiscalyear_period(fiscalyear)
114 stop_period = self.get_last_fiscalyear_period(fiscalyear)
115
116 # Retrieving accounts
117 filter_type = ('payable', 'receivable')
118 if result_selection == 'customer':
119 filter_type = ('receivable',)
120 if result_selection == 'supplier':
121 filter_type = ('payable',)
122
123 account_ids = self.get_all_accounts(new_ids, exclude_type=['view'], only_type=filter_type)
124
125 if not account_ids:
126 raise osv.except_osv(_('Error'), _('No accounts to print.'))
127
128 # computation of ledeger lines
129 if main_filter == 'filter_date':
130 start = start_date
131 stop = stop_date
132 else:
133 start = start_period
134 stop = stop_period
135 ledger_lines_memoizer = self._compute_open_transactions_lines(account_ids,
136 main_filter,
137 target_move,
138 start,
139 stop,
140 date_until,
141 partner_filter=partner_ids)
142 objects = []
143 for account in self.pool.get('account.account').browse(self.cursor, self.uid, account_ids):
144 account.ledger_lines = ledger_lines_memoizer.get(account.id, {})
145 account.init_balance = init_balance_memoizer.get(account.id, {})
146 ## we have to compute partner order based on inital balance
147 ## and ledger line as we may have partner with init bal
148 ## that are not in ledger line and vice versa
149 ledg_lines_pids = ledger_lines_memoizer.get(account.id, {}).keys()
150 non_null_init_balances = dict([(ib, amounts) for ib, amounts in account.init_balance.iteritems()
151 if amounts['init_balance'] or amounts['init_balance_currency']])
152 init_bal_lines_pids = non_null_init_balances.keys()
153
154 account.partners_order = self._order_partners(ledg_lines_pids, init_bal_lines_pids)
155 account.ledger_lines = ledger_lines_memoizer.get(account.id, {})
156 if group_by_currency:
157 self._group_lines_by_currency(account)
158 objects.append(account)
159
160 self.localcontext.update({
161 'fiscalyear': fiscalyear,
162 'start_date': start_date,
163 'stop_date': stop_date,
164 'start_period': start_period,
165 'stop_period': stop_period,
166 'date_until': date_until,
167 'partner_ids': partner_ids,
168 'chart_account': chart_account,
169 })
170
171 return super(PartnersOpenInvoicesWebkit, self).set_context(objects, data, new_ids,
172 report_type=report_type)
173
174 def _compute_open_transactions_lines(self, accounts_ids, main_filter, target_move, start, stop, date_until=False, partner_filter=False):
175 res = defaultdict(dict)
176
177 ## we check if until date and date stop have the same value
178 if main_filter in ('filter_period', 'filter_no'):
179 date_stop = stop.date_stop
180 date_until_match = (date_stop == date_until)
181
182 elif main_filter == 'filter_date':
183 date_stop = stop
184 date_until_match = (stop == date_until)
185
186 else:
187 raise osv.except_osv(_('Unsuported filter'),
188 _('Filter has to be in filter date, period, or none'))
189
190 initial_move_lines_per_account = {}
191 if main_filter in ('filter_period', 'filter_no'):
192 initial_move_lines_per_account = self._tree_move_line_ids(
193 self._partners_initial_balance_line_ids(accounts_ids,
194 start,
195 partner_filter,
196 exclude_reconcile=True,
197 force_period_ids=False,
198 date_stop=date_stop), key='id')
199
200 for account_id in accounts_ids:
201 initial_move_lines_ids_per_partner = initial_move_lines_per_account.get(account_id, {})
202
203 # We get the move line ids of the account
204 move_line_ids_per_partner = self.get_partners_move_lines_ids(account_id,
205 main_filter,
206 start,
207 stop,
208 target_move,
209 exclude_reconcile=True,
210 partner_filter=partner_filter)
211
212 if not initial_move_lines_ids_per_partner and not move_line_ids_per_partner:
213 continue
214 for partner_id in list(set(initial_move_lines_ids_per_partner.keys() + move_line_ids_per_partner.keys())):
215 partner_line_ids = (move_line_ids_per_partner.get(partner_id, []) +
216 initial_move_lines_ids_per_partner.get(partner_id, []))
217
218 clearance_line_ids = []
219 if date_until and not date_until_match and partner_line_ids:
220 clearance_line_ids = self._get_clearance_move_line_ids(partner_line_ids, date_stop, date_until)
221 partner_line_ids += clearance_line_ids
222
223 lines = self._get_move_line_datas(list(set(partner_line_ids)))
224 for line in lines:
225 if line['id'] in initial_move_lines_ids_per_partner.get(partner_id, []):
226 line['is_from_previous_periods'] = True
227 if line['id'] in clearance_line_ids:
228 line['is_clearance_line'] = True
229
230 res[account_id][partner_id] = lines
231 return res
232
233
234 HeaderFooterTextWebKitParser('report.account.account_report_open_invoices_webkit',
235 'account.account',
236 'addons/account_financial_report_webkit/report/templates/account_report_open_invoices.mako',
237 parser=PartnersOpenInvoicesWebkit)