From 917f25e3a56f320810f47a25d97e8a754d5d8f83 Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:00:01 +0200 Subject: [PATCH 1/9] [19.0] base_import_async: migrate Scope: base_import_async only --- base_import_async/README.rst | 16 +++++--- base_import_async/__manifest__.py | 4 +- .../models/base_import_import.py | 2 +- .../static/description/index.html | 38 +++++++++++-------- test-requirements.txt | 1 + 5 files changed, 36 insertions(+), 25 deletions(-) create mode 100644 test-requirements.txt diff --git a/base_import_async/README.rst b/base_import_async/README.rst index 030c371758..5c873466aa 100644 --- a/base_import_async/README.rst +++ b/base_import_async/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + =================== Asynchronous Import =================== @@ -13,17 +17,17 @@ Asynchronous Import .. |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/licence-AGPL--3-blue.png +.. |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%2Fqueue-lightgray.png?logo=github - :target: https://github.com/OCA/queue/tree/18.0/base_import_async + :target: https://github.com/OCA/queue/tree/19.0/base_import_async :alt: OCA/queue .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/queue-18-0/queue-18-0-base_import_async + :target: https://translation.odoo-community.org/projects/queue-19-0/queue-19-0-base_import_async :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/queue&target_branch=18.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/queue&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -87,7 +91,7 @@ Bug Tracker Bugs are tracked on `GitHub 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -149,6 +153,6 @@ 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/queue `_ project on GitHub. +This module is part of the `OCA/queue `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_import_async/__manifest__.py b/base_import_async/__manifest__.py index 5432d7c5ca..58dd6eb8b0 100644 --- a/base_import_async/__manifest__.py +++ b/base_import_async/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Asynchronous Import", "summary": "Import CSV files in the background", - "version": "18.0.1.0.0", + "version": "19.0.1.0.0", "author": "Akretion, ACSONE SA/NV, Odoo Community Association (OCA)", "license": "AGPL-3", "website": "https://github.com/OCA/queue", @@ -20,6 +20,6 @@ "base_import_async/static/src/xml/import_data_sidepanel.xml", ], }, - "installable": False, + "installable": True, "development_status": "Production/Stable", } diff --git a/base_import_async/models/base_import_import.py b/base_import_async/models/base_import_import.py index f77a4bbc59..4c42cd0b31 100644 --- a/base_import_async/models/base_import_import.py +++ b/base_import_async/models/base_import_import.py @@ -78,8 +78,8 @@ def _link_attachment_to_job(self, delayed_job, attachment): ) attachment.write({"res_model": "queue.job", "res_id": queue_job.id}) - @api.returns("ir.attachment") def _create_csv_attachment(self, fields, data, options, file_name): + # Odoo 19: @api.returns decorator removed; just return the recordset. # write csv f = StringIO() writer = csv.writer( diff --git a/base_import_async/static/description/index.html b/base_import_async/static/description/index.html index 2994cf9efa..132578a26e 100644 --- a/base_import_async/static/description/index.html +++ b/base_import_async/static/description/index.html @@ -3,7 +3,7 @@ -Asynchronous Import +README.rst -
-

Asynchronous Import

+
+ + +Odoo Community Association + +
+

Asynchronous Import

-

Production/Stable License: AGPL-3 OCA/queue Translate me on Weblate Try me on Runboat

+

Production/Stable License: AGPL-3 OCA/queue Translate me on Weblate Try me on Runboat

This module extends the standard CSV import functionality to import files in the background using the OCA/queue framework.

Table of contents

@@ -392,7 +397,7 @@

Asynchronous Import

-

Usage

+

Usage

The user is presented with a new checkbox in the import screen. When selected, the import is delayed in a background job.

This job in turn splits the CSV file in chunks of minimum 100 lines (or @@ -416,7 +421,7 @@

Usage

-

Known issues / Roadmap

+

Known issues / Roadmap

  • There is currently no user interface to control the chunk size, which is currently 100 by default. Should this proves to be an issue, it is @@ -425,33 +430,33 @@

    Known issues / Roadmap

-

Changelog

+

Changelog

-

13.0.1.0.0 (2019-12-20)

+

13.0.1.0.0 (2019-12-20)

  • [MIGRATION] from 12.0 branched at rev. a7f8031
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub 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.

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Akretion
  • ACSONE SA/NV
-

Contributors

+

Contributors

Sébastien Beau (Akretion) authored the initial prototype.

Stéphane Bidoul (ACSONE) extended it to version 1.0 to support multi-line records, store data to import as attachments and let the user @@ -473,12 +478,12 @@

Contributors

-

Other credits

+

Other credits

The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -486,10 +491,11 @@

Maintainers

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/queue project on GitHub.

+

This module is part of the OCA/queue project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 0000000000..b1f46fe1b4 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +odoo-addon-queue_job @ git+https://github.com/OCA/queue.git@refs/pull/840/head#subdirectory=queue_job From 47f6b496b1a33d14ffa557eae02d0d5090865321 Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:00:01 +0200 Subject: [PATCH 2/9] [DON'T MERGE] test-requirements.txt From d0fb9d83b16cb46dddb792b7fcf59cf961130484 Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:00:05 +0200 Subject: [PATCH 3/9] [pre-commit] auto-fixes for base_import_async scope --- .pre-commit-config.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d0fa1036b..338be17dd6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,6 @@ exclude: | (?x) # NOT INSTALLABLE ADDONS - ^base_import_async/| ^queue_job/| ^queue_job_batch/| ^queue_job_cron/| From 646a18644a1ddb91758bc9aed376a0fa1fd14550 Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:05:19 +0200 Subject: [PATCH 4/9] [pre-commit] auto-fixes for base_import_async (imports, requirements cleanup) --- base_import_async/models/base_import_import.py | 2 +- requirements.txt | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 requirements.txt diff --git a/base_import_async/models/base_import_import.py b/base_import_async/models/base_import_import.py index 4c42cd0b31..34a65bae57 100644 --- a/base_import_async/models/base_import_import.py +++ b/base_import_async/models/base_import_import.py @@ -9,7 +9,7 @@ from io import BytesIO, StringIO, TextIOWrapper from os.path import splitext -from odoo import _, api, models +from odoo import _, models from odoo.models import fix_import_export_id_paths from odoo.addons.base_import.models.base_import import ImportValidationError diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index b4d39fb9e0..0000000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -# generated from manifests external_dependencies -requests From e44bf84382cb39c7965bf6d44f3002f7a55de3d9 Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:09:51 +0200 Subject: [PATCH 5/9] [lint] base_import_async: move TransientModel to wizard/, fix translations --- base_import_async/__init__.py | 1 + base_import_async/models/queue_job.py | 4 +-- base_import_async/wizard/__init__.py | 4 +++ .../{models => wizard}/base_import_import.py | 34 ++++++++----------- 4 files changed, 22 insertions(+), 21 deletions(-) create mode 100644 base_import_async/wizard/__init__.py rename base_import_async/{models => wizard}/base_import_import.py (90%) diff --git a/base_import_async/__init__.py b/base_import_async/__init__.py index 31660d6a96..93aa2c1f84 100644 --- a/base_import_async/__init__.py +++ b/base_import_async/__init__.py @@ -1,3 +1,4 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import models +from . import wizard diff --git a/base_import_async/models/queue_job.py b/base_import_async/models/queue_job.py index b7313505f3..f3034e9d54 100644 --- a/base_import_async/models/queue_job.py +++ b/base_import_async/models/queue_job.py @@ -1,7 +1,7 @@ # Copyright 2017 ACSONE SA/NV # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from odoo import _, models +from odoo import models class QueueJob(models.Model): @@ -11,7 +11,7 @@ class QueueJob(models.Model): def _related_action_attachment(self): return { - "name": _("Attachment"), + "name": self.env._("Attachment"), "type": "ir.actions.act_window", "res_model": "ir.attachment", "view_mode": "form", diff --git a/base_import_async/wizard/__init__.py b/base_import_async/wizard/__init__.py new file mode 100644 index 0000000000..0f53be19c4 --- /dev/null +++ b/base_import_async/wizard/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import base_import_import + diff --git a/base_import_async/models/base_import_import.py b/base_import_async/wizard/base_import_import.py similarity index 90% rename from base_import_async/models/base_import_import.py rename to base_import_async/wizard/base_import_import.py index 34a65bae57..eeac18101d 100644 --- a/base_import_async/models/base_import_import.py +++ b/base_import_async/wizard/base_import_import.py @@ -9,7 +9,7 @@ from io import BytesIO, StringIO, TextIOWrapper from os.path import splitext -from odoo import _, models +from odoo import models from odoo.models import fix_import_export_id_paths from odoo.addons.base_import.models.base_import import ImportValidationError @@ -55,10 +55,11 @@ def execute_import(self, fields, columns, options, dryrun=False): translated_model_name = search_result[0][1] else: translated_model_name = self._description - description = _("Import %(model)s from file %(from_file)s") % { - "model": translated_model_name, - "from_file": self.file_name, - } + description = self.env._( + "Import %s from file %s", + translated_model_name, + self.file_name, + ) attachment = self._create_csv_attachment( import_fields, data, options, self.file_name ) @@ -146,26 +147,20 @@ def _split_file( fields, data = self._read_csv_attachment(attachment, options) padding = len(str(len(data))) priority = options.get(OPT_PRIORITY, INIT_PRIORITY) - if options.get(OPT_HAS_HEADER): - header_offset = 1 - else: - header_offset = 0 + header_offset = 1 if options.get(OPT_HAS_HEADER) else 0 chunk_size = options.get(OPT_CHUNK_SIZE) or DEFAULT_CHUNK_SIZE for row_from, row_to in self._extract_chunks( model_obj, fields, data, chunk_size ): chunk = str(priority - INIT_PRIORITY).zfill(padding) - description = _( - "Import %(model)s from file %(file_name)s - " - "#%(chunk)s - lines %(from)s to %(to)s" + description = self.env._( + "Import %s from file %s - #%s - lines %s to %s", + translated_model_name, + file_name, + chunk, + row_from + 1 + header_offset, + row_to + 1 + header_offset, ) - description = description % { - "model": translated_model_name, - "file_name": file_name, - "chunk": chunk, - "from": row_from + 1 + header_offset, - "to": row_to + 1 + header_offset, - } # create a CSV attachment and enqueue the job root, ext = splitext(file_name) attachment = self._create_csv_attachment( @@ -194,3 +189,4 @@ def _import_one_chunk(self, model_name, attachment, options): if error_message: raise FailedJobError("\n".join(error_message)) return result + From 51ae203d9f83ced74d8670565d0e9a089304d6c8 Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:10:12 +0200 Subject: [PATCH 6/9] [pre-commit] fix end-of-file newline in wizard files --- base_import_async/wizard/__init__.py | 1 - base_import_async/wizard/base_import_import.py | 1 - 2 files changed, 2 deletions(-) diff --git a/base_import_async/wizard/__init__.py b/base_import_async/wizard/__init__.py index 0f53be19c4..695ed69ea5 100644 --- a/base_import_async/wizard/__init__.py +++ b/base_import_async/wizard/__init__.py @@ -1,4 +1,3 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from . import base_import_import - diff --git a/base_import_async/wizard/base_import_import.py b/base_import_async/wizard/base_import_import.py index eeac18101d..7416e9debb 100644 --- a/base_import_async/wizard/base_import_import.py +++ b/base_import_async/wizard/base_import_import.py @@ -189,4 +189,3 @@ def _import_one_chunk(self, model_name, attachment, options): if error_message: raise FailedJobError("\n".join(error_message)) return result - From 8d75b73f87b43c9a5ff411ccdc8ec0df95154413 Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:13:05 +0200 Subject: [PATCH 7/9] [lint] base_import_async: named placeholders + wrap long line --- .../wizard/base_import_import.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/base_import_async/wizard/base_import_import.py b/base_import_async/wizard/base_import_import.py index 7416e9debb..b8d3e30acf 100644 --- a/base_import_async/wizard/base_import_import.py +++ b/base_import_async/wizard/base_import_import.py @@ -56,9 +56,9 @@ def execute_import(self, fields, columns, options, dryrun=False): else: translated_model_name = self._description description = self.env._( - "Import %s from file %s", - translated_model_name, - self.file_name, + "Import %(model)s from file %(file_name)s", + model=translated_model_name, + file_name=self.file_name, ) attachment = self._create_csv_attachment( import_fields, data, options, self.file_name @@ -154,12 +154,15 @@ def _split_file( ): chunk = str(priority - INIT_PRIORITY).zfill(padding) description = self.env._( - "Import %s from file %s - #%s - lines %s to %s", - translated_model_name, - file_name, - chunk, - row_from + 1 + header_offset, - row_to + 1 + header_offset, + ( + "Import %(model)s from file %(file_name)s - #%(chunk)s - " + "lines %(from_line)s to %(to_line)s" + ), + model=translated_model_name, + file_name=file_name, + chunk=chunk, + from_line=row_from + 1 + header_offset, + to_line=row_to + 1 + header_offset, ) # create a CSV attachment and enqueue the job root, ext = splitext(file_name) From 177b4a1f5e6de6328350dc679fb2e7b4c35242d1 Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:26:32 +0200 Subject: [PATCH 8/9] [fix] base_import_async: remove stale import from models/__init__.py --- base_import_async/models/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/base_import_async/models/__init__.py b/base_import_async/models/__init__.py index 2af21f4102..b54b6491b9 100644 --- a/base_import_async/models/__init__.py +++ b/base_import_async/models/__init__.py @@ -1,4 +1,3 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -from . import base_import_import from . import queue_job From 7d02e1f223ece3193a78fa9257dd604ba73c920f Mon Sep 17 00:00:00 2001 From: Milan Topuzov Date: Wed, 1 Oct 2025 19:30:15 +0200 Subject: [PATCH 9/9] [tests] base_import_async: update import path to wizard for OPT_USE_QUEUE --- base_import_async/tests/test_base_import_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base_import_async/tests/test_base_import_import.py b/base_import_async/tests/test_base_import_import.py index 4a815d6707..a6ec20da61 100644 --- a/base_import_async/tests/test_base_import_import.py +++ b/base_import_async/tests/test_base_import_import.py @@ -3,7 +3,7 @@ from odoo.tests.common import RecordCapturer, TransactionCase -from ..models.base_import_import import OPT_USE_QUEUE +from ..wizard.base_import_import import OPT_USE_QUEUE class TestBaseImportImport(TransactionCase):