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