How to override create methode in odoo 10 - odoo

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)

Related

Calculate two fields with on function

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'
),

Raise UserError only if none fields selected

I added my custom field to res.partner model and when I'm creating partner if branch_id is checked I want to that one of 3 fields should be selected. If some of the fields are not selected then I want to raise UserError.
But now it raises UserError even if I one of the fields is selected.
class ResPartner(models.Model):
_inherit = 'res.partner'
branch_id = fields.Many2one('branch.responsibility','Responsibility by branch')
drawer_id = fields.Many2one(
'furniture.parts.type', string='Drawer Type',
domain=[('type', '=', 'drawer')], )
flexible_id = fields.Many2one(
'furniture.parts.type', string='Flexible Type',
domain=[('type', '=', 'flexible')],)
runner_id = fields.Many2one(
'furniture.parts.type', string='Runner Type',
domain=[('type', '=', 'runner')], )
#api.model
def create(self, vals):
if vals.get('branch_id'):
if not vals['drawer_id'] or not vals['flexible_id'] or not vals['runner_id']:
raise UserError('You need to chose values from notebook raport data')
return super(ResPartner, self).create(vals)
UPDATE.
for write method, I tried this as CZoellner suggested for create but always get True True True for fields_to_check_in_vals
#api.multi
def write(self, vals):
if vals.get('branch_id') or vals.get('drawer_id') or vals.get('flexible_id') or vals.get('runner_id') or
vals.get('group_1_id') or vals.get('group_2_id')or
vals.get('group_3_id'):
fields_to_check = ['drawer_id', 'flexible_id', 'runner_id', 'group_1_id', 'group_2_id', 'group_3_id']
fields_to_check_in_vals = [f in self for f in fields_to_check]
if not any(fields_to_check_in_vals):
raise UserError('If branch is selected then you need to select one of the fields from data raport')
> return super(ResPartner, self).write(vals)
Your logic says, that all 3 fields have to be set. You could use any here:
if vals.get('branch_id'):
fields_to_check = ['drawer_id', 'flexible_id', 'runner_id']
fields_to_check_in_vals = [f in vals for f in fields_to_check]
if not any(fields_to_check_in_vals):
raise UserError()
Edit: the write method is a bit more tricky. Usually it is a multi record method, so a for each loop on self should be implemented. Then you'll need to use either getattr or just (it's suggested in the Odoo doc) treat the recordset like a dict. And then it could be, that the change happens right on the write call. So you have to check both the persisted and the new values:
for record in self:
if vals.get('branch_id'):
fields_to_check = ['drawer_id', 'flexible_id', 'runner_id']
fields_to_check_dict = {f:record[f] for f in fields_to_check}
fields_to_check_dict.update({f:f in vals for f in fields_to_check})
if not any(fields_to_check_dict.values()):
raise UserError()
That's a bit complicated. You could also first call super and just check after that. Raising an exception will rollback all changes, so nothing will happen.
res = super(MyModel, self).write(vals)
for record in self:
if vals.get('branch_id'):
fields_to_check = ['drawer_id', 'flexible_id', 'runner_id']
fields_to_check_in_record = [record[f] for f in fields_to_check]
if not any(fields_to_check_in_record):
raise UserError()
return res

Auto fill on2many field on form load odoo 8

I have tried to create a functional field with type="one2many" and auto fill on form load. I tried below code:
Code 1:
'flat_members1': fields.function(_get_flat_members, relation="family.info", method=True, type="one2many", multi='flat_fkk'),
def _get_flat_members(self, cr, uid, ids, name, arg, context=None):
cr.execute("Select * from family_info where flat="+str(flat_id)+"")
cr_res = cr.dictfetchall()
res = {}
for data in self.browse(cr,uid,ids):
res[data.id] = self.pool.get('family.info').search(cr,uid,[('flat', '=', flat_id)])
return values
Code 2:
member_ids = []
for res in cr_res:
member_ids.append((0,0,{'name':res.get('name'),
'flat':res.get('flat'),
}))
values.update(family_members1=member_ids)
return values
In both way i got an error:
AttributeError: 'list' object has no attribute 'iteritems'
Please suggest me a solution thanks.
Use Odoo8 new api:
flat_members1 = fields.One2many(compute='_get_flat_members',
comodel_name='family.info',
string='flat_members1',
store=True)
#api.one
#api.depends('flat_id')
def _get_flat_members(self):
member_ids = []
# get member_ids
self.flat_members1 = member_ids

Show product default_code in purchase order line

When creating a new purchase order I want to remove the product_name under the product_id so for that I did this function:
class snc_product(osv.osv):
_name='product.product'
_inherit='product.product'
def name_get(self, cr, uid, ids, context=None):
return_val = super(snc_product, self).name_get(cr, uid, ids, context=context)
res = []
def _name_get(d):
code = d.get('code','')
if d.get('variants'):
code = code + ' - %s' % (d['variants'],)
return (d['id'], code)
for product in self.browse(cr, uid, ids, context=context):
res.append((product.id, (product.code)))
return res or return_val
The problem now is even under description I'm getting the default_code instead of the name.
http://imgur.com/afLNQMS
How could I fix this problem?
Seems like you redefined also the name_get() method of the purchase.order.line model. The second column, named 'Description' is showing the name field ot the purchase.order.line model. That's why I suppose you redefined it.
Your solution is working for me - I have the product code in the first column and the description in the second. Only one thing - you don't need this internal _name_get() method as you don't use it.
Here is the code that worked for me:
from openerp.osv import osv, fields
class snc_product(osv.osv):
_name = 'product.product'
_inherit = 'product.product'
def name_get(self, cr, uid, ids, context=None):
return_val = super(snc_product, self).name_get(cr, uid, ids,
context=context)
res = []
for product in self.browse(cr, uid, ids, context=context):
res.append((product.id, (product.code)))
return res or return_val
snc_product()

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.