Odoo 10 Traverse Many2many field - odoo

I have the following for loop where account_move_id is a Many2one field:
...
for line in payment.move_line_ids + expense_sheet.account_move_id.line_ids:
...
I have modified account_move_id making it a Many2many field. Hence when I run the code I get an "expected singleton" exception in the for loop line.
Given that now account_move_id is a Many2many field, how could I get all line_ids from all account_move_ids of expense_sheet?
Thanks,

I don't where is the problem exactly but when you get this error most likely you where trying to acces a field but in recordSet that contains more than one record.
When you use decorator api.multi self in the method can contains more than one record so to avoid this error always loop through self.
for rec in self:
# here rec will alawys contain just one record
rec.some_field
so this error can happen in one2many field basically check where did you acces a field or method in a recordSet

You can use mapped() to gather a certain field from all records in a recordset.
How could I get all line_ids from all account_move_id of expense_sheet?
# If account_move_id is a recordset, mapped will get line_ids for all of them
line_ids = expense_sheet.account_move_id.mapped('line_ids')

Related

Override many2one with many2many

I try to override many2one field with many2many
property_product_pricelist = fields.Many2many('product.pricelist',
string="Sale Pricelist",
help="This pricelist will be used, instead of the default one, for sales to the current partner")
and i get this error when try to save values
File "/home//workspace/odoo-9.0/openerp/models.py", line 5384, in _browse
env.prefetch[cls._name].update(ids)
TypeError: unhashable type: 'list'
also i tryid like this
property_product_pricelist = fields.Many2many('product.pricelist', column1='partner_id', column2='pricelist_id')
but get
ProgrammingError: column product_pricelist_res_partner_rel.pricelist_id does not exist
LINE 1: SELECT product_pricelist_res_partner_rel.pricelist_id, produ...
Best solution I came up with.
create a many2many field totally new
write an onchange method which sets the value of the original field (here the many2one) to the new many2many field
multiply_pricelists_ids = fields.Many2many(
'product.pricelist', string='Multiply Pricelists')
#api.onchange('property_product_pricelist')
#api.multi
def pricelist_change(self):
self.multiply_pricelists_ids = self.property_product_pricelist

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.

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 ..

Computed many2many field dependencies in Odoo 10

I am trying to create a new field on the sale.order.line model. This field is called x_all_route_ids, and is meant to contain all of the available stock.location.route for an Order Line.
It should look up the product_id.route_ids and product_id.routes_from_categ_ids for the Order Line, and join them together into a single set of Routes.
I am trying to set this field up through the Odoo UI, but getting error related to my "Dependencies".
I have Dependencies defined as:
product_id, product_id.route_ids, product_id.routes_from_categ_ids
I have Compute defined as:
for record in self:
record['x_all_route_ids'] = record.product_id.route_ids
To start I am just trying to get the field to show the same value as product_id.route_ids, but it's not working. When I save, I get the following error:
Error while validating constraint
Unknown field u'product_id' in dependency u'product_id'
Any idea what I'm doing wrong here?
I was able to get this working. I think the issue was just a bug in the UI that came about because I had been trying so many different things. After refreshing the page, the following worked:
Dependency = product_id
Field type = many2many
Compute method:
for record in self:
full = record.product_id.route_ids | record.product_id.route_from_categ_ids
record['x_all_route_ids'] = full.filtered('sale_selectable')

Odoo - Understanding recordsets in the new api

Please look at the following code block:
class hr_payslip:
...
#api.multi # same behavior with or without method decorators
def do_something(self):
print "self------------------------------->",self
for r in self:
print "r------------------------------->",r
As you can see I'm overriding a 'hr.payslip' model and I need to access some field inside this method. The problem is that it doesn't make sense to me what gets printed:
self-------------------------------> hr.payslip(hr.payslip(1,),)
r-------------------------------> hr.payslip(hr.payslip(1,),)
Why is it the same thing inside and outside of for loop. If it's always a 'recordset', how would one access one record's field.
My lack of understanding is probably connected to this question also:
Odoo - Cannot loop trough model records
Working on RecordSets always means working on RecordSets. When you loop over one RecordSet you will get RecordSets as looping variable. But you can only access fields directly when the length of a RecordSet is 1 or 0. You can test it fairly easy (more then one payslip in database!):
slips = self.env['hr.payslip'].search([])
# Exception because you cannot access the field directly on multi entries
print slips.id
# Working
print slips.ids
for slip in slips:
print slip.id