mirror of
https://github.com/OCA/reporting-engine.git
synced 2025-02-16 16:30:38 +02:00
[IMP] report_csv: add encoding option
This commit is contained in:
committed by
Aungkokolin1997
parent
7fcaee191e
commit
5d89b44e47
@@ -7,7 +7,7 @@ Base report csv
|
|||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:ec79b69b51f6950f27d658111240cf9c35f2f74f3431fb23369106bdbd3ca9ab
|
!! source digest: sha256:f2082a65edddcb957a5a22e07ffcd761bf2038fd8fe93322bab2be04b8102557
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||||
@@ -35,6 +35,19 @@ This module provides a basic report class to generate csv report.
|
|||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
=============
|
||||||
|
|
||||||
|
In case the exported CSV report should be encoded in another system than UTF-8, following
|
||||||
|
fields of the report record (*Settings > Technical > Reports*) should be populated accordingly.
|
||||||
|
|
||||||
|
* Encoding: set an encoding system (such as cp932)
|
||||||
|
* Encode Error Handling: select 'Ignore' or 'Replace' as necessary.
|
||||||
|
|
||||||
|
* 'Ignore': in case of an encoding error, the problematic character will be removed from the exported file.
|
||||||
|
* 'Replace': in case of an encoding error, the problematic character will be replaced with '?' symbol.
|
||||||
|
* Leaving the field blank: in case of an encoding error, the report generation fails with an error message.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
@@ -77,6 +90,8 @@ A report XML record ::
|
|||||||
attachment_use="False"
|
attachment_use="False"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
Update encoding with an appropriate value (e.g. cp932) as necessary.
|
||||||
|
|
||||||
Bug Tracker
|
Bug Tracker
|
||||||
===========
|
===========
|
||||||
|
|
||||||
@@ -101,6 +116,9 @@ Contributors
|
|||||||
* Enric Tobella <etobella@creublanca.es>
|
* Enric Tobella <etobella@creublanca.es>
|
||||||
* Jaime Arroyo <jaime.arroyo@creublanca.es>
|
* Jaime Arroyo <jaime.arroyo@creublanca.es>
|
||||||
* Rattapong Chokmasermkul <rattapongc@ecosoft.co.th>
|
* Rattapong Chokmasermkul <rattapongc@ecosoft.co.th>
|
||||||
|
* `Quartile <https://www.quartile.co>`__:
|
||||||
|
|
||||||
|
* Aung Ko Ko Lin
|
||||||
|
|
||||||
Maintainers
|
Maintainers
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
"version": "14.0.1.0.0",
|
"version": "14.0.1.0.0",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"depends": ["base", "web"],
|
"depends": ["base", "web"],
|
||||||
"data": ["views/webclient_templates.xml"],
|
"data": ["views/webclient_templates.xml", "views/ir_actions_views.xml"],
|
||||||
"demo": ["demo/report.xml"],
|
"demo": ["demo/report.xml"],
|
||||||
"installable": True,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ class ReportAction(models.Model):
|
|||||||
report_type = fields.Selection(
|
report_type = fields.Selection(
|
||||||
selection_add=[("csv", "csv")], ondelete={"csv": "set default"}
|
selection_add=[("csv", "csv")], ondelete={"csv": "set default"}
|
||||||
)
|
)
|
||||||
|
encoding = fields.Char(
|
||||||
|
help="Encoding to be applied to the generated CSV file. e.g. cp932"
|
||||||
|
)
|
||||||
|
encode_error_handling = fields.Selection(
|
||||||
|
selection=[("ignore", "Ignore"), ("replace", "Replace")],
|
||||||
|
help="If nothing is selected, CSV export will fail with an error message when "
|
||||||
|
"there is a character that fail to be encoded.",
|
||||||
|
)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _render_csv(self, docids, data):
|
def _render_csv(self, docids, data):
|
||||||
@@ -19,7 +27,11 @@ class ReportAction(models.Model):
|
|||||||
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,
|
||||||
|
"encoding": self.encoding,
|
||||||
|
"encode_error_handling": self.encode_error_handling,
|
||||||
|
}
|
||||||
).create_csv_report(docids, data)
|
).create_csv_report(docids, data)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
|
|||||||
9
report_csv/readme/CONFIGURE.rst
Normal file
9
report_csv/readme/CONFIGURE.rst
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
In case the exported CSV report should be encoded in another system than UTF-8, following
|
||||||
|
fields of the report record (*Settings > Technical > Reports*) should be populated accordingly.
|
||||||
|
|
||||||
|
* Encoding: set an encoding system (such as cp932)
|
||||||
|
* Encode Error Handling: select 'Ignore' or 'Replace' as necessary.
|
||||||
|
|
||||||
|
* 'Ignore': in case of an encoding error, the problematic character will be removed from the exported file.
|
||||||
|
* 'Replace': in case of an encoding error, the problematic character will be replaced with '?' symbol.
|
||||||
|
* Leaving the field blank: in case of an encoding error, the report generation fails with an error message.
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
* Enric Tobella <etobella@creublanca.es>
|
* Enric Tobella <etobella@creublanca.es>
|
||||||
* Jaime Arroyo <jaime.arroyo@creublanca.es>
|
* Jaime Arroyo <jaime.arroyo@creublanca.es>
|
||||||
* Rattapong Chokmasermkul <rattapongc@ecosoft.co.th>
|
* Rattapong Chokmasermkul <rattapongc@ecosoft.co.th>
|
||||||
|
* `Quartile <https://www.quartile.co>`__:
|
||||||
|
|
||||||
|
* Aung Ko Ko Lin
|
||||||
|
|||||||
@@ -36,3 +36,5 @@ A report XML record ::
|
|||||||
file="res_partner"
|
file="res_partner"
|
||||||
attachment_use="False"
|
attachment_use="False"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
Update encoding with an appropriate value (e.g. cp932) as necessary.
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
import logging
|
import logging
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from odoo import models
|
from odoo import _, models
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -46,7 +47,18 @@ 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)
|
||||||
|
encoding = self._context.get("encoding")
|
||||||
|
if not encoding:
|
||||||
return file_data.read(), "csv"
|
return file_data.read(), "csv"
|
||||||
|
error_handling = self._context.get("encode_error_handling")
|
||||||
|
if error_handling:
|
||||||
|
return file_data.read().encode(encoding, errors=error_handling), "csv"
|
||||||
|
try:
|
||||||
|
return file_data.read().encode(encoding), "csv"
|
||||||
|
except Exception:
|
||||||
|
raise UserError(
|
||||||
|
_("Failed to encode the data with the encoding set in the report.")
|
||||||
|
)
|
||||||
|
|
||||||
def csv_report_options(self):
|
def csv_report_options(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -367,25 +367,40 @@ ul.auto-toc {
|
|||||||
!! This file is generated by oca-gen-addon-readme !!
|
!! This file is generated by oca-gen-addon-readme !!
|
||||||
!! changes will be overwritten. !!
|
!! changes will be overwritten. !!
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
!! source digest: sha256:ec79b69b51f6950f27d658111240cf9c35f2f74f3431fb23369106bdbd3ca9ab
|
!! source digest: sha256:f2082a65edddcb957a5a22e07ffcd761bf2038fd8fe93322bab2be04b8102557
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/reporting-engine/tree/14.0/report_csv"><img alt="OCA/reporting-engine" src="https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/reporting-engine-14-0/reporting-engine-14-0-report_csv"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=14.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/reporting-engine/tree/14.0/report_csv"><img alt="OCA/reporting-engine" src="https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/reporting-engine-14-0/reporting-engine-14-0-report_csv"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=14.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
||||||
<p>This module provides a basic report class to generate csv report.</p>
|
<p>This module provides a basic report class to generate csv report.</p>
|
||||||
<p><strong>Table of contents</strong></p>
|
<p><strong>Table of contents</strong></p>
|
||||||
<div class="contents local topic" id="contents">
|
<div class="contents local topic" id="contents">
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
|
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
|
||||||
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
|
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
|
||||||
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
|
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
|
||||||
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
|
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
|
||||||
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
|
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
|
||||||
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
|
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
|
||||||
|
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="configuration">
|
||||||
|
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
|
||||||
|
<p>In case the exported CSV report should be encoded in another system than UTF-8, following
|
||||||
|
fields of the report record (<em>Settings > Technical > Reports</em>) should be populated accordingly.</p>
|
||||||
|
<ul class="simple">
|
||||||
|
<li>Encoding: set an encoding system (such as cp932)</li>
|
||||||
|
<li>Encode Error Handling: select ‘Ignore’ or ‘Replace’ as necessary.<ul>
|
||||||
|
<li>‘Ignore’: in case of an encoding error, the problematic character will be removed from the exported file.</li>
|
||||||
|
<li>‘Replace’: in case of an encoding error, the problematic character will be replaced with ‘?’ symbol.</li>
|
||||||
|
<li>Leaving the field blank: in case of an encoding error, the report generation fails with an error message.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="usage">
|
<div class="section" id="usage">
|
||||||
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
|
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
|
||||||
<p>An example of CSV report for partners on a module called <cite>module_name</cite>:</p>
|
<p>An example of CSV report for partners on a module called <cite>module_name</cite>:</p>
|
||||||
<p>A python class</p>
|
<p>A python class</p>
|
||||||
<pre class="literal-block">
|
<pre class="literal-block">
|
||||||
@@ -423,9 +438,10 @@ class PartnerCSV(models.AbstractModel):
|
|||||||
attachment_use="False"
|
attachment_use="False"
|
||||||
/>
|
/>
|
||||||
</pre>
|
</pre>
|
||||||
|
<p>Update encoding with an appropriate value (e.g. cp932) as necessary.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="bug-tracker">
|
<div class="section" id="bug-tracker">
|
||||||
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
|
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
|
||||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>.
|
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>.
|
||||||
In case of trouble, please check there if your issue has already been reported.
|
In case of trouble, please check there if your issue has already been reported.
|
||||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||||
@@ -433,23 +449,27 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
|
|||||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="credits">
|
<div class="section" id="credits">
|
||||||
<h1><a class="toc-backref" href="#toc-entry-3">Credits</a></h1>
|
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
|
||||||
<div class="section" id="authors">
|
<div class="section" id="authors">
|
||||||
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
|
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Creu Blanca</li>
|
<li>Creu Blanca</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="contributors">
|
<div class="section" id="contributors">
|
||||||
<h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
|
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
|
||||||
<ul class="simple">
|
<ul class="simple">
|
||||||
<li>Enric Tobella <<a class="reference external" href="mailto:etobella@creublanca.es">etobella@creublanca.es</a>></li>
|
<li>Enric Tobella <<a class="reference external" href="mailto:etobella@creublanca.es">etobella@creublanca.es</a>></li>
|
||||||
<li>Jaime Arroyo <<a class="reference external" href="mailto:jaime.arroyo@creublanca.es">jaime.arroyo@creublanca.es</a>></li>
|
<li>Jaime Arroyo <<a class="reference external" href="mailto:jaime.arroyo@creublanca.es">jaime.arroyo@creublanca.es</a>></li>
|
||||||
<li>Rattapong Chokmasermkul <<a class="reference external" href="mailto:rattapongc@ecosoft.co.th">rattapongc@ecosoft.co.th</a>></li>
|
<li>Rattapong Chokmasermkul <<a class="reference external" href="mailto:rattapongc@ecosoft.co.th">rattapongc@ecosoft.co.th</a>></li>
|
||||||
|
<li><a class="reference external" href="https://www.quartile.co">Quartile</a>:<ul>
|
||||||
|
<li>Aung Ko Ko Lin</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="section" id="maintainers">
|
<div class="section" id="maintainers">
|
||||||
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
|
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
|
||||||
<p>This module is maintained by the OCA.</p>
|
<p>This module is maintained by the OCA.</p>
|
||||||
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
||||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
from odoo.exceptions import UserError
|
||||||
from odoo.tests import common
|
from odoo.tests import common
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
@@ -55,3 +56,15 @@ class TestReport(common.TransactionCase):
|
|||||||
# Typical call from render
|
# Typical call from render
|
||||||
objs = self.csv_report._get_objs_for_report(self.docs.ids, {})
|
objs = self.csv_report._get_objs_for_report(self.docs.ids, {})
|
||||||
self.assertEqual(objs, self.docs)
|
self.assertEqual(objs, self.docs)
|
||||||
|
|
||||||
|
def test_report_with_encoding(self):
|
||||||
|
report = self.report
|
||||||
|
report.write({"encoding": "cp932"})
|
||||||
|
rep = report._render_csv(self.docs.ids, {})
|
||||||
|
str_io = StringIO(rep[0].decode())
|
||||||
|
dict_report = list(csv.DictReader(str_io, delimiter=";", quoting=csv.QUOTE_ALL))
|
||||||
|
self.assertEqual(self.docs.name, dict(dict_report[0])["name"])
|
||||||
|
|
||||||
|
report.write({"encoding": "xyz"})
|
||||||
|
with self.assertRaises(UserError):
|
||||||
|
rep = report._render_csv(self.docs.ids, {})
|
||||||
|
|||||||
20
report_csv/views/ir_actions_views.xml
Normal file
20
report_csv/views/ir_actions_views.xml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="act_report_xml_view" model="ir.ui.view">
|
||||||
|
<field name="name">ir.actions.report</field>
|
||||||
|
<field name="model">ir.actions.report</field>
|
||||||
|
<field name="inherit_id" ref="base.act_report_xml_view" />
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//field[@name='report_type']" position="after">
|
||||||
|
<field
|
||||||
|
name="encoding"
|
||||||
|
attrs="{'invisible': [('report_type', '!=', 'csv')]}"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="encode_error_handling"
|
||||||
|
attrs="{'invisible': [('encoding', '=', False)]}"
|
||||||
|
/>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user