How to update one2many in customers from accounting invoice - odoo

I have created an one2many to customer form. So, when I am validating (button validate) an invoice I am trying to pass some values in that one2many. I have tried many ways and followed odoo forums, but I am having trouble to do that. Using following code:
My one2many field is 'customer_status' in 'res.partner' :
#api.multi
#api.model
def invoice_validate(self):
customer_obj=self.env['res.partner']
customer_id=customer_obj.search([('id','=',self.partner_id.id)])
customer_line=customer_obj.browse(customer_id)
dd = {'policy_number': self.policy_no,}
customer_stat_add = customer_obj.write([customer_line.id],{
'customer_status': [(0, 0, dd)]
})
state_change = self.write({'state': 'open'})
return state_change, customer_stat_add
It gives me this error:
ValueError: "invoice_validate() takes exactly 2 arguments (1 given)" while evaluating
u'invoice_validate()'
Thanks.

buttons w/ new api need #api.multi and if you want to work on a single object you can use self.ensure_one();
#api.multi
def foo(self):
self.ensure_one()
print self.my_field
Also, you don't need to browse object as you already get browse objects w/ new api.
Bear in mind that if that feature is an odoo base feature you must call super().method_name to not break anything ;)

Related

error with rec.env['book.tickets'].search()

#api.depends('totalbook')
def _computebook(self):
sum_a = 0
for rec in self:
for l in rec.env['book.tickets'].search([('status', 'in', ('sold', 'rent'))]):
if l:
sum_a += 1
rec.currentbook = rec.totalbook - sum_a
I use this compute to calculate current book in library.
But when I run this code, the problem calculate of my each book base on all books.
When you are write any compute method in odoo, in self you will get all the list of browsable objects.
And then you are trying to search data from that browsable object. That's why you get a error.
You have to use self.env instead of rec.env.
Because you can't search data from browsable object you can access only data of that browsable object.
You have to add limit 1 on when you are searching a record of multiple record are than you will get another expected Singleton error.
Either you can you use another loop after searching record.
Let me know if you face any errors again.
Thanks
this error occured because
whenever you are trying to make a object of another model at that time you should have to use with self.env instead of rec.env because in your method rec is just a record-set of your instance
so please update your method as per the following snippet.
for l in self.env['book.tickets'].search([('status', 'in', ('sold','rent'))]):

Accesing oneToMany data from odoo model (odoo 12)

I have a list of tasks related to a project in a one-to-many relationship one project have many tasks, reading the official documentation the field access should be as easy as iterating on a list and access the field by name, this is the code I have done so far:
def _roles_assigned(self):
for rec in self:
total = len(rec.task_ids)
for e in rec.tasks
logging.info(e.status) #<-- this should print status
I print the result and get 'project.task(X,)' where I guess X is the Id of the task, how can I access the task properties?
Note: the field is a selection field
try something like this:
def _roles_assigned(self):
for tasks in self.task_ids:
logging.info(tasks.status)
Since the field is a selection I had to access the dictionary
#api.multi
#api.depends('task_ids')
def _roles_assigned(self):
for rec in self:
total = len(rec.tasks)
assigned = 0
for e in rec.tasks:
selected = dict(e._fields['status'].selection).get(e.status) #<-- getting selected value from a selection field

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

Expected singleton odoo 9

After enter 2 and more new row in tree view and click on save get error
raise ValueError("Expected singleton: %s" % self)
ValueError: Expected singleton: my.model(2116, 2117)
My source code:
#api.depends('start', 'finish','stop')
def total_fun(self):
time1 = datetime.strptime(self.start, "%Y-%m-%d %H:%M:%S")
time2 = datetime.strptime(self.finish, "%Y-%m-%d %H:%M:%S")
self.total = round(((time2 - time1).seconds / float(60*60) - self.stop))
Error message says -> expected singleton this means: you are using recordset instead of record.
To fix this use
for rec in self:
in the begining of function, and then use rec instead of self
As you can see in the error message Expected singleton: my.model(2116, 2117)
By default in odoo the self is always a recordSet (means it can contain more then one record.) so when you do self.getSomeField here odoo will be confused wich record you want to get the value from.
if you don't tell odoo that make sure that the self will always contain one record when you acces an attribute if the recordSet contains more than one record this error is raised.
Now how to tell odoo make sure there is always one record is by adding #api.one decorator to the method. but is not recommended because odoo in your case there is two record so he will loop and call the method for each record and pass a recordSet that have only that record. imagine that you execute a search or any communication with database.
so don't use #api.one only if you are sure of what you are doing because you can make 10000 method call and interact with database.
like this example using #api.one:
# every call to this method you will execute a search.
self.env['some.model'].search([('m2o_id' , '=', self.id)]
you can do this before the loop:
# one query for all record with one call to the method
result = self.env['some.model'].search([('m2o_id' , 'in', self.ids)]
for rec in self:
# use result here
# or here ..