Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
14dfa20
[ADD] report_csv
etobella Feb 5, 2019
db07332
[IMP] report_csv: use dialects
JordiBForgeFlow Feb 5, 2019
0a2a729
[IMP] report_csv: allow to evaluate print_report_name for multiple re…
JordiBForgeFlow Feb 7, 2019
872752a
[IMP] report_csv: pass multi variable to be able to distingish which …
LoisRForgeFlow Feb 7, 2019
b439048
[12.0][MIG] report_csv
Jul 2, 2019
a6fd3c5
[IMP] report_csv: black, isort
kongrattapong Feb 21, 2020
f15d441
[MIG] report_csv: Migration to 13.0
kongrattapong Feb 21, 2020
93e69cb
[FIX] report_py3o: prettier xml after merge with master
lmignon May 12, 2020
adfc231
[FIX] eslint error
lmignon May 13, 2020
00a4d68
[FIX] make prettier happy
sbidoul May 13, 2020
6dba10b
[IMP] report_csv: black, isort, prettier
tupaq Oct 15, 2020
ceeca65
[MIG] report_csv: Migration to 14.0
tupaq Oct 15, 2020
4de2b67
[IMP] report_csv : black, isort, prettier
Apr 5, 2022
bdc5c04
[MIG] report_csv: Migration to 15.0
Apr 5, 2022
71e8894
[MIG] report_csv: Migration to 16.0
AnizR Nov 8, 2022
e45004d
[FIX] report_csv: Assign 'reportname' variable before accessing it
rousseldenis Jun 26, 2023
918094d
[FIX] report_csv: Return werkzeug Exception
rousseldenis Jun 27, 2023
90ab4b1
[IMP] report_csv: Add controller tests
rousseldenis Jun 27, 2023
135c56d
[IMP] report_csv: add encoding option
AungKoKoLin1997 Jan 18, 2023
044a51a
Added translation using Weblate (Italian)
mymage Jan 10, 2024
7a65fde
Added translation using Weblate (Spanish)
Ivorra78 Apr 22, 2024
9c68ef8
[16.0][IMP] report_csv: support attachment use
sbejaoui Sep 26, 2023
d0747e7
[IMP] report_csv: pre-commit auto fixes
victoralmau Feb 21, 2025
b36db50
[MIG] report_csv: Migration to 17.0
victoralmau Feb 21, 2025
4f758ff
[UPD] Update report_csv.pot
Mar 4, 2025
49b9b27
[BOT] post-merge updates
OCA-git-bot Mar 4, 2025
dd568cc
[DCK] report_csv: Add development_status key to manifest
victoralmau Mar 4, 2025
cedc0fb
[BOT] post-merge updates
OCA-git-bot Mar 4, 2025
a122003
[IMP] report_csv: black, isort, prettier
JasminSForgeFlow Mar 26, 2025
289a7d0
[MIG] report_csv: Migration to 18.0
JasminSForgeFlow Mar 26, 2025
267b949
[UPD] Update report_csv.pot
Apr 23, 2025
7289f19
[BOT] post-merge updates
OCA-git-bot Apr 23, 2025
5acc2ce
Added translation using Weblate (Portuguese (Brazil))
marcelsavegnago Jul 1, 2025
c5ed60b
[FIX] report_csv: make it working if docids is None
maisim Jan 8, 2025
a161cd4
[MIG] report_csv: Migration to 19.0
sergijPf Feb 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions report_csv/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

===============
Base report csv
===============

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:380b9dc8c98a77b37a8e5e5846b3ddc471dcbf470c9805cc5f9a04f2e4913f12
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
:target: https://odoo-community.org/page/development-status
:alt: Production/Stable
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
:target: https://github.com/OCA/reporting-engine/tree/19.0/report_csv
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/reporting-engine-19-0/reporting-engine-19-0-report_csv
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module provides a basic report class to generate csv report.

**Table of contents**

.. contents::
: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
=====

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.report_csv.partner_csv'
_inherit = 'report.report_csv.abstract'

def generate_csv_report(self, writer, data, partners):
writer.writeheader()
for obj in partners:
writer.writerow({
'name': obj.name,
'email': obj.email,
})

def csv_report_options(self):
res = super().csv_report_options()
res['fieldnames'].append('name')
res['fieldnames'].append('email')
res['delimiter'] = ';'
res['quoting'] = csv.QUOTE_ALL
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"
/>

Update encoding with an appropriate value (e.g. cp932) as necessary.

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 to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_csv%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Creu Blanca

Contributors
------------

- Enric Tobella <[email protected]>
- Jaime Arroyo <[email protected]>
- Rattapong Chokmasermkul <[email protected]>
- `Quartile <https://www.quartile.co>`__:

- Aung Ko Ko Lin

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

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.

This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/19.0/report_csv>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
3 changes: 3 additions & 0 deletions report_csv/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import controllers
from . import models
from . import report
21 changes: 21 additions & 0 deletions report_csv/__manifest__.py
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).
{
"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": "19.0.1.0.0",
"license": "AGPL-3",
"depends": ["base", "web"],
"demo": ["demo/report.xml"],
"data": ["views/ir_actions_views.xml"],
"assets": {
"web.assets_backend": [
"report_csv/static/src/js/report/qwebactionmanager.esm.js"
]
},
"development_status": "Production/Stable",
"installable": True,
}
1 change: 1 addition & 0 deletions report_csv/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import main
111 changes: 111 additions & 0 deletions report_csv/controllers/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Copyright (C) 2019 Creu Blanca
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).

import json
import logging

from werkzeug.exceptions import InternalServerError
from werkzeug.urls import url_decode

from odoo.http import (
content_disposition,
request,
route,
)
from odoo.http import (
serialize_exception as _serialize_exception,
)
from odoo.tools import html_escape
from odoo.tools.safe_eval import safe_eval, time

from odoo.addons.web.controllers import report

_logger = logging.getLogger(__name__)


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(
reportname, docids, data=data
)[0]
csvhttpheaders = [
("Content-Type", "text/csv"),
("Content-Length", len(csv)),
]
return request.make_response(csv, headers=csvhttpheaders)
return super().report_routes(reportname, docids, converter, **data)

@route()
def report_download(self, data, context=None, token=None, readonly=True):
requestcontent = json.loads(data)
url, report_type = requestcontent[0], requestcontent[1]
reportname = ""
try:
if report_type == "csv":
reportname = url.split("/report/csv/")[1].split("?")[0]
docids = None
if "/" in reportname:
reportname, docids = reportname.split("/")
if docids:
# Generic report:
response = self.report_routes(
reportname, docids=docids, converter="csv", context=context
)
else:
# Particular report:
data = dict(
url_decode(url.split("?")[1]).items()
) # decoding the args represented in JSON
if "context" in data:
context, data_context = (
json.loads(context or "{}"),
json.loads(data.pop("context")),
)
context = json.dumps({**context, **data_context})
response = self.report_routes(
reportname, converter="csv", context=context, **data
)

report = request.env["ir.actions.report"]._get_report_from_name(
reportname
)
filename = f"{report.name}.csv"

if docids:
ids = [int(x) for x in docids.split(",")]
obj = request.env[report.model].browse(ids)
if report.print_report_name and not len(obj) > 1:
report_name = safe_eval(
report.print_report_name, {"object": obj, "time": time}
)
filename = f"{report_name}.csv"
response.headers.add(
"Content-Disposition", content_disposition(filename)
)
return response
else:
return super().report_download(
data, context, token=token, readonly=readonly
)
except Exception as e:
_logger.exception("Error while generating report %s", reportname)
se = _serialize_exception(e)
error = {"code": 200, "message": "Odoo Server Error", "data": se}
res = request.make_response(html_escape(json.dumps(error)))
raise InternalServerError(response=res) from e
14 changes: 14 additions & 0 deletions report_csv/demo/report.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--
Copyright 2019 Creu Blanca
License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
-->
<record id="partner_csv" model="ir.actions.report">
<field name="name">Print to CSV</field>
<field name="model">res.partner</field>
<field name="report_type">csv</field>
<field name="report_name">report_csv.partner_csv</field>
<field name="report_file">res_partner</field>
</record>
</odoo>
Loading