From 6bfda323bab6ea016e88731f3a1f4719f2155f81 Mon Sep 17 00:00:00 2001 From: "qdp-launchpad@tinyerp.com" <> Date: Wed, 20 Oct 2010 10:54:13 +0200 Subject: [PATCH 1/2] [FIX + REF] analytic: fixed the computation of debit, credit, balance and quantity displayed on the chart of analytic account with refactoring of the code bzr revid: qdp-launchpad@tinyerp.com-20101020085413-7l93t70eotxs7p2x --- addons/analytic/analytic.py | 172 ++++++++++++------------------------ 1 file changed, 55 insertions(+), 117 deletions(-) diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index f6263bfeb0d..8370af159dd 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -28,130 +28,68 @@ class account_analytic_account(osv.osv): _name = 'account.analytic.account' _description = 'Analytic Account' - def _compute_currency_for_level_tree(self, cr, uid, ids, ids2, res, context=None): - # Handle multi-currency on each level of analytic account - # This is a refactoring of _balance_calc computation - cr.execute("SELECT a.id, r.currency_id FROM account_analytic_account a INNER JOIN res_company r ON (a.company_id = r.id) where a.id IN %s" , (tuple(ids2),)) - currency = dict(cr.fetchall()) - res_currency= self.pool.get('res.currency') + def _compute_level_tree(self, cr, uid, ids, child_ids, res, field_names, context=None): + def recursive_computation(account_id, res): + account = self.browse(cr, uid, account_id) + for son in account.child_ids: + res = recursive_computation(son.id, res) + for field in field_names: + res[account.id][field] += res[son.id][field] + return res for account in self.browse(cr, uid, ids, context=context): - if account.id not in ids2: + if account.id not in child_ids: continue - for child in account.child_ids: - if child.id != account.id: - res.setdefault(account.id, 0.0) - if currency[child.id] != currency[account.id]: - res[account.id] += res_currency.compute(cr, uid, currency[child.id], currency[account.id], res.get(child.id, 0.0), context=context) - else: - res[account.id] += res.get(child.id, 0.0) + res = recursive_computation(account.id, res) + return res - cur_obj = res_currency.browse(cr, uid, currency.values(), context=context) - cur_obj = dict([(o.id, o) for o in cur_obj]) - for id in ids: - if id in ids2: - res[id] = res_currency.round(cr, uid, cur_obj[currency[id]], res.get(id,0.0)) - - return dict([(i, res[i]) for i in ids ]) - - def _credit_calc(self, cr, uid, ids, name, arg, context=None): + def _debit_credit_bal_qtty(self, cr, uid, ids, name, arg, context=None): res = {} if context is None: context = {} - parent_ids = tuple(self.search(cr, uid, [('parent_id', 'child_of', ids)])) - for i in ids: - res.setdefault(i,0.0) + child_ids = tuple(self.search(cr, uid, [('parent_id', 'child_of', ids)])) + for i in child_ids: + res[i] = {} + for n in name: + res[i][n] = 0.0 - if not parent_ids: + if not child_ids: return res - where_date = '' + where_date = where_date_sub = '' + where_clause_args = [] if context.get('from_date', False): - where_date += " AND l.date >= '" + context['from_date'] + "'" + where_date += " AND l.date >= %s" + where_date_sub += " AND l2.date >= %s" + where_clause_args += [context['from_date']] if context.get('to_date', False): - where_date += " AND l.date <= '" + context['to_date'] + "'" - cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id "+where_date+") WHERE l.amount<0 and a.id IN %s GROUP BY a.id",(tuple(parent_ids),)) - r = dict(cr.fetchall()) - return self._compute_currency_for_level_tree(cr, uid, ids, parent_ids, r, context) - - def _debit_calc(self, cr, uid, ids, name, arg, context=None): - res = {} - if context is None: - context = {} - parent_ids = tuple(self.search(cr, uid, [('parent_id', 'child_of', ids)])) - for i in ids: - res.setdefault(i,0.0) - - if not parent_ids: - return res - - where_date = '' - if context.get('from_date',False): - where_date += " AND l.date >= '" + context['from_date'] + "'" - if context.get('to_date',False): - where_date += " AND l.date <= '" + context['to_date'] + "'" - cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id "+where_date+") WHERE l.amount>0 and a.id IN %s GROUP BY a.id" ,(tuple(parent_ids),)) - r = dict(cr.fetchall()) - return self._compute_currency_for_level_tree(cr, uid, ids, parent_ids, r, context=context) - - def _balance_calc(self, cr, uid, ids, name, arg, context=None): - res = {} - if context is None: - context = {} - - parent_ids = tuple(self.search(cr, uid, [('parent_id', 'child_of', ids)])) - for i in ids: - res.setdefault(i,0.0) - - if not parent_ids: - return res - - where_date = '' - if context.get('from_date',False): - where_date += " AND l.date >= '" + context['from_date'] + "'" - if context.get('to_date',False): - where_date += " AND l.date <= '" + context['to_date'] + "'" - cr.execute("SELECT a.id, COALESCE(SUM(l.amount),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id "+where_date+") WHERE a.id IN %s GROUP BY a.id",(tuple(parent_ids),)) - - for account_id, sum in cr.fetchall(): - res[account_id] = sum - return self._compute_currency_for_level_tree(cr, uid, ids, parent_ids, res, context=context) - - def _quantity_calc(self, cr, uid, ids, name, arg, context=None): - #XXX must convert into one uom - res = {} - if context is None: - context = {} - - parent_ids = tuple(self.search(cr, uid, [('parent_id', 'child_of', ids)])) - - for i in ids: - res.setdefault(i,0.0) - - if not parent_ids: - return res - - where_date = '' - if context.get('from_date',False): - where_date += " AND l.date >= '" + context['from_date'] + "'" - if context.get('to_date',False): - where_date += " AND l.date <= '" + context['to_date'] + "'" - - cr.execute('SELECT a.id, COALESCE(SUM(l.unit_amount), 0) \ - FROM account_analytic_account a \ - LEFT JOIN account_analytic_line l ON (a.id = l.account_id ' + where_date + ') \ - WHERE a.id IN %s GROUP BY a.id',(tuple(parent_ids),)) - - for account_id, sum in cr.fetchall(): - res[account_id] = sum - - for account in self.browse(cr, uid, ids, context=context): - if account.id not in parent_ids: - continue - for child in account.child_ids: - if child.id != account.id: - res.setdefault(account.id, 0.0) - res[account.id] += res.get(child.id, 0.0) - return dict([(i, res[i]) for i in ids]) + where_date += " AND l.date <= %s" + where_date_sub += " AND l2.date <= %s" + where_clause_args += [context['to_date']] + where_clause_args += where_clause_args + [tuple(child_ids)] + where_clause_args + cr.execute(""" + SELECT a.id, + ( SELECT coalesce(sum(l2.amount),0) + FROM account_analytic_line l2 + WHERE l2.account_id = a.id + AND l2.amount >0 + """ + where_date_sub + """ + ) AS debit, + ( SELECT coalesce(sum(-l2.amount),0) + FROM account_analytic_line l2 + WHERE l2.account_id = a.id + AND l2.amount <0 + """ + where_date_sub + """ + ) AS credit, + COALESCE(SUM(l.amount),0) AS balance, + COALESCE(SUM(l.unit_amount),0) AS quantity + FROM account_analytic_account a + LEFT JOIN account_analytic_line l ON (a.id=l.account_id) + WHERE a.id IN %s + """ + where_date + """ + GROUP BY a.id""", where_clause_args) + for ac_id, debit, credit, balance, quantity in cr.fetchall(): + res[ac_id] = {'debit': debit, 'credit': credit, 'balance': balance, 'quantity': quantity} + return self._compute_level_tree(cr, uid, ids, child_ids, res, ['debit', 'credit', 'balance', 'quantity'], context) def name_get(self, cr, uid, ids, context=None): if not ids: @@ -180,10 +118,10 @@ class account_analytic_account(osv.osv): 'parent_id': fields.many2one('account.analytic.account', 'Parent Analytic Account', select=2), 'child_ids': fields.one2many('account.analytic.account', 'parent_id', 'Child Accounts'), 'line_ids': fields.one2many('account.analytic.line', 'account_id', 'Analytic Entries'), - 'balance': fields.function(_balance_calc, method=True, type='float', string='Balance'), - 'debit': fields.function(_debit_calc, method=True, type='float', string='Debit'), - 'credit': fields.function(_credit_calc, method=True, type='float', string='Credit'), - 'quantity': fields.function(_quantity_calc, method=True, type='float', string='Quantity'), + 'balance': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Balance', multi='debit_credit_bal_qtty'), + 'debit': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Debit', multi='debit_credit_bal_qtty'), + 'credit': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Credit', multi='debit_credit_bal_qtty'), + 'quantity': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Quantity', multi='debit_credit_bal_qtty'), 'quantity_max': fields.float('Maximum Quantity', help='Sets the higher limit of quantity of hours.'), 'partner_id': fields.many2one('res.partner', 'Partner'), 'contact_id': fields.many2one('res.partner.address', 'Contact'), From 12ddd46d74b6b77734d72dc08af7ec11c690554b Mon Sep 17 00:00:00 2001 From: "qdp-launchpad@tinyerp.com" <> Date: Mon, 25 Oct 2010 16:26:16 +0200 Subject: [PATCH 2/2] [IMP] analytic: removed decimal precision on quantity function field on analytic account bzr revid: qdp-launchpad@tinyerp.com-20101025142616-vgmzxx8ff8nlz2if --- addons/analytic/analytic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index 5bcba9a90a5..674da6a3679 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -118,7 +118,7 @@ class account_analytic_account(osv.osv): 'balance': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Balance', multi='debit_credit_bal_qtty', digits_compute=dp.get_precision('Account')), 'debit': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Debit', multi='debit_credit_bal_qtty', digits_compute=dp.get_precision('Account')), 'credit': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Credit', multi='debit_credit_bal_qtty', digits_compute=dp.get_precision('Account')), - 'quantity': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Quantity', multi='debit_credit_bal_qtty', digits_compute=dp.get_precision('Account')), + 'quantity': fields.function(_debit_credit_bal_qtty, method=True, type='float', string='Quantity', multi='debit_credit_bal_qtty'), 'quantity_max': fields.float('Maximum Quantity', help='Sets the higher limit of quantity of hours.'), 'partner_id': fields.many2one('res.partner', 'Partner'), 'contact_id': fields.many2one('res.partner.address', 'Contact'),