Skip to content

Commit 78e714d

Browse files
authored
Merge pull request #938 from OCA/18.0
Syncing from upstream OCA/reporting-engine (18.0)
2 parents b3c82d6 + 7f1f62a commit 78e714d

21 files changed

Lines changed: 823 additions & 1 deletion

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ addon | version | maintainers | summary
5151
[report_xlsx_helper](report_xlsx_helper/) | 18.0.1.0.0 | | Report xlsx helpers
5252
[report_xml](report_xml/) | 18.0.1.1.1 | | Allow to generate XML reports
5353
[sql_export](sql_export/) | 18.0.1.1.1 | <a href='https://github.com/legalsylvain'><img src='https://github.com/legalsylvain.png' width='32' height='32' style='border-radius:50%;' alt='legalsylvain'/></a> <a href='https://github.com/florian-dacosta'><img src='https://github.com/florian-dacosta.png' width='32' height='32' style='border-radius:50%;' alt='florian-dacosta'/></a> | Export data in csv file with SQL requests
54+
[sql_export_delta](sql_export_delta/) | 18.0.1.0.0 | <a href='https://github.com/hbrunn'><img src='https://github.com/hbrunn.png' width='32' height='32' style='border-radius:50%;' alt='hbrunn'/></a> | Support exporting only the changes from last export
5455
[sql_export_excel](sql_export_excel/) | 18.0.1.0.1 | <a href='https://github.com/florian-dacosta'><img src='https://github.com/florian-dacosta.png' width='32' height='32' style='border-radius:50%;' alt='florian-dacosta'/></a> | Allow to export a sql query to an excel file.
5556
[sql_export_mail](sql_export_mail/) | 18.0.1.0.0 | <a href='https://github.com/legalsylvain'><img src='https://github.com/legalsylvain.png' width='32' height='32' style='border-radius:50%;' alt='legalsylvain'/></a> | Send csv file generated by sql query by mail.
5657
[sql_request_abstract](sql_request_abstract/) | 18.0.1.0.0 | <a href='https://github.com/legalsylvain'><img src='https://github.com/legalsylvain.png' width='32' height='32' style='border-radius:50%;' alt='legalsylvain'/></a> | Abstract Model to manage SQL Requests

‎setup/_metapackage/pyproject.toml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "odoo-addons-oca-reporting-engine"
3-
version = "18.0.20260421.0"
3+
version = "18.0.20260608.0"
44
dependencies = [
55
"odoo-addon-base_comment_template==18.0.*",
66
"odoo-addon-bi_sql_editor==18.0.*",
@@ -31,6 +31,7 @@ dependencies = [
3131
"odoo-addon-report_xlsx_helper==18.0.*",
3232
"odoo-addon-report_xml==18.0.*",
3333
"odoo-addon-sql_export==18.0.*",
34+
"odoo-addon-sql_export_delta==18.0.*",
3435
"odoo-addon-sql_export_excel==18.0.*",
3536
"odoo-addon-sql_export_mail==18.0.*",
3637
"odoo-addon-sql_request_abstract==18.0.*",

‎sql_export_delta/README.rst‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
==========================
2+
SQL Export (delta support)
3+
==========================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:dd3a07363d46834fce0fc63546a1d8c36e7aa3460f4cf5fc27a2098e1dfe8237
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Alpha
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
20+
:target: https://github.com/OCA/reporting-engine/tree/18.0/sql_export_delta
21+
:alt: OCA/reporting-engine
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-sql_export_delta
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=18.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This module extends the functionality of ``sql_export`` to allow you to
32+
only export changes between export runs.
33+
34+
.. IMPORTANT::
35+
This is an alpha version, the data model and design can change at any time without warning.
36+
Only for development or testing purpose, do not use in production.
37+
`More details on development status <https://odoo-community.org/page/development-status>`_
38+
39+
**Table of contents**
40+
41+
.. contents::
42+
:local:
43+
44+
Configuration
45+
=============
46+
47+
To configure this module, you need to:
48+
49+
1. Go to an export in draft mode
50+
2. Check the flag 'Delta'
51+
52+
Bug Tracker
53+
===========
54+
55+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/reporting-engine/issues>`_.
56+
In case of trouble, please check there if your issue has already been reported.
57+
If you spotted it first, help us to smash it by providing a detailed and welcomed
58+
`feedback <https://github.com/OCA/reporting-engine/issues/new?body=module:%20sql_export_delta%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
59+
60+
Do not contact contributors directly about support or help with technical issues.
61+
62+
Credits
63+
=======
64+
65+
Authors
66+
-------
67+
68+
* Hunki Enterprises BV
69+
70+
Contributors
71+
------------
72+
73+
- Holger Brunn <mail@hunki-enterprises.com>
74+
(https://hunki-enterprises.com)
75+
- Therp BV info@therp.nl (https://therp.nl)
76+
77+
Maintainers
78+
-----------
79+
80+
This module is maintained by the OCA.
81+
82+
.. image:: https://odoo-community.org/logo.png
83+
:alt: Odoo Community Association
84+
:target: https://odoo-community.org
85+
86+
OCA, or the Odoo Community Association, is a nonprofit organization whose
87+
mission is to support the collaborative development of Odoo features and
88+
promote its widespread use.
89+
90+
.. |maintainer-hbrunn| image:: https://github.com/hbrunn.png?size=40px
91+
:target: https://github.com/hbrunn
92+
:alt: hbrunn
93+
94+
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
95+
96+
|maintainer-hbrunn|
97+
98+
This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/18.0/sql_export_delta>`_ project on GitHub.
99+
100+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

‎sql_export_delta/__init__.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from . import models
2+
from . import wizards
3+
from .hooks import uninstall_hook

‎sql_export_delta/__manifest__.py‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright 2024 Hunki Enterprises BV
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0)
3+
4+
{
5+
"name": "SQL Export (delta support)",
6+
"summary": "Support exporting only the changes from last export",
7+
"version": "18.0.1.0.0",
8+
"development_status": "Alpha",
9+
"category": "Extra Tools",
10+
"website": "https://github.com/OCA/reporting-engine",
11+
"author": "Hunki Enterprises BV, Odoo Community Association (OCA)",
12+
"maintainers": ["hbrunn"],
13+
"license": "AGPL-3",
14+
"uninstall_hook": "uninstall_hook",
15+
"depends": [
16+
"sql_export",
17+
],
18+
"data": [
19+
"views/sql_export.xml",
20+
],
21+
}

‎sql_export_delta/hooks.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Copyright 2024 Hunki Enterprises BV
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0)
3+
4+
5+
def uninstall_hook(env):
6+
for export in env["sql.export"].search([]):
7+
export._export_delta_cleanup(keep_last=False)

‎sql_export_delta/i18n/it.po‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Translation of Odoo Server.
2+
# This file contains the translation of the following modules:
3+
# * sql_export_delta
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: Odoo Server 16.0\n"
8+
"Report-Msgid-Bugs-To: \n"
9+
"PO-Revision-Date: 2024-11-08 11:06+0000\n"
10+
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
11+
"Language-Team: none\n"
12+
"Language: it\n"
13+
"MIME-Version: 1.0\n"
14+
"Content-Type: text/plain; charset=UTF-8\n"
15+
"Content-Transfer-Encoding: \n"
16+
"Plural-Forms: nplurals=2; plural=n != 1;\n"
17+
"X-Generator: Weblate 5.6.2\n"
18+
19+
#. module: sql_export_delta
20+
#: model:ir.model,name:sql_export_delta.model_sql_file_wizard
21+
msgid "Allow the user to save the file with sql request's data"
22+
msgstr "Consente all'utente di salvare il file con i dati della richiesta SQL"
23+
24+
#. module: sql_export_delta
25+
#: model:ir.model.fields,field_description:sql_export_delta.field_sql_export__export_delta
26+
msgid "Delta"
27+
msgstr "Differenza"
28+
29+
#. module: sql_export_delta
30+
#: model:ir.model,name:sql_export_delta.model_sql_export
31+
msgid "SQL export"
32+
msgstr "Esporta SQL"
33+
34+
#. module: sql_export_delta
35+
#: model:ir.model.fields,help:sql_export_delta.field_sql_export__export_delta
36+
msgid ""
37+
"With this checked, the full result of the query will be stored as table in "
38+
"the database, but the file generated will only contain rows not existing in "
39+
"the n-1st export"
40+
msgstr ""
41+
"Se questa opzione è selezionata, il risultato completo della query verrà "
42+
"memorizzato come tabella nel database, ma il file generato conterrà solo "
43+
"righe non esistenti nell'esportazione n-1"
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Translation of Odoo Server.
2+
# This file contains the translation of the following modules:
3+
# * sql_export_delta
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: Odoo Server 18.0\n"
8+
"Report-Msgid-Bugs-To: \n"
9+
"Last-Translator: \n"
10+
"Language-Team: \n"
11+
"MIME-Version: 1.0\n"
12+
"Content-Type: text/plain; charset=UTF-8\n"
13+
"Content-Transfer-Encoding: \n"
14+
"Plural-Forms: \n"
15+
16+
#. module: sql_export_delta
17+
#: model:ir.model,name:sql_export_delta.model_sql_file_wizard
18+
msgid "Allow the user to save the file with sql request's data"
19+
msgstr ""
20+
21+
#. module: sql_export_delta
22+
#: model:ir.model.fields,field_description:sql_export_delta.field_sql_export__export_delta
23+
msgid "Delta"
24+
msgstr ""
25+
26+
#. module: sql_export_delta
27+
#: model:ir.model,name:sql_export_delta.model_sql_export
28+
msgid "SQL export"
29+
msgstr ""
30+
31+
#. module: sql_export_delta
32+
#: model:ir.model.fields,help:sql_export_delta.field_sql_export__export_delta
33+
msgid ""
34+
"With this checked, the full result of the query will be stored as table in "
35+
"the database, but the file generated will only contain rows not existing in "
36+
"the n-1st export"
37+
msgstr ""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import sql_export
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Copyright 2024 Hunki Enterprises BV
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0)
3+
4+
from psycopg2.sql import SQL, Identifier
5+
6+
from odoo import fields, models
7+
8+
9+
class SqlExport(models.Model):
10+
_inherit = "sql.export"
11+
12+
export_delta = fields.Boolean(
13+
string="Delta",
14+
help="With this checked, the full result of the query "
15+
"will be stored as table in the database, but the file generated will "
16+
"only contain rows not existing in the n-1st export",
17+
)
18+
19+
def write(self, vals):
20+
"""Delete previous results when we change the query"""
21+
if "query" in vals:
22+
for this in self:
23+
this._export_delta_cleanup(keep_last=False)
24+
return super().write(vals)
25+
26+
def _execute_sql_request(
27+
self,
28+
params=None,
29+
mode="fetchall",
30+
rollback=True,
31+
view_name=False,
32+
copy_options="CSV HEADER DELIMITER ';'",
33+
header=False,
34+
):
35+
delta_id = self.env.context.get("export_delta_id")
36+
37+
if delta_id:
38+
original_query = self.env.cr.mogrify(self.query, params).decode("utf-8")
39+
result_table = self._export_delta_table_name(delta_id)
40+
table_query = SQL(
41+
"WITH result as ({0}) SELECT * INTO TABLE {1} FROM result"
42+
).format(SQL(original_query), Identifier(result_table))
43+
previous_result_table = self._export_delta_existing_tables()[-1:]
44+
if previous_result_table:
45+
result_query = SQL("SELECT * FROM {0} EXCEPT SELECT * FROM {1}").format(
46+
Identifier(result_table),
47+
Identifier(previous_result_table[0]),
48+
)
49+
else:
50+
result_query = SQL("SELECT * FROM {0}").format(Identifier(result_table))
51+
self.env.cr.execute(table_query)
52+
# inject new query in cache for super to use
53+
self._cache["query"] = result_query
54+
result = super()._execute_sql_request(
55+
params=None,
56+
mode=mode,
57+
rollback=rollback,
58+
view_name=view_name,
59+
copy_options=copy_options,
60+
header=header,
61+
)
62+
self.invalidate_recordset(["query"])
63+
self._export_delta_cleanup(keep_last=True)
64+
else:
65+
result = super()._execute_sql_request(
66+
params=params,
67+
mode=mode,
68+
rollback=rollback,
69+
view_name=view_name,
70+
copy_options=copy_options,
71+
header=header,
72+
)
73+
74+
return result
75+
76+
def _export_delta_table_name(self, identifier):
77+
"""
78+
Return the name of a table to store data for delta export, must end with
79+
{identifier}
80+
"""
81+
return f"sql_export_delta_{self.id}_{identifier}"
82+
83+
def _export_delta_existing_tables(self):
84+
"""Return all table names used for storing data for delta export"""
85+
self.env.cr.execute(
86+
"SELECT table_name FROM information_schema.tables WHERE table_name LIKE %s",
87+
(self._export_delta_table_name("%"),),
88+
)
89+
return sorted(
90+
[name for (name,) in self.env.cr.fetchall()],
91+
key=lambda name: int(name[len(self._export_delta_table_name("")) :]),
92+
)
93+
94+
def _export_delta_cleanup(self, keep_last=True):
95+
"""Delete tables storing data for delta export"""
96+
table_names = self._export_delta_existing_tables()[: -1 if keep_last else None]
97+
for table_name in table_names:
98+
self.env.cr.execute(SQL("DROP TABLE {0}").format(Identifier(table_name)))

0 commit comments

Comments
 (0)