diff --git a/dms_storage/README.rst b/dms_storage/README.rst new file mode 100644 index 000000000..b2e4cb0f6 --- /dev/null +++ b/dms_storage/README.rst @@ -0,0 +1,84 @@ +=========== +Dms Storage +=========== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:0bc9e984f4e8846f73e2366a15a8bf47ca8e7f7ecde0bd6ab3987096f8844e34 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-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%2Fdms-lightgray.png?logo=github + :target: https://github.com/OCA/dms/tree/17.0/dms_storage + :alt: OCA/dms +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/dms-17-0/dms-17-0-dms_storage + :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/dms&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Use OCA storages in order to store DMS documents. + +It allows us to create store outside our systems. + +They will be stored using the same system used on DMS System (Path and +Name) + +**Table of contents** + +.. contents:: + :local: + +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 `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* CreuBlanca + +Contributors +------------ + +- Enric Tobella +- `APSL-Nagarro `__: + + - Bernat Obrador + +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/dms `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/dms_storage/__init__.py b/dms_storage/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/dms_storage/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/dms_storage/__manifest__.py b/dms_storage/__manifest__.py new file mode 100644 index 000000000..e240bd6fd --- /dev/null +++ b/dms_storage/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2022 CreuBlanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Dms Storage", + "summary": """ + Integrate DMS with external Storages""", + "version": "17.0.1.0.0", + "license": "AGPL-3", + "author": "CreuBlanca,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/dms", + "depends": ["dms", "fs_storage"], + "data": [ + "views/dms_storage.xml", + ], +} diff --git a/dms_storage/i18n/dms_storage.pot b/dms_storage/i18n/dms_storage.pot new file mode 100644 index 000000000..abe8e77d8 --- /dev/null +++ b/dms_storage/i18n/dms_storage.pot @@ -0,0 +1,49 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_storage +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: dms_storage +#: model:ir.model,name:dms_storage.model_dms_file +msgid "File" +msgstr "" + +#. module: dms_storage +#: model:ir.model.fields,field_description:dms_storage.field_dms_storage__save_type +msgid "Save Type" +msgstr "" + +#. module: dms_storage +#: model:ir.model,name:dms_storage.model_dms_storage +#: model:ir.model.fields.selection,name:dms_storage.selection__dms_storage__save_type__storage +msgid "Storage" +msgstr "" + +#. module: dms_storage +#: model:ir.model.fields,field_description:dms_storage.field_dms_file__storage_backend_id +#: model:ir.model.fields,field_description:dms_storage.field_dms_storage__storage_backend_id +msgid "Storage Backend" +msgstr "" + +#. module: dms_storage +#: model:ir.model.fields,field_description:dms_storage.field_dms_file__storage_path +msgid "Storage Path" +msgstr "" + +#. module: dms_storage +#: model:ir.model.fields,help:dms_storage.field_dms_storage__save_type +msgid "" +"The save type is used to determine how a file is saved by the\n" +" system. If you change this setting, you can migrate existing files\n" +" manually by triggering the action." +msgstr "" diff --git a/dms_storage/i18n/it.po b/dms_storage/i18n/it.po new file mode 100644 index 000000000..adef422f7 --- /dev/null +++ b/dms_storage/i18n/it.po @@ -0,0 +1,57 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_storage +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-07-29 10:58+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: dms_storage +#: model:ir.model,name:dms_storage.model_dms_file +msgid "File" +msgstr "File" + +#. module: dms_storage +#: model:ir.model.fields,field_description:dms_storage.field_dms_storage__save_type +msgid "Save Type" +msgstr "Tipo salvataggio" + +#. module: dms_storage +#: model:ir.model,name:dms_storage.model_dms_storage +#: model:ir.model.fields.selection,name:dms_storage.selection__dms_storage__save_type__storage +msgid "Storage" +msgstr "Deposito" + +#. module: dms_storage +#: model:ir.model.fields,field_description:dms_storage.field_dms_file__storage_backend_id +#: model:ir.model.fields,field_description:dms_storage.field_dms_storage__storage_backend_id +msgid "Storage Backend" +msgstr "Backend deposito" + +#. module: dms_storage +#: model:ir.model.fields,field_description:dms_storage.field_dms_file__storage_path +msgid "Storage Path" +msgstr "Percorso deposito" + +#. module: dms_storage +#: model:ir.model.fields,help:dms_storage.field_dms_storage__save_type +msgid "" +"The save type is used to determine how a file is saved by the\n" +" system. If you change this setting, you can migrate existing files\n" +" manually by triggering the action." +msgstr "" +"Il tipo di salvataggio viene utilizzato per determinare come un file viene " +"salvato dal sistema.\n" +" Se si modifica questa impostazione, si può eseguire la migrazione " +"dei file esistenti\n" +" manualmente attivando l'azione." diff --git a/dms_storage/models/__init__.py b/dms_storage/models/__init__.py new file mode 100644 index 000000000..1d2155838 --- /dev/null +++ b/dms_storage/models/__init__.py @@ -0,0 +1,2 @@ +from . import dms_storage +from . import dms_file diff --git a/dms_storage/models/dms_file.py b/dms_storage/models/dms_file.py new file mode 100644 index 000000000..945eb7a50 --- /dev/null +++ b/dms_storage/models/dms_file.py @@ -0,0 +1,36 @@ +# Copyright 2022 CreuBlanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, fields, models + + +class DmsFile(models.Model): + _inherit = "dms.file" + + storage_path = fields.Char() + storage_backend_id = fields.Many2one("fs.storage") + + def _update_content_vals(self, vals, binary): + result = super()._update_content_vals(vals, binary) + result.update( + { + "storage_path": False, + "storage_backend_id": False, + } + ) + if self.storage_id.save_type == "storage": + storage_path = self.path_names + if self.storage_path: + self.storage_id.storage_backend_id.delete(self.storage_path) + self.storage_id.storage_backend_id.add(storage_path, binary) + result["storage_path"] = storage_path + result["storage_backend_id"] = self.storage_id.storage_backend_id.id + return result + + @api.depends("storage_path") + def _compute_content(self): + res = super()._compute_content() + for record in self.filtered(lambda r: r.storage_path): + record.content = self.storage_backend_id.get( + record.storage_path, binary=False + ) + return res diff --git a/dms_storage/models/dms_storage.py b/dms_storage/models/dms_storage.py new file mode 100644 index 000000000..9c9f62dc0 --- /dev/null +++ b/dms_storage/models/dms_storage.py @@ -0,0 +1,13 @@ +# Copyright 2022 CreuBlanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class DmsStorage(models.Model): + _inherit = "dms.storage" + + save_type = fields.Selection( + selection_add=[("storage", "Storage")], ondelete={"storage": "cascade"} + ) + storage_backend_id = fields.Many2one("fs.storage") diff --git a/dms_storage/pyproject.toml b/dms_storage/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/dms_storage/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/dms_storage/readme/CONTRIBUTORS.md b/dms_storage/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..4b345b2ac --- /dev/null +++ b/dms_storage/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- Enric Tobella +- [APSL-Nagarro](): + - Bernat Obrador \<\> \ No newline at end of file diff --git a/dms_storage/readme/DESCRIPTION.md b/dms_storage/readme/DESCRIPTION.md new file mode 100644 index 000000000..5410004f8 --- /dev/null +++ b/dms_storage/readme/DESCRIPTION.md @@ -0,0 +1,6 @@ +Use OCA storages in order to store DMS documents. + +It allows us to create store outside our systems. + +They will be stored using the same system used on DMS System (Path and +Name) diff --git a/dms_storage/static/description/icon.png b/dms_storage/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/dms_storage/static/description/icon.png differ diff --git a/dms_storage/static/description/index.html b/dms_storage/static/description/index.html new file mode 100644 index 000000000..92ff1933c --- /dev/null +++ b/dms_storage/static/description/index.html @@ -0,0 +1,430 @@ + + + + + +Dms Storage + + + +
+

Dms Storage

+ + +

Beta License: AGPL-3 OCA/dms Translate me on Weblate Try me on Runboat

+

Use OCA storages in order to store DMS documents.

+

It allows us to create store outside our systems.

+

They will be stored using the same system used on DMS System (Path and +Name)

+

Table of contents

+ +
+

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.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • CreuBlanca
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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

+

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

+
+
+
+ + diff --git a/dms_storage/tests/__init__.py b/dms_storage/tests/__init__.py new file mode 100644 index 000000000..8f3fb899e --- /dev/null +++ b/dms_storage/tests/__init__.py @@ -0,0 +1 @@ +from . import test_storage diff --git a/dms_storage/tests/test_storage.py b/dms_storage/tests/test_storage.py new file mode 100644 index 000000000..6fbefaa94 --- /dev/null +++ b/dms_storage/tests/test_storage.py @@ -0,0 +1,85 @@ +# Copyright 2020 Creu Blanca +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import base64 +import uuid + +from odoo.tests.common import Form +from odoo.tools import human_size + +from odoo.addons.fs_storage.tests.common import TestFSStorageCase + + +class TestDmsField(TestFSStorageCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.access_group = cls.env["dms.access.group"].create( + { + "name": "Access Group", + "group_ids": [(4, cls.env.ref("base.group_user").id)], + } + ) + cls.storage = cls.env["dms.storage"].create( + { + "name": "DMS Storage", + "save_type": "storage", + "storage_backend_id": cls.backend.id, + } + ) + cls.storage_database = cls.env["dms.storage"].create( + { + "name": "DMS Database", + "save_type": "database", + } + ) + cls.directory = cls.env["dms.directory"].create( + {"storage_id": cls.storage.id, "is_root_directory": True, "name": "MY DIR"} + ) + cls.directory_database = cls.env["dms.directory"].create( + { + "storage_id": cls.storage_database.id, + "is_root_directory": True, + "name": "MY DIR", + } + ) + + def content_base64(self): + return base64.b64encode(b"\xff data") + + def create_file(self, directory, content=False, sudo=False): + model = self.env["dms.file"].sudo() if sudo else self.env["dms.file"] + record = Form(model) + record.name = uuid.uuid4().hex + record.directory_id = directory + record.content = content or self.content_base64() + return record.save() + + def test_storage_file_migration(self): + file = self.create_file(self.directory) + self.assertTrue(file.storage_backend_id) + self.assertTrue(file.storage_path) + path = file.storage_path.rsplit("/", 1)[0] + self.assertTrue(self.backend.list_files(path)) + file.directory_id = self.directory_database + self.assertTrue(file.storage_backend_id) + file.action_migrate() + self.assertFalse(file.storage_backend_id) + self.assertFalse(file.storage_path) + + def test_storage_file_move(self): + file = self.create_file(self.directory) + self.assertTrue(file.storage_backend_id) + self.assertTrue(file.storage_path) + path = file.storage_path + self.assertEqual( + self.content_base64(), base64.b64encode(self.backend.get(path)) + ) + file.name = uuid.uuid4() + file.write({"content": self.content_base64()}) + with self.assertRaises(FileNotFoundError): + self.backend.get(path) + self.assertEqual( + human_size(len(base64.b64decode(self.content_base64()))), + file.with_context(bin_size=True).content.decode("utf-8"), + ) diff --git a/dms_storage/views/dms_storage.xml b/dms_storage/views/dms_storage.xml new file mode 100644 index 000000000..aba6fa4a4 --- /dev/null +++ b/dms_storage/views/dms_storage.xml @@ -0,0 +1,19 @@ + + + + + dms.storage.form (in dms_storage) + dms.storage + + + + + + + +