How to get values in onchange with sudo() - odoo

I have added one onchange method, in that onchange method I have used sudo() while accessing many2one field.
But with sudo(), I am not able to get record's values with sudo.
So how can I get values of onchange record (<odoo.models.NewId object at 0x7fba62f7b3d8>) with sudo().
Here is sample code :
#api.onchange('product_id')
def onchange_product_id(self):
for record in self:
print(record.product_id)
print(record.sudo().product_id)
Actual result :
product.product(13,)
product.product()
Expected result :
product.product(13,)
product.product(13,)

That's because the recordset doesn't exist outside the current transaction. So your current user can see the contents but other users can't.
The code looks good to me, in fact, if you see path_to_v12/addons/hr_expense/models/hr_expense.py lines 563-567, you'll see a similar code:
#api.onchange('employee_id')
def _onchange_employee_id(self):
self.address_id = self.employee_id.sudo().address_home_id
self.department_id = self.employee_id.department_id
self.user_id = self.employee_id.expense_manager_id or
self.employee_id.parent_id.user_id

Related

Rails: How to use instance method in Active Record Query

I am having a filter query which should return all the records where either
attribute (column) "status" is not "done", or
instance method "completeness_status" does not return "done"
The query is something like that:
Studies.where("studies.status != ? OR studies.completeness_status != ?", "done", "done")
but I am getting error that column completeness_status does not exist.
Unfortunately, the column status is not continuously updated, so I cannot use it only. Also, the instance method "completeness_status" is based on records from other tables.
I try to add a scope to my model and use this instance method as scope but also I was not successful.
Also, I tried to used it as class method but then I do not know how to call it from where clause.
def self.completeness_status(study)
# code
end
or
def self.completeness_status_done?(study)
# code return true or false
end
Any Idea how to solve that.
Thanks.
You cannot use instance methods inside your query. But if you like to check the condition of completeness for only one row, then you can use it as instance method:
first_study = Study.first
first_study.completeness_status_done?
Also, if you provide more information about what is going on inside your completeness_status_done? then maybe I can give you some ideas to use scopes.
https://guides.rubyonrails.org/active_record_querying.html

How can I find out the difference between when user changes fields and when field fills automatically from record on the table in onchange function?

I have a many2one field as A and one2many field as A_details that A_details has filter base on A,
A = fields.Many2one(comodel_name="headertable")
A_details = fields.One2many(comodel_name="detailtable")
and in the xml I pass the A value with context in A_detail to filter it
<field name="A_detail" context="{'parent_id': A,}"/>
now I want to delete A_detail's records when user changes the A value, so I use onchange decorator on A field like this:
#api.onchange('A')
def _delete_selected_records(self):
for rec in self.A_details:
self.A_details = [(3, rec.id, 0)]
this function workes correctly to create mode but the problem occurs when I open the record from tree view and while A field is getting value from model Onchanged decorator call the _delete_selected_records function and it delete all the A_detail's records, That's why I want to check in this function that if user change the A, delete the A_detail's records else if system sets value to field do nothing... how can I handle this???
You should add a check if A is deleted or not meaning if A is False then do X:
#api.onchange('A')
def _delete_selected_records(self):
for rec in self:
if rec.A is False:
rec.A_details = [(3, rec.id, 0)] # You can you .unlink() btw
else:
continue
This way even if the function is triggered by let's say a user accidentally putting cursor on the field in the view or something you won't risk deleting anything unless the correct condition is met.

How to get old value of a field in a fucntion - Odoo12

I am trying to get the old value of a field in onchange method.
Here is what I tried.
#api.onchange('assigned_to')
# #api.depends('assigned_to')
def onchange_assigned_to(self):
print('onchange_assigned_to')
history = self._origin.read(["assigned_to"])
if history:
id = history[0]["assigned_to"][0]
last_assigned = self.env['res.users'].browse([id])
self.last_assign_id = last_assigned
The above code is working and I getting the old value only if I change the field value through GUI.
I am also changing the field value via button action., that time this function is not working.
How can I achieve this?
And I also tried on compute function with #api.depends.
That time I got an
'AttributeError: 'crm.lead' object has no attribute '_origin''
You can implement this in write method, and will always work, you can keep the onchange
if you want to give a feedback to the user:
#api.multi
def write(vals):
""" keep assignment history. """
if 'assigned_to' in vals: # keep assignment history
# no need to keep it in vals here
vals.pop('last_assign_id', None)
for rec in self:
rec.last_assign_id = rec.assigned_to
return super(ClassName, self).write(vals)

Set one2many values through onchange in odoo 9

How to set value for one2many field in odoo 9?
I've a one2many field login_details and its onchange function below:
#api.onchange('login_details')
def check_contact(self):
return {
'value':{'login_details': [(6,0, [])]}
}
But there is no effect on GUI? Help please
This may help you, and make sure that the field login_details is not readonly.
#api.onchange('login_details')
def check_contact(self):
# add your own code
res=[(0, 0, {'first_field': value1,
'second_field': value2,
})]
self.login_details = res
Odoo cut off the onchange values changes for o2m and m2m fields as you could see at:
https://github.com/odoo/odoo/blob/9.0/openerp/models.py#L6108-L6112
You could read there a comment saying that: At the moment, the client does not support updates on a *2many field. This statement is false
To get it working you will need to do something like I have proposed at:
https://www.odoo.com/forum/help-1/question/one2many-onchange-in-odoo-91362#answer-91400
Check and Try specifically the onchange redefined method to get it working

How to fill a field by date now from a click of a button

I want to fill a field by date now from a click of a button of the action
class sale_inheritd(models.Model):
_inherit = 'sale.order'
#api.multi
def action_sale_temporary(self):
for order in self:
self.env['project.project'].search([('project_id', '=', 'related_project_id')]).write({'temporary_reception_date':datetime.date.today()})
order.write({'state': 'temporary'})
What is the problem with this function?
I didn't understand the domain that you have passed to search method but if you want to fill a field with type Date:
.write({'temporary_reception_date':fields.Date.today()})
and for Datetime field:
.write({'temporary_reception_date':fields.Datetime.now()})
Note: and don't use self to access a field inside the loop exm: self.related_project_id use order.related_project_id instead or you most likely will have Singleton Error
EDITS: as #CZoellner said it's better to fields.Date.context_today(self) because that will prevent problems with user timezones
From your question it is not clear what are you trying to accomplish.
Your search method you search for project_id[looks like many2one field] equals to a string.
If it is many2one field then pass id to get correct result.
Also make sure self.env['project.project'].search([('project_id', '=', 'related_project_id')]) returns a single record only else it will lead to singleton error.
If there is only one record returned by search method then there is no issue in writing to the record like you did.