Odoo 11 - pull fields values from other models - odoo

I have added a custom field (many2one) in crm.lead form and a custom class for that
Here is my code (I am using odoo 11):
models.py
from odoo import models, fields, api
# Add fields to Leads
class Leads_events(models.Model):
_inherit = 'crm.lead'
venue = fields.Many2one('crm.lead.venue',String="Venue")
venue_city = fields.Char(String="City")
venue_country = fields.Many2one('res.country', string="Country")
# Create venue class
class Leads_venue(models.Model):
_name = 'crm.lead.venue'
name = fields.Char(string="Venue name")
city = fields.Char(string="City")
country = fields.Many2one('res.country', string="Country")
address = fields.Text(string="Address")
website = fields.Char(string="Website")
phone = fields.Char(string="Phone")
fax = fields.Char(string="Fax")
notes = fields.Text(string="Notes")
views.xml
<record id="crm_lead_venue_form" model="ir.ui.view">
<field name="name">crm.lead.venue.form</field>
<field name="model">crm.lead.venue</field>
<field name="arch" type="xml">
<form string="Venues">
<group>
<group>
<field name="name"/>
<field name="country"/>
<field name="city"/>
<field name="address"/>
</group>
<group>
<field name="phone"/>
<field name="fax"/>
<field name="website"/>
</group>
<group>
<field name="notes" />
</group>
</group>
</form>
</field>
</record>
<record id="crm.crm_case_form_view_oppor_events" model="ir.ui.view">
<field name="name">crm_case_form_view_oppor_events</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_form_view_oppor"/>
<field name="arch" type="xml">
<xpath expr="//notebook" position="before">
<group string="Venue">
<field name="venue"/>
<field name="event_city" string="City"/>
<field name="event_country"/>
</group>
</xpath>
</field>
</record>
This works fine. Now what I am trying to pull is the city and country from crm.lead.venue selected record to crm.lead 'venue_city' and 'venue_country' fields.
I looked at onchange function but I cannot find how to make it work...
I've tried this following another post I read but it is not working
#api.onchange('venue')
def onchange_venue(self):
if self.venue:
self.event_city = self.venue.city
self.event_country = self.venue.country
Is there anywhere I can find a documentation or help more complete on this ? The official documentation is not very precise on this matter.

The onchange method works when the user change the field in the view, and I cant see the field on your view, so the method would be never be called. You should add "venue" field to the form and test it again.
Edit
Have you seen that it is not event_city but venue_city? The onchange should be on leads_events. Did you test that onchange is executed and has no value? Or it doesnt even execute the function ?
#api.onchange('venue')
def onchange_venue(self):
if self.venue:
self.venue_city = self.venue.city
self.venue_country = self.venue.country

Related

Odoo - How add a field to view from another wizard model?

I want the use a field from wizard to my form view.
Let me explain with code:
class CancelAppointmentWizard(models.Model):
_name = "cancel.appointment.wizard"
_description = "Cancel Appointment Wizard"
reason = fields.Text(string="Reason")
and i want the show this "reason" field inside of some form views.
<record id="view_hospital_appointment_form" model="ir.ui.view">
<field name="name">hospital.appointment.form</field>
<field name="model">hospital.appointment</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="reason"/>
</group>
</sheet>
</form>
</field>
</record>
but of course this give me error like
hospital.appointment don't have a field like reason.
How can show this field ?
I tried to make a dummy code, i hope i was able to explain my problem.
I assume the wizard is called from the view_hospital_appointment_form. And in the wizard view let say there is a button tag with name attribute, which is this attribute associated to python method in your wizard class.
Wizard view
<record id="view_cancel_appointment_wizard_form" model="ir.ui.view">
<field name="name">cancel.appointment.wizard.form</field>
<field name="model">cancel.appointment.wizard</field>
<field name="arch" type="xml">
<form>
…
…
<footer>
<button name="action_ok" string="Ok" type="object"/>
</footer>
</form>
</field>
</record>
Python method
def action_ok(self):
ids = self.env.context.get('active_ids')
hospital_appointment = self.env['hospital.appointment'].browse(ids)
hospital_appointment.reason = self.reason
return {'type': 'ir.actions.act_window_close'}

Odoo Inheriting fields and functionality

I am have made two different classes(model.Models). I have 10 fields in one class and I need to inherit only two fields in other class from the former one. Like I update two fields in one class , It automatically must be updated in next class. So please help me out. How should I need to inherit these two fields and their functionality?
This is the Odoo Framework.
You can use related fields to get values from another model. You can do this by defining a Many2one to the model and access field in that model using related fields.
example:
class ModelA(models.Model):
_name = 'model.a'
field1 = fields.Char()
.....
field10 = fields.Char()
class ModelB(models.Model):
_name = 'model.b'
model_a_id = fields.Many2one('model.a', string='Related Model')
field1 = fields.Char(related='model_a_id.field1', string='field1')
field2 = fields.Char(related='model_a_id.field2', string='field2')
You can access any field in model.a from model.b using related fields. If you change values of field1 or field2 from any of these models, the change will be reflected in both models. So if you don't want the user to change values of these model from model.b, you can make them readonly in that model.
<record id="ping_tree_view_id" model="ir.ui.view">
<field name="name">Ping tree view</field>
<field name="model">ping.ping</field>
<field name="arch" type="xml">
<tree string="Ping">
<field name="model_a_id"/>
<field name="Last_update"/>
<field name="Last_attempt"/>
</tree>
</field>
</record>
<record id="ping_form_view_id" model="ir.ui.view">
<field name="name">Ping form view</field>
<field name="model">ping.ping</field>
<field name="arch" type="xml">
<form string="Ping">
<sheet>
<group>
<field name="model_a_id"/>
<field name="Last_update"/>
<field name="Last_attempt"/>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="ping_actions_win">
<field name="name">Ping</field>
<field name="res_model">ping.ping</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>

Default filter with partial number

In tree view i have field "code" and i want to filter only records when code starts with 910 and it should be default filter.
I trying to play with context but not much. i can filter by code but how can i add this 910 in there.
<field name="context">{"search_default_code":1}</field>
Update.
<record id="project_proposal_view_search" model="ir.ui.view">
<field name="name">project.part.search</field>
<field name="model">project.proposal</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="project_id"/>
<field name="code"/>
<filter name="code" string="Starts with 910" domain="[('code','ilike', '910')]"/>
</search>
</field>
</record>
class ProjectProposal(models.Model):
_name = 'project.proposal'
_inherit = ['mail.thread']
code = fields.Char(compute='_compute_code')
#api.multi
#api.onchange('project_id', 'object', 'stage_id', 'part_template_id')
def _compute_code(self):
for r in self:
code = []
if r.project_id:
code.append(r.project_id.code or '')
if r.object:
code.append(r.object or '')
if r.stage_id:
code.append(r.stage_id.code or '')
if r.part_template_id:
code.append(r.part_template_id.code or '')
r.code = '-'.join(code)
you have to inform us about the code field type. it seems to be of type char.also it seems you are using an action with context.
so you have to define filter code which you are trying to use {"search_default_code":1}
<filter name="code" string="starts with 910" domain="[('code','ilike', '910')]" />
so you will end up defining something like that
<!-- FILTERS FOR YOUR MODEL -->
<record id="filter_model_name" model="ir.ui.view">
<field name="name">FILTER NAME</field>
<field name="model">MODEL.NAME</field>
<field name="arch" type="xml">
<search string="MODEL NAME">
<filter name="code" string="starts with 910" domain="[('code','ilike', '910')]" />
</search>
</field>
</record>
<!-- FILTERS FOR YOUR MODEL -->
please make sure your field definition to be like
code = fields.Char(compute='_compute_code', store=True)

Pass data to many2one widget

I have a custom module with the following simple data structure:
class Site(models.Model):
_name = 'sites.site'
site_name = fields.Char(string="Site Name")
contact_in_site_role_ids = fields.One2many(comodel_name="sites.contact_in_site_role", inverse_name="site_id", string="Site Contacts", required=False, )
class SiteRole(models.Model):
_name = "sites.site_role"
role_name = fields.Char(string="Role Name")
class ContactInSiteRole(models.Model):
_name = "sites.contact_in_site_role"
site_id = fields.Many2one("sites.site",string="Site")
contact_id = fields.Many2one("res.partner",string="Contact")
role_id = fields.Many2one("sites.site_role",string="Site Role")
role_detail = fields.Char(string="Role details")
This is currently managed by the following form:
<record model="ir.ui.view" id="site_form_view">
<field name="name">site.form</field>
<field name="model">sites.site</field>
<field name="arch" type="xml">
<form string="Site Form">
<sheet>
<group>
<field name="site_name"/>
</group>
<notebook>
<page string="Site Contacts">
<field name="contact_in_site_role_ids" widget="one2many_list">
<tree>
<field name="contact_id"/>
<field name="role_id"/>
<field name="role_detail"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
This works well, apart from when clicking to add a contact on the Many2One widget on the "Edit Site Form", it prompts again for the site. How do I remove the "Site" option from this popup form, and have the relevant site passed from the parent form:
Try to pass like below and see
<field name="contact_in_site_role_ids" widget="one2many_list" context="{'default_site_id':parent.id}"/>
The concept here is we can initialize the child element values by passing them in the context like:
{default_child_field: value}

ODOO 8 on_change

Please I am facing somes problems with the new odoo 8 api, I have the following classes
class TypeProcessus(models.Model):
_name = 'atom.promaintenance.type.processus'
name = fields.Char()
id_phases = fields.One2many('atom.promaintenance.phases','id_processus','Liste des Phases')
class Phases(models.Model):
_name = 'atom.promaintenance.phases'
name = fields.Char()
autoriserCommentaire = fields.Boolean()
autoriserPiecesJointes = fields.Boolean()
id_processus = fields.Many2one('atom.promaintenance.type.processus')
parent_id = fields.Many2one('atom.promaintenance.phases','Phase Parent', select=True, ondelete='cascade')
commentaire = fields.Text()
#api.one
#api.onchange('name')
def phases_write(self):
print 'test'
<record model="ir.ui.view" id="atom_promaintenance_type_processus">
<field name="name">atom.promaintenance.type.processus.form</field>
<field name="model">atom.promaintenance.type.processus</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Type Processus" >
<sheet>
<h1>UPDATED</h1>
<field name="name" />
<tree string="note_evaluation_tree" editable="bottom">
<field name="id_phases" />
</tree>
</sheet>
</form>
</field>
</record>
First of all my problem is when Creating a new Processus, and adding phases, there is a relation parent child between phases and the drop down list for parent stay empty unless u save the processus to make them available.
i managed to add onChange event to the phases to persist them to database but i can't figure out how to save those records with the new api system, thank you
If you mean what I understand, you need to use the widget one2many_list in the XML code, which by the way, I think is wrong. It should be something like this:
<record model="ir.ui.view" id="atom_promaintenance_type_processus">
<field name="name">atom.promaintenance.type.processus.form</field>
<field name="model">atom.promaintenance.type.processus</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Type Processus" >
<sheet>
<h1>UPDATED</h1>
<field name="name" />
<field name="id_phases" widget="one2many_list">
<tree string="note_evaluation_tree" editable="bottom">
<field name="name"/>
<field name="autoriserCommentaire"/>
<field name="autoriserPiecesJointes"/>
<field name="parent_id"/>
<field name="commentaire"/>
</tree>
</field>
</sheet>
</form>
</field>
</record>
The widget will allow you to add phases for a processus and then save it.
The new API uses self for all the record modifications. So in your case, if you want to change the name, write like this:
#api.one
#api.onchange('name')
def onchange_name(self):
self.name = 'what you want to save'