Speed Improvement:

Nested Trees
	Multiple Fields Computation at once

bzr revid: fp@tinyerp.com-20080817182944-vq0kp64i93ceull9
This commit is contained in:
Fabien Pinckaers 2008-08-17 20:29:44 +02:00
parent d88fb99fe4
commit f7e6fcc3ce
2 changed files with 37 additions and 80 deletions

View File

@ -156,89 +156,46 @@ class account_account(osv.osv):
return super(account_account,self).search(cr, uid, args, offset, limit, return super(account_account,self).search(cr, uid, args, offset, limit,
order, context=context, count=count) order, context=context, count=count)
def _credit(self, cr, uid, ids, field_name, arg, context={}): # def _credit(self, cr, uid, ids, field_name, arg, context={}):
acc_set = ",".join(map(str, ids)) # return self.__compute(cr, uid, ids, field_name, arg, context, 'COALESCE(SUM(l.credit), 0)')
query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) #
cr.execute(("SELECT a.id, " \ # def _debit(self, cr, uid, ids, field_name, arg, context={}):
"SUM(COALESCE(l.credit * a.sign, 0)) " \ # return self.__compute(cr, uid, ids, field_name, arg, context, 'COALESCE(SUM(l.debit), 0)')
"FROM account_account a " \ #
"LEFT JOIN account_move_line l " \ # def _balance(self, cr, uid, ids, field_name, arg, context={}):
"ON (a.id = l.account_id) " \ # return self.__compute(cr, uid, ids, field_name, arg, context, 'COALESCE(SUM(l.debit) - SUM(l.credit), 0)')
"WHERE a.type != 'view' " \
"AND a.id IN (%s) " \
"AND " + query + " " \
"AND a.active " \
"GROUP BY a.id") % (acc_set, ))
res2 = cr.fetchall()
res = {}
for id in ids:
res[id] = 0.0
for account_id, sum in res2:
res[account_id] += sum
return res
def _debit(self, cr, uid, ids, field_name, arg, context={}): def __compute(self, cr, uid, ids, field_names, arg, context={}, query=''):
acc_set = ",".join(map(str, ids)) mapping = {
query = self.pool.get('account.move.line')._query_get(cr, uid, context=context) 'balance': "COALESCE(SUM(l.debit) - SUM(l.credit), 0) as balance ",
cr.execute(("SELECT a.id, " \ 'debit': "COALESCE(SUM(l.debit), 0) as debit ",
"SUM(COALESCE(l.debit * a.sign, 0)) " \ 'credit': "COALESCE(SUM(l.credit), 0) as credit "
"FROM account_account a " \ }
"LEFT JOIN account_move_line l " \
"ON (a.id = l.account_id) " \
"WHERE a.type != 'view' " \
"AND a.id IN (%s) " \
"AND " + query + " " \
"AND a.active " \
"GROUP BY a.id") % (acc_set, ))
res2 = cr.fetchall()
res = {}
for id in ids:
res[id] = 0.0
for account_id, sum in res2:
res[account_id] += sum
return res
def _balance(self, cr, uid, ids, field_name, arg, context={}):
ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)])
ids2 = {}.fromkeys(ids + ids2).keys()
acc_set = ",".join(map(str, ids2)) acc_set = ",".join(map(str, ids2))
query = self.pool.get('account.move.line')._query_get(cr, uid, query = self.pool.get('account.move.line')._query_get(cr, uid,
context=context) context=context)
cr.execute(("SELECT a.id, " \ cr.execute(("SELECT l.account_id, " +\
"SUM((COALESCE(l.debit, 0) - COALESCE(l.credit, 0))) " \ ' , '.join(map(lambda x: mapping[x], field_names)) +
"FROM account_account a " \ "FROM " \
"LEFT JOIN account_move_line l " \ "account_move_line l " \
"ON (a.id=l.account_id) " \ "WHERE " \
"WHERE a.type != 'view' " \ "l.account_id IN (%s) " \
"AND a.id IN (%s) " \
"AND " + query + " " \ "AND " + query + " " \
"AND a.active " \ "GROUP BY l.account_id") % (acc_set, ))
"GROUP BY a.id") % (acc_set, ))
res = {}
for account_id, sum in cr.fetchall():
res[account_id] = round(sum,2)
cr.execute("SELECT a.id, a.company_id " \
"FROM account_account a " \
"WHERE id IN (%s)" % acc_set)
resc = dict(cr.fetchall())
cr.execute("SELECT id, currency_id FROM res_company")
rescur = dict(cr.fetchall())
accounts = {}
for res in cr.fetchall():
accounts[res[0]] = res[1:]
res = {}
for id in ids: for id in ids:
ids3 = self.search(cr, uid, [('parent_id', 'child_of', [id])]) res[id] = map(lambda x: 0.0, field_names)
to_currency_id = rescur[resc[id]] ids2 = self.search(cr, uid, [('parent_id', 'child_of', [id])])
for idx in ids3: for i in ids2:
if idx <> id: for a in range(len(field_names)):
res.setdefault(id, 0.0) res[id][a] += accounts.get(i, (0.0,0.0,0.0))[a]
if resc[idx]<>resc[id] and resc[idx] and resc[id]: print res
from_currency_id = rescur[resc[idx]]
res[id] += self.pool.get('res.currency').compute(cr,
uid, from_currency_id, to_currency_id,
res.get(idx, 0.0), context=context)
else:
res[id] += res.get(idx, 0.0)
for id in ids:
res[id] = round(res.get(id,0.0), 2)
return res return res
def _get_company_currency(self, cr, uid, ids, field_name, arg, context={}): def _get_company_currency(self, cr, uid, ids, field_name, arg, context={}):
@ -274,9 +231,9 @@ class account_account(osv.osv):
'child_id': fields.function(_get_child_ids, method=True, type='many2many',relation="account.account",string="Children Accounts"), 'child_id': fields.function(_get_child_ids, method=True, type='many2many',relation="account.account",string="Children Accounts"),
# 'child_id': fields.many2many('account.account', 'account_account_rel', 'parent_id', 'child_id', 'Children'), # 'child_id': fields.many2many('account.account', 'account_account_rel', 'parent_id', 'child_id', 'Children'),
'balance': fields.function(_balance, digits=(16,2), method=True, string='Balance'), 'balance': fields.function(__compute, digits=(16,2), method=True, string='Balance', multi='balance'),
'credit': fields.function(_credit, digits=(16,2), method=True, string='Credit'), 'credit': fields.function(__compute, digits=(16,2), method=True, string='Credit', multi='balance'),
'debit': fields.function(_debit, digits=(16,2), method=True, string='Debit'), 'debit': fields.function(__compute, digits=(16,2), method=True, string='Debit', multi='balance'),
'reconcile': fields.boolean('Reconcile', help="Check this account if the user can make a reconciliation of the entries in this account."), 'reconcile': fields.boolean('Reconcile', help="Check this account if the user can make a reconciliation of the entries in this account."),
'shortcut': fields.char('Shortcut', size=12), 'shortcut': fields.char('Shortcut', size=12),
'close_method': fields.selection([('none','None'), ('balance','Balance'), ('detail','Detail'),('unreconciled','Unreconciled')], 'Deferral Method', required=True, help="Tell Tiny ERP how to process the entries of this account when you close a fiscal year. None removes all entries to start with an empty account for the new fiscal year. Balance creates only one entry to keep the balance for the new fiscal year. Detail keeps the detail of all entries of the preceeding years. Unreconciled keeps the detail of unreconciled entries only."), 'close_method': fields.selection([('none','None'), ('balance','Balance'), ('detail','Detail'),('unreconciled','Unreconciled')], 'Deferral Method', required=True, help="Tell Tiny ERP how to process the entries of this account when you close a fiscal year. None removes all entries to start with an empty account for the new fiscal year. Balance creates only one entry to keep the balance for the new fiscal year. Detail keeps the detail of all entries of the preceeding years. Unreconciled keeps the detail of unreconciled entries only."),

View File

@ -317,8 +317,8 @@ class account_move_line(osv.osv):
'amount_currency': fields.float('Amount Currency', help="The amount expressed in an optionnal other currency if it is a multi-currency entry."), 'amount_currency': fields.float('Amount Currency', help="The amount expressed in an optionnal other currency if it is a multi-currency entry."),
'currency_id': fields.many2one('res.currency', 'Currency', help="The optionnal other currency if it is a multi-currency entry."), 'currency_id': fields.many2one('res.currency', 'Currency', help="The optionnal other currency if it is a multi-currency entry."),
'period_id': fields.many2one('account.period', 'Period', required=True), 'period_id': fields.many2one('account.period', 'Period', required=True, select=2),
'journal_id': fields.many2one('account.journal', 'Journal', required=True), 'journal_id': fields.many2one('account.journal', 'Journal', required=True, select=1),
'blocked': fields.boolean('Litigation', help="You can check this box to mark the entry line as a litigation with the associated partner"), 'blocked': fields.boolean('Litigation', help="You can check this box to mark the entry line as a litigation with the associated partner"),
'partner_id': fields.many2one('res.partner', 'Partner Ref.'), 'partner_id': fields.many2one('res.partner', 'Partner Ref.'),