1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 ##############################################################################
23 from osv import fields,osv
26 from tools.config import config
30 class actions(osv.osv):
31 _name = 'ir.actions.actions'
34 'name': fields.char('Action Name', required=True, size=64),
35 'type': fields.char('Action Type', required=True, size=32),
36 'usage': fields.char('Action Usage', size=32),
39 'usage': lambda *a: False,
43 class report_custom(osv.osv):
44 _name = 'ir.actions.report.custom'
45 _table = 'ir_act_report_custom'
46 _sequence = 'ir_actions_id_seq'
48 'name': fields.char('Report Name', size=64, required=True, translate=True),
49 'type': fields.char('Report Type', size=32, required=True),
50 'model':fields.char('Object', size=64, required=True),
51 'report_id': fields.integer('Report Ref.', required=True),
52 'usage': fields.char('Action Usage', size=32),
53 'multi': fields.boolean('On multiple doc.', help="If set to true, the action will not be displayed on the right toolbar of a form views.")
56 'multi': lambda *a: False,
57 'type': lambda *a: 'ir.actions.report.custom',
61 class report_xml(osv.osv):
63 def _report_content(self, cursor, user, ids, name, arg, context=None):
65 for report in self.browse(cursor, user, ids, context=context):
66 data = report[name + '_data']
67 if not data and report[name[:-8]]:
69 fp = tools.file_open(report[name[:-8]], mode='rb')
76 def _report_content_inv(self, cursor, user, id, name, value, arg, context=None):
77 self.write(cursor, user, id, {name+'_data': value}, context=context)
79 def _report_sxw(self, cursor, user, ids, name, arg, context=None):
81 for report in self.browse(cursor, user, ids, context=context):
83 res[report.id] = report.report_rml.replace('.rml', '.sxw')
85 res[report.id] = False
88 _name = 'ir.actions.report.xml'
89 _table = 'ir_act_report_xml'
90 _sequence = 'ir_actions_id_seq'
92 'name': fields.char('Name', size=64, required=True, translate=True),
93 'type': fields.char('Report Type', size=32, required=True),
94 'model': fields.char('Object', size=64, required=True),
95 'report_name': fields.char('Internal Name', size=64, required=True),
96 'report_xsl': fields.char('XSL path', size=256),
97 'report_xml': fields.char('XML path', size=256),
98 'report_rml': fields.char('RML path', size=256,
99 help="The .rml path of the file or NULL if the content is in report_rml_content"),
100 'report_sxw': fields.function(_report_sxw, method=True, type='char',
102 'report_sxw_content_data': fields.binary('SXW content'),
103 'report_rml_content_data': fields.binary('RML content'),
104 'report_sxw_content': fields.function(_report_content,
105 fnct_inv=_report_content_inv, method=True,
106 type='binary', string='SXW content',),
107 'report_rml_content': fields.function(_report_content,
108 fnct_inv=_report_content_inv, method=True,
109 type='binary', string='RML content'),
110 'auto': fields.boolean('Automatic XSL:RML', required=True),
111 'usage': fields.char('Action Usage', size=32),
112 'header': fields.boolean('Add RML header',
113 help="Add or not the coporate RML header"),
114 'multi': fields.boolean('On multiple doc.',
115 help="If set to true, the action will not be displayed on the right toolbar of a form views."),
116 'report_type': fields.selection([
122 ], string='Type', required=True),
123 'groups_id': fields.many2many('res.groups', 'res_groups_report_rel', 'uid', 'gid', 'Groups'),
124 'attachment': fields.char('Save As Attachment Prefix', size=128, help='This is the filename of the attachment to store the printing result. Keep empty to not save the printed reports. You can use python expression using the object and time variables.'),
125 'attachment_use': fields.boolean('Reload from Attachment', help='If you check this, the second time the user print with same attachment name, it returns the previour report.')
128 'type': lambda *a: 'ir.actions.report.xml',
129 'multi': lambda *a: False,
130 'auto': lambda *a: True,
131 'header': lambda *a: True,
132 'report_sxw_content': lambda *a: False,
133 'report_type': lambda *a: 'pdf',
134 'attachment': lambda *a: False,
139 class act_window(osv.osv):
140 _name = 'ir.actions.act_window'
141 _table = 'ir_act_window'
142 _sequence = 'ir_actions_id_seq'
144 # def search(self, cr, uid, args, offset=0, limit=2000, order=None,
145 # context=None, count=False):
146 # if context is None:
148 # ids = osv.orm.orm.search(self, cr, uid, args, offset, limit, order,
152 # user_groups = self.pool.get('res.users').read(cr, uid, [uid])[0]['groups_id']
154 # for act in self.browse(cr, uid, ids):
155 # if not len(act.groups_id):
156 # result.append(act.id)
158 # for g in act.groups_id:
159 # if g.id in user_groups:
160 # result.append(act.id)
164 def _views_get_fnc(self, cr, uid, ids, name, arg, context={}):
166 for act in self.browse(cr, uid, ids):
167 res[act.id]=[(view.view_id.id, view.view_mode) for view in act.view_ids]
168 modes = act.view_mode.split(',')
169 if len(modes)>len(act.view_ids):
172 res[act.id].append((act.view_id.id, act.view_id.type))
173 for t in modes[len(act.view_ids):]:
174 if act.view_id and (t == act.view_id.type) and not find:
177 res[act.id].append((False, t))
181 'name': fields.char('Action Name', size=64, translate=True),
182 'type': fields.char('Action Type', size=32, required=True),
183 'view_id': fields.many2one('ir.ui.view', 'View Ref.', ondelete='cascade'),
184 'domain': fields.char('Domain Value', size=250),
185 'context': fields.char('Context Value', size=250),
186 'res_model': fields.char('Object', size=64),
187 'src_model': fields.char('Source Object', size=64),
188 'target': fields.selection([('current','Current Window'),('new','New Window')], 'Target Window'),
189 'view_type': fields.selection((('tree','Tree'),('form','Form')),string='Type of view'),
190 'view_mode': fields.char('Mode of view', size=250),
191 'usage': fields.char('Action Usage', size=32),
192 'view_ids': fields.one2many('ir.actions.act_window.view', 'act_window_id', 'Views'),
193 'views': fields.function(_views_get_fnc, method=True, type='binary', string='Views'),
194 'limit': fields.integer('Limit', help='Default limit for the list view'),
195 'auto_refresh': fields.integer('Auto-Refresh',
196 help='Add an auto-refresh on the view'),
197 'groups_id': fields.many2many('res.groups', 'ir_act_window_group_rel',
198 'act_id', 'gid', 'Groups'),
201 'type': lambda *a: 'ir.actions.act_window',
202 'view_type': lambda *a: 'form',
203 'view_mode': lambda *a: 'tree,form',
204 'context': lambda *a: '{}',
205 'limit': lambda *a: 80,
206 'target': lambda *a: 'current',
207 'auto_refresh': lambda *a: 0,
211 class act_window_view(osv.osv):
212 _name = 'ir.actions.act_window.view'
213 _table = 'ir_act_window_view'
214 _rec_name = 'view_id'
216 'sequence': fields.integer('Sequence'),
217 'view_id': fields.many2one('ir.ui.view', 'View'),
218 'view_mode': fields.selection((
222 ('calendar', 'Calendar'),
223 ('gantt', 'Gantt')), string='Type of view', required=True),
224 'act_window_id': fields.many2one('ir.actions.act_window', 'Action', ondelete='cascade'),
225 'multi': fields.boolean('On multiple doc.',
226 help="If set to true, the action will not be displayed on the right toolbar of a form views."),
229 'multi': lambda *a: False,
234 class act_wizard(osv.osv):
235 _name = 'ir.actions.wizard'
236 _inherit = 'ir.actions.actions'
237 _table = 'ir_act_wizard'
238 _sequence = 'ir_actions_id_seq'
240 'name': fields.char('Wizard info', size=64, required=True, translate=True),
241 'type': fields.char('Action type', size=32, required=True),
242 'wiz_name': fields.char('Wizard name', size=64, required=True),
243 'multi': fields.boolean('Action on multiple doc.', help="If set to true, the wizard will not be displayed on the right toolbar of a form views."),
244 'groups_id': fields.many2many('res.groups', 'res_groups_wizard_rel', 'uid', 'gid', 'Groups'),
245 'model': fields.char('Object', size=64),
248 'type': lambda *a: 'ir.actions.wizard',
249 'multi': lambda *a: False,
253 class act_url(osv.osv):
254 _name = 'ir.actions.url'
255 _table = 'ir_act_url'
256 _sequence = 'ir_actions_id_seq'
258 'name': fields.char('Action Name', size=64, translate=True),
259 'type': fields.char('Action Type', size=32, required=True),
260 'url': fields.text('Action Url',required=True),
261 'target': fields.selection((
262 ('new', 'New Window'),
263 ('self', 'This Window')),
264 'Action Target', required=True
268 'type': lambda *a: 'ir.actions.act_url',
269 'target': lambda *a: 'new'
273 def model_get(self, cr, uid, context={}):
274 wkf_pool = self.pool.get('workflow')
275 ids = wkf_pool.search(cr, uid, [])
276 osvs = wkf_pool.read(cr, uid, ids, ['osv'])
279 mpool = self.pool.get('ir.model')
281 model = osv.get('osv')
282 id = mpool.search(cr, uid, [('model','=',model)])
283 name = mpool.read(cr, uid, id)[0]['name']
284 res.append((model, name))
288 class ir_model_fields(osv.osv):
289 _inherit = 'ir.model.fields'
290 _rec_name = 'field_description'
292 'complete_name': fields.char('Complete Name', size=64, select=1),
295 def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=800):
296 def get_fields(cr, uid, field, rel):
298 mobj = self.pool.get('ir.model')
299 id = mobj.search(cr, uid, [('model','=',rel)])
301 obj = self.pool.get('ir.model.fields')
302 ids = obj.search(cr, uid, [('model_id','in',id)])
303 records = obj.read(cr, uid, ids)
304 for record in records:
306 fld = field + '/' + record['name']
308 result.append((id, fld))
315 return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
317 if context.get('key') != 'server_action':
318 return super(ir_model_fields, self).name_search(cr, uid, name, args, operator, context, limit)
321 obj = self.pool.get('ir.model.fields')
322 ids = obj.search(cr, uid, args)
323 records = obj.read(cr, uid, ids)
324 for record in records:
326 field = record['name']
328 if record['ttype'] == 'many2one':
329 rel = record['relation']
330 res = get_fields(cr, uid, field, record['relation'])
334 result.append((id, field))
337 obj.write(cr, uid, [rs[0]], {'complete_name':rs[1]})
343 result = super(ir_model_fields, self).name_search(cr, uid, name, [('complete_name','ilike',name), ('id','in',iids)], operator, context, limit)
349 class server_object_lines(osv.osv):
350 _name = 'ir.server.object.lines'
351 _sequence = 'ir_actions_id_seq'
353 'server_id': fields.many2one('ir.actions.server', 'Object Mapping'),
354 'col1': fields.many2one('ir.model.fields', 'Destination', required=True),
355 'value': fields.text('Value', required=True),
356 'type': fields.selection([
358 ('equation','Formula')
359 ], 'Type', required=True, size=32, change_default=True),
362 'type': lambda *a: 'equation',
364 server_object_lines()
367 # Actions that are run on the server side
369 class actions_server(osv.osv):
371 def _select_signals(self, cr, uid, context={}):
372 cr.execute("select distinct t.signal as key, t.signal || ' - [ ' || w.osv || ' ] ' as val from wkf w, wkf_activity a, wkf_transition t "\
373 " where w.id = a.wkf_id " \
374 " and t.act_from = a.wkf_id " \
375 " or t.act_to = a.wkf_id and t.signal not in (null, NULL)")
376 result = cr.fetchall() or []
379 if not rs[0] == None and not rs[1] == None:
383 _name = 'ir.actions.server'
384 _table = 'ir_act_server'
385 _sequence = 'ir_actions_id_seq'
388 'name': fields.char('Action Name', required=True, size=64, help="Easy to Refer action by name i.e. One Sales Order -> Many Invoice"),
389 'condition' : fields.char('Condition', size=256, required=True, help="Condition that is to be test before execute action, i.e : object.list_price > object.cost_price"),
390 'state': fields.selection([
391 ('client_action','Client Action'),
393 ('loop','Iteration'),
394 ('code','Python Code'),
395 ('trigger','Trigger'),
398 ('object_create','Create Object'),
399 ('object_write','Write Object'),
400 ('other','Multi Actions'),
401 ], 'Action Type', required=True, size=32, help="Type of the Action that is to be execute"),
402 'code':fields.text('Python Code', help="python code to be execute"),
403 'sequence': fields.integer('Sequence', help="Important when you deal with the multi action, the execution order will be decided based on this, low number higher priority"),
404 'model_id': fields.many2one('ir.model', 'Object', required=True, help="select the obect on which the action will work (read, write, create)"),
405 'action_id': fields.many2one('ir.actions.actions', 'Client Action', help="Select the Ation Window, Report, Wizard to be execute"),
406 'trigger_name': fields.selection(_select_signals, string='Trigger Name', size=128, help="Select the Signal name that is to be "),
407 'wkf_model_id': fields.many2one('ir.model', 'Workflow on', help="Workflow to be execute on which model"),
408 'trigger_obj_id': fields.many2one('ir.model.fields','Trigger On', help="select the object from the model on which the workflow will execute"),
409 'email': fields.char('Email Address', size=512, help="provides the fiels that will refer to the tiny to fetch the email address, i.e. you select the invoice, then `object.invoice_address_id.email` is the field which give the correct address"),
410 'subject': fields.char('Subject', size=1024, translate=True, help="Specify the subject, you can use the fields from the object. like `Hello [[ object.partner_id.name ]]`"),
411 'message': fields.text('Message', translate=True, help="Specify the Message, you can use the fields from the object. like `Dear [[ object.partner_id.name ]]`"),
412 'mobile': fields.char('Mobile No', size=512, help="provides the fiels that will refer to the tiny to fetch the mobile number, i.e. you select the invoice, then `object.invoice_address_id.mobile` is the field which give the correct mobile number"),
413 'sms': fields.char('SMS', size=160, translate=True),
414 'child_ids': fields.many2many('ir.actions.server', 'rel_server_actions', 'server_id', 'action_id', 'Others Actions'),
415 'usage': fields.char('Action Usage', size=32),
416 'type': fields.char('Action Type', size=32, required=True),
417 'srcmodel_id': fields.many2one('ir.model', 'Model', help="In which object you want to create / write the object if its empty refer to the Object field"),
418 'fields_lines': fields.one2many('ir.server.object.lines', 'server_id', 'Fields Mapping'),
419 'record_id':fields.many2one('ir.model.fields', 'Create Id', help="Provide the field name from where the record id stores after the create operations, if its empty, you can not track the new record"),
420 'write_id':fields.char('Write Id', size=256, help="Provide the field name from where the record id refer for the write operation, if its empty it will refer to the active id of the object"),
421 'loop_action':fields.many2one('ir.actions.server', 'Loop Action', help="select the action, which will be executes. Loop action will not be avaliable inside loop"),
422 'expression':fields.char('Loop Expression', size=512, help="enter the field/expression that will return the list, i.e. select the sale order in Object, and we can have loop on sales order line. Expression = `object.order_line`"),
425 'state': lambda *a: 'dummy',
426 'condition': lambda *a: 'True',
427 'type': lambda *a: 'ir.actions.server',
428 'sequence': lambda *a: 5,
429 'code': lambda *a: """# You can use the following variables
436 # If you plan to return an action, assign: action = {...}
440 def get_email(self, cr, uid, action, context):
441 logger = netsvc.Logger()
442 obj_pool = self.pool.get(action.model_id.model)
443 id = context.get('active_id')
444 obj = obj_pool.browse(cr, uid, id)
448 if '/' in action.email.complete_name:
449 fields = action.email.complete_name.split('/')
450 elif '.' in action.email.complete_name:
451 fields = action.email.complete_name.split('.')
455 obj = getattr(obj, field)
457 logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (field))
461 def get_mobile(self, cr, uid, action, context):
462 logger = netsvc.Logger()
463 obj_pool = self.pool.get(action.model_id.model)
464 id = context.get('active_id')
465 obj = obj_pool.browse(cr, uid, id)
469 if '/' in action.mobile.complete_name:
470 fields = action.mobile.complete_name.split('/')
471 elif '.' in action.mobile.complete_name:
472 fields = action.mobile.complete_name.split('.')
476 obj = getattr(obj, field)
478 logger.notifyChannel('Workflow', netsvc.LOG_ERROR, 'Failed to parse : %s' % (field))
482 def merge_message(self, cr, uid, keystr, action, context):
483 logger = netsvc.Logger()
485 obj_pool = self.pool.get(action.model_id.model)
486 id = context.get('active_id')
487 obj = obj_pool.browse(cr, uid, id)
488 exp = str(match.group()[2:-2]).strip()
489 result = eval(exp, {'object':obj, 'context': context,'time':time})
490 if result in (None, False):
491 return str("--------")
494 com = re.compile('(\[\[.+?\]\])')
495 message = com.sub(merge, keystr)
499 # Context should contains:
501 # id : current id of the object
503 # False : Finnished correctly
504 # ACTION_ID : Action to launch
506 def run(self, cr, uid, ids, context={}):
507 logger = netsvc.Logger()
509 for action in self.browse(cr, uid, ids, context):
510 obj_pool = self.pool.get(action.model_id.model)
511 obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
520 expr = eval(str(action.condition), cxt)
524 if action.state=='client_action':
525 if not action.action_id:
526 raise osv.except_osv(_('Error'), _("Please specify an action to launch !"))
527 result = self.pool.get(action.action_id.type).read(cr, uid, action.action_id.id, context=context)
530 if action.state=='python':
532 'self': self.pool.get(action.model_id.model),
539 exec action.code in localdict
540 if 'action' in localdict:
541 return localdict['action']
543 if action.state == 'email':
544 user = config['email_from']
545 address = str(action.email)
547 address = eval(str(action.email), cxt)
552 raise osv.except_osv(_('Error'), _("Please specify the Partner Email address !"))
554 raise osv.except_osv(_('Error'), _("Please specify server option --smtp-from !"))
556 subject = self.merge_message(cr, uid, str(action.subject), action, context)
557 body = self.merge_message(cr, uid, str(action.message), action, context)
559 if tools.email_send(user, [address], subject, body, debug=False, subtype='html') == True:
560 logger.notifyChannel('email', netsvc.LOG_INFO, 'Email successfully send to : %s' % (address))
562 logger.notifyChannel('email', netsvc.LOG_ERROR, 'Failed to send email to : %s' % (address))
564 if action.state == 'trigger':
565 wf_service = netsvc.LocalService("workflow")
566 model = action.wkf_model_id.model
567 obj_pool = self.pool.get(action.model_id.model)
568 res_id = self.pool.get(action.model_id.model).read(cr, uid, [context.get('active_id')], [action.trigger_obj_id.name])
569 id = res_id [0][action.trigger_obj_id.name]
570 wf_service.trg_validate(uid, model, int(id), action.trigger_name, cr)
572 if action.state == 'sms':
573 #TODO: set the user and password from the system
574 # for the sms gateway user / password
577 to = self.get_mobile(cr, uid, action, context)
578 #TODO: Apply message mearge with the field
579 if tools.sms_send(user, password, api_id, text, to) == True:
580 logger.notifyChannel('sms', netsvc.LOG_INFO, 'SMS successfully send to : %s' % (action.address))
582 logger.notifyChannel('sms', netsvc.LOG_ERROR, 'Failed to send SMS to : %s' % (action.address))
584 if action.state == 'other':
586 for act in action.child_ids:
587 context['active_id'] = context['active_ids'][0]
588 result = self.run(cr, uid, [act.id], context)
594 if action.state == 'loop':
595 obj_pool = self.pool.get(action.model_id.model)
596 obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
605 expr = eval(str(action.expression), cxt)
606 context['object'] = obj
608 context['active_id'] = i.id
609 result = self.run(cr, uid, [action.loop_action.id], context)
611 if action.state == 'object_write':
613 for exp in action.fields_lines:
615 if exp.type == 'equation':
616 obj_pool = self.pool.get(action.model_id.model)
617 obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
618 cxt = {'context':context, 'object': obj, 'time':time}
619 expr = eval(euq, cxt)
622 res[exp.col1.name] = expr
624 if not action.write_id:
625 if not action.srcmodel_id:
626 obj_pool = self.pool.get(action.model_id.model)
627 obj_pool.write(cr, uid, [context.get('active_id')], res)
629 write_id = context.get('active_id')
630 obj_pool = self.pool.get(action.srcmodel_id.model)
631 obj_pool.write(cr, uid, [write_id], res)
633 elif action.write_id:
634 obj_pool = self.pool.get(action.srcmodel_id.model)
635 rec = self.pool.get(action.model_id.model).browse(cr, uid, context.get('active_id'))
636 id = eval(action.write_id, {'object': rec})
640 raise osv.except_osv(_('Error'), _("Problem in configuration `Record Id` in Server Action!"))
642 if type(id) != type(1):
643 raise osv.except_osv(_('Error'), _("Problem in configuration `Record Id` in Server Action!"))
645 obj_pool.write(cr, uid, [write_id], res)
647 if action.state == 'object_create':
649 for exp in action.fields_lines:
651 if exp.type == 'equation':
652 obj_pool = self.pool.get(action.model_id.model)
653 obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
654 expr = eval(euq, {'context':context, 'object': obj, 'time':time})
657 res[exp.col1.name] = expr
661 obj_pool = self.pool.get(action.srcmodel_id.model)
662 res_id = obj_pool.create(cr, uid, res)
665 self.pool.get(action.model_id.model).write(cr, uid, [context.get('active_id')], {action.record_id.name:res_id})
671 class act_window_close(osv.osv):
672 _name = 'ir.actions.act_window_close'
673 _inherit = 'ir.actions.actions'
674 _table = 'ir_actions'
676 'type': lambda *a: 'ir.actions.act_window_close',
680 # This model use to register action services.
681 # if action type is 'configure', it will be start on configuration wizard.
682 # if action type is 'service',
683 # - if start_type= 'at once', it will be start at one time on start date
684 # - if start_type='auto', it will be start on auto starting from start date, and stop on stop date
685 # - if start_type="manual", it will start and stop on manually
686 class ir_actions_todo(osv.osv):
687 _name = 'ir.actions.todo'
689 'name':fields.char('Name',size=64,required=True, select=True),
690 'note':fields.text('Text', translate=True),
691 'start_date': fields.datetime('Start Date'),
692 'end_date': fields.datetime('End Date'),
693 'action_id':fields.many2one('ir.actions.act_window', 'Action', select=True,required=True, ondelete='cascade'),
694 'sequence':fields.integer('Sequence'),
695 'active': fields.boolean('Active'),
696 'type':fields.selection([('configure', 'Configure'),('service', 'Service'),('other','Other')], string='Type', required=True),
697 'start_on':fields.selection([('at_once', 'At Once'),('auto', 'Auto'),('manual','Manual')], string='Start On'),
698 'groups_id': fields.many2many('res.groups', 'res_groups_act_todo_rel', 'act_todo_id', 'group_id', 'Groups'),
699 'users_id': fields.many2many('res.users', 'res_users_act_todo_rel', 'act_todo_id', 'user_id', 'Users'),
700 'state':fields.selection([('open', 'Not Started'),('done', 'Done'),('skip','Skipped'),('cancel','Cancel')], string='State', required=True)
703 'state': lambda *a: 'open',
704 'sequence': lambda *a: 10,
705 'active':lambda *a:True,
706 'type':lambda *a:'configure'
711 # This model to use run all configuration actions
712 class ir_actions_configuration_wizard(osv.osv_memory):
713 _name='ir.actions.configuration.wizard'
714 def next_configuration_action(self,cr,uid,context={}):
715 item_obj = self.pool.get('ir.actions.todo')
716 item_ids = item_obj.search(cr, uid, [('type','=','configure'),('state', '=', 'open'),('active','=',True)], limit=1, context=context)
717 if item_ids and len(item_ids):
718 item = item_obj.browse(cr, uid, item_ids[0], context=context)
721 def _get_action_name(self, cr, uid, context={}):
722 next_action=self.next_configuration_action(cr,uid,context=context)
724 return next_action.note
726 return "Your database is now fully configured.\n\nClick 'Continue' and enjoy your OpenERP experience..."
729 def _get_action(self, cr, uid, context={}):
730 next_action=self.next_configuration_action(cr,uid,context=context)
732 return next_action.id
735 def _progress_get(self,cr,uid, context={}):
736 total = self.pool.get('ir.actions.todo').search_count(cr, uid, [], context)
737 todo = self.pool.get('ir.actions.todo').search_count(cr, uid, [('type','=','configure'),('active','=',True),('state','<>','open')], context)
738 return max(5.0,round(todo*100/total))
741 'name': fields.text('Next Wizard',readonly=True),
742 'progress': fields.float('Configuration Progress', readonly=True),
743 'item_id':fields.many2one('ir.actions.todo', 'Next Configuration Wizard',invisible=True, readonly=True),
746 'progress': _progress_get,
747 'item_id':_get_action,
748 'name':_get_action_name,
750 def button_next(self,cr,uid,ids,context=None):
751 user_action=self.pool.get('res.users').browse(cr,uid,uid)
752 act_obj=self.pool.get(user_action.menu_id.type)
753 action_ids=act_obj.search(cr,uid,[('name','=',user_action.menu_id.name)])
754 action_open=act_obj.browse(cr,uid,action_ids)[0]
755 if context.get('menu',False):
757 'view_type': action_open.view_type,
758 'view_id':action_open.view_id and [action_open.view_id.id] or False,
759 'res_model': action_open.res_model,
760 'type': action_open.type,
761 'domain':action_open.domain
763 return {'type':'ir.actions.act_window_close'}
765 def button_skip(self,cr,uid,ids,context=None):
766 item_obj = self.pool.get('ir.actions.todo')
767 item_id=self.read(cr,uid,ids)[0]['item_id']
769 item = item_obj.browse(cr, uid, item_id, context=context)
770 item_obj.write(cr, uid, item.id, {
776 'res_model': 'ir.actions.configuration.wizard',
777 'type': 'ir.actions.act_window',
780 return self.button_next(cr, uid, ids, context)
782 def button_continue(self, cr, uid, ids, context=None):
783 item_obj = self.pool.get('ir.actions.todo')
784 item_id=self.read(cr,uid,ids)[0]['item_id']
786 item = item_obj.browse(cr, uid, item_id, context=context)
787 item_obj.write(cr, uid, item.id, {
791 'view_mode': item.action_id.view_mode,
792 'view_type': item.action_id.view_type,
793 'view_id':item.action_id.view_id and [item.action_id.view_id.id] or False,
794 'res_model': item.action_id.res_model,
795 'type': item.action_id.type,
796 'target':item.action_id.target,
798 return self.button_next(cr, uid, ids, context)
799 ir_actions_configuration_wizard()
801 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: