~xrg/openobject-doc/trunk-xrg

« back to all changes in this revision

Viewing changes to i18n/vi/source/developer/3_10_wizard/index.rst

  • Committer: TruongSinh Tran
  • Date: 2009-07-17 18:59:45 UTC
  • Revision ID: truongsinh@vipescoserver-20090717185945-ajjp3zso6xh5jddm
[FIX]private issue

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
.. i18n: ===============================
 
3
.. i18n: Creating Wizard - (The Process)
 
4
.. i18n: ===============================
 
5
 
 
6
===============================
 
7
Creating Wizard - (The Process)
 
8
===============================
 
9
 
 
10
.. i18n: Introduction
 
11
.. i18n: ============
 
12
.. i18n: Wizards describe interaction sequences between the client and the server.
 
13
 
 
14
Introduction
 
15
============
 
16
Wizards describe interaction sequences between the client and the server.
 
17
 
 
18
.. i18n: Here is, as an example, a typical process for a wizard:
 
19
 
 
20
Here is, as an example, a typical process for a wizard:
 
21
 
 
22
.. i18n:    1. A window is sent to the client (a form to be completed)
 
23
.. i18n:    2. The client sends back the data from the fields which were filled in
 
24
.. i18n:    3. The server gets the result, usually execute a function and possibly sends another window/form to the client 
 
25
 
 
26
   1. A window is sent to the client (a form to be completed)
 
27
   2. The client sends back the data from the fields which were filled in
 
28
   3. The server gets the result, usually execute a function and possibly sends another window/form to the client 
 
29
 
 
30
.. i18n: .. image:: images/Wizard.png
 
31
 
 
32
.. image:: images/Wizard.png
 
33
 
 
34
.. i18n: Here is a screenshot of the wizard used to reconcile transactions (when you click on the gear icon in an account chart):
 
35
 
 
36
Here is a screenshot of the wizard used to reconcile transactions (when you click on the gear icon in an account chart):
 
37
 
 
38
.. i18n: .. image:: images/Wizard_screenshot.png 
 
39
 
 
40
.. image:: images/Wizard_screenshot.png 
 
41
 
 
42
.. i18n: Wizards - Principles
 
43
.. i18n: ====================
 
44
.. i18n: A wizard is a succession of steps. A step is composed of several actions;
 
45
 
 
46
Wizards - Principles
 
47
====================
 
48
A wizard is a succession of steps. A step is composed of several actions;
 
49
 
 
50
.. i18n: #. send a form to the client and some buttons
 
51
.. i18n: #. get the form result and the button pressed from the client
 
52
.. i18n: #. execute some actions
 
53
.. i18n: #. send a new action to the client (form, print, ...) 
 
54
 
 
55
#. send a form to the client and some buttons
 
56
#. get the form result and the button pressed from the client
 
57
#. execute some actions
 
58
#. send a new action to the client (form, print, ...) 
 
59
 
 
60
.. i18n: To define a wizard, you have to create a class inheriting from **wizard.interface** and instantiate it. Each wizard must have a unique name, which can be chosen arbitrarily except for the fact it has to start with the module name (for example: account.move.line.reconcile). The wizard must define a dictionary named **states** which defines all its steps.
 
61
 
 
62
To define a wizard, you have to create a class inheriting from **wizard.interface** and instantiate it. Each wizard must have a unique name, which can be chosen arbitrarily except for the fact it has to start with the module name (for example: account.move.line.reconcile). The wizard must define a dictionary named **states** which defines all its steps.
 
63
 
 
64
.. i18n: Here is an example of such a class:
 
65
 
 
66
Here is an example of such a class:
 
67
 
 
68
.. i18n: .. code-block:: python
 
69
.. i18n: 
 
70
.. i18n:        class wiz_reconcile(wizard.interface):
 
71
.. i18n:              states = {
 
72
.. i18n:                   'init': {
 
73
.. i18n:                        'actions': [_trans_rec_get],
 
74
.. i18n:                        'result': {'type': 'form', 
 
75
.. i18n:                                   'arch': _transaction_form, 
 
76
.. i18n:                                   'fields': _transaction_fields,  
 
77
.. i18n:                                   'state':[('reconcile','Reconcile'),('end','Cancel')]}
 
78
.. i18n:                  },
 
79
.. i18n:                   'reconcile': {
 
80
.. i18n:                        'actions': [_trans_rec_reconcile],
 
81
.. i18n:                        'result': {'type': 'state', 'state':'end'}
 
82
.. i18n:                  }
 
83
.. i18n:             }
 
84
.. i18n:        wiz_reconcile('account.move.line.reconcile');
 
85
 
 
86
.. code-block:: python
 
87
 
 
88
        class wiz_reconcile(wizard.interface):
 
89
              states = {
 
90
                   'init': {
 
91
                        'actions': [_trans_rec_get],
 
92
                        'result': {'type': 'form', 
 
93
                                   'arch': _transaction_form, 
 
94
                                   'fields': _transaction_fields,  
 
95
                                   'state':[('reconcile','Reconcile'),('end','Cancel')]}
 
96
                  },
 
97
                   'reconcile': {
 
98
                        'actions': [_trans_rec_reconcile],
 
99
                        'result': {'type': 'state', 'state':'end'}
 
100
                  }
 
101
             }
 
102
        wiz_reconcile('account.move.line.reconcile');
 
103
 
 
104
.. i18n: The 'states' dictionary define all the states of the wizard. In this example; **init** and **reconcile**. There is another state which is named end which is implicit.
 
105
 
 
106
The 'states' dictionary define all the states of the wizard. In this example; **init** and **reconcile**. There is another state which is named end which is implicit.
 
107
 
 
108
.. i18n: A wizard always starts in the **init** state and ends in the **end** state.
 
109
 
 
110
A wizard always starts in the **init** state and ends in the **end** state.
 
111
 
 
112
.. i18n: A state define two things:
 
113
 
 
114
A state define two things:
 
115
 
 
116
.. i18n:        #. a list of actions
 
117
.. i18n:        #. a result 
 
118
 
 
119
        #. a list of actions
 
120
        #. a result 
 
121
 
 
122
.. i18n: The list of actions
 
123
.. i18n: -------------------
 
124
.. i18n: Each step/state of a wizard defines a list of actions which are executed when the wizard enters the state. This list can be empty.
 
125
 
 
126
The list of actions
 
127
-------------------
 
128
Each step/state of a wizard defines a list of actions which are executed when the wizard enters the state. This list can be empty.
 
129
 
 
130
.. i18n: The function (actions) must have the following signatures:
 
131
 
 
132
The function (actions) must have the following signatures:
 
133
 
 
134
.. i18n: .. code-block:: python
 
135
.. i18n: 
 
136
.. i18n:        def _trans_rec_get(self, uid, data, res_get=False):
 
137
 
 
138
.. code-block:: python
 
139
 
 
140
        def _trans_rec_get(self, uid, data, res_get=False):
 
141
 
 
142
.. i18n: Where:
 
143
 
 
144
Where:
 
145
 
 
146
.. i18n:     * **self** is the pointer to the wizard object
 
147
.. i18n:     * **uid** is the user ID of the user which is executing the wizard
 
148
.. i18n:     * **data** is a dictionary containing the following data:
 
149
.. i18n:            * **ids**: the list of ids of resources selected when the user executed the wizard
 
150
.. i18n:            * **id**: the id highlighted when the user executed the wizard
 
151
.. i18n:            * **form**: a dictionary containing all the values the user completed in the preceding forms. If you change values in this dictionary, the following forms will be pre-completed. 
 
152
 
 
153
    * **self** is the pointer to the wizard object
 
154
    * **uid** is the user ID of the user which is executing the wizard
 
155
    * **data** is a dictionary containing the following data:
 
156
           * **ids**: the list of ids of resources selected when the user executed the wizard
 
157
           * **id**: the id highlighted when the user executed the wizard
 
158
           * **form**: a dictionary containing all the values the user completed in the preceding forms. If you change values in this dictionary, the following forms will be pre-completed. 
 
159
 
 
160
.. i18n: The result
 
161
 
 
162
The result
 
163
 
 
164
.. i18n: Here are some result examples:
 
165
 
 
166
Here are some result examples:
 
167
 
 
168
.. i18n: Result: next step
 
169
 
 
170
Result: next step
 
171
 
 
172
.. i18n: .. code-block:: python
 
173
.. i18n: 
 
174
.. i18n:        'result': {'type': 'state', 
 
175
.. i18n:                   'state':'end'}
 
176
 
 
177
.. code-block:: python
 
178
 
 
179
        'result': {'type': 'state', 
 
180
                   'state':'end'}
 
181
 
 
182
.. i18n: Indicate that the wizard has to continue to the next state: 'end'. If this is the 'end' state, the wizard stops.
 
183
 
 
184
Indicate that the wizard has to continue to the next state: 'end'. If this is the 'end' state, the wizard stops.
 
185
 
 
186
.. i18n: Result: new dialog for the client
 
187
 
 
188
Result: new dialog for the client
 
189
 
 
190
.. i18n: .. code-block:: python
 
191
.. i18n: 
 
192
.. i18n:        'result': {'type': 'form', 
 
193
.. i18n:                   'arch': _form, 
 
194
.. i18n:                   'fields': _fields, 
 
195
.. i18n:                   'state':[('reconcile','Reconcile'),('end','Cancel')]}
 
196
 
 
197
.. code-block:: python
 
198
 
 
199
        'result': {'type': 'form', 
 
200
                   'arch': _form, 
 
201
                   'fields': _fields, 
 
202
                   'state':[('reconcile','Reconcile'),('end','Cancel')]}
 
203
 
 
204
.. i18n: The type=form indicate that this step is a dialog to the client. The dialog is composed of:
 
205
 
 
206
The type=form indicate that this step is a dialog to the client. The dialog is composed of:
 
207
 
 
208
.. i18n: #. a form : with fields description and a form description
 
209
.. i18n: #. some buttons : on wich the user press after completing the form 
 
210
 
 
211
#. a form : with fields description and a form description
 
212
#. some buttons : on wich the user press after completing the form 
 
213
 
 
214
.. i18n: The form description (arch) is like in the views objects. Here is an example of form:
 
215
 
 
216
The form description (arch) is like in the views objects. Here is an example of form:
 
217
 
 
218
.. i18n: .. code-block:: xml
 
219
.. i18n: 
 
220
.. i18n:        _form = """<?xml version="1.0"?>
 
221
.. i18n:                <form title="Reconciliation">
 
222
.. i18n:                  <separator string="Reconciliation transactions" colspan="4"/>
 
223
.. i18n:                  <field name="trans_nbr"/>
 
224
.. i18n:                  <newline/>
 
225
.. i18n:                  <field name="credit"/>
 
226
.. i18n:                  <field name="debit"/>
 
227
.. i18n:                  <separator string="Write-Off" colspan="4"/>
 
228
.. i18n:                  <field name="writeoff"/>
 
229
.. i18n:                  <newline/>
 
230
.. i18n:                  <field name="writeoff_acc_id" colspan="3"/>
 
231
.. i18n:                </form>
 
232
.. i18n:                """
 
233
 
 
234
.. code-block:: xml
 
235
 
 
236
        _form = """<?xml version="1.0"?>
 
237
                <form title="Reconciliation">
 
238
                  <separator string="Reconciliation transactions" colspan="4"/>
 
239
                  <field name="trans_nbr"/>
 
240
                  <newline/>
 
241
                  <field name="credit"/>
 
242
                  <field name="debit"/>
 
243
                  <separator string="Write-Off" colspan="4"/>
 
244
                  <field name="writeoff"/>
 
245
                  <newline/>
 
246
                  <field name="writeoff_acc_id" colspan="3"/>
 
247
                </form>
 
248
                """
 
249
 
 
250
.. i18n: The fields description is similar to the fields described in the python ORM objects. Example:
 
251
 
 
252
The fields description is similar to the fields described in the python ORM objects. Example:
 
253
 
 
254
.. i18n: .. code-block:: python
 
255
.. i18n: 
 
256
.. i18n:        _transaction_fields = {
 
257
.. i18n:              'trans_nbr': {'string':'# of Transaction', 'type':'integer', 'readonly':True},
 
258
.. i18n:              'credit': {'string':'Credit amount', 'type':'float', 'readonly':True},
 
259
.. i18n:              'debit': {'string':'Debit amount', 'type':'float', 'readonly':True},
 
260
.. i18n:              'writeoff': {'string':'Write-Off amount', 'type':'float', 'readonly':True},
 
261
.. i18n:              'writeoff_acc_id': {'string':'Write-Off account', 
 
262
.. i18n:                                    'type':'many2one', 
 
263
.. i18n:                                    'relation':'account.account'
 
264
.. i18n:                                  },
 
265
.. i18n:        }
 
266
 
 
267
.. code-block:: python
 
268
 
 
269
        _transaction_fields = {
 
270
              'trans_nbr': {'string':'# of Transaction', 'type':'integer', 'readonly':True},
 
271
              'credit': {'string':'Credit amount', 'type':'float', 'readonly':True},
 
272
              'debit': {'string':'Debit amount', 'type':'float', 'readonly':True},
 
273
              'writeoff': {'string':'Write-Off amount', 'type':'float', 'readonly':True},
 
274
              'writeoff_acc_id': {'string':'Write-Off account', 
 
275
                                   'type':'many2one', 
 
276
                                   'relation':'account.account'
 
277
                                 },
 
278
        }
 
279
 
 
280
.. i18n: Each step/state of a wizard can have several buttons. Those are located on the bottom right of the dialog box. The list of buttons for each step of the wizard is declared in the state key of its result dictionary.
 
281
 
 
282
Each step/state of a wizard can have several buttons. Those are located on the bottom right of the dialog box. The list of buttons for each step of the wizard is declared in the state key of its result dictionary.
 
283
 
 
284
.. i18n: For example:
 
285
 
 
286
For example:
 
287
 
 
288
.. i18n: .. code-block:: python
 
289
.. i18n: 
 
290
.. i18n:        'state':[('end', 'Cancel', 'gtk-cancel'), ('reconcile', 'Reconcile', '', True)]
 
291
 
 
292
.. code-block:: python
 
293
 
 
294
        'state':[('end', 'Cancel', 'gtk-cancel'), ('reconcile', 'Reconcile', '', True)]
 
295
 
 
296
.. i18n: #. the next step name (determine which state will be next)
 
297
.. i18n: #. the button string (to display for the client)
 
298
.. i18n: #. the gtk stock item without the stock prefix (since 4.2)
 
299
.. i18n: #. a boolean, if true the button is set as the default action (since 4.2) 
 
300
 
 
301
#. the next step name (determine which state will be next)
 
302
#. the button string (to display for the client)
 
303
#. the gtk stock item without the stock prefix (since 4.2)
 
304
#. a boolean, if true the button is set as the default action (since 4.2) 
 
305
 
 
306
.. i18n: Here is a screenshot of this form:
 
307
 
 
308
Here is a screenshot of this form:
 
309
 
 
310
.. i18n: .. image:: images/Wizard_screenshot1.png
 
311
 
 
312
.. image:: images/Wizard_screenshot1.png
 
313
 
 
314
.. i18n: Result: call a method to determine which state is next
 
315
 
 
316
Result: call a method to determine which state is next
 
317
 
 
318
.. i18n: .. code-block:: python
 
319
.. i18n: 
 
320
.. i18n:        def _check_refund(self, cr, uid, data, context):
 
321
.. i18n:            ...
 
322
.. i18n:            return datas['form']['refund_id'] and 'wait_invoice' or 'end'
 
323
.. i18n:         
 
324
.. i18n:            ...
 
325
.. i18n:         
 
326
.. i18n:            'result': {'type':'choice', 'next_state':_check_refund}
 
327
 
 
328
.. code-block:: python
 
329
 
 
330
        def _check_refund(self, cr, uid, data, context):
 
331
            ...
 
332
            return datas['form']['refund_id'] and 'wait_invoice' or 'end'
 
333
         
 
334
            ...
 
335
         
 
336
            'result': {'type':'choice', 'next_state':_check_refund}
 
337
 
 
338
.. i18n: Result: print a report
 
339
 
 
340
Result: print a report
 
341
 
 
342
.. i18n: .. code-block:: python
 
343
.. i18n: 
 
344
.. i18n:        def _get_invoice_id(self, uid, datas):
 
345
.. i18n:              ...
 
346
.. i18n:              return {'ids': [...]}
 
347
.. i18n:         
 
348
.. i18n:              ...
 
349
.. i18n:         
 
350
.. i18n:              'actions': [_get_invoice_id],
 
351
.. i18n:              'result': {'type':'print', 
 
352
.. i18n:                         'report':'account.invoice', 
 
353
.. i18n:                         'get_id_from_action': True, 
 
354
.. i18n:                         'state':'check_refund'}
 
355
 
 
356
.. code-block:: python
 
357
 
 
358
        def _get_invoice_id(self, uid, datas):
 
359
              ...
 
360
              return {'ids': [...]}
 
361
         
 
362
              ...
 
363
         
 
364
              'actions': [_get_invoice_id],
 
365
              'result': {'type':'print', 
 
366
                         'report':'account.invoice', 
 
367
                         'get_id_from_action': True, 
 
368
                         'state':'check_refund'}
 
369
 
 
370
.. i18n: Result: client run an action
 
371
 
 
372
Result: client run an action
 
373
 
 
374
.. i18n: .. code-block:: python
 
375
.. i18n: 
 
376
.. i18n:        def _makeInvoices(self, cr, uid, data, context):
 
377
.. i18n:            ...
 
378
.. i18n:            return {
 
379
.. i18n:                        'domain': "[('id','in', ["+','.join(map(str,newinv))+"])]",
 
380
.. i18n:                        'name': 'Invoices',
 
381
.. i18n:                        'view_type': 'form',
 
382
.. i18n:                        'view_mode': 'tree,form',
 
383
.. i18n:                        'res_model': 'account.invoice',
 
384
.. i18n:                        'view_id': False,
 
385
.. i18n:                        'context': "{'type':'out_refund'}",
 
386
.. i18n:                        'type': 'ir.actions.act_window'
 
387
.. i18n:                }
 
388
.. i18n:         
 
389
.. i18n:                ...
 
390
.. i18n:         
 
391
.. i18n:                'result': {'type': 'action', 
 
392
.. i18n:                'action': _makeInvoices, 
 
393
.. i18n:                'state': 'end'}
 
394
 
 
395
.. code-block:: python
 
396
 
 
397
        def _makeInvoices(self, cr, uid, data, context):
 
398
            ...
 
399
            return {
 
400
                        'domain': "[('id','in', ["+','.join(map(str,newinv))+"])]",
 
401
                        'name': 'Invoices',
 
402
                        'view_type': 'form',
 
403
                        'view_mode': 'tree,form',
 
404
                        'res_model': 'account.invoice',
 
405
                        'view_id': False,
 
406
                        'context': "{'type':'out_refund'}",
 
407
                        'type': 'ir.actions.act_window'
 
408
                }
 
409
         
 
410
                ...
 
411
         
 
412
                'result': {'type': 'action', 
 
413
                'action': _makeInvoices, 
 
414
                'state': 'end'}
 
415
 
 
416
.. i18n: The result of the function must be an all the fields of an ir.actions.* Here it is an ir.action.act_window, so the client will open an new tab for the objects account.invoice For more information about the fields used click here.
 
417
 
 
418
The result of the function must be an all the fields of an ir.actions.* Here it is an ir.action.act_window, so the client will open an new tab for the objects account.invoice For more information about the fields used click here.
 
419
 
 
420
.. i18n: It is recommended to use the result of a read on the ir.actions object like this:
 
421
 
 
422
It is recommended to use the result of a read on the ir.actions object like this:
 
423
 
 
424
.. i18n: .. code-block:: python
 
425
.. i18n: 
 
426
.. i18n:        def _account_chart_open_window(self, cr, uid, data, context):
 
427
.. i18n:                mod_obj = pooler.get_pool(cr.dbname).get('ir.model.data')
 
428
.. i18n:                act_obj = pooler.get_pool(cr.dbname).get('ir.actions.act_window')
 
429
.. i18n:         
 
430
.. i18n:                result = mod_obj._get_id(cr, uid, 'account', 'action_account_tree')
 
431
.. i18n:                id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
 
432
.. i18n:                result = act_obj.read(cr, uid, [id])[0]
 
433
.. i18n:                result['context'] = str({'fiscalyear': data['form']['fiscalyear']})
 
434
.. i18n:                return result
 
435
.. i18n:         
 
436
.. i18n:                ...
 
437
.. i18n:         
 
438
.. i18n:                'result': {'type': 'action', 
 
439
.. i18n:                           'action': _account_chart_open_window, 
 
440
.. i18n:                           'state':'end'}
 
441
 
 
442
.. code-block:: python
 
443
 
 
444
        def _account_chart_open_window(self, cr, uid, data, context):
 
445
                mod_obj = pooler.get_pool(cr.dbname).get('ir.model.data')
 
446
                act_obj = pooler.get_pool(cr.dbname).get('ir.actions.act_window')
 
447
         
 
448
                result = mod_obj._get_id(cr, uid, 'account', 'action_account_tree')
 
449
                id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
 
450
                result = act_obj.read(cr, uid, [id])[0]
 
451
                result['context'] = str({'fiscalyear': data['form']['fiscalyear']})
 
452
                return result
 
453
         
 
454
                ...
 
455
         
 
456
                'result': {'type': 'action', 
 
457
                           'action': _account_chart_open_window, 
 
458
                           'state':'end'}
 
459
 
 
460
.. i18n: Specification
 
461
.. i18n: =============
 
462
 
 
463
Specification
 
464
=============
 
465
 
 
466
.. i18n: Form
 
467
.. i18n: ----
 
468
 
 
469
Form
 
470
----
 
471
 
 
472
.. i18n: .. code-block:: xml
 
473
.. i18n: 
 
474
.. i18n:        _form = '''<?xml version="1.0"?>
 
475
.. i18n:        <form string="Your String">
 
476
.. i18n:            <field name="Field 1"/>
 
477
.. i18n:            <newline/>
 
478
.. i18n:            <field name="Field 2"/>
 
479
.. i18n:        </form>'''
 
480
 
 
481
.. code-block:: xml
 
482
 
 
483
        _form = '''<?xml version="1.0"?>
 
484
        <form string="Your String">
 
485
            <field name="Field 1"/>
 
486
            <newline/>
 
487
            <field name="Field 2"/>
 
488
        </form>'''
 
489
 
 
490
.. i18n: Fields
 
491
.. i18n: ------
 
492
 
 
493
Fields
 
494
------
 
495
 
 
496
.. i18n: Standard
 
497
.. i18n: +++++++++
 
498
 
 
499
Standard
 
500
+++++++++
 
501
 
 
502
.. i18n: .. code-block:: python
 
503
.. i18n: 
 
504
.. i18n:        Field type: char, integer, boolean, float, date, datetime
 
505
.. i18n: 
 
506
.. i18n:        _fields = {
 
507
.. i18n:              'str_field': {'string':'product name', 'type':'char', 'readonly':True},
 
508
.. i18n:        }
 
509
 
 
510
.. code-block:: python
 
511
 
 
512
        Field type: char, integer, boolean, float, date, datetime
 
513
 
 
514
        _fields = {
 
515
              'str_field': {'string':'product name', 'type':'char', 'readonly':True},
 
516
        }
 
517
 
 
518
.. i18n: * **string**: Field label (required)
 
519
.. i18n: * **type**: (required)
 
520
.. i18n: * **readonly**: (optional) 
 
521
 
 
522
* **string**: Field label (required)
 
523
* **type**: (required)
 
524
* **readonly**: (optional) 
 
525
 
 
526
.. i18n: Relational
 
527
.. i18n: ++++++++++
 
528
 
 
529
Relational
 
530
++++++++++
 
531
 
 
532
.. i18n: .. code-block:: python
 
533
.. i18n: 
 
534
.. i18n:        Field type: one2one,many2one,one2many,many2many
 
535
.. i18n: 
 
536
.. i18n:        _fields = {
 
537
.. i18n:            'field_id': {'string':'Write-Off account', 'type':'many2one', 'relation':'account.account'}
 
538
.. i18n:        }
 
539
 
 
540
.. code-block:: python
 
541
 
 
542
        Field type: one2one,many2one,one2many,many2many
 
543
 
 
544
        _fields = {
 
545
            'field_id': {'string':'Write-Off account', 'type':'many2one', 'relation':'account.account'}
 
546
        }
 
547
 
 
548
.. i18n: * **string**: Field label (required)
 
549
.. i18n: * **type**: (required)
 
550
.. i18n: * **relation**: name of the relation object 
 
551
 
 
552
* **string**: Field label (required)
 
553
* **type**: (required)
 
554
* **relation**: name of the relation object 
 
555
 
 
556
.. i18n: Add A New Wizard
 
557
.. i18n: ================
 
558
 
 
559
Add A New Wizard
 
560
================
 
561
 
 
562
.. i18n: To create a new wizard, you must:
 
563
 
 
564
To create a new wizard, you must:
 
565
 
 
566
.. i18n:     * create the wizard definition in a .py file
 
567
.. i18n:           * wizards are usually defined in the wizard subdirectory of their module as in server/bin/addons/module_name/wizard/your_wizard_name.py 
 
568
.. i18n:     * add your wizard to the list of import statements in the __init__.py file of your module's wizard subdirectory.
 
569
.. i18n:     * declare your wizard in the database 
 
570
 
 
571
    * create the wizard definition in a .py file
 
572
          * wizards are usually defined in the wizard subdirectory of their module as in server/bin/addons/module_name/wizard/your_wizard_name.py 
 
573
    * add your wizard to the list of import statements in the __init__.py file of your module's wizard subdirectory.
 
574
    * declare your wizard in the database 
 
575
 
 
576
.. i18n: The declaration is needed to map the wizard with a key of the client; when to launch which client. To declare a new wizard, you need to add it to the module_name_wizard.xml file, which contains all the wizard declarations for the module. If that file does not exist, you need to create it first.
 
577
 
 
578
The declaration is needed to map the wizard with a key of the client; when to launch which client. To declare a new wizard, you need to add it to the module_name_wizard.xml file, which contains all the wizard declarations for the module. If that file does not exist, you need to create it first.
 
579
 
 
580
.. i18n: Here is an example of the account_wizard.xml file;
 
581
 
 
582
Here is an example of the account_wizard.xml file;
 
583
 
 
584
.. i18n: .. code-block:: python
 
585
.. i18n: 
 
586
.. i18n:        <?xml version="1.0"?>
 
587
.. i18n:        <terp>
 
588
.. i18n:            <data>
 
589
.. i18n:                <delete model="ir.actions.wizard" search="[('wiz_name','like','account.')]" />
 
590
.. i18n:                <wizard string="Reconcile Transactions" model="account.move.line" 
 
591
.. i18n:                         name="account.move.line.reconcile" />
 
592
.. i18n:                <wizard string="Verify Transac steptions" model="account.move.line" 
 
593
.. i18n:                         name="account.move.line.check" keyword="tree_but_action" /> 
 
594
.. i18n:                <wizard string="Verify Transactions" model="account.move.line"  
 
595
.. i18n:                         name="account.move.line.check" />
 
596
.. i18n:                <wizard string="Print Journal" model="account.account" 
 
597
.. i18n:                         name="account.journal" />
 
598
.. i18n:                <wizard string="Split Invoice" model="account.invoice" 
 
599
.. i18n:                         name="account.invoice.split" />
 
600
.. i18n:                <wizard string="Refund Invoice" model="account.invoice" 
 
601
.. i18n:                         name="account.invoice.refund" />
 
602
.. i18n:            </data>
 
603
.. i18n:        </terp>
 
604
 
 
605
.. code-block:: python
 
606
 
 
607
        <?xml version="1.0"?>
 
608
        <terp>
 
609
            <data>
 
610
                <delete model="ir.actions.wizard" search="[('wiz_name','like','account.')]" />
 
611
                <wizard string="Reconcile Transactions" model="account.move.line" 
 
612
                        name="account.move.line.reconcile" />
 
613
                <wizard string="Verify Transac steptions" model="account.move.line" 
 
614
                        name="account.move.line.check" keyword="tree_but_action" /> 
 
615
                <wizard string="Verify Transactions" model="account.move.line"  
 
616
                        name="account.move.line.check" />
 
617
                <wizard string="Print Journal" model="account.account" 
 
618
                        name="account.journal" />
 
619
                <wizard string="Split Invoice" model="account.invoice" 
 
620
                        name="account.invoice.split" />
 
621
                <wizard string="Refund Invoice" model="account.invoice" 
 
622
                        name="account.invoice.refund" />
 
623
            </data>
 
624
        </terp>
 
625
 
 
626
.. i18n: Attributes for the wizard tag:
 
627
 
 
628
Attributes for the wizard tag:
 
629
 
 
630
.. i18n:     * **id** (optional):
 
631
.. i18n:     * **string**: The string which will be displayed if there are several wizards for one resthe user will be presented a list with wizards names).
 
632
.. i18n:     * **model**: The name of the **model** where the data needed by the wizard is.
 
633
.. i18n:     * **name**: The name of the wizard. It is used internally and should be unique.
 
634
.. i18n:     * **replace** (optional): Whether or not the wizard should override **all** existing wizards for this model. Default value: False.
 
635
.. i18n:     * **menu** (optional): Whether or not (True|False) to link the wizard with the 'gears' button (i.e. show the button or not). Default value: True.
 
636
.. i18n:     * **keyword** (optional): Bind the wizard to another action (print icon, gear icon, ...). Possible values for the keyword attribute are:
 
637
.. i18n:           * **client_print_multi**: the print icon in a form
 
638
.. i18n:           * **client_action_multi**: the 'gears' icon in a form
 
639
.. i18n:           * **tree_but_action**: the 'gears' icon in a tree view (with the shortcuts on the left)
 
640
.. i18n:           * **tree_but_open**: the double click on a branch of a tree (with the shortcuts on the left). For example, this is used, to bind wizards in the menu. 
 
641
 
 
642
    * **id** (optional):
 
643
    * **string**: The string which will be displayed if there are several wizards for one resthe user will be presented a list with wizards names).
 
644
    * **model**: The name of the **model** where the data needed by the wizard is.
 
645
    * **name**: The name of the wizard. It is used internally and should be unique.
 
646
    * **replace** (optional): Whether or not the wizard should override **all** existing wizards for this model. Default value: False.
 
647
    * **menu** (optional): Whether or not (True|False) to link the wizard with the 'gears' button (i.e. show the button or not). Default value: True.
 
648
    * **keyword** (optional): Bind the wizard to another action (print icon, gear icon, ...). Possible values for the keyword attribute are:
 
649
          * **client_print_multi**: the print icon in a form
 
650
          * **client_action_multi**: the 'gears' icon in a form
 
651
          * **tree_but_action**: the 'gears' icon in a tree view (with the shortcuts on the left)
 
652
          * **tree_but_open**: the double click on a branch of a tree (with the shortcuts on the left). For example, this is used, to bind wizards in the menu. 
 
653
 
 
654
.. i18n: **__terp__.py**
 
655
 
 
656
**__terp__.py**
 
657
 
 
658
.. i18n: If the wizard you created is the first one of its module, you probably had to create the modulename_wizard.xml file yourself. In that case, it should be added to the update_xml field of the __terp__.py file of the module.
 
659
 
 
660
If the wizard you created is the first one of its module, you probably had to create the modulename_wizard.xml file yourself. In that case, it should be added to the update_xml field of the __terp__.py file of the module.
 
661
 
 
662
.. i18n: Here is, for example, the **__terp__.py** file for the account module.
 
663
 
 
664
Here is, for example, the **__terp__.py** file for the account module.
 
665
 
 
666
.. i18n: .. code-block:: python
 
667
.. i18n: 
 
668
.. i18n:        {
 
669
.. i18n:            "name": Open ERP Accounting",
 
670
.. i18n:            "version": "0.1",
 
671
.. i18n:            "depends": ["base"],
 
672
.. i18n:            "init_xml": ["account_workflow.xml", "account_data.xml"],
 
673
.. i18n:            "update_xml": ["account_view.xml","account_report.xml", "account_wizard.xml"],
 
674
.. i18n:        }
 
675
 
 
676
.. code-block:: python
 
677
 
 
678
        {
 
679
            "name": Open ERP Accounting",
 
680
            "version": "0.1",
 
681
            "depends": ["base"],
 
682
            "init_xml": ["account_workflow.xml", "account_data.xml"],
 
683
            "update_xml": ["account_view.xml","account_report.xml", "account_wizard.xml"],
 
684
        }
 
685
 
 
686
.. i18n: osv_memory Wizard System
 
687
.. i18n: ========================
 
688
.. i18n: To develop osv_memory wizard, just create a normal object, But instead of inheriting from osv.osv, Inherit from osv.osv_memory. Methods of "wizard" are in object and if the wizard is complex, You can define workflow on object. osv_memory object is managed in memory instead of storing in postgresql.
 
689
 
 
690
osv_memory Wizard System
 
691
========================
 
692
To develop osv_memory wizard, just create a normal object, But instead of inheriting from osv.osv, Inherit from osv.osv_memory. Methods of "wizard" are in object and if the wizard is complex, You can define workflow on object. osv_memory object is managed in memory instead of storing in postgresql.
 
693
 
 
694
.. i18n: That's all, nothing more than just changing the inherit.
 
695
 
 
696
That's all, nothing more than just changing the inherit.
 
697
 
 
698
.. i18n: So what makes them looks like 'old' wizards?
 
699
 
 
700
So what makes them looks like 'old' wizards?
 
701
 
 
702
.. i18n:     * In the action that opens the object, you can put 
 
703
 
 
704
    * In the action that opens the object, you can put 
 
705
 
 
706
.. i18n: .. code-block:: python
 
707
.. i18n: 
 
708
.. i18n:        <field name="target">new</field>
 
709
 
 
710
.. code-block:: python
 
711
 
 
712
        <field name="target">new</field>
 
713
 
 
714
.. i18n: It means the object will open in a new window instead of the current one.
 
715
 
 
716
It means the object will open in a new window instead of the current one.
 
717
 
 
718
.. i18n:     * On a button, you can use <button special="cancel" .../> to close the window. 
 
719
 
 
720
    * On a button, you can use <button special="cancel" .../> to close the window. 
 
721
 
 
722
.. i18n: Example : In project.py file.
 
723
 
 
724
Example : In project.py file.
 
725
 
 
726
.. i18n: .. code-block:: python
 
727
.. i18n: 
 
728
.. i18n:        class config_compute_remaining(osv.osv_memory):
 
729
.. i18n:            _name='config.compute.remaining'
 
730
.. i18n:            def _get_remaining(self,cr, uid, ctx):
 
731
.. i18n:                if 'active_id' in ctx:
 
732
.. i18n:                    return self.pool.get('project.task').browse(cr,uid,ctx['active_id']).remaining_hours
 
733
.. i18n:                return False
 
734
.. i18n:            _columns = {
 
735
.. i18n:                'remaining_hours' : fields.float('Remaining Hours', digits=(16,2),),
 
736
.. i18n:                    }
 
737
.. i18n:            _defaults = {
 
738
.. i18n:                'remaining_hours': _get_remaining
 
739
.. i18n:                }
 
740
.. i18n:            def compute_hours(self, cr, uid, ids, context=None):
 
741
.. i18n:                if 'active_id' in context:
 
742
.. i18n:                    remaining_hrs=self.browse(cr,uid,ids)[0].remaining_hours
 
743
.. i18n:                    self.pool.get('project.task').write(cr,uid,context['active_id'],
 
744
.. i18n:                                                          {'remaining_hours' : remaining_hrs})
 
745
.. i18n:                return {
 
746
.. i18n:                        'type': 'ir.actions.act_window_close',
 
747
.. i18n:                 }
 
748
.. i18n:        config_compute_remaining()
 
749
 
 
750
.. code-block:: python
 
751
 
 
752
        class config_compute_remaining(osv.osv_memory):
 
753
            _name='config.compute.remaining'
 
754
            def _get_remaining(self,cr, uid, ctx):
 
755
                if 'active_id' in ctx:
 
756
                    return self.pool.get('project.task').browse(cr,uid,ctx['active_id']).remaining_hours
 
757
                return False
 
758
            _columns = {
 
759
                'remaining_hours' : fields.float('Remaining Hours', digits=(16,2),),
 
760
                    }
 
761
            _defaults = {
 
762
                'remaining_hours': _get_remaining
 
763
                }
 
764
            def compute_hours(self, cr, uid, ids, context=None):
 
765
                if 'active_id' in context:
 
766
                    remaining_hrs=self.browse(cr,uid,ids)[0].remaining_hours
 
767
                    self.pool.get('project.task').write(cr,uid,context['active_id'],
 
768
                                                         {'remaining_hours' : remaining_hrs})
 
769
                return {
 
770
                        'type': 'ir.actions.act_window_close',
 
771
                 }
 
772
        config_compute_remaining()
 
773
 
 
774
.. i18n: * View is same as normal view (Note buttons). 
 
775
 
 
776
* View is same as normal view (Note buttons). 
 
777
 
 
778
.. i18n: Example :
 
779
 
 
780
Example :
 
781
 
 
782
.. i18n: .. code-block:: xml
 
783
.. i18n: 
 
784
.. i18n:        <record id="view_config_compute_remaining" model="ir.ui.view">
 
785
.. i18n:                    <field name="name">Compute Remaining Hours </field>
 
786
.. i18n:                    <field name="model">config.compute.remaining</field>
 
787
.. i18n:                    <field name="type">form</field>
 
788
.. i18n:                    <field name="arch" type="xml">
 
789
.. i18n:                        <form string="Remaining Hours">
 
790
.. i18n:                            <separator colspan="4" string="Change Remaining Hours"/>
 
791
.. i18n:                            <newline/>
 
792
.. i18n:                            <field name="remaining_hours" widget="float_time"/>
 
793
.. i18n:                            <group col="4" colspan="4">
 
794
.. i18n:                                <button icon="gtk-cancel" special="cancel" string="Cancel"/>
 
795
.. i18n:                                <button icon="gtk-ok" name="compute_hours" string="Update" type="object"/>
 
796
.. i18n:                            </group>
 
797
.. i18n:                        </form>
 
798
.. i18n:                    </field>
 
799
.. i18n:                </record>
 
800
 
 
801
.. code-block:: xml
 
802
 
 
803
        <record id="view_config_compute_remaining" model="ir.ui.view">
 
804
                    <field name="name">Compute Remaining Hours </field>
 
805
                    <field name="model">config.compute.remaining</field>
 
806
                    <field name="type">form</field>
 
807
                    <field name="arch" type="xml">
 
808
                        <form string="Remaining Hours">
 
809
                            <separator colspan="4" string="Change Remaining Hours"/>
 
810
                            <newline/>
 
811
                            <field name="remaining_hours" widget="float_time"/>
 
812
                            <group col="4" colspan="4">
 
813
                                <button icon="gtk-cancel" special="cancel" string="Cancel"/>
 
814
                                <button icon="gtk-ok" name="compute_hours" string="Update" type="object"/>
 
815
                            </group>
 
816
                        </form>
 
817
                    </field>
 
818
                </record>
 
819
 
 
820
.. i18n: * Action is also same as normal action (don't forget to add target attribute) 
 
821
 
 
822
* Action is also same as normal action (don't forget to add target attribute) 
 
823
 
 
824
.. i18n: Example :
 
825
 
 
826
Example :
 
827
 
 
828
.. i18n: .. code-block:: xml
 
829
.. i18n: 
 
830
.. i18n:        <record id="action_config_compute_remaining" model="ir.actions.act_window">
 
831
.. i18n:            <field name="name">Compute Remaining Hours</field>
 
832
.. i18n:            <field name="type">ir.actions.act_window</field>
 
833
.. i18n:            <field name="res_model">config.compute.remaining</field>
 
834
.. i18n:            <field name="view_type">form</field>
 
835
.. i18n:            <field name="view_mode">form</field>
 
836
.. i18n:            <field name="target">new</field>
 
837
.. i18n:        </record>
 
838
 
 
839
.. code-block:: xml
 
840
 
 
841
        <record id="action_config_compute_remaining" model="ir.actions.act_window">
 
842
            <field name="name">Compute Remaining Hours</field>
 
843
            <field name="type">ir.actions.act_window</field>
 
844
            <field name="res_model">config.compute.remaining</field>
 
845
            <field name="view_type">form</field>
 
846
            <field name="view_mode">form</field>
 
847
            <field name="target">new</field>
 
848
        </record>