Esempio n. 1
0
    def execute(cls, ids, data):
        '''
        Execute the report on record ids.
        The dictionary with data that will be set in local context of the
        report.
        It returns a tuple with:
            report type,
            data,
            a boolean to direct print,
            the report name
        '''
        pool = Pool()
        ActionReport = pool.get('ir.action.report')
        cls.check_access()

        action_id = data.get('action_id')
        if action_id is None:
            action_reports = ActionReport.search([('report_name', '=',
                                                   cls.__name__)])
            assert action_reports, '%s not found' % cls
            action_report = action_reports[0]
        else:
            action_report = ActionReport(action_id)

        records = []
        model = action_report.model or data.get('model')
        if model:
            records = cls._get_records(ids, model, data)
        if action_report.single and len(records) > 1:
            content = BytesIO()
            with zipfile.ZipFile(content, 'w') as content_zip:
                for record in records:
                    oext, rcontent = cls._execute([record], data,
                                                  action_report)
                    filename = slugify('%s-%s' % (record.id, record.rec_name))
                    rfilename = '%s.%s' % (filename, oext)
                    content_zip.writestr(rfilename, rcontent)
            content = content.getvalue()
            oext = 'zip'
        else:
            oext, content = cls._execute(records, data, action_report)
        if not isinstance(content, str):
            content = bytearray(content) if bytes == str else bytes(content)

        suffix = '-'.join(r.rec_name for r in records[:5])
        if len(records) > 5:
            suffix += '__' + str(len(records[5:]))
        report_name = '-'.join(filter(None, [action_report.name, suffix]))
        return (oext, content, action_report.direct_print, report_name)
Esempio n. 2
0
def data(request, pool, model):
    User = pool.get('res.user')
    Lang = pool.get('ir.lang')
    try:
        Model = pool.get(model)
    except KeyError:
        abort(HTTPStatus.NOT_FOUND)
    transaction = Transaction()
    context = User(transaction.user).get_preferences(context_only=True)
    language = request.args.get('l')
    if language:
        context['language'] = language
    try:
        domain = json.loads(request.args.get('d', '[]'),
                            object_hook=JSONDecoder())
    except json.JSONDecodeError:
        abort(HTTPStatus.BAD_REQUEST)
    try:
        ctx = json.loads(request.args.get('c', '{}'),
                         object_hook=JSONDecoder())
    except json.JSONDecoder:
        abort(HTTPStatus.BAD_REQUEST)
    for key in list(ctx.keys()):
        if key.startswith('_') and key != '_datetime':
            del ctx[key]
    context.update(ctx)
    limit = None
    offset = 0
    if 's' in request.args:
        try:
            limit = int(request.args.get('s'))
            if 'p' in request.args:
                offset = int(request.args.get('p')) * limit
        except ValueError:
            abort(HTTPStatus.BAD_REQUEST)
    if 'o' in request.args:
        order = [(o.split(',', 1) + [''])[:2]
                 for o in request.args.getlist('o')]
    else:
        order = None
    fields_names = request.args.getlist('f')
    encoding = request.args.get('enc', 'UTF-8')
    delimiter = request.args.get('dl', ',')
    quotechar = request.args.get('qc', '"')
    try:
        header = bool(int(request.args.get('h', True)))
        locale_format = bool(int(request.args.get('loc', False)))
    except ValueError:
        abort(HTTPStatus.BAD_REQUEST)

    with transaction.set_context(**context):
        lang = Lang.get(transaction.language)

        def format_(row):
            for i, value in enumerate(row):
                if locale_format:
                    if isinstance(value, Number):
                        value = lang.format('%.12g', value)
                    elif isinstance(value, (dt.date, dt.datetime)):
                        value = lang.strftime(value)
                elif isinstance(value, bool):
                    value = int(value)
                row[i] = value
            return row

        try:
            if domain and isinstance(domain[0], (int, float)):
                rows = Model.export_data(domain, fields_names)
            else:
                rows = Model.export_data_domain(domain,
                                                fields_names,
                                                limit=limit,
                                                offset=offset,
                                                order=order)
        except (ValueError, KeyError):
            abort(HTTPStatus.BAD_REQUEST)
        data = io.StringIO(newline='')
        writer = csv.writer(data, delimiter=delimiter, quotechar=quotechar)
        if header:
            writer.writerow(fields_names)
        for row in rows:
            writer.writerow(format_(row))
        data = data.getvalue().encode(encoding)
        filename = slugify(Model.__names__()['model']) + '.csv'
        filename = filename.encode('latin-1', 'ignore')
        response = Response(data, mimetype='text/csv; charset=' + encoding)
        response.headers.add('Content-Disposition',
                             'attachment',
                             filename=filename)
        response.headers.add('Content-Length', len(data))
        return response
Esempio n. 3
0
 def on_change_string(self):
     if not self.name and self.string:
         self.name = slugify(self.string.lower(), hyphenate='_')
Esempio n. 4
0
    def execute(cls, ids, data):
        '''
        Execute the report on record ids.
        The dictionary with data that will be set in local context of the
        report.
        It returns a tuple with:
            report type,
            data,
            a boolean to direct print,
            the report name
        '''
        pool = Pool()
        ActionReport = pool.get('ir.action.report')
        cls.check_access()

        action_id = data.get('action_id')
        if action_id is None:
            action_reports = ActionReport.search([('report_name', '=',
                                                   cls.__name__)])
            assert action_reports, '%s not found' % cls
            action_report = action_reports[0]
        else:
            action_report = ActionReport(action_id)

        def report_name(records):
            name = '-'.join(r.rec_name for r in records[:5])
            if len(records) > 5:
                name += '__' + str(len(records[5:]))
            return name

        records = []
        model = action_report.model or data.get('model')
        if model:
            records = cls._get_records(ids, model, data)

        if action_report.single:
            groups = [[r] for r in records]
            headers = [dict(cls.header_key(r)) for r in records]
        else:
            groups = []
            headers = []
            for key, group in groupby(records, key=cls.header_key):
                groups.append(list(group))
                headers.append(dict(key))

        n = len(groups)
        if n > 1:
            padding = math.ceil(math.log10(n))
            content = BytesIO()
            with zipfile.ZipFile(content, 'w') as content_zip:
                for i, (header,
                        group_records) in enumerate(zip(headers, groups), 1):
                    oext, rcontent = cls._execute(group_records, header, data,
                                                  action_report)
                    filename = report_name(group_records)
                    number = str(i).zfill(padding)
                    filename = slugify('%s-%s' % (number, filename))
                    rfilename = '%s.%s' % (filename, oext)
                    content_zip.writestr(rfilename, rcontent)
            content = content.getvalue()
            oext = 'zip'
        else:
            oext, content = cls._execute(groups[0], headers[0], data,
                                         action_report)
        if not isinstance(content, str):
            content = bytearray(content) if bytes == str else bytes(content)
        filename = '-'.join(
            filter(
                None,
                [action_report.name, report_name(records)]))
        return (oext, content, action_report.direct_print, filename)
Esempio n. 5
0
 def test_slugify_hyphenate(self):
     "Test hyphenate in slugify"
     self.assertEqual(slugify('foo bar', hyphenate='_'), 'foo_bar')
Esempio n. 6
0
 def test_slugify(self):
     "Test slugify"
     self.assertEqual(slugify('unicode ♥ is ☢'), 'unicode-is')
Esempio n. 7
0
    def execute(cls, ids, data):
        '''
        Execute the report on record ids.
        The dictionary with data that will be set in local context of the
        report.
        It returns a tuple with:
            report type,
            data,
            a boolean to direct print,
            the report name (with or without the record names)
        '''
        pool = Pool()
        ActionReport = pool.get('ir.action.report')
        cls.check_access()
        context = Transaction().context
        ids = list(map(int, ids))

        action_id = data.get('action_id')
        if action_id is None:
            action_reports = ActionReport.search([('report_name', '=',
                                                   cls.__name__)])
            assert action_reports, '%s not found' % cls
            action_report = action_reports[0]
        else:
            action_report = ActionReport(action_id)

        def report_name(records, reserved_length=0):
            names = []
            name_length = 0
            record_count = len(records)
            max_length = (REPORT_NAME_MAX_LENGTH - reserved_length -
                          len(str(record_count)) - 2)
            if action_report.record_name:
                template = TextTemplate(action_report.record_name)
            else:
                template = None
            for record in records[:5]:
                if template:
                    record_name = template.generate(record=record).render()
                else:
                    record_name = record.rec_name
                name_length += len(unicodedata.normalize('NFKD',
                                                         record_name)) + 1
                if name_length > max_length:
                    break
                names.append(record_name)

            name = '-'.join(names)
            if len(records) > len(names):
                name += '__' + str(record_count - len(names))
            return name

        records = []
        model = action_report.model or data.get('model')
        if model:
            records = cls._get_records(ids, model, data)

        if not records:
            groups = [[]]
            headers = [{}]
        elif action_report.single:
            groups = [[r] for r in records]
            headers = [dict(cls.header_key(r)) for r in records]
        else:
            groups = []
            headers = []
            for key, group in groupby(records, key=cls.header_key):
                groups.append(list(group))
                headers.append(dict(key))

        n = len(groups)
        join_string = '-'
        if n > 1:
            padding = math.ceil(math.log10(n))
            content = BytesIO()
            with zipfile.ZipFile(content, 'w') as content_zip:
                for i, (header,
                        group_records) in enumerate(zip(headers, groups), 1):
                    oext, rcontent = cls._execute(group_records, header, data,
                                                  action_report)
                    number = str(i).zfill(padding)
                    filename = report_name(group_records,
                                           len(number) + len(join_string))
                    filename = slugify(join_string.join([number, filename]))
                    rfilename = '%s.%s' % (filename, oext)
                    content_zip.writestr(rfilename, rcontent)
            content = content.getvalue()
            oext = 'zip'
        else:
            oext, content = cls._execute(groups[0], headers[0], data,
                                         action_report)
        if not isinstance(content, str):
            content = bytearray(content) if bytes == str else bytes(content)
        action_report_name = action_report.name[:REPORT_NAME_MAX_LENGTH]
        if context.get('with_rec_name', True):
            filename = join_string.join(
                filter(None, [
                    action_report_name,
                    report_name(records,
                                len(action_report_name) + len(join_string))
                ]))
        else:
            filename = action_report_name
        return (oext, content, action_report.direct_print, filename)