Esempio n. 1
0
 def confirm(cls, sales):
     Warning = Pool().get('res.user.warning')
     # make sure noone is able to confirm a sale with shipment or invoice methods we do not want
     for sale in sales:
         if sale.shipment_method != 'order':
             raise UserError('Liefermethode ungültig')
         if sale.invoice_method != 'shipment':
             raise UserError('Rechnungmethode ungültig')
         if not sale.payment_term:
             raise UserError('Keine Zahlungsbedingungen angegeben!')
     # first check if we have a line without product and issue a warning
     warning_name = 'saleline_noproduct,%s' % cls
     need_fixing = []
     for sale in sales:
         if not sale.party.pn_name or len(sale.party.pn_name.strip()) < 1:
             raise UserError(
                 'Verkaufsparteien müssen einen PN Namen zugewiesen haben.')
         for line in sale.lines:
             if not line.product:
                 need_fixing.append(line.rec_name)
     if Warning.check(warning_name):
         if need_fixing:
             msg = 'Position ohne Produkt gefunden!!'
             #msg += '\n'.join(need_fixing)
             raise UserWarning(warning_name, msg)
     # check if we already have an order fromt his customer for this date with the same sale_date_extra
     warning_sale_date_extra = 'sale_date_extra,%s' % cls
     warn_sale_date = []
     for sale in sales:
         others = Pool().get('sale.sale').search([
             ('sale_folder_postfix', '=', sale.sale_folder_postfix),
             ('party', '=', sale.party),
             ('sale_date', '=', sale.sale_date),
             ('number', '!=', sale.number),
         ])
         for s in others:
             warn_sale_date.append(s.number)
     if Warning.check(warning_sale_date_extra):
         if warn_sale_date:
             msg = 'Verkauf für diesen Kunden mit gleichem Bestelldatum und Bestellordner Zusatz existiert bereits:'
             msg += '\n'.join(warn_sale_date)
             raise UserWarning(warning_sale_date_extra, msg)
     # give the users a warning before actually confirming an order and creating shipments,..
     confirm_warning = 'sale_confirm,%s' % cls
     if Warning.check(confirm_warning):
         raise UserWarning(
             confirm_warning,
             'Bestätigen des Verkaufs erzeugt einen Lieferschein - fortfahren?'
         )
     super(Sale, cls).confirm(sales)
Esempio n. 2
0
    def raise_user_warning(cls, warning_name, warning,
            warning_args=None, warning_description='',
            warning_description_args=None):
        '''
        Raise an exception that will be displayed as a warning message
        in the client, if the user has not yet bypassed it.

        :param warning_name: the unique warning name
        :param warning: the key of the dictionary _error_messages used
            for warning message
        :param warning_args: the arguments that will be used for
            "%"-based substitution
        :param warning_description: the key of the dictionary
            _error_messages used for warning description
        :param warning_description_args: the arguments that will be used
            for "%"-based substitution
        '''
        Warning_ = Pool().get('res.user.warning')
        if Warning_.check(warning_name):
            if warning_description:
                warning, warning_description = cls.raise_user_error(warning,
                        error_args=warning_args,
                        error_description=warning_description,
                        error_description_args=warning_description_args,
                        raise_exception=False)
                raise UserWarning(warning_name, warning, warning_description)
            else:
                warning = cls.raise_user_error(warning,
                        error_args=warning_args, raise_exception=False)
                raise UserWarning(warning_name, warning)
Esempio n. 3
0
    def raise_user_warning(cls,
                           warning_name,
                           warning,
                           warning_args=None,
                           warning_description='',
                           warning_description_args=None):
        '''
        Raise an exception that will be displayed as a warning message
        in the client, if the user has not yet bypassed it.

        :param warning_name: the unique warning name
        :param warning: the key of the dictionary _error_messages used
            for warning message
        :param warning_args: the arguments that will be used for
            "%"-based substitution
        :param warning_description: the key of the dictionary
            _error_messages used for warning description
        :param warning_description_args: the arguments that will be used
            for "%"-based substitution
        '''
        Warning_ = Pool().get('res.user.warning')
        if Warning_.check(warning_name):
            if warning_description:
                warning, warning_description = cls.raise_user_error(
                    warning,
                    error_args=warning_args,
                    error_description=warning_description,
                    error_description_args=warning_description_args,
                    raise_exception=False)
                raise UserWarning(warning_name, warning, warning_description)
            else:
                warning = cls.raise_user_error(warning,
                                               error_args=warning_args,
                                               raise_exception=False)
                raise UserWarning(warning_name, warning)
    def delete(self, ids):
        '''
        Delete records.

        :param ids: a list of ids or an id
        :return: True if succeed
        '''
        model_access_obj = Pool().get('ir.model.access')

        model_access_obj.check(self._name, 'delete')
        if not self.check_xml_record(ids, None):
            self.raise_user_error('delete_xml_record',
                    error_description='xml_record_desc')

        # Clean cursor cache
        for cache in Transaction().cursor.cache.values():
            for cache in (cache, cache.get('_language_cache', {}).values()):
                if self._name in cache:
                    if isinstance(ids, (int, long)):
                        ids = [ids]
                    for i in ids:
                        if i in cache[self._name]:
                            del cache[self._name][i]
        return False
Esempio n. 5
0
    def copy_from(self, from_table):
        Warning = Pool().get('res.user.warning')

        fields = {x.name for x in self.fields}
        from_fields = {x.name for x in from_table.fields}
        missing = sorted(list(from_fields - fields))

        existing = fields & from_fields
        fields = {}
        for field in self.fields:
            if field.name in existing:
                fields[field.name] = field.type

        different_types = []
        for field in from_table.fields:
            if field.name in existing:
                if (FIELD_TYPE_TRYTON[field.type] !=
                        FIELD_TYPE_TRYTON[fields[field.name]]):
                    different_types.append(
                        "%s (%s -> %s)" %
                        (field.name, field.type, fields[field.name]))
                    existing.remove(field.name)

        if missing or different_types:
            message = ['- %s' % x for x in (missing + different_types)]
            key = 'shine_copy_from_warning.%s.%s' % (self.name, from_table.id),
            if Warning.check(key):
                raise UserWarning(
                    key,
                    gettext('shine.copy_from_warning',
                            fields='\n'.join(message),
                            from_table=from_table.rec_name,
                            table=self.rec_name))

        if not existing:
            return

        existing = sorted(list(existing))
        table = sql.Table(from_table.name)
        subquery = table.select()
        subquery.columns = [sql.Column(table, x) for x in existing]
        table = sql.Table(self.name)
        query = table.insert([sql.Column(table, x) for x in existing],
                             subquery)

        cursor = Transaction().connection.cursor()
        cursor.execute(*query)
Esempio n. 6
0
 def check_diagnosis_length(cls, details):
     Warning = Pool().get('res.user.warning')
     for detail in details:
         if not detail.template or not detail.template.diagnosis_length:
             continue
         diagnosis_length = detail.template.diagnosis_length
         for sample in detail.samples:
             if not sample.diagnosis:
                 continue
             if len(sample.diagnosis) > diagnosis_length:
                 key = 'lims_diagnosis_length@%s' % sample.id
                 if Warning.check(key):
                     raise UserWarning(
                         key,
                         gettext(
                             'lims_diagnosis.msg_invalid_diagnosis_length',
                             length=str(len(sample.diagnosis)),
                             allowed=str(diagnosis_length)))
Esempio n. 7
0
    def set_totp_secret(cls, users, name, value):
        Warning = Pool().get('res.user.warning')

        if value:
            try:
                key = _TOTPFactory(key=value).to_json()
            except BinAsciiError:
                raise TOTPInvalidSecretError(
                    gettext('authentication_totp.msg_user_invalid_totp_secret',
                            login=users[0].login))
        else:
            key = None

        if cls._totp_admin() and cls._totp_key_length_too_short(key):
            warning_name = 'authentication_totp.key_too_short'
            if Warning.check(warning_name):
                raise TOTPKeyTooShortWarning(
                    warning_name,
                    gettext('authentication_totp.msg_user_totp_too_short',
                            login=users[0].login))

        cls.write(list(users), {
            'totp_key': key,
        })
Esempio n. 8
0
class WfsRequest(object):
    def __init__(self):
        self.tmpl_loader = TemplateLoader(
            os.path.join(os.path.dirname(__file__), 'templates'),
            auto_reload=True,
            default_class=MarkupTemplate,
        )
        WfsConf = Pool().get('wfs.conf')
        conf = WfsConf.search([])

        if len(conf) == 0:
            self.show_non_geo = False
            self.default_geo = False
        else:
            self.show_non_geo = conf[0].show_non_geo
            self.default_geo = conf[0].default_geo

        self.url = WfsConf.get_url()
        self.model_access = Pool().get('ir.model.access')
        self.field_access = Pool().get('ir.model.field.access')

    def access_check(self, model, field=None, mode='read', raise_exception=True):
        allowed = True
        try:
            allowed &= self.model_access.check(model, mode, raise_exception=False)
            if field is not None:
                allowed &= self.field_access.check(model, [field], mode, raise_exception=False)
        except:
            allowed = False

        if not allowed and raise_exception:
            raise Exception('Permission denied')
        return allowed

    def _parse_args(self, **kw):
        _kw = {}
        for arg, val in kw.iteritems():
            if isinstance(val, str):
                _kw[arg.lower()] = unquote(val)

        if 'acceptversions' in _kw:
            version = _kw.pop('acceptversions')
            if WFS_VERSION not in version.split(','):
                raise Exception('Unsupported version, server version %s, client version %s' % (WFS_VERSION, version))

        if 'version' in _kw:
            self.version = _kw.pop('version')
            if self.version.split('.') > WFS_VERSION.split('.'):
                logger.warning('Wfs version of client is superior than our version (1.0.0)')
        else:
            self.version = ''

        service = _kw.pop('service', 'wfs').lower()
        if service != 'wfs':
            raise Exception('Invalid service %s, expected WFS' % service)

        if 'srsname' in _kw:
            _kw['srsname'] = int(_kw['srsname'].split(':')[1])
        return _kw

    def handle(self, **kw):
        _kw = self._parse_args(**kw)
        request = _kw.pop('request').lower()

        if request in WFS_REQUESTS and hasattr(self, request):
            return getattr(self, request)(**_kw)
        return self.getcapabilities()

    def getcapabilities(self, bbox=[], srsname=0, **kw):
        Field = Pool().get('ir.model.field')
        features = []
        models = []
        if bbox != []:
            bbox = [float(nbr) for nbr in bbox.split(',')]

        domain = ['OR'] + [[('ttype', '=', geo_type)] for geo_type in GEO_TYPES]
        fields = Field.search(domain)
        for field in fields:
            model = field.model.model
            if not self.access_check(model, raise_exception=False):
                continue
            Model = Pool().get(model)
            records = Model.search([], limit=1)

            # Check the table contains records in the bbox
            models.append(model)
            cursor = Transaction().cursor
            table = model.replace('.', '_')
            if Model.table_query() : table = '('+Model.table_query()[0]%tuple(Model.table_query()[1])+') AS mytable'
            col = field.name
            if bbox != [] and srsname != 0:
                sql = 'SELECT ST_Extent(Box2D(%(col)s)) FROM %(table)s WHERE\
                    ST_Intersects(\
                        ST_SetSRID(\
                            ST_MakeBox2D(\
                                ST_MakePoint(%(xmin)s, %(ymin)s),\
                                ST_MakePoint(%(xmax)s, %(ymax)s)\
                            ), %(srsname)s\
                        ), %(col)s )' % {
                        'col': col,
                        'table': table,
                        'xmin' : bbox[0],
                        'ymin' : bbox[1],
                        'xmax' : bbox[2],
                        'ymax' : bbox[3],
                        'srsname' : srsname}
                cursor.execute(sql)
            else:
                try: 
                    cursor.execute('SELECT ST_Estimated_Extent(\'%s\', \'%s\');' % (table, col))
                except:
                    cursor.connection.rollback()
                    cursor.execute('SELECT ST_Extent(Box2D(%s)) FROM %s;' % (col, table))


            feature_bbox = cursor.fetchall()
            if len(feature_bbox) != 0 and len(feature_bbox[0]) != 0 and feature_bbox[0][0] is not None:
                feature_bbox = feature_bbox[0][0]
                feature_bbox = feature_bbox.replace('BOX(', '')
                feature_bbox = feature_bbox.replace(')', '')
                tl, ur = feature_bbox.split(',')
                feature_bbox = tl.split(' ') + ur.split(' ')
            else:
                feature_bbox = None

            features.append({
                'title': field.model.name,
                'name': field.model.model,
                'srs': 'EPSG:%s' % getattr(Model, field.name).srid,
                'bbox': feature_bbox,
            })

        if self.show_non_geo:
            Model = Pool().get('ir.model')
            domain = [('model', '!=', model) for model in models]
            for model in Model.search(domain):
                if not self.access_check(model.model, raise_exception=False):
                    continue
                m = Pool().get(model.model)
                if not hasattr(m, 'search'):
                    continue

                records = m.search([], limit=1)
                features.append({
                    'title': model.name,
                    'name': model.model,
                    'srs': '',
                    'bbox': None,
                })

        # Sort models
        features = sorted(features, key=lambda x: x['title'])

        wfs_capabilities = self.tmpl_loader.load('wfs_capabilities.xml')
        rendered = wfs_capabilities.generate(name='Tryton',
                                             title='Tryton WFS module',
                                             abstract='Tryton WFS module',
                                             url=self.url,
                                             features=features).render()
        return rendered

    def describefeaturetype(self, typename, **kw):
        tryton, model = typename.split(':', 1)
        if tryton != 'tryton':
            raise Exception('Unknown feature type %s' % typename)
        self.access_check(model)
        Fields = Pool().get('ir.model.field')
        fields = Fields.search([('model.model', '=', model)])

        elements = []
        for field in fields:
            if field.name in TRYTON_FIELDS:
                continue
            if not self.access_check(model, field.name, raise_exception=False):
                continue
            nillable = 'true'
            if hasattr(field, 'required') and field.required:
                nillable = 'false'

            if get_wfs_type(field.ttype) == {}:
                continue

            element = {
                'name': field.name,
                'type': get_wfs_type(field.ttype),
                'nillable': nillable,
            }
            elements.append(element)

        wfs_featuretype = self.tmpl_loader.load('wfs_featuretype.xml')
        rendered = wfs_featuretype.generate(name=fields[0].model.model,
                                            elements=elements).render()
        return rendered

    def getfeature(self, typename, filter='', srsname=0, maxfeatures=1024, bbox=[], **kw):
        tryton, model = typename.split(':', 1)
        if tryton != 'tryton':
            raise Exception('Unknown feature %s' % typename)

        self.access_check(model)

        if bbox != []:
            bbox = [float(nbr) for nbr in bbox.split(',')]

        Fields = Pool().get('ir.model.field')
        fields = Fields.search([('model.model', '=', model)])
        Model = Pool().get(model)
        factory = ElementFactory()
        cursor = Transaction().cursor
        records = None
        filter_domain = filter2domain(filter)

        # Find a geometry field and select records in the bbox if there is one
        if bbox != []:
            for field in fields:
                if field.ttype not in GEO_TYPES:
                    continue

                if not self.access_check(model, field.name, raise_exception=False):
                    continue

                sql = 'SELECT id FROM %(table)s WHERE\
                    ST_Intersects(\
                        ST_SetSRID(\
                            ST_MakeBox2D(\
                                ST_MakePoint(%(xmin)s, %(ymin)s),\
                                ST_MakePoint(%(xmax)s, %(ymax)s)\
                            ), %(srsname)s\
                        ), %(col)s\
                    ) LIMIT %(maxfeatures)s' % {
                            'table' : model.replace('.', '_'), 
                            'col' : field.name,
                            'xmin' : bbox[0],
                            'ymin' : bbox[1],
                            'xmax' : bbox[2],
                            'ymax' : bbox[3],
                            'srsname' : srsname,
                            'maxfeatures' : maxfeatures }
                cursor.execute(sql)
                domain = [[('id', '=', col[0])] for col in cursor.fetchall()]
                if len(domain) == 0:
                    continue
                domain = ['AND', filter_domain, [['OR'] + domain]]
                records = Model.search(domain, limit=maxfeatures)
                break
        else:
            records = Model.search(filter_domain, limit=maxfeatures)

        if not records: records = []
        print len(records), ' features returned'

        fbbox = None
        elems = []
        for record in records:
            elem = getattr(factory, 'gml:featureMember')
            tag = getattr(factory, 'tryton:%s' % model)(fid='%s.%i' % (model, record.id))
            elem.children.append(tag)
            elems.append(elem)

            for field in fields:
                if field.name in TRYTON_FIELDS:
                    continue

                if not self.access_check(model, field.name, raise_exception=False):
                    continue

                if get_wfs_type(field.ttype) == {}:
                    continue

                if field.ttype in GEO_TYPES:
                    cursor.execute('SELECT ST_AsGML(%s) FROM %s WHERE id=%s' % (field.name, model.replace('.', '_'), record.id))
                    ret = cursor.fetchall()
                    if ret[0][0] is None and self.default_geo:
                        # when there is no geometry, create one
                        if bbox == []:
                            if srsname == 0 or srsname == 2154:
                                srsname = 2154
                                # EPSG:2154 projected boundaries
                                fbbox = [
                                    -357823.2365,
                                    6037008.6939,
                                    1313632.3628,
                                    7230727.3772
                                ]
                            else:
                                # TODO: handle this case
                                raise Exception('You must specify a bounding box when using an srsname different of EPSG:2154')
                        else:
                            fbbox = bbox

                        xmin = fbbox[0] + ((fbbox[2] - fbbox[0]) * 0.25)
                        xmax = fbbox[0] + ((fbbox[2] - fbbox[0]) * 0.75)
                        ymin = fbbox[1] + ((fbbox[3] - fbbox[1]) * 0.25)
                        ymax = fbbox[1] + ((fbbox[3] - fbbox[1]) * 0.75)

                        if field.ttype == 'multipolygon':
                            cursor.execute("SELECT ST_AsGML(ST_GeomFromEWKT('srid=%i;multipolygon( ((%s %s, %s %s, %s %s, %s %s, %s %s)) )'))" %
                                           (srsname,
                                            xmin, ymin,
                                            xmin, ymax,
                                            xmax, ymax,
                                            xmax, ymin,
                                            xmin, ymin), ())
                            val = Markup(cursor.fetchall()[0][0])
                        elif field.ttype == 'multilinestring':
                            cursor.execute("SELECT ST_AsGML(ST_GeomFromEWKT('srid=%i;multilinestring( (%s %s, %s %s, %s %s, %s %s) )'))" %
                                           (srsname,
                                            xmin, ymin,
                                            xmin, ymax,
                                            xmax, ymax,
                                            xmax, ymin), ())
                            val = Markup(cursor.fetchall()[0][0])
                        elif field.ttype == 'multipoint':
                            cursor.execute("SELECT ST_AsGML(ST_GeomFromEWKT('srid=%i;multipoint(%s %s, %s %s)'))" %
                                           (srsname,
                                            xmin, ymin,
                                            xmin, ymax), ())
                            val = Markup(cursor.fetchall()[0][0])
                    elif ret[0][0] is None:
                        val = ''
                    else:
                        val = Markup(ret[0][0])
                else:
                    val = getattr(record, field.name)
                    if val is None:
                        val = ''
                    elif field.ttype == 'many2one':
                        val = val.id

                _field = getattr(ElementFactory(), 'tryton:%s' % field.name)()
                _field.children.append(val)
                tag.children.append(_field)

        wfs_feature = self.tmpl_loader.load('wfs_feature.xml')
        rendered = wfs_feature.generate(url=self.url,
                                        ttype='tryton:%s' % model,
                                        elems=elems).render()
        return rendered

    def post(self, data, **kw):
        data = parseString(data)
        data = data.firstChild
        if data.nodeName != 'Transaction':
            raise Exception('Invalid transaction')

        inserts = []
        deletes = []
        updates = []

        _kw = self._parse_args(**kw)
        srsname = _kw.get('srsname', 0)

        for trans_type in ('Delete', 'Update', 'Insert'):
            for transaction in data.childNodes:
                if transaction.nodeName != trans_type:
                    continue
                if transaction.nodeName in ('Update', 'Delete'):
                    typename = transaction.getAttribute('typeName')
                    tryton, model = typename.split(':', 1)
                else:
                    if transaction.firstChild is None:
                        raise Exception('Invalid transaction')
                    typename = transaction.firstChild.nodeName
                    model = typename
                    tryton = 'tryton'

                tryton_op = WFS_OPERATIONS[transaction.nodeName]
                self.access_check(model, mode=tryton_op)

                Model = None
                try:
                    Model = Pool().get(model)
                except:
                    pass

                if Model is None or tryton != 'tryton':
                    raise Exception('Unknown feature type %s' % typename)

                if srsname == 0:
                    for field in Model._fields.itervalues():
                        if field._type in GEO_TYPES:
                            srsname = field.srid
                            break
                    else:
                        raise Exception('Srid is not set, cannot modify geometry')

                geo_field = None
                field = None
                value = None
                record_id = None
                to_delete = []
                record = {}
                if transaction.nodeName in ('Update', 'Delete'):
                    children = transaction.childNodes
                elif transaction.nodeName == 'Insert':
                    children = transaction.firstChild.childNodes

                for child in children:
                    if transaction.nodeName in ('Update', 'Delete'):
                        if child.nodeName == 'Property':
                            for property in child.childNodes:
                                if property.nodeName == 'Name':
                                    field = property.firstChild.data
                                    self.access_check(model, field, mode=tryton_op)
                                elif property.nodeName == 'Value':
                                    if (property.hasChildNodes() and
                                            property.firstChild.namespaceURI == GML_NS):
                                        value = gml2sql(property.firstChild.toxml(), getattr(Model, field))
                                        geo_field = field
                                    else:
                                        if property.firstChild is not None:
                                            value = property.firstChild.nodeValue
                                        else:
                                            value = None
                                else:
                                    raise Exception('Unhandled node type %s' % property.nodeName)

                        elif child.nodeName == 'Filter':
                            for subchild in child.childNodes:
                                if subchild.nodeName == 'FeatureId':
                                    fid = subchild.getAttribute('fid')
                                    _model, record_id = fid.rsplit('.', 1)
                                    if transaction.nodeName == 'Delete':
                                        to_delete.append(int(record_id))

                                    if model != _model:
                                        raise Exception('fid doesn\'t match the typename of the model (%s != %s)' % (model, _model))
                                else:
                                    raise Exception('Unhandled node type %s' % child.nodeName)
                        else:
                            raise Exception('Unhandled node type %s' % child.nodeName)
                    elif transaction.nodeName == 'Insert':
                        field = child.nodeName
                        if (child.hasChildNodes() and
                                child.firstChild.namespaceURI == GML_NS):
                            value = gml2sql(child.firstChild.toxml(), getattr(Model, field))
                            geo_field = field
                        else:
                            if child.firstChild is None:
                                value = None
                            else:
                                value = child.firstChild.nodeValue

                    if trans_type != 'Delete':
                        if field == 'id':
                            continue

                        if getattr(Model, field).readonly:
                            continue

                    record[field] = value

                if transaction.nodeName == 'Insert' and record != {}:
                    if geo_field is not None:
                        value = record.pop(geo_field)
                    record = Model.create([record])[0]
                    if geo_field is not None:
                        cursor = Transaction().cursor
                        cursor.execute('UPDATE %s SET %s = %s WHERE id = %%s' %
                                       (model.replace('.', '_'), field, value), (record.id,))
                    inserts.append('%s.%i' % (model, record.id))
                elif transaction.nodeName == 'Delete':
                    Model.delete(to_delete)
                    to_delete = ['%s.%s' % (model, _id) for _id in to_delete]
                    deletes += to_delete
                elif transaction.nodeName == 'Update' and record != {}:
                    fields = record.keys()
                    sql = 'UPDATE %s SET ' % model.replace('.', '_')
                    sql += ', '.join(['%s = %%s' % field for field in fields])
                    sql += ' WHERE id = %s'

                    sql_args = [record[field] for field in fields]
                    sql_args.append(record_id)
                    cursor = Transaction().cursor
                    cursor.execute(sql, sql_args)
                    updates.append('%s.%s' % (model, record_id))

        wfs_trans_summary = self.tmpl_loader.load('wfs_trans_response.xml')
        rendered = wfs_trans_summary.generate(updates=updates,
                                              deletes=deletes,
                                              inserts=inserts).render()
        return rendered

    def format_exc(self):
        wfs_error = self.tmpl_loader.load('wfs_error.xml')
        if CONFIG['log_level'].upper() == 'DEBUG':
            tb_s = ''.join(format_exception(*sys.exc_info()))
            for path in sys.path:
                tb_s = tb_s.replace(path, '')
        else:
            tb_s = ''.join(format_exception_only(*sys.exc_info()[:2]))

        error_msg = escape(tb_s.decode('utf-8'))
        rendered = wfs_error.generate(error_msg=error_msg).render()
        return rendered
Esempio n. 9
0
 def _totp_admin(cls):
     ModelAccess = Pool().get('ir.model.access')
     return ModelAccess.check('res.user',
                              mode='write',
                              raise_exception=False)