# 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 <topics-actions>.

`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.