From 903e7af39d342c5a6cfa558ae73d90e73ddbe6a8 Mon Sep 17 00:00:00 2001 From: Kev-Roche Date: Mon, 18 Sep 2023 21:03:08 +0200 Subject: [PATCH 1/3] [14.0][ADD] script_file_import --- script_file_import/__init__.py | 1 + script_file_import/__manifest__.py | 24 ++++++++++++++ script_file_import/models/__init__.py | 2 ++ .../models/abstract_script_processor.py | 33 +++++++++++++++++++ .../models/script_file_import.py | 27 +++++++++++++++ script_file_import/readme/CONTRIBUTORS.rst | 1 + script_file_import/readme/DESCRIPTION.rst | 1 + script_file_import/readme/USAGE.rst | 1 + .../security/ir.model.access.csv | 3 ++ script_file_import/views/menu.xml | 21 ++++++++++++ .../views/script_file_import.xml | 24 ++++++++++++++ .../odoo/addons/script_file_import | 1 + setup/script_file_import/setup.py | 6 ++++ 13 files changed, 145 insertions(+) create mode 100644 script_file_import/__init__.py create mode 100644 script_file_import/__manifest__.py create mode 100644 script_file_import/models/__init__.py create mode 100644 script_file_import/models/abstract_script_processor.py create mode 100644 script_file_import/models/script_file_import.py create mode 100644 script_file_import/readme/CONTRIBUTORS.rst create mode 100644 script_file_import/readme/DESCRIPTION.rst create mode 100644 script_file_import/readme/USAGE.rst create mode 100644 script_file_import/security/ir.model.access.csv create mode 100644 script_file_import/views/menu.xml create mode 100644 script_file_import/views/script_file_import.xml create mode 120000 setup/script_file_import/odoo/addons/script_file_import create mode 100644 setup/script_file_import/setup.py diff --git a/script_file_import/__init__.py b/script_file_import/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/script_file_import/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/script_file_import/__manifest__.py b/script_file_import/__manifest__.py new file mode 100644 index 000000000..8f72673e0 --- /dev/null +++ b/script_file_import/__manifest__.py @@ -0,0 +1,24 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Kévin Roche +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Script File Import", + "summary": "base module for import with script", + "version": "14.0.1.0.0", + "category": "tools", + "website": "https://github.com/akretion/ak-odoo-incubator", + "author": "Akretion, Odoo Community Association (OCA)", + "maintainers": ["Kev-Roche"], + "license": "AGPL-3", + "application": False, + "installable": True, + "depends": [ + "pattern_import_export", + ], + "data": [ + "views/menu.xml", + "views/script_file_import.xml", + "security/ir.model.access.csv", + ], +} diff --git a/script_file_import/models/__init__.py b/script_file_import/models/__init__.py new file mode 100644 index 000000000..7ba9539ab --- /dev/null +++ b/script_file_import/models/__init__.py @@ -0,0 +1,2 @@ +from . import script_file_import +from . import abstract_script_processor diff --git a/script_file_import/models/abstract_script_processor.py b/script_file_import/models/abstract_script_processor.py new file mode 100644 index 000000000..f86146fca --- /dev/null +++ b/script_file_import/models/abstract_script_processor.py @@ -0,0 +1,33 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Kévin Roche +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import csv + +from odoo import models + + +class AbstractScriptProcessor(models.AbstractModel): + _name = "abstract.script.processor" + _description = "Abstract Script Processor" + + def _process_line(self, line): + raise NotImplementedError() + + def run(self, data): + headers = set() + output = [] + for line in csv.reader(data): + output.append(self._process_line(line)) + headers |= set(output.keys()) + return self.write_output(headers, output) + + def write_output(self, headers, output): + writer = csv.DictWriter( + output, + delimiter=",", + quotechar='"', + fieldnames=headers, + ) + + return data diff --git a/script_file_import/models/script_file_import.py b/script_file_import/models/script_file_import.py new file mode 100644 index 000000000..5b8c59f48 --- /dev/null +++ b/script_file_import/models/script_file_import.py @@ -0,0 +1,27 @@ +# Copyright 2023 Akretion (https://www.akretion.com). +# @author Kévin Roche +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ScriptFileImport(models.Model): + _name = "script.file.import" + _description = "Script File Import" + + in_data = fields.Binary(string="Input CSV file", required=True) + + out_data = fields.Binary(string="Output CSV file", readonly=True) + + processor = fields.Selection( + string="Processor", selection="_get_processor", required=True + ) + + def _get_processor(self): + return [] + + def run(self): + selected_processor = dict( + self._fields["processor"]._description_selection(self.env) + ).get(self.processor) + self.out_data = self.env[selected_processor].run(self.in_data) diff --git a/script_file_import/readme/CONTRIBUTORS.rst b/script_file_import/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..dcae277c8 --- /dev/null +++ b/script_file_import/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Kévin Roche diff --git a/script_file_import/readme/DESCRIPTION.rst b/script_file_import/readme/DESCRIPTION.rst new file mode 100644 index 000000000..eb42f57b0 --- /dev/null +++ b/script_file_import/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows to diff --git a/script_file_import/readme/USAGE.rst b/script_file_import/readme/USAGE.rst new file mode 100644 index 000000000..eb42f57b0 --- /dev/null +++ b/script_file_import/readme/USAGE.rst @@ -0,0 +1 @@ +This module allows to diff --git a/script_file_import/security/ir.model.access.csv b/script_file_import/security/ir.model.access.csv new file mode 100644 index 000000000..761058f9c --- /dev/null +++ b/script_file_import/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_script_file_import,script.file.import.user,model_script_file_import,base.group_user,1,1,1,1 +access_abstract_script_processor,abstract.script.processor.user,model_abstract_script_processor,base.group_user,1,1,1,1 diff --git a/script_file_import/views/menu.xml b/script_file_import/views/menu.xml new file mode 100644 index 000000000..c4fa43eec --- /dev/null +++ b/script_file_import/views/menu.xml @@ -0,0 +1,21 @@ + + + + + Script File Import + ir.actions.act_window + script.file.import + form + + + + diff --git a/script_file_import/views/script_file_import.xml b/script_file_import/views/script_file_import.xml new file mode 100644 index 000000000..9b25ad90c --- /dev/null +++ b/script_file_import/views/script_file_import.xml @@ -0,0 +1,24 @@ + + + + + script_file_import_form + script.file.import + +
+
+
+ + + + + + + +
+
+
+
diff --git a/setup/script_file_import/odoo/addons/script_file_import b/setup/script_file_import/odoo/addons/script_file_import new file mode 120000 index 000000000..a98060335 --- /dev/null +++ b/setup/script_file_import/odoo/addons/script_file_import @@ -0,0 +1 @@ +../../../../script_file_import \ No newline at end of file diff --git a/setup/script_file_import/setup.py b/setup/script_file_import/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/script_file_import/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From b7cfce7271a72bc3d76fc3d3d1f91fe7931e96af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Tue, 19 Sep 2023 00:23:22 +0200 Subject: [PATCH 2/3] script_file_import: improve ui, fix import --- .../models/abstract_script_processor.py | 40 ++++++++++++++----- .../models/script_file_import.py | 24 +++++++++-- .../views/script_file_import.xml | 21 ++++++++-- 3 files changed, 67 insertions(+), 18 deletions(-) diff --git a/script_file_import/models/abstract_script_processor.py b/script_file_import/models/abstract_script_processor.py index f86146fca..ff8fa85a7 100644 --- a/script_file_import/models/abstract_script_processor.py +++ b/script_file_import/models/abstract_script_processor.py @@ -2,10 +2,15 @@ # @author Kévin Roche # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import base64 import csv +import io +import logging from odoo import models +_logger = logging.getLogger(__name__) + class AbstractScriptProcessor(models.AbstractModel): _name = "abstract.script.processor" @@ -17,17 +22,30 @@ def _process_line(self, line): def run(self, data): headers = set() output = [] - for line in csv.reader(data): - output.append(self._process_line(line)) - headers |= set(output.keys()) - return self.write_output(headers, output) - - def write_output(self, headers, output): + in_file = io.StringIO(base64.b64decode(data).decode("utf-8")) + reader = csv.DictReader(in_file) + for idx, line in enumerate(reader): + _logger.info("Process line %s", idx) + self.flush() + try: + with self.env.cr.savepoint(): + self._process_line(line) + except Exception as e: + line["error"] = str(e) + output.append(line) + _logger.error("Script import error %s", e) + headers = ["error"] + reader.fieldnames + return self.write_output(headers, output, reader.dialect) + + def write_output(self, headers, data, dialect): + f = io.StringIO() writer = csv.DictWriter( - output, - delimiter=",", - quotechar='"', + f, + dialect=dialect, fieldnames=headers, ) - - return data + writer.writeheader() + for row in data: + writer.writerow(row) + f.seek(0) + return base64.b64encode(f.read().encode("utf-8")) diff --git a/script_file_import/models/script_file_import.py b/script_file_import/models/script_file_import.py index 5b8c59f48..9a4d0624b 100644 --- a/script_file_import/models/script_file_import.py +++ b/script_file_import/models/script_file_import.py @@ -9,6 +9,9 @@ class ScriptFileImport(models.Model): _name = "script.file.import" _description = "Script File Import" + in_filename = fields.Char() + out_filename = fields.Char(compute="_compute_out_filename") + in_data = fields.Binary(string="Input CSV file", required=True) out_data = fields.Binary(string="Output CSV file", readonly=True) @@ -16,12 +19,25 @@ class ScriptFileImport(models.Model): processor = fields.Selection( string="Processor", selection="_get_processor", required=True ) + state = fields.Selection( + [ + ("draft", "Draft"), + ("processing", "Processing"), + ("done", "Done"), + ], + ) def _get_processor(self): return [] + def run_in_background(self): + self.state = "processing" + self.with_delay().run() + def run(self): - selected_processor = dict( - self._fields["processor"]._description_selection(self.env) - ).get(self.processor) - self.out_data = self.env[selected_processor].run(self.in_data) + self.out_data = self.env[self.processor].run(self.in_data) + self.state = "done" + + def _compute_out_filename(self): + for record in self: + record.out_filename = "Result-" + record.in_filename diff --git a/script_file_import/views/script_file_import.xml b/script_file_import/views/script_file_import.xml index 9b25ad90c..6524a8390 100644 --- a/script_file_import/views/script_file_import.xml +++ b/script_file_import/views/script_file_import.xml @@ -9,12 +9,27 @@
-
- - + + + + From ab0abba7aa1dd9c5ccc87d00c0766d508cb5367a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Tue, 19 Sep 2023 10:18:08 +0200 Subject: [PATCH 3/3] script_file_import: fix view --- script_file_import/views/menu.xml | 2 +- .../views/script_file_import.xml | 23 ++++++++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/script_file_import/views/menu.xml b/script_file_import/views/menu.xml index c4fa43eec..4b348c3d8 100644 --- a/script_file_import/views/menu.xml +++ b/script_file_import/views/menu.xml @@ -7,7 +7,7 @@ Script File Import ir.actions.act_window script.file.import - form + tree,form - + + + script.file.import + + + + + + + + + + + script.file.import + + + + + + + +