Calculate two fields with on function - odoo

I have this function that calculates qty_incoming, but there is an outgoing_qty field that I want to calculate with the same function and not to create separate function for its calculation. how can I do this?
_columns = {
'
'incoming_qty': fields.function(_product_inc_out_qty, type='float',
digits_compute=dp.get_precision('Product Unit of Measure'),
string='Incoming'
),
'outgoing_qty': fields.function(_product_inc_out_qty, type='float',
digits_compute=dp.get_precision('Product Unit of Measure'),
string='Outgoing'
),
}
function:
def _product_inc_out_qty(self, cr, uid, ids, field_names=None, arg=False, context=None):
if context is None:
context = {}
res = {}
for move_id in ids:
move = self.browse(cr, uid, move_id, context=context)
res[move.id] = move.product_id.incoming_qty or 0.0
return res
if I do something like this, then I get error TypeError: float() argument must be a string or a number
def _product_inc_out_qty(self, cr, uid, ids, field_names=None, arg=False, context=None):
if context is None:
context = {}
res = {}
vals = {
'outgoing_qty': 0.0,
'incoming_qty': 0.0,
}
for move_id in ids:
move = self.browse(cr, uid, move_id, context=context)
vals['outgoing_qty'] = move.product_id.qty_available or 0.0
vals['incoming_qty'] = move.product_id.incoming_qty or 0.0
res[move.id] = vals
return res

Multiple fields can be computed at the same time by the same method, just use the same method on all fields and set all of them:
discount_value = fields.Float(compute='_apply_discount')
total = fields.Float(compute='_apply_discount')
#depends('value', 'discount')
def _apply_discount(self):
for record in self:
# compute actual discount from discount percentage
discount = record.value * record.discount
record.discount_value = discount
record.total = record.value - discount
You can find an example in old api at sale_order

The problem in my code was that in old API if you want to return values for more than 1 field you need to add multi="any_string" to your field
So my fields should look like this
'incoming_qty': fields.function(_product_inc_out_qty, type='float',
digits_compute=dp.get_precision('Product Unit of Measure'),
multi='all',
string='Incoming'
),

Related

How to override create methode in odoo 10

i want to use same create method in odoo 10 as below means i want to convert below code in odoo 10, below code is working well for odoo 8
def create(self, cr, uid, vals, context=None):
phase_obj = self.pool.get('hr_evaluation.plan.phase')
survey_id = phase_obj.read(cr, uid, vals.get('phase_id'), fields=['survey_id'], context=context)['survey_id'][0]
if vals.get('user_id'):
user_obj = self.pool.get('res.users')
partner_id = user_obj.read(cr, uid, vals.get('user_id'), fields=['partner_id'], context=context)['partner_id'][0]
else:
partner_id = None
user_input_obj = self.pool.get('survey.user_input')
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = user_input_obj.create(cr, uid, {'survey_id': survey_id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id}, context=context)
vals['request_id'] = ret
return super(hr_evaluation_interview, self).create(cr, uid, vals, context=context)
i am trying below code:
def create(self, vals):
survey_id = self.env['hr_evaluation.plan.phase'].read(vals.get('phase_id'),fields=['survey_id'])['survey_id'][0]
if vals.get('user_id'):
partner_id = self.env['res.users'].read(vals.get('user_id'), fields=['partner_id'])['partner_id'][0]
else:
partner_id = None
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = self.env['survey.user_input'].create({'survey_id': survey_id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id})
vals['request_id'] = ret
return super(hr_evaluation_interview, self).create(vals)
but it is giving me error like TypeError: read() got multiple values for keyword argument 'fields' so please guide me how can i remove this error?
read method accept fields as argument and you give it two arguments.
read([fields])
Reads the requested fields for the records in self, low-level/RPC method. In Python code, prefer browse().
Parameters
fields -- list of field names to return (default is all fields)
Returns
a list of dictionaries mapping field names to their values, with one dictionary per record
Raises
AccessError -- if user has no read rights on some of the given records
Instead of calling read method it's better to call browse() method, you can read Browse() vs read() performance in Odoo 8
Your code should be:
def create(self, vals):
survey_id = self.env['hr_evaluation.plan.phase'].browse(vals.get('phase_id'))
if vals.get('user_id'):
partner_id = self.env['res.users'].browse(vals.get('user_id'))
else:
partner_id = None
if not vals.get('deadline'):
vals['deadline'] = (datetime.now() + timedelta(days=28)).strftime(DF)
ret = self.env['survey.user_input'].create({'survey_id': survey_id.id,
'deadline': vals.get('deadline'),
'type': 'link',
'partner_id': partner_id.id})
vals['request_id'] = ret.id
return super(hr_evaluation_interview, self).create(vals)

How to display name_get() in openerp?

I have tried to display name , description fields for the many to one field. The code is as follows, help me to resolve this problem
from openerp.osv import orm, fields
class post_branch(orm.Model):
_name = "branches"
_columns = {
'name':fields.char("Name", size=50, required=True),
'description':fields.text("Description",),
'emp_id':fields.one2many("man", "branch_id", "lines")
# 'emp_id':fields.many2one("man","lines",required=True)
}
def name_get(self, cr, uid, ids, context=None):
res = []
for r in self.read(cr, uid, ids['name', 'description']):
res.append(r['id'], '%s,%s' (r['name'],r['description']))
return res
# def name_des(self, cr,uid, context=None):
# obj_name=self.pool.get('')
Try following,
def name_get(self, cr, uid, ids, context=None):
res = []
if not ids:
return res
for r in self.browse(cr, uid, ids, context=context):
name = str(r.name) + ',' + str(r.description or '')
res.append((r.id, name))
return res

field.function - KeyError: 40

Created a column 'line_no' when i updated the value it throws the KeyError: 40
My code:
def _get_line_no(self, cr, uid, ids, line_no, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
nextno =0
no = record.next_line_no
next_no = nextno + no
total =+ next_no
res={
'next_line_no':next_no,
'line_no': total
}
return res
_columns = {
'line_no':fields.function(_get_line_no,string='Line No',type='integer'),
'next_line_no':fields.integer(' Next Line No'),
}
_defaults = {
'next_line_no':1
}
Throws Error : KeyError: 40
How do i resolve?
next_line_no is a database field, So it won't effect the dynamic way.
You need to modify this way,
def _get_line_no(self, cr, uid, ids, line_no, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
nextno =0
no = record.next_line_no
next_no = nextno + no
total += next_no
res[record.id]={
'next_line_no':next_no,
'line_no': total
}
return res
_columns = {
'line_no':fields.function(_get_line_no,string='Line No',type='integer', multi="lineno"),
'next_line_no': function(_get_line_no,string='Next Line No',type='integer', multi="lineno", store=True),
}
_defaults = {
'next_line_no':1
}
I hope this will yelp you.
Change the columns by,
_columns = {
'line_no':fields.function(_get_line_no,string='Line No',type='integer', multi="line"),
'next_line_no':fields.function(_get_line_no, type='integer', string='next line number' ,multi="line"),
}
and your method like,
def _get_line_no(self, cr, uid, ids, field_names, args, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
nextno =0
no = record.next_line_no
next_no = nextno + no
total += next_no
res[record.id]={
'next_line_no':next_no,
'line_no': total
}
return res
This will work.

indent using condition

please help me..what's wrong
def _amount_all(self, cr, uid, ids, name, args, context=None):
res = {}
for invoice in self.browse(cr, uid, ids, context=context):
res[invoice.id] = {
'amount_untaxed': 0.0,
'amount_tax': 0.0,
'amount_total': 0.0
}
for line in invoice.invoice_line:
res[invoice.id]['amount_untaxed'] += line.price_subtotal
for line in invoice.tax_line:
res[invoice.id]['amount_tax'] += line.amount
res[invoice.id]['amount_total'] = res[invoice.id]['amount_tax'] + res[invoice.id]['amount_untaxed']
cr.execute('select payment from sale_order where name = %s',(invoice.origin,))
ads = cr.fetchone()
pay = ads and ads[0] or None
if pay == 'deposit':
if invoice.partner_id.avail < 0:
raise osv.except_osv(_('Invalid action !'), _('Deposit must be recharged')
if invoice.amount_total != res[invoice.id]['amount_total']:
temp = invoice.partner_id.depot - res[invoice.id]['amount_total']
cr.execute('update res_partner set depot=%s where id = %s', (temp, invoice.partner_id.id,))
return res
I checked the condition that if he paid using a deposit and is available if less than zero if not then deposit reduction is done. I think..this is correct..but when I running, appear like this
if invoice.amount_total != res[invoice.id]['amount_total']:
SyntaxError: invalid syntax
Why have you given 2tabs(8 spaces) after the line raise osv.except_osv()
Your code should be like
def _amount_all(self, cr, uid, ids, name, args, context=None):
res = {}
for invoice in self.browse(cr, uid, ids, context=context):
res[invoice.id] = {
'amount_untaxed': 0.0,
'amount_tax': 0.0,
'amount_total': 0.0
}
for line in invoice.invoice_line:
res[invoice.id]['amount_untaxed'] += line.price_subtotal
for line in invoice.tax_line:
res[invoice.id]['amount_tax'] += line.amount
res[invoice.id]['amount_total'] = res[invoice.id]['amount_tax'] + res[invoice.id]['amount_untaxed']
cr.execute('select payment from sale_order where name = %s',(invoice.origin,))
ads = cr.fetchone()
pay = ads and ads[0] or None
if pay == 'deposit':
if invoice.partner_id.avail < 0:
raise osv.except_osv(_('Invalid action !'), _('Deposit must be recharged')
if invoice.amount_total != res[invoice.id]['amount_total']:
temp = invoice.partner_id.depot - res[invoice.id]['amount_total']
cr.execute('update res_partner set depot=%s where id = %s', (temp, invoice.partner_id.id,))
return res

take field date from another database

in ticket.py. I have two class. class deposit.line and res_partner (inherit). I want to take the date of the class deposit.line but its function in the class res_partner(inherit)
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
obj2 = self.pool.get('deposit.line')
for record in obj2.deposit_line:
temp1 = record.date
print temp1
print result
return result
but the results of its existing print false. what wrong ? please correct my code
PS:
My explanation is less good. but look at my code,surely knowing my explanation.
THIS MY COMPLETE CODE:
class deposit_line(osv.osv):
_name ="deposit.line"
_description = "Deposit Line"
_columns = {
'name': fields.char('Name', size=64),
'ref': fields.char('Reference', size=64),
'amount': fields.float('Amount'),
'date': fields.date('Date', required=True),
'deposit_id': fields.many2one('res.partner', 'Deposit ', required=True, ondelete='cascade'),
}
deposit_line()
class res_partner(osv.osv):
_inherit = 'res.partner'
def _compute_age(self, cr, uid, ids,date_birth,age,arg, context=None):
result = {}
for r in self.browse(cr, uid, ids, context=context):
age=0
if r.date_birth:
age = (datetime.now()-datetime.strptime(r.date_birth,"%Y-%m-%d")).days/365.25
result[r.id] = age
return result
def _compute_dept(self, cr, uid, ids, deposit, available, arg, context=None):
result = {}
for r in self.browse(cr, uid, ids, context=context):
avail=0
temp = r.available
if r.deposit:
avail = r.deposit + temp
result[r.id] = avail
return result
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
obj2 = self.pool.get('deposit.line')
for record in obj2.deposit_line:
temp1 = record.date
print temp1
print result
return result
_columns = {
'speaker': fields.boolean('Leader'),
'event_ids': fields.one2many('event.event','main_speaker_id', readonly=True),
'event_registration_ids': fields.one2many('event.registration','partner_id', readonly=True),
'airline': fields.boolean('Airlines'),
'hotel': fields.boolean('Hotel'),
'date_birth': fields.date('Date of Birth'),
'id_no': fields.char('ID. No', size=20),
'id_expired': fields.date('Expired Date'),
'sex':fields.selection([('male','Male'),('female','Female')],'Sex'),
'age' : fields.function(_compute_age, type='float', method=True, store=True, string='Age', readonly=True),
'deposit': fields.function(_compute_dept2, type='float', method=True, store=True, string='Deposit', readonly=True),
'available': fields.function(_compute_dept, type='float', method=True, store=True, string='Available', readonly=True),
'deposit_ids':fields.one2many('deposit.line', 'deposit_id', 'Deposit Line'),
}
res_partner()
Since you have one2many field for deposit_line defined in the res.partner model, you do not need the to access deposit_line object directly.
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
for partner in self.browse(cr, uid, id, context=context)
result[partner.id]=0
for deposit_line in partner.deposit_ids:
result[partner.id] += deposit_line.amount
return result
After line 3, you forgot to:
obj2.browse(cr, uid, ids, context=context)
You should learn to use the debugger:
Add the line import pdb; pdb.set_trace() where you want to place a breakpoint. When the Python reaches the breakpoint it stops at the console with a (pdb) prompt. There type p obj to print variable obj, n to step to the next instruction, and hfor help. You might find more info in this post and in the docs.