#This file is part of Tryton. The COPYRIGHT file at the top level of #this repository contains the full copyright notices and license terms. from trytond.pool import Pool import copy from threading import Lock from random import randint from sys import maxint class Wizard(object): _name = "" states = {} pool = None def __new__(cls): Pool.register(cls, type='wizard') def __init__(self): super(Wizard, self).__init__() self._rpc = { 'create': True, 'delete': True, 'execute': True, } self._error_messages = {} self._lock = Lock() self._datas = {} def init(self, cursor, module_name): for state in self.states.keys(): if self.states[state]['result']['type'] == 'form': for button in \ self.states[state]['result']['state']: button_name = button[0] button_value = button[1] cursor.execute('SELECT id, name, src ' \ 'FROM ir_translation ' \ 'WHERE module = %s ' \ 'AND lang = %s ' \ 'AND type = %s ' \ 'AND name = %s', (module_name, 'en_US', 'wizard_button', self._name + ',' + state + ',' + button_name)) res = cursor.dictfetchall() if not res: cursor.execute('INSERT INTO ir_translation ' \ '(name, lang, type, src, value, module, fuzzy)'\ ' VALUES (%s, %s, %s, %s, %s, %s, %s)', (self._name + ',' + state + ',' + button_name, 'en_US', 'wizard_button', button_value, '', module_name, False)) elif res[0]['src'] != button_value: cursor.execute('UPDATE ir_translation ' \ 'SET src = %s, ' \ 'fuzzy = %s ' 'WHERE id = %s', (button_value, True, res[0]['id'])) cursor.execute('SELECT id, src FROM ir_translation ' \ 'WHERE lang = %s ' \ 'AND type = %s ' \ 'AND name = %s', ('en_US', 'error', self._name)) trans_error = {} for trans in cursor.dictfetchall(): trans_error[trans['src']] = trans for error in self._error_messages.values(): if error not in trans_error: cursor.execute('INSERT INTO ir_translation ' \ '(name, lang, type, src, value, module, fuzzy) ' \ 'VALUES (%s, %s, %s, %s, %s, %s, %s)', (self._name, 'en_US', 'error', error, '', module_name, False)) def raise_user_error(self, cursor, error, error_args=None, error_description='', error_description_args=None, context=None): translation_obj = self.pool.get('ir.translation') if context is None: context = {} error = self._error_messages.get(error, error) res = translation_obj._get_source(cursor, self._name, 'error', context.get('language', 'en_US'), error) if res: error = res if error_args: error = error % error_args if error_description: error_description = self._error_messages.get(error_description, error_description) res = translation_obj._get_source(cursor, self._name, 'error', context.get('language', 'en_US'), error_description) if res: error_description = res if error_description_args: error_description = error_description % error_description_args raise Exception('UserError', error, error_description) raise Exception('UserError', error) def create(self, cursor, user): self._lock.acquire() wiz_id = 0 while True: wiz_id = randint(0, maxint) if wiz_id not in self._datas: break self._datas[wiz_id] = {'user': user, '_wiz_id': wiz_id} self._lock.release() return wiz_id def delete(self, cursor, user, wiz_id): if wiz_id not in self._datas: return if self._datas[wiz_id]['user'] != user: raise Exception('AccessDenied') self._lock.acquire() del self._datas[wiz_id] self._lock.release() def execute(self, cursor, user, wiz_id, data, state='init', context=None): translation_obj = self.pool.get('ir.translation') wizard_size_obj = self.pool.get('ir.action.wizard_size') if context is None: context = {} res = {} if self._datas[wiz_id]['user'] != user: raise Exception('AccessDenied') self._datas[wiz_id].update(data) data = self._datas[wiz_id] state_def = self.states[state] result_def = state_def.get('result', {}) actions_res = {} # iterate through the list of actions defined for this state for action in state_def.get('actions', []): # execute them action_res = getattr(self, action)(cursor, user, data, context) assert isinstance(action_res, dict), \ 'The return value of wizard actions ' \ 'should be a dictionary' actions_res.update(action_res) res = copy.copy(result_def) if state_def.get('actions'): res['datas'] = actions_res lang = context.get('language', 'en_US') if result_def['type'] == 'action': res['action'] = getattr(self, result_def['action'])(cursor, user, data, context) elif result_def['type'] == 'form': obj = self.pool.get(result_def['object']) view = obj.fields_view_get(cursor, user, view_type='form', context=context, toolbar=False) fields = view['fields'] arch = view['arch'] button_list = copy.copy(result_def['state']) default_values = obj.default_get(cursor, user, fields.keys(), context=context) for field in default_values.keys(): if '.' in field: continue fields[field]['value'] = default_values[field] # translate buttons for i, button in enumerate(button_list): button_name = button[0] res_trans = translation_obj._get_source(cursor, self._name + ',' + state + ',' + button_name, 'wizard_button', lang) if res_trans: button = list(button) button[1] = res_trans button_list[i] = tuple(button) res['fields'] = fields res['arch'] = arch res['state'] = button_list res['size'] = wizard_size_obj.get_size(cursor, user, self._name, result_def['object'], context=context) elif result_def['type'] == 'choice': next_state = getattr(self, result_def['next_state'])(cursor, user, data, context) if next_state == 'end': return {'type': 'state', 'state': 'end'} return self.execute(cursor, user, wiz_id, data, next_state, context=context) return res