forked from OCA/reporting-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
397 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg | ||
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
|
||
=============== | ||
Base report csv | ||
=============== | ||
|
||
This module provides a basic report class to generate csv report. | ||
|
||
|
||
Usage | ||
===== | ||
|
||
An example of CSV report for partners on a module called `module_name`: | ||
|
||
A python class :: | ||
|
||
from odoo import models | ||
|
||
class PartnerCsv(models.AbstractModel): | ||
_name = 'report.module_name.report_name' | ||
_inherit = 'report.report_csv.abstract' | ||
def generate_csv_report(self, writer, data, partners): | ||
for obj in partners: | ||
writer.writeheader() | ||
writer.writerow({ | ||
'name': obj.name | ||
}) | ||
|
||
def csv_report_options(self): | ||
res = super().csv_report_options() | ||
res['fieldnames'].append('name') | ||
return res | ||
|
||
A report XML record :: | ||
|
||
<report | ||
id="partner_csv" | ||
model="res.partner" | ||
string="Print to CSV" | ||
report_type="csv" | ||
name="module_name.report_name" | ||
file="res_partner" | ||
attachment_use="False" | ||
/> | ||
|
||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas | ||
:alt: Try me on Runbot | ||
:target: https://runbot.odoo-community.org/runbot/143/11.0 | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues | ||
<https://github.com/OCA/reporting-engine/issues>`_. In case of trouble, please | ||
check there if your issue has already been reported. If you spotted it first, | ||
help us smashing it by providing a detailed and welcomed feedback. | ||
|
||
Credits | ||
======= | ||
|
||
Contributors | ||
------------ | ||
|
||
* Enric Tobella <[email protected]> | ||
|
||
Maintainer | ||
---------- | ||
|
||
.. image:: https://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
|
||
This module is maintained by the OCA. | ||
|
||
OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. | ||
|
||
To contribute to this module, please visit https://odoo-community.org. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from . import controllers | ||
from . import models | ||
from . import report |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Copyright 2019 Creu Blanca | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). | ||
{ | ||
'name': "Base report csv", | ||
|
||
'summary': "Base module to create csv report", | ||
'author': 'Creu Blanca,' | ||
'Odoo Community Association (OCA)', | ||
'website': "https://github.com/oca/reporting-engine", | ||
'category': 'Reporting', | ||
'version': '11.0.1.0.0', | ||
'license': 'AGPL-3', | ||
'external_dependencies': { | ||
'python': [ | ||
'csv', | ||
], | ||
}, | ||
'depends': [ | ||
'base', 'web', | ||
], | ||
'data': [ | ||
'views/webclient_templates.xml', | ||
], | ||
'demo': [ | ||
'demo/report.xml', | ||
], | ||
'installable': True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Copyright (C) 2019 Creu Blanca | ||
# 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 | ||
|
||
import json | ||
|
||
|
||
class ReportController(report.ReportController): | ||
@route() | ||
def report_routes(self, reportname, docids=None, converter=None, **data): | ||
if converter == 'csv': | ||
report = request.env['ir.actions.report']._get_report_from_name( | ||
reportname) | ||
context = dict(request.env.context) | ||
if docids: | ||
docids = [int(i) for i in docids.split(',')] | ||
if data.get('options'): | ||
data.update(json.loads(data.pop('options'))) | ||
if data.get('context'): | ||
# Ignore 'lang' here, because the context in data is the one | ||
# from the webclient *but* if the user explicitely wants to | ||
# change the lang, this mechanism overwrites it. | ||
data['context'] = json.loads(data['context']) | ||
if data['context'].get('lang'): | ||
del data['context']['lang'] | ||
context.update(data['context']) | ||
csv = report.with_context(context).render_csv( | ||
docids, data=data | ||
)[0] | ||
csvhttpheaders = [ | ||
('Content-Type', 'text/csv'), | ||
('Content-Length', len(csv)), | ||
( | ||
'Content-Disposition', | ||
content_disposition(report.report_file + '.csv') | ||
) | ||
] | ||
return request.make_response(csv, headers=csvhttpheaders) | ||
return super(ReportController, self).report_routes( | ||
reportname, docids, converter, **data | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<odoo> | ||
<!-- | ||
© 2017 Creu Blanca | ||
License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). | ||
--> | ||
<report | ||
id="partner_csv" | ||
model="res.partner" | ||
string="Print to CSV" | ||
report_type="csv" | ||
name="report_csv.partner_csv" | ||
file="res_partner" | ||
attachment_use="False" | ||
/> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import ir_report |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Copyright 2019 Creu Blanca | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). | ||
|
||
from odoo import api, fields, models, _ | ||
from odoo.exceptions import UserError | ||
|
||
|
||
class ReportAction(models.Model): | ||
_inherit = 'ir.actions.report' | ||
|
||
report_type = fields.Selection(selection_add=[("csv", "csv")]) | ||
|
||
@api.model | ||
def render_csv(self, docids, data): | ||
report_model_name = 'report.%s' % self.report_name | ||
report_model = self.env.get(report_model_name) | ||
if report_model is None: | ||
raise UserError(_('%s model was not found' % report_model_name)) | ||
return report_model.with_context({ | ||
'active_model': self.model | ||
}).create_csv_report(docids, data) | ||
|
||
@api.model | ||
def _get_report_from_name(self, report_name): | ||
res = super(ReportAction, self)._get_report_from_name(report_name) | ||
if res: | ||
return res | ||
report_obj = self.env['ir.actions.report'] | ||
qwebtypes = ['csv'] | ||
conditions = [('report_type', 'in', qwebtypes), | ||
('report_name', '=', report_name)] | ||
context = self.env['res.users'].context_get() | ||
return report_obj.with_context(context).search(conditions, limit=1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from . import report_csv | ||
from . import report_partner_csv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Copyright 2019 Creu Blanca | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). | ||
|
||
from io import StringIO | ||
|
||
from odoo import models | ||
|
||
import logging | ||
_logger = logging.getLogger(__name__) | ||
|
||
try: | ||
import csv | ||
except ImportError: | ||
_logger.debug('Can not import csvwriter`.') | ||
|
||
|
||
class ReportCSVAbstract(models.AbstractModel): | ||
_name = 'report.report_csv.abstract' | ||
|
||
def _get_objs_for_report(self, docids, data): | ||
""" | ||
Returns objects for csv report. From WebUI these | ||
are either as docids taken from context.active_ids or | ||
in the case of wizard are in data. Manual calls may rely | ||
on regular context, setting docids, or setting data. | ||
:param docids: list of integers, typically provided by | ||
qwebactionmanager for regular Models. | ||
:param data: dictionary of data, if present typically provided | ||
by qwebactionmanager for TransientModels. | ||
:param ids: list of integers, provided by overrides. | ||
:return: recordset of active model for ids. | ||
""" | ||
if docids: | ||
ids = docids | ||
elif data and 'context' in data: | ||
ids = data["context"].get('active_ids', []) | ||
else: | ||
ids = self.env.context.get('active_ids', []) | ||
return self.env[self.env.context.get('active_model')].browse(ids) | ||
|
||
def create_csv_report(self, docids, data): | ||
objs = self._get_objs_for_report(docids, data) | ||
file_data = StringIO() | ||
file = csv.DictWriter(file_data, **self.csv_report_options()) | ||
self.generate_csv_report(file, data, objs) | ||
file_data.seek(0) | ||
return file_data.read(), 'csv' | ||
|
||
def csv_report_options(self): | ||
return {'fieldnames': []} | ||
|
||
def generate_csv_report(self, file, data, objs): | ||
raise NotImplementedError() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Copyright 2019 Creu Blanca | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). | ||
|
||
from odoo import models | ||
|
||
|
||
class PartnerCSV(models.AbstractModel): | ||
_name = 'report.report_csv.partner_csv' | ||
_inherit = 'report.report_csv.abstract' | ||
|
||
def generate_csv_report(self, writer, data, partners): | ||
for obj in partners: | ||
writer.writeheader() | ||
writer.writerow({ | ||
'name': obj.name | ||
}) | ||
|
||
def csv_report_options(self): | ||
res = super().csv_report_options() | ||
res['fieldnames'].append('name') | ||
return res |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// © 2019 Creu Blanca | ||
// License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). | ||
odoo.define('report_csv.report', function(require){ | ||
'use strict'; | ||
|
||
var ActionManager= require('web.ActionManager'); | ||
var crash_manager = require('web.crash_manager'); | ||
var framework = require('web.framework'); | ||
|
||
ActionManager.include({ | ||
ir_actions_report: function (action, options){ | ||
var self = this; | ||
var cloned_action = _.clone(action); | ||
if (cloned_action.report_type === 'csv') { | ||
framework.blockUI(); | ||
var report_csv_url = 'report/csv/' + cloned_action.report_name; | ||
if (_.isUndefined(cloned_action.data) || | ||
_.isNull(cloned_action.data) || | ||
(_.isObject(cloned_action.data) && _.isEmpty(cloned_action.data))) | ||
{ | ||
if(cloned_action.context.active_ids) { | ||
report_csv_url += '/' + cloned_action.context.active_ids.join(','); | ||
} | ||
} else { | ||
report_csv_url += '?options=' + encodeURIComponent(JSON.stringify(cloned_action.data)); | ||
report_csv_url += '&context=' + encodeURIComponent(JSON.stringify(cloned_action.context)); | ||
} | ||
self.getSession().get_file({ | ||
url: report_csv_url, | ||
data: {data: JSON.stringify([ | ||
report_csv_url, | ||
cloned_action.report_type | ||
])}, | ||
error: crash_manager.rpc_error.bind(crash_manager), | ||
success: function (){ | ||
if(cloned_action && options && !cloned_action.dialog){ | ||
options.on_close(); | ||
} | ||
} | ||
}); | ||
framework.unblockUI(); | ||
return; | ||
} | ||
return self._super(action, options); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import test_report |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Copyright 2019 Creu Blanca | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). | ||
from io import StringIO | ||
from odoo.tests import common | ||
import logging | ||
_logger = logging.getLogger(__name__) | ||
try: | ||
import csv | ||
except ImportError: | ||
_logger.debug('Can not import csv.') | ||
|
||
|
||
class TestReport(common.TransactionCase): | ||
def setUp(self): | ||
super().setUp() | ||
report_object = self.env['ir.actions.report'] | ||
self.csv_report = ( | ||
self.env['report.report_csv.abstract'] | ||
.with_context(active_model='res.partner') | ||
) | ||
self.report_name = 'report_csv.partner_csv' | ||
self.report = report_object._get_report_from_name(self.report_name) | ||
self.docs = self.env['res.company'].search([], limit=1).partner_id | ||
|
||
def test_report(self): | ||
report = self.report | ||
self.assertEqual(report.report_type, 'csv') | ||
rep = report.render(self.docs.ids, {}) | ||
str_io = StringIO(rep[0]) | ||
dict_report = list(csv.DictReader(str_io)) | ||
self.assertEqual(self.docs.name, dict(dict_report[0])['name']) | ||
|
||
def test_id_retrieval(self): | ||
|
||
# Typical call from WebUI with wizard | ||
objs = self.csv_report._get_objs_for_report( | ||
False, {"context": {"active_ids": self.docs.ids}}) | ||
self.assertEquals(objs, self.docs) | ||
|
||
# Typical call from within code not to report_action | ||
objs = self.csv_report.with_context( | ||
active_ids=self.docs.ids)._get_objs_for_report(False, False) | ||
self.assertEquals(objs, self.docs) | ||
|
||
# Typical call from WebUI | ||
objs = self.csv_report._get_objs_for_report( | ||
self.docs.ids, | ||
{"data": [self.report_name, self.report.report_type]} | ||
) | ||
self.assertEquals(objs, self.docs) | ||
|
||
# Typical call from render | ||
objs = self.csv_report._get_objs_for_report(self.docs.ids, {}) | ||
self.assertEquals(objs, self.docs) |
Oops, something went wrong.