From ff19c0f96b8e0f64c381e2e075a0398e2401de01 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Thu, 17 Dec 2009 15:13:32 +0100 Subject: [PATCH 01/18] Account: [ADD] Field company_id on account.analytic.line [ADD] Function Field currency_id, amount_currency on account.analytic.line, on account.analytic.account currency_id [ADD] Function field currency_id on account.analytic.account = company currency [API] Change the on_change_unit_amount signature, adding date and company_id [IMP] Change the on_change_unit_amount funtcion to base cost price on valuation instead of standard price. Product: [ADD] Add a new property called property_valuation_pricelist into res.company. purpose of this pricelist is to compute the cost price for a given y. Hr_timesheet: [API] Change the on_change_unit_amount signature, adding date Hr_timesheet_invoice [IMP] Function field currency_id of account.analytic.account base computation pricelist currency instead of company currency Hr_timesheet_sheet: [IMP] Add support of new signature for on_change_unit_amount bzr revid: joel.grandguillaume@camptocamp.com-20091217141332-23u4v79m3pbst7u9 --- addons/account/account_analytic_line.py | 57 +++++++++++++++++-- addons/account/project/project.py | 5 ++ addons/account/project/project_view.xml | 26 ++++++--- addons/hr_timesheet/hr_timesheet.py | 8 ++- addons/hr_timesheet/hr_timesheet_view.xml | 12 ++-- .../hr_timesheet_invoice.py | 19 +++++-- .../hr_timesheet_invoice_view.xml | 14 ++++- .../hr_timesheet_sheet_view.xml | 8 +-- addons/product/__init__.py | 2 +- addons/product/__terp__.py | 1 + addons/product/company.py | 53 +++++++++++++++++ addons/product/company_view.xml | 18 ++++++ addons/product/product_data.xml | 28 ++++++++- 13 files changed, 216 insertions(+), 35 deletions(-) create mode 100644 addons/product/company.py create mode 100644 addons/product/company_view.xml diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 3e3266044b4..7b0723ca07f 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -24,10 +24,38 @@ import time from osv import fields from osv import osv from tools.translate import _ +import tools +from tools import config class account_analytic_line(osv.osv): _name = 'account.analytic.line' _description = 'Analytic lines' + + def _amount_currency(self, cr, uid, ids, field_name, arg, context={}): + result = {} + for rec in self.browse(cr, uid, ids, context): + cmp_cur_id=rec.company_id.currency_id.id + aa_cur_id=rec.account_id.currency_id.id + result[rec.id] = 0.0 + if cmp_cur_id <> aa_cur_id: + cur_obj = self.pool.get('res.currency') + ctx = {} + if rec.date and rec.amount: + ctx['date'] = rec.date + result[rec.id] = cur_obj.compute(cr, uid, rec.company_id.currency_id.id, + rec.account_id.currency_id.id, rec.amount, + context=ctx) + return result + + def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): + result = {} + for rec in self.browse(cr, uid, ids, context): + if rec.company_id.currency_id.id <> rec.account_id.currency_id.id: + result[rec.id] = (rec.account_id.currency_id.id,rec.account_id.currency_id.code) + else: + result[rec.id] = False + return result + _columns = { 'name' : fields.char('Description', size=256, required=True), 'date' : fields.date('Date', required=True), @@ -42,13 +70,21 @@ class account_analytic_line(osv.osv): 'code' : fields.char('Code', size=8), 'user_id' : fields.many2one('res.users', 'User',), 'ref': fields.char('Ref.', size=32), + 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Currency', + store=True, help="The related account currency if not equal to the company one."), + 'company_id': fields.many2one('res.company','Company',required=True), + 'amount_currency': fields.function(_amount_currency, method=True, digits=(16, int(config['price_accuracy'])), string='Amount currency', + store=True, + help="The amount expressed in the related account currency if not equal to the company one.", + ), + } _defaults = { 'date': lambda *a: time.strftime('%Y-%m-%d'), + 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', c), } _order = 'date' - def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): if context is None: context = {} @@ -72,8 +108,10 @@ class account_analytic_line(osv.osv): # (_check_company, 'You can not create analytic line that is not in the same company than the account line', ['account_id']) ] - def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, - unit=False, context=None): + # Compute the cost based on the valuation pricelist define into company + # property_product_pricelist property + def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount,company_id, + date,unit=False, context=None): uom_obj = self.pool.get('product.uom') product_obj = self.pool.get('product.product') # if unit_amount and prod_id: @@ -87,8 +125,17 @@ class account_analytic_line(osv.osv): _('There is no expense account defined ' \ 'for this product: "%s" (id:%d)') % \ (prod.name, prod.id,)) - amount = unit_amount * uom_obj._compute_price(cr, uid, - prod.uom_id.id, prod.standard_price, unit) + if company_id: + company_obj = self.pool.get('res.company') + else: + company_id=self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context) + pricelist_id=company_obj.browse(cr,uid,company_id).property_valuation_pricelist.id + amount_unit = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist_id], + prod_id, unit_amount or 1.0, None, { + 'uom': unit, + 'date': date, + })[pricelist_id] + amount=amount_unit*unit_amount or 1.0 return {'value': { 'amount': - round(amount, 2), 'general_account_id': a, diff --git a/addons/account/project/project.py b/addons/account/project/project.py index 51431ee1be1..d6d68eee76f 100644 --- a/addons/account/project/project.py +++ b/addons/account/project/project.py @@ -167,6 +167,10 @@ class account_analytic_account(osv.osv): result[rec.id] = (rec.company_id.currency_id.id,rec.company_id.currency_id.code) or False return result + def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): + result=self._get_company_currency(cr, uid, ids, field_name, arg, context={}) + return result + _columns = { 'name' : fields.char('Account Name', size=64, required=True), 'complete_name': fields.function(_complete_name_calc, method=True, type='char', string='Full Account Name'), @@ -194,6 +198,7 @@ class account_analytic_account(osv.osv): \n* If any associated partner is there, it can be in \'Open\' state.\ \n* If any pending balance is there it can be in \'Pending\'. \ \n* And finally when all the transactions are over, it can be in \'Close\' state.'), + 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store=True), } def _default_company(self, cr, uid, context={}): diff --git a/addons/account/project/project_view.xml b/addons/account/project/project_view.xml index accbbf52d53..ef4da006e49 100644 --- a/addons/account/project/project_view.xml +++ b/addons/account/project/project_view.xml @@ -50,6 +50,7 @@ + @@ -134,6 +135,9 @@ + + + @@ -146,16 +150,19 @@ tree - + - - + + - + + + + @@ -212,13 +219,16 @@
- + - - - + + + + + + diff --git a/addons/hr_timesheet/hr_timesheet.py b/addons/hr_timesheet/hr_timesheet.py index 652814b6e02..278b1d0357c 100644 --- a/addons/hr_timesheet/hr_timesheet.py +++ b/addons/hr_timesheet/hr_timesheet.py @@ -53,11 +53,13 @@ class hr_analytic_timesheet(osv.osv): return super(hr_analytic_timesheet, self).unlink(cr, uid, ids, context) - def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, unit, context={}): + def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, date, unit, context={}): res = {} # if prod_id and unit_amount: - if prod_id: - res = self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount,unit, context) + if prod_id and date: + # find company + company_id=self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context) + res = self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount,company_id,date,unit, context) return res def _getEmployeeProduct(self, cr, uid, context): diff --git a/addons/hr_timesheet/hr_timesheet_view.xml b/addons/hr_timesheet/hr_timesheet_view.xml index 49ba1d602ad..ab07c4d1633 100644 --- a/addons/hr_timesheet/hr_timesheet_view.xml +++ b/addons/hr_timesheet/hr_timesheet_view.xml @@ -11,9 +11,9 @@ - - - + + + @@ -29,10 +29,10 @@ - + - - + + diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py index 182d8843b8c..3236807c928 100644 --- a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py +++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py @@ -52,8 +52,15 @@ class account_analytic_account(osv.osv): res[id] = round(res.get(id, 0.0),2) return res + def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): + result=super(account_analytic_account, self)._get_account_currency(cr, uid, ids, field_name, arg, context) + for rec in self.browse(cr, uid, ids, context): + result[rec.id] = rec.pricelist_id and (rec.pricelist_id.currency_id.id,rec.pricelist_id.currency_id.code) or result[rec.id] + return result + _inherit = "account.analytic.account" _columns = { + 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store=True), 'pricelist_id' : fields.many2one('product.pricelist', 'Sale Pricelist'), 'amount_max': fields.float('Max. Invoice Price'), 'amount_invoiced': fields.function(_invoiced_calc, method=True, string='Invoiced Amount', @@ -77,7 +84,7 @@ class account_analytic_line(osv.osv): } def unlink(self, cursor, user, ids, context=None): - self._check(cursor, user, ids) + # self._check(cursor, user, ids) return super(account_analytic_line,self).unlink(cursor, user, ids, context=context) @@ -90,11 +97,11 @@ class account_analytic_line(osv.osv): select = ids if isinstance(select, (int, long)): select = [ids] - if ( not vals.has_key('invoice_id')) or vals['invoice_id' ] == False: - for line in self.browse(cr, uid, select): - if line.invoice_id: - raise osv.except_osv(_('Error !'), - _('You can not modify an invoiced analytic line!')) + if ( not vals.has_key('invoice_id')) or vals['invoice_id' ] == False: + for line in self.browse(cr, uid, select): + if line.invoice_id: + raise osv.except_osv(_('Error !'), + _('You can not modify an invoiced analytic line!')) return True def copy(self, cursor, user, obj_id, default=None, context=None): diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml b/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml index 4ff5ac27c95..3ca932f6bcd 100644 --- a/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml +++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml @@ -21,7 +21,19 @@ - + + + account.analytic.account.form + account.analytic.account + + form + + + + + + + hr.analytic.timesheet.form hr.analytic.timesheet diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml index be40d8bacef..5452ccf790b 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml @@ -118,11 +118,11 @@ - + - + @@ -131,11 +131,11 @@ - + - + diff --git a/addons/product/__init__.py b/addons/product/__init__.py index 3f95fcb1900..da66b46efec 100644 --- a/addons/product/__init__.py +++ b/addons/product/__init__.py @@ -23,6 +23,6 @@ import pricelist import report import partner import wizard - +import company # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product/__terp__.py b/addons/product/__terp__.py index 3069a901577..183973a2275 100644 --- a/addons/product/__terp__.py +++ b/addons/product/__terp__.py @@ -54,6 +54,7 @@ 'product_view.xml', 'pricelist_view.xml', 'partner_view.xml', + 'company_view.xml', 'product_wizard.xml', 'process/product_process.xml' ], diff --git a/addons/product/company.py b/addons/product/company.py new file mode 100644 index 00000000000..32c4f3bccd2 --- /dev/null +++ b/addons/product/company.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import fields, osv + + +class res_company(osv.osv): + _inherit = 'res.company' + _columns = { + 'property_valuation_pricelist': fields.property( + 'product.pricelist', + type='many2one', + relation='product.pricelist', + domain=[('type','=','valuation')], + string="Valuation Pricelist", + method=True, + view_load=True, + help="This pricelist will be used, instead of the default one, \ + for valuation to the current company"), + } + + def _check_currency(self, cr, uid, ids): + for rec in self.browse(cr, uid, ids): + if rec.currency_id.id <> rec.property_valuation_pricelist.currency_id.id: + return False + return True + + _constraints = [ + (_check_currency, 'Error! You can not chooes a pricelist in a different currency than your company.', ['property_valuation_pricelist']) + ] + +res_company() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/product/company_view.xml b/addons/product/company_view.xml new file mode 100644 index 00000000000..5ccd5982de4 --- /dev/null +++ b/addons/product/company_view.xml @@ -0,0 +1,18 @@ + + + + + + res.company.product.property.form.inherit + res.company + form + + + + + + + + + + diff --git a/addons/product/product_data.xml b/addons/product/product_data.xml index 2f000fdbfc6..452253f0c96 100644 --- a/addons/product/product_data.xml +++ b/addons/product/product_data.xml @@ -73,7 +73,6 @@ parameter) will see those record just disappear. - @@ -81,6 +80,11 @@ parameter) will see those record just disappear. Sale Pricelist sale + + + Valuation Pricelist + valuation + @@ -107,5 +126,12 @@ parameter) will see those record just disappear. + + + property_valuation_pricelist + + + + From d3c8dc2db40be0aa9cdc04ba60e1b9b6119e6810 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Thu, 17 Dec 2009 16:12:33 +0100 Subject: [PATCH 02/18] [IMP] Add computation of stock entries based on valuation priclist of company for accounting entries bzr revid: joel.grandguillaume@camptocamp.com-20091217151233-85fnrq17pt2o7w7n --- .../hr_timesheet_invoice/hr_timesheet_invoice.py | 12 ++++++------ addons/stock/stock.py | 14 +++++++++++--- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py index 3236807c928..be0b8c4ccad 100644 --- a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py +++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py @@ -57,7 +57,7 @@ class account_analytic_account(osv.osv): for rec in self.browse(cr, uid, ids, context): result[rec.id] = rec.pricelist_id and (rec.pricelist_id.currency_id.id,rec.pricelist_id.currency_id.code) or result[rec.id] return result - + _inherit = "account.analytic.account" _columns = { 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store=True), @@ -97,11 +97,11 @@ class account_analytic_line(osv.osv): select = ids if isinstance(select, (int, long)): select = [ids] - if ( not vals.has_key('invoice_id')) or vals['invoice_id' ] == False: - for line in self.browse(cr, uid, select): - if line.invoice_id: - raise osv.except_osv(_('Error !'), - _('You can not modify an invoiced analytic line!')) + if ( not vals.has_key('invoice_id')) or vals['invoice_id' ] == False: + for line in self.browse(cr, uid, select): + if line.invoice_id: + raise osv.except_osv(_('Error !'), + _('You can not modify an invoiced analytic line!')) return True def copy(self, cursor, user, obj_id, default=None, context=None): diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 8b5356a8573..01ed2c62fbe 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1321,13 +1321,21 @@ class stock_move(osv.osv): ref = move.picking_id and move.picking_id.name or False product_uom_obj = self.pool.get('product.uom') default_uom = move.product_id.uom_id.id + date = time.strftime('%Y-%m-%d') q = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom) if move.product_id.cost_method == 'average' and move.price_unit: amount = q * move.price_unit + # Base computation on valuation pricelist else: - amount = q * move.product_id.standard_price - - date = time.strftime('%Y-%m-%d') + company_id=move.company_id.id + pricelist_id = self.pool.get('res.company').browse(cr,uid,company_id).property_valuation_pricelist.id + amount_unit = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist_id], + move.product_id.id, q or 1.0, None, { + 'date': date, + })[pricelist_id] + amount=amount_unit * q or 1.0 + # amount = q * move.product_id.standard_price + partner_id = False if move.picking_id: partner_id = move.picking_id.address_id and (move.picking_id.address_id.partner_id and move.picking_id.address_id.partner_id.id or False) or False From a7c8200828c0a01fc6214067c182f816c093b74e Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Thu, 17 Dec 2009 17:13:33 +0100 Subject: [PATCH 03/18] [FIX] Change the computation of _total_cost_calc for account_analytic_analysis bzr revid: joel.grandguillaume@camptocamp.com-20091217161333-zickpw2wyjf7fzx5 --- .../account_analytic_analysis.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index bbd976f8c29..8876928caa6 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -171,9 +171,19 @@ class account_analytic_account(osv.osv): on account_analytic_line.journal_id = account_analytic_journal.id \ where account_analytic_line.account_id IN (%s) \ and amount<0 \ + and amount_currency=0.0 \ GROUP BY account_analytic_line.account_id"""%acc_set) for account_id, sum in cr.fetchall(): res[account_id] = round(sum,2) + cr.execute("""select account_analytic_line.account_id,COALESCE(sum(amount_currency),0.0) \ + from account_analytic_line \ + join account_analytic_journal \ + on account_analytic_line.journal_id = account_analytic_journal.id \ + where account_analytic_line.account_id IN (%s) \ + and amount_currency<0 \ + GROUP BY account_analytic_line.account_id"""%acc_set) + for account_id, sum in cr.fetchall(): + res[account_id] += round(sum,2) for obj_id in ids: res.setdefault(obj_id, 0.0) for child_id in self.search(cr, uid, From 97d33b0da54e12295ea5f836b9ad26ff27eed9e7 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Thu, 17 Dec 2009 17:42:53 +0100 Subject: [PATCH 04/18] [IMP] Add trigger on analytic line, so currency and amount currency are recomputed if company change [REM] Remove the currency_id of analytic account to be computed based on sale pricelist, it's now the reported company currency_id [ADD] some demo to demo data provided by multicompany module bzr revid: joel.grandguillaume@camptocamp.com-20091217164253-3jwugrn14mkj21pe --- addons/account/account_analytic_line.py | 25 ++++++++++++++----- .../account_analytic_analysis.py | 5 +++- .../hr_timesheet_invoice.py | 12 ++++----- addons/multi_company/multi_company_demo.xml | 24 ++++++++++++++++++ 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 7b0723ca07f..e3332d15ca0 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -55,7 +55,16 @@ class account_analytic_line(osv.osv): else: result[rec.id] = False return result - + + def _get_account_line(self, cr, uid, ids, context={}): + aac_ids = {} + for acc in self.pool.get('account.analytic.account').browse(cr, uid, ids): + aac_ids[acc.id] = True + aal_ids = [] + if aac_ids: + aal_ids = self.pool.get('account.analytic.line').search(cr, uid, [('account_id','in',aac_ids.keys())], context=context) + return aal_ids + _columns = { 'name' : fields.char('Description', size=256, required=True), 'date' : fields.date('Date', required=True), @@ -70,13 +79,17 @@ class account_analytic_line(osv.osv): 'code' : fields.char('Code', size=8), 'user_id' : fields.many2one('res.users', 'User',), 'ref': fields.char('Ref.', size=32), - 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Currency', - store=True, help="The related account currency if not equal to the company one."), + 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', + store={ + 'account.analytic.account': (_get_account_line, ['company_id'], 50), + }, + help="The related account currency if not equal to the company one."), 'company_id': fields.many2one('res.company','Company',required=True), 'amount_currency': fields.function(_amount_currency, method=True, digits=(16, int(config['price_accuracy'])), string='Amount currency', - store=True, - help="The amount expressed in the related account currency if not equal to the company one.", - ), + store={ + 'account.analytic.account': (_get_account_line, ['company_id'], 50), + }, + help="The amount expressed in the related account currency if not equal to the company one.",), } _defaults = { diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index 8876928caa6..425cde301d3 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -183,7 +183,10 @@ class account_analytic_account(osv.osv): and amount_currency<0 \ GROUP BY account_analytic_line.account_id"""%acc_set) for account_id, sum in cr.fetchall(): - res[account_id] += round(sum,2) + if res.has_key(account_id): + res[account_id] += round(sum,2) + else: + res[account_id] = round(sum,2) for obj_id in ids: res.setdefault(obj_id, 0.0) for child_id in self.search(cr, uid, diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py index be0b8c4ccad..2a44dc4c5f8 100644 --- a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py +++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py @@ -52,15 +52,15 @@ class account_analytic_account(osv.osv): res[id] = round(res.get(id, 0.0),2) return res - def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): - result=super(account_analytic_account, self)._get_account_currency(cr, uid, ids, field_name, arg, context) - for rec in self.browse(cr, uid, ids, context): - result[rec.id] = rec.pricelist_id and (rec.pricelist_id.currency_id.id,rec.pricelist_id.currency_id.code) or result[rec.id] - return result + # def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): + # result=super(account_analytic_account, self)._get_account_currency(cr, uid, ids, field_name, arg, context) + # for rec in self.browse(cr, uid, ids, context): + # result[rec.id] = rec.pricelist_id and (rec.pricelist_id.currency_id.id,rec.pricelist_id.currency_id.code) or result[rec.id] + # return result _inherit = "account.analytic.account" _columns = { - 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store=True), + # 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store=True), 'pricelist_id' : fields.many2one('product.pricelist', 'Sale Pricelist'), 'amount_max': fields.float('Max. Invoice Price'), 'amount_invoiced': fields.function(_invoiced_calc, method=True, string='Invoiced Amount', diff --git a/addons/multi_company/multi_company_demo.xml b/addons/multi_company/multi_company_demo.xml index 7f18b7edd86..292cae0a0b5 100644 --- a/addons/multi_company/multi_company_demo.xml +++ b/addons/multi_company/multi_company_demo.xml @@ -1,6 +1,24 @@ + + + + + Valuation Pricelist USD + valuation + + + + + Default Valuation Pricelist Version USD + + + + + Default Valuation Pricelist Line USD + + OpenERP Corp. @@ -29,26 +47,32 @@ OpenERP Editor + OpenERP US + + OpenERP BE + OpenERP IN OpenERP IN + Odoo + From ee076f30df8f0a87b3ba461a2087ed49cafdef9a Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 23 Dec 2009 08:52:56 +0100 Subject: [PATCH 05/18] [FIX] Correct typo into account in order to allow compilation bzr revid: joel.grandguillaume@camptocamp.com-20091223075256-k6tmy2wbc8delay7 --- addons/account/account_analytic_line.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 335cdd7f22e..4ae603a5438 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -88,7 +88,7 @@ class account_analytic_line(osv.osv): store={ 'account.analytic.account': (_get_account_line, ['company_id'], 50), }, - help="The amount expressed in the related account currency if not equal to the company one.",) + help="The amount expressed in the related account currency if not equal to the company one."), 'ref': fields.char('Reference', size=32), } _defaults = { From 497c1bed05c4f395944655d82a5bfc5a95866c67 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 23 Dec 2009 09:51:37 +0100 Subject: [PATCH 06/18] [FIX] Correct debit, credit and balance on analytic account in order to give it in account currency [IMP] Always compute amount in currency, to allow debit,credit,balance computation bzr revid: joel.grandguillaume@camptocamp.com-20091223085137-pzuzatuknoluuhuh --- addons/account/account_analytic_line.py | 10 +++++----- addons/account/project/project.py | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 4ae603a5438..473a60f921b 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -36,7 +36,7 @@ class account_analytic_line(osv.osv): for rec in self.browse(cr, uid, ids, context): cmp_cur_id=rec.company_id.currency_id.id aa_cur_id=rec.account_id.currency_id.id - result[rec.id] = 0.0 + # Always provide the amount in currency if cmp_cur_id <> aa_cur_id: cur_obj = self.pool.get('res.currency') ctx = {} @@ -45,15 +45,15 @@ class account_analytic_line(osv.osv): result[rec.id] = cur_obj.compute(cr, uid, rec.company_id.currency_id.id, rec.account_id.currency_id.id, rec.amount, context=ctx) + else: + result[rec.id]=rec.amount return result def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): result = {} for rec in self.browse(cr, uid, ids, context): - if rec.company_id.currency_id.id <> rec.account_id.currency_id.id: - result[rec.id] = (rec.account_id.currency_id.id,rec.account_id.currency_id.code) - else: - result[rec.id] = False + # Always provide second currency + result[rec.id] = (rec.account_id.currency_id.id,rec.account_id.currency_id.code) return result def _get_account_line(self, cr, uid, ids, context={}): diff --git a/addons/account/project/project.py b/addons/account/project/project.py index 469b3aab874..5fa9e8c96ff 100644 --- a/addons/account/project/project.py +++ b/addons/account/project/project.py @@ -42,7 +42,7 @@ class account_analytic_account(osv.osv): 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 %s) WHERE l.amount<0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) + cr.execute("SELECT a.id, COALESCE(SUM(l.amount_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount_currency<0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) r = dict(cr.fetchall()) for i in ids: r.setdefault(i,0.0) @@ -58,7 +58,7 @@ class account_analytic_account(osv.osv): 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 %s) WHERE l.amount>0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) + cr.execute("SELECT a.id, COALESCE(SUM(l.amount_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount_currency>0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) r= dict(cr.fetchall()) for i in ids: r.setdefault(i,0.0) @@ -81,7 +81,7 @@ class account_analytic_account(osv.osv): 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 %s) WHERE a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) + cr.execute("SELECT a.id, COALESCE(SUM(l.amount_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) for account_id, sum in cr.fetchall(): res[account_id] = sum From d8500896c936e10fdf157492aa2ed2787b47fca7 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 23 Dec 2009 10:55:20 +0100 Subject: [PATCH 07/18] [IMP] Add trigger on account.analytic.line for currency change [IMP] Refactoring the _balance_calc in project.py [FIX] Use the new refactored funtion to compute indicator in right the currency according to each level of analytical account bzr revid: joel.grandguillaume@camptocamp.com-20091223095520-8gsqff2w7z0yrc7z --- addons/account/account_analytic_line.py | 14 +++-- addons/account/project/project.py | 52 ++++++++++--------- .../account_analytic_analysis.py | 43 +++------------ 3 files changed, 45 insertions(+), 64 deletions(-) diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 473a60f921b..34a422579fe 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -81,14 +81,18 @@ class account_analytic_line(osv.osv): 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store={ 'account.analytic.account': (_get_account_line, ['company_id'], 50), + 'account.analytic.line': (lambda self,cr,uid,ids,c={}: ids, ['amount','unit_amount'],10), }, - help="The related account currency if not equal to the company one."), + # multi='all', + help="The related account currency if not equal to the company one."), 'company_id': fields.many2one('res.company','Company',required=True), 'amount_currency': fields.function(_amount_currency, method=True, digits=(16, int(config['price_accuracy'])), string='Amount currency', - store={ - 'account.analytic.account': (_get_account_line, ['company_id'], 50), - }, - help="The amount expressed in the related account currency if not equal to the company one."), + store={ + 'account.analytic.account': (_get_account_line, ['company_id'], 50), + 'account.analytic.line': (lambda self,cr,uid,ids,c={}: ids, ['amount','unit_amount'],10), + }, + # multi='all', + help="The amount expressed in the related account currency if not equal to the company one."), 'ref': fields.char('Reference', size=32), } _defaults = { diff --git a/addons/account/project/project.py b/addons/account/project/project.py index 5fa9e8c96ff..38d7e63ed30 100644 --- a/addons/account/project/project.py +++ b/addons/account/project/project.py @@ -33,6 +33,32 @@ class account_analytic_account(osv.osv): _name = 'account.analytic.account' _description = 'Analytic Accounts' + def _compute_currency_for_level_tree(self, cr, uid, ids, ids2, res, acc_set, context={}): + # 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)" % acc_set) + currency= dict(cr.fetchall()) + res_currency= self.pool.get('res.currency') + for id in ids: + if id not in ids2: + continue + for child in self.search(cr, uid, [('parent_id', 'child_of', [id])]): + if child <> id: + res.setdefault(id, 0.0) + if currency[child]<>currency[id]: + res[id] += res_currency.compute(cr, uid, currency[child], currency[id], res.get(child, 0.0), context=context) + else: + res[id] += res.get(child, 0.0) + + cur_obj = res_currency.browse(cr,uid,currency.values(),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={}): acc_set = ",".join(map(str, ids)) @@ -86,30 +112,8 @@ class account_analytic_account(osv.osv): for account_id, sum in cr.fetchall(): res[account_id] = sum - 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)" % acc_set) - - currency= dict(cr.fetchall()) - - res_currency= self.pool.get('res.currency') - for id in ids: - if id not in ids2: - continue - for child in self.search(cr, uid, [('parent_id', 'child_of', [id])]): - if child <> id: - res.setdefault(id, 0.0) - if currency[child]<>currency[id]: - res[id] += res_currency.compute(cr, uid, currency[child], currency[id], res.get(child, 0.0), context=context) - else: - res[id] += res.get(child, 0.0) - - cur_obj = res_currency.browse(cr,uid,currency.values(),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 ]) - + return self._compute_currency_for_level_tree(cr, uid, ids, ids2, res, acc_set, context) + def _quantity_calc(self, cr, uid, ids, name, arg, context={}): #XXX must convert into one uom res = {} diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index 425cde301d3..e623b1c94f7 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -35,7 +35,7 @@ class account_analytic_account(osv.osv): ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) if ids2: acc_set = ",".join(map(str, ids2)) - cr.execute("select account_analytic_line.account_id, COALESCE(sum(amount),0.0) \ + cr.execute("select account_analytic_line.account_id, COALESCE(sum(amount_currency),0.0) \ from account_analytic_line \ join account_analytic_journal \ on account_analytic_line.journal_id = account_analytic_journal.id \ @@ -44,15 +44,8 @@ class account_analytic_account(osv.osv): group by account_analytic_line.account_id" % acc_set) for account_id, sum in cr.fetchall(): res[account_id] = round(sum,2) - for obj_id in ids: - res.setdefault(obj_id, 0.0) - for child_id in self.search(cr, uid, - [('parent_id', 'child_of', [obj_id])]): - if child_id != obj_id: - res[obj_id] += res.get(child_id, 0.0) - for id in ids: - res[id] = round(res.get(id, 0.0),2) - return res + + return self._compute_currency_for_level_tree(cr, uid, ids, ids2, res, acc_set, context) def _ca_to_invoice_calc(self, cr, uid, ids, name, arg, context={}): res = {} @@ -165,38 +158,18 @@ class account_analytic_account(osv.osv): ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) if ids2: acc_set = ",".join(map(str, ids2)) - cr.execute("""select account_analytic_line.account_id,COALESCE(sum(amount),0.0) \ - from account_analytic_line \ - join account_analytic_journal \ - on account_analytic_line.journal_id = account_analytic_journal.id \ - where account_analytic_line.account_id IN (%s) \ - and amount<0 \ - and amount_currency=0.0 \ - GROUP BY account_analytic_line.account_id"""%acc_set) - for account_id, sum in cr.fetchall(): - res[account_id] = round(sum,2) cr.execute("""select account_analytic_line.account_id,COALESCE(sum(amount_currency),0.0) \ from account_analytic_line \ join account_analytic_journal \ on account_analytic_line.journal_id = account_analytic_journal.id \ where account_analytic_line.account_id IN (%s) \ - and amount_currency<0 \ + and amount<0 \ + GROUP BY account_analytic_line.account_id"""%acc_set) for account_id, sum in cr.fetchall(): - if res.has_key(account_id): - res[account_id] += round(sum,2) - else: - res[account_id] = round(sum,2) - for obj_id in ids: - res.setdefault(obj_id, 0.0) - for child_id in self.search(cr, uid, - [('parent_id', 'child_of', [obj_id])]): - if child_id != obj_id: - res[obj_id] += res.get(child_id, 0.0) - for id in ids: - res[id] = round(res.get(id, 0.0),2) - return res - + res[account_id] = round(sum,2) + return self._compute_currency_for_level_tree(cr, uid, ids, ids2, res, acc_set, context) + def _ca_theorical_calc(self, cr, uid, ids, name, arg, context={}): res = {} res2 = {} From 4a628b63d7f4cb180af0cff3d3ad57c0ad51cfb1 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 23 Dec 2009 11:38:37 +0100 Subject: [PATCH 08/18] [COM] All indicators in account analytic analysis are now well computed, according to account currency, except theorical revenue and amount to invoice because they don't take care of pricelist neither account currency. bzr revid: joel.grandguillaume@camptocamp.com-20091223103837-etie8lovwb2twwbh --- .../account_analytic_analysis.py | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index e623b1c94f7..3178391b918 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -53,6 +53,9 @@ class account_analytic_account(osv.osv): ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) if ids2: # Amount uninvoiced hours to invoice at sale price + # Warnning + # This computation doesn't take care of pricelist ! + # Just consider list_price acc_set = ",".join(map(str, ids2)) cr.execute("""SELECT account_analytic_account.id, \ COALESCE(sum (product_template.list_price * \ @@ -89,6 +92,7 @@ class account_analytic_account(osv.osv): # GROUP BY account_analytic_line.account_id;"%acc_set) #for account_id, sum in cr.fetchall(): # res2[account_id] = round(sum,2) + for obj_id in ids: res.setdefault(obj_id, 0.0) res2.setdefault(obj_id, 0.0) @@ -169,11 +173,81 @@ class account_analytic_account(osv.osv): for account_id, sum in cr.fetchall(): res[account_id] = round(sum,2) return self._compute_currency_for_level_tree(cr, uid, ids, ids2, res, acc_set, context) + + # TODO Take care of pricelist and purchase ! + # def _ca_theorical_calc(self, cr, uid, ids, name, arg, context={}): + # res = {} + # res2 = {} + # date = time.strftime('%Y-%m-%d') + # ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + # # Take care of pricelist unit_price on all hours + # if ids2: + # acc_set = ",".join(map(str, ids2)) + # cr.execute("""select account_analytic_line.account_id as account_id, \ + # COALESCE(sum((account_analytic_line.unit_amount * pt.list_price) \ + # - (account_analytic_line.unit_amount * pt.list_price \ + # * hr.factor)),0.0) as somme,\ + # account_analytic_line.unit_amount as qty, + # a.pricelist_id as pricelist, + # account_analytic_line.product_id as product, + # a.partner_id as partner_id + # from account_analytic_line \ + # left join account_analytic_journal \ + # on (account_analytic_line.journal_id = account_analytic_journal.id) \ + # join product_product pp \ + # on (account_analytic_line.product_id = pp.id) \ + # join product_template pt \ + # on (pp.product_tmpl_id = pt.id) \ + # join account_analytic_account a \ + # on (a.id=account_analytic_line.account_id) \ + # join hr_timesheet_invoice_factor hr \ + # on (hr.id=a.to_invoice) \ + # where account_analytic_line.account_id IN (%s) \ + # and a.to_invoice IS NOT NULL \ + # and account_analytic_journal.type in ('purchase','general') + # GROUP BY account_analytic_line.account_id,"""%acc_set) + # # Compute unit amount with pricelist for given qty and product + # for account_id, sum, qty, pricelist,product, partner_id in cr.fetchall(): + # # If no product, no pricelist or no partner_id, no need to compute + # if not pricelist or not product or not partner_id: + # res2[account_id] = 0,0 + # else: + # unit_price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist], + # product, qty or 1.0, partner_id, { + # 'date': date, + # })[pricelist] + # if unit_price is False: + # warning = { + # 'title': 'No valid pricelist line found !', + # 'message': + # "Couldn't find a pricelist line matching this product and quantity.\n" + # "You have to change either the product, the quantity or the pricelist." + # } + # else: + # res2[account_id] = round(unit_price,2) + # + # for obj_id in ids: + # res.setdefault(obj_id, 0.0) + # res2.setdefault(obj_id, 0.0) + # for child_id in self.search(cr, uid, + # [('parent_id', 'child_of', [obj_id])]): + # if child_id != obj_id: + # res[obj_id] += res.get(child_id, 0.0) + # res[obj_id] += res2.get(child_id, 0.0) + # + # # sum both result on account_id + # for id in ids: + # res[id] = round(res.get(id, 0.0),2) + round(res2.get(id, 0.0),2) + # return res + def _ca_theorical_calc(self, cr, uid, ids, name, arg, context={}): res = {} res2 = {} ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + # Warnning + # This computation doesn't take care of pricelist ! + # Just consider list_price if ids2: acc_set = ",".join(map(str, ids2)) cr.execute("""select account_analytic_line.account_id as account_id, \ @@ -197,7 +271,7 @@ class account_analytic_account(osv.osv): GROUP BY account_analytic_line.account_id"""%acc_set) for account_id, sum in cr.fetchall(): res2[account_id] = round(sum,2) - + for obj_id in ids: res.setdefault(obj_id, 0.0) res2.setdefault(obj_id, 0.0) @@ -206,7 +280,7 @@ class account_analytic_account(osv.osv): if child_id != obj_id: res[obj_id] += res.get(child_id, 0.0) res[obj_id] += res2.get(child_id, 0.0) - + # sum both result on account_id for id in ids: res[id] = round(res.get(id, 0.0),2) + round(res2.get(id, 0.0),2) From ffd766bd42301213e351d2b3a068ee3faf674211 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 23 Dec 2009 16:28:06 +0100 Subject: [PATCH 09/18] [IMP] Change pricelist for price type into company property [IMP] Change all valuation according to price type instead of pricelist [IMP] Compute the aveerage price based on the define price type in the company, this allow company to have different cost price bzr revid: joel.grandguillaume@camptocamp.com-20091223152806-cacd3e8loi7tea53 --- addons/account/account_analytic_line.py | 27 +++++++++---------- addons/hr_timesheet/wizard/sign_in_out.py | 2 +- addons/multi_company/__init__.py | 1 + addons/multi_company/__terp__.py | 4 ++- addons/multi_company/multi_company_demo.xml | 20 +++++--------- addons/product/company.py | 18 ++++++------- addons/product/company_view.xml | 2 +- addons/product/pricelist.py | 1 + addons/product/product_data.xml | 27 +++---------------- addons/stock/stock.py | 11 ++++---- addons/stock/wizard/wizard_partial_picking.py | 11 +++++--- 11 files changed, 50 insertions(+), 74 deletions(-) diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 34a422579fe..0abe79f01c6 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -83,7 +83,6 @@ class account_analytic_line(osv.osv): 'account.analytic.account': (_get_account_line, ['company_id'], 50), 'account.analytic.line': (lambda self,cr,uid,ids,c={}: ids, ['amount','unit_amount'],10), }, - # multi='all', help="The related account currency if not equal to the company one."), 'company_id': fields.many2one('res.company','Company',required=True), 'amount_currency': fields.function(_amount_currency, method=True, digits=(16, int(config['price_accuracy'])), string='Amount currency', @@ -91,7 +90,6 @@ class account_analytic_line(osv.osv): 'account.analytic.account': (_get_account_line, ['company_id'], 50), 'account.analytic.line': (lambda self,cr,uid,ids,c={}: ids, ['amount','unit_amount'],10), }, - # multi='all', help="The amount expressed in the related account currency if not equal to the company one."), 'ref': fields.char('Reference', size=32), } @@ -124,13 +122,15 @@ class account_analytic_line(osv.osv): # (_check_company, 'You can not create analytic line that is not in the same company than the account line', ['account_id']) ] - # Compute the cost based on the valuation pricelist define into company - # property_product_pricelist property + # Compute the cost based on the price type define into company + # property_valuation_price_type property def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount,company_id, date,unit=False, context=None): + if context==None: + context={} uom_obj = self.pool.get('product.uom') product_obj = self.pool.get('product.product') -# if unit_amount and prod_id: + company_obj=self.pool.get('res.company') if prod_id: prod = product_obj.browse(cr, uid, prod_id) a = prod.product_tmpl_id.property_account_expense.id @@ -141,16 +141,13 @@ class account_analytic_line(osv.osv): _('There is no expense account defined ' \ 'for this product: "%s" (id:%d)') % \ (prod.name, prod.id,)) - if company_id: - company_obj = self.pool.get('res.company') - else: - company_id=self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context) - pricelist_id=company_obj.browse(cr,uid,company_id).property_valuation_pricelist.id - amount_unit = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist_id], - prod_id, unit_amount or 1.0, None, { - 'uom': unit, - 'date': date, - })[pricelist_id] + if not company_id: + company_id=company_obj._company_default_get(cr, uid, 'account.analytic.line', context) + + # Compute based on pricetype + pricetype=self.pool.get('product.price.type').browse(cr,uid,company_obj.browse(cr,uid,company_id).property_valuation_price_type.id) + amount_unit=prod.price_get(pricetype.field, context)[prod.id] + amount=amount_unit*unit_amount or 1.0 return {'value': { 'amount': - round(amount, 2), diff --git a/addons/hr_timesheet/wizard/sign_in_out.py b/addons/hr_timesheet/wizard/sign_in_out.py index 69be06a4b88..ac2f9d3d5c4 100644 --- a/addons/hr_timesheet/wizard/sign_in_out.py +++ b/addons/hr_timesheet/wizard/sign_in_out.py @@ -106,7 +106,7 @@ def _write(self, cr, uid, data, emp_id, context): res = timesheet_obj.default_get(cr, uid, ['product_id','product_uom_id']) if not res['product_uom_id']: raise wizard.except_wizard(_('UserError'), _('No cost unit defined for this employee !')) - up = timesheet_obj.on_change_unit_amount(cr, uid, False, res['product_id'], hour, res['product_uom_id'])['value'] + up = timesheet_obj.on_change_unit_amount(cr, uid, False, res['product_id'], hour, data['form']['date'], res['product_uom_id'])['value'] res['name'] = data['form']['info'] res['account_id'] = data['form']['account_id'] res['unit_amount'] = hour diff --git a/addons/multi_company/__init__.py b/addons/multi_company/__init__.py index 0d29405d526..537dbb62253 100644 --- a/addons/multi_company/__init__.py +++ b/addons/multi_company/__init__.py @@ -18,6 +18,7 @@ # along with this program. If not, see . # ############################################################################## +import product # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/multi_company/__terp__.py b/addons/multi_company/__terp__.py index 83d6afa777f..d541c91cf4a 100644 --- a/addons/multi_company/__terp__.py +++ b/addons/multi_company/__terp__.py @@ -32,10 +32,12 @@ 'depends': [ 'base', 'sale', - 'project' + 'project', + 'product', ], 'init_xml': [], 'update_xml': [ + "multi_company_view.xml", #'security/ir.model.access.csv', ], 'demo_xml': [ diff --git a/addons/multi_company/multi_company_demo.xml b/addons/multi_company/multi_company_demo.xml index 292cae0a0b5..f550d133b28 100644 --- a/addons/multi_company/multi_company_demo.xml +++ b/addons/multi_company/multi_company_demo.xml @@ -3,21 +3,13 @@ - - - Valuation Pricelist USD - valuation + + + Cost Price USD + standard_price_usd - - - Default Valuation Pricelist Version USD - - - - - Default Valuation Pricelist Line USD - + @@ -54,7 +46,7 @@ OpenERP US - + diff --git a/addons/product/company.py b/addons/product/company.py index 32c4f3bccd2..f23d010b600 100644 --- a/addons/product/company.py +++ b/addons/product/company.py @@ -25,26 +25,26 @@ from osv import fields, osv class res_company(osv.osv): _inherit = 'res.company' _columns = { - 'property_valuation_pricelist': fields.property( - 'product.pricelist', + 'property_valuation_price_type': fields.property( + 'product.price.type', type='many2one', - relation='product.pricelist', - domain=[('type','=','valuation')], - string="Valuation Pricelist", + relation='product.price.type', + domain=[], + string="Valuation Price Type", method=True, view_load=True, - help="This pricelist will be used, instead of the default one, \ - for valuation to the current company"), + help="The price type field in the selected price type will be used, instead of the default one, \ + for valuation of product in the current company"), } def _check_currency(self, cr, uid, ids): for rec in self.browse(cr, uid, ids): - if rec.currency_id.id <> rec.property_valuation_pricelist.currency_id.id: + if rec.currency_id.id <> rec.property_valuation_price_type.currency_id.id: return False return True _constraints = [ - (_check_currency, 'Error! You can not chooes a pricelist in a different currency than your company.', ['property_valuation_pricelist']) + (_check_currency, 'Error! You can not chooes a pricetype in a different currency than your company (Not supported now).', ['property_valuation_price_type']) ] res_company() diff --git a/addons/product/company_view.xml b/addons/product/company_view.xml index 5ccd5982de4..eb0294e2daa 100644 --- a/addons/product/company_view.xml +++ b/addons/product/company_view.xml @@ -9,7 +9,7 @@ - + diff --git a/addons/product/pricelist.py b/addons/product/pricelist.py index 0849ee85dcd..857cdc9b89b 100644 --- a/addons/product/pricelist.py +++ b/addons/product/pricelist.py @@ -62,6 +62,7 @@ class price_type(osv.osv): "active": lambda *args: True, "currency_id": _get_currency } + price_type() #---------------------------------------------------------- diff --git a/addons/product/product_data.xml b/addons/product/product_data.xml index 452253f0c96..8037453101e 100644 --- a/addons/product/product_data.xml +++ b/addons/product/product_data.xml @@ -81,10 +81,6 @@ parameter) will see those record just disappear. sale - - Valuation Pricelist - valuation - @@ -127,10 +108,10 @@ parameter) will see those record just disappear. - - property_valuation_pricelist - - + + property_valuation_price_type + + diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 00db75ce0f5..afe2ff47ee3 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1328,14 +1328,13 @@ class stock_move(osv.osv): q = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom) if move.product_id.cost_method == 'average' and move.price_unit: amount = q * move.price_unit - # Base computation on valuation pricelist + # Base computation on valuation price type else: company_id=move.company_id.id - pricelist_id = self.pool.get('res.company').browse(cr,uid,company_id).property_valuation_pricelist.id - amount_unit = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist_id], - move.product_id.id, q or 1.0, None, { - 'date': date, - })[pricelist_id] + + pricetype=self.pool.get('product.price.type').browse(cr,uid,move.company_id.property_valuation_price_type.id) + amount_unit=move.product_id.price_get(cr, uid, ids, pricetype.field, context) + amount=amount_unit * q or 1.0 # amount = q * move.product_id.standard_price diff --git a/addons/stock/wizard/wizard_partial_picking.py b/addons/stock/wizard/wizard_partial_picking.py index 416558735ff..52714f45eb6 100644 --- a/addons/stock/wizard/wizard_partial_picking.py +++ b/addons/stock/wizard/wizard_partial_picking.py @@ -131,7 +131,7 @@ def _do_split(self, cr, uid, data, context): currency = data['form']['currency%s' % move.id] qty = uom_obj._compute_qty(cr, uid, uom, qty, product.uom_id.id) - + pricetype=pool.get('product.price.type').browse(cr,uid,user.company_id.property_valuation_price_type.id) if (qty > 0): new_price = currency_obj.compute(cr, uid, currency, user.company_id.currency_id.id, price) @@ -140,11 +140,14 @@ def _do_split(self, cr, uid, data, context): if product.qty_available<=0: new_std_price = new_price else: - new_std_price = ((product.standard_price * product.qty_available)\ + # Get the standard price + amount_unit=product.price_get(pricetype.field, context)[product.id] + new_std_price = ((amount_unit * product.qty_available)\ + (new_price * qty))/(product.qty_available + qty) - + + # Write the field according to price type field product_obj.write(cr, uid, [product.id], - {'standard_price': new_std_price}) + {pricetype.field: new_std_price}) move_obj.write(cr, uid, [move.id], {'price_unit': new_price}) for move in too_few: From 0793892ca416afcb4b2e489d8eadcc8bfedd5580 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 23 Dec 2009 16:28:37 +0100 Subject: [PATCH 10/18] [IMP] Change the demo data according to last modification bzr revid: joel.grandguillaume@camptocamp.com-20091223152837-b46zaj4iv1ua02jb --- addons/multi_company/multi_company_view.xml | 20 +++++++++++++ addons/multi_company/product.py | 33 +++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 addons/multi_company/multi_company_view.xml create mode 100644 addons/multi_company/product.py diff --git a/addons/multi_company/multi_company_view.xml b/addons/multi_company/multi_company_view.xml new file mode 100644 index 00000000000..96a4695f576 --- /dev/null +++ b/addons/multi_company/multi_company_view.xml @@ -0,0 +1,20 @@ + + + + + + product.normal.form + product.product + form + + + + + + + + + + + + diff --git a/addons/multi_company/product.py b/addons/multi_company/product.py new file mode 100644 index 00000000000..988ef7ee39e --- /dev/null +++ b/addons/multi_company/product.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from osv import fields, osv +from tools import config + +class product_product(osv.osv): + _inherit = "product.product" + + _columns = { + 'standard_price_usd': fields.float('Cost Price USD', required=True, digits=(16, int(config['price_accuracy'])), + help="Product's cost in USDfor accounting stock valuation."), + } + +product_product() \ No newline at end of file From 90ddcec2d73d2770455b1b6a2eac8cf3c023251c Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 23 Dec 2009 17:34:53 +0100 Subject: [PATCH 11/18] [API] Remove date from onchange_unit_amount from analytic line, cause they are no more used as we base computation on pricetype [FIX] Start to replace standard_price in everymodule with the right field according to company property bzr revid: joel.grandguillaume@camptocamp.com-20091223163453-1a1y2pu9kmrzbep4 --- addons/account/account_analytic_line.py | 2 +- addons/account/project/project_view.xml | 20 ++++++------ addons/hr_expense/hr_expense.py | 10 ++++-- addons/hr_expense/hr_expense_view.xml | 4 +-- addons/hr_timesheet/hr_timesheet.py | 4 +-- addons/hr_timesheet/hr_timesheet_view.xml | 12 +++---- addons/hr_timesheet/wizard/sign_in_out.py | 2 +- .../hr_timesheet_sheet_view.xml | 8 ++--- addons/project_timesheet/project_timesheet.py | 7 +++- addons/stock/stock.py | 32 +++++++++++++++---- addons/stock/wizard/wizard_partial_move.py | 9 ++++-- 11 files changed, 72 insertions(+), 38 deletions(-) diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 0abe79f01c6..20ec20f3f32 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -125,7 +125,7 @@ class account_analytic_line(osv.osv): # Compute the cost based on the price type define into company # property_valuation_price_type property def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount,company_id, - date,unit=False, context=None): + unit=False, context=None): if context==None: context={} uom_obj = self.pool.get('product.uom') diff --git a/addons/account/project/project_view.xml b/addons/account/project/project_view.xml index a730a172f09..dbbfc0cc9c3 100644 --- a/addons/account/project/project_view.xml +++ b/addons/account/project/project_view.xml @@ -163,19 +163,19 @@ tree - + - - + + - + - + @@ -232,16 +232,16 @@
- + - - - + + + - + diff --git a/addons/hr_expense/hr_expense.py b/addons/hr_expense/hr_expense.py index 4c2ca16ce0c..5064eef8ff1 100644 --- a/addons/hr_expense/hr_expense.py +++ b/addons/hr_expense/hr_expense.py @@ -212,12 +212,18 @@ class hr_expense_line(osv.osv): 'date_value' : lambda *a: time.strftime('%Y-%m-%d'), } _order = "sequence" - def onchange_product_id(self, cr, uid, ids, product_id, uom_id, context={}): + def onchange_product_id(self, cr, uid, ids, product_id, uom_id, employee_id, context={}): v={} if product_id: product=self.pool.get('product.product').browse(cr,uid,product_id, context=context) v['name']=product.name - v['unit_amount']=product.standard_price + + # Compute based on pricetype of employee company + pricetype_id = self.pool.get('hr.employee').browse(cr,uid,employee_id).user_id.company_id.property_valuation_price_type.id + pricetype=self.pool.get('product.price.type').browse(cr,uid,pricetype_id) + amount_unit=product.price_get(pricetype.field, context)[product.id] + + v['unit_amount']=amount_unit if not uom_id: v['uom_id']=product.uom_id.id return {'value':v} diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml index 184f95a4c3f..3d0e3dde899 100644 --- a/addons/hr_expense/hr_expense_view.xml +++ b/addons/hr_expense/hr_expense_view.xml @@ -58,8 +58,8 @@
- - + + diff --git a/addons/hr_timesheet/hr_timesheet.py b/addons/hr_timesheet/hr_timesheet.py index 1f4f8d2aadb..bf0e0d1426b 100644 --- a/addons/hr_timesheet/hr_timesheet.py +++ b/addons/hr_timesheet/hr_timesheet.py @@ -53,13 +53,13 @@ class hr_analytic_timesheet(osv.osv): return super(hr_analytic_timesheet, self).unlink(cr, uid, ids, context) - def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, date, unit, context={}): + def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, unit, context={}): res = {} # if prod_id and unit_amount: if prod_id and date: # find company company_id=self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context) - res = self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount,company_id,date,unit, context) + res = self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount,company_id,unit, context) return res def _getEmployeeProduct(self, cr, uid, context): diff --git a/addons/hr_timesheet/hr_timesheet_view.xml b/addons/hr_timesheet/hr_timesheet_view.xml index 976bd64f5fb..0650889f182 100644 --- a/addons/hr_timesheet/hr_timesheet_view.xml +++ b/addons/hr_timesheet/hr_timesheet_view.xml @@ -11,9 +11,9 @@ - - - + + + @@ -29,10 +29,10 @@ - + - - + + diff --git a/addons/hr_timesheet/wizard/sign_in_out.py b/addons/hr_timesheet/wizard/sign_in_out.py index ac2f9d3d5c4..69be06a4b88 100644 --- a/addons/hr_timesheet/wizard/sign_in_out.py +++ b/addons/hr_timesheet/wizard/sign_in_out.py @@ -106,7 +106,7 @@ def _write(self, cr, uid, data, emp_id, context): res = timesheet_obj.default_get(cr, uid, ['product_id','product_uom_id']) if not res['product_uom_id']: raise wizard.except_wizard(_('UserError'), _('No cost unit defined for this employee !')) - up = timesheet_obj.on_change_unit_amount(cr, uid, False, res['product_id'], hour, data['form']['date'], res['product_uom_id'])['value'] + up = timesheet_obj.on_change_unit_amount(cr, uid, False, res['product_id'], hour, res['product_uom_id'])['value'] res['name'] = data['form']['info'] res['account_id'] = data['form']['account_id'] res['unit_amount'] = hour diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml index a92c6575de9..e0603037b03 100644 --- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml +++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml @@ -118,11 +118,11 @@ - + - + @@ -131,11 +131,11 @@ - + - + diff --git a/addons/project_timesheet/project_timesheet.py b/addons/project_timesheet/project_timesheet.py index 03d463b8269..1dfda98b645 100644 --- a/addons/project_timesheet/project_timesheet.py +++ b/addons/project_timesheet/project_timesheet.py @@ -104,7 +104,12 @@ class project_work(osv.osv): vals_line['date'] = vals['date'][:10] if 'hours' in vals: vals_line['unit_amount'] = vals['hours'] - vals_line['amount'] = (-1) * vals['hours'] * (obj.browse(cr,uid,line_id).product_id.standard_price or 0.0) + + # Compute based on pricetype + amount_unit=obj.on_change_unit_amount(cr, uid, line_id, + vals_line['product_id'], vals_line['unit_amount'], unit, context) + + vals_line['amount'] = (-1) * vals['hours'] * (amount_unit or 0.0) obj.write(cr, uid, [line_id], vals_line, {}) return super(project_work,self).write(cr, uid, ids, vals, context) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index afe2ff47ee3..d8873a9e0c7 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -110,11 +110,15 @@ class stock_location(osv.osv): cr.execute('select distinct product_id from stock_move where (location_id=%s) or (location_dest_id=%s)', (id, id)) result = cr.dictfetchall() if result: + # Choose the right filed standard_price to read + # Take the user company + price_type_id=self.pool.get('res.users').browse(cr,uid,uid).company_id.property_valuation_price_type.id + pricetype=self.pool.get('product.price.type').browse(cr,uid,price_type_id) for r in result: c = (context or {}).copy() c['location'] = id - product = self.pool.get('product.product').read(cr, uid, r['product_id'], [field_to_read, 'standard_price'], context=c) - final_value += (product[field_to_read] * product['standard_price']) + product = self.pool.get('product.product').read(cr, uid, r['product_id'], [field_to_read, pricetype.field], context=c) + final_value += (product[field_to_read] * product[pricetype.field]) return final_value def _product_value(self, cr, uid, ids, field_names, arg, context={}): @@ -211,6 +215,10 @@ class stock_location(osv.osv): if context is None: context = {} product_obj = self.pool.get('product.product') + # Take the user company and pricetype + price_type_id=self.pool.get('res.users').browse(cr,uid,uid).company_id.property_valuation_price_type.id + pricetype=self.pool.get('product.price.type').browse(cr,uid,price_type_id) + if not product_ids: product_ids = product_obj.search(cr, uid, []) @@ -241,10 +249,16 @@ class stock_location(osv.osv): continue product = products_by_id[product_id] quantity_total += qty[product_id] - price = qty[product_id] * product.standard_price + + # Compute based on pricetype + # Choose the right filed standard_price to read + amount_unit=product.price_get(pricetype.field, context)[product.id] + price = qty[product_id] * amount_unit + # price = qty[product_id] * product.standard_price + total_price += price result['product'].append({ - 'price': product.standard_price, + 'price': amount_unit, 'prod_name': product.name, 'code': product.default_code, # used by lot_overview_all report! 'variants': product.variants or '', @@ -645,7 +659,12 @@ class stock_picking(osv.osv): def _get_price_unit_invoice(self, cursor, user, move_line, type): '''Return the price unit for the move line''' if type in ('in_invoice', 'in_refund'): - return move_line.product_id.standard_price + # Take the user company and pricetype + price_type_id=self.pool.get('res.users').browse(cr,users,users).company_id.property_valuation_price_type.id + pricetype=self.pool.get('product.price.type').browse(cr,uid,price_type_id) + amount_unit=move_line.product_id.price_get(pricetype.field, context)[move_line.product_id.id] + return amount_unit + # return move_line.product_id.standard_price else: return move_line.product_id.list_price @@ -1411,7 +1430,8 @@ class stock_inventory(osv.osv): move_line = [] for line in inv.inventory_line_id: pid = line.product_id.id - price = line.product_id.standard_price or 0.0 + + # price = line.product_id.standard_price or 0.0 amount = self.pool.get('stock.location')._product_get(cr, uid, line.location_id.id, [pid], {'uom': line.product_uom.id})[pid] change = line.product_qty - amount if change: diff --git a/addons/stock/wizard/wizard_partial_move.py b/addons/stock/wizard/wizard_partial_move.py index 66e426c1e18..e374c472789 100644 --- a/addons/stock/wizard/wizard_partial_move.py +++ b/addons/stock/wizard/wizard_partial_move.py @@ -124,7 +124,8 @@ def _do_split(self, cr, uid, data, context): currency = data['form']['currency%s' % move.id] qty = uom_obj._compute_qty(cr, uid, uom, qty, product.uom_id.id) - + pricetype=pool.get('product.price.type').browse(cr,uid,user.company_id.property_valuation_price_type.id) + if (qty > 0): new_price = currency_obj.compute(cr, uid, currency, user.company_id.currency_id.id, price) @@ -133,11 +134,13 @@ def _do_split(self, cr, uid, data, context): if product.qty_available<=0: new_std_price = new_price else: - new_std_price = ((product.standard_price * product.qty_available)\ + # Get the standard price + amount_unit=product.price_get(pricetype.field, context)[product.id] + new_std_price = ((product.amount_unit * product.qty_available)\ + (new_price * qty))/(product.qty_available + qty) product_obj.write(cr, uid, [product.id], - {'standard_price': new_std_price}) + {pricetype.field: new_std_price}) move_obj.write(cr, uid, move.id, {'price_unit': new_price}) for move in too_few: From b75d214b25cf7e7be63b4ad192b133d0456e9a14 Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 23 Dec 2009 18:14:09 +0100 Subject: [PATCH 12/18] [FIX] Analytic_user_function and project_timsheet corrected according to pricetype bzr revid: joel.grandguillaume@camptocamp.com-20091223171409-a0wfgy034f8o5yjw --- .../analytic_user_function.py | 14 ++++++++++---- addons/hr_timesheet/hr_timesheet.py | 2 +- addons/project_timesheet/project_timesheet.py | 8 ++++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/addons/analytic_user_function/analytic_user_function.py b/addons/analytic_user_function/analytic_user_function.py index e2279bb891e..264c9fe43c0 100644 --- a/addons/analytic_user_function/analytic_user_function.py +++ b/addons/analytic_user_function/analytic_user_function.py @@ -99,8 +99,11 @@ class hr_analytic_timesheet(osv.osv): _('There is no expense account define ' \ 'for this product: "%s" (id:%d)') % \ (r.product_id.name, r.product_id.id,)) - amount = unit_amount * self.pool.get('product.uom')._compute_price(cr, uid, - r.product_id.uom_id.id, r.product_id.standard_price, False) + # Compute based on pricetype + amount_unit=self.on_change_unit_amount(cr, uid, ids, + r.product_id.id, unit_amount, r.product_id.uom_id.id)['value']['amount'] + + amount = unit_amount * amount_unit res ['value']['amount']= - round(amount, 2) res ['value']['general_account_id']= a return res @@ -132,8 +135,11 @@ class hr_analytic_timesheet(osv.osv): _('There is no expense account define ' \ 'for this product: "%s" (id:%d)') % \ (r.product_id.name, r.product_id.id,)) - amount = unit_amount * r.product_id.uom_id._compute_price(cr, uid, - r.product_id.uom_id.id, r.product_id.standard_price, False) + # Compute based on pricetype + amount_unit=self.on_change_unit_amount(cr, uid, ids, + r.product_id.id, unit_amount, r.product_id.uom_id.id)['value']['amount'] + + amount = unit_amount * amount_unit res ['value']['amount']= - round(amount, 2) res ['value']['general_account_id']= a return res diff --git a/addons/hr_timesheet/hr_timesheet.py b/addons/hr_timesheet/hr_timesheet.py index bf0e0d1426b..6082528379b 100644 --- a/addons/hr_timesheet/hr_timesheet.py +++ b/addons/hr_timesheet/hr_timesheet.py @@ -56,7 +56,7 @@ class hr_analytic_timesheet(osv.osv): def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, unit, context={}): res = {} # if prod_id and unit_amount: - if prod_id and date: + if prod_id: # find company company_id=self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context) res = self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount,company_id,unit, context) diff --git a/addons/project_timesheet/project_timesheet.py b/addons/project_timesheet/project_timesheet.py index 1dfda98b645..2152053f3de 100644 --- a/addons/project_timesheet/project_timesheet.py +++ b/addons/project_timesheet/project_timesheet.py @@ -77,8 +77,12 @@ class project_work(osv.osv): vals_line['journal_id'] = result['journal_id'] vals_line['amount'] = 00.0 timeline_id = obj.create(cr, uid, vals_line, {}) - - vals_line['amount'] = (-1) * vals['hours']* ( obj.browse(cr,uid,timeline_id).product_id.standard_price or 0.0) + + # Compute based on pricetype + amount_unit=obj.on_change_unit_amount(cr, uid, line_id, + vals_line['product_id'], vals_line['unit_amount'], unit, context) + + vals_line['amount'] = (-1) * vals['hours']* (unit_amount or 0.0) obj.write(cr, uid,[timeline_id], vals_line, {}) vals['hr_analytic_timesheet_id'] = timeline_id return super(project_work,self).create(cr, uid, vals, *args, **kwargs) From 9388c1b1f1e60139bcbee299df0359ab36da722b Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 6 Jan 2010 08:10:38 +0100 Subject: [PATCH 13/18] [FIX] Stock move valuation now use correctly price_get bzr revid: joel.grandguillaume@camptocamp.com-20100106071038-cp4xu2htyrkz7a3u --- addons/stock/stock.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index d8873a9e0c7..90d431d42f1 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1352,8 +1352,7 @@ class stock_move(osv.osv): company_id=move.company_id.id pricetype=self.pool.get('product.price.type').browse(cr,uid,move.company_id.property_valuation_price_type.id) - amount_unit=move.product_id.price_get(cr, uid, ids, pricetype.field, context) - + amount_unit=move.product_id.price_get(pricetype.field, context)[move.product_id.id] amount=amount_unit * q or 1.0 # amount = q * move.product_id.standard_price From c832258c146b8217d6c233076a2329f36336e95f Mon Sep 17 00:00:00 2001 From: Joel Grand-Guillaume Date: Wed, 6 Jan 2010 08:40:27 +0100 Subject: [PATCH 14/18] [IMP] Compute debit and credit at each level in tree AA view bzr revid: joel.grandguillaume@camptocamp.com-20100106074027-ytdx87cjtwobvthv --- addons/account/project/project.py | 35 ++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/addons/account/project/project.py b/addons/account/project/project.py index 38d7e63ed30..0fa80d101f8 100644 --- a/addons/account/project/project.py +++ b/addons/account/project/project.py @@ -60,8 +60,16 @@ class account_analytic_account(osv.osv): def _credit_calc(self, cr, uid, ids, name, arg, context={}): - acc_set = ",".join(map(str, ids)) - + res = {} + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + + for i in ids: + res.setdefault(i,0.0) + + if not acc_set: + return res + where_date = '' if context.get('from_date',False): where_date += " AND l.date >= '" + context['from_date'] + "'" @@ -70,13 +78,18 @@ class account_analytic_account(osv.osv): cr.execute("SELECT a.id, COALESCE(SUM(l.amount_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount_currency<0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) r = dict(cr.fetchall()) - for i in ids: - r.setdefault(i,0.0) - return r - + return self._compute_currency_for_level_tree(cr, uid, ids, ids2, r, acc_set, context) + def _debit_calc(self, cr, uid, ids, name, arg, context={}): - - acc_set = ",".join(map(str, ids)) + res = {} + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + + for i in ids: + res.setdefault(i,0.0) + + if not acc_set: + return res where_date = '' if context.get('from_date',False): @@ -86,10 +99,8 @@ class account_analytic_account(osv.osv): cr.execute("SELECT a.id, COALESCE(SUM(l.amount_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount_currency>0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) r= dict(cr.fetchall()) - for i in ids: - r.setdefault(i,0.0) - return r - + return self._compute_currency_for_level_tree(cr, uid, ids, ids2, r, acc_set, context) + def _balance_calc(self, cr, uid, ids, name, arg, context={}): res = {} ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) From fb4db629b490e71537c582d20801e673699e1e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Grand-Guillaume?= Date: Thu, 11 Feb 2010 15:23:26 +0100 Subject: [PATCH 15/18] [DEL] Remove the demo data in multi-company module as asked by Fabien bzr revid: joel.grandguillaume@camptocamp.com-20100211142326-lc011kadf8kluj64 --- addons/multi_company/__init__.py | 2 -- addons/multi_company/multi_company_demo.xml | 16 ---------- addons/multi_company/product.py | 33 --------------------- 3 files changed, 51 deletions(-) delete mode 100644 addons/multi_company/product.py diff --git a/addons/multi_company/__init__.py b/addons/multi_company/__init__.py index aa6ce64cfcc..4716d0d109b 100644 --- a/addons/multi_company/__init__.py +++ b/addons/multi_company/__init__.py @@ -18,7 +18,5 @@ # along with this program. If not, see . # ############################################################################## -import product - # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/multi_company/multi_company_demo.xml b/addons/multi_company/multi_company_demo.xml index f550d133b28..7f18b7edd86 100644 --- a/addons/multi_company/multi_company_demo.xml +++ b/addons/multi_company/multi_company_demo.xml @@ -1,16 +1,6 @@ - - - - - Cost Price USD - standard_price_usd - - - - OpenERP Corp. @@ -39,32 +29,26 @@ OpenERP Editor - OpenERP US - - OpenERP BE - OpenERP IN OpenERP IN - Odoo - diff --git a/addons/multi_company/product.py b/addons/multi_company/product.py deleted file mode 100644 index 988ef7ee39e..00000000000 --- a/addons/multi_company/product.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from osv import fields, osv -from tools import config - -class product_product(osv.osv): - _inherit = "product.product" - - _columns = { - 'standard_price_usd': fields.float('Cost Price USD', required=True, digits=(16, int(config['price_accuracy'])), - help="Product's cost in USDfor accounting stock valuation."), - } - -product_product() \ No newline at end of file From 92bad635f583a80c126c5fefcbcc840aa6d2e00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Grand-Guillaume?= Date: Thu, 11 Feb 2010 15:29:14 +0100 Subject: [PATCH 16/18] [DEL] Remove the multi-company view from multi-company bzr revid: joel.grandguillaume@camptocamp.com-20100211142914-dz5cgttn6x8hqcm4 --- addons/multi_company/__terp__.py | 2 -- addons/multi_company/multi_company_view.xml | 20 -------------------- 2 files changed, 22 deletions(-) delete mode 100644 addons/multi_company/multi_company_view.xml diff --git a/addons/multi_company/__terp__.py b/addons/multi_company/__terp__.py index 27bce01b194..b3126b9bf99 100644 --- a/addons/multi_company/__terp__.py +++ b/addons/multi_company/__terp__.py @@ -33,11 +33,9 @@ 'base', 'sale', 'project', - 'product', ], 'init_xml': [], 'update_xml': [ - "multi_company_view.xml", #'security/ir.model.access.csv', ], 'demo_xml': [ diff --git a/addons/multi_company/multi_company_view.xml b/addons/multi_company/multi_company_view.xml deleted file mode 100644 index 96a4695f576..00000000000 --- a/addons/multi_company/multi_company_view.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - product.normal.form - product.product - form - - - - - - - - - - - - From 94eca59637517f8881704a0bf1117afbf8387363 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Grand-Guillaume?= Date: Thu, 11 Feb 2010 16:16:50 +0100 Subject: [PATCH 17/18] [REF] Refactoring : moving the project.py from account to analytic module as it was done by Tiny bzr revid: joel.grandguillaume@camptocamp.com-20100211151650-m0a414hx0bkgjjv8 --- addons/account/project/project.py | 262 ------------------------------ addons/analytic/project.py | 142 +++++++++------- 2 files changed, 83 insertions(+), 321 deletions(-) diff --git a/addons/account/project/project.py b/addons/account/project/project.py index 5344bb5ae9d..a844d6dec2e 100644 --- a/addons/account/project/project.py +++ b/addons/account/project/project.py @@ -25,268 +25,6 @@ import operator from osv import fields from osv import osv -# -# Object definition -# - -class account_analytic_account(osv.osv): - _name = 'account.analytic.account' - _description = 'Analytic Accounts' - - def _compute_currency_for_level_tree(self, cr, uid, ids, ids2, res, acc_set, context={}): - # 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)" % acc_set) - currency= dict(cr.fetchall()) - res_currency= self.pool.get('res.currency') - for id in ids: - if id not in ids2: - continue - for child in self.search(cr, uid, [('parent_id', 'child_of', [id])]): - if child <> id: - res.setdefault(id, 0.0) - if currency[child]<>currency[id]: - res[id] += res_currency.compute(cr, uid, currency[child], currency[id], res.get(child, 0.0), context=context) - else: - res[id] += res.get(child, 0.0) - - cur_obj = res_currency.browse(cr,uid,currency.values(),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={}): - res = {} - ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) - acc_set = ",".join(map(str, ids2)) - - for i in ids: - res.setdefault(i,0.0) - - if not acc_set: - 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_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount_currency<0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) - r = dict(cr.fetchall()) - return self._compute_currency_for_level_tree(cr, uid, ids, ids2, r, acc_set, context) - - def _debit_calc(self, cr, uid, ids, name, arg, context={}): - res = {} - ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) - acc_set = ",".join(map(str, ids2)) - - for i in ids: - res.setdefault(i,0.0) - - if not acc_set: - 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_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE l.amount_currency>0 and a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) - r= dict(cr.fetchall()) - return self._compute_currency_for_level_tree(cr, uid, ids, ids2, r, acc_set, context) - - def _balance_calc(self, cr, uid, ids, name, arg, context={}): - res = {} - ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) - acc_set = ",".join(map(str, ids2)) - - for i in ids: - res.setdefault(i,0.0) - - if not acc_set: - 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_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id %s) WHERE a.id IN (%s) GROUP BY a.id" % (where_date,acc_set)) - - for account_id, sum in cr.fetchall(): - res[account_id] = sum - - return self._compute_currency_for_level_tree(cr, uid, ids, ids2, res, acc_set, context) - - def _quantity_calc(self, cr, uid, ids, name, arg, context={}): - #XXX must convert into one uom - res = {} - ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) - acc_set = ",".join(map(str, ids2)) - - for i in ids: - res.setdefault(i,0.0) - - if not acc_set: - 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 ('+acc_set+') GROUP BY a.id') - - for account_id, sum in cr.fetchall(): - res[account_id] = sum - - for id in ids: - if id not in ids2: - continue - for child in self.search(cr, uid, [('parent_id', 'child_of', [id])]): - if child <> id: - res.setdefault(id, 0.0) - res[id] += res.get(child, 0.0) - return dict([(i, res[i]) for i in ids]) - - def name_get(self, cr, uid, ids, context={}): - if not len(ids): - return [] - reads = self.read(cr, uid, ids, ['name','parent_id'], context) - res = [] - for record in reads: - name = record['name'] - if record['parent_id']: - name = record['parent_id'][1]+' / '+name - res.append((record['id'], name)) - return res - - def _complete_name_calc(self, cr, uid, ids, prop, unknow_none, unknow_dict): - res = self.name_get(cr, uid, ids) - return dict(res) - - def _get_company_currency(self, cr, uid, ids, field_name, arg, context={}): - result = {} - for rec in self.browse(cr, uid, ids, context): - result[rec.id] = (rec.company_id.currency_id.id,rec.company_id.currency_id.code) or False - return result - - def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): - result=self._get_company_currency(cr, uid, ids, field_name, arg, context={}) - return result - - _columns = { - 'name' : fields.char('Account Name', size=64, required=True), - 'complete_name': fields.function(_complete_name_calc, method=True, type='char', string='Full Account Name'), - 'code' : fields.char('Account Code', size=24), - 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the analytic account without removing it."), - 'type': fields.selection([('view','View'), ('normal','Normal')], 'Account Type'), - 'description' : fields.text('Description'), - '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'), - 'quantity_max': fields.float('Maximum Quantity'), - 'partner_id' : fields.many2one('res.partner', 'Associated Partner'), - 'contact_id' : fields.many2one('res.partner.address', 'Contact'), - 'user_id' : fields.many2one('res.users', 'Account Manager'), - 'date_start': fields.date('Date Start'), - 'date': fields.date('Date End'), - 'company_id': fields.many2one('res.company', 'Company', required=True), - 'company_currency_id': fields.function(_get_company_currency, method=True, type='many2one', relation='res.currency', string='Currency'), - 'state': fields.selection([('draft','Draft'),('open','Open'), ('pending','Pending'),('cancelled', 'Cancelled'),('close','Close'),('template', 'Template')], 'State', required=True,readonly=True, - help='* When an account is created its in \'Draft\' state.\ - \n* If any associated partner is there, it can be in \'Open\' state.\ - \n* If any pending balance is there it can be in \'Pending\'. \ - \n* And finally when all the transactions are over, it can be in \'Close\' state. \ - \n* The project can be in either if the states \'Template\' and \'Running\'.\n If it is template then we can make projects based on the template projects. If its in \'Running\' state it is a normal project.\ - \n If it is to be reviewed then the state is \'Pending\'.\n When the project is completed the state is set to \'Done\'.'), - 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store=True), - } - - def _default_company(self, cr, uid, context={}): - user = self.pool.get('res.users').browse(cr, uid, uid, context=context) - if user.company_id: - return user.company_id.id - return self.pool.get('res.company').search(cr, uid, [('parent_id', '=', False)])[0] - _defaults = { - 'active' : lambda *a : True, - 'type' : lambda *a : 'normal', - 'company_id': _default_company, - 'state' : lambda *a : 'draft', - 'user_id' : lambda self,cr,uid,ctx : uid, - 'partner_id': lambda self,cr, uid, ctx: ctx.get('partner_id', False), - 'contact_id': lambda self,cr, uid, ctx: ctx.get('contact_id', False), - } - - def check_recursion(self, cr, uid, ids, parent=None): - return super(account_analytic_account, self).check_recursion(cr, uid, ids, parent=parent) - - _order = 'parent_id desc,code' - _constraints = [ - (check_recursion, 'Error! You can not create recursive analytic accounts.', ['parent_id']) - ] - - def create(self, cr, uid, vals, context=None): - parent_id = vals.get('parent_id', 0) - if ('code' not in vals or not vals['code']) and not parent_id: - vals['code'] = self.pool.get('ir.sequence').get(cr, uid, 'account.analytic.account') - return super(account_analytic_account, self).create(cr, uid, vals, context=context) - - def copy(self, cr, uid, id, default=None, context={}): - if not default: - default = {} - default['code'] = False - default['line_ids'] = [] - return super(account_analytic_account, self).copy(cr, uid, id, default, context=context) - - - def on_change_parent(self, cr, uid, id, parent_id): - if not parent_id: - return {} - parent = self.read(cr, uid, [parent_id], ['partner_id','code'])[0] - childs = self.search(cr, uid, [('parent_id', '=', parent_id), ('active', 'in', [True, False])]) - numchild = len(childs) - if parent['partner_id']: - partner = parent['partner_id'][0] - else: - partner = False - res = {'value' : {'code' : '%s - %03d' % (parent['code'] or '', numchild + 1),}} - if partner: - res['value']['partner_id'] = partner - return res - - def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100): - if not args: - args=[] - if not context: - context={} - account = self.search(cr, uid, [('code', '=', name)]+args, limit=limit, context=context) - if not account: - account = self.search(cr, uid, [('name', 'ilike', '%%%s%%' % name)]+args, limit=limit, context=context) - newacc = account - while newacc: - newacc = self.search(cr, uid, [('parent_id', 'in', newacc)]+args, limit=limit, context=context) - account+=newacc - return self.name_get(cr, uid, account, context=context) - -account_analytic_account() - - class account_analytic_journal(osv.osv): _name = 'account.analytic.journal' _columns = { diff --git a/addons/analytic/project.py b/addons/analytic/project.py index 7e0ab40c63a..43a73aa0c65 100644 --- a/addons/analytic/project.py +++ b/addons/analytic/project.py @@ -33,57 +33,11 @@ class account_analytic_account(osv.osv): _name = 'account.analytic.account' _description = 'Analytic Accounts' - def _credit_calc(self, cr, uid, ids, name, arg, context={}): - - 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 =ANY(%s) GROUP BY a.id",(ids,)) - r = dict(cr.fetchall()) - for i in ids: - r.setdefault(i,0.0) - return r - - def _debit_calc(self, cr, uid, ids, name, arg, context={}): - - 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 =ANY(%s) GROUP BY a.id" ,(ids,)) - r= dict(cr.fetchall()) - for i in ids: - r.setdefault(i,0.0) - return r - - def _balance_calc(self, cr, uid, ids, name, arg, context={}): - res = {} - ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) - for i in ids: - res.setdefault(i,0.0) - if not ids2: - 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 =ANY(%s) GROUP BY a.id",(ids2,)) - - for account_id, sum in cr.fetchall(): - res[account_id] = sum - - 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 =ANY(%s)",(ids2,)) - + def _compute_currency_for_level_tree(self, cr, uid, ids, ids2, res, acc_set, context={}): + # 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)" % acc_set) currency= dict(cr.fetchall()) - res_currency= self.pool.get('res.currency') for id in ids: if id not in ids2: @@ -104,24 +58,88 @@ class account_analytic_account(osv.osv): return dict([(i, res[i]) for i in ids ]) - def _quantity_calc(self, cr, uid, ids, name, arg, context={}): - #XXX must convert into one uom + + def _credit_calc(self, cr, uid, ids, name, arg, context={}): res = {} ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) acc_set = ",".join(map(str, ids2)) - + for i in ids: res.setdefault(i,0.0) - - if not acc_set: + + if not ids2: 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_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id "+where_date+") WHERE l.amount_currency<0 and a.id =ANY(%s) GROUP BY a.id",(ids2,)) + r = dict(cr.fetchall()) + return self._compute_currency_for_level_tree(cr, uid, ids, ids2, r, acc_set, context) + + def _debit_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + + for i in ids: + res.setdefault(i,0.0) + + if not ids2: + 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_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id "+where_date+") WHERE l.amount_currency>0 and a.id =ANY(%s) GROUP BY a.id" ,(ids2,)) + r= dict(cr.fetchall()) + return self._compute_currency_for_level_tree(cr, uid, ids, ids2, r, acc_set, context) + + def _balance_calc(self, cr, uid, ids, name, arg, context={}): + res = {} + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + + for i in ids: + res.setdefault(i,0.0) + + if not ids2: + 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_currency),0) FROM account_analytic_account a LEFT JOIN account_analytic_line l ON (a.id=l.account_id "+where_date+") WHERE a.id =ANY(%s) GROUP BY a.id",(ids2,)) + + for account_id, sum in cr.fetchall(): + res[account_id] = sum + return self._compute_currency_for_level_tree(cr, uid, ids, ids2, res, acc_set, context) + + def _quantity_calc(self, cr, uid, ids, name, arg, context={}): + #XXX must convert into one uom + res = {} + ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) + acc_set = ",".join(map(str, ids2)) + + for i in ids: + res.setdefault(i,0.0) + + if not ids2: + 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 + ') \ @@ -161,11 +179,15 @@ class account_analytic_account(osv.osv): result[rec.id] = (rec.company_id.currency_id.id,rec.company_id.currency_id.code) or False return result + def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): + result=self._get_company_currency(cr, uid, ids, field_name, arg, context={}) + return result + _columns = { 'name' : fields.char('Account Name', size=128, required=True), 'complete_name': fields.function(_complete_name_calc, method=True, type='char', string='Full Account Name'), 'code' : fields.char('Account Code', size=24), -# 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the analytic account without removing it."), + # 'active' : fields.boolean('Active', help="If the active field is set to true, it will allow you to hide the analytic account without removing it."), 'type': fields.selection([('view','View'), ('normal','Normal')], 'Account Type'), 'description' : fields.text('Description'), 'parent_id': fields.many2one('account.analytic.account', 'Parent Analytic Account', select=2), @@ -190,6 +212,7 @@ class account_analytic_account(osv.osv): \n* And finally when all the transactions are over, it can be in \'Close\' state. \ \n* The project can be in either if the states \'Template\' and \'Running\'.\n If it is template then we can make projects based on the template projects. If its in \'Running\' state it is a normal project.\ \n If it is to be reviewed then the state is \'Pending\'.\n When the project is completed the state is set to \'Done\'.'), + 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store=True), } def _default_company(self, cr, uid, context={}): @@ -198,14 +221,14 @@ class account_analytic_account(osv.osv): return user.company_id.id return self.pool.get('res.company').search(cr, uid, [('parent_id', '=', False)])[0] _defaults = { -# 'active' : lambda *a : True, + 'active' : lambda *a : True, 'type' : lambda *a : 'normal', 'company_id': _default_company, 'state' : lambda *a : 'open', 'user_id' : lambda self,cr,uid,ctx : uid, 'partner_id': lambda self,cr, uid, ctx: ctx.get('partner_id', False), 'contact_id': lambda self,cr, uid, ctx: ctx.get('contact_id', False), - 'date_start': lambda *a: time.strftime('%Y-%m-%d') + 'date_start': lambda *a: time.strftime('%Y-%m-%d') } def check_recursion(self, cr, uid, ids, parent=None): @@ -260,3 +283,4 @@ class account_analytic_account(osv.osv): return self.name_get(cr, uid, account, context=context) account_analytic_account() + From 8da75403886ec23ed71b8f97269f1b5eca8b9167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Grand-Guillaume?= Date: Mon, 15 Feb 2010 11:39:48 +0100 Subject: [PATCH 18/18] [FIX] According to Xavier (OpenERP) to fit OpenERP requierements : remove commented code, use != instead of <>, fix picking wizard. bzr revid: joel.grandguillaume@camptocamp.com-20100215103948-cbnngoh2px14pk6a --- addons/account/account_analytic_line.py | 2 +- .../account_analytic_analysis.py | 86 +------------------ addons/analytic/project.py | 6 +- .../hr_timesheet_invoice.py | 6 -- addons/stock/stock.py | 1 - addons/stock/wizard/wizard_partial_move.py | 6 +- addons/stock/wizard/wizard_partial_picking.py | 4 +- 7 files changed, 13 insertions(+), 98 deletions(-) diff --git a/addons/account/account_analytic_line.py b/addons/account/account_analytic_line.py index 1f355def87f..08f36f65e53 100644 --- a/addons/account/account_analytic_line.py +++ b/addons/account/account_analytic_line.py @@ -37,7 +37,7 @@ class account_analytic_line(osv.osv): cmp_cur_id=rec.company_id.currency_id.id aa_cur_id=rec.account_id.currency_id.id # Always provide the amount in currency - if cmp_cur_id <> aa_cur_id: + if cmp_cur_id != aa_cur_id: cur_obj = self.pool.get('res.currency') ctx = {} if rec.date and rec.amount: diff --git a/addons/account_analytic_analysis/account_analytic_analysis.py b/addons/account_analytic_analysis/account_analytic_analysis.py index e38bf33d965..8f91d03c7e6 100644 --- a/addons/account_analytic_analysis/account_analytic_analysis.py +++ b/addons/account_analytic_analysis/account_analytic_analysis.py @@ -81,18 +81,6 @@ class account_analytic_account(osv.osv): for account_id, sum in cr.fetchall(): res[account_id] = round(sum,2) - # Expense amount and purchase invoice - #acc_set = ",".join(map(str, ids2)) - #cr.execute ("select account_analytic_line.account_id, sum(amount) \ - # from account_analytic_line \ - # join account_analytic_journal \ - # on account_analytic_line.journal_id = account_analytic_journal.id \ - # where account_analytic_line.account_id IN (%s) \ - # and account_analytic_journal.type = 'purchase' \ - # GROUP BY account_analytic_line.account_id;"%acc_set) - #for account_id, sum in cr.fetchall(): - # res2[account_id] = round(sum,2) - for obj_id in ids: res.setdefault(obj_id, 0.0) res2.setdefault(obj_id, 0.0) @@ -171,74 +159,8 @@ class account_analytic_account(osv.osv): for account_id, sum in cr.fetchall(): res[account_id] = round(sum,2) return self._compute_currency_for_level_tree(cr, uid, ids, ids2, res, acc_set, context) - + # TODO Take care of pricelist and purchase ! - # def _ca_theorical_calc(self, cr, uid, ids, name, arg, context={}): - # res = {} - # res2 = {} - # date = time.strftime('%Y-%m-%d') - # ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)]) - # # Take care of pricelist unit_price on all hours - # if ids2: - # acc_set = ",".join(map(str, ids2)) - # cr.execute("""select account_analytic_line.account_id as account_id, \ - # COALESCE(sum((account_analytic_line.unit_amount * pt.list_price) \ - # - (account_analytic_line.unit_amount * pt.list_price \ - # * hr.factor)),0.0) as somme,\ - # account_analytic_line.unit_amount as qty, - # a.pricelist_id as pricelist, - # account_analytic_line.product_id as product, - # a.partner_id as partner_id - # from account_analytic_line \ - # left join account_analytic_journal \ - # on (account_analytic_line.journal_id = account_analytic_journal.id) \ - # join product_product pp \ - # on (account_analytic_line.product_id = pp.id) \ - # join product_template pt \ - # on (pp.product_tmpl_id = pt.id) \ - # join account_analytic_account a \ - # on (a.id=account_analytic_line.account_id) \ - # join hr_timesheet_invoice_factor hr \ - # on (hr.id=a.to_invoice) \ - # where account_analytic_line.account_id IN (%s) \ - # and a.to_invoice IS NOT NULL \ - # and account_analytic_journal.type in ('purchase','general') - # GROUP BY account_analytic_line.account_id,"""%acc_set) - # # Compute unit amount with pricelist for given qty and product - # for account_id, sum, qty, pricelist,product, partner_id in cr.fetchall(): - # # If no product, no pricelist or no partner_id, no need to compute - # if not pricelist or not product or not partner_id: - # res2[account_id] = 0,0 - # else: - # unit_price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist], - # product, qty or 1.0, partner_id, { - # 'date': date, - # })[pricelist] - # if unit_price is False: - # warning = { - # 'title': 'No valid pricelist line found !', - # 'message': - # "Couldn't find a pricelist line matching this product and quantity.\n" - # "You have to change either the product, the quantity or the pricelist." - # } - # else: - # res2[account_id] = round(unit_price,2) - # - # for obj_id in ids: - # res.setdefault(obj_id, 0.0) - # res2.setdefault(obj_id, 0.0) - # for child_id in self.search(cr, uid, - # [('parent_id', 'child_of', [obj_id])]): - # if child_id != obj_id: - # res[obj_id] += res.get(child_id, 0.0) - # res[obj_id] += res2.get(child_id, 0.0) - # - # # sum both result on account_id - # for id in ids: - # res[id] = round(res.get(id, 0.0),2) + round(res2.get(id, 0.0),2) - # return res - - def _ca_theorical_calc(self, cr, uid, ids, name, arg, context={}): res = {} res2 = {} @@ -352,7 +274,7 @@ class account_analytic_account(osv.osv): def _remaining_hours_calc(self, cr, uid, ids, name, arg, context={}): res = {} for account in self.browse(cr, uid, ids): - if account.quantity_max <> 0: + if account.quantity_max != 0: res[account.id] = account.quantity_max - account.hours_quantity else: res[account.id]=0.0 @@ -386,7 +308,7 @@ class account_analytic_account(osv.osv): for account in self.browse(cr, uid, ids): if account.ca_invoiced == 0: res[account.id]=0.0 - elif account.total_cost <> 0.0: + elif account.total_cost != 0.0: res[account.id] = -(account.real_margin / account.total_cost) * 100 else: res[account.id] = 0.0 @@ -397,7 +319,7 @@ class account_analytic_account(osv.osv): def _remaining_ca_calc(self, cr, uid, ids, name, arg, context={}): res = {} for account in self.browse(cr, uid, ids): - if account.amount_max <> 0: + if account.amount_max != 0: res[account.id] = account.amount_max - account.ca_invoiced else: res[account.id]=0.0 diff --git a/addons/analytic/project.py b/addons/analytic/project.py index 43a73aa0c65..54f160840e9 100644 --- a/addons/analytic/project.py +++ b/addons/analytic/project.py @@ -43,9 +43,9 @@ class account_analytic_account(osv.osv): if id not in ids2: continue for child in self.search(cr, uid, [('parent_id', 'child_of', [id])]): - if child <> id: + if child != id: res.setdefault(id, 0.0) - if currency[child]<>currency[id]: + if currency[child]!=currency[id]: res[id] += res_currency.compute(cr, uid, currency[child], currency[id], res.get(child, 0.0), context=context) else: res[id] += res.get(child, 0.0) @@ -152,7 +152,7 @@ class account_analytic_account(osv.osv): if id not in ids2: continue for child in self.search(cr, uid, [('parent_id', 'child_of', [id])]): - if child <> id: + if child != id: res.setdefault(id, 0.0) res[id] += res.get(child, 0.0) return dict([(i, res[i]) for i in ids]) diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py index 624fdcbb04b..50814bf93dd 100644 --- a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py +++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py @@ -52,15 +52,9 @@ class account_analytic_account(osv.osv): res[id] = round(res.get(id, 0.0),2) return res - # def _get_account_currency(self, cr, uid, ids, field_name, arg, context={}): - # result=super(account_analytic_account, self)._get_account_currency(cr, uid, ids, field_name, arg, context) - # for rec in self.browse(cr, uid, ids, context): - # result[rec.id] = rec.pricelist_id and (rec.pricelist_id.currency_id.id,rec.pricelist_id.currency_id.code) or result[rec.id] - # return result _inherit = "account.analytic.account" _columns = { - # 'currency_id': fields.function(_get_account_currency, method=True, type='many2one', relation='res.currency', string='Account currency', store=True), 'pricelist_id' : fields.many2one('product.pricelist', 'Sale Pricelist'), 'amount_max': fields.float('Max. Invoice Price'), 'amount_invoiced': fields.function(_invoiced_calc, method=True, string='Invoiced Amount', diff --git a/addons/stock/stock.py b/addons/stock/stock.py index d0b42b398e0..310e993146d 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -664,7 +664,6 @@ class stock_picking(osv.osv): pricetype=self.pool.get('product.price.type').browse(cr,uid,price_type_id) amount_unit=move_line.product_id.price_get(pricetype.field, context)[move_line.product_id.id] return amount_unit - # return move_line.product_id.standard_price else: return move_line.product_id.list_price diff --git a/addons/stock/wizard/wizard_partial_move.py b/addons/stock/wizard/wizard_partial_move.py index 74fe1c08e0b..dd75407e2d4 100644 --- a/addons/stock/wizard/wizard_partial_move.py +++ b/addons/stock/wizard/wizard_partial_move.py @@ -55,7 +55,7 @@ def _get_moves(self, cr, uid, data, context): for move in move_lines: quantity = move.product_qty - if move.state <> 'assigned': + if move.state != 'assigned': quantity = 0 _moves_arch_lst.append('' % (move.id,)) @@ -136,7 +136,7 @@ def _do_split(self, cr, uid, data, context): else: # Get the standard price amount_unit=product.price_get(pricetype.field, context)[product.id] - new_std_price = ((product.amount_unit * product.qty_available)\ + new_std_price = ((amount_unit * product.qty_available)\ + (new_price * qty))/(product.qty_available + qty) product_obj.write(cr, uid, [product.id], @@ -144,7 +144,7 @@ def _do_split(self, cr, uid, data, context): move_obj.write(cr, uid, move.id, {'price_unit': new_price}) for move in too_few: - if data['form']['move%s' % move.id] <> 0: + if data['form']['move%s' % move.id] != 0: new_move = move_obj.copy(cr, uid, move.id, { 'product_qty' : data['form']['move%s' % move.id], diff --git a/addons/stock/wizard/wizard_partial_picking.py b/addons/stock/wizard/wizard_partial_picking.py index 0930efbcd74..389d6b8f5b6 100644 --- a/addons/stock/wizard/wizard_partial_picking.py +++ b/addons/stock/wizard/wizard_partial_picking.py @@ -61,7 +61,7 @@ def _get_moves(self, cr, uid, data, context): if m.state in ('done', 'cancel'): continue quantity = m.product_qty - if m.state<>'assigned': + if m.state!='assigned': quantity = 0 _moves_arch_lst.append('' % (m.id,)) @@ -161,7 +161,7 @@ def _do_split(self, cr, uid, data, context): 'move_lines' : [], 'state':'draft', }) - if data['form']['move%s' % move.id] <> 0: + if data['form']['move%s' % move.id] != 0: new_obj = move_obj.copy(cr, uid, move.id, { 'product_qty' : data['form']['move%s' % move.id],