Merge lp:~alhashash/openobject-addons/trunk-faster-move-line-reconcile into lp:openobject-addons

Proposed by Mohammad Alhashash
Status: Needs review
Proposed branch: lp:~alhashash/openobject-addons/trunk-faster-move-line-reconcile
Merge into: lp:openobject-addons
Diff against target: 59 lines (+25/-21)
1 file modified
account/account_invoice.py (+25/-21)
To merge this branch: bzr merge lp:~alhashash/openobject-addons/trunk-faster-move-line-reconcile
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+219457@code.launchpad.net

Description of the change

When reconciling or updating large number of account move lines the process is extremely slow. Profiling shows that the bottleneck is account.invoice._get_invoice_from_reconcile() which triggers update of stored fields in related invoices. This functions uses the ORM to traverse move line and reconciliation records and to serach for invoices.

This patch uses SQL directly and bypasses the ORM in account.invoice._get_invoice_from_line() and account.invoice._get_invoice_from_reconcile() for up to two orders of magnitude faster reconcile and update operation for large number of move lines.

To post a comment you must log in.
9457. By Mohammad Alhashash

Fix typos and add comment.

9458. By Mohammad Alhashash

Enhance SQL query

Unmerged revisions

9458. By Mohammad Alhashash

Enhance SQL query

9457. By Mohammad Alhashash

Fix typos and add comment.

9456. By Mohammad Alhashash

Use SQL directly and bypass the ORM in account.invoice._get_invoice_from_line() and account.invoice._get_invoice_from_reconcile() for much faster account_move_line reconcilliation and update. Up to two orders of magnitude faster when updating/reconciling a lot of move lines.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'account/account_invoice.py'
2--- account/account_invoice.py 2014-05-07 17:01:12 +0000
3+++ account/account_invoice.py 2014-05-14 07:07:53 +0000
4@@ -187,30 +187,34 @@
5 return result
6
7 def _get_invoice_from_line(self, cr, uid, ids, context=None):
8- move = {}
9- for line in self.pool.get('account.move.line').browse(cr, uid, ids, context=context):
10- if line.reconcile_partial_id:
11- for line2 in line.reconcile_partial_id.line_partial_ids:
12- move[line2.move_id.id] = True
13- if line.reconcile_id:
14- for line2 in line.reconcile_id.line_id:
15- move[line2.move_id.id] = True
16- invoice_ids = []
17- if move:
18- invoice_ids = self.pool.get('account.invoice').search(cr, uid, [('move_id','in',move.keys())], context=context)
19+ '''Returns all invoices related to move lines (ids) or related to any reconciled move lines'''
20+ query = '''
21+ SELECT i.id
22+ FROM account_move_line l
23+ INNER JOIN
24+ ( SELECT coalesce(reconcile_id, reconcile_partial_id) id
25+ FROM account_move_line
26+ WHERE id IN %s AND (reconcile_id IS NOT NULL OR reconcile_partial_id IS NOT NULL)
27+ GROUP BY coalesce(reconcile_id, reconcile_partial_id)
28+ ) r
29+ ON r.id = l.reconcile_id OR r.id = l.reconcile_partial_id
30+ INNER JOIN account_invoice i ON i.move_id = l.move_id
31+ GROUP BY i.id;
32+ '''
33+ cr.execute(query, (tuple(ids),))
34+ invoice_ids = [invoice_id for (invoice_id,) in cr.fetchall()]
35 return invoice_ids
36
37 def _get_invoice_from_reconcile(self, cr, uid, ids, context=None):
38- move = {}
39- for r in self.pool.get('account.move.reconcile').browse(cr, uid, ids, context=context):
40- for line in r.line_partial_ids:
41- move[line.move_id.id] = True
42- for line in r.line_id:
43- move[line.move_id.id] = True
44-
45- invoice_ids = []
46- if move:
47- invoice_ids = self.pool.get('account.invoice').search(cr, uid, [('move_id','in',move.keys())], context=context)
48+ '''Returns all invoices related to move lines reconciled using ids'''
49+ query = '''
50+ SELECT i.id
51+ FROM account_move_line l JOIN account_invoice i ON i.move_id = l.move_id
52+ WHERE l.reconcile_id IN %(ids)s OR l.reconcile_partial_id IN %(ids)s
53+ GROUP BY i.id
54+ '''
55+ cr.execute(query, {'ids': tuple(ids)})
56+ invoice_ids = [invoice_id for (invoice_id,) in cr.fetchall()]
57 return invoice_ids
58
59 _name = "account.invoice"

Subscribers

People subscribed via source and target branches

to all changes: