def email_send(self, cr, uid, obj, emails, body, emailfrom=tools.config.get('email_from', False), context=None):
        mail_message = self.pool.get('mail.message')
        body = self.format_mail(obj, body)
        if not emailfrom:
            if hasattr(obj, 'user_id')  and obj.user_id and obj.user_id.user_email:
                emailfrom = obj.user_id.user_email

        ###dreis: customizable Subject line, specified in the first line of the "body"
        # name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
		#
        subject = body.splitlines()[0] #get first line of the body
        if subject.startswith('Subject:'): 
            name = subject.split(':', 1)[1].lstrip() #subject is text after ':'; strip leading spaces
            body = '\n'.join( body.splitlines()[1:] ) #body without the first line
        else:
            name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
        ###dreis end
		
        emailfrom = tools.ustr(emailfrom)
        if hasattr(obj, 'section_id') and obj.section_id and obj.section_id.reply_to:
            reply_to = obj.section_id.reply_to
        else:
            reply_to = emailfrom
        if not emailfrom:
            raise osv.except_osv(_('Error!'), 
                    _("No E-Mail ID Found for your Company address!"))
        #rint "...email_send:", emails ###, name ###reis###
        return mail_message.schedule_with_attach(cr, uid, emailfrom, emails, name, body, model='base.action.rule', reply_to=reply_to, res_id=obj.id)
Example #2
0
    def pull_continue_thread(self, cr, uid, ids, context=None):
        _logger = logging.getLogger('pull.rw')
        cr = pooler.get_db(cr.dbname).cursor()
        try:
            wizard = self.browse(cr, uid, ids[0])
            #US-26: Added a check if the zip file has already been imported before
            syncusb = self.pool.get('sync.usb.files')
            md5 = syncusb.md5(wizard.pull_data)
            self.write(cr, uid, ids, {'in_progress': True})
            updates_pulled = update_pull_error = updates_ran = update_run_error = \
            messages_pulled = message_pull_error = messages_ran = message_run_error = 0
            try:
                updates_pulled, update_pull_error, updates_ran, update_run_error, \
                messages_pulled, message_pull_error, messages_ran, message_run_error = self.pool.get('sync.client.entity').usb_pull(cr, uid, wizard.pull_data, context=context)
            except zipfile.BadZipfile:
                raise osv.except_osv(_('Not a Zip File'), _('The file you uploaded was not a valid .zip file'))

            #Update list of pulled files
            syncusb.create(cr, uid, {
                'sum': md5,
                'date': datetime.datetime.now().isoformat(),
            }, context=context)

            # handle returned values
            pull_result = ''
            if not update_pull_error:
                pull_result += 'Pulled %d update(s)' % updates_pulled 
                if not update_run_error:
                    pull_result += '\nRan %s update(s)' % updates_ran
                else:
                    pull_result += '\nError while executing %s update(s): %s' % (updates_ran, update_run_error)
            else:
                pull_result += 'Got an error while pulling %d update(s): %s' % (updates_pulled, update_pull_error)

            if not message_pull_error:
                pull_result += '\nPulled %d message(s)' % messages_pulled 
                if not message_run_error:
                    pull_result += '\nRan %s message(s)' % messages_ran
                else:
                    pull_result += '\nError while executing %s message(s): %s' % (messages_ran, message_run_error)
            else:
                pull_result += '\nGot an error while pulling %d message(s): %s' % (messages_pulled, message_pull_error)

            # If the correct sequence is received, then update this value into the DB for this instance, and inform in the RW sync dialog  
            rw_pull_sequence = context.get('rw_pull_sequence', -1)
            if rw_pull_sequence != -1:
                entity = self._get_entity(cr, uid, context)
                self.pool.get('sync.client.entity').write(cr, uid, entity.id, {'rw_pull_sequence': rw_pull_sequence}, context)        
                pull_result += '\n\nThe pulling file sequence is updated. The next expected sequence is %d' % (rw_pull_sequence + 1)

            vals = {
                'pull_result': pull_result,
                'usb_sync_step': self._get_usb_sync_step(cr, uid, context=context),
                'push_file_visible': False,
            }

            self.write(cr, uid, ids, vals, context=context)
        except osv.except_osv, e:
            self.write(cr, uid, ids, {'pull_result': "Error: %s" % e.value})
            _logger.error("%s : %s" % (tools.ustr(e.value), tools.ustr(traceback.format_exc())))
Example #3
0
        def group_unlink_update_execution(obj, sdref_update_ids):
            obj_ids = obj.find_sd_ref(cr, uid, sdref_update_ids.keys(), context=context)
            done_ids = []
            for sdref, id in obj_ids.items():
                try:
                    update_id = sdref_update_ids[sdref]
                    secure_unlink_data(obj, [id])
                except BaseException, e:
                    if isinstance(e, osv.except_osv):
                        error = '%s: %s' % (e.name, e.value)
                    else:
                        error = e
                    e = "Error during unlink on model %s!\nid: %s\nUpdate id: %s\nReason: %s\nSD ref:\n%s\n" \
                        % (obj._name, id, update_id, tools.ustr(error), update.sdref)
                    self.write(cr, uid, [update_id], {
                        'execution_date': datetime.now(),
                        'run' : False,
                        'log' : tools.ustr(e)
                    }, context=context)

                    ########################################################################
                    #
                    # UFTP-116: Cannot raise the exception here, because it will stop the whole sync!!!! Just set this line to become not run, OR set it run but error message
                    # If we just set it not run, it will be again and again executed but never successfully, and thus it will remain for every not run, attempt to execute EVERYTIME!
                    # ???? So, just set it RUN?
                    ########################################################################

#                    raise
                else:
                    done_ids.append(update_id)
Example #4
0
    def email_send(self, cr, uid, obj, emails, body, emailfrom=None, context=None):
        """ send email
            @param self: The object pointer
            @param cr: the current row, from the database cursor,
            @param uid: the current user’s ID for security checks,
            @param email: pass the emails
            @param emailfrom: Pass name the email From else False
            @param context: A standard dictionary for contextual values """

        if not emailfrom:
            emailfrom = tools.config.get('email_from', False)

        if context is None:
            context = {}

        body = self.format_mail(obj, body)
        if not emailfrom:
            if hasattr(obj, 'user_id')  and obj.user_id and obj.user_id.address_id and\
                        obj.user_id.address_id.email:
                emailfrom = obj.user_id.address_id.email

        name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
        emailfrom = tools.ustr(emailfrom)
        reply_to = emailfrom
        if not emailfrom:
            raise osv.except_osv(_('Error!'), 
                    _("No E-Mail ID Found for your Company address!"))
        return tools.email_send(emailfrom, emails, name, body, reply_to=reply_to, openobject_id=str(obj.id))
Example #5
0
    def load_from_file(self, path, dbname, key):
        class_inst = None
        expected_class = 'Parser'

        try:
            ad = os.path.abspath(os.path.join(tools.ustr(config['root_path']), u'addons'))
            mod_path_list = map(lambda m: os.path.abspath(tools.ustr(m.strip())), config['addons_path'].split(','))
            mod_path_list.append(ad)
            mod_path_list = list(set(mod_path_list))

            for mod_path in mod_path_list:
                if os.path.lexists(mod_path+os.path.sep+path.split(os.path.sep)[0]):
                    filepath=mod_path+os.path.sep+path
                    filepath = os.path.normpath(filepath)
                    sys.path.append(os.path.dirname(filepath))
                    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])
                    mod_name = '%s_%s_%s' % (dbname,mod_name,key)

                    if file_ext.lower() == '.py':
                        py_mod = imp.load_source(mod_name, filepath)

                    elif file_ext.lower() == '.pyc':
                        py_mod = imp.load_compiled(mod_name, filepath)

                    if expected_class in dir(py_mod):
                        class_inst = py_mod.Parser
                    return class_inst
                elif os.path.lexists(mod_path+os.path.sep+path.split(os.path.sep)[0]+'.zip'):
                    zimp = zipimport.zipimporter(mod_path+os.path.sep+path.split(os.path.sep)[0]+'.zip')
                    return zimp.load_module(path.split(os.path.sep)[0]).parser.Parser
        except SyntaxError, e:
            raise osv.except_osv(_('Syntax Error !'), e)
 def _get_periode(self, data):
     ttyme = datetime.fromtimestamp(time.mktime(time.strptime(data,"%Y-%m-%d")))
     bulan = tools.ustr(ttyme.strftime('%m'))
 	if bulan == '01':
 	    mo = 'Januari'
 	elif bulan == '02':
         mo = 'Februari'	
 	elif bulan == '03':
         mo = 'Maret'
 	elif bulan == '04':
         mo = 'April'
 	elif bulan == '05':
         mo = 'Mei'
 	elif bulan == '06':
         mo = 'Juni'
 	elif bulan == '07':
         mo = 'Juli'
 	elif bulan == '08':
         mo = 'Agustus'
 	elif bulan == '09':
         mo = 'September'
 	elif bulan == '10':
         mo = 'Oktober'
 	elif bulan == '11':
         mo = 'November'
 	elif bulan == '12':
         mo = 'Desember'
 	else:
 	    mo = tools.ustr(ttyme.strftime('%B'))
 	tahun = tools.ustr(ttyme.strftime('%Y'))
     #print "tahun, mo",tahun, mo
     return "%s %s" % (mo,tahun)
Example #7
0
    def do_check(self, cr, uid, action, obj, context=None):
        ok = super(base_action_rule, self).do_check(cr, uid, action, obj, context=context)

        if 'section_id' in obj._model._all_columns:
            ok = ok and (not action.trg_section_id or action.trg_section_id.id == obj.section_id.id)
        if 'categ_id' in obj._model._all_columns:
            ok = ok and (not action.trg_categ_id or action.trg_categ_id.id == obj.categ_id.id)

        # Cheking for history
        regex = action.regex_history
        if regex:
            res = False
            ptrn = re.compile(ustr(regex))
            for history in obj.message_ids:
                _result = ptrn.search(ustr(history.subject))
                if _result:
                    res = True
                    break
            ok = ok and res

        if action.trg_max_history:
            res_count = False
            history_ids = filter(lambda x: x.email_from, obj.message_ids)
            if len(history_ids) <= action.trg_max_history:
                res_count = True
            ok = ok and res_count
        return ok
Example #8
0
    def _get_source(self, cr, uid, name, tt, lang, source=None):
        """
        Returns the translation for the given combination of name, type, language
        and source. All values passed to this method should be unicode (not byte strings),
        especially ``source``.

        :param name: identification of the term to translate, such as field name
        :param type: type of term to translate (see ``type`` field on ir.translation)
        :param lang: language code of the desired translation
        :param source: optional source term to translate (should be unicode)
        :rtype: unicode
        :return: the request translation, or an empty unicode string if no translation was
                 found and `source` was not passed
        """
        if source:
            cr.execute('select value ' \
                    'from ir_translation ' \
                    'where lang=%s ' \
                        'and type=%s ' \
                        'and name=%s ' \
                        'and src=%s',
                    (lang or '', tt, tools.ustr(name), source))
        else:
            cr.execute('select value ' \
                    'from ir_translation ' \
                    'where lang=%s ' \
                        'and type=%s ' \
                        'and name=%s',
                    (lang or '', tt, tools.ustr(name)))
        res = cr.fetchone()
        trad = res and res[0] or u''
        if source and not trad:
            return tools.ustr(source)
        return trad
Example #9
0
        def create_normal_update(self, rule, context):
            domain = eval(rule.domain or '[]')
            included_fields = eval(rule.included_fields or '[]') 
            if not 'id' in included_fields: 
                included_fields.append('id')

            ids_need_to_push = self.usb_need_to_push(cr, uid, context=context)
            if not ids_need_to_push:
                return 0
            domain.append(('id', 'in', ids_need_to_push))
            ids_to_compute = self.search_ext(cr, uid, domain, context=context)
            if not ids_to_compute:
                return 0

            owners = self.get_destination_name(cr, uid, ids_to_compute, rule.owner_field, context)
            datas = self.export_data(cr, uid, ids_to_compute, included_fields, context=context)['datas']
            sdrefs = self.get_sd_ref(cr, uid, ids_to_compute, context=context)
            versions = self.version(cr, uid, ids_to_compute, context=context)
            ustr_included_fields = tools.ustr(included_fields)
            for (id, row) in zip(ids_to_compute, datas):
                for owner in (owners[id] if hasattr(owners[id], '__iter__') else [owners[id]]):
                    update_id = update.create(cr, uid, {
                        'session_id' : session_id,
                        'values' : tools.ustr(row),
                        'model' : self._name,
                        'version' : versions[id] + 1,
                        'rule_id' : rule.id,
                        'sdref' : sdrefs[id],
                        'fields' : ustr_included_fields,
                        'owner' : owner,
                    }, context=context)
                    update._logger.debug("Created 'normal' update model=%s id=%d (rule sequence=%d)" % (self._name, update_id, rule.id))

            return len(ids_to_compute)
    def create(self, cr, uid, vals, *args, **kwargs):
        obj = self.pool.get('hr.analytic.timesheet')
        vals_line = {}
        obj_task = self.pool.get('project.task').browse(cr, uid, vals['task_id'])
        result = self.get_user_related_details(cr, uid, vals.get('user_id', uid))
        vals_line['name'] = '%s: %s' % (tools.ustr(obj_task.name), tools.ustr(vals['name']) or '/')
        vals_line['user_id'] = vals['user_id']
        vals_line['product_id'] = result['product_id']
        vals_line['date'] = vals['date'][:10]
        vals_line['unit_amount'] = vals['hours']
        acc_id = obj_task.project_id.category_id.id
        vals_line['account_id'] = acc_id
        res = obj.on_change_account_id(cr, uid, False, acc_id)
        if res.get('value'):
            vals_line.update(res['value'])
        vals_line['general_account_id'] = result['general_account_id']
        vals_line['journal_id'] = result['journal_id']
        vals_line['amount'] = 00.0
        vals_line['product_uom_id'] = result['product_uom_id']
        timeline_id = obj.create(cr, uid, vals_line, {})

        vals_line['amount'] = (-1) * vals['hours'] * obj.browse(cr, uid, timeline_id).product_id.standard_price
        obj.write(cr, uid,[timeline_id], vals_line, {})
        vals['hr_analytic_timesheet_id'] = timeline_id
        return super(project_work,self).create(cr, uid, vals, *args, **kwargs)
Example #11
0
    def load_from_file(self, path, dbname, key):
        class_inst = None
        expected_class = 'Parser'

        try:
            ad = os.path.abspath(os.path.join(tools.ustr(config['root_path']), u'addons'))
            mod_path_list = map(lambda m: os.path.abspath(tools.ustr(m.strip())), config['addons_path'].split(','))
            mod_path_list.append(ad)
            mod_path_list = list(set(mod_path_list))

            for mod_path in mod_path_list:
                if os.path.lexists(mod_path+os.path.sep+path.split(os.path.sep)[0]):
                    filepath=mod_path+os.path.sep+path
                    filepath = os.path.normpath(filepath)
                    sys.path.append(os.path.dirname(filepath))
                    mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1])
                    mod_name = '%s_%s_%s' % (dbname,mod_name,key)

                    if file_ext.lower() == '.py':
                        py_mod = imp.load_source(mod_name, filepath)

                    elif file_ext.lower() == '.pyc':
                        py_mod = imp.load_compiled(mod_name, filepath)

                    if expected_class in dir(py_mod):
                        class_inst = py_mod.Parser
                    return class_inst
                elif os.path.lexists(mod_path+os.path.sep+path.split(os.path.sep)[0]+'.zip'):
                    zimp = zipimport.zipimporter(mod_path+os.path.sep+path.split(os.path.sep)[0]+'.zip')
                    return zimp.load_module(path.split(os.path.sep)[0]).parser.Parser
        except SyntaxError, e:
            raise osv.except_osv(_('Syntax Error !'), e)
Example #12
0
 def name_get(self, cr, uid, ids, context=None):
     if not ids:
         return []
     if isinstance(ids, (int, long)):
         ids = [ids]
     reads = self.read(cr, uid, ids, ['name','symbol'], context=context, load='_classic_write')
     return [(x['id'], tools.ustr(x['name']) + (x['symbol'] and (' (' + tools.ustr(x['symbol']) + ')') or '')) for x in reads]
Example #13
0
def sync_log(obj, message=None, level='debug', ids=None, data=None, traceback=False):
    if not hasattr(obj, '_logger'):
        raise Exception("No _logger specified for object %s!" % obj._name)
    output = ""
    if traceback:
        output += traceback.format_exc()
    if message is None:
        previous_frame = sys._getframe(1)
        output += "%s.%s()" % (previous_frame.f_globals['__package__'], previous_frame.f_code.co_name)
    elif isinstance(message, BaseException):
        if hasattr(message, 'value'):
            output += tools.ustr(message.value)
        elif hasattr(message, 'message'):
            output += tools.ustr(message.message)
        else:
            output += tools.ustr(message)
        if output and output[-1] != "\n": output += "\n"
    else:
        output += "%s: %s" % (level.capitalize(), message)
    if ids is not None:
        output += " in model %s, ids %s\n" % (obj._name, ", ".join(ids))
    if data is not None:
        output += " in content: %s\n" % pprint.pformat(data)
    if output and output[-1] != "\n": output += "\n"
    getattr(obj._logger, level)(output[:-1])
    return output
Example #14
0
 def name_get(self, cr, uid, ids, context=None):
     if not ids:
         return []
     if isinstance(ids, (int, long)):
         ids = [ids]
     reads = self.read(cr, uid, ids, ['name','symbol'], context=context, load='_classic_write')
     return [(x['id'], tools.ustr(x['name']) + (x['symbol'] and (' (' + tools.ustr(x['symbol']) + ')') or '')) for x in reads]
Example #15
0
 def _get_source(self, cr, uid, name, tt, lang, source=None):
     if not lang:
         return ''
     if source:
         #if isinstance(source, unicode):
         #   source = source.encode('utf8')
         cr.execute('select value ' \
                 'from ir_translation ' \
                 'where lang=%s ' \
                     'and type=%s ' \
                     'and name=%s ' \
                     'and src=%s',
                 (lang or '', tt, tools.ustr(name), source))
     else:
         cr.execute('select value ' \
                 'from ir_translation ' \
                 'where lang=%s ' \
                     'and type=%s ' \
                     'and name=%s',
                 (lang or '', tt, tools.ustr(name)))
     res = cr.fetchone()
     trad = res and res[0] or ''
     if source and not trad:
         return source
     return trad
Example #16
0
    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = {}
        if vals.get('project_id', False) or vals.get('name', False):
            vals_line = {}
            hr_anlytic_timesheet = self.pool.get('hr.analytic.timesheet')
            task_obj_l = self.browse(cr, uid, ids, context=context)
            if vals.get('project_id', False):
                project_obj = self.pool.get('project.project').browse(
                    cr, uid, vals['project_id'], context=context)
                acc_id = project_obj.analytic_account_id.id

            for task_obj in task_obj_l:
                if len(task_obj.work_ids):
                    for task_work in task_obj.work_ids:
                        if not task_work.hr_analytic_timesheet_id:
                            continue
                        line_id = task_work.hr_analytic_timesheet_id.id
                        if vals.get('project_id', False):
                            vals_line['account_id'] = acc_id
                        if vals.get('name', False):
                            vals_line['name'] = '%s: %s' % (tools.ustr(
                                vals['name']), tools.ustr(task_work.name
                                                          or '/'))
                        hr_anlytic_timesheet.write(cr, uid, [line_id],
                                                   vals_line, {})
        return super(task, self).write(cr, uid, ids, vals, context)
Example #17
0
    def do_check(self, cr, uid, action, obj, context=None):
        """ @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param context: A standard dictionary for contextual values"""
        ok = super(base_action_rule, self).do_check(cr, uid, action, obj, context=context)

        if hasattr(obj, 'section_id'):
            ok = ok and (not action.trg_section_id or action.trg_section_id.id==obj.section_id.id)
        if hasattr(obj, 'categ_id'):
            ok = ok and (not action.trg_categ_id or action.trg_categ_id.id==obj.categ_id.id)

        #Cheking for history 
        regex = action.regex_history
        result_history = True
        if regex:
            res = False
            ptrn = re.compile(tools.ustr(regex))
            for history in obj.message_ids:
                _result = ptrn.search(tools.ustr(history.name))
                if _result:
                    res = True
                    break
            result_history = res
        ok = ok and (not regex or result_history)

        res_count = True
        if action.trg_max_history:
            res_count = False
            history_ids = filter(lambda x: x.history, obj.message_ids)
            if len(history_ids) <= action.trg_max_history:
                res_count = True
        ok = ok and res_count
        return ok
Example #18
0
def _process_text(self, txt):
    if not self.localcontext:
        return str2xml(txt)
    if not txt:
        return ''
    result = ''
    sps = _regex.split(txt)
    while sps:
        # This is a simple text to translate
        to_translate = tools.ustr(sps.pop(0))
        result += tools.ustr(
            self.localcontext.get('translate', lambda x: x)(to_translate))
        if sps:
            try:
                txt = None
                expr = sps.pop(0)
                txt = eval(expr, self.localcontext)
                if txt and isinstance(txt, basestring):
                    txt = tools.ustr(txt)
            except Exception:
                pass
            if isinstance(txt, basestring):
                result += txt
            elif txt and (txt is not None) and (txt is not False):
                result += ustr(txt)
    return str2xml(result)
    def get_value(self, cr, uid, model, res_id, context=None):
        """Returns a defaults-like dict with initial values for the composition
           wizard when sending an email related to the document record identified
           by ``model`` and ``res_id``.

           Overrides the default implementation to provide more default field values
           related to the corresponding CRM case.

           :param str model: model name of the document record this mail is related to.
           :param int res_id: id of the document record this mail is related to.
           :param dict context: several context values will modify the behavior
                                of the wizard, cfr. the class description.
        """
        result = super(mail_compose_message, self).get_value(cr, uid, model, res_id, context=context)
        if model in SUPPORTED_MODELS and res_id:
            model_obj = self.pool.get(model)
            data = model_obj.browse(cr, uid, res_id, context)
            user = self.pool.get("res.users").browse(cr, uid, uid, context=context)
            result.update(
                {
                    "subject": data.name or False,
                    "email_to": data.email_from or False,
                    "email_from": user.user_email or tools.config.get("email_from", False),
                    "body_text": "\n" + tools.ustr(user.signature or ""),
                    "email_cc": tools.ustr(data.email_cc or ""),
                    "model": model,
                    "res_id": res_id,
                    "subtype": "plain",
                }
            )
            if hasattr(data, "section_id"):
                result.update({"reply_to": data.section_id and data.section_id.reply_to or False})
        return result
    def write(self, cr, uid, ids, vals, context=None):
        vals_line = {}

        task = self.pool.get('project.task.work').browse(cr, uid, ids)[0]
        line_id = task.hr_analytic_timesheet_id
        # in case,if a record is deleted from timesheet,but we change it from tasks!
        list_avail_ids = self.pool.get('hr.analytic.timesheet').search(cr, uid, [])
        if line_id in list_avail_ids:
            obj = self.pool.get('hr.analytic.timesheet')
            if 'name' in vals:
                vals_line['name'] = '%s: %s' % (tools.ustr(task.task_id.name), tools.ustr(vals['name']) or '/')
            if 'user_id' in vals:
                vals_line['user_id'] = vals['user_id']
                result = self.get_user_related_details(cr, uid, vals['user_id'])
                vals_line['product_id'] = result['product_id']
                vals_line['general_account_id'] = result['general_account_id']
                vals_line['journal_id'] = result['journal_id']
                vals_line['product_uom_id'] = result['product_uom_id']
            if 'date' in vals:
                vals_line['date'] = vals['date'][:10]
            if 'hours' in vals:
                vals_line['unit_amount'] = vals['hours']
                vals_line['amount'] = (-1) * vals['hours'] * obj.browse(cr, uid, line_id).product_id.standard_price
            obj.write(cr, uid, [line_id], vals_line, {})

        return super(project_work,self).write(cr, uid, ids, vals, context)
Example #21
0
    def create_xml(self,cr, uid, ids, datas, context=None):
        pool= pooler.get_pool(cr.dbname)
        lots = pool.get('auction.lots').browse(cr, uid, ids, context=context)
        auction = lots[0].auction_id

        xml = '''<?xml version="1.0" encoding="UTF-8"?>
<report>
    <auction>
        <name>%s</name>
        <date-au1>%s</date-au1>
    </auction>''' % (toxml(auction['name']), toxml(auction['auction1']))

        i = 0
        for l in lots:
            if l['obj_price']==0:
                price_french = u'retiré'
            else:
                price_french = int_to_text(int(l['obj_price'] or 0.0))+' eur'
            i+=1
            xml += '''  <object>
        <number>%d</number>
        <obj_num>%d</obj_num>
        <lot_desc>%s</lot_desc>
        <price>%s</price>
        <obj_price>%s</obj_price>
    </object>''' % (i, l['obj_num'], ustr(toxml(l['name'])), ustr(price_french), ustr(l['obj_price'] or '/'))
        xml += '</report>'

        return xml
Example #22
0
        def process_data(field, value, fields_def):
            if not value or field not in fields_def:
                return
            if '.' not in field:
                # type datetime, date, bool, int, float
                if fields_def[field]['type'] == 'boolean':
                    value = value.lower() not in ('0', 'false', 'off','-', 'no', 'n')
                elif fields_def[field]['type'] == 'selection':
                    if impobj == 'product.product' and self._cache[dbname].get('product.product.%s.%s' % (field, value), False):
                        value = self._cache[dbname]['product.product.%s.%s' % (field, value)]
                    else:
                        for key, val in fields_def[field]['selection']:
                            if value.lower() in [tools.ustr(key).lower(), tools.ustr(val).lower()]:
                                value = key
                                if impobj == 'product.product':
                                    self._cache[dbname].setdefault('product.product.%s' % field, {})
                                    self._cache[dbname]['product.product.%s.%s' % (field, value)] = key
                                break
                elif fields_def[field]['type'] == 'date':
                    dt = DateTime.strptime(value,"%d/%m/%Y")
                    value = dt.strftime("%Y-%m-%d")
                elif fields_def[field]['type'] == 'float':
                    # remove space and unbreakable space
                    value = re.sub('[  ]+', '', value)
                    value = float(value.replace(',', '.'))
                return value

            else:
                if fields_def[field.split('.')[0]]['type'] in 'many2one':
                    return _get_obj(field, value, fields_def)

            raise osv.except_osv(_('Warning !'), _('%s does not exist')%(value,))
Example #23
0
    def default_get(self, cr, uid, fields, context=None):
        """
        This function gets default values
        """
        res = super(project_task_delegate, self).default_get(cr, uid, fields, context=context)
        if context is None:
            context = {}
        record_id = context and context.get('active_id', False) or False
        task_pool = self.pool.get('project.task')
        task = task_pool.browse(cr, uid, record_id, context=context)
        task_name =tools.ustr(task.name)

        if 'name' in fields:
            if task_name.startswith(_('CHECK: ')):
                newname = tools.ustr(task_name).replace(_('CHECK: '), '')
            else:
                newname = tools.ustr(task_name or '')
            res.update({'name': newname})
        if 'planned_hours' in fields:
            res.update({'planned_hours': task.remaining_hours or 0.0})
        if 'prefix' in fields:
            if task_name.startswith(_('CHECK: ')):
                newname = tools.ustr(task_name).replace(_('CHECK: '), '')
            else:
                newname = tools.ustr(task_name or '')
            prefix = _('CHECK: %s') % newname
            res.update({'prefix': prefix})
        if 'new_task_description' in fields:
            res.update({'new_task_description': task.description})
        return res
def _process_text(self, txt):
        if not self.localcontext:
            return str2xml(txt)
        if not txt:
            return ''
        result = ''
        sps = _regex.split(txt)
        while sps:
            # This is a simple text to translate
            to_translate = tools.ustr(sps.pop(0))
            result += tools.ustr(self.localcontext.get('translate', lambda x:x)(to_translate))
            if sps:
                try:
                    txt = None
                    expr = sps.pop(0)
                    txt = eval(expr, self.localcontext)
                    if txt and isinstance(txt, basestring):
                        txt = tools.ustr(txt)
                except Exception:
                    pass
                if isinstance(txt, basestring):
                    result += txt
                elif txt and (txt is not None) and (txt is not False):
                    result += ustr(txt)
        return str2xml(result)
Example #25
0
    def email_send(self,
                   cr,
                   uid,
                   obj,
                   emails,
                   body,
                   emailfrom=tools.config.get('email_from', False),
                   context=None):
        mail_message = self.pool.get('mail.message')
        body = self.format_mail(obj, body)
        if not emailfrom:
            if hasattr(obj,
                       'user_id') and obj.user_id and obj.user_id.user_email:
                emailfrom = obj.user_id.user_email

        name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
        emailfrom = tools.ustr(emailfrom)
        if hasattr(
                obj,
                'section_id') and obj.section_id and obj.section_id.reply_to:
            reply_to = obj.section_id.reply_to
        else:
            reply_to = emailfrom
        if not emailfrom:
            raise osv.except_osv(
                _('Error!'), _("No E-Mail Found for your Company address!"))
        return mail_message.schedule_with_attach(cr,
                                                 uid,
                                                 emailfrom,
                                                 emails,
                                                 name,
                                                 body,
                                                 model='base.action.rule',
                                                 reply_to=reply_to,
                                                 res_id=obj.id)
Example #26
0
    def do_check(self, cr, uid, action, obj, context=None):
        ok = super(base_action_rule, self).do_check(cr, uid, action, obj, context=context)

        if hasattr(obj, 'section_id'):
            ok = ok and (not action.trg_section_id or action.trg_section_id.id == obj.section_id.id)
        if hasattr(obj, 'categ_id'):
            ok = ok and (not action.trg_categ_id or action.trg_categ_id.id == obj.categ_id.id)

        #Cheking for history
        regex = action.regex_history
        if regex:
            res = False
            ptrn = re.compile(ustr(regex))
            for history in obj.message_ids:
                _result = ptrn.search(ustr(history.subject))
                if _result:
                    res = True
                    break
            ok = ok and res

        if action.trg_max_history:
            res_count = False
            history_ids = filter(lambda x: x.email_from, obj.message_ids)
            if len(history_ids) <= action.trg_max_history:
                res_count = True
            ok = ok and res_count
        return ok
Example #27
0
    def email_send(self, cr, uid, obj, emails, body, emailfrom=None, context=None):
        """ send email
            @param self: The object pointer
            @param cr: the current row, from the database cursor,
            @param uid: the current user’s ID for security checks,
            @param email: pass the emails
            @param emailfrom: Pass name the email From else False
            @param context: A standard dictionary for contextual values """

        if not emailfrom:
            emailfrom = tools.config.get('email_from', False)

        if context is None:
            context = {}

        body = self.format_mail(obj, body)
        if not emailfrom:
            if hasattr(obj, 'user_id')  and obj.user_id and obj.user_id.address_id and\
                        obj.user_id.address_id.email:
                emailfrom = obj.user_id.address_id.email

        name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
        emailfrom = tools.ustr(emailfrom)
        reply_to = emailfrom
        if not emailfrom:
            raise osv.except_osv(_('Error!'), 
                    _("No E-Mail ID Found for your Company address!"))
        return tools.email_send(emailfrom, emails, name, body, reply_to=reply_to, openobject_id=str(obj.id))
 def _render_tab(self, cr, uid, export_file, template_part, localdict):
     """Render the output of this template in a tabular format"""
     template = []
     try:
         delimiter = eval(export_file.delimiter)
     except TypeError:
         delimiter = export_file.delimiter
     # Header & Footer
     if getattr(export_file, template_part):
         template.append(self._render(cr, uid, export_file, template_part, localdict))
     # Header with fieldnames
     if template_part == 'header' and export_file.fieldnames_in_header:
         template.append(delimiter.join((tools.ustr(column.name) for column in export_file.column_ids)))
     if export_file.extension == 'xls':
         _render_func = _render_data
     else:
         _render_func = _render_unicode
     # Body
     if template_part == 'body':
         sub_objects = localdict['object']
         if export_file.refer_to_underlying_object:
             sub_objects = eval(export_file.records, localdict)
         if not isinstance(sub_objects, list):
             sub_objects = [sub_objects]
         for index, sub_object in enumerate(sub_objects):
             localdict['line_number'] = index + 1
             localdict['object'] = sub_object
             line = []
             for column in export_file.column_ids:
                 try:
                     column_value = _render_func(column.value or '', localdict)
                     if column.default_value and not column_value:
                         column_value = _render_func(column.default_value, localdict)
                     if column.column_validator:
                         validation = eval(column.column_validator, localdict)
                         if not validation:
                             try:
                                 exception_msg = _render_unicode(column.exception_msg, localdict)
                             except Exception:
                                 exception_msg = column.exception_msg
                             raise except_orm(_('Error'), exception_msg)
                     column_value = tools.ustr(column_value)
                     if column_value:
                         if column.min_width:
                             column_value = getattr(column_value, column.justify)(column.min_width, tools.ustr(column.fillchar))
                         if column.max_width:
                             column_value = column_value[:column.max_width]
                     if not column.not_string and export_file.extension != 'xls' and export_file.quotechar:
                         try:
                             quotechar = export_file.quotechar and eval(export_file.quotechar) or ''
                         except TypeError:
                             quotechar = export_file.quotechar
                         column_value = '%(quotechar)s%(column_value)s%(quotechar)s' % {
                             'column_value': quotechar and column_value.replace(quotechar, "\\" + quotechar) or column_value,
                             'quotechar': quotechar,
                         }
                     line.append(column_value)
                 except Exception, e:
                     raise except_orm(_('Error'), 'column %s: %s' % (column.name, e))
             template.append(delimiter.join(line))
Example #29
0
    def refresh(self):
        t = self.date.timetuple()
        from tools import ustr
        from locale import getlocale
        sysencoding = getlocale()[1]

        if self.mode == 'month':
            self._radio_month.set_active(True)
            self.cal_view.range = self.cal_view.RANGE_MONTH
            self._label_current.set_text(ustr(self.date.strftime('%B %Y'), sysencoding))
        elif self.mode == 'week':
            self._radio_week.set_active(True)
            self.cal_view.range = self.cal_view.RANGE_WEEK
            self._label_current.set_text(_('Week') + ' ' + self.date.strftime('%W, %Y'))
        elif self.mode == 'day':
            self._radio_day.set_active(True)
            self.cal_view.range = self.cal_view.RANGE_CUSTOM
            d1 = datetime(*t[:3])
            d2 = Calendar.util.end_of_day(d1)
            self.cal_view.active_range = self.cal_view.visible_range = d1, d2
            self._label_current.set_text(ustr(self.date.strftime('%A %x'), sysencoding))

        self.cal_view.selected = date(*list(t)[:3])
        self._small_calendar.select_month(t[1]-1,t[0])
        self._small_calendar.select_day(t[2])

        self.cal_view.refresh()
 def _get_ids(self, cr, uid, name, tt, lang, ids):
     translations = dict.fromkeys(ids, False)
     if ids:
         cr.execute('select res_id,value ' \
                 'from ir_translation ' \
                 'where lang=%s ' \
                     'and type=%s ' \
                     'and name=%s ' \
                     'and res_id IN %s',
                 (lang,tt,name,tuple(ids)))
         for res_id, value in cr.fetchall():
             translations[res_id] = value
         for res_id in translations.keys():
             res_value = translations.get(res_id, False)
             if not res_value:
                 res_model,res_field = name.split(',')
                 cr.execute('select '+res_field +' from '+ \
                     self.pool.get(res_model)._table +' where id=%s ',
                     (res_id,))
                 source = cr.fetchone()
                 source = source and source[0] or u''
                 cr.execute("""SELECT value
                       FROM ir_translation
                       WHERE lang=%s
                        AND lower(src)=lower(%s)""",
                 (lang or '', tools.ustr(source)))
                 res = cr.fetchone()
                 trad = res and res[0] or u''
                 if source and not trad:
                     trad = tools.ustr(source)
                 translations[res_id] = trad
     return translations
Example #31
0
    def email_send(self, cr, uid, obj, emails, body, emailfrom=None, context=None):
        """ send email
            @param self: The object pointer
            @param cr: the current row, from the database cursor,
            @param uid: the current user’s ID for security checks,
            @param email: pass the emails
            @param emailfrom: Pass name the email From else False
            @param context: A standard dictionary for contextual values """

        if not emailfrom:
            emailfrom = tools.config.get("email_from", False)

        if context is None:
            context = {}

        mail_message = self.pool.get("mail.message")
        body = self.format_mail(obj, body)
        if not emailfrom:
            if hasattr(obj, "user_id") and obj.user_id and obj.user_id.user_email:
                emailfrom = obj.user_id.user_email

        name = "[%d] %s" % (obj.id, tools.ustr(obj.name))
        emailfrom = tools.ustr(emailfrom)
        reply_to = emailfrom
        if not emailfrom:
            raise osv.except_osv(_("Error!"), _("No E-Mail ID Found for your Company address!"))
        return mail_message.schedule_with_attach(
            cr, uid, emailfrom, emails, name, body, model="base.action.rule", reply_to=reply_to, res_id=obj.id
        )
    def get_value(self, cr, uid, model, res_id, context=None):
        """Returns a defaults-like dict with initial values for the composition
           wizard when sending an email related to the document record identified
           by ``model`` and ``res_id``.

           Overrides the default implementation to provide more default field values
           related to the corresponding CRM case.

           :param str model: model name of the document record this mail is related to.
           :param int res_id: id of the document record this mail is related to.
           :param dict context: several context values will modify the behavior
                                of the wizard, cfr. the class description.
        """
        result = super(mail_compose_message, self).get_value(cr, uid,  model, res_id, context=context)
        if model in SUPPORTED_MODELS and res_id:
            model_obj = self.pool.get(model)
            data = model_obj.browse(cr, uid , res_id, context)
            user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
            result.update({
                    'subject' : data.name or False,
                    'email_to' : data.email_from or False,
                    'email_from' : user.user_email or tools.config.get('email_from', False),
                    'body_text' : '\n' + tools.ustr(user.signature),
                    'email_cc' : tools.ustr(data.email_cc or ''),
                    'model': model,
                    'res_id': res_id,
                    'subtype': 'plain',
                })
            if hasattr(data, 'section_id'):
                result.update({'reply_to' : data.section_id and data.section_id.reply_to or False})
        return result
Example #33
0
 def _bom_explode(self, cr, uid, bom, factor, properties=[], addthis=False, level=0, routing_id=False):
     """ Redefine native function - add product_id parameter
     Finds Products and Work Centers for related BoM for manufacturing order.
     @param bom: BoM of particular product.
     @param factor: Factor of product UoM.
     @param properties: A List of properties Ids.
     @param addthis: If BoM found then True else False.
     @param level: Depth level to find BoM lines starts from 10.
     @param product_id: ID of product, which is producing.
     @return: result: List of dictionaries containing product details.
              result2: List of dictionaries containing Work Center details.
     """
     routing_obj = self.pool.get('mrp.routing')
     factor = factor / (bom.product_efficiency or 1.0)
     factor = rounding(factor, bom.product_rounding)
     if factor < bom.product_rounding:
         factor = bom.product_rounding
     result = []
     result2 = []
     phantom = False
     if bom.type == 'phantom' and not bom.bom_lines:
         newbom = self._bom_find(cr, uid, product.id, bom.product_uom.id, properties)
         
         if newbom:
             res = self._bom_explode(cr, uid, self.browse(cr, uid, [newbom])[0], factor*1, properties, addthis=True, level=level+10, product_id=product_id)
             result = result + res[0]
             result2 = result2 + res[1]
             phantom = True
         else:
             phantom = False
     if not phantom:
         if addthis and not bom.bom_lines:
             result.append(
             {
                 'name': bom.template_id.name,
                 'template_id': bom.template_id.id,
                 'product_qty': factor * bom.product_qty,
                 'product_uom': bom.product_uom.id,
                 'product_uos_qty': bom.product_uos and bom.product_uos_qty * factor or False,
                 'product_uos': bom.product_uos and bom.product_uos.id or False,
             })
         routing = (routing_id and routing_obj.browse(cr, uid, routing_id)) or bom.routing_id or False
         if routing:
             for wc_use in routing.workcenter_lines:
                 wc = wc_use.workcenter_id
                 d, m = divmod(factor, wc_use.workcenter_id.capacity_per_cycle)
                 mult = (d + (m and 1.0 or 0.0))
                 cycle = mult * wc_use.cycle_nbr
                 result2.append({
                     'name': tools.ustr(wc_use.name) + ' - '  + tools.ustr(bom.template_id.name),
                     'workcenter_id': wc.id,
                     'sequence': level+(wc_use.sequence or 0),
                     'cycle': cycle,
                     'hour': float(wc_use.hour_nbr*mult + ((wc.time_start or 0.0)+(wc.time_stop or 0.0)+cycle*(wc.time_cycle or 0.0)) * (wc.time_efficiency or 1.0)),
                 })
         for bom2 in bom.bom_lines:
             res = self._bom_explode(cr, uid, bom2, factor, properties, addthis=True, level=level+10)
             result = result + res[0]
             result2 = result2 + res[1]
     return result, result2
    def inter_call(self, cr, uid, data, context=None):
        res = base_module_save._create_module(self, cr, uid, data, context)
        mod_obj = self.pool.get('ir.model.data')
        model_data_ids = mod_obj.search(
            cr,
            uid, [('model', '=', 'ir.ui.view'),
                  ('name', '=', 'module_create_form_view')],
            context=context)
        resource_id = mod_obj.read(cr,
                                   uid,
                                   model_data_ids,
                                   fields=['res_id'],
                                   context=context)[0]['res_id']
        context.update(res)

        return {
            'name': _('Message'),
            'context': {
                'default_module_filename': tools.ustr(res['module_filename']),
                'default_module_file': tools.ustr(res['module_file']),
            },
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'base.module.record.objects',
            'views': [(resource_id, 'form')],
            'type': 'ir.actions.act_window',
            'target': 'new',
        }
    def create(self, cr, uid, vals, *args, **kwargs):
        obj = self.pool.get("hr.analytic.timesheet")
        vals_line = {}
        obj_task = self.pool.get("project.task").browse(cr, uid, vals["task_id"])

        emp_obj = self.pool.get("hr.employee")
        emp_id = emp_obj.search(cr, uid, [("user_id", "=", vals.get("user_id", uid))])

        if not emp_id:
            raise osv.except_osv(_("Bad Configuration !"), _("No employee defined for this user. You must create one."))
        emp = self.pool.get("hr.employee").browse(cr, uid, emp_id[0])
        if not emp.product_id:
            raise osv.except_osv(
                _("Bad Configuration !"),
                _("No product defined on the related employee.\nFill in the timesheet tab of the employee form."),
            )

        if not emp.journal_id:
            raise osv.except_osv(
                _("Bad Configuration !"),
                _("No journal defined on the related employee.\nFill in the timesheet tab of the employee form."),
            )

        a = emp.product_id.product_tmpl_id.property_account_expense.id
        if not a:
            a = emp.product_id.categ_id.property_account_expense_categ.id
        vals_line["general_account_id"] = a
        vals_line["journal_id"] = emp.journal_id.id
        vals_line["name"] = "%s: %s" % (tools.ustr(obj_task.name), tools.ustr(vals["name"]) or "/")
        vals_line["user_id"] = vals["user_id"]
        vals_line["date"] = vals["date"][:10]
        vals_line["unit_amount"] = vals["hours"]
        vals_line["account_id"] = obj_task.project_id.category_id.id
        vals_line["amount"] = 00.0
        timeline_id = obj.create(cr, uid, vals_line, {})
        if emp.cost_based_on == "contract":
            sql_req = """
                SELECT -c.wage * cwt.factor_type / p.factor_days as hourlywage
                FROM hr_contract c
                  LEFT JOIN hr_employee emp on (c.employee_id=emp.id)
                  LEFT JOIN hr_contract_wage_type cwt on (cwt.id = c.wage_type_id)
                  LEFT JOIN hr_contract_wage_type_period p on (cwt.period_id = p.id)
                WHERE
                  (emp.user_id=%d) AND
                  (date_start <= %s) AND
                  (date_end IS NULL OR date_end >= %s)
                LIMIT 1
                """
            cr.execute(sql_req, (uid, vals["date"][:10], vals["date"][:10]))
            contract_info = cr.dictfetchone()
            if contract_info:
                vals_line["amount"] = -contract_info["hourlywage"] * vals["hours"]
            else:
                vals_line["amount"] = (-1) * vals["hours"] * obj.browse(cr, uid, timeline_id).product_id.standard_price
        else:
            vals_line["amount"] = (-1) * vals["hours"] * obj.browse(cr, uid, timeline_id).product_id.standard_price
        obj.write(cr, uid, [timeline_id], vals_line, {})
        vals["hr_analytic_timesheet_id"] = timeline_id
        return super(osv.osv, self).create(cr, uid, vals, *args, **kwargs)
    def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
        """
        Returns views and fields for current model where view will depend on {view_type}.
        @param cr: A database cursor
        @param user: ID of the user currently logged in
        @param view_id: list of fields, which required to read signatures
        @param view_type: defines a view type. it can be one of (form, tree, graph, calender, gantt, search, mdx)
        @param context: context arguments, like lang, time zone
        @param toolbar: contains a list of reports, wizards, and links related to current model

        @return: Returns a dict that contains definition for fields, views, and toolbars
        """
        if context is None:context = {}
        res = super(account_move_journal, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar,submenu=False)

        if context:
            if not view_id:
                return res
    
            period_pool = self.pool.get('account.period')
            journal_pool = self.pool.get('account.journal')
    
            journal_id = self._get_journal(cr, uid, context)
            period_id = self._get_period(cr, uid, context)
    
            journal = False
            if journal_id:
                journal = journal_pool.read(cr, uid, [journal_id], ['name'])[0]['name']
                journal_string = _("Journal: %s") % tools.ustr(journal)
            else:
                journal_string = _("Journal: All")
    
            period = False
            if period_id:
                period = period_pool.browse(cr, uid, [period_id], ['name'])[0]['name']
                period_string = _("Period: %s") % tools.ustr(period)
    
            open_string = _("Open")
            view = """<?xml version="1.0" encoding="utf-8"?>
            <form string="Standard entries" version="7.0">
                <group>
                    <field name="target_move"/>
                </group>
                %s: <label string="%s"/>
                %s: <label string="%s"/>
                <footer>
                    <button string="%s" name="action_open_window" default_focus="1" type="object" class="oe_highlight"/>
                    or
                    <button string="Cancel" class="oe_link" special="cancel"/>
                </footer>
            </form>""" % (_('Journal'), journal_string, _('Period'), period_string, open_string)
    
            view = etree.fromstring(view.encode('utf8'))
            xarch, xfields = self._view_look_dom_arch(cr, uid, view, view_id, context=context)
            view = xarch
            res.update({
                'arch': view
            })
        return res
Example #37
0
   def getImage(self, value, height = 50, xw=1, rotate=None, extension = "PNG"):
      """ Get an image with PIL library 
      value code barre value
      height height in pixel of the bar code
      extension image file extension"""
      from PIL import Image, ImageFont, ImageDraw
      import os
      from string import lower, upper
      
      # Get the bar code list
      bits = self.makeCode(value)
      
      # Get thee bar code with the checksum added
      code = ""
      for digit in self.EAN13:
         code += "%d"%digit
      
      # Create a new image
      position = 8
      im = Image.new("1",(len(bits)+position,height))
      
      # Load font
      ad = os.path.abspath(os.path.join(ustr(config['root_path']), u'addons'))
      mod_path_list = map(lambda m: os.path.abspath(ustr(m.strip())), config['addons_path'].split(','))
      mod_path_list.append(ad)

      for mod_path in mod_path_list:
          font_file = mod_path+os.path.sep+ \
                      "report_aeroo"+os.path.sep+"barcode"+os.path.sep+"FreeMonoBold.ttf"
          if os.path.lexists(font_file):
              font = ImageFont.truetype(font_file, fontsize)
      
      # Create drawer
      draw = ImageDraw.Draw(im)
      
      # Erase image
      draw.rectangle(((0,0),(im.size[0],im.size[1])),fill=256)
      
      # Draw first part of number
      draw.text((0, height-9), code[0], font=font, fill=0)
      
      # Draw first part of number
      draw.text((position+7, height-9), code[1:7], font=font, fill=0)
         
      # Draw second part of number
      draw.text((len(bits)/2+6+position, height-9), code[7:], font=font, fill=0)
      
      # Draw the bar codes
      for bit in range(len(bits)):
         # Draw normal bar
         if bits[bit] == '1':
            draw.rectangle(((bit+position,0),(bit+position,height-10)),fill=0)
         # Draw long bar
         elif bits[bit] == 'L':
            draw.rectangle(((bit+position,0),(bit+position,height-3)),fill=0)
            
      # Save the result image
      return im
    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = {}
        timesheet_obj = self.pool.get("hr.analytic.timesheet")
        project_obj = self.pool.get("project.project")
        uom_obj = self.pool.get("product.uom")
        result = {}

        if isinstance(ids, (long, int)):
            ids = [ids]

        for task in self.browse(cr, uid, ids, context=context):
            line_id = task.hr_analytic_timesheet_id
            if not line_id:
                # if a record is deleted from timesheet, the line_id will become
                # null because of the foreign key on-delete=set null
                continue
            vals_line = {}
            if "name" in vals:
                vals_line["name"] = "%s: %s" % (tools.ustr(task.task_id.name), tools.ustr(vals["name"]) or "/")
            if "user_id" in vals:
                vals_line["user_id"] = vals["user_id"]
                result = self.get_user_related_details(cr, uid, vals.get("user_id", task.user_id.id))
                for fld in ("product_id", "general_account_id", "journal_id", "product_uom_id"):
                    if result.get(fld, False):
                        vals_line[fld] = result[fld]

            if "date" in vals:
                vals_line["date"] = vals["date"][:10]
            if "hours" in vals:
                default_uom = self.pool.get("res.users").browse(cr, uid, uid).company_id.project_time_mode_id.id
                vals_line["unit_amount"] = vals["hours"]
                prod_id = vals_line.get("product_id", line_id.product_id.id)  # False may be set

                if result.get("product_uom_id", False) and (not result["product_uom_id"] == default_uom):
                    vals_line["unit_amount"] = uom_obj._compute_qty(
                        cr, uid, default_uom, vals["hours"], result["product_uom_id"]
                    )

                # Compute based on pricetype
                amount_unit = timesheet_obj.on_change_unit_amount(
                    cr,
                    uid,
                    line_id.id,
                    prod_id=prod_id,
                    company_id=False,
                    unit_amount=vals_line["unit_amount"],
                    unit=False,
                    journal_id=vals_line["journal_id"],
                    context=context,
                )

                if amount_unit and "amount" in amount_unit.get("value", {}):
                    vals_line["amount"] = amount_unit["value"]["amount"]

            self.pool.get("hr.analytic.timesheet").write(cr, uid, [line_id.id], vals_line, context=context)

        return super(project_work, self).write(cr, uid, ids, vals, context)
Example #39
0
    def create(self, cr, uid, vals, *args, **kwargs):
        obj_timesheet = self.pool.get('account.analytic.line')
        project_obj = self.pool.get('project.project')
        task_obj = self.pool.get('project.task')
        journal_obj = self.pool.get('account.analytic.journal')
        account_obj = self.pool.get('account.account')
        product_obj = self.pool.get('product.product')
        unit_obj = self.pool.get('product.uom')

        vals_line = {}
        context = kwargs.get('context', {})
        if not context.get('no_analytic_entry', False):
            journal_ids = journal_obj.search(cr, uid, [('code', '=', 'EXP')])
            if not journal_ids:
                raise osv.except_osv(
                    _('Error!'),
                    _('You must create an analytic journal with code EXP for extraordinary expenses'
                      ))
            account_ids = False
            parent_account_ids = account_obj.search(cr, uid,
                                                    [('code', '=', '678')])
            if parent_account_ids:
                account_ids = account_obj.search(
                    cr, uid, [('parent_id', '=', parent_account_ids[0])])
            if not account_ids and not account_ids[0]:
                raise osv.except_osv(
                    _('Error!'),
                    _('Expense account not found for company, please install the accounting plan for that company'
                      ))

            obj_task = task_obj.browse(cr, uid, vals['task_id'])
            vals_line['name'] = '%s: %s' % (ustr(
                obj_task.name_get()[0][1]), ustr(vals.get('name', '')) or '/')
            vals_line['unit_amount'] = 1
            #Poner a unidades
            unit_ids = unit_obj.search(cr, uid, [('name', '=', 'PCE')])
            if unit_ids:
                vals_line['product_uom_id'] = unit_ids[0]

            acc_id = obj_task.project_id and obj_task.project_id.analytic_account_id.id or False
            if acc_id:
                vals_line['account_id'] = acc_id
                res = obj_timesheet.on_change_account_id(
                    cr, uid, False, acc_id)
                if res.get('value'):
                    vals_line.update(res['value'])
                vals_line['general_account_id'] = account_ids[0]
                if journal_ids:
                    vals_line['journal_id'] = journal_ids[0]
                vals_line['amount'] = -(vals.get('amount', 0.0))

                timeline_id = obj_timesheet.create(cr,
                                                   uid,
                                                   vals=vals_line,
                                                   context=context)
                vals['account_analytic_line_id'] = timeline_id
        return super(project_task_extraordinary_expenses,
                     self).create(cr, uid, vals, *args, **kwargs)
Example #40
0
 def _bom_explode(self, cr, uid, bom, factor, properties=[], addthis=False, level=0):
     """ Finds Products and Workcenters for related BoM for manufacturing order.
     @param bom: BoM of particular product.
     @param factor: Factor of product UoM.
     @param properties: A List of properties Ids.
     @param addthis: If BoM found then True else False.
     @param level: Depth level to find BoM lines starts from 10.
     @return: result: List of dictionaries containing product details.
              result2: List of dictionaries containing workcenter details.
     """
     factor = factor / (bom.product_efficiency or 1.0)
     factor = rounding(factor, bom.product_rounding)
     if factor < bom.product_rounding:
         factor = bom.product_rounding
     result = []
     result2 = []
     phantom = False
     if bom.type == 'phantom' and not bom.bom_lines:
         newbom = self._bom_find(cr, uid, bom.product_id.id, bom.product_uom.id, properties)
         if newbom:
             res = self._bom_explode(cr, uid, self.browse(cr, uid, [newbom])[0], factor*bom.product_qty, properties, addthis=True, level=level+10)
             result = result + res[0]
             result2 = result2 + res[1]
             phantom = True
         else:
             phantom = False
     if not phantom:
         if addthis and not bom.bom_lines:
             result.append(
             {
                 'name': bom.product_id.name,
                 'product_id': bom.product_id.id,
                 'consumed_on': bom.consumed_on.id,
                 'product_qty': bom.product_qty * factor,
                 'product_uom': bom.product_uom.id,
                 'product_uos_qty': bom.product_uos and bom.product_uos_qty * factor or False,
                 'product_uos': bom.product_uos and bom.product_uos.id or False,
             })
         if bom.routing_id:
             for wc_use in bom.routing_id.workcenter_lines:
                 wc = wc_use.workcenter_id
                 d, m = divmod(factor, wc_use.workcenter_id.capacity_per_cycle)
                 mult = (d + (m and 1.0 or 0.0))
                 cycle = mult * wc_use.cycle_nbr
                 result2.append({
                     'name': tools.ustr(wc_use.name) + ' - '  + tools.ustr(bom.product_id.name),
                     'workcenter_id': wc.id,
                     'sequence': level+(wc_use.sequence or 0),
                     'cycle': cycle,
                     'hour': float(wc_use.hour_nbr*mult + ((wc.time_start or 0.0)+(wc.time_stop or 0.0)+cycle*(wc.time_cycle or 0.0)) * (wc.time_efficiency or 1.0)),
                 })
         for bom2 in bom.bom_lines:
             res = self._bom_explode(cr, uid, bom2, factor, properties, addthis=True, level=level+10)
             result = result + res[0]
             result2 = result2 + res[1]
     return result, result2
Example #41
0
 def _generate_mailbox_item_from_template(self, cursor, user, template, record_id, context=None):
     """
     Generates an email from the template for
     record record_id of target object
     
     @param cursor: Database Cursor
     @param user: ID of User
     @param template: Browse record of
                      template
     @param record_id: ID of the target model
                       for which this mail has
                       to be generated
     @return: ID of created object
     """
     if context is None:
         context = {}
     # If account to send from is in context select it, else use enforced account
     if "account_id" in context.keys():
         from_account = self.pool.get("poweremail.core_accounts").read(
             cursor, user, context.get("account_id"), ["name", "email_id"], context
         )
     else:
         from_account = {
             "id": template.enforce_from_account.id,
             "name": template.enforce_from_account.name,
             "email_id": template.enforce_from_account.email_id,
         }
     lang = get_value(cursor, user, record_id, template.lang, template, context)
     if lang:
         ctx = context.copy()
         ctx.update({"lang": lang})
         template = self.browse(cursor, user, template.id, context=ctx)
     mailbox_values = {
         "pem_from": tools.ustr(from_account["name"]) + "<" + tools.ustr(from_account["email_id"]) + ">",
         "pem_to": get_value(cursor, user, record_id, template.def_to, template, context),
         "pem_cc": get_value(cursor, user, record_id, template.def_cc, template, context),
         "pem_bcc": get_value(cursor, user, record_id, template.def_bcc, template, context),
         "pem_subject": get_value(cursor, user, record_id, template.def_subject, template, context),
         "pem_body_text": get_value(cursor, user, record_id, template.def_body_text, template, context),
         "pem_body_html": get_value(cursor, user, record_id, template.def_body_html, template, context),
         "pem_account_id": from_account["id"],
         # This is a mandatory field when automatic emails are sent
         "state": "na",
         "folder": "drafts",
         "mail_type": "multipart/alternative",
     }
     # Use signatures if allowed
     if template.use_sign:
         sign = self.pool.get("res.users").read(cursor, user, user, ["signature"], context)["signature"]
         if mailbox_values["pem_body_text"]:
             mailbox_values["pem_body_text"] += sign
         if mailbox_values["pem_body_html"]:
             mailbox_values["pem_body_html"] += sign
     mailbox_id = self.pool.get("poweremail.mailbox").create(cursor, user, mailbox_values, context)
     return mailbox_id
Example #42
0
 def compat_string(self):
     """Get the string that v5, xml-rpc1 exceptions would need
     """
     if self.args[2] == 'exception':
         ret = tools.ustr(self.args[0])
         if self.args[1]:
             ret += '\n' + tools.ustr(self.args[1])
         return ret
     else:
         return "%s -- %s\n\n%s" % (self.args[2], tools.ustr(
             self.args[0]), tools.ustr(self.args[1]))
Example #43
0
    def name_get(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
#        We can use the following line,if we want to restrict this name_get for company setup only
#        But, its better to show currencies as name(Code).
        if not len(ids):
            return []
        if isinstance(ids, (int, long)):
            ids = [ids]
        reads = self.read(cr, uid, ids, ['name','symbol'], context, load='_classic_write')
        return [(x['id'], tools.ustr(x['name']) + (x['symbol'] and (' (' + tools.ustr(x['symbol']) + ')') or '')) for x in reads]
Example #44
0
 def login(self, db, login, password):
     result = super(res_users, self).login(db, login, password)
     if result:
         return result
     else:
         with utils.cursor(db) as cr:
             cr.execute(
                 'UPDATE res_users SET date=now() WHERE login=%s AND openid_key=%s AND active=%s RETURNING id',
                 (tools.ustr(login), tools.ustr(password), True))
             res = cr.fetchone()
             cr.commit()
             return res[0] if res else False
Example #45
0
    def _get_source(self, cr, uid, name, types, lang, source=None):
        """
        Returns the translation for the given combination of name, type, language
        and source. All values passed to this method should be unicode (not byte strings),
        especially ``source``.

        :param name: identification of the term to translate, such as field name (optional if source is passed)
        :param types: single string defining type of term to translate (see ``type`` field on ir.translation), or sequence of allowed types (strings)
        :param lang: language code of the desired translation
        :param source: optional source term to translate (should be unicode)
        :rtype: unicode
        :return: the request translation, or an empty unicode string if no translation was
                 found and `source` was not passed
        """
        # FIXME: should assert that `source` is unicode and fix all callers to always pass unicode
        # so we can remove the string encoding/decoding.
        if not lang:
            return u''
        if isinstance(types, basestring):
            types = [types,]
        else:
            types = list(types)
        if source and not name:
            cr.execute_prepared('ir_trans_get_src0',
                    'SELECT value ' \
                    'FROM ir_translation ' \
                    'WHERE lang=%s ' \
                        'AND type = ANY(%s) ' \
                        'AND src=%s ' \
                        "AND value IS NOT NULL AND value <> '' ",
                    (lang, types, source), debug=self._debug)
        elif source:
            cr.execute_prepared('ir_trans_get_src1',
                    'SELECT value ' \
                    'FROM ir_translation ' \
                    'WHERE lang=%s ' \
                        'AND type = ANY(%s) ' \
                        'AND name=%s ' \
                        'AND src=%s ' \
                        "AND value IS NOT NULL AND value <> '' ",
                    (lang, types, tools.ustr(name), source), debug=self._debug)
        else:
            cr.execute_prepared('ir_trans_get_src2',
                    'SELECT value ' \
                    'FROM ir_translation ' \
                    'WHERE lang=%s ' \
                        'AND type = ANY(%s) ' \
                        'AND name=%s ' \
                        "AND value IS NOT NULL AND value <> '' ",
                    (lang, types, tools.ustr(name)), debug=self._debug)
        res = cr.fetchone()
        trad = res and res[0] or u''
        return trad
Example #46
0
 def _name_get_full_path(self, cursor, uid, ids, fields, arg, context=None):
     result = {}
     for category in self.browse(cursor, uid, ids):
         full_path = ''
         current_category = category
         while current_category:
             if full_path == '':
                 full_path = ustr(current_category.name)
             else:
                 full_path = ustr(current_category.name) + ' / ' + full_path
             current_category = current_category.parent_id or False
         result[category.id] = full_path
     return result
Example #47
0
 def login(self, db, login, password):
     if not password:
         return False
     cr = pooler.get_db(db).cursor()
     cr.execute(
         'select id from res_users where login=%s and password=%s and active',
         (tools.ustr(login), tools.ustr(password)))
     res = cr.fetchone()
     cr.close()
     if res:
         return res[0]
     else:
         return False
Example #48
0
 def do_check(self, cr, uid, action, obj, context=None):
     """ check Action
         @param self: The object pointer
         @param cr: the current row, from the database cursor,
         @param uid: the current user’s ID for security checks,
         @param context: A standard dictionary for contextual values """
     if context is None:
         context = {}
     ok = True
     if action.filter_id:
         if action.model_id.model == action.filter_id.model_id:
             context.update(eval(action.filter_id.context))
             obj_ids = obj._table.search(cr,
                                         uid,
                                         eval(action.filter_id.domain),
                                         context=context)
             if not obj.id in obj_ids:
                 ok = False
         else:
             ok = False
     if 'user_id' in obj._model._all_columns:
         ok = ok and (not action.trg_user_id.id
                      or action.trg_user_id.id == obj.user_id.id)
     if 'partner_id' in obj._model._all_columns:
         ok = ok and (not action.trg_partner_id.id
                      or action.trg_partner_id.id == obj.partner_id.id)
         ok = ok and (
             not action.trg_partner_categ_id.id or
             (obj.partner_id.id and (action.trg_partner_categ_id.id in map(
                 lambda x: x.id, obj.partner_id.category_id or []))))
     state_to = context.get('state_to', False)
     state = 'state' in obj._model._all_columns
     if state:
         ok = ok and (not action.trg_state_from
                      or action.trg_state_from == state)
     if state_to:
         ok = ok and (not action.trg_state_to
                      or action.trg_state_to == state_to)
     elif action.trg_state_to:
         ok = False
     reg_name = action.regex_name
     result_name = True
     if reg_name:
         ptrn = re.compile(ustr(reg_name))
         _result = ptrn.search(ustr(obj.name))
         if not _result:
             result_name = False
     regex_n = not reg_name or result_name
     ok = ok and regex_n
     return ok
Example #49
0
    def write(self, cr, uid, ids, vals, context=None):
        if context is None:
            context = {}
        timesheet_obj = self.pool['hr.analytic.timesheet']
        project_obj = self.pool['project.project']
        uom_obj = self.pool['product.uom']
        result = {}
        
        if isinstance(ids, (long, int)):
            ids = [ids,]

        for task in self.browse(cr, uid, ids, context=context):
            line_id = task.hr_analytic_timesheet_id
            if not line_id:
                # if a record is deleted from timesheet, the line_id will become
                # null because of the foreign key on-delete=set null
                continue
            vals_line = {}
            if 'name' in vals:
                vals_line['name'] = '%s: %s' % (tools.ustr(task.task_id.name), tools.ustr(vals['name'] or '/'))
            if 'user_id' in vals:
                vals_line['user_id'] = vals['user_id']
                        
            if 'date' in vals:
                vals_line['date'] = vals['date'][:10]
            if 'hours' in vals:
                default_uom = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id.id
                vals_line['unit_amount'] = vals['hours']
                prod_id = vals_line.get('product_id', line_id.product_id.id) # False may be set
                result = self.get_user_related_details(cr, uid, vals.get('user_id', task.user_id.id))
                for fld in ('product_id', 'general_account_id', 'journal_id', 'product_uom_id'):
                    if result.get(fld, False):
                        vals_line[fld] = result[fld]

                if result.get('product_uom_id',False) and (not result['product_uom_id'] == default_uom):
                    vals_line['unit_amount'] = uom_obj._compute_qty(cr, uid, default_uom, vals['hours'], result['product_uom_id'])
                    
                # Compute based on pricetype
                amount_unit = timesheet_obj.on_change_unit_amount(cr, uid, line_id.id,
                    prod_id=prod_id, company_id=False,
                    unit_amount=vals_line['unit_amount'], unit=False, journal_id=vals_line['journal_id'], context=context)

                if amount_unit and 'amount' in amount_unit.get('value',{}):
                    vals_line['amount'] = amount_unit['value']['amount']

            #workaround for lp:1023047
            if vals_line:
                self.pool.get('hr.analytic.timesheet').write(cr, uid, [line_id.id], vals_line, context=context)
            
        return super(project_work,self).write(cr, uid, ids, vals, context)
    def email_send(self,
                   cr,
                   uid,
                   obj,
                   emails,
                   body,
                   emailfrom=tools.config.get('email_from', False),
                   context=None):
        mail_message = self.pool.get('mail.message')
        body = self.format_mail(obj, body)
        if not emailfrom:
            if hasattr(obj,
                       'user_id') and obj.user_id and obj.user_id.user_email:
                emailfrom = obj.user_id.user_email

        ###dreis: customizable Subject line, specified in the first line of the "body"
        # name = '[%d] %s' % (obj.id, tools.ustr(obj.name))

#
        subject = body.splitlines()[0]  #get first line of the body
        if subject.startswith('Subject:'):
            name = subject.split(':', 1)[1].lstrip(
            )  #subject is text after ':'; strip leading spaces
            body = '\n'.join(
                body.splitlines()[1:])  #body without the first line
        else:
            name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
        ###dreis end

        emailfrom = tools.ustr(emailfrom)
        if hasattr(
                obj,
                'section_id') and obj.section_id and obj.section_id.reply_to:
            reply_to = obj.section_id.reply_to
        else:
            reply_to = emailfrom
        if not emailfrom:
            raise osv.except_osv(
                _('Error!'), _("No E-Mail ID Found for your Company address!"))
        #rint "...email_send:", emails ###, name ###reis###
        return mail_message.schedule_with_attach(cr,
                                                 uid,
                                                 emailfrom,
                                                 emails,
                                                 name,
                                                 body,
                                                 model='base.action.rule',
                                                 reply_to=reply_to,
                                                 res_id=obj.id)
    def create(self, cr, uid, values, context=None):
        """
        #TODO make doc string
        Comment this
        """
        if context is None:
            context = {}
        if context.get('model', False):
            obj_timesheet = self.pool.get('hr.analytic.timesheet')
            case_obj = self.pool.get(context['model'])
            uom_obj = self.pool.get('product.uom')

            values_line = {}
            obj_case = case_obj.browse(cr, uid, values['res_id'])
            result = self.get_user_related_details(cr, uid, values.get('user_id', uid))
            values_line['name'] = '%s: %s' % (ustr(obj_case.name), ustr(values['name']) or '/')
            values_line['user_id'] = values['user_id']
            values_line['product_id'] = result['product_id']
            values_line['date'] = values['date'][:10]

            #calculate quantity based on employee's product's uom 
            values_line['unit_amount'] = values['hours']

            default_uom = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id.id
            if result['product_uom_id'] != default_uom:
                values_line['unit_amount'] = uom_obj._compute_qty(cr, uid, default_uom, values['hours'], result['product_uom_id'])
            acc_id = values_line['account_id'] = values['analytic_account_id']
            res = obj_timesheet.on_change_account_id(cr, uid, False, acc_id)
            if res.get('value'):
                values_line.update(res['value'])
            values_line['general_account_id'] = result['general_account_id']
            values_line['journal_id'] = result['journal_id']
            values_line['amount'] = 0.0
            values_line['product_uom_id'] = result['product_uom_id']
            amount = values_line['unit_amount']
            prod_id = values_line['product_id']
            unit = False
            timeline_id = obj_timesheet.create(cr, uid, values_line, context=context)

            # Compute based on pricetype
            amount_unit = obj_timesheet.on_change_unit_amount(cr, uid, timeline_id,
                prod_id, amount, False, unit, values_line['journal_id'], context=context)
            if amount_unit and 'amount' in amount_unit.get('value',{}):
                updv = { 'amount': amount_unit['value']['amount'] }
                obj_timesheet.write(cr, uid, [timeline_id], updv, context=context)
            values['hr_analytic_timesheet_id'] = timeline_id
            values['model'] = context['model']
        return super(crm_analytic_timesheet, self).create(cr, uid, values, context=context)
Example #52
0
 def get_client_info(self):
     try:
         rev_id = os.popen('bzr revision-info').read()
         if not rev_id:
             rev_id = 'Bazaar Package not Found !'
     except Exception, e:
         rev_id = 'Exception: %s\n' % (tools.ustr(e))
Example #53
0
 def email_send(self, cr, uid, obj, emails, body, emailfrom=tools.config.get('email_from', False), context=None):
     body = self.format_mail(obj, body)
     if not emailfrom:
         if hasattr(obj, 'user_id')  and obj.user_id and obj.user_id.address_id and obj.user_id.address_id.email:
             emailfrom = obj.user_id.address_id.email
         
     name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
     emailfrom = tools.ustr(emailfrom)
     if hasattr(obj, 'section_id') and obj.section_id and obj.section_id.reply_to:
         reply_to = obj.section_id.reply_to
     else:
         reply_to = emailfrom
     if not emailfrom:
         raise osv.except_osv(_('Error!'), 
                 _("No E-Mail ID Found for your Company address!"))
     return tools.email_send(emailfrom, emails, name, body, reply_to=reply_to, openobject_id=str(obj.id))
Example #54
0
    def emit(self, record):
        ct = threading.current_thread()
        ct_db = getattr(ct, 'dbname', None)
        dbname = tools.config['log_db'] if tools.config[
            'log_db'] and tools.config['log_db'] != '%d' else ct_db
        if not dbname:
            return
        with tools.ignore(Exception), tools.mute_logger(
                'openerp.sql_db'), sql_db.db_connect(
                    dbname, allow_uri=True).cursor() as cr:
            msg = tools.ustr(record.msg)
            if record.args:
                msg = msg % record.args
            traceback = getattr(record, 'exc_text', '')
            if traceback:
                msg = "%s\n%s" % (msg, traceback)
            # we do not use record.levelname because it may have been changed by ColoredFormatter.
            levelname = logging.getLevelName(record.levelno)

            val = ('server', ct_db, record.name, levelname, msg,
                   record.pathname[len(path_prefix) + 1:], record.lineno,
                   record.funcName)
            cr.execute(
                """
                INSERT INTO ir_logging(create_date, type, dbname, name, level, message, path, line, func)
                VALUES (NOW() at time zone 'UTC', %s, %s, %s, %s, %s, %s, %s, %s)
            """, val)
Example #55
0
        def go(id, uid, ids, datas, context):
            cr = pooler.get_db(db).cursor()
            import traceback
            import sys
            try:
                obj = netsvc.LocalService('report.'+object)
                (result, format) = obj.create(cr, uid, ids, datas, context)
                if not result:
                    tb = sys.exc_info()
                    self._reports[id]['exception'] = ExceptionWithTraceback('RML is not available at specified location or not enough data to print!', tb)
                self._reports[id]['result'] = result
                self._reports[id]['format'] = format
                self._reports[id]['state'] = True
            except Exception, exception:

                tb = sys.exc_info()
                tb_s = "".join(traceback.format_exception(*tb))
                logger = netsvc.Logger()
                logger.notifyChannel('web-services', netsvc.LOG_ERROR,
                        'Exception: %s\n%s' % (str(exception), tb_s))
                if hasattr(exception, 'name') and hasattr(exception, 'value'):
                    self._reports[id]['exception'] = ExceptionWithTraceback(tools.ustr(exception.name), tools.ustr(exception.value))
                else:
                    self._reports[id]['exception'] = ExceptionWithTraceback(tools.exception_to_unicode(exception), tb)
                self._reports[id]['state'] = True
    def save_as_template(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        email_template = self.pool.get('email.template')
        model_pool = self.pool.get('ir.model')
        for record in self.browse(cr, uid, ids, context=context):
            model = record.model or context.get('active_model')
            model_ids = model_pool.search(cr, uid, [('model', '=', model)])
            model_id = model_ids and model_ids[0] or False
            model_name = ''
            if model_id:
                model_name = model_pool.browse(cr, uid, model_id, context=context).name
            template_name = "%s: %s" % (model_name, tools.ustr(record.subject))
            values = {
                'name': template_name,
                'email_from': record.email_from or False,
                'subject': record.subject or False,
                'body_text': record.body_text or False,
                'email_to': record.email_to or False,
                'email_cc': record.email_cc or False,
                'email_bcc': record.email_bcc or False,
                'reply_to': record.reply_to or False,
                'model_id': model_id or False,
                'attachment_ids': [(6, 0, [att.id for att in record.attachment_ids])]
            }
            template_id = email_template.create(cr, uid, values, context=context)
            record.write({'template_id': template_id,
                          'use_template': True})

        # _reopen same wizard screen with new template preselected
        return False