[IMP] report_csv: black, isort

pull/605/head
kongrattapong 2020-02-21 17:16:12 +07:00 committed by Adrien Peiffer
parent 317398fa71
commit f9856fa5a4
No known key found for this signature in database
GPG Key ID: D9266D898B218452
6 changed files with 88 additions and 102 deletions

View File

@ -1,28 +1,16 @@
# Copyright 2019 Creu Blanca # Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{ {
'name': "Base report csv", "name": "Base report csv",
"summary": "Base module to create csv report",
'summary': "Base module to create csv report", "author": "Creu Blanca," "Odoo Community Association (OCA)",
'author': 'Creu Blanca,' "website": "https://github.com/oca/reporting-engine",
'Odoo Community Association (OCA)', "category": "Reporting",
'website': "https://github.com/oca/reporting-engine", "version": "12.0.1.0.0",
'category': 'Reporting', "license": "AGPL-3",
'version': '12.0.1.0.0', "external_dependencies": {"python": ["csv"]},
'license': 'AGPL-3', "depends": ["base", "web"],
'external_dependencies': { "data": ["views/webclient_templates.xml"],
'python': [ "demo": ["demo/report.xml"],
'csv', "installable": True,
],
},
'depends': [
'base', 'web',
],
'data': [
'views/webclient_templates.xml',
],
'demo': [
'demo/report.xml',
],
'installable': True,
} }

View File

@ -1,58 +1,55 @@
# Copyright (C) 2019 Creu Blanca # Copyright (C) 2019 Creu Blanca
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
from odoo.addons.web.controllers import main as report
from odoo.http import content_disposition, route, request
from odoo.tools.safe_eval import safe_eval
import json import json
import time import time
from odoo.http import content_disposition, request, route
from odoo.tools.safe_eval import safe_eval
from odoo.addons.web.controllers import main as report
class ReportController(report.ReportController): class ReportController(report.ReportController):
@route() @route()
def report_routes(self, reportname, docids=None, converter=None, **data): def report_routes(self, reportname, docids=None, converter=None, **data):
if converter == 'csv': if converter == "csv":
report = request.env['ir.actions.report']._get_report_from_name( report = request.env["ir.actions.report"]._get_report_from_name(reportname)
reportname)
context = dict(request.env.context) context = dict(request.env.context)
if docids: if docids:
docids = [int(i) for i in docids.split(',')] docids = [int(i) for i in docids.split(",")]
if data.get('options'): if data.get("options"):
data.update(json.loads(data.pop('options'))) data.update(json.loads(data.pop("options")))
if data.get('context'): if data.get("context"):
# Ignore 'lang' here, because the context in data is the one # Ignore 'lang' here, because the context in data is the one
# from the webclient *but* if the user explicitely wants to # from the webclient *but* if the user explicitely wants to
# change the lang, this mechanism overwrites it. # change the lang, this mechanism overwrites it.
data['context'] = json.loads(data['context']) data["context"] = json.loads(data["context"])
if data['context'].get('lang'): if data["context"].get("lang"):
del data['context']['lang'] del data["context"]["lang"]
context.update(data['context']) context.update(data["context"])
csv = report.with_context(context).render_csv( csv = report.with_context(context).render_csv(docids, data=data)[0]
docids, data=data filename = "{}.{}".format(report.name, "csv")
)[0]
filename = "%s.%s" % (report.name, "csv")
if docids: if docids:
obj = request.env[report.model].browse(docids) obj = request.env[report.model].browse(docids)
if report.print_report_name and not len(obj) > 1: if report.print_report_name and not len(obj) > 1:
report_name = safe_eval( report_name = safe_eval(
report.print_report_name, report.print_report_name,
{'object': obj, 'time': time, 'multi': False}) {"object": obj, "time": time, "multi": False},
filename = "%s.%s" % (report_name, "csv") )
filename = "{}.{}".format(report_name, "csv")
# When we print multiple records we still allow a custom # When we print multiple records we still allow a custom
# filename. # filename.
elif report.print_report_name and len(obj) > 1: elif report.print_report_name and len(obj) > 1:
report_name = safe_eval( report_name = safe_eval(
report.print_report_name, report.print_report_name,
{'objects': obj, 'time': time, 'multi': True}) {"objects": obj, "time": time, "multi": True},
filename = "%s.%s" % (report_name, "csv") )
filename = "{}.{}".format(report_name, "csv")
csvhttpheaders = [ csvhttpheaders = [
('Content-Type', 'text/csv'), ("Content-Type", "text/csv"),
('Content-Length', len(csv)), ("Content-Length", len(csv)),
( ("Content-Disposition", content_disposition(filename)),
'Content-Disposition',
content_disposition(filename)
)
] ]
return request.make_response(csv, headers=csvhttpheaders) return request.make_response(csv, headers=csvhttpheaders)
return super(ReportController, self).report_routes( return super(ReportController, self).report_routes(

View File

@ -1,33 +1,35 @@
# Copyright 2019 Creu Blanca # Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models, _ from odoo import _, api, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
class ReportAction(models.Model): class ReportAction(models.Model):
_inherit = 'ir.actions.report' _inherit = "ir.actions.report"
report_type = fields.Selection(selection_add=[("csv", "csv")]) report_type = fields.Selection(selection_add=[("csv", "csv")])
@api.model @api.model
def render_csv(self, docids, data): def render_csv(self, docids, data):
report_model_name = 'report.%s' % self.report_name report_model_name = "report.%s" % self.report_name
report_model = self.env.get(report_model_name) report_model = self.env.get(report_model_name)
if report_model is None: if report_model is None:
raise UserError(_('%s model was not found' % report_model_name)) raise UserError(_("%s model was not found" % report_model_name))
return report_model.with_context({ return report_model.with_context(
'active_model': self.model {"active_model": self.model}
}).create_csv_report(docids, data) ).create_csv_report(docids, data)
@api.model @api.model
def _get_report_from_name(self, report_name): def _get_report_from_name(self, report_name):
res = super(ReportAction, self)._get_report_from_name(report_name) res = super(ReportAction, self)._get_report_from_name(report_name)
if res: if res:
return res return res
report_obj = self.env['ir.actions.report'] report_obj = self.env["ir.actions.report"]
qwebtypes = ['csv'] qwebtypes = ["csv"]
conditions = [('report_type', 'in', qwebtypes), conditions = [
('report_name', '=', report_name)] ("report_type", "in", qwebtypes),
context = self.env['res.users'].context_get() ("report_name", "=", report_name),
]
context = self.env["res.users"].context_get()
return report_obj.with_context(context).search(conditions, limit=1) return report_obj.with_context(context).search(conditions, limit=1)

View File

@ -1,22 +1,22 @@
# Copyright 2019 Creu Blanca # Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
import logging
from io import StringIO from io import StringIO
from odoo import models from odoo import models
import logging
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
try: try:
import csv import csv
except ImportError: except ImportError:
_logger.debug('Can not import csvwriter`.') _logger.debug("Can not import csvwriter`.")
class ReportCSVAbstract(models.AbstractModel): class ReportCSVAbstract(models.AbstractModel):
_name = 'report.report_csv.abstract' _name = "report.report_csv.abstract"
_description = 'Abstract Model for CSV reports' _description = "Abstract Model for CSV reports"
def _get_objs_for_report(self, docids, data): def _get_objs_for_report(self, docids, data):
""" """
@ -34,11 +34,11 @@ class ReportCSVAbstract(models.AbstractModel):
""" """
if docids: if docids:
ids = docids ids = docids
elif data and 'context' in data: elif data and "context" in data:
ids = data["context"].get('active_ids', []) ids = data["context"].get("active_ids", [])
else: else:
ids = self.env.context.get('active_ids', []) ids = self.env.context.get("active_ids", [])
return self.env[self.env.context.get('active_model')].browse(ids) return self.env[self.env.context.get("active_model")].browse(ids)
def create_csv_report(self, docids, data): def create_csv_report(self, docids, data):
objs = self._get_objs_for_report(docids, data) objs = self._get_objs_for_report(docids, data)
@ -46,7 +46,7 @@ class ReportCSVAbstract(models.AbstractModel):
file = csv.DictWriter(file_data, **self.csv_report_options()) file = csv.DictWriter(file_data, **self.csv_report_options())
self.generate_csv_report(file, data, objs) self.generate_csv_report(file, data, objs)
file_data.seek(0) file_data.seek(0)
return file_data.read(), 'csv' return file_data.read(), "csv"
def csv_report_options(self): def csv_report_options(self):
""" """
@ -55,7 +55,7 @@ class ReportCSVAbstract(models.AbstractModel):
Valid parameters include 'delimiter', 'quotechar', 'escapechar', Valid parameters include 'delimiter', 'quotechar', 'escapechar',
'doublequote', 'skipinitialspace', 'lineterminator', 'quoting'. 'doublequote', 'skipinitialspace', 'lineterminator', 'quoting'.
""" """
return {'fieldnames': []} return {"fieldnames": []}
def generate_csv_report(self, file, data, objs): def generate_csv_report(self, file, data, objs):
raise NotImplementedError() raise NotImplementedError()

View File

@ -1,25 +1,23 @@
# Copyright 2019 Creu Blanca # Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
import csv import csv
from odoo import models from odoo import models
class PartnerCSV(models.AbstractModel): class PartnerCSV(models.AbstractModel):
_name = 'report.report_csv.partner_csv' _name = "report.report_csv.partner_csv"
_inherit = 'report.report_csv.abstract' _inherit = "report.report_csv.abstract"
def generate_csv_report(self, writer, data, partners): def generate_csv_report(self, writer, data, partners):
writer.writeheader() writer.writeheader()
for obj in partners: for obj in partners:
writer.writerow({ writer.writerow({"name": obj.name, "email": obj.email})
'name': obj.name,
'email': obj.email,
})
def csv_report_options(self): def csv_report_options(self):
res = super().csv_report_options() res = super().csv_report_options()
res['fieldnames'].append('name') res["fieldnames"].append("name")
res['fieldnames'].append('email') res["fieldnames"].append("email")
res['delimiter'] = ';' res["delimiter"] = ";"
res['quoting'] = csv.QUOTE_ALL res["quoting"] = csv.QUOTE_ALL
return res return res

View File

@ -1,52 +1,53 @@
# Copyright 2019 Creu Blanca # Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from io import StringIO
from odoo.tests import common
import logging import logging
from io import StringIO
from odoo.tests import common
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
try: try:
import csv import csv
except ImportError: except ImportError:
_logger.debug('Can not import csv.') _logger.debug("Can not import csv.")
class TestReport(common.TransactionCase): class TestReport(common.TransactionCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
report_object = self.env['ir.actions.report'] report_object = self.env["ir.actions.report"]
self.csv_report = ( self.csv_report = self.env["report.report_csv.abstract"].with_context(
self.env['report.report_csv.abstract'] active_model="res.partner"
.with_context(active_model='res.partner')
) )
self.report_name = 'report_csv.partner_csv' self.report_name = "report_csv.partner_csv"
self.report = report_object._get_report_from_name(self.report_name) self.report = report_object._get_report_from_name(self.report_name)
self.docs = self.env['res.company'].search([], limit=1).partner_id self.docs = self.env["res.company"].search([], limit=1).partner_id
def test_report(self): def test_report(self):
report = self.report report = self.report
self.assertEqual(report.report_type, 'csv') self.assertEqual(report.report_type, "csv")
rep = report.render(self.docs.ids, {}) rep = report.render(self.docs.ids, {})
str_io = StringIO(rep[0]) str_io = StringIO(rep[0])
dict_report = list(csv.DictReader(str_io, delimiter=';', dict_report = list(csv.DictReader(str_io, delimiter=";", quoting=csv.QUOTE_ALL))
quoting=csv.QUOTE_ALL)) self.assertEqual(self.docs.name, dict(dict_report[0])["name"])
self.assertEqual(self.docs.name, dict(dict_report[0])['name'])
def test_id_retrieval(self): def test_id_retrieval(self):
# Typical call from WebUI with wizard # Typical call from WebUI with wizard
objs = self.csv_report._get_objs_for_report( objs = self.csv_report._get_objs_for_report(
False, {"context": {"active_ids": self.docs.ids}}) False, {"context": {"active_ids": self.docs.ids}}
)
self.assertEquals(objs, self.docs) self.assertEquals(objs, self.docs)
# Typical call from within code not to report_action # Typical call from within code not to report_action
objs = self.csv_report.with_context( objs = self.csv_report.with_context(
active_ids=self.docs.ids)._get_objs_for_report(False, False) active_ids=self.docs.ids
)._get_objs_for_report(False, False)
self.assertEquals(objs, self.docs) self.assertEquals(objs, self.docs)
# Typical call from WebUI # Typical call from WebUI
objs = self.csv_report._get_objs_for_report( objs = self.csv_report._get_objs_for_report(
self.docs.ids, self.docs.ids, {"data": [self.report_name, self.report.report_type]}
{"data": [self.report_name, self.report.report_type]}
) )
self.assertEquals(objs, self.docs) self.assertEquals(objs, self.docs)