Launchpad automatic translations update.
[odoo/odoo.git] / addons / account / report / account_aged_partner_balance.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
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 import time
23 from report import report_sxw
24 from common_report_header import common_report_header
25
26 class aged_trial_report(report_sxw.rml_parse, common_report_header):
27
28     def __init__(self, cr, uid, name, context):
29         super(aged_trial_report, self).__init__(cr, uid, name, context=context)
30         self.total_account = []
31         self.localcontext.update({
32             'time': time,
33             'get_lines_with_out_partner': self._get_lines_with_out_partner,
34             'get_lines': self._get_lines,
35             'get_total': self._get_total,
36             'get_direction': self._get_direction,
37             'get_for_period': self._get_for_period,
38             'get_company': self._get_company,
39             'get_currency': self._get_currency,
40             'get_partners':self._get_partners,
41             'get_account': self._get_account,
42             'get_fiscalyear': self._get_fiscalyear,
43             'get_target_move': self._get_target_move,
44         })
45
46     def set_context(self, objects, data, ids, report_type=None):
47         obj_move = self.pool.get('account.move.line')
48         ctx = data['form'].get('used_context', {})
49         ctx.update({'fiscalyear': False, 'all_fiscalyear': True})
50         self.query = obj_move._query_get(self.cr, self.uid, obj='l', context=ctx)
51         self.direction_selection = data['form'].get('direction_selection', 'past')
52         self.target_move = data['form'].get('target_move', 'all')
53         self.date_from = data['form'].get('date_from', time.strftime('%Y-%m-%d'))
54         if (data['form']['result_selection'] == 'customer' ):
55             self.ACCOUNT_TYPE = ['receivable']
56         elif (data['form']['result_selection'] == 'supplier'):
57             self.ACCOUNT_TYPE = ['payable']
58         else:
59             self.ACCOUNT_TYPE = ['payable','receivable']
60         lang_dict = self.pool.get('res.users').read(self.cr,self.uid,self.uid,['context_lang'])
61         data['lang'] = lang_dict.get('context_lang') or False
62         return super(aged_trial_report, self).set_context(objects, data, ids, report_type=report_type)
63
64     def _get_lines(self, form):
65         res = []
66         move_state = ['draft','posted']
67         if self.target_move == 'posted':
68             move_state = ['posted']
69         self.cr.execute('SELECT DISTINCT res_partner.id AS id,\
70                     res_partner.name AS name \
71                 FROM res_partner,account_move_line AS l, account_account, account_move am\
72                 WHERE (l.account_id=account_account.id) \
73                     AND (l.move_id=am.id) \
74                     AND (am.state IN %s)\
75                     AND (account_account.type IN %s)\
76                     AND account_account.active\
77                     AND ((reconcile_id IS NULL)\
78                        OR (reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
79                     AND (l.partner_id=res_partner.id)\
80                     AND (l.date <= %s)\
81                     AND ' + self.query + ' \
82                 ORDER BY res_partner.name', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, self.date_from,))
83         partners = self.cr.dictfetchall()
84         ## mise a 0 du total
85         for i in range(7):
86             self.total_account.append(0)
87         #
88         # Build a string like (1,2,3) for easy use in SQL query
89         partner_ids = [x['id'] for x in partners]
90         if not partner_ids:
91             return []
92         # This dictionary will store the debit-credit for all partners, using partner_id as key.
93
94         totals = {}
95         self.cr.execute('SELECT l.partner_id, SUM(l.debit-l.credit) \
96                     FROM account_move_line AS l, account_account, account_move am \
97                     WHERE (l.account_id = account_account.id) AND (l.move_id=am.id) \
98                     AND (am.state IN %s)\
99                     AND (account_account.type IN %s)\
100                     AND (l.partner_id IN %s)\
101                     AND ((l.reconcile_id IS NULL)\
102                     OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
103                     AND ' + self.query + '\
104                     AND account_account.active\
105                     AND (l.date <= %s)\
106                     GROUP BY l.partner_id ', (tuple(move_state), tuple(self.ACCOUNT_TYPE), tuple(partner_ids), self.date_from, self.date_from,))
107         t = self.cr.fetchall()
108         for i in t:
109             totals[i[0]] = i[1]
110
111         # This dictionary will store the future or past of all partners
112         future_past = {}
113         if self.direction_selection == 'future':
114             self.cr.execute('SELECT l.partner_id, SUM(l.debit-l.credit) \
115                         FROM account_move_line AS l, account_account, account_move am \
116                         WHERE (l.account_id=account_account.id) AND (l.move_id=am.id) \
117                         AND (am.state IN %s)\
118                         AND (account_account.type IN %s)\
119                         AND (COALESCE(l.date_maturity, l.date) < %s)\
120                         AND (l.partner_id IN %s)\
121                         AND ((l.reconcile_id IS NULL)\
122                         OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
123                         AND '+ self.query + '\
124                         AND account_account.active\
125                     AND (l.date <= %s)\
126                         GROUP BY l.partner_id', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, tuple(partner_ids),self.date_from, self.date_from,))
127             t = self.cr.fetchall()
128             for i in t:
129                 future_past[i[0]] = i[1]
130         elif self.direction_selection == 'past': # Using elif so people could extend without this breaking
131             self.cr.execute('SELECT l.partner_id, SUM(l.debit-l.credit) \
132                     FROM account_move_line AS l, account_account, account_move am \
133                     WHERE (l.account_id=account_account.id) AND (l.move_id=am.id)\
134                         AND (am.state IN %s)\
135                         AND (account_account.type IN %s)\
136                         AND (COALESCE(l.date_maturity,l.date) > %s)\
137                         AND (l.partner_id IN %s)\
138                         AND ((l.reconcile_id IS NULL)\
139                         OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
140                         AND '+ self.query + '\
141                         AND account_account.active\
142                     AND (l.date <= %s)\
143                         GROUP BY l.partner_id', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, tuple(partner_ids), self.date_from, self.date_from,))
144             t = self.cr.fetchall()
145             for i in t:
146                 future_past[i[0]] = i[1]
147
148         # Use one query per period and store results in history (a list variable)
149         # Each history will contain: history[1] = {'<partner_id>': <partner_debit-credit>}
150         history = []
151         for i in range(5):
152             args_list = (tuple(move_state), tuple(self.ACCOUNT_TYPE), tuple(partner_ids),self.date_from,)
153             dates_query = '(COALESCE(l.date_maturity,l.date)'
154             if form[str(i)]['start'] and form[str(i)]['stop']:
155                 dates_query += ' BETWEEN %s AND %s)'
156                 args_list += (form[str(i)]['start'], form[str(i)]['stop'])
157             elif form[str(i)]['start']:
158                 dates_query += ' > %s)'
159                 args_list += (form[str(i)]['start'],)
160             else:
161                 dates_query += ' < %s)'
162                 args_list += (form[str(i)]['stop'],)
163             args_list += (self.date_from,)
164             self.cr.execute('''SELECT l.partner_id, SUM(l.debit-l.credit)
165                     FROM account_move_line AS l, account_account, account_move am 
166                     WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)
167                         AND (am.state IN %s)
168                         AND (account_account.type IN %s)
169                         AND (l.partner_id IN %s)
170                         AND ((l.reconcile_id IS NULL)
171                           OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))
172                         AND ''' + self.query + '''
173                         AND account_account.active
174                         AND ''' + dates_query + '''
175                     AND (l.date <= %s)
176                     GROUP BY l.partner_id''', args_list)
177             t = self.cr.fetchall()
178             d = {}
179             for i in t:
180                 d[i[0]] = i[1]
181             history.append(d)
182
183         for partner in partners:
184             values = {}
185             ## If choise selection is in the future
186             if self.direction_selection == 'future':
187                 # Query here is replaced by one query which gets the all the partners their 'before' value
188                 before = False
189                 if future_past.has_key(partner['id']):
190                     before = [ future_past[partner['id']] ]
191                 self.total_account[6] = self.total_account[6] + (before and before[0] or 0.0)
192                 values['direction'] = before and before[0] or 0.0
193             elif self.direction_selection == 'past': # Changed this so people could in the future create new direction_selections
194                 # Query here is replaced by one query which gets the all the partners their 'after' value
195                 after = False
196                 if future_past.has_key(partner['id']): # Making sure this partner actually was found by the query
197                     after = [ future_past[partner['id']] ]
198
199                 self.total_account[6] = self.total_account[6] + (after and after[0] or 0.0)
200                 values['direction'] = after and after[0] or 0.0
201
202             for i in range(5):
203                 during = False
204                 if history[i].has_key(partner['id']):
205                     during = [ history[i][partner['id']] ]
206                 # Ajout du compteur
207                 self.total_account[(i)] = self.total_account[(i)] + (during and during[0] or 0)
208                 values[str(i)] = during and during[0] or 0.0
209             total = False
210             if totals.has_key( partner['id'] ):
211                 total = [ totals[partner['id']] ]
212             values['total'] = total and total[0] or 0.0
213             ## Add for total
214             self.total_account[(i+1)] = self.total_account[(i+1)] + (total and total[0] or 0.0)
215             values['name'] = partner['name']
216
217             res.append(values)
218
219         total = 0.0
220         totals = {}
221         for r in res:
222             total += float(r['total'] or 0.0)
223             for i in range(5)+['direction']:
224                 totals.setdefault(str(i), 0.0)
225                 totals[str(i)] += float(r[str(i)] or 0.0)
226         return res
227
228     def _get_lines_with_out_partner(self, form):
229         res = []
230         move_state = ['draft','posted']
231         if self.target_move == 'posted':
232             move_state = ['posted']
233
234         ## mise a 0 du total
235         for i in range(7):
236             self.total_account.append(0)
237         totals = {}
238         self.cr.execute('SELECT SUM(l.debit-l.credit) \
239                     FROM account_move_line AS l, account_account, account_move am \
240                     WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)\
241                     AND (am.state IN %s)\
242                     AND (l.partner_id IS NULL)\
243                     AND (account_account.type IN %s)\
244                     AND ((l.reconcile_id IS NULL) \
245                     OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
246                     AND ' + self.query + '\
247                     AND (l.date <= %s)\
248                     AND account_account.active ',(tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, self.date_from,))
249         t = self.cr.fetchall()
250         for i in t:
251             totals['Unknown Partner'] = i[0]
252         future_past = {}
253         if self.direction_selection == 'future':
254             self.cr.execute('SELECT SUM(l.debit-l.credit) \
255                         FROM account_move_line AS l, account_account, account_move am\
256                         WHERE (l.account_id=account_account.id) AND (l.move_id=am.id)\
257                         AND (am.state IN %s)\
258                         AND (l.partner_id IS NULL)\
259                         AND (account_account.type IN %s)\
260                         AND (COALESCE(l.date_maturity, l.date) < %s)\
261                         AND ((l.reconcile_id IS NULL)\
262                         OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
263                         AND '+ self.query + '\
264                         AND account_account.active ', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, self.date_from))
265             t = self.cr.fetchall()
266             for i in t:
267                 future_past['Unknown Partner'] = i[0]
268         elif self.direction_selection == 'past': # Using elif so people could extend without this breaking
269             self.cr.execute('SELECT SUM(l.debit-l.credit) \
270                     FROM account_move_line AS l, account_account, account_move am \
271                     WHERE (l.account_id=account_account.id) AND (l.move_id=am.id)\
272                         AND (am.state IN %s)\
273                         AND (l.partner_id IS NULL)\
274                         AND (account_account.type IN %s)\
275                         AND (COALESCE(l.date_maturity,l.date) > %s)\
276                         AND ((l.reconcile_id IS NULL)\
277                         OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
278                         AND '+ self.query + '\
279                         AND account_account.active ', (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from, self.date_from))
280             t = self.cr.fetchall()
281             for i in t:
282                 future_past['Unknown Partner'] = i[0]
283         history = []
284
285         for i in range(5):
286             args_list = (tuple(move_state), tuple(self.ACCOUNT_TYPE), self.date_from,)
287             dates_query = '(COALESCE(l.date_maturity,l.date)'
288             if form[str(i)]['start'] and form[str(i)]['stop']:
289                 dates_query += ' BETWEEN %s AND %s)'
290                 args_list += (form[str(i)]['start'], form[str(i)]['stop'])
291             elif form[str(i)]['start']:
292                 dates_query += ' > %s)'
293                 args_list += (form[str(i)]['start'],)
294             else:
295                 dates_query += ' < %s)'
296                 args_list += (form[str(i)]['stop'],)
297             args_list += (self.date_from,)
298             self.cr.execute('SELECT SUM(l.debit-l.credit)\
299                     FROM account_move_line AS l, account_account, account_move am \
300                     WHERE (l.account_id = account_account.id) AND (l.move_id=am.id)\
301                         AND (am.state IN %s)\
302                         AND (account_account.type IN %s)\
303                         AND (l.partner_id IS NULL)\
304                         AND ((l.reconcile_id IS NULL)\
305                         OR (l.reconcile_id IN (SELECT recon.id FROM account_move_reconcile AS recon WHERE recon.create_date > %s )))\
306                         AND '+ self.query + '\
307                         AND account_account.active\
308                         AND ' + dates_query + '\
309                     AND (l.date <= %s)\
310                     GROUP BY l.partner_id', args_list)
311             t = self.cr.fetchall()
312             d = {}
313             for i in t:
314                 d['Unknown Partner'] = i[0]
315             history.append(d)
316
317         values = {}
318         if self.direction_selection == 'future':
319             before = False
320             if future_past.has_key('Unknown Partner'):
321                 before = [ future_past['Unknown Partner'] ]
322             self.total_account[6] = self.total_account[6] + (before and before[0] or 0.0)
323             values['direction'] = before and before[0] or 0.0
324         elif self.direction_selection == 'past':
325             after = False
326             if future_past.has_key('Unknown Partner'):
327                 after = [ future_past['Unknown Partner'] ]
328             self.total_account[6] = self.total_account[6] + (after and after[0] or 0.0)
329             values['direction'] = after and after[0] or 0.0
330
331         for i in range(5):
332             during = False
333             if history[i].has_key('Unknown Partner'):
334                 during = [ history[i]['Unknown Partner'] ]
335             self.total_account[(i)] = self.total_account[(i)] + (during and during[0] or 0)
336             values[str(i)] = during and during[0] or 0.0
337
338         total = False
339         if totals.has_key( 'Unknown Partner' ):
340             total = [ totals['Unknown Partner'] ]
341         values['total'] = total and total[0] or 0.0
342         ## Add for total
343         self.total_account[(i+1)] = self.total_account[(i+1)] + (total and total[0] or 0.0)
344         values['name'] = 'Unknown Partner'
345
346         if values['total']:
347             res.append(values)
348
349         total = 0.0
350         totals = {}
351         for r in res:
352             total += float(r['total'] or 0.0)
353             for i in range(5)+['direction']:
354                 totals.setdefault(str(i), 0.0)
355                 totals[str(i)] += float(r[str(i)] or 0.0)
356         return res
357
358     def _get_total(self,pos):
359         period = self.total_account[int(pos)]
360         return period or 0.0
361
362     def _get_direction(self,pos):
363         period = self.total_account[int(pos)]
364         return period or 0.0
365
366     def _get_for_period(self,pos):
367         period = self.total_account[int(pos)]
368         return period or 0.0
369
370     def _get_partners(self,data):
371         if data['form']['result_selection'] == 'customer':
372             return 'Receivable Accounts'
373         elif data['form']['result_selection'] == 'supplier':
374             return 'Payable Accounts'
375         elif data['form']['result_selection'] == 'customer_supplier':
376             return 'Receivable and Payable Accounts'
377         return ''
378
379 report_sxw.report_sxw('report.account.aged_trial_balance', 'res.partner',
380         'addons/account/report/account_aged_partner_balance.rml',parser=aged_trial_report, header="internal landscape")
381
382
383 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: