2
.. i18n: ===============================
3
.. i18n: Creating Wizard - (The Process)
4
.. i18n: ===============================
6
===============================
7
Creating Wizard - (The Process)
8
===============================
12
.. i18n: Wizards describe interaction sequences between the client and the server.
16
Wizards describe interaction sequences between the client and the server.
18
.. i18n: Here is, as an example, a typical process for a wizard:
20
Here is, as an example, a typical process for a wizard:
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
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
30
.. i18n: .. image:: images/Wizard.png
32
.. image:: images/Wizard.png
34
.. i18n: Here is a screenshot of the wizard used to reconcile transactions (when you click on the gear icon in an account chart):
36
Here is a screenshot of the wizard used to reconcile transactions (when you click on the gear icon in an account chart):
38
.. i18n: .. image:: images/Wizard_screenshot.png
40
.. image:: images/Wizard_screenshot.png
42
.. i18n: Wizards - Principles
43
.. i18n: ====================
44
.. i18n: A wizard is a succession of steps. A step is composed of several actions;
48
A wizard is a succession of steps. A step is composed of several actions;
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, ...)
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, ...)
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.
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.
64
.. i18n: Here is an example of such a class:
66
Here is an example of such a class:
68
.. i18n: .. code-block:: python
70
.. i18n: class wiz_reconcile(wizard.interface):
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')]}
79
.. i18n: 'reconcile': {
80
.. i18n: 'actions': [_trans_rec_reconcile],
81
.. i18n: 'result': {'type': 'state', 'state':'end'}
84
.. i18n: wiz_reconcile('account.move.line.reconcile');
86
.. code-block:: python
88
class wiz_reconcile(wizard.interface):
91
'actions': [_trans_rec_get],
92
'result': {'type': 'form',
93
'arch': _transaction_form,
94
'fields': _transaction_fields,
95
'state':[('reconcile','Reconcile'),('end','Cancel')]}
98
'actions': [_trans_rec_reconcile],
99
'result': {'type': 'state', 'state':'end'}
102
wiz_reconcile('account.move.line.reconcile');
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.
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.
108
.. i18n: A wizard always starts in the **init** state and ends in the **end** state.
110
A wizard always starts in the **init** state and ends in the **end** state.
112
.. i18n: A state define two things:
114
A state define two things:
116
.. i18n: #. a list of actions
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.
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.
130
.. i18n: The function (actions) must have the following signatures:
132
The function (actions) must have the following signatures:
134
.. i18n: .. code-block:: python
136
.. i18n: def _trans_rec_get(self, uid, data, res_get=False):
138
.. code-block:: python
140
def _trans_rec_get(self, uid, data, res_get=False):
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.
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.
164
.. i18n: Here are some result examples:
166
Here are some result examples:
168
.. i18n: Result: next step
172
.. i18n: .. code-block:: python
174
.. i18n: 'result': {'type': 'state',
175
.. i18n: 'state':'end'}
177
.. code-block:: python
179
'result': {'type': 'state',
182
.. i18n: Indicate that the wizard has to continue to the next state: 'end'. If this is the 'end' state, the wizard stops.
184
Indicate that the wizard has to continue to the next state: 'end'. If this is the 'end' state, the wizard stops.
186
.. i18n: Result: new dialog for the client
188
Result: new dialog for the client
190
.. i18n: .. code-block:: python
192
.. i18n: 'result': {'type': 'form',
193
.. i18n: 'arch': _form,
194
.. i18n: 'fields': _fields,
195
.. i18n: 'state':[('reconcile','Reconcile'),('end','Cancel')]}
197
.. code-block:: python
199
'result': {'type': 'form',
202
'state':[('reconcile','Reconcile'),('end','Cancel')]}
204
.. i18n: The type=form indicate that this step is a dialog to the client. The dialog is composed of:
206
The type=form indicate that this step is a dialog to the client. The dialog is composed of:
208
.. i18n: #. a form : with fields description and a form description
209
.. i18n: #. some buttons : on wich the user press after completing the form
211
#. a form : with fields description and a form description
212
#. some buttons : on wich the user press after completing the form
214
.. i18n: The form description (arch) is like in the views objects. Here is an example of form:
216
The form description (arch) is like in the views objects. Here is an example of form:
218
.. i18n: .. code-block:: xml
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"/>
225
.. i18n: <field name="credit"/>
226
.. i18n: <field name="debit"/>
227
.. i18n: <separator string="Write-Off" colspan="4"/>
228
.. i18n: <field name="writeoff"/>
230
.. i18n: <field name="writeoff_acc_id" colspan="3"/>
236
_form = """<?xml version="1.0"?>
237
<form title="Reconciliation">
238
<separator string="Reconciliation transactions" colspan="4"/>
239
<field name="trans_nbr"/>
241
<field name="credit"/>
242
<field name="debit"/>
243
<separator string="Write-Off" colspan="4"/>
244
<field name="writeoff"/>
246
<field name="writeoff_acc_id" colspan="3"/>
250
.. i18n: The fields description is similar to the fields described in the python ORM objects. Example:
252
The fields description is similar to the fields described in the python ORM objects. Example:
254
.. i18n: .. code-block:: python
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'
267
.. code-block:: python
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',
276
'relation':'account.account'
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.
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.
284
.. i18n: For example:
288
.. i18n: .. code-block:: python
290
.. i18n: 'state':[('end', 'Cancel', 'gtk-cancel'), ('reconcile', 'Reconcile', '', True)]
292
.. code-block:: python
294
'state':[('end', 'Cancel', 'gtk-cancel'), ('reconcile', 'Reconcile', '', True)]
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)
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)
306
.. i18n: Here is a screenshot of this form:
308
Here is a screenshot of this form:
310
.. i18n: .. image:: images/Wizard_screenshot1.png
312
.. image:: images/Wizard_screenshot1.png
314
.. i18n: Result: call a method to determine which state is next
316
Result: call a method to determine which state is next
318
.. i18n: .. code-block:: python
320
.. i18n: def _check_refund(self, cr, uid, data, context):
322
.. i18n: return datas['form']['refund_id'] and 'wait_invoice' or 'end'
326
.. i18n: 'result': {'type':'choice', 'next_state':_check_refund}
328
.. code-block:: python
330
def _check_refund(self, cr, uid, data, context):
332
return datas['form']['refund_id'] and 'wait_invoice' or 'end'
336
'result': {'type':'choice', 'next_state':_check_refund}
338
.. i18n: Result: print a report
340
Result: print a report
342
.. i18n: .. code-block:: python
344
.. i18n: def _get_invoice_id(self, uid, datas):
346
.. i18n: return {'ids': [...]}
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'}
356
.. code-block:: python
358
def _get_invoice_id(self, uid, datas):
360
return {'ids': [...]}
364
'actions': [_get_invoice_id],
365
'result': {'type':'print',
366
'report':'account.invoice',
367
'get_id_from_action': True,
368
'state':'check_refund'}
370
.. i18n: Result: client run an action
372
Result: client run an action
374
.. i18n: .. code-block:: python
376
.. i18n: def _makeInvoices(self, cr, uid, data, context):
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'
391
.. i18n: 'result': {'type': 'action',
392
.. i18n: 'action': _makeInvoices,
393
.. i18n: 'state': 'end'}
395
.. code-block:: python
397
def _makeInvoices(self, cr, uid, data, context):
400
'domain': "[('id','in', ["+','.join(map(str,newinv))+"])]",
403
'view_mode': 'tree,form',
404
'res_model': 'account.invoice',
406
'context': "{'type':'out_refund'}",
407
'type': 'ir.actions.act_window'
412
'result': {'type': 'action',
413
'action': _makeInvoices,
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.
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.
420
.. i18n: It is recommended to use the result of a read on the ir.actions object like this:
422
It is recommended to use the result of a read on the ir.actions object like this:
424
.. i18n: .. code-block:: python
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')
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
438
.. i18n: 'result': {'type': 'action',
439
.. i18n: 'action': _account_chart_open_window,
440
.. i18n: 'state':'end'}
442
.. code-block:: python
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')
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']})
456
'result': {'type': 'action',
457
'action': _account_chart_open_window,
460
.. i18n: Specification
461
.. i18n: =============
472
.. i18n: .. code-block:: xml
474
.. i18n: _form = '''<?xml version="1.0"?>
475
.. i18n: <form string="Your String">
476
.. i18n: <field name="Field 1"/>
478
.. i18n: <field name="Field 2"/>
483
_form = '''<?xml version="1.0"?>
484
<form string="Your String">
485
<field name="Field 1"/>
487
<field name="Field 2"/>
502
.. i18n: .. code-block:: python
504
.. i18n: Field type: char, integer, boolean, float, date, datetime
507
.. i18n: 'str_field': {'string':'product name', 'type':'char', 'readonly':True},
510
.. code-block:: python
512
Field type: char, integer, boolean, float, date, datetime
515
'str_field': {'string':'product name', 'type':'char', 'readonly':True},
518
.. i18n: * **string**: Field label (required)
519
.. i18n: * **type**: (required)
520
.. i18n: * **readonly**: (optional)
522
* **string**: Field label (required)
523
* **type**: (required)
524
* **readonly**: (optional)
532
.. i18n: .. code-block:: python
534
.. i18n: Field type: one2one,many2one,one2many,many2many
537
.. i18n: 'field_id': {'string':'Write-Off account', 'type':'many2one', 'relation':'account.account'}
540
.. code-block:: python
542
Field type: one2one,many2one,one2many,many2many
545
'field_id': {'string':'Write-Off account', 'type':'many2one', 'relation':'account.account'}
548
.. i18n: * **string**: Field label (required)
549
.. i18n: * **type**: (required)
550
.. i18n: * **relation**: name of the relation object
552
* **string**: Field label (required)
553
* **type**: (required)
554
* **relation**: name of the relation object
556
.. i18n: Add A New Wizard
557
.. i18n: ================
562
.. i18n: To create a new wizard, you must:
564
To create a new wizard, you must:
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
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
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.
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.
580
.. i18n: Here is an example of the account_wizard.xml file;
582
Here is an example of the account_wizard.xml file;
584
.. i18n: .. code-block:: python
586
.. i18n: <?xml version="1.0"?>
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" />
605
.. code-block:: python
607
<?xml version="1.0"?>
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" />
626
.. i18n: Attributes for the wizard tag:
628
Attributes for the wizard tag:
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.
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.
654
.. i18n: **__terp__.py**
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.
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.
662
.. i18n: Here is, for example, the **__terp__.py** file for the account module.
664
Here is, for example, the **__terp__.py** file for the account module.
666
.. i18n: .. code-block:: python
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"],
676
.. code-block:: python
679
"name": Open ERP Accounting",
682
"init_xml": ["account_workflow.xml", "account_data.xml"],
683
"update_xml": ["account_view.xml","account_report.xml", "account_wizard.xml"],
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.
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.
694
.. i18n: That's all, nothing more than just changing the inherit.
696
That's all, nothing more than just changing the inherit.
698
.. i18n: So what makes them looks like 'old' wizards?
700
So what makes them looks like 'old' wizards?
702
.. i18n: * In the action that opens the object, you can put
704
* In the action that opens the object, you can put
706
.. i18n: .. code-block:: python
708
.. i18n: <field name="target">new</field>
710
.. code-block:: python
712
<field name="target">new</field>
714
.. i18n: It means the object will open in a new window instead of the current one.
716
It means the object will open in a new window instead of the current one.
718
.. i18n: * On a button, you can use <button special="cancel" .../> to close the window.
720
* On a button, you can use <button special="cancel" .../> to close the window.
722
.. i18n: Example : In project.py file.
724
Example : In project.py file.
726
.. i18n: .. code-block:: python
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),),
737
.. i18n: _defaults = {
738
.. i18n: 'remaining_hours': _get_remaining
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})
746
.. i18n: 'type': 'ir.actions.act_window_close',
748
.. i18n: config_compute_remaining()
750
.. code-block:: python
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
759
'remaining_hours' : fields.float('Remaining Hours', digits=(16,2),),
762
'remaining_hours': _get_remaining
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})
770
'type': 'ir.actions.act_window_close',
772
config_compute_remaining()
774
.. i18n: * View is same as normal view (Note buttons).
776
* View is same as normal view (Note buttons).
782
.. i18n: .. code-block:: xml
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"/>
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"/>
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"/>
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"/>
820
.. i18n: * Action is also same as normal action (don't forget to add target attribute)
822
* Action is also same as normal action (don't forget to add target attribute)
828
.. i18n: .. code-block:: xml
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>
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>