[merge] CampToCamp's multi company cost price branch

bzr revid: xmo@tinyerp.com-20100215162033-j3st3yq2rz8a2gwx
This commit is contained in:
Xavier Morel 2010-02-15 17:20:33 +01:00
commit 9c77a058d9
23 changed files with 379 additions and 162 deletions

View File

@ -25,10 +25,46 @@ 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
# Always provide the amount in currency
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)
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):
# 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={}):
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),
@ -42,14 +78,27 @@ class account_analytic_line(osv.osv):
'journal_id' : fields.many2one('account.analytic.journal', 'Analytic Journal', required=True, ondelete='cascade', select=True),
'code' : fields.char('Code', size=8),
'user_id' : fields.many2one('res.users', 'User',),
'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."),
'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),
'account.analytic.line': (lambda self,cr,uid,ids,c={}: ids, ['amount','unit_amount'],10),
},
help="The amount expressed in the related account currency if not equal to the company one."),
'ref': fields.char('Reference', size=32),
}
_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 = {}
@ -73,11 +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'])
]
def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount,
# 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,
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
@ -88,8 +141,14 @@ 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 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),
'general_account_id': a,

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -15,7 +15,7 @@
# 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 <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@ -25,10 +25,6 @@ import operator
from osv import fields
from osv import osv
#
# Object definition
#
class account_analytic_journal(osv.osv):
_name = 'account.analytic.journal'
_columns = {

View File

@ -69,6 +69,7 @@
<field name="parent_id" on_change="on_change_parent(parent_id)"/>
<field name="company_id" select="2" widget="selection"/>
<field name="type" select="2"/>
<field name="company_currency_id" select="2"/>
</group>
<notebook colspan="4">
<page string="Account Data">
@ -147,6 +148,9 @@
<field name="move_id" select="2"/>
<field name="unit_amount" select="2"/>
<field name="ref" select="2"/>
<field name="currency_id" select="2"/>
<field name="amount_currency" select="2"/>
<field name="company_id" select="2"/>
<newline/>
<field name="product_id" select="2"/>
<field name="product_uom_id" select="2"/>
@ -159,16 +163,19 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree editable="top" string="Analytic Entries">
<field name="date"/>
<field name="date" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
<field name="name"/>
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)" sum="Total quantity"/>
<field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)"/>
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)" sum="Total quantity"/>
<field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
<field domain="[('type','=','normal')]" name="account_id"/>
<field invisible="True" name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)"/>
<field invisible="True" name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
<field name="amount" sum="Total amount"/>
<field name="general_account_id"/>
<field name="journal_id"/>
<field name="ref"/>
<field name="currency_id" />
<field name="amount_currency" />
<field name="company_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
</tree>
</field>
</record>
@ -225,13 +232,16 @@
<form string="Project line">
<field name="name"/>
<field name="account_id"/>
<field name="date"/>
<field name="date" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
<field name="journal_id"/>
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)"/>
<field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)"/>
<field name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, product_uom_id)"/>
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
<field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
<field name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
<field invisible="True" name="general_account_id"/>
<field name="amount"/>
<field name="currency_id" />
<field name="amount_currency" />
<field name="company_id" on_change="on_change_unit_amount(product_id, unit_amount, company_id, product_uom_id)"/>
</form>
</field>
</record>

View File

@ -34,7 +34,8 @@ class account_analytic_account(osv.osv):
res = {}
ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)])
if ids2:
cr.execute("select account_analytic_line.account_id, COALESCE(sum(amount),0.0) \
acc_set = ",".join(map(str, ids2))
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 \
@ -43,15 +44,8 @@ class account_analytic_account(osv.osv):
group by account_analytic_line.account_id" ,(ids2,))
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 = {}
@ -59,6 +53,10 @@ 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
# Warning
# 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 * \
account_analytic_line.unit_amount * \
@ -83,17 +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)
@ -160,7 +147,9 @@ class account_analytic_account(osv.osv):
res = {}
ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)])
if ids2:
cr.execute("""select account_analytic_line.account_id,COALESCE(sum(amount),0.0) \
acc_set = ",".join(map(str, ids2))
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 \
@ -169,20 +158,16 @@ class account_analytic_account(osv.osv):
GROUP BY account_analytic_line.account_id""",(ids2,))
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)
# TODO Take care of pricelist and purchase !
def _ca_theorical_calc(self, cr, uid, ids, name, arg, context={}):
res = {}
res2 = {}
ids2 = self.search(cr, uid, [('parent_id', 'child_of', ids)])
# Warning
# This computation doesn't take care of pricelist !
# Just consider list_price
if ids2:
cr.execute("""select account_analytic_line.account_id as account_id, \
COALESCE(sum((account_analytic_line.unit_amount * pt.list_price) \
@ -205,7 +190,7 @@ class account_analytic_account(osv.osv):
GROUP BY account_analytic_line.account_id""",(ids2,))
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)
@ -214,7 +199,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)
@ -289,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
@ -323,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
@ -334,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

View File

@ -33,65 +33,19 @@ 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:
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)
@ -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 + ') \
@ -134,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])
@ -161,11 +179,14 @@ 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."),
'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 +211,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 +220,13 @@ 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,
'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 +281,4 @@ class account_analytic_account(osv.osv):
return self.name_get(cr, uid, account, context=context)
account_analytic_account()

View File

@ -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

View File

@ -210,12 +210,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}

View File

@ -73,8 +73,8 @@
<newline/>
<field colspan="4" name="line_ids" nolabel="1">
<form string="Expense Lines">
<field name="product_id" on_change="onchange_product_id(product_id, uom_id)" select="2"/>
<field name="uom_id" on_change="onchange_product_id(product_id, uom_id)" select="2"/>
<field name="product_id" on_change="onchange_product_id(product_id, uom_id, parent.employee_id)" select="2"/>
<field name="uom_id" on_change="onchange_product_id(product_id, uom_id, parent.employee_id)" select="2"/>
<field name="name" select="1"/>
<field name="date_value" select="1"/>
<field name="unit_quantity" select="2"/>

View File

@ -57,7 +57,9 @@ class hr_analytic_timesheet(osv.osv):
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)
# 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)
return res
def _getEmployeeProduct(self, cr, uid, context):

View File

@ -52,6 +52,7 @@ class account_analytic_account(osv.osv):
res[id] = round(res.get(id, 0.0),2)
return res
_inherit = "account.analytic.account"
_columns = {
'pricelist_id' : fields.many2one('product.pricelist', 'Sale Pricelist'),
@ -77,7 +78,6 @@ class account_analytic_line(osv.osv):
}
def unlink(self, cursor, user, ids, context=None):
self._check(cursor, user, ids)
return super(account_analytic_line,self).unlink(cursor, user, ids,
context=context)
@ -90,11 +90,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):

View File

@ -20,7 +20,19 @@
</field>
</field>
</record>
<record id="view_account_analytic_account_form" model="ir.ui.view">
<field name="name">account.analytic.account.form</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="account.view_account_analytic_account_form"/>
<field name="type">form</field>
<field name="arch" type="xml">
<field name="company_currency_id" select="2" position="replace">
<field name="currency_id" select="2"/>
</field>
</field>
</record>
<record id="hr_timesheet_line_form" model="ir.ui.view">
<field name="name">hr.analytic.timesheet.form</field>
<field name="model">hr.analytic.timesheet</field>

View File

@ -18,6 +18,5 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -32,7 +32,7 @@
'depends': [
'base',
'sale',
'project'
'project',
],
'init_xml': [],
'update_xml': [

View File

@ -23,6 +23,6 @@ import pricelist
import report
import partner
import wizard
import company
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -54,6 +54,7 @@
'product_view.xml',
'pricelist_view.xml',
'partner_view.xml',
'company_view.xml',
'product_wizard.xml',
'process/product_process.xml'
],

53
addons/product/company.py Normal file
View File

@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
class res_company(osv.osv):
_inherit = 'res.company'
_columns = {
'property_valuation_price_type': fields.property(
'product.price.type',
type='many2one',
relation='product.price.type',
domain=[],
string="Valuation Price Type",
method=True,
view_load=True,
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_price_type.currency_id.id:
return False
return True
_constraints = [
(_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()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,18 @@
<openerp>
<data>
<record id="view_company_property_form" model="ir.ui.view">
<field name="name">res.company.product.property.form.inherit</field>
<field name="model">res.company</field>
<field name="type">form</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<field name="currency_id" position="after">
<field name="property_valuation_price_type"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@ -62,6 +62,7 @@ class price_type(osv.osv):
"active": lambda *args: True,
"currency_id": _get_currency
}
price_type()
#----------------------------------------------------------

View File

@ -73,7 +73,6 @@ parameter) will see those record just disappear.
<!--
Price list type
-->
@ -81,6 +80,7 @@ parameter) will see those record just disappear.
<field name="name">Sale Pricelist</field>
<field name="key">sale</field>
</record>
<!--
Price list
@ -107,5 +107,12 @@ parameter) will see those record just disappear.
<field name="fields_id" search="[('model','=','res.partner'),('name','=','property_product_pricelist')]"/>
<field eval="'product.pricelist,'+str(ref('list0'))" name="value"/>
</record>
<record forcecreate="True" id="property_valuation_price_type" model="ir.property">
<field name="name">property_valuation_price_type</field>
<field name="fields_id" search="[('model','=','res.company'),('name','=','property_valuation_price_type')]"/>
<field eval="'product.price.type,'+str(ref('standard_price'))" name="value"/>
</record>
</data>
</openerp>

View File

@ -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)
@ -104,7 +108,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)

View File

@ -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,11 @@ 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
else:
return move_line.product_id.list_price
@ -1408,13 +1426,19 @@ 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 price type
else:
amount = q * move.product_id.standard_price
date = time.strftime('%Y-%m-%d')
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(pricetype.field, context)[move.product_id.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
@ -1492,7 +1516,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
lot_id = line.prod_lot_id.id

View File

@ -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('<field name="move%s" />' % (move.id,))
@ -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,15 +134,17 @@ 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)
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:
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],

View File

@ -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('<field name="move%s" />' % (m.id,))
@ -133,7 +133,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)
@ -142,11 +142,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:
@ -158,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],