I have three models
class ZohoTags(models.Model):
_name = 'zoho.tags'
name = fields.Char(string="Tags")
tag_id = fields.Char(string="Tag Id")
class TagsLine(models.Model):
_name = 'zoho.tags.line'
x_zoho_tags = fields.Many2one('zoho.tags', string='Tags')
x_tags_option = fields.Many2one('zoho.tag.option', string='Tags Option', domain="[('tag_ids', '=', x_zoho_tags.tag_id)]")
rules_id = fields.Many2one('hr.salary.rule')
class TagOptions(models.Model):
_name = 'zoho.tag.option'
name = fields.Char(string="tag option name")
option_tag_id = fields.Char(string="tag option id")
tag_ids = fields.Char(string="tag_id")
In the zoho.tags model, I have a field called tag_id and in the zoho.tag.option, I have tag_ids and both are having the same values.
In the zoho.tags.line model, I have a Many2one field called x_zoho_tags, which shows a list of tags like: division, state, etc. and x_tags_option, which shows options for each tag, such as:
Tag (division) has options (A,B,C) and these options are having the same tag_ids stored for (division) tag
I want to add a domain to x_tags_option in order to filter x_tag_option
to show only options that are having the same tag_id.
So when I select division from x_zoho_tags, then x_tags_option should show only A, B and C.
I have tried to add this line below, but it does not work
domain="[('tag_ids', '=', x_zoho_tags.tag_id)]
I have figure it out. This is how I have done it:
In python:
#api.onchange('x_zoho_tags')
def onchange_tags(self):
res = {}
if self.x_zoho_tags:
res['domain'] = {'x_tags_option': [('tag_ids', '=', self.x_zoho_tags.tag_id)]}
return res
In XML:
<field name="x_zoho_tags"/>
<field name="x_tags_option" onchange="onchange_tags(x_zoho_tags)"/>
Related
I have two models in my odoo project. Employee and equipment, as shown bellow.
Equipment/model.py
from openerp import models, fields, api
import datetime
class equipment(models.Model):
_name = 'equipment.equipment'
name = fields.Char(string='Name', )
date_of_purchase = fields.Date(string='Date Of Purchase', default=fields.Date.today(), )
write_off_days = fields.Integer(string="Days To Write-off", required=True, )
write_off_date = fields.Date(string="Write-off Date", compute="_get_write_off_date", )
price = fields.Float(string="Price '$'", required=True, )
description = fields.Char(string="Description", required=False, )
employee_id = fields.Char(string="Owner", compute="_get_owner", )
#api.one
#api.depends('employee_id')
def _get_owner(self):
//result = self.env.['res.equipment_table'].
//get id from relation database <-------------
#api.one
#api.depends('write_off_days', 'date_of_purchase')
def _get_write_off_date(self):
date = datetime.datetime.strptime(self.date_of_purchase, "%Y-%m-%d")
self.write_off_date = date + datetime.timedelta(days=self.write_off_days)
employee/model.py
from openerp import models, fields, api
class employee(models.Model):
_name = 'employee.employee'
name = fields.Char(string='First Name')
last_name = fields.Char(string='Last Name')
birth_date = fields.Date(string='Birth Date', default=fields.Date.today(), )
equipment_ids = fields.Many2many(string="Equipment", comodel_name="equipment.equipment", relation="equipment_table", )
total_equipment_price = fields.Float(string="Total Equipment Price '$'", compute="_get_total_equipment_price", )
#api.one
#api.depends('equipment_ids')
def _get_total_equipment_price(self):
total = 0
for equipment in self.equipment_ids:
total += equipment.price
self.total_equipment_price = total
I have many2many field, which holds all equipment that employee owns. I need to update the equipment owner every time the field is changed. The reason for this is.. when a user adds new equipment to the employee, there should be shown only unowned equipment. That is why I need to check and update the owner.
I already made a domain to check if equipment already has an owner, which will be shown below. Just need to update that employee_id field somehow.
<notebook>
<page string="Equipment">
<group>
<field name="equipment_ids" domain="[('employee_id', '=', False)]"/>
</group>
</page>
</notebook>
Change the type of employee_id to Many2one:
employee_id = fields.Many2one('employee.employee', string="Owner")
Override create and write methods to set employee_id each time new equipment is added to the list:
class Employee(models.Model):
_name = 'employee.employee'
#api.model
def create(self, values):
res = super(Employee, self).create(values)
if res.equipment_ids:
res.equipment_ids.write({'employee_id': res.id})
return res
#api.multi
def write(self, values):
res = super(Employee, self).write(values)
for r in self:
equipment_ids = r.equipment_ids.filtered(lambda s: not s.employee_id)
if equipment_ids:
equipment_ids.write({'employee_id': r.id})
return res
Because an equipment can set to one owner, I suggest you to change the type of equipment_ids to One2many to be able to set a list of equipments by employee and the employee_id field value will be set automatically for you when you add equipment to the list.
If you change the value of employee_id the equipment will be automatically visible in the list of equipments of the new employee.
equipment_ids = fields.One2many("equipment.equipment", 'employee_id', string="Equipments")
Reset owner
#api.multi
def write(self, values):
removed_ids = set()
old_ids = {r.id: r.equipment_ids.ids for r in self}
res = super(Employee, self).write(values)
for r in self:
equipment_ids = r.equipment_ids.filtered(lambda s: not s.employee_id)
if equipment_ids:
equipment_ids.write({'employee_id': r.id})
removed_ids |= set(old_ids[r.id]) - set(r.equipment_ids.ids)
self.equipment_ids.browse(removed_ids).write({'employee_id': False})
return res
I want to change the retrieved set of values of a many2many field according to a many2one field onchange function, it worked well with another many2one field, but doesn't seem to filter the outcome on a many2many field
my code is as follows
class CustomPurchase(models.Model):
_name = 'custom.purchase'
_description = 'Purchase Record'
supplier_id = fields.Many2one('custom.supplier', string='Supplier', required=True)
product_ids = fields.Many2many('custom.supply.line', string='Purchase Lines', required=True)
#api.onchange('supplier_id')
def onchange_supplier(self):
selected_lines = []
if self.supplier_id:
for rec in self:
selected_lines = rec.env['custom.supply.line'].search([('supplier_id', '=', rec.supplier_id.id)])
domain = {'product_ids': [('id', '=', selected_lines.id)]}
return {'domain': domain, 'value': {'selected_lines': []}}
Expected behavior is to have just the items related to the supplier_id many2one field
Produced behavior is all the items are retrieved
Edit:
I've noticed that i when i remove widget="section_and_note_one2many" the domain works perfectly, yet the tree view can't be edited within the same form, even with editable="bottom"
You can add check using supplier field directly inside domain.
Code:
#api.onchange('supplier_id')
def onchange_supplier(self):
domain = {'product_ids': []}
for rec in self:
if rec.supplier_id:
domain = {'product_ids': [('supplier_id', '=', rec.supplier_id.id)]}
return {'domain': domain}
UPDATE:
Try to implement this as same as in /addons/mrp/models/mrp_bom.py on attribute_value_ids. [Version:12]
I would like to retrieve all the values of the records of a model in a Many2one field. I don't know if it's possible with a compute.
My class of I want to recover the value:
class ResPartner_school(models.Model):
_name = 'ecole.partner.school'
_order = 'id desc'
school_name = fields.Many2one(comodel_name="ecole.establishment.webservice",
string="Etablissement Scolaire",
default=1)
school_level = fields.Many2one(comodel_name="ecole.establishment.webservice",
string="Niveau Scolaire",
compute="_get_level")
My other class:
class SchoolEstablishmentWebServices(models.Model):
_name = 'ecole.establishment.webservice'
_rec_name = "establishment_name"
establishment_name = fields.Many2one(comodel_name="horanet.school.establishment", string="Etablissement Scolaire")
id_establishment = fields.Char(string='idEtablissement')
grade_name = fields.Many2one(comodel_name="horanet.school.grade", string="Niveau Scolaire")
id_class = fields.Char(string='idClasse')
My function in my class ResPartner_school:
#api.multi
def _get_level(self):
school_level = self.school_name.grade_name
return school_level
How to retrieve all values from the grade_name field of the class SchoolEstablishmentWebServices?
One solution to show "all" data (depends on how much of data there is) is overriding the name_get() of a model with two variants.
Variant context-based name_get()
First override the name_get() of model ecole.establishment.webservice
class SchoolEstablishmentWebServices(models.Model):
_name = 'ecole.establishment.webservice'
#api.multi
def name_get(self):
res = []
for webservice in self:
if 'full_name' in self.env.context:
res.append((webservice.id, webservice.get_full_name()))
else:
res.append((webservice.id, webservice.establishment_name))
return res
def get_full_name(self):
# example logic
self.ensure_one()
full_format = "{establishment}, {grade}"
return full_format.format(
establishment=self.establishment_name, grade=self.grade_name)
Then you need to put the value full_name into the context. You could add it to the field itself, which won't work that good. Better you put that value into the context of the action of the menu, which is used to show your 'ecole.partner.school' entries.
<record id="my.list.action.for.school" model="ir.actions.act_window">
<field name="name">my.action</field>
<!-- and so on -->
<field name="context">{'full_name': 1}</field>
</record>
Variant non context-based -> it's the same as variant 1 without using the context at all. It will be system-wide at not only where you want it to be. It's the easier variant.
I will want to retrieve different values from a chosen field. Let me explain:
I have this class:
class SchoolWebServices(models.Model):
_name = 'ecole.webservices'
name = fields.Char(string='Nom')
code_produit = fields.Char(string='Produit')
code_CDG = fields.Char(string='Centre de Gestion')
code_Catalog = fields.Char(string='Catalogue Produits')
I have this other class:
class ResPartner_school(models.Model):
_name = 'ecole.partner.school'
_order = 'id desc'
half_pension_name = fields.Many2one(comodel_name="ecole.webservices",
string="Lieu")
And I have a function who is in the class: ecole.partner.school
#api.multi
def create_compte_cantine(self):
print "Inscription réussie"
get_halfpension_name = self.half_pension_name.id
if get_halfpension_name:
code_Catalog = self.env['ecole.webservices'].code_Catalog
I get the id of half_pension_name in my variable get_halfpension_name but I wish to recover the code_Catalog of the same recording too. How to do?
You just need to use dot-notation to retrieve the value:
#api.multi
def create_compte_cantine(self):
self.ensure_one()
if self.half_pension_name:
code_Catalog = self.half_pension_name.code_Catalog
Try to stay in the "rules" of the Odoo guideline. For example a Many2one relation field should be end with _id -> half_pension_id = fields.Many2one(comodel_name="ecole.webservices", string="Lieu")
I tried to use api.constrain in odoo. The case is, I want to give condition to odoo if user missing one field, odoo will give some warning like alert, and user have to give some input to the previous field. This is my code :
class Provinc(models.Model):
_name = 'provinsi.model'
_rec_name ='prov'
prov = fields.Char(
string='Provinsi',
)
res_partner_ids = fields.One2many(
'res.partner',
'provinsi'
city_id = fields.One2many(
'city.model',
'provinsi_id'
)
class city(models.Model):
_name = 'kota.model'
_rec_name ='city'
city = fields.Char(
string='City',
)
res_partner_city = fields.One2many(
'res.partner',
'city'
)
provinsi_id = fields.Many2one(
'provinsi.model',
string='provinsi',
)
class Master_data(models.Model):
_inherit = 'res.partner'
provinsi = fields.Many2one(
'provinsi.model',
'provinsi',
)
city = fields.Many2one(
'city.model',
'city',
)
#api.onchange('provinsi')
def show_provinsi(self):
return {'domain': {'city': [('provinsi_id', '=', self.provinsi.id)]}}
#api.constrains('provinsi')
#api.onchange('city')
def show_kota(self):
for record in self:
if record.provinsi == False:
raise ValidationError("is gonna be error")
I have tried 2 ways. First, I put the api.constrain insode class City, and it's doesn't work,second ways I tried put the api.constrain like the code inside class master, and the result remains the same.
you only need onchang not any constrains to display warning!
#api.onchange('city')
def show_kota(self):
if self.city and not self.provinsi:
raise ValidationError("is gonna be error")
now if you select value in city field and provinsi missing value then it will display error msg
guessing field "city" and "provinsi" is in 'res.partner' form view!
If you want to check a field value is empty or not, just use required ="1" like:
<field name="provinsi" required="1"/>