Reputation: 31
I've written a custom odoo module, and when I install it, it throws a singleton error. When I comment out everything inside _compute_margin(self), and just return 0.0, the module installs fine. When I then change the _compute_margin function back to original, and update the module, it updates fine.
What change(s) do I need to make in order to make the module install fine with the contents of the _compute_margin function?
class MyCompanyintercompanyMargin(models.Model):
_name = 'my_companyintercompany.margin'
name = fields.Char()
x_marginsplitmodel = fields.Char()
x_marginsplitdescription = fields.Char()
class ResPartner(models.Model):
_name = 'res.partner'
_inherit = 'res.partner'
x_my_companyintercompany = fields.Boolean()
x_my_companyintercompany_marginsplit = fields.Many2one(
'my_companyintercompany.margin',
string='Margin Split Model'
)
class SaleOrder(models.Model):
_name = 'sale.order'
_inherit = 'sale.order'
x_endcustomer = fields.Many2one(
comodel_name='res.partner',
string='Customer'
)
x_my_companyintercompany_marginsplit = fields.Many2one(string='Margin Split', related="partner_id.x_my_companyintercompany_marginsplit")
x_my_companyintercompany_marginsplitid = fields.Char(related="x_my_companyintercompany_marginsplit.name", string="Margin Split")
x_prsmarginpercentage = fields.Float(string="Marge %")
@api.depends('order_line.margin')
def _compute_margin(self):
amount_untaxed = self.amount_untaxed
if self.x_my_companyintercompany_marginsplit:
try:
if self.x_my_companyintercompany_marginsplitid == "Total -2,5%":
totalordercost = 0.0
for line in self.order_line:
totalordercost += line.purchase_price * line.product_uom_qty
intercompanymargin = amount_untaxed * 0.025
self.x_prsmargin = amount_untaxed - totalordercost - intercompanymargin
elif self.x_my_companyintercompany_marginsplitid == "Marge 50/50":
self.x_prsmargin = self.margin / 2
else:
self.x_prsmargin = self.margin
except:
raise "Exception!"
else:
self.x_prsmargin = self.margin
if amount_untaxed > 0.0:
self.x_prsmarginpercentage = self.x_prsmargin / amount_untaxed * 100
else:
self.x_prsmarginpercentage = 0.0
x_prsmargin = fields.Monetary(compute='_compute_margin', store='true')
Upvotes: 2
Views: 3318
Reputation: 14778
The compute method will be called with multiple records, which are provided in self
. But you try to get attributes directly from self
, which only works on singletons (record sets with exactly one record).
So you have two options to fix the problem:
self
. You should also decorate the method with @api.multi
. Simple example:@api.multi
@api.depends('field1', 'field2', 'fieldn')
def _compute_my_field(self):
for record in self:
record.my_field = 4711
@api.one
to tell Odoo to loop on it for every record in self
. Odoo will loop on every record in self
and will gather the method return values in a list which will be the return value in the end of the loop. You can use self
in a way you are using already: as a singleton.Upvotes: 2
Reputation: 2135
You need to decorate your compute method with @api.multi.
Basically, when Odoo tries to initialize your new field in the database, it is going to compute for many records at once. The way you have your method set up currently can only support a single record at a time, which is why you get the Expected singleton message.
Try with following:
# First, include the @api.multi decorator
@api.multi
@api.depends('order_line.margin')
def _compute_margin(self):
# Second, use a for loop to loop over self
# because it's possible for self to be multiple records
for order in self:
# Finally, use your same method logic in the loop...
# Except that you must assign the result **per record**
# in the loop (with `order` in this example instead of `self`)
order.x_prsmarginpercentage = ...
See more details in the Odoo ORM Documentation
Upvotes: 2