def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None): taxes = self.env['account.tax'] company = self.env.user.company_id for tax in self: localdict = { 'price_unit': price_unit, 'quantity': quantity, 'product': product, 'partner': partner, 'company': company } safe_eval(tax.python_applicable, localdict, mode="exec", nocopy=True) if localdict.get('result', False): taxes += tax return super(AccountTaxPython, taxes).compute_all(price_unit, currency, quantity, product, partner)
def get_default_auth_signup_template_user_id(self, cr, uid, fields, context=None): icp = self.pool.get('ir.config_parameter') # we use safe_eval on the result, since the value of the parameter is a nonempty string return { 'auth_signup_reset_password': safe_eval(icp.get_param(cr, uid, 'auth_signup.reset_password', 'False')), 'auth_signup_uninvited': safe_eval(icp.get_param(cr, uid, 'auth_signup.allow_uninvited', 'False')), 'auth_signup_template_user_id': safe_eval(icp.get_param(cr, uid, 'auth_signup.template_user_id', 'False')), }
def _compute_amount(self, base_amount, price_unit, quantity=1.0, product=None, partner=None): self.ensure_one() if self.amount_type == 'code': company = self.env.user.company_id localdict = {'base_amount': base_amount, 'price_unit':price_unit, 'quantity': quantity, 'product':product, 'partner':partner, 'company': company} safe_eval(self.python_compute, localdict, mode="exec", nocopy=True) return localdict['result'] return super(AccountTaxPython, self)._compute_amount(base_amount, price_unit, quantity, product, partner)
def _ogone_form_validate(self, cr, uid, tx, data, context=None): if tx.state == 'done': _logger.info( 'Ogone: trying to validate an already validated tx (ref %s)', tx.reference) return True status = int(data.get('STATUS', '0')) if status in self._ogone_valid_tx_status: vals = { 'state': 'done', 'date_validate': datetime.datetime.strptime( data['TRXDATE'], '%m/%d/%y').strftime(DEFAULT_SERVER_DATE_FORMAT), 'acquirer_reference': data['PAYID'], } if data.get('ALIAS') and tx.partner_id and tx.type == 'form_save': pm_id = self.pool['payment.method'].create( cr, uid, { 'partner_id': tx.partner_id.id, 'acquirer_id': tx.acquirer_id.id, 'acquirer_ref': data.get('ALIAS'), 'name': '%s - %s' % (data.get('CARDNO'), data.get('CN')) }, context=context) vals.update(payment_method_id=pm_id) tx.write(vals) if tx.callback_eval: safe_eval(tx.callback_eval, {'self': tx}) return True elif status in self._ogone_cancel_tx_status: tx.write({ 'state': 'cancel', 'acquirer_reference': data.get('PAYID'), }) elif status in self._ogone_pending_tx_status or status in self._ogone_wait_tx_status: tx.write({ 'state': 'pending', 'acquirer_reference': data.get('PAYID'), }) else: error = 'Ogone: feedback error: %(error_str)s\n\n%(error_code)s: %(error_msg)s' % { 'error_str': data.get('NCERRORPLUS'), 'error_code': data.get('NCERROR'), 'error_msg': ogone.OGONE_ERROR_MAP.get(data.get('NCERROR')), } _logger.info(error) tx.write({ 'state': 'error', 'state_message': error, 'acquirer_reference': data.get('PAYID'), }) return False
def compute_all(self, price_unit, currency=None, quantity=1.0, product=None, partner=None): taxes = self.env['account.tax'] company = self.env.user.company_id for tax in self: localdict = {'price_unit':price_unit, 'quantity': quantity, 'product':product, 'partner':partner, 'company': company} safe_eval(tax.python_applicable, localdict, mode="exec", nocopy=True) if localdict.get('result', False): taxes += tax return super(AccountTaxPython, taxes).compute_all(price_unit, currency, quantity, product, partner)
def _ogone_s2s_validate_tree(self, tx, tree, tries=2): if tx.state not in ('draft', 'pending'): _logger.info( 'Ogone: trying to validate an already validated tx (ref %s)', tx.reference) return True status = int(tree.get('STATUS') or 0) if status in self._ogone_valid_tx_status: tx.write({ 'state': 'done', 'date_validate': datetime.date.today().strftime(DEFAULT_SERVER_DATE_FORMAT), 'acquirer_reference': tree.get('PAYID'), }) if tx.callback_eval: safe_eval(tx.callback_eval, {'self': tx}) return True elif status in self._ogone_cancel_tx_status: tx.write({ 'state': 'cancel', 'acquirer_reference': tree.get('PAYID'), }) elif status in self._ogone_pending_tx_status: tx.write({ 'state': 'pending', 'acquirer_reference': tree.get('PAYID'), 'html_3ds': str(tree.HTML_ANSWER).decode('base64') }) elif (not status or status in self._ogone_wait_tx_status) and tries > 0: time.sleep(500) tx.write({'acquirer_reference': tree.get('PAYID')}) tree = self._ogone_s2s_get_tx_status(tx) return self._ogone_s2s_validate_tree(tx, tree, tries - 1) else: error = 'Ogone: feedback error: %(error_str)s\n\n%(error_code)s: %(error_msg)s' % { 'error_str': tree.get('NCERRORPLUS'), 'error_code': tree.get('NCERROR'), 'error_msg': ogone.OGONE_ERROR_MAP.get(tree.get('NCERROR')), } _logger.info(error) tx.write({ 'state': 'error', 'state_message': error, 'acquirer_reference': tree.get('PAYID'), }) return False
def generate_data_files(self): """ Generate data and demo files """ data, demo = {}, {} filters = [ (data, ir_filter) for ir_filter in self.data_ids ] + [ (demo, ir_filter) for ir_filter in self.demo_ids ] for target, ir_filter in filters: model = ir_filter.model_id model_obj = self.env[model] target.setdefault(model, model_obj.browse([])) target[model] |= model_obj.search(safe_eval(ir_filter.domain)) res = [] for prefix, model_data, file_list in [ ('data', data, self._data_files), ('demo', demo, self._demo_files)]: for model_name, records in model_data.iteritems(): fname = self.friendly_name(self.unprefix(model_name)) filename = '{0}/{1}.xml'.format(prefix, fname) self._data_files.append(filename) res.append(self.generate_file_details( filename, 'data/model_name.xml.template', model=model_name, records=records, )) return res
def fixup_arch(cls, archstr): doc = lxml.etree.fromstring(archstr) for elem in doc.xpath("//*[@name]"): elem.attrib["name"] = cls.unprefix(elem.attrib["name"]) for elem in doc.xpath("//*[@attrs]"): try: attrs = safe_eval(elem.attrib["attrs"]) except Exception: _logger.error("Unable to eval attribute: %s, skipping", elem.attrib["attrs"]) continue if isinstance(attrs, dict): for key, val in attrs.iteritems(): if isinstance(val, (list, tuple)): attrs[key] = cls.fixup_domain(val) elem.attrib["attrs"] = repr(attrs) for elem in doc.xpath("//field"): # Make fields self-closed by removing useless whitespace if elem.text and not elem.text.strip(): elem.text = None return lxml.etree.tostring(doc)
def fixup_arch(cls, archstr): doc = lxml.etree.fromstring(archstr) for elem in doc.xpath("//*[@name]"): elem.attrib["name"] = cls.unprefix(elem.attrib["name"]) for elem in doc.xpath("//*[@attrs]"): try: attrs = safe_eval(elem.attrib["attrs"]) except Exception: _logger.error("Unable to eval attribute: %s, skipping", elem.attrib["attrs"]) continue if isinstance(attrs, dict): for key, val in attrs.iteritems(): if isinstance(val, (list, tuple)): attrs[key] = cls.fixup_domain(val) elem.attrib["attrs"] = repr(attrs) for elem in doc.xpath("//field"): # Make fields self-closed by removing useless whitespace if elem.text and not elem.text.strip(): elem.text = None return lxml.etree.tostring(doc)
def generate_data_files(self): """ Generate data and demo files """ data, demo = {}, {} filters = [(data, ir_filter) for ir_filter in self.data_ids ] + [(demo, ir_filter) for ir_filter in self.demo_ids] for target, ir_filter in filters: model = ir_filter.model_id model_obj = self.env[model] target.setdefault(model, model_obj.browse([])) target[model] |= model_obj.search(safe_eval(ir_filter.domain)) res = [] for prefix, model_data, file_list in [('data', data, self._data_files), ('demo', demo, self._demo_files) ]: for model_name, records in model_data.iteritems(): fname = self.friendly_name(self.unprefix(model_name)) filename = '{0}/{1}.xml'.format(prefix, fname) self._data_files.append(filename) res.append( self.generate_file_details( filename, 'data/model_name.xml.template', model=model_name, records=records, )) return res
def get_action(self, cr, uid, goal_id, context=None): """Get the ir.action related to update the goal In case of a manual goal, should return a wizard to update the value :return: action description in a dictionnary """ goal = self.browse(cr, uid, goal_id, context=context) if goal.definition_id.action_id: # open a the action linked to the goal action = goal.definition_id.action_id.read()[0] if goal.definition_id.res_id_field: current_user = self.pool.get('res.users').browse(cr, uid, uid, context=context) action['res_id'] = safe_eval(goal.definition_id.res_id_field, {'user': current_user}) # if one element to display, should see it in form mode if possible action['views'] = [(view_id, mode) for (view_id, mode) in action['views'] if mode == 'form'] or action['views'] return action if goal.computation_mode == 'manually': # open a wizard window to update the value manually action = { 'name': _("Update %s") % goal.definition_id.name, 'id': goal_id, 'type': 'ir.actions.act_window', 'views': [[False, 'form']], 'target': 'new', 'context': {'default_goal_id': goal_id, 'default_current': goal.current}, 'res_model': 'gamification.goal.wizard' } return action return False
def _ogone_form_validate(self, cr, uid, tx, data, context=None): if tx.state == 'done': _logger.info('Ogone: trying to validate an already validated tx (ref %s)', tx.reference) return True status = int(data.get('STATUS', '0')) if status in self._ogone_valid_tx_status: vals = { 'state': 'done', 'date_validate': datetime.datetime.strptime(data['TRXDATE'], '%m/%d/%y').strftime(DEFAULT_SERVER_DATE_FORMAT), 'acquirer_reference': data['PAYID'], } if data.get('ALIAS') and tx.partner_id and tx.type == 'form_save': pm_id = self.pool['payment.method'].create(cr, uid, { 'partner_id': tx.partner_id.id, 'acquirer_id': tx.acquirer_id.id, 'acquirer_ref': data.get('ALIAS'), 'name': '%s - %s' % (data.get('CARDNO'), data.get('CN')) }, context=context) vals.update(payment_method_id=pm_id) tx.write(vals) if tx.callback_eval: safe_eval(tx.callback_eval, {'self': tx}) return True elif status in self._ogone_cancel_tx_status: tx.write({ 'state': 'cancel', 'acquirer_reference': data.get('PAYID'), }) elif status in self._ogone_pending_tx_status or status in self._ogone_wait_tx_status: tx.write({ 'state': 'pending', 'acquirer_reference': data.get('PAYID'), }) else: error = 'Ogone: feedback error: %(error_str)s\n\n%(error_code)s: %(error_msg)s' % { 'error_str': data.get('NCERRORPLUS'), 'error_code': data.get('NCERROR'), 'error_msg': ogone.OGONE_ERROR_MAP.get(data.get('NCERROR')), } _logger.info(error) tx.write({ 'state': 'error', 'state_message': error, 'acquirer_reference': data.get('PAYID'), }) return False
def _ogone_s2s_validate_tree(self, tx, tree, tries=2): if tx.state not in ('draft', 'pending'): _logger.info('Ogone: trying to validate an already validated tx (ref %s)', tx.reference) return True status = int(tree.get('STATUS') or 0) if status in self._ogone_valid_tx_status: tx.write({ 'state': 'done', 'date_validate': datetime.date.today().strftime(DEFAULT_SERVER_DATE_FORMAT), 'acquirer_reference': tree.get('PAYID'), }) if tx.callback_eval: safe_eval(tx.callback_eval, {'self': tx}) return True elif status in self._ogone_cancel_tx_status: tx.write({ 'state': 'cancel', 'acquirer_reference': tree.get('PAYID'), }) elif status in self._ogone_pending_tx_status: tx.write({ 'state': 'pending', 'acquirer_reference': tree.get('PAYID'), 'html_3ds': str(tree.HTML_ANSWER).decode('base64') }) elif (not status or status in self._ogone_wait_tx_status) and tries > 0: time.sleep(500) tx.write({'acquirer_reference': tree.get('PAYID')}) tree = self._ogone_s2s_get_tx_status(tx) return self._ogone_s2s_validate_tree(tx, tree, tries - 1) else: error = 'Ogone: feedback error: %(error_str)s\n\n%(error_code)s: %(error_msg)s' % { 'error_str': tree.get('NCERRORPLUS'), 'error_code': tree.get('NCERROR'), 'error_msg': ogone.OGONE_ERROR_MAP.get(tree.get('NCERROR')), } _logger.info(error) tx.write({ 'state': 'error', 'state_message': error, 'acquirer_reference': tree.get('PAYID'), }) return False
def get_default_auth_signup_template_user_id(self, cr, uid, fields, context=None): icp = self.pool.get('ir.config_parameter') # we use safe_eval on the result, since the value of the parameter is a nonempty string return { 'auth_signup_reset_password': safe_eval( icp.get_param(cr, uid, 'auth_signup.reset_password', 'False')), 'auth_signup_uninvited': safe_eval( icp.get_param(cr, uid, 'auth_signup.allow_uninvited', 'False')), 'auth_signup_template_user_id': safe_eval( icp.get_param(cr, uid, 'auth_signup.template_user_id', 'False')), }
def eval(self, record, expr): #TODO: support remote variables (eg address.title) in expr # how to do that: parse the string, find dots, replace those dotted variables by temporary # "simple ones", fetch the value of those variables and add them (temporarily) to the _data # dictionary passed to eval #FIXME: it wont work if the data hasn't been fetched yet... this could # happen if the eval node is the first one using this Record # the next line is a workaround for the problem: it causes the resource to be loaded #Pinky: Why not this ? eval(expr, browser) ? # name = browser.name # data_dict = browser._data[self.get_value(browser, 'id')] return safe_eval(expr, {}, {'obj': record})
def _compute_amount(self, base_amount, price_unit, quantity=1.0, product=None, partner=None): self.ensure_one() if self.amount_type == 'code': company = self.env.user.company_id localdict = { 'base_amount': base_amount, 'price_unit': price_unit, 'quantity': quantity, 'product': product, 'partner': partner, 'company': company } safe_eval(self.python_compute, localdict, mode="exec", nocopy=True) return localdict['result'] return super(AccountTaxPython, self)._compute_amount(base_amount, price_unit, quantity, product, partner)
def eval(self, record, expr): #TODO: support remote variables (eg address.title) in expr # how to do that: parse the string, find dots, replace those dotted variables by temporary # "simple ones", fetch the value of those variables and add them (temporarily) to the _data # dictionary passed to eval #FIXME: it wont work if the data hasn't been fetched yet... this could # happen if the eval node is the first one using this Record # the next line is a workaround for the problem: it causes the resource to be loaded #Pinky: Why not this ? eval(expr, browser) ? # name = browser.name # data_dict = browser._data[self.get_value(browser, 'id')] return safe_eval(expr, {}, {'obj': record})
def _check_domain_validity(self, cr, uid, ids, context=None): # take admin as should always be present superuser = self.pool['res.users'].browse(cr, uid, SUPERUSER_ID, context=context) for definition in self.browse(cr, uid, ids, context=context): if definition.computation_mode not in ('count', 'sum'): continue obj = self.pool[definition.model_id.model] try: domain = safe_eval(definition.domain, {'user': superuser}) # demmy search to make sure the domain is valid obj.search(cr, uid, domain, context=context, count=True) except (ValueError, SyntaxError), e: msg = e.message or (e.msg + '\n' + e.text) raise UserError(_("The domain for the definition %s seems incorrect, please check it.\n\n%s" % (definition.name, msg)))
def _exec_action(action, datas, context): # taken from client/modules/action/main.py:84 _exec_action() if isinstance(action, bool) or 'type' not in action: return # Updating the context : Adding the context of action in order to use it on Views called from buttons if datas.get('id', False): context.update({ 'active_id': datas.get('id', False), 'active_ids': datas.get('ids', []), 'active_model': datas.get('model', False) }) context1 = action.get('context', {}) if isinstance(context1, basestring): context1 = safe_eval(context1, context.copy()) context.update(context1) if action['type'] in ['ir.actions.act_window', 'ir.actions.submenu']: for key in ('res_id', 'res_model', 'view_type', 'view_mode', 'limit', 'auto_refresh', 'search_view', 'auto_search', 'search_view_id'): datas[key] = action.get(key, datas.get(key, None)) view_id = False if action.get('views', []): if isinstance(action['views'], list): view_id = action['views'][0][0] datas['view_mode'] = action['views'][0][1] else: if action.get('view_id', False): view_id = action['view_id'][0] elif action.get('view_id', False): view_id = action['view_id'][0] assert datas['res_model'], "Cannot use the view without a model" # Here, we have a view that we need to emulate log_test("will emulate a %s view: %s#%s", action['view_type'], datas['res_model'], view_id or '?') view_res = registry[datas['res_model']].fields_view_get( cr, uid, view_id, action['view_type'], context) assert view_res and view_res.get( 'arch'), "Did not return any arch for the view" view_data = {} if view_res.get('fields', {}).keys(): view_data = registry[datas['res_model']].default_get( cr, uid, view_res['fields'].keys(), context) if datas.get('form'): view_data.update(datas.get('form')) if wiz_data: view_data.update(wiz_data) _logger.debug("View data is: %r", view_data) for fk, field in view_res.get('fields', {}).items(): # Default fields returns list of int, while at create() # we need to send a [(6,0,[int,..])] if field['type'] in ('one2many', 'many2many') \ and view_data.get(fk, False) \ and isinstance(view_data[fk], list) \ and not isinstance(view_data[fk][0], tuple) : view_data[fk] = [(6, 0, view_data[fk])] action_name = action.get('name') try: from xml.dom import minidom cancel_found = False buttons = [] dom_doc = minidom.parseString(view_res['arch']) if not action_name: action_name = dom_doc.documentElement.getAttribute('name') for button in dom_doc.getElementsByTagName('button'): button_weight = 0 if button.getAttribute('special') == 'cancel': cancel_found = True continue if button.getAttribute('icon') == 'gtk-cancel': cancel_found = True continue if button.getAttribute('default_focus') == '1': button_weight += 20 if button.getAttribute('string') in wiz_buttons: button_weight += 30 elif button.getAttribute('icon') in wiz_buttons: button_weight += 10 string = button.getAttribute( 'string') or '?%s' % len(buttons) buttons.append({ 'name': button.getAttribute('name'), 'string': string, 'type': button.getAttribute('type'), 'weight': button_weight, }) except Exception, e: _logger.warning( "Cannot resolve the view arch and locate the buttons!", exc_info=True) raise AssertionError(e.args[0]) if not datas['res_id']: # it is probably an orm_memory object, we need to create # an instance datas['res_id'] = registry[datas['res_model']].create( cr, uid, view_data, context) if not buttons: raise AssertionError( "view form doesn't have any buttons to press!") buttons.sort(key=lambda b: b['weight']) _logger.debug( 'Buttons are: %s', ', '.join( ['%s: %d' % (b['string'], b['weight']) for b in buttons])) res = None while buttons and not res: b = buttons.pop() log_test("in the \"%s\" form, I will press the \"%s\" button.", action_name, b['string']) if not b['type']: log_test("the \"%s\" button has no type, cannot use it", b['string']) continue if b['type'] == 'object': #there we are! press the button! fn = getattr(registry[datas['res_model']], b['name']) if not fn: _logger.error( "The %s model doesn't have a %s attribute!", datas['res_model'], b['name']) continue res = fn(cr, uid, [ datas['res_id'], ], context) break else: _logger.warning( "in the \"%s\" form, the \"%s\" button has unknown type %s", action_name, b['string'], b['type']) return res
def update(self, cr, uid, ids, context=None): """Update the goals to recomputes values and change of states If a manual goal is not updated for enough time, the user will be reminded to do so (done only once, in 'inprogress' state). If a goal reaches the target value, the status is set to reached If the end date is passed (at least +1 day, time not considered) without the target value being reached, the goal is set as failed.""" if context is None: context = {} commit = context.get('commit_gamification', False) goals_by_definition = {} for goal in self.browse(cr, uid, ids, context=context): goals_by_definition.setdefault(goal.definition_id, []).append(goal) for definition, goals in goals_by_definition.items(): goals_to_write = dict((goal.id, {}) for goal in goals) if definition.computation_mode == 'manually': for goal in goals: goals_to_write[goal.id].update(self._check_remind_delay(cr, uid, goal, context)) elif definition.computation_mode == 'python': # TODO batch execution for goal in goals: # execute the chosen method cxt = { 'self': self.pool.get('gamification.goal'), 'object': goal, 'pool': self.pool, 'cr': cr, 'context': dict(context), # copy context to prevent side-effects of eval 'uid': uid, 'date': date, 'datetime': datetime, 'timedelta': timedelta, 'time': time } code = definition.compute_code.strip() safe_eval(code, cxt, mode="exec", nocopy=True) # the result of the evaluated codeis put in the 'result' local variable, propagated to the context result = cxt.get('result') if result is not None and type(result) in (float, int, long): goals_to_write.update( self._get_write_values(cr, uid, goal, result, context=context) ) else: _logger.exception(_('Invalid return content from the evaluation of code for definition %s') % definition.name) else: # count or sum obj = self.pool.get(definition.model_id.model) field_date_name = definition.field_date_id and definition.field_date_id.name or False if definition.computation_mode == 'count' and definition.batch_mode: # batch mode, trying to do as much as possible in one request general_domain = safe_eval(definition.domain) field_name = definition.batch_distinctive_field.name subqueries = {} for goal in goals: start_date = field_date_name and goal.start_date or False end_date = field_date_name and goal.end_date or False subqueries.setdefault((start_date, end_date), {}).update({goal.id:safe_eval(definition.batch_user_expression, {'user': goal.user_id})}) # the global query should be split by time periods (especially for recurrent goals) for (start_date, end_date), query_goals in subqueries.items(): subquery_domain = list(general_domain) subquery_domain.append((field_name, 'in', list(set(query_goals.values())))) if start_date: subquery_domain.append((field_date_name, '>=', start_date)) if end_date: subquery_domain.append((field_date_name, '<=', end_date)) if field_name == 'id': # grouping on id does not work and is similar to search anyway user_ids = obj.search(cr, uid, subquery_domain, context=context) user_values = [{'id': user_id, 'id_count': 1} for user_id in user_ids] else: user_values = obj.read_group(cr, uid, subquery_domain, fields=[field_name], groupby=[field_name], context=context) # user_values has format of read_group: [{'partner_id': 42, 'partner_id_count': 3},...] for goal in [g for g in goals if g.id in query_goals.keys()]: for user_value in user_values: queried_value = field_name in user_value and user_value[field_name] or False if isinstance(queried_value, tuple) and len(queried_value) == 2 and isinstance(queried_value[0], (int, long)): queried_value = queried_value[0] if queried_value == query_goals[goal.id]: new_value = user_value.get(field_name+'_count', goal.current) goals_to_write.update( self._get_write_values(cr, uid, goal, new_value, context=context) ) else: for goal in goals: # eval the domain with user replaced by goal user object domain = safe_eval(definition.domain, {'user': goal.user_id}) # add temporal clause(s) to the domain if fields are filled on the goal if goal.start_date and field_date_name: domain.append((field_date_name, '>=', goal.start_date)) if goal.end_date and field_date_name: domain.append((field_date_name, '<=', goal.end_date)) if definition.computation_mode == 'sum': field_name = definition.field_id.name # TODO for master: group on user field in batch mode res = obj.read_group(cr, uid, domain, [field_name], [], context=context) new_value = res and res[0][field_name] or 0.0 else: # computation mode = count new_value = obj.search(cr, uid, domain, context=context, count=True) goals_to_write.update( self._get_write_values(cr, uid, goal, new_value, context=context) ) for goal_id, value in goals_to_write.items(): if not value: continue self.write(cr, uid, [goal_id], value, context=context) if commit: cr.commit() return True