Create wizard#
Sometime you want to add functionalities to a model that do not suite the use of a button. For this kind of use case the wizard is the preferred solution. A wizard is a kind of state machine where states can be a form view, an action or transition.
Let’s create a wizard that converts the opportunities by asking for the end date.
First we define a ModelView
class in
opportunity.py
:
class ConvertStart(ModelView):
"Convert Opportunities"
__name__ = 'training.opportunity.convert.start'
end_date = fields.Date("End Date", required=True)
And we register it in the Pool
in __init__.py
:
def register():
Pool.register(
...,
opportunity.ConvertStart,
module='opportunity', type_='model')
Then the form view record in opportunity.xml
:
<tryton>
<data>
...
<record model="ir.ui.view" id="opportunity_convert_start_view_form">
<field name="model">training.opportunity.convert.start</field>
<field name="type">form</field>
<field name="name">opportunity_convert_start_form</field>
</record>
</data>
</tryton>
And the view in view/opportunity_convert_start_form.xml
:
<form col="2">
<label string="Convert Opportunities?" id="convert_opportunities" colspan="2" xalign="0"/>
<label name="end_date"/>
<field name="end_date"/>
</form>
Now we can define the Wizard
with a start
StateView
for the form and a convert
StateTransition
in opportunity.py
:
from trytond.wizard import Wizard, StateView, StateTransition, Button
...
class Opportunity(...):
...
@classmethod
@Workflow.transition('converted')
def convert(cls, opportunities, end_date=None):
pool = Pool()
Date = pool.get('ir.date')
cls.write(opportunities, {
'end_date': end_date or Date.today(),
})
...
class Convert(Wizard):
"Convert Opportunities"
__name__ = 'training.opportunity.convert'
start = StateView(
'training.opportunity.convert.start',
'opportunity.opportunity_convert_start_view_form', [
Button("Cancel", 'end', 'tryton-cancel'),
Button("Convert", 'convert', 'tryton-ok', default=True),
])
convert = StateTransition()
def transition_convert(self):
self.model.convert(self.records, self.start.end_date)
return 'end'
Note
We added an optional end_date
to the convert method.
And we register it in the Pool
as type wizard
in
__init__.py
:
def register():
...
Pool.register(
opportunity.Convert,
module='opportunity', type_='wizard')
Finally we just need to create a ir.action.wizard
and ir.action.keyword
in opportunity.xml
:
<tryton>
<data>
...
<record model="ir.action.wizard" id="act_convert_opportunities">
<field name="name">Convert Opportunities</field>
<field name="wiz_name">training.opportunity.convert</field>
<field name="model">training.opportunity</field>
</record>
<record model="ir.action.keyword" id="act_convert_opportunities_keyword">
<field name="keyword">form_action</field>
<field name="model">training.opportunity,-1</field>
<field name="action" ref="act_convert_opportunities"/>
</record>
</data>
</tryton>
The ir.action.wizard
links the Wizard
with the
Model
.
name
The string that is shown on the menu.
wiz_name
The name of the
Wizard
.model
The name of the
Model
.
And the ir.action.keyword
makes the Wizard
available as action to any training.opportunity
.
keyword
The type of keyword.
model
The model or record for which the action must be displayed. Use
-1
as id for any record.action
The link to the action.
Update database#
As we have defined new fields and XML records, we need to update the database with:
$ trytond-admin -d test --all
And restart the server and reconnect with the client to test the wizard:
$ trytond
Let’s create a a report to print opportunities.