I have a problem in ODOO 10 with a many2many relationship.
I have extended res.partner this way:
class ResPartner(models.Model):
x_bagsdesign = fields.Many2many('product.product',string='Bags Design',relation='bags_design_manufactur')
then I have extended also product.template model:
class product_template_fields(models.Model):
_inherit = 'product.template'
x_traders_stock = fields.Many2many(
'res.partner', string='Traders with access to stock',relation='xtradstock_res_partner_rel')
#api.multi
def write(self, vals):
record = super(product_template_fields, self).write(vals)
for singletrader in self.x_traders_stock:
singletrader.x_bagsdesign = [(4,self.id)]
return record
This way every time a new x_traders_stock is inserted in product.template, a new x_bags_design is also created in res.partner.
BUT.. when I save a new record in product.template I get an sql error:
bad query: INSERT INTO bags_design_manufactur (res_partner_id, product_product_id)
(SELECT a, b FROM unnest(ARRAY[1]) AS a, unnest(ARRAY[7]) AS b)
EXCEPT (SELECT res_partner_id, product_product_id FROM bags_design_manufactur WHERE res_partner_id IN (1))
I don't understand where the EXCEPT part of the sql query is coming from and how to prevent it. If anyone can help I would be grateful.. thanks!
The error message is a bit different from expected, but I can fix some problems in your code. First of all you have to take into account that a product.product object is a variant of a product.template object, so you can have in a database many product.product objects pointing to the same product.template (e.g. a product.template is a T-shirt and a product.product is a T-shirt colour red size M). This means that you can't try to set the ID of a product.template in a field which is expecting the ID of a product.product, as you're doing here:
singletrader.x_bagsdesign = [(4,self.id)]
Of course, that mistake will not give you the message error you are receiving, there must be something wrong in other part of your code (I guess related to bags_design_manufactur model).
However, to fix the problem I told you above, you should write this:
class product_template_fields(models.Model):
_inherit = 'product.template'
x_traders_stock = fields.Many2many(
comodel_name='res.partner',
string='Traders with access to stock',
relation='xtradstock_res_partner_rel'
)
#api.multi
def write(self, vals):
result = super(product_template_fields, self).write(vals)
for prod_templ in self:
products = self.env['product.product'].search([
('product_tmpl_id', '=', prod_templ.id),
])
for singletrader in prod_templ.x_traders_stock:
singletrader.write({
'x_bagsdesign': [(4, product.id) for product in products],
})
return result
EDIT
product.product inherits from product.template by delegation, this means that every field you create in product.template model is going to be available in product.product objects, so when you are creating the Many2many field x_traders_stock in product.template, you're creating it in product.product too, so you don't need to add records each time a x_trader is generated. Instead you should change your models:
class ResPartner(models.Model):
x_bagsdesign_prod_templ = fields.Many2many(
comodel_name='product.template',
column1='partner_id',
column2='product_tmpl_id',
string='Bags Design',
relation='xtradstock_res_partner_rel'
)
class ProductTemplate(models.Model):
_inherit = 'product.template'
x_traders_stock = fields.Many2many(
comodel_name='res.partner',
column1='product_tmpl_id',
column2='partner_id',
string='Traders with access to stock',
relation='xtradstock_res_partner_rel'
)
And then, if you want to access to the product.product objects a partner has, you can do it this way:
any_partner.x_bagsdesign_prod_templ.mapped('product_variant_ids')
If you preferred it, you could even create a new related field in res.partner which brought the product.product objects a partner has.
Related
I have a visitorSaveSerializer which is responsible for validating the data to be saved:
class VisitorSaveSerializer(serializers.ModelSerializer):
class Meta:
model = Visitor
fields = ('gsm', 'email', 'firstname', 'lastname')
The problem is:
visitor_serializer = VisitorSaveSerializer(data={...related data here...})
if visitor_serializer.is_valid():
visitor_serializer.save()
visitor_id = visitor.serializer.data.get("id", 0) // Fails for sure.
OK, I know id is not among serializer fields, so last line fails.
How should I approach saving an object when I need to get last inserted id?
The serializer returns the instance saved, so you can obtain the primary key of that instance with:
visitor_serializer = VisitorSaveSerializer(data={…})
if visitor_serializer.is_valid():
visitor = visitor_serializer.save()
visitor_id = visitor.pk
I have an inherited model from res.partner.bank which i added a custom field called location to, this is how the model looks like.
class SalesPartnerBankInherit(models.Model):
_inherit = 'res.partner.bank'
location = fields.Char()
I have another inherited model from sale.order with a field that has a many2one relationship to res.partner.bank
I want to show only 1 record on the many2one dropdown if there are more than 1 records in res.partner.bank that has the same location field value?
This is my inherited sale.order model with the many2one location_id field
location_id = fields.Many2one('res.partner.bank',
string='Bank Account Location')
So if there are duplicate res.partner.bank records with the same location, I want to show only 1 record on the dropdown.
First, make your field compute then in compute method search all record from specific model and assign as per your requirement.
location_id = fields.Many2one('res.partner.bank', string='Meters', compute="_get_value")
def _get_value(self):
for i in self:
records = self.env['res.partner.bank'].search([], limit=1) # search with one record only from whole search and assign it.
i.location_id = records and records.id
Odoo-10
My .py
class komMo(models.Model):
_name = 'kom.mo'
mo_id = fields.Integer(string='Code mo') #this is just the recognition number
name = fields.Char(string='Name mo')
parent_id = fields.Many2one('kom.mo')
I want to hide the option(example) from the drop list ('parent_id'), if that is the name of the object itself
So when I'm going to edit an 'example', I do not want to be offered as an option in the field 'parent_id'
When I create a new 'example2' it's all good, because only the existing items are displayed in the drop-down list.
If I was not clear please tell me.
my .xml file was pretty basic i did not add any options or attributes
Just add this domain to the field domain="[('id', '!=', id)]". That will remove the object for its own form.
You can also use odoo's nested set system for parent child relationship, which has great benefit in resolving parent child relationship query, by setting _parent_store = True in models definition, and adding parent_left, parent_right fields, you can the also use #api.constraint on parent_id calling odoo Models _check_recursion to ensure that there is no recursive parent child relationship creation.
For example on odoo Product category model:
class ProductCategory(models.Model):
_name = "product.category"
_description = "Product Category"
_parent_name = "parent_id"
_parent_store = True
_parent_order = 'name'
_rec_name = 'complete_name'
_order = 'parent_left'
parent_id = fields.Many2one('product.category', 'Parent Category', index=True, ondelete='cascade')
parent_left = fields.Integer('Left Parent', index=1)
parent_right = fields.Integer('Right Parent', index=1)
#api.constrains('parent_id')
def _check_category_recursion(self):
if not self._check_recursion():
raise ValidationError(_('Error ! You cannot create recursive categories.'))
return True
I added 2 fields in 'sale.order.line' object. Let's say 'field1' and 'field2', those are readonly field. The value of the 2 fields will appear whenever the product is change in order line.
When I select a product, it shows the value of the two fields but when save it, the value will back 0, not stored.
Here's my code:
class sale_order_line(models.Model):
_inherit = 'sale.order.line'
field1 = fields.Float('One')
field2 = fields.Float('Two')
#api.multi
def product_id_change(self, pricelist, product, qty=0,
uom=False, qty_uos=0, uos=False, name='', partner_id=False,
lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False):
res = super(sale_order_line, self).product_id_change(pricelist, product, qty,
uom, qty_uos, uos, name, partner_id,
lang, update_tax, date_order, packaging, fiscal_position, flag)
if product:
one = self.search([('product_id', '=', product), ('partner_id', '=', partner_id)])
two = self.search([('product_id', '=', product), ('partner_id', '!=', partner_id)])
if customer:
field1 = one[-1]
res['value']['field1'] = field1
if other:
field2 = two[-1].
res['value']['field2'] = field2
return res
In Odoo framework we are now allowing to set readonly fields value, as well as readonly fields will not be getting in vals in create and write methods.
So if you set those readonly fields value in onchange methods then also it will not persist it's value because by nature it's readonly, it will not gives you any errors.
Purpose : The aims behind to define readonly attributes is to behave same through the all states of the record on UI and user can not change it's value and mainly define for display purpose.That is why readonly fields are not accessible for edit in onchange method.
Solution:
You need to override CREATE or WRITE method in following manner.
#api.model
def create(self, vals):
######
# WRITE YOUR LOGIC HERE AND BRING THOSE VALUE INTO VARIABLE AND THEN UPDATE IT IN VALS
VARIABLE_1 = SEARCH YOUR DATA
VARIABLE_2 = SEARCH YOUR DATA
vals.update({field1' : VARIABLE_1, 'field_2' : VARIABLE_2})
return super(sale_order_line, self).create(vals)
Update vals (record dictionary) by setting those readonly fields in to dictionary before calling super method or update those fields after calling super method.
There is an alternative solution for your problem. In Odoo Apps one module available from that system will store readonly value in the database.
Read Only ByPass
It is because readonly mode works only for display. In this case value from fields will not send to server-side.
You can override method create of sale.order.line. It should be something like this:
class sale_order_line(models.Model):
_inherit = 'sale.order.line'
#api.model
def create(self, vals):
# just example
vals[u'field1'] = 2.03
vals[u'field2'] = 3.05
return super(sale_order_line, self).create(vals)
Hope this helps you.
Hello to all I have been developing module under Odoo 8. I have a class "hrEmployee" with "_inherit=hr.employee" , now in my hrEmployee there is a One2many field having relation with another model "hr.employee.visa". I want to get the field values of the "hrEmployee" with onchange function defined on the field of "hr.employee.visa". Like when I change field value of "hrEmployee", I can get the field value entered on the current form (hrEmployee). How am I able to achieve this in Odoo v8? My Python code is shown below:
class hrEmployee(models.Model):
_inherit = "hr.employee"
diwan_no = fields.Char('Diwan No', size=30, help='Diwan Number')
zeo_number = fields.Char('ZEO Number',size=30, help='ZEO Number')
visas_ids = fields.One2many('hr.employee.visas', 'employee_id', 'Visas')
class hr_employee_visas(models.Model):
_name='hr.employee.visas'
employee_id = fields.Many2one("hr.employee.visas", "Employee" )
#api.onchange('visas_number')
#api.depends( 'visas_number')
def _visa_num(self):
cr=self._cr
uid=self._uid
ids=self._ids
for id in ids:
obj1=self.pool.get('hr.employee').browse(cr,uid,id,context=None)
print obj1.name_related
visas_sponsor = fields.Char('Sponsor')
visas_states = fields.Selection([('apply','Apply'),('active','Active'),('expire','Expire'),('cancel','Cancelled')], string='State' )
visas_number = fields.Char('Visa No', help='Visa Number')
I tried to use self.pool.get browse but it gives me "False" . Plz guide me or point me my mistake. Hopes for suggestion
Try following,
class hr_employee_visas(models.Model):
_name='hr.employee.visas'
employee_id = fields.Many2one("hr.employee", "Employee" )
#api.onchange('visas_number')
#api.depends( 'visas_number')
def _visa_num(self):
for obj in self:
print obj.employee_id.name
Here is the mistake
employee_id = fields.Many2one("hr.employee.visas", "Employee" )
You need to set hr.employee here.
No need to write both of the decorators together, in case of any changes into the visas_number field this method will be called, you can use any of the single decorator for this.