Odoo v9.
I would like to prompt the user with a yes/no option before certain python code is executed.
If this were in a button I could use the confirm="text?" attribute, however I do not want to trigger any database updates irrespective of the users answer to this particular prompt.
e.g. onchange event triggers yes/no box, which can then manipulate page, however the user still has to press "save" to keep any changes.
Is there any way of doing this using base odoo?
onchange events can't return a dialog because they were simply not built to do that https://www.odoo.com/forum/how-to/developers-13/what-should-onchange-methods-do-and-return-57760
You can use a wizard (it's not really a wizard it's just a form) and show it as a popup. our wizard model will be a Transient model, which would be discarded by odoo after a specified amount of time.
from openerp import fields, models, api
class test_model(models.Model):
_name = 'test.model'
name = fields.Char(string='Value')
#api.multi
def call_up_wizard(self):
return {
'name': 'Are you sure?',
'type': 'ir.actions.act_window',
'res_model': 'wizard',
'view_mode': 'form',
'view_type': 'form',
'target': 'new',
}
class wizard(models.TransientModel):
_name = 'wizard'
yes_no = fields.Char(default='Do you want to proceed?')
#api.multi
def yes(self):
pass
# sure continue!
#api.multi
def no(self):
pass # don't do anything stupid
This is how your view would look like
<record id="cashadvance_list" model="ir.ui.view">
<field name="name">Test Dialog</field>
<field name="model">test.model</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Test Dialog" version="8.0">
<group>
<button class="oe_highlight" name="call_up_wizard" string="confirm" type="object" />
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="wizard_form">
<field name="name">wizard.form</field>
<field name="model">wizard</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Confirm dialog">
<field name="yes_no" readonly="1" />
<footer>
<button class="oe_highlight" name="yes" string="Yes" />
<button class="oe_highlight" name="no" string="No" />
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="action_test">
<field name="name">Cash advance list</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">test.model</field>
<field name="view_type">form</field>
<field name="view_mode">form,tree</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
It's empty, create something
</p>
</field>
</record>
In our test_model view we have a button that's shows the wizard as a popup, and then in the wizard buttons are handled by the yes and no methods respectively, this gives you better control over the buttons as you know have separate methods controlling the two buttons you have on the form.
I just put this answer, for anyone who happens to stumble on this thread and wants to know how to create a popup from a button.
Related
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'}
so I Have several fields in my Wizard model that the default value is the same from the form but we can change it. I try to send my form field value using context but it has an error like this
odoo.tools.convert.ParseError: ": "name
'arrival_date' is not defined"
while evaluating. The name of the field already right because when I use context in my line or one2many field It works just fine.
And Second when I create the record its not referencing my form record. Do I need to change the default write method?
<record model="ir.ui.view" id="kre_product_reservation_wizard_form_view">
<field name="name">kre.product_reservation.form</field>
<field name="model">kre.product_reservation</field>
<field name="arch" type="xml">
<form string="Add Attendees">
<group>
<group>
<!-- Add your fields here -->
<field name="reservation_number"/>
<field name="arrivals_date"/>
<field name="departure_date"/>
<field name="stay_period"/>
<field name="qty"/>
<field name="price"/>
<field name="tax"/>
<field name="sub_amount"/>
<field name="tax_amount"/>
<field name="amount"/>
<field name="description"/>
</group>
<notebook>
<page string="Guest List">
<field name="guests"/>
</page>
</notebook>
</group>
</form>
</field>
</record>
<act_window id="insert_reservation_wizard" name="Insert Reservation" context="{'reservation_id' : active_id, 'arrival_date' : arrival_date, 'departure_date' : departure_date}" binding_model="kre.reservation" res_model="kre.product_reservation" view_mode="form" target="new"/>
And this is the binding model Field that I want to send in Context.
<field name="name"/>
<field name="billing_name"/>
<field name="arrival_date"/>
<field name="departure_date"/>
<field name="group"/>
<field name="currency"/>
<field name="sub_total"/>
<field name="tax"/>
<field name="total"/>
Hello Theodorus Agum Gumilang,
On your act_window you can set the model id or any selection or boolean from the default context passing. Like this,
<act_window id="insert_reservation_wizard"
name="Insert Reservation"
binding_model="kre.reservation"
res_model="kre.product_reservation"
view_mode="form"
context="{'default_reservation_id' : active_id, 'reservation_id' : active_id}"
target="new"/>
You can check the other reference on odoo for default value set from act_window. As on your default value set from the form itself on wizard view, you can do with by changing the approach this way,
1) Calling your wizard action from the python.
2) On the python, you can pass the default value on context.
On you form view added the button,
<button name="action_wizard" string="Your String" type="object" class="btn-primary" />
On Python Function,
def action_wizard(self):
return {
'name': _("Your String"),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'Object',
'view_id': self.env.ref('module.ref_id').id,
'target': 'new',
'context': {
'default_name': self.default_name,
'default_billing_name': self.default_billing_name,
'default_arrival_date': self.default_arrival_date,
'default_departure_date': self.default_departure_date,
'default_group': self.default_group,
'default_currency': self.default_currency,
'default_sub_total': self.default_sub_total,
'default_tax': self.default_tax,
'default_total': self.default_total
}}
Thanks
In order to show this form view :
<record model="ir.ui.view" id="program_viewform">
<field name="name">My Program</field>
<field name="model">res.partner</field>
<field name="arch" type="xml">
<form>
<separator string="My Program " />
<field name="projects_ids" nolabel="True"/>
<separator string="submitted Tasks" />
<field name="submission_task_ids" nolabel="True"/>
</form>
</field>
</record>
I created this action :
<record model="ir.actions.act_window" id="myprogram_action">
<field name="name">My Program</field>
<field name="res_model">res.partner</field>
<field name="form_view_id" ref="training_program_management.program_viewform"/>
<field name="domain">[('id','=',user.id.partner_id)]</field>
<field name="view_mode">form</field>
</record>
and this Menu :
<menuitem name="My Program" id="program_menu" sequence="5"
parent="training_program_management.menu" action="training_program_management.myprogram_action"/>
What I need is to show the record of res_partner corresponding to the current User, knowing that res.users contains a Many2one Field "Partner_id".
What do I need to do?
This is tested for odoo 8 but it can probably be adapted for odoo 10 or at least help you :
Change <record model="ir.actions.act_window" id="myprogram_action"> to <record model="ir.actions.server" id="myprogram_action">
Then add (yes, old API is on purpose, it doesn't work with the new API, for odoo 8 that is)
<field name='model_id' ref='base.model_res_partner'/>
<field name="code">
action = self._action_open_user_res_partner(cr, uid)
</field>
Create a model extending res.partner in your module, add (more old API ... also I didn't find a way to use ref())
#api.model
def _action_open_user_res_partner(self, cr, uid):
return {
'view_type': 'form',
'view_mode': 'form',
# Since this is a constant, you can use a global to hold the value for 'view_id'
'view_id': int(self.pool['ir.ui.view'].search(cr, uid,
[('name', '=', 'My Program')])[0]),
'res_model': 'res.partner',
'res_id': int(self.pool['res.users'].browse(cr, uid, [uid])[0].partner_id),
'type': 'ir.actions.act_window',
'context': {}
}
Adapting this to odoo 10 probably involves using the new API instead of the old one. This means self.pool should be self.env or env, and that you don't need cr and uid anymore. You can use user variable instead of uid in the function returning (well actually it could be used for odoo 8 too, but since uid is needed anyway...).
On the other hand, the documentation for odoo 10 about actions strongly suggests you'd still need to use the old API for this, except for model replacing self.
So you should first try something like this for odoo 10 :
<field name='model_id' ref='base.model_res_partner'/>
<field name="code">
action = model._action_open_user_res_partner(cr, uid)
</field>
The function in the model is still the same, since we still use the old API.
If it doesn't work, you should try with the new API (get rid of cr, uid)
The code bellow, worked perfectly for me, Thank you alot for your help:
<record model="ir.actions.server" id="myprogram_action">
<field name="name">My Program</field>
<field name='model_id' ref='base.model_res_partner'/>
<field name="state">code</field>
<field name="code">
action = {
'type': 'ir.actions.act_window',
'name': 'My Program',
'view_mode': 'form',
'view_type': 'form',
'res_model': 'res.partner',
'nodestroy': 'true',
'res_id': int(env['res.users'].browse(env.user.partner_id.id)),
'views': [(False, 'form')],
'view_id': 'ref="training_program_management.program_viewform"',
}
</field>
</record>
Still have a small problem thou, i have two FormViews for res.partner, this line doesn't seem to show the desired View:
'view_id': 'ref="training_program_management.program_viewform"',
It shows me The First FormView That i've inherited.
My training_program_management.program_viewform :
<record model="ir.ui.view" id="program_viewform">
<field name="name">My Program</field>
<field name="model">res.partner</field>
<field name="arch" type="xml">
<form>
<separator string="My Program " />
<field name="projects_ids" nolabel="True"/>
<separator string="submitted Tasks" />
<field name="submission_task_ids" nolabel="True"/>
</form>
</field>
</record>
What can i do to show this View Instead Of the inherited one ?
I am trying to inherit the Website settings menu and have two views. website.config.settings is a models.TransientModel
When I am inheriting that and viewing with a new menuitem it overwrites the previous view. Like - There are two views now, the new record I defined named Website Event Settings . When I click on that it loads the new modified view but when I click on existing Settings menu, it shows nothing.
In summary, the existing website settings menu not working and new menu does. I need both of them.
The py code and record view I used are following -
class cofair_website_design_config(models.TransientModel):
_name = 'website.config.settings'
_inherit = 'website.config.settings'
event_title = fields.Char(related='website_id.event_title', string='Event Title')
XML:
<record id="view_website_event_config_settings" model="ir.ui.view">
<field name="name">Website Event Settings</field>
<field name="model">website.config.settings</field>
<field name="arch" type="xml">
<form class="oe_form_configuration">
<header>
<button string="Apply" type="object" name="execute" class="oe_highlight"/>
<button string="Cancel" type="object" name="cancel" class="oe_link"/>
</header>
<div>
<group string="Event Page Section">
<group>
<field name="event_title_color"/>
</group>
</group>
</div>
</form>
</field>
</record>
<record id="action_website_event_configuration" model="ir.actions.act_window">
<field name="name">Website Event Settings</field>
<field name="res_model">website.config.settings</field>
<field name="view_mode">form</field>
<field name="target">inline</field>
<field name="view_id" ref="view_website_event_config_settings"/>
</record>
<menuitem id="menu_website_event_settings" parent="website.menu_website_configuration" name="Website Event Settings" action="action_website_event_configuration"/>
Instead of renaming the modules (which causes relational error), I found a workaround. I have inherited the main settings and put a view id there and called it with menuitem -
<!-- Bring settings menu out -->
<record id="website.action_website_configuration" model="ir.actions.act_window">
<field name="name">Website Settings</field>
<field name="res_model">website.config.settings</field>
<field name="view_mode">form</field>
<field name="target">inline</field>
<field name="view_id" ref="website.view_website_config_settings"/>
</record>
<menuitem id="website.menu_website_website_settings" parent="website.menu_website_configuration" name="Website Admin" action="website.action_website_configuration"/>
Then I called my record action and it loaded the view and action. Another catch point is I had to show website_id to show the values of specific websites or the transient model will always be empty.
Change the _name attribute in your model definition to something else and also modify the xml appropraitely.
class cofair_website_design_config(models.TransientModel):
_name = 'something.else'
_inherit = 'website.config.settings'
event_title = fields.Char(related='website_id.event_title', string='Event Title')
ir.ui.view
<field name="model">something.else</field>
and ir.actions.act_window
<field name="res_model">something.else</field>
That should copy all the fields and methods from website.config.settings to the new model something.else and keep it separate from website.config.settings
I have created a button named 'Confirm' in customer invoice. When i click 'Confirm' button 'state1' will be 'confirmed'. I want to hide Validate button when 'state1'='draft' and show the Validate button when 'state1'='confirmed'. I tried below code but it is not working. Can anyone help me?
<!-- inherit account invoice form -->
<record id="invoice_form_inheritai" model="ir.ui.view">
<field name="name">account.invoice.form.inheritai</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<button name="invoice_print" position="after">
<field name="state1" invisible="1"/>
<button name="invoice_check" string="Confirm" type="object" attrs="{'invisible': [('state1','not in', ['draft'])]}" class="oe_highlight" groups="base.group_user"/>
</button>
<button name="invoice_open" position="replace">
<button name="invoice_open" state="draft" string="Validate" attrs="{'invisible': [('state1','!=', ['confirmed'])]}" groups="base.group_user"/>
</button>
</field>
</record>
<button name="invoice_open" string="Validate" attrs="{'invisible': [('state1','not in', ['confirmed']),('state','not in',['draft'])]}" groups="base.group_user"/>
Please avoid using both invisible attribute and states.
Try using 'states' instead of 'state'. And even attr won't be required. It will work automatically. Ex:
<button name="invoice_open" states="confirmed" string="Validate" groups="base.group_user"/>