Add values on One2many field onchange - odoo

I'm trying to add values in my one2many field onchange.
I tried using the [(0,0, {values})] but nothing happened. Any idea on how to implement it?
custom_line_ids = fields.One2many('mrp.production', 'product_id', 'Custom Line')
#api.onchange('product_id')
def add_custom_line_ids(self):
mrp = self.env['mrp.productions'].search([])
result = []
vals = {
'sequence': self.sequence,
'name': self.name,
'product_id': self.product_id,
'date_planned_start': self.date_planned_start,
'state': self.state,
}
self.update({'custom_line_ids':[(0, 0, vals)]})

Actually you are using update method, which only update the model's value but not yet stored on database. You should use write method instead.

You need to return the value in onchange. This would work:
custom_line_ids = fields.One2many('mrp.production', 'product_id', 'Custom Line')
#api.onchange('product_id')
def add_custom_line_ids(self):
vals = {}
mrp_ids = self.env['mrp.productions'].search([])
if mrp_ids:
for mrp in mrp_ids:
vals['custom_line_ids']=[(0,0,{
'date': mrp.date,
})]
return {'value': vals}

Related

Update records on one2many fields in wizard for odoo16

Geting Issue 'TypeError: unhashable type: 'dict' for insert values in one2many field from onchange method in odoo16
My code is below:
class EmployeeAddWizard(models.TransientModel):
_name = 'employee.add.wizard'
line_ids = fields.One2many('employee.goal.add.line', 'wizard_id', string="Lines")
#api.onchange('challenge_id', 'employee_id')
def _onchange_action_goal_add(self):
r = []
value = {}
self.line_ids = {}
if self.challenge_id and self.employee_id:
goal_records = self.env['gamification.challenge.line'].search([('challenge_id', '=', self.challenge_id.id)])
for emp in self.employee_id:
for line in goal_records:
data = {'wizard_id': self.id, # Other table m2o
'goal_definition_id': line.definition_id.id,
'goal_rating': 0.0,
'goal_target': line.target_goal,
'employee_id': emp.id,
}
r.append(data)
value.update(records=r)
self.line_ids = value['records']
class GoalLine(models.Model):
_name = 'employee.goal.add.line'
wizard_id = fields.Integer()
goal_definition_id = fields.Many2one('gamification.goal.definition', string='Goal Definition', required=True, ondelete="cascade")
goal_rating = fields.Float('Rating', required=True)
goal_target = fields.Float('Target Value ', required=True)
employee_id = fields.Many2one('res.users', string="Employee", required=True, ondelete="cascade")
Thanks in advance
You passed a list of dicts which is not valid, you need to use special commands
Example:
r.append(Command.create(data))
or:
r.append((0, 0, data))
You can use Command.clear(), to remove previous lines if needed ( self.line_ids = {} should raise an error: ValueError: Wrong value).
Check this answer

Odoo TypeError: 'NewId' object is not iterable

I am trying to create an activity when a stage change occurs but keep getting TypeError: 'NewId' object is not iterable .
I figured out that #onchange creates a new object which replaces self and I am guessing this is the errors cause.
Here is my code:
class ProjectSetAndDateType(models.Model):
_inherit = 'project.task.type'
last_stage = fields.Boolean(string="Fertigstellungsstufe")
class ProjectSetEndDate(models.Model):
_inherit = 'project.task'
#api.onchange('stage_id')
def _set_end_date(self):
if self.stage_id.last_stage:
self.kanban_state = "done"
self.date_finished = datetime.strftime(datetime.now(),'%Y-%m-%d %H:%M:%S')
activity_deadline = datetime.now() + timedelta(days=30)
data = {
'res_id': self._origin.id,
'res_model': 'project.task',
'res_model_id': self.env['ir.model'].search([('model', '=', 'project.task')]).id,
'user_id': self._origin.project_id.user_id.id,
'summary': 'Aufgabe archivieren nach Fertigstellung',
'activity_type_id': self.env.ref('project_set_end_date.mail_set_end_date_archive').id,
'date_deadline': activity_deadline
}
self.env['mail.activity'].create(data)
'NewId' object is an recordset, when you are creating any new record odoo will store it in newid class , not in database and you are trying to write the kanban_state, date_finished in the record which is not yet created.
I suggest you to change the logic and rewrite this code on the write or create method,
Note: make sure you don't create any record on onchange method because it is very risky and not user friendly.
I rewrote it to this, now it is working as expected.
from odoo import models, fields, api
from datetime import timedelta
from datetime import datetime
class ProjectSetAndDateType(models.Model):
_inherit = 'project.task.type'
last_stage = fields.Boolean(string="Fertigstellungsstufe")
class ProjectSetEndDate(models.Model):
_inherit = 'project.task'
#api.multi
def write(self, vals):
if 'stage_id' in vals:
final_stage = self.env['project.task.type'].search([('id', '=', vals['stage_id'])]).last_stage
if final_stage:
vals['kanban_state'] = "done"
vals['date_finished'] = datetime.strftime(datetime.now(),'%Y-%m-%d %H:%M:%S')
activity_deadline = datetime.now() + timedelta(days=40)
data = {
'res_id': self.id,
'res_model': 'project.task',
'res_model_id': self.env['ir.model'].search([('model', '=', 'project.task')]).id,
'user_id': self.project_id.user_id.id,
'summary': 'Aufgabe archivieren nach Fertigstellung',
'activity_type_id': self.env.ref('project_set_end_date.mail_set_end_date_archive').id,
'date_deadline': activity_deadline
}
self.env['mail.activity'].create(data)
res = super().write(vals)
return res

Calling onchange method on product from values

I created invoice already and now I want to create invoice lines. but first, I want to call _onchange_product_id() method on the product that I'm adding to account_inv_line that I would receive all values from that product. how can I do this? onchange_inv_line_fields always returns None
for key, value in csv_info.iteritems():
account_invoice = {
'partner_id': value['partner_id'],
'number': value['number'],
'date_invoice': value['date_invoice'],
}
invocie = acc_inv_obj.with_context(type='in_invoice').create(account_invoice)
for value_line in csv_info[key]['invoice_line']:
account_inv_line = {
'product_id': value_line['product_id'],
'price_unit': value_line['price_unit'],
'quantity': value_line['quantity'],
}
inv_line = self.env['account.invoice.line'].create(account_inv_line)
onchange_inv_line_fields = inv_line._onchange_product_id()
To call onchange method we need to create temp_lines like this:
temp_line = self.env['account.invoice.line'].new(account_inv_line)
temp_line._onchange_product_id()
account_inv_line.update(temp_line._convert_to_write(temp_line._cache))
invocie.invoice_line_ids.create(account_inv_line)

Odoo: Two selection fields, second selection depends on the first selected value

I have a model with two selection fields. In the first selection field the user chooses a project, and in second the user chooses a tranche, depends on the selected first field. (for one project, we have many tranche)
I use this declaration to my function:
#api.multi
#api.onchange('project')
def _get_tranche(self):
print res
return res`
If I'll print in console the result of returned value is correct, and I have exactly what I search, but in the view, the second field value does not displays computed values to choose after setting the second field value.
Is there any method to make it work properly?
This is my code:
#api.model
def _get_project(self):
values = {'$top' : 100,
'$filter' : "'name==:1&&parent==null'",
'$params' : '\'["*"]\'' }
response = requests.get('http://localhost:8081/rest/Project/name',
auth=('admin', 'admin'),
params=values)
data = response.json()
res = []
for record in data['__ENTITIES']:
res.append((record['__KEY'], record['name']))
return res
#property
def ret_value(self):
return self.project
#api.multi
#api.onchange('project')
def _get_tranche(self):
if self.ret_value == False:
return []
values = {'$top' : 100,
'$filter' : "'parent.ID==:1'",
'$params' : '\'[' + self.ret_value + ']\'' }
response = requests.get('http://localhost:8081/rest/Project/name',
auth=('admin', 'admin'),
params=values)
data = response.json()
res = []
for record in data['__ENTITIES']:
res.append((record['__KEY'], record['name']))
print res
return res
_columns = {
'name': fields.char("Name", required=True),
'description' : fields.text(),
'project' :fields.selection(selection=_get_project, string="Project"),
'tranche' : fields.selection(selection=_get_tranche, string="Tranche"),
}
NB: a tranche is a project with parent_id (not null) = id of a project, I need do the following: when I select a project X from the first field selection "project", I can select the tranches of this project (project with parent_id=X) from the second field selection "tranche" what I can't understand is the result of print in the console is correct, but in the view the field tranche is empty??!!
Now I am trying this:
_columns = {
'name': fields.char("Name", required=True),
'description' : fields.text(),
'project' :fields.selection(selection=_get_project, string="Project"),
'tranche' : fields.selection(selection=_get_tranche,
string="Tranche", compute='_return_tranche'),
}
#api.depends('project')
def _return_tranche(self):
if self.ret_value == False:
self.tranche = []
return
values = {'$top' : 100,
'$filter' : "'parent.ID==:1'",
'$params' : '\'[' + self.ret_value + ']\'' }
response = requests.get('http://localhost:8081/rest/Project/name',
auth=('admin', 'admin'),
params=values)
data = response.json()
res = []
for record in data['__ENTITIES']:
res.append((str(record['__KEY']),str(record['name'])))
print res
self.tranche = res
return
#api.model
def _get_tranche(self):
values = {'$top' : 100,
'$filter' : "'name==:1&&parent!=null'",
'$params' : '\'["*"]\'' }
response = requests.get('http://localhost:8081/rest/Project/name',
auth=('admin', 'admin'),
params=values)
data = response.json()
res = []
for record in data['__ENTITIES']:
res.append((record['__KEY'], record['name']))
return res
But I get this error
File "/opt/odoo/odoo/openerp/fields.py", line 1529, in convert_to_cache
raise ValueError("Wrong value for %s: %r" % (self, value))
ValueError: Wrong value for crm.lead.tranche: [('6', 'Tranche I'), ('7', 'Tranche II'), ('8', 'Tranche III')]
Help me please...

Openerp Comparing another object field value with an object field

I have this:
class events_places(osv.osv):
"""Places for events"""
_name = 'oevents.places'
_columns = {
'name': fields.char('Name',size=35, help='Place\'s name', required = True),
'description': fields.char('Description',size=50, help='Place\'s description'),
'street': fields.char('Street',size=35, help='Place\'s street', required = True),
'number': fields.integer('Local number', help='Place\'s local number', required = True),
'zip': fields.char('Zip Code', size=5, help='Place\'s Zip code', required = True),
'city': fields.char('City',size=20, help='Place\'s city', required = True),
'country': fields.many2one('res.country', 'Country', help='Place\'s country'),
'state': fields.many2one('res.country.state','State', help='Place\'s state'),
'inWinter': fields.boolean('Active in winter', store = True, help='Place\'s province'),
}
_defaults = {
'inWinter' : True,
}
class events_events(osv.osv):
"""Client's contacts"""
_name = 'oevents.events'
_columns = {
'name': fields.char('Name',size=20, help='Event\'s name', required = True),
'place': fields.many2one('oevents.places','Place', help='Event\'s location', required = True),
'artist': fields.many2one('oevents.artists','Artist', help='Artist\'s performing in the event.', required = True),
'client': fields.many2one('res.partner','Client', help='Event\'s clients.', required = True),
'date': fields.date('Date', help='Event\'s date.', required = True),
'type': fields.selection([('children','Children\'s'),('private','Private'),('concert','Concert')],'Event type', help='Type of event this artist can do'),
}
_defaults = {
'type' : 'private'
}
When I want to create an event, there's a place related field. The event has a date, but it shouldn't let me create the event in a a winter date if the related place field in the event has the field inWinter unchecked.
How can I do that? I need to create a function or constraint which gets place inWinter field and compare it with the date, but I don't know how to do it. Any suggestions?
Thanks in advance!
You can override create & write method. In those methods just check whether "inWinter" is True or False.
def create() method will be called when new record will be created.
def create(self, cr, uid, vals, context=None):
if vals.get('place'):
event_brw = self.pool.get('oevents.places').browse(cr, uid, vals.get('place'), context=context)
#if inWinter is True
if event_brw.inWinter:
raise osv.except_osv('Error ! ', 'You can not create an event in winter.')
return super(oevents_events, self).create(cr, uid, vals, context)
def write() method will be called when record will be modified.
def write(self, cr, uid, ids, vals, context=None):
if vals.get('place'):
event_brw = self.pool.get('oevents.places').browse(cr, uid, vals.get('place'), context=context)
#if inWinter is True
if event_brw.inWinter:
raise osv.except_osv('Error ! ', 'You can not create an event in winter.')
return super(oevents_events, self).write(cr, uid, ids, vals, context)
you have to write an on_change function on 'date' field, where you raise an error if given date is in winter months and isWinter is false.
Of course, yo have to define range date for iswinter an put on_change in field definition in your xml view.
you should use constraints. grep addons folder for _constraints and _sql_contraints and you'll find a lot of examples.
Go for _constraints= , Is not at all good idea to call create and write.