From 62a4d0dae0ca9d8db204272abebe4e6d3789d661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Fri, 19 Jan 2024 08:23:43 +0100 Subject: [PATCH 01/15] [ADD] dms_auto_classification: New module TT46805 [UPD] Update dms_auto_classification.pot --- dms_auto_classification/README.rst | 106 +++++ dms_auto_classification/__init__.py | 4 + dms_auto_classification/__manifest__.py | 20 + .../demo/dms_classification_template_demo.xml | 11 + .../i18n/dms_auto_classification.pot | 191 ++++++++ dms_auto_classification/i18n/es.po | 195 ++++++++ dms_auto_classification/models/__init__.py | 3 + .../models/dms_classification_template.py | 21 + dms_auto_classification/readme/CONFIGURE.rst | 6 + .../readme/CONTRIBUTORS.rst | 4 + .../readme/DESCRIPTION.rst | 1 + dms_auto_classification/readme/USAGE.rst | 5 + .../security/ir.model.access.csv | 4 + dms_auto_classification/security/security.xml | 9 + .../static/description/icon.png | Bin 0 -> 5069 bytes .../static/description/icon.svg | 210 ++++++++ .../static/description/index.html | 448 ++++++++++++++++++ dms_auto_classification/tests/__init__.py | 3 + dms_auto_classification/tests/data/test.zip | Bin 0 -> 2890 bytes .../tests/test_dms_auto_classification.py | 123 +++++ .../dms_classification_template_views.xml | 46 ++ dms_auto_classification/wizards/__init__.py | 3 + .../wizards/wizard_dms_classification.py | 189 ++++++++ .../wizard_dms_classification_views.xml | 71 +++ 24 files changed, 1673 insertions(+) create mode 100644 dms_auto_classification/README.rst create mode 100644 dms_auto_classification/__init__.py create mode 100644 dms_auto_classification/__manifest__.py create mode 100644 dms_auto_classification/demo/dms_classification_template_demo.xml create mode 100644 dms_auto_classification/i18n/dms_auto_classification.pot create mode 100644 dms_auto_classification/i18n/es.po create mode 100644 dms_auto_classification/models/__init__.py create mode 100644 dms_auto_classification/models/dms_classification_template.py create mode 100644 dms_auto_classification/readme/CONFIGURE.rst create mode 100644 dms_auto_classification/readme/CONTRIBUTORS.rst create mode 100644 dms_auto_classification/readme/DESCRIPTION.rst create mode 100644 dms_auto_classification/readme/USAGE.rst create mode 100644 dms_auto_classification/security/ir.model.access.csv create mode 100644 dms_auto_classification/security/security.xml create mode 100644 dms_auto_classification/static/description/icon.png create mode 100644 dms_auto_classification/static/description/icon.svg create mode 100644 dms_auto_classification/static/description/index.html create mode 100644 dms_auto_classification/tests/__init__.py create mode 100644 dms_auto_classification/tests/data/test.zip create mode 100644 dms_auto_classification/tests/test_dms_auto_classification.py create mode 100644 dms_auto_classification/views/dms_classification_template_views.xml create mode 100644 dms_auto_classification/wizards/__init__.py create mode 100644 dms_auto_classification/wizards/wizard_dms_classification.py create mode 100644 dms_auto_classification/wizards/wizard_dms_classification_views.xml diff --git a/dms_auto_classification/README.rst b/dms_auto_classification/README.rst new file mode 100644 index 000000000..748d1d3c5 --- /dev/null +++ b/dms_auto_classification/README.rst @@ -0,0 +1,106 @@ +================================ +Auto classify documents into DMS +================================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:3e93b0096e03b1ed8f97c4542423a631ee1cafff5e6ebe4bc537528b680bc1c1 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/15.0/dms_auto_classification + :alt: OCA/dms +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/dms-15-0/dms-15-0-dms_auto_classification + :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=15.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Automatically classify files within a .zip file to the corresponding DMS directory(s). + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +#. Go to `Documents / Configuration / Classification Templates` and create a new template. +#. You can set patterns (regex expressions) for filenames and directories. + +Example of filename pattern to use only .txt files: .txt$ +Directory pattern example 1: Documents +Directory pattern example 1: Documents / Data + +Usage +===== + +#. Go to `Documents / Auto Classification` and select a template and a .zip file. +#. Press the `Analyze` button +#. As many lines will be set as the number of files contained in the .zip file and apply the filename pattern. +#. Press the `Classify` button +#. The files (dms.file) will be created in the corresponding directories. + +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 +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* `Tecnativa `_: + + * Víctor Martínez + * Pedro M. Baeza + +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. + +.. |maintainer-victoralmau| image:: https://github.com/victoralmau.png?size=40px + :target: https://github.com/victoralmau + :alt: victoralmau + +Current `maintainer `__: + +|maintainer-victoralmau| + +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_auto_classification/__init__.py b/dms_auto_classification/__init__.py new file mode 100644 index 000000000..e1e144406 --- /dev/null +++ b/dms_auto_classification/__init__.py @@ -0,0 +1,4 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import models +from . import wizards diff --git a/dms_auto_classification/__manifest__.py b/dms_auto_classification/__manifest__.py new file mode 100644 index 000000000..1bde5cfe0 --- /dev/null +++ b/dms_auto_classification/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2024 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Auto classify documents into DMS", + "version": "15.0.1.0.0", + "category": "Document Management", + "website": "https://github.com/OCA/dms", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["dms"], + "installable": True, + "data": [ + "security/ir.model.access.csv", + "security/security.xml", + "views/dms_classification_template_views.xml", + "wizards/wizard_dms_classification_views.xml", + ], + "demo": ["demo/dms_classification_template_demo.xml"], + "maintainers": ["victoralmau"], +} diff --git a/dms_auto_classification/demo/dms_classification_template_demo.xml b/dms_auto_classification/demo/dms_classification_template_demo.xml new file mode 100644 index 000000000..93cd98700 --- /dev/null +++ b/dms_auto_classification/demo/dms_classification_template_demo.xml @@ -0,0 +1,11 @@ + + + + Documents template + .txt$ + Documents + + diff --git a/dms_auto_classification/i18n/dms_auto_classification.pot b/dms_auto_classification/i18n/dms_auto_classification.pot new file mode 100644 index 000000000..9ecce0750 --- /dev/null +++ b/dms_auto_classification/i18n/dms_auto_classification.pot @@ -0,0 +1,191 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_auto_classification +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.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_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification__state__analyze +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Analyze" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.actions.act_window,name:dms_auto_classification.action_wizard_dms_classification +#: model:ir.ui.menu,name:dms_auto_classification.menu_wizard_dms_classification +msgid "Auto Classification" +msgstr "" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Cancel" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.actions.act_window,name:dms_auto_classification.action_dms_classification_template +#: model:ir.ui.menu,name:dms_auto_classification.menu_dms_classification_template +msgid "Classification Templates" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification_detail__state__classified +msgid "Classified" +msgstr "" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Classify" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__company_id +msgid "Company" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__create_uid +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__create_uid +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__create_uid +msgid "Created by" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__create_date +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__create_date +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__create_date +msgid "Created on" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__detail_ids +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Details" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__directory_id +msgid "Directory" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__directory_pattern +msgid "Directory Pattern" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__display_name +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__display_name +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__display_name +msgid "Display Name" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_dms_classification_template +msgid "Dms Classification Template" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification__state__draft +msgid "Draft" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_file +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_id +msgid "File" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_name +msgid "File name" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__filename_pattern +msgid "Filename Pattern" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__id +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__id +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__id +msgid "ID" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template____last_update +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification____last_update +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail____last_update +msgid "Last Modified on" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__write_uid +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__write_uid +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__write_date +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__write_date +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__write_date +msgid "Last Updated on" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__name +msgid "Name" +msgstr "" + +#. module: dms_auto_classification +#: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 +#, python-format +msgid "Only .zip files are allowed" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__parent_id +msgid "Parent" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__sequence +msgid "Sequence" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__state +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__state +msgid "State" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__template_id +msgid "Template" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification_detail__state__to_classify +msgid "To classify" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification +msgid "Wizard Dms Classification" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification_detail +msgid "Wizard Dms Classification Detail" +msgstr "" diff --git a/dms_auto_classification/i18n/es.po b/dms_auto_classification/i18n/es.po new file mode 100644 index 000000000..b552c0066 --- /dev/null +++ b/dms_auto_classification/i18n/es.po @@ -0,0 +1,195 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_auto_classification +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-02-05 08:37+0000\n" +"PO-Revision-Date: 2024-02-05 09:38+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"X-Generator: Poedit 3.0.1\n" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification__state__analyze +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Analyze" +msgstr "Analizar" + +#. module: dms_auto_classification +#: model:ir.actions.act_window,name:dms_auto_classification.action_wizard_dms_classification +#: model:ir.ui.menu,name:dms_auto_classification.menu_wizard_dms_classification +msgid "Auto Classification" +msgstr "Auto-clasificación" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Cancel" +msgstr "Cancelar" + +#. module: dms_auto_classification +#: model:ir.actions.act_window,name:dms_auto_classification.action_dms_classification_template +#: model:ir.ui.menu,name:dms_auto_classification.menu_dms_classification_template +msgid "Classification Templates" +msgstr "Plantillas de clasificación" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification_detail__state__classified +msgid "Classified" +msgstr "Clasificado" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Classify" +msgstr "Clasificar" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__company_id +msgid "Company" +msgstr "Compañía" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__create_uid +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__create_uid +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__create_date +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__create_date +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__detail_ids +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Details" +msgstr "Detalles" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__directory_id +msgid "Directory" +msgstr "Directorio" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__directory_pattern +msgid "Directory Pattern" +msgstr "Patrón del directorio" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__display_name +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__display_name +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__display_name +msgid "Display Name" +msgstr "Nombre a Mostrar" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_dms_classification_template +msgid "Dms Classification Template" +msgstr "Plantilla de clasificación Dms" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification__state__draft +msgid "Draft" +msgstr "Borrador" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_file +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_id +msgid "File" +msgstr "Archivo" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_name +msgid "File name" +msgstr "Nombre de archivo" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__filename_pattern +msgid "Filename Pattern" +msgstr "Patrón de nombre de archivo" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__id +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__id +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__id +msgid "ID" +msgstr "ID" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template____last_update +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification____last_update +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail____last_update +msgid "Last Modified on" +msgstr "Última Modificación el" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__write_uid +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__write_uid +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__write_uid +msgid "Last Updated by" +msgstr "Última Actualización por" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__write_date +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__write_date +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__write_date +msgid "Last Updated on" +msgstr "Ultima actualización el" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__name +msgid "Name" +msgstr "Nombrr" + +#. module: dms_auto_classification +#: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 +#, python-format +msgid "Only .zip files are allowed" +msgstr "Solo se permiten archivos .zip" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__parent_id +msgid "Parent" +msgstr "Padre" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__sequence +msgid "Sequence" +msgstr "Secuencia" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__state +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__state +msgid "State" +msgstr "Estado" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__template_id +msgid "Template" +msgstr "Plantilla" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification_detail__state__to_classify +msgid "To classify" +msgstr "A clasificar" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification +msgid "Wizard Dms Classification" +msgstr "" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification_detail +msgid "Wizard Dms Classification Detail" +msgstr "" diff --git a/dms_auto_classification/models/__init__.py b/dms_auto_classification/models/__init__.py new file mode 100644 index 000000000..cb95092bf --- /dev/null +++ b/dms_auto_classification/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import dms_classification_template diff --git a/dms_auto_classification/models/dms_classification_template.py b/dms_auto_classification/models/dms_classification_template.py new file mode 100644 index 000000000..23ff91f03 --- /dev/null +++ b/dms_auto_classification/models/dms_classification_template.py @@ -0,0 +1,21 @@ +# Copyright 2024 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class DmsClassificationTemplate(models.Model): + _name = "dms.classification.template" + _order = "sequence,name,id" + _description = "Dms Classification Template" + + name = fields.Char(required=True) + sequence = fields.Integer(required=True, default=10) + company_id = fields.Many2one( + comodel_name="res.company", + string="Company", + store=True, + index=True, + ) + filename_pattern = fields.Char() + directory_pattern = fields.Char() diff --git a/dms_auto_classification/readme/CONFIGURE.rst b/dms_auto_classification/readme/CONFIGURE.rst new file mode 100644 index 000000000..8066cc5cd --- /dev/null +++ b/dms_auto_classification/readme/CONFIGURE.rst @@ -0,0 +1,6 @@ +#. Go to `Documents / Configuration / Classification Templates` and create a new template. +#. You can set patterns (regex expressions) for filenames and directories. + +Example of filename pattern to use only .txt files: .txt$ +Directory pattern example 1: Documents +Directory pattern example 1: Documents / Data diff --git a/dms_auto_classification/readme/CONTRIBUTORS.rst b/dms_auto_classification/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..5fb713053 --- /dev/null +++ b/dms_auto_classification/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* `Tecnativa `_: + + * Víctor Martínez + * Pedro M. Baeza diff --git a/dms_auto_classification/readme/DESCRIPTION.rst b/dms_auto_classification/readme/DESCRIPTION.rst new file mode 100644 index 000000000..f8d45a51e --- /dev/null +++ b/dms_auto_classification/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Automatically classify files within a .zip file to the corresponding DMS directory(s). diff --git a/dms_auto_classification/readme/USAGE.rst b/dms_auto_classification/readme/USAGE.rst new file mode 100644 index 000000000..d8b5dbc0e --- /dev/null +++ b/dms_auto_classification/readme/USAGE.rst @@ -0,0 +1,5 @@ +#. Go to `Documents / Auto Classification` and select a template and a .zip file. +#. Press the `Analyze` button +#. As many lines will be set as the number of files contained in the .zip file and apply the filename pattern. +#. Press the `Classify` button +#. The files (dms.file) will be created in the corresponding directories. diff --git a/dms_auto_classification/security/ir.model.access.csv b/dms_auto_classification/security/ir.model.access.csv new file mode 100644 index 000000000..cc3f846c2 --- /dev/null +++ b/dms_auto_classification/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_dms_classification_template_manager,dms_classification_template_manager,model_dms_classification_template,dms.group_dms_manager,1,1,1,1 +access_wizard_dms_classification_manager,wizard_dms_classification_manager,model_wizard_dms_classification,dms.group_dms_manager,1,1,1,1 +access_wizard_dms_classification_detail_manager,wizard_dms_classification_detail_manager,model_wizard_dms_classification_detail,dms.group_dms_manager,1,1,1,1 diff --git a/dms_auto_classification/security/security.xml b/dms_auto_classification/security/security.xml new file mode 100644 index 000000000..a8332fbdd --- /dev/null +++ b/dms_auto_classification/security/security.xml @@ -0,0 +1,9 @@ + + + + DMS Classification Template multi-company + + + [('company_id', 'in', [False] + company_ids)] + + diff --git a/dms_auto_classification/static/description/icon.png b/dms_auto_classification/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9fd5b327acab0e692cbd7160b1f457c092ee3f1d GIT binary patch literal 5069 zcmbtYhf@3+002fEZ4KiK8T%jT zE?@LzU({4C1iiPmg&zPwr|};yjcWE@i~%?in&t=-uNQ~_J6}gYKtO<`i>I5Py`8tC zq?fN#+Qxk@0D$$Wj)s~kGJQQGDE8Ttkk_Q+58VT9PSfQj0XMEFRsQv#>u{MHdv#Az zvy=`0`MDbTIHw|NrxT6fwH7?lh%lc z8>wXhgj9BQy2ar&pmtfp1bk+a3<4XdhA!=w3=#LhhH|kfA01DSXg*cqq6tIsW%yRwQ4gvvW1Tkqf+Q_ zHwwX}lzba#KTgNbzC^9Pip>%E=pv%R_f(x)S161wQfF~zx^b`9riD+p?PN2Y>CE0z zWLH!+r6VP^t;fL|NQ-u4b4+L}VF1%=8W|#P$bud)MjCN*`#iq`@vHCNJnE9?g`@Uo z!kg`^&O;RNz!(iGVSL*i2DC@`{7txpg$RIv&2cG2sk%b3Eb)mkS~By8CxOaY{VH7K z&lMTkGcbMr3oG-_qQvetl!%~nz{UKy@Cpwee#1+e@b;SdljgFq{dIxFR-HU7aqQ)a zfvE0?2(YE>+7Cl#BjR;j_&p?n1Hc|k#!Op{$$^2I@`xJ}98FdQhRZco7N+eYH4&dg zWOEkoCZ0XTP)DmMJ6Ud@kkveNauDG();OyCu94-c4*<*wIY;Brbc4 zIFIX;r0U>y3I1#Mxj0a)(I#qczQ_ z0C_YhBP(a^lZw|C#8?O{7;~~Lb@wgUP-U8OM>_jw<|;u%Xd!*tnYedSY8ZZ%{@%Je_;t>PRD!*8VJRhZ!sxDv&V74V_pl!h&yW21lkFY;K~+du#Xqf; zmqOmyQos2a!;f`N-}QIv;Z=aHjo)n(X9mO7$WU+|C6Ud^#I-Q>ifZ<>>XPMuGfx{7 zomWBcpd#parN~^=IIvX?07Cah|ju z&E%5$!C`*nWib5KcTh>_z17Tl77Y;~2FWAH(*=yI)a^IOCKM)N%tU5-7wLppC^DRn zzr9U`z14HNbCnhl`z+J1Aack*?oZjZ$J^x<>ir6Q<5jiE1c@@muUGZg|5|+=B72PVtSg17*?DneRmElPXFzo z!w@wpRq?m$)1R1%98BdYO3Sk;VatEbRq~tCHqise$G5Ov`?$(;lB=vfKU7U3Js1+> zVL>jB3$DC2|DIPzrl`|2^3c4pP3TGKbLTa)K1C_}YLB!FgWtY?w~+IidJvqcXfQXy zQE%Mq48a)Z1wc+Koqc+*F%=a{yGm;#Y+sKhNl?be*HZSNW{~zb^3w}2z22M!8%PRl zYcA%PlcNrIc6Qi}Mr1MRhdK#o%tx&xnJ5>gNuS}am7x}xpUY3j&iPQXuC_~$RXH)W z$B653cKawGmZhUL-sz{6HM%3BYHKg@pESRjZzqk|m5_>g#k|L?HEOXlX5UdpYLWca zuceZ;RKJvI?_RRK$muuR`+`0W#{v`54hTqe@sb))HNP1iUT{Z0k=u)>FleyU^8WQM z=CBLLJ1$>t8gMmWXtzDsn2e2oqSAh5y!#CI$G$s?=^9IVx`X>^;DE$mBIw->WFPo#3t{tp;? zsG@#%wmLLJ;mz}Lp`&BYiOSqLR9XrHQ~dUCH?OFOKQ~~ir08Qt^c!oKm3Pw-fh%(BZAvi zKrf|sN>N9gJ)cCn4hWTgAcuz}_I>x;6APR5HsYd1SUEl44PI&ZrbIhAlOi29H(xlT z@FC_i{_D6GseiUTve=-&E;zlVIfx!+)pWUVaoH#}{)QlVq_h6brHdqnFVX(HaCmrl z7zX8n@OU}6x>E@z+yDJ5B4M>oCPPgU>EF#K0yJ zj;wS%PXBn2Ow!1>bKMbw1!+V?Ml&!au5SG4^Qbk7(klK&uJO3WL%C5qeRhRHjhb8c zxHu~XWfN}7;5+!}Y*W~iT&O@;t*DMQljN_B>$oTqSgFkw- z)GwoJ$Y`GZ+SIsX~7S?#%tniF&SP} zL%)Cbu}&2G|c4HbP~O zdKNvlF?KWksej;lDxmE_f&Y!cO+S-~K^Q z1HC)x67_^A{W639cB~pXxH)|$#mz!gE~}i(Vihag$qPO4s2`L3*RI-~2Dzq9v3+6V zhq)r&ho0{iyqf*xGz8E$GOSw&ZhaNCZ#p%8@6{X)tJf=OdY9(LUimT`eWClu){?aC z3p2&t%WLZ&8>=u?xvUJCT-gPUc)0TQ7gAjLonsVmL4=m_ud$FV40Bjk@S5d`>w#yg zf5zK5_= zXi)Ehd^U-DbSL|GBd~kV=~36=YAx!kWw_IAk;4h`25DB|$J>orr?Ht2UdxfPw5)^+ z3C`F#*N?rfu5Be13>iH_%ChM>hFzu7jW5sNb&X+soeAHl`RXDgK4vZ1AP4DCZ|u(wY>QtZSavH+(^%#LtZGP1semZ6c3Jp3VKWa zEZO+eaxi6(ZMz-kb&d?Q`GA>G7(kd7?L~iyk&JyzcE)Nr6FnX_;L1esaO+}9>)r!E zY1oUVCp0H2D*I0kvWvu~56>QR+>^hvsXUocI^nkzCxUG|@()3LmQU#APUk2=)y%@! ztv>v$b~{Wg4`Iv;=5WNUfDN)F~EMU`DOaj zfpyD<@r!lYCzboDSJ%?C1|M&)Z>s1)OeWJm>RBM{f)nWUWzA8;g)WBK(yOZ@8jVe3 zRI?Tn19ZPX+cAbB57>uOc&1MV$X7kN_*CwG&CEJy?Q*!Qp_nFluDK`S#Gf|J}kSEdSPdkR$EQoDmHE}s2g?ZmRO-xv^ zIi^3vIJmf;J2=pgp?CCI+oki*y;336)YNdz3e52D2?eXAx`xd;oOZ!(Jwv-tVvqfY zPP4am>^9e9b%U}eX6vP~IY?rXVsdY#+o+^(eeY&933NAw;j!xJZpo&{SVguZ5paKB zYC7W}mG1;8rApbFS{WTYLGWE5D>AQvV^E1tW5v7YDQmRGSiRp80=*TMpAYeDIealV zY=iw#Q2Q;{Une6YW5TyrBJ)$J3s=B&i2M=NK}{MXypeeQ=V0d|HpJ22%j`=8Be(gJ z){?WsF{0yD3ApD~;(AhNxpre-vnZ^)$lkAo#})HqO!<`D624{!Y|a zLGZSuX`3oX2ta>}WAEt|Ti78T497o^E>N;Y-od)|ybBe=7r}2KFN(B=Kmr$@FhF-_ z@?;{<{a_6bK6;z z71TD^{i3Jt)b+L;Zq;>T~3N1h;3Mz-2zS*1qLA zjAE}bhdJ_AU3E3SKTY0dKQ#}X94~0z)%N8CZ)-LBtI|HQp#ADz*ILWs;*NfQ>!Mhz zWvypkWo65FlB9o9v$S;3tvV7Z%kAQ-iBl5ts}w*FLE{2Q$CGH?agrPqS`l)*uPHe) z?4U_U4FY27mNJ9BL*tY->T*5(o+WYjJ{Nb%M!bBv-Ez=ezG}3L@54q*JAM)$shmS6 zm_~xN=76HH9c;!N(YHTIvpmuM?=8@#{fr-zQ1=ih=!5w`EBG^a^}JY1=*M=;>Gxff z%LMgzuZ zWyO~br+imyznR!;=TMdDE=qbXlF>9?LV(gzAudyWJ~~B1`xDpAdXZwWz-8=14f68t z@m8^zkCm{;I0r5~ZhXE#$PtR2_An%4nJ1P6^VeuhN63#ttPEtf)VJE5x%wLn)ab;! zTh)Lj^owS1^F=78_>Tk@L-|LcC5DJ1 z*7Aa@#K}j8>dtvg`F=VM3I3b`eaHo5z5O5eA0eS1EL16mwIW(gkf1R*+>Egh>0#6PMSrCN^Pn2-UBWr6EtEV5NCKHZRB#=DnncXce6=`v zX90RGNJHDr@0F?}>oo2pgHu=26|6_65FL0TOB@-C^FdM&@tDu^hM+Lt46U1M(Ax>y zo7QDjVD!yJ1=ugS2$0ljYECf!tOC<=%?;*MEmI@9LRTLj@XZC5w|Gra+xLQcx^xit zG<3e>Y4&&3+W?z}#iZ_1#1Xmw!80;lu^0+2u|YMnHLTZzSFexhWT9&J(M}fVrTG}y zZbNB2Jyum(Z@Vt%ag-??%cS`xiZJ}qg`!&wP8b#sqInH6e=SOLZye$=E_6v2M48Gh zZwXX=Mg(ld$WQz`beB7(&jQWf{8%jZJMX$ql7zuZ)}q3~C3T~_LlF_ey!Q~xev58X zvu*RWQ@`zn6XQ9O{A(S@m2se + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dms_auto_classification/static/description/index.html b/dms_auto_classification/static/description/index.html new file mode 100644 index 000000000..277e4de6c --- /dev/null +++ b/dms_auto_classification/static/description/index.html @@ -0,0 +1,448 @@ + + + + + +Auto classify documents into DMS + + + +
+

Auto classify documents into DMS

+ + +

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

+

Automatically classify files within a .zip file to the corresponding DMS directory(s).

+

Table of contents

+ +
+

Configuration

+
    +
  1. Go to Documents / Configuration / Classification Templates and create a new template.
  2. +
  3. You can set patterns (regex expressions) for filenames and directories.
  4. +
+

Example of filename pattern to use only .txt files: .txt$ +Directory pattern example 1: Documents +Directory pattern example 1: Documents / Data

+
+
+

Usage

+
    +
  1. Go to Documents / Auto Classification and select a template and a .zip file.
  2. +
  3. Press the Analyze button
  4. +
  5. As many lines will be set as the number of files contained in the .zip file and apply the filename pattern.
  6. +
  7. Press the Classify button
  8. +
  9. The files (dms.file) will be created in the corresponding directories.
  10. +
+
+
+

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

+
    +
  • Tecnativa
  • +
+
+
+

Contributors

+
    +
  • Tecnativa:
      +
    • Víctor Martínez
    • +
    • Pedro M. Baeza
    • +
    +
  • +
+
+
+

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.

+

Current maintainer:

+

victoralmau

+

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_auto_classification/tests/__init__.py b/dms_auto_classification/tests/__init__.py new file mode 100644 index 000000000..7ad1c277a --- /dev/null +++ b/dms_auto_classification/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from . import test_dms_auto_classification diff --git a/dms_auto_classification/tests/data/test.zip b/dms_auto_classification/tests/data/test.zip new file mode 100644 index 0000000000000000000000000000000000000000..a529960957e7bc171ffbd64d19a0aa1b6ceb6597 GIT binary patch literal 2890 zcmWIWW@Zs#U|`^2nC|KyX#Q)d6B{c7!)_i11}+8}hP2F_R9!>8l8Tbh5Kac>yYJiM z7dx&>Ev?{YU}Sm0%)kI9V#A{Io|p;znIHUt;n1DLjh+pxla8`=zp-~;bX+!I%9-{D zkC*S7z5Zl-Zm;_r_tH?){O$JrFUp+LwRYd+t9O~KA-#L|o*7>`POiQARH*mvizQov zDx{uk-anh~Ua)$iyjRMd%c+mwMhVH^&L~$@UZR`r=5x!(YR~eiMK?7v_U--|w`cpZ zA2OMxCo8JNYM#x|yOk5|U|e@iF4 zIC6hs_7%}y@0$T9^zwMxY+oLHe|<_>?CE(q5ocyU&QR61 zlV_c&zbmGvj8Uw={BNmf{j{9Tk2i3OXRle_&om>(Ca5=Q>($*q58YSnEpNY>+c{+d z$BRN<{f>F>&34J?y2n(V=-yO%?6bl9XZo+h#B+?UKlHZSxi79~Nvy?tnJ+gwF4tW; z*D&SYm&4I}rZj#O4))vfc~0=QhNsdERl9yT359FCJ>I5fAargLN;>HZyy1s;-G)W@TDj*4-x+n;{&kw0On4yt;*}tA>S-%$#{1*Ag^`M)L%N)ClE3_VDcYaf}x)R5_Yw6-vuI%S5y!&=^suUT` zT7R)j-jh$ajB`aWV_})r8Aju0I(L(IJURD!rhe#cwP`Xpw_N%0rl2b;P1wG1PJ#2B zH=Bz>SJ&6BpA`L;udnHyzg(GcUHb92W)CF$uH89zV~5z6-M&ScYtmX-cQE$1_O@5E z><^jlZS1(NWV=V0j!iIEoP@*IRlLRVOvXAN3vacuFns|=H-eQ~G_XI<*; zHgD!>>pzb&ws^gX^HNod-aOgrc79?}O!VKNSC?N!s+WH@=i4YDwJ~JDvpKCwEoLX} zI?wC$)LfnY%;@7^j!ims7gLW4@2)wbrFx*H@ZD?1SFGh~{CPn_P8uw)d~0M4I#VV{+X?LEGo@hro`*`vGdJK?oWd2wNCpdeu}beC_s*Xo-)T0*-!7}hN**z%oqL7SG#!?TYMep&WU%GYJ{TJt*i${t)8+9>J(jzX$zq@HuC1DQZb^UQF7EHvGx(xK z^un1+GvxM%T+}JpCNh)d#=_Z;-M8o|YQInF$CN0O=`QARYj9 Cb~-r# literal 0 HcmV?d00001 diff --git a/dms_auto_classification/tests/test_dms_auto_classification.py b/dms_auto_classification/tests/test_dms_auto_classification.py new file mode 100644 index 000000000..be60f33fd --- /dev/null +++ b/dms_auto_classification/tests/test_dms_auto_classification.py @@ -0,0 +1,123 @@ +# Copyright 2024 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from base64 import b64encode +from os import path + +from odoo.tests import Form, common + + +class TestDmsAutoClassification(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.template = cls.env.ref( + "dms_auto_classification.dms_classification_template_documents" + ) + cls.directory = cls.env.ref("dms.directory_01_demo") + cls.wizard = cls._create_wizard_dms_classification(cls, cls.template) + cls.extra_wizard = cls._create_wizard_dms_classification(cls, cls.template) + + def _data_file(self, filename, encoding=None): + mode = "rt" if encoding else "rb" + with open(path.join(path.dirname(__file__), filename), mode) as file: + data = file.read() + if encoding: + data = data.encode(encoding) + return b64encode(data) + + def _create_wizard_dms_classification(self, template): + wizard_form = Form(self.env["wizard.dms.classification"]) + wizard_form.template_id = template + wizard_form.data_file = self._data_file(self, "data/test.zip") + return wizard_form.save() + + def test_wizard_dms_clasification_process(self): + self.assertEqual(self.wizard.state, "draft") + # Wizard - Analyze process + self.wizard.action_analyze() + self.assertEqual(self.wizard.state, "analyze") + self.assertEqual(len(self.wizard.detail_ids), 2) + file_names = self.wizard.mapped("detail_ids.file_name") + self.assertIn("file-1.txt", file_names) + self.assertIn("file-2.txt", file_names) + self.assertIn(self.directory, self.wizard.mapped("detail_ids.directory_id")) + detail_1 = self.wizard.detail_ids.filtered( + lambda x: x.file_name == "file-1.txt" + ) + self.assertEqual(detail_1.state, "to_classify") + detail_2 = self.wizard.detail_ids.filtered( + lambda x: x.file_name == "file-2.txt" + ) + self.assertEqual(detail_2.state, "to_classify") + # Wizard - Classify process + res = self.wizard.action_classify() + dms_files = self.env[res["res_model"]].search(res["domain"]) + self.assertEqual(len(dms_files), 2) + self.assertEqual(detail_1.state, "classified") + self.assertEqual(detail_1.file_id.directory_id, self.directory) + self.assertEqual(detail_1.file_id.name, "file-1.txt") + self.assertTrue(detail_1.file_id.content) + self.assertEqual(detail_2.state, "classified") + self.assertEqual(detail_2.file_id.directory_id, self.directory) + self.assertEqual(detail_2.file_id.name, "file-2.txt") + self.assertTrue(detail_2.file_id.content) + # Extra wizard + self.assertEqual(self.extra_wizard.state, "draft") + # New Wizard - Analyze process + self.extra_wizard.action_analyze() + self.assertEqual(self.extra_wizard.state, "analyze") + self.assertEqual(len(self.extra_wizard.detail_ids), 2) + file_names = self.extra_wizard.mapped("detail_ids.file_name") + self.assertIn("file-1.txt", file_names) + self.assertIn("file-2.txt", file_names) + self.assertIn( + self.directory, self.extra_wizard.mapped("detail_ids.directory_id") + ) + detail_1 = self.extra_wizard.detail_ids.filtered( + lambda x: x.file_name == "file-1.txt" + ) + self.assertTrue(detail_1.file_id) + self.assertEqual(detail_1.state, "classified") + detail_2 = self.extra_wizard.detail_ids.filtered( + lambda x: x.file_name == "file-2.txt" + ) + self.assertTrue(detail_2.file_id) + self.assertEqual(detail_1.state, "classified") + # New Wizard - Classify process + res = self.extra_wizard.action_classify() + dms_files = self.env[res["res_model"]].search(res["domain"]) + self.assertEqual(len(dms_files), 2) + + def test_wizard_dms_clasification_process_filename_pattern(self): + self.template.filename_pattern = ".pdf$" + self.assertEqual(self.wizard.state, "draft") + self.wizard.action_analyze() + self.assertEqual(self.wizard.state, "analyze") + self.assertEqual(len(self.wizard.detail_ids), 0) + + def test_wizard_dms_clasification_process_directory_pattern(self): + self.template.directory_pattern = "Documents2" + self.assertEqual(self.wizard.state, "draft") + # Analyze process + self.wizard.action_analyze() + self.assertEqual(self.wizard.state, "analyze") + self.assertEqual(len(self.wizard.detail_ids), 2) + file_names = self.wizard.mapped("detail_ids.file_name") + self.assertIn("file-1.txt", file_names) + self.assertIn("file-2.txt", file_names) + self.assertNotIn(self.directory, self.wizard.mapped("detail_ids.directory_id")) + detail_1 = self.wizard.detail_ids.filtered( + lambda x: x.file_name == "file-1.txt" + ) + self.assertEqual(detail_1.state, "to_classify") + detail_2 = self.wizard.detail_ids.filtered( + lambda x: x.file_name == "file-2.txt" + ) + self.assertEqual(detail_2.state, "to_classify") + # Classify process + res = self.wizard.action_classify() + dms_files = self.env[res["res_model"]].search(res["domain"]) + self.assertEqual(len(dms_files), 0) + self.assertFalse(detail_1.file_id) + self.assertFalse(detail_2.file_id) diff --git a/dms_auto_classification/views/dms_classification_template_views.xml b/dms_auto_classification/views/dms_classification_template_views.xml new file mode 100644 index 000000000..590043c8d --- /dev/null +++ b/dms_auto_classification/views/dms_classification_template_views.xml @@ -0,0 +1,46 @@ + + + + + dms.classification.template + + + + + + + + + + + + dms.classification.template + +
+ +
+

+
+ + + + + +
+
+
+
+ + Classification Templates + dms.classification.template + tree,form + + +
diff --git a/dms_auto_classification/wizards/__init__.py b/dms_auto_classification/wizards/__init__.py new file mode 100644 index 000000000..4ba9cc23a --- /dev/null +++ b/dms_auto_classification/wizards/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import wizard_dms_classification diff --git a/dms_auto_classification/wizards/wizard_dms_classification.py b/dms_auto_classification/wizards/wizard_dms_classification.py new file mode 100644 index 000000000..526d0197e --- /dev/null +++ b/dms_auto_classification/wizards/wizard_dms_classification.py @@ -0,0 +1,189 @@ +# Copyright 2024 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +import base64 +import re +import zipfile +from io import BytesIO + +from odoo import _, api, fields, models +from odoo.exceptions import UserError + + +class WizardDmsClassification(models.TransientModel): + _name = "wizard.dms.classification" + _description = "Wizard Dms Classification" + + state = fields.Selection( + selection=[ + ("draft", "Draft"), + ("analyze", "Analyze"), + ], + default="draft", + ) + template_id = fields.Many2one( + comodel_name="dms.classification.template", + string="Template", + required=True, + ) + data_file = fields.Binary( + string="File", + required=True, + ) + detail_ids = fields.One2many( + comodel_name="wizard.dms.classification.detail", + inverse_name="parent_id", + string="Details", + ) + + def _is_zipfile(self): + try: + zipfile.ZipFile(BytesIO(base64.b64decode(self.data_file))) + return True + except (zipfile.BadZipFile, ValueError): + return False + + @api.onchange("data_file") + def _onchange_data_file(self): + for item in self.filtered("data_file"): + if not item._is_zipfile(): + raise UserError(_("Only .zip files are allowed")) + + def _return_item(self): + return { + "context": self.env.context, + "view_type": "form", + "view_mode": "form", + "res_model": self._name, + "res_id": self.id, + "view_id": False, + "type": "ir.actions.act_window", + "target": "new", + } + + def _get_directory_from_pattern(self, pattern, directories): + directory = False + for d in directories: + if re.search(pattern, d.complete_name): + directory = d + break + return directory + + def action_analyze(self): + """Process the zip file and generate details.""" + details = self._prepare_details_vals() + self.state = "analyze" + self.detail_ids = [(0, 0, vals) for vals in details] + return self._return_item() + + def _prepare_details_vals(self): + """Method that gets the files from .zip and if it apply the filename pattern + it will set it as detail with the corresponding values.""" + details = [] + zip_file = zipfile.ZipFile(BytesIO(base64.b64decode(self.data_file))) + filename_pattern = self.template_id.filename_pattern + for filename in zip_file.namelist(): + if re.search(filename_pattern, filename): + file_content = zip_file.read(filename) + data_file = base64.b64encode(file_content) + details.append(self._prepare_detail_vals(filename, data_file)) + return details + + def _prepare_detail_vals(self, file_name, data_file): + """Method to set the values of each detail. May be extended by other modules.""" + return { + "file_name": file_name, + "data_file": data_file, + } + + def _action_classify(self): + """Create the files (dms.file) in the corresponding directory. + Details that do not have a directory or already have a linked + file are skipped.""" + for detail in self.detail_ids.filtered( + lambda x: x.state == "to_classify" and x.directory_id + ): + detail._create_dms_file() + + def action_classify(self): + self._action_classify() + action = self.env["ir.actions.act_window"]._for_xml_id("dms.action_dms_file") + action["view_mode"] = "tree" + action["views"] = [(False, "tree")] + action["domain"] = [("id", "in", self.mapped("detail_ids.file_id").ids)] + return action + + +class WizardDmsClassificationDetail(models.TransientModel): + _name = "wizard.dms.classification.detail" + _description = "Wizard Dms Classification Detail" + + parent_id = fields.Many2one( + comodel_name="wizard.dms.classification", + string="Parent", + ) + file_name = fields.Char( + string="File name", + required=True, + readonly="True", + ) + data_file = fields.Binary( + string="File", + required=True, + ) + directory_id = fields.Many2one( + comodel_name="dms.directory", + string="Directory", + compute="_compute_directory_id", + store=True, + readonly=False, + ) + file_id = fields.Many2one( + comodel_name="dms.file", + string="File", + compute="_compute_file_id", + store=True, + readonly=True, + ) + state = fields.Selection( + selection=[ + ("to_classify", "To classify"), + ("classified", "Classified"), + ], + compute="_compute_state", + store=True, + readonly=True, + ) + + @api.depends("file_name") + def _compute_directory_id(self): + directories = self.env["dms.directory"].sudo().search([]) + for item in self: + item.directory_id = self.parent_id._get_directory_from_pattern( + self.parent_id.template_id.directory_pattern, directories + ) + + @api.depends("file_name", "directory_id", "parent_id.state") + def _compute_file_id(self): + for item in self.filtered(lambda x: x.file_name and x.directory_id): + files = item.directory_id.file_ids.filtered( + lambda x: x.name == item.file_name + ) + item.file_id = fields.first(files) + + @api.depends("file_id") + def _compute_state(self): + items_with_file = self.filtered("file_id") + items_with_file.state = "classified" + (self - items_with_file).state = "to_classify" + + def _create_dms_file(self): + self.ensure_one() + if not self.directory_id or self.file_id: + return + self.file_id = self.env["dms.file"].create( + { + "name": self.file_name, + "directory_id": self.directory_id.id, + "content": self.data_file, + } + ) diff --git a/dms_auto_classification/wizards/wizard_dms_classification_views.xml b/dms_auto_classification/wizards/wizard_dms_classification_views.xml new file mode 100644 index 000000000..9a8fb1f49 --- /dev/null +++ b/dms_auto_classification/wizards/wizard_dms_classification_views.xml @@ -0,0 +1,71 @@ + + + + + wizard.dms.classification + +
+
+ +
+ + + + + + + + + + + + + + + + +
+
+
+
+
+ + Auto Classification + wizard.dms.classification + form + new + + +
From 86861b3869f8ab23dc32baca087dfcf04831dedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Fri, 9 Feb 2024 13:40:47 +0100 Subject: [PATCH 02/15] [IMP] dms_auto_classification: Allow users with Documents: User permissions can use the wizard TT46805 --- .../security/ir.model.access.csv | 5 ++-- .../tests/test_dms_auto_classification.py | 30 ++++++++++++++++++- .../dms_classification_template_views.xml | 2 ++ .../wizard_dms_classification_views.xml | 2 ++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/dms_auto_classification/security/ir.model.access.csv b/dms_auto_classification/security/ir.model.access.csv index cc3f846c2..a15072901 100644 --- a/dms_auto_classification/security/ir.model.access.csv +++ b/dms_auto_classification/security/ir.model.access.csv @@ -1,4 +1,5 @@ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_dms_classification_template_user,dms_classification_template_user,model_dms_classification_template,dms.group_dms_user,1,0,0,0 access_dms_classification_template_manager,dms_classification_template_manager,model_dms_classification_template,dms.group_dms_manager,1,1,1,1 -access_wizard_dms_classification_manager,wizard_dms_classification_manager,model_wizard_dms_classification,dms.group_dms_manager,1,1,1,1 -access_wizard_dms_classification_detail_manager,wizard_dms_classification_detail_manager,model_wizard_dms_classification_detail,dms.group_dms_manager,1,1,1,1 +access_wizard_dms_classification_manager,wizard_dms_classification_manager,model_wizard_dms_classification,dms.group_dms_user,1,1,1,1 +access_wizard_dms_classification_detail_manager,wizard_dms_classification_detail_manager,model_wizard_dms_classification_detail,dms.group_dms_user,1,1,1,1 diff --git a/dms_auto_classification/tests/test_dms_auto_classification.py b/dms_auto_classification/tests/test_dms_auto_classification.py index be60f33fd..c09c374ec 100644 --- a/dms_auto_classification/tests/test_dms_auto_classification.py +++ b/dms_auto_classification/tests/test_dms_auto_classification.py @@ -4,19 +4,42 @@ from base64 import b64encode from os import path -from odoo.tests import Form, common +from odoo.tests import Form, common, new_test_user +from odoo.tests.common import users class TestDmsAutoClassification(common.TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() + cls.env = cls.env( + context=dict( + cls.env.context, + mail_create_nolog=True, + mail_create_nosubscribe=True, + mail_notrack=True, + no_reset_password=True, + tracking_disable=True, + ) + ) cls.template = cls.env.ref( "dms_auto_classification.dms_classification_template_documents" ) cls.directory = cls.env.ref("dms.directory_01_demo") cls.wizard = cls._create_wizard_dms_classification(cls, cls.template) cls.extra_wizard = cls._create_wizard_dms_classification(cls, cls.template) + cls.user = new_test_user( + cls.env, login="test_dms_user", groups="dms.group_dms_user" + ) + access_group = cls.env["dms.access.group"].create( + { + "name": "Test access group", + "perm_create": True, + "perm_write": True, + "explicit_user_ids": [(4, cls.user.id)], + } + ) + cls.directory.group_ids = [(4, access_group.id)] def _data_file(self, filename, encoding=None): mode = "rt" if encoding else "rb" @@ -32,7 +55,9 @@ def _create_wizard_dms_classification(self, template): wizard_form.data_file = self._data_file(self, "data/test.zip") return wizard_form.save() + @users("test_dms_user") def test_wizard_dms_clasification_process(self): + self.wizard = self.wizard.with_user(self.env.user) self.assertEqual(self.wizard.state, "draft") # Wizard - Analyze process self.wizard.action_analyze() @@ -65,6 +90,7 @@ def test_wizard_dms_clasification_process(self): # Extra wizard self.assertEqual(self.extra_wizard.state, "draft") # New Wizard - Analyze process + self.extra_wizard = self.extra_wizard.with_user(self.env.user) self.extra_wizard.action_analyze() self.assertEqual(self.extra_wizard.state, "analyze") self.assertEqual(len(self.extra_wizard.detail_ids), 2) @@ -96,10 +122,12 @@ def test_wizard_dms_clasification_process_filename_pattern(self): self.assertEqual(self.wizard.state, "analyze") self.assertEqual(len(self.wizard.detail_ids), 0) + @users("test_dms_user") def test_wizard_dms_clasification_process_directory_pattern(self): self.template.directory_pattern = "Documents2" self.assertEqual(self.wizard.state, "draft") # Analyze process + self.wizard = self.wizard.with_user(self.env.user) self.wizard.action_analyze() self.assertEqual(self.wizard.state, "analyze") self.assertEqual(len(self.wizard.detail_ids), 2) diff --git a/dms_auto_classification/views/dms_classification_template_views.xml b/dms_auto_classification/views/dms_classification_template_views.xml index 590043c8d..84c05c474 100644 --- a/dms_auto_classification/views/dms_classification_template_views.xml +++ b/dms_auto_classification/views/dms_classification_template_views.xml @@ -35,6 +35,7 @@ Classification Templates dms.classification.template tree,form + diff --git a/dms_auto_classification/wizards/wizard_dms_classification_views.xml b/dms_auto_classification/wizards/wizard_dms_classification_views.xml index 9a8fb1f49..0c63af6d3 100644 --- a/dms_auto_classification/wizards/wizard_dms_classification_views.xml +++ b/dms_auto_classification/wizards/wizard_dms_classification_views.xml @@ -60,6 +60,7 @@ wizard.dms.classification form new + From 2b44b19a4fbe0b06ca9edd9b71e0ca3e5becb0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Wed, 3 Apr 2024 08:34:22 +0200 Subject: [PATCH 03/15] [MIG] dms_auto_classification: Migration to 16.0 [UPD] Update dms_auto_classification.pot Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: dms-16.0/dms-16.0-dms_auto_classification Translate-URL: https://translation.odoo-community.org/projects/dms-16-0/dms-16-0-dms_auto_classification/ --- dms_auto_classification/README.rst | 12 ++++++------ dms_auto_classification/__manifest__.py | 2 +- .../i18n/dms_auto_classification.pot | 8 +++++++- dms_auto_classification/i18n/es.po | 6 ++++++ .../static/description/index.html | 9 +++++---- .../tests/test_dms_auto_classification.py | 16 ++++------------ .../wizards/wizard_dms_classification.py | 1 + .../wizards/wizard_dms_classification_views.xml | 2 ++ 8 files changed, 32 insertions(+), 24 deletions(-) diff --git a/dms_auto_classification/README.rst b/dms_auto_classification/README.rst index 748d1d3c5..a85918d11 100644 --- a/dms_auto_classification/README.rst +++ b/dms_auto_classification/README.rst @@ -7,7 +7,7 @@ Auto classify documents into DMS !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:3e93b0096e03b1ed8f97c4542423a631ee1cafff5e6ebe4bc537528b680bc1c1 + !! source digest: sha256:1858db5a66c0c6bb3643b0423f883b19a12a3f1bfec859f4a627362c3e2437e2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -17,13 +17,13 @@ Auto classify documents into DMS :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/15.0/dms_auto_classification + :target: https://github.com/OCA/dms/tree/16.0/dms_auto_classification :alt: OCA/dms .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/dms-15-0/dms-15-0-dms_auto_classification + :target: https://translation.odoo-community.org/projects/dms-16-0/dms-16-0-dms_auto_classification :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=15.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/dms&target_branch=16.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -60,7 +60,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. @@ -101,6 +101,6 @@ Current `maintainer `__: |maintainer-victoralmau| -This module is part of the `OCA/dms `_ project on GitHub. +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_auto_classification/__manifest__.py b/dms_auto_classification/__manifest__.py index 1bde5cfe0..50ba6dce6 100644 --- a/dms_auto_classification/__manifest__.py +++ b/dms_auto_classification/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Auto classify documents into DMS", - "version": "15.0.1.0.0", + "version": "16.0.1.0.0", "category": "Document Management", "website": "https://github.com/OCA/dms", "author": "Tecnativa, Odoo Community Association (OCA)", diff --git a/dms_auto_classification/i18n/dms_auto_classification.pot b/dms_auto_classification/i18n/dms_auto_classification.pot index 9ecce0750..9f6f509ba 100644 --- a/dms_auto_classification/i18n/dms_auto_classification.pot +++ b/dms_auto_classification/i18n/dms_auto_classification.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 15.0\n" +"Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -65,6 +65,11 @@ msgstr "" msgid "Created on" msgstr "" +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_filename +msgid "Data Filename" +msgstr "" + #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__detail_ids #: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form @@ -149,6 +154,7 @@ msgid "Name" msgstr "" #. module: dms_auto_classification +#. odoo-python #: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 #, python-format msgid "Only .zip files are allowed" diff --git a/dms_auto_classification/i18n/es.po b/dms_auto_classification/i18n/es.po index b552c0066..7956451f9 100644 --- a/dms_auto_classification/i18n/es.po +++ b/dms_auto_classification/i18n/es.po @@ -69,6 +69,11 @@ msgstr "Creado por" msgid "Created on" msgstr "Creado el" +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_filename +msgid "Data Filename" +msgstr "" + #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__detail_ids #: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form @@ -153,6 +158,7 @@ msgid "Name" msgstr "Nombrr" #. module: dms_auto_classification +#. odoo-python #: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 #, python-format msgid "Only .zip files are allowed" diff --git a/dms_auto_classification/static/description/index.html b/dms_auto_classification/static/description/index.html index 277e4de6c..1cfbdd598 100644 --- a/dms_auto_classification/static/description/index.html +++ b/dms_auto_classification/static/description/index.html @@ -1,3 +1,4 @@ + @@ -366,9 +367,9 @@

Auto classify documents into DMS

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:3e93b0096e03b1ed8f97c4542423a631ee1cafff5e6ebe4bc537528b680bc1c1 +!! source digest: sha256:1858db5a66c0c6bb3643b0423f883b19a12a3f1bfec859f4a627362c3e2437e2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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

Automatically classify files within a .zip file to the corresponding DMS directory(s).

Table of contents

@@ -409,7 +410,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.

@@ -439,7 +440,7 @@

Maintainers

promote its widespread use.

Current maintainer:

victoralmau

-

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

+

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_auto_classification/tests/test_dms_auto_classification.py b/dms_auto_classification/tests/test_dms_auto_classification.py index c09c374ec..ca8705e62 100644 --- a/dms_auto_classification/tests/test_dms_auto_classification.py +++ b/dms_auto_classification/tests/test_dms_auto_classification.py @@ -4,24 +4,16 @@ from base64 import b64encode from os import path -from odoo.tests import Form, common, new_test_user +from odoo.tests import Form, new_test_user from odoo.tests.common import users +from odoo.addons.base.tests.common import BaseCommon -class TestDmsAutoClassification(common.TransactionCase): + +class TestDmsAutoClassification(BaseCommon): @classmethod def setUpClass(cls): super().setUpClass() - cls.env = cls.env( - context=dict( - cls.env.context, - mail_create_nolog=True, - mail_create_nosubscribe=True, - mail_notrack=True, - no_reset_password=True, - tracking_disable=True, - ) - ) cls.template = cls.env.ref( "dms_auto_classification.dms_classification_template_documents" ) diff --git a/dms_auto_classification/wizards/wizard_dms_classification.py b/dms_auto_classification/wizards/wizard_dms_classification.py index 526d0197e..1987e6e17 100644 --- a/dms_auto_classification/wizards/wizard_dms_classification.py +++ b/dms_auto_classification/wizards/wizard_dms_classification.py @@ -29,6 +29,7 @@ class WizardDmsClassification(models.TransientModel): string="File", required=True, ) + data_filename = fields.Char() detail_ids = fields.One2many( comodel_name="wizard.dms.classification.detail", inverse_name="parent_id", diff --git a/dms_auto_classification/wizards/wizard_dms_classification_views.xml b/dms_auto_classification/wizards/wizard_dms_classification_views.xml index 0c63af6d3..4b424b77f 100644 --- a/dms_auto_classification/wizards/wizard_dms_classification_views.xml +++ b/dms_auto_classification/wizards/wizard_dms_classification_views.xml @@ -17,7 +17,9 @@ + Date: Fri, 3 May 2024 15:18:34 +0200 Subject: [PATCH 04/15] [IMP] dms_auto_classification: Add folder support within the .zip file Changes done: - The full path is now shown in the detail line. - The dms file that will be created will be with the name (not the full file path). - When scanning the .zip files the folders are skipped. - Add more use cases in tests - Improve documentation TT49047 [UPD] Update dms_auto_classification.pot [BOT] post-merge updates Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: dms-16.0/dms-16.0-dms_auto_classification Translate-URL: https://translation.odoo-community.org/projects/dms-16-0/dms-16-0-dms_auto_classification/ --- dms_auto_classification/README.rst | 6 ++- dms_auto_classification/__manifest__.py | 2 +- .../i18n/dms_auto_classification.pot | 6 +++ dms_auto_classification/i18n/es.po | 6 +++ dms_auto_classification/readme/CONFIGURE.rst | 3 ++ dms_auto_classification/readme/USAGE.rst | 1 + .../static/description/index.html | 6 ++- dms_auto_classification/tests/data/test.zip | Bin 2890 -> 3116 bytes .../tests/test_dms_auto_classification.py | 50 +++++++++++++++++- .../wizards/wizard_dms_classification.py | 30 ++++++++--- .../wizard_dms_classification_views.xml | 3 +- 11 files changed, 100 insertions(+), 13 deletions(-) diff --git a/dms_auto_classification/README.rst b/dms_auto_classification/README.rst index a85918d11..f972744b4 100644 --- a/dms_auto_classification/README.rst +++ b/dms_auto_classification/README.rst @@ -7,7 +7,7 @@ Auto classify documents into DMS !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:1858db5a66c0c6bb3643b0423f883b19a12a3f1bfec859f4a627362c3e2437e2 + !! source digest: sha256:20399fc6e0a34d031b09c407d6a58873ced772aa0772ace693d89d5eb15bf88c !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png @@ -45,12 +45,16 @@ Example of filename pattern to use only .txt files: .txt$ Directory pattern example 1: Documents Directory pattern example 1: Documents / Data +If the pattern doesn't contain path separators (/), the file name will be search across +all the subdirectories. + Usage ===== #. Go to `Documents / Auto Classification` and select a template and a .zip file. #. Press the `Analyze` button #. As many lines will be set as the number of files contained in the .zip file and apply the filename pattern. +#. The full path to the file will be displayed in each detail line. #. Press the `Classify` button #. The files (dms.file) will be created in the corresponding directories. diff --git a/dms_auto_classification/__manifest__.py b/dms_auto_classification/__manifest__.py index 50ba6dce6..8c1a68e1c 100644 --- a/dms_auto_classification/__manifest__.py +++ b/dms_auto_classification/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Auto classify documents into DMS", - "version": "16.0.1.0.0", + "version": "16.0.1.1.0", "category": "Document Management", "website": "https://github.com/OCA/dms", "author": "Tecnativa, Odoo Community Association (OCA)", diff --git a/dms_auto_classification/i18n/dms_auto_classification.pot b/dms_auto_classification/i18n/dms_auto_classification.pot index 9f6f509ba..bb0a00e24 100644 --- a/dms_auto_classification/i18n/dms_auto_classification.pot +++ b/dms_auto_classification/i18n/dms_auto_classification.pot @@ -112,6 +112,7 @@ msgstr "" #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_name +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form msgid "File name" msgstr "" @@ -120,6 +121,11 @@ msgstr "" msgid "Filename Pattern" msgstr "" +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__full_path +msgid "Full path" +msgstr "" + #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__id #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__id diff --git a/dms_auto_classification/i18n/es.po b/dms_auto_classification/i18n/es.po index 7956451f9..8366d4616 100644 --- a/dms_auto_classification/i18n/es.po +++ b/dms_auto_classification/i18n/es.po @@ -116,6 +116,7 @@ msgstr "Archivo" #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_name +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form msgid "File name" msgstr "Nombre de archivo" @@ -124,6 +125,11 @@ msgstr "Nombre de archivo" msgid "Filename Pattern" msgstr "Patrón de nombre de archivo" +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__full_path +msgid "Full path" +msgstr "" + #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__id #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__id diff --git a/dms_auto_classification/readme/CONFIGURE.rst b/dms_auto_classification/readme/CONFIGURE.rst index 8066cc5cd..d64f705f3 100644 --- a/dms_auto_classification/readme/CONFIGURE.rst +++ b/dms_auto_classification/readme/CONFIGURE.rst @@ -4,3 +4,6 @@ Example of filename pattern to use only .txt files: .txt$ Directory pattern example 1: Documents Directory pattern example 1: Documents / Data + +If the pattern doesn't contain path separators (/), the file name will be search across +all the subdirectories. diff --git a/dms_auto_classification/readme/USAGE.rst b/dms_auto_classification/readme/USAGE.rst index d8b5dbc0e..e2d1b1cba 100644 --- a/dms_auto_classification/readme/USAGE.rst +++ b/dms_auto_classification/readme/USAGE.rst @@ -1,5 +1,6 @@ #. Go to `Documents / Auto Classification` and select a template and a .zip file. #. Press the `Analyze` button #. As many lines will be set as the number of files contained in the .zip file and apply the filename pattern. +#. The full path to the file will be displayed in each detail line. #. Press the `Classify` button #. The files (dms.file) will be created in the corresponding directories. diff --git a/dms_auto_classification/static/description/index.html b/dms_auto_classification/static/description/index.html index 1cfbdd598..0d8953529 100644 --- a/dms_auto_classification/static/description/index.html +++ b/dms_auto_classification/static/description/index.html @@ -1,4 +1,3 @@ - @@ -367,7 +366,7 @@

Auto classify documents into DMS

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:1858db5a66c0c6bb3643b0423f883b19a12a3f1bfec859f4a627362c3e2437e2 +!! source digest: sha256:20399fc6e0a34d031b09c407d6a58873ced772aa0772ace693d89d5eb15bf88c !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

Automatically classify files within a .zip file to the corresponding DMS directory(s).

@@ -394,6 +393,8 @@

Configuration

Example of filename pattern to use only .txt files: .txt$ Directory pattern example 1: Documents Directory pattern example 1: Documents / Data

+

If the pattern doesn’t contain path separators (/), the file name will be search across +all the subdirectories.

Usage

@@ -401,6 +402,7 @@

Usage

  • Go to Documents / Auto Classification and select a template and a .zip file.
  • Press the Analyze button
  • As many lines will be set as the number of files contained in the .zip file and apply the filename pattern.
  • +
  • The full path to the file will be displayed in each detail line.
  • Press the Classify button
  • The files (dms.file) will be created in the corresponding directories.
  • diff --git a/dms_auto_classification/tests/data/test.zip b/dms_auto_classification/tests/data/test.zip index a529960957e7bc171ffbd64d19a0aa1b6ceb6597..78f317a001b5ad4758bac6efb063b5e01ab745a6 100644 GIT binary patch delta 530 zcmX>lwnm~pz?+#xgaHIN@)t*d8Bl_iL4lzpwYWq-G=!Id{ow_ZG#DK%Omp=Qgc-4$hk=0~W<*+MPO7e*s#0r+v68Iu1bA)fypFob3Lm# zs}DPe`LCr;Y^)3nAdSQtX@p{AKG;a8iS_6vGBSxUf1vrVrA} - + + From 58eacab7b0b3e740c5678ca666df4198e5aee8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Mon, 30 Sep 2024 10:55:35 +0200 Subject: [PATCH 05/15] [IMP] dms_auto_classification: Remove warning by several names with the same label WARNING devel odoo.addons.base.models.ir_model: Two fields (file_id, data_file) of wizard.dms.classification.detail() have the same label: File. [Modules: dms_auto_classification and dms_auto_classification] TT51051 [UPD] Update dms_auto_classification.pot [BOT] post-merge updates Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: dms-16.0/dms-16.0-dms_auto_classification Translate-URL: https://translation.odoo-community.org/projects/dms-16-0/dms-16-0-dms_auto_classification/ --- dms_auto_classification/README.rst | 2 +- dms_auto_classification/__manifest__.py | 2 +- .../i18n/dms_auto_classification.pot | 6 +++++- dms_auto_classification/i18n/es.po | 6 +++++- .../static/description/index.html | 13 ++++++++----- .../wizards/wizard_dms_classification.py | 2 +- 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/dms_auto_classification/README.rst b/dms_auto_classification/README.rst index f972744b4..6afabeadd 100644 --- a/dms_auto_classification/README.rst +++ b/dms_auto_classification/README.rst @@ -7,7 +7,7 @@ Auto classify documents into DMS !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:20399fc6e0a34d031b09c407d6a58873ced772aa0772ace693d89d5eb15bf88c + !! source digest: sha256:4b8df517cdad94a806c89521ecfd60b1505a9bf4f71ac75b281321313237b66e !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/dms_auto_classification/__manifest__.py b/dms_auto_classification/__manifest__.py index 8c1a68e1c..33582293a 100644 --- a/dms_auto_classification/__manifest__.py +++ b/dms_auto_classification/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Auto classify documents into DMS", - "version": "16.0.1.1.0", + "version": "16.0.1.1.1", "category": "Document Management", "website": "https://github.com/OCA/dms", "author": "Tecnativa, Odoo Community Association (OCA)", diff --git a/dms_auto_classification/i18n/dms_auto_classification.pot b/dms_auto_classification/i18n/dms_auto_classification.pot index bb0a00e24..bf3c7f122 100644 --- a/dms_auto_classification/i18n/dms_auto_classification.pot +++ b/dms_auto_classification/i18n/dms_auto_classification.pot @@ -105,11 +105,15 @@ msgstr "" #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_file -#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_id msgid "File" msgstr "" +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file +msgid "File content" +msgstr "" + #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_name #: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form diff --git a/dms_auto_classification/i18n/es.po b/dms_auto_classification/i18n/es.po index 8366d4616..73b7f9af0 100644 --- a/dms_auto_classification/i18n/es.po +++ b/dms_auto_classification/i18n/es.po @@ -109,11 +109,15 @@ msgstr "Borrador" #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_file -#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_id msgid "File" msgstr "Archivo" +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file +msgid "File content" +msgstr "" + #. module: dms_auto_classification #: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__file_name #: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form diff --git a/dms_auto_classification/static/description/index.html b/dms_auto_classification/static/description/index.html index 0d8953529..14521d156 100644 --- a/dms_auto_classification/static/description/index.html +++ b/dms_auto_classification/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -366,7 +367,7 @@

    Auto classify documents into DMS

    !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:20399fc6e0a34d031b09c407d6a58873ced772aa0772ace693d89d5eb15bf88c +!! source digest: sha256:4b8df517cdad94a806c89521ecfd60b1505a9bf4f71ac75b281321313237b66e !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

    Automatically classify files within a .zip file to the corresponding DMS directory(s).

    @@ -436,7 +437,9 @@

    Contributors

    Maintainers

    This module is maintained by the OCA.

    -Odoo Community Association + +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.

    diff --git a/dms_auto_classification/wizards/wizard_dms_classification.py b/dms_auto_classification/wizards/wizard_dms_classification.py index ea9d629ef..23b22ddfa 100644 --- a/dms_auto_classification/wizards/wizard_dms_classification.py +++ b/dms_auto_classification/wizards/wizard_dms_classification.py @@ -137,7 +137,7 @@ class WizardDmsClassificationDetail(models.TransientModel): string="File name", ) data_file = fields.Binary( - string="File", + string="File content", required=True, ) directory_id = fields.Many2one( From 5bf9ab281e328bbc27d1be934031b11d8bbc37c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Mon, 12 May 2025 10:09:05 +0200 Subject: [PATCH 06/15] [IMP] dms_auto_classification: pre-commit auto fixes --- dms_auto_classification/README.rst | 56 ++++++++++--------- dms_auto_classification/pyproject.toml | 3 + dms_auto_classification/readme/CONFIGURE.md | 11 ++++ dms_auto_classification/readme/CONFIGURE.rst | 9 --- .../readme/CONTRIBUTORS.md | 3 + .../readme/CONTRIBUTORS.rst | 4 -- .../{DESCRIPTION.rst => DESCRIPTION.md} | 3 +- dms_auto_classification/readme/USAGE.md | 9 +++ dms_auto_classification/readme/USAGE.rst | 6 -- .../static/description/index.html | 38 +++++++------ .../dms_classification_template_views.xml | 4 +- 11 files changed, 84 insertions(+), 62 deletions(-) create mode 100644 dms_auto_classification/pyproject.toml create mode 100644 dms_auto_classification/readme/CONFIGURE.md delete mode 100644 dms_auto_classification/readme/CONFIGURE.rst create mode 100644 dms_auto_classification/readme/CONTRIBUTORS.md delete mode 100644 dms_auto_classification/readme/CONTRIBUTORS.rst rename dms_auto_classification/readme/{DESCRIPTION.rst => DESCRIPTION.md} (73%) create mode 100644 dms_auto_classification/readme/USAGE.md delete mode 100644 dms_auto_classification/readme/USAGE.rst diff --git a/dms_auto_classification/README.rst b/dms_auto_classification/README.rst index 6afabeadd..d659797d1 100644 --- a/dms_auto_classification/README.rst +++ b/dms_auto_classification/README.rst @@ -17,18 +17,19 @@ Auto classify documents into DMS :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/16.0/dms_auto_classification + :target: https://github.com/OCA/dms/tree/18.0/dms_auto_classification :alt: OCA/dms .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/dms-16-0/dms-16-0-dms_auto_classification + :target: https://translation.odoo-community.org/projects/dms-18-0/dms-18-0-dms_auto_classification :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=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/dms&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -Automatically classify files within a .zip file to the corresponding DMS directory(s). +Automatically classify files within a .zip file to the corresponding DMS +directory(s). **Table of contents** @@ -38,25 +39,30 @@ Automatically classify files within a .zip file to the corresponding DMS directo Configuration ============= -#. Go to `Documents / Configuration / Classification Templates` and create a new template. -#. You can set patterns (regex expressions) for filenames and directories. +1. Go to Documents / Configuration / Classification Templates and create + a new template. +2. You can set patterns (regex expressions) for filenames and + directories. -Example of filename pattern to use only .txt files: .txt$ -Directory pattern example 1: Documents -Directory pattern example 1: Documents / Data +Example of filename pattern to use only .txt files: .txt$ Directory +pattern example 1: Documents Directory pattern example 1: Documents / +Data -If the pattern doesn't contain path separators (/), the file name will be search across -all the subdirectories. +If the pattern doesn't contain path separators (/), the file name will +be search across all the subdirectories. Usage ===== -#. Go to `Documents / Auto Classification` and select a template and a .zip file. -#. Press the `Analyze` button -#. As many lines will be set as the number of files contained in the .zip file and apply the filename pattern. -#. The full path to the file will be displayed in each detail line. -#. Press the `Classify` button -#. The files (dms.file) will be created in the corresponding directories. +1. Go to Documents / Auto Classification and select a template and a + .zip file. +2. Press the Analyze button +3. As many lines will be set as the number of files contained in the + .zip file and apply the filename pattern. +4. The full path to the file will be displayed in each detail line. +5. Press the Classify button +6. The files (dms.file) will be created in the corresponding + directories. Bug Tracker =========== @@ -64,7 +70,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. @@ -72,20 +78,20 @@ Credits ======= Authors -~~~~~~~ +------- * Tecnativa Contributors -~~~~~~~~~~~~ +------------ -* `Tecnativa `_: +- `Tecnativa `__: - * Víctor Martínez - * Pedro M. Baeza + - Víctor Martínez + - Pedro M. Baeza Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -105,6 +111,6 @@ Current `maintainer `__: |maintainer-victoralmau| -This module is part of the `OCA/dms `_ project on GitHub. +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_auto_classification/pyproject.toml b/dms_auto_classification/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/dms_auto_classification/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/dms_auto_classification/readme/CONFIGURE.md b/dms_auto_classification/readme/CONFIGURE.md new file mode 100644 index 000000000..a2f733cf8 --- /dev/null +++ b/dms_auto_classification/readme/CONFIGURE.md @@ -0,0 +1,11 @@ +1. Go to Documents / Configuration / Classification Templates and + create a new template. +2. You can set patterns (regex expressions) for filenames and + directories. + +Example of filename pattern to use only .txt files: .txt\$ Directory +pattern example 1: Documents Directory pattern example 1: Documents / +Data + +If the pattern doesn't contain path separators (/), the file name will +be search across all the subdirectories. diff --git a/dms_auto_classification/readme/CONFIGURE.rst b/dms_auto_classification/readme/CONFIGURE.rst deleted file mode 100644 index d64f705f3..000000000 --- a/dms_auto_classification/readme/CONFIGURE.rst +++ /dev/null @@ -1,9 +0,0 @@ -#. Go to `Documents / Configuration / Classification Templates` and create a new template. -#. You can set patterns (regex expressions) for filenames and directories. - -Example of filename pattern to use only .txt files: .txt$ -Directory pattern example 1: Documents -Directory pattern example 1: Documents / Data - -If the pattern doesn't contain path separators (/), the file name will be search across -all the subdirectories. diff --git a/dms_auto_classification/readme/CONTRIBUTORS.md b/dms_auto_classification/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..5fee39042 --- /dev/null +++ b/dms_auto_classification/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- [Tecnativa](https://www.tecnativa.com): + - Víctor Martínez + - Pedro M. Baeza diff --git a/dms_auto_classification/readme/CONTRIBUTORS.rst b/dms_auto_classification/readme/CONTRIBUTORS.rst deleted file mode 100644 index 5fb713053..000000000 --- a/dms_auto_classification/readme/CONTRIBUTORS.rst +++ /dev/null @@ -1,4 +0,0 @@ -* `Tecnativa `_: - - * Víctor Martínez - * Pedro M. Baeza diff --git a/dms_auto_classification/readme/DESCRIPTION.rst b/dms_auto_classification/readme/DESCRIPTION.md similarity index 73% rename from dms_auto_classification/readme/DESCRIPTION.rst rename to dms_auto_classification/readme/DESCRIPTION.md index f8d45a51e..2a8faa89d 100644 --- a/dms_auto_classification/readme/DESCRIPTION.rst +++ b/dms_auto_classification/readme/DESCRIPTION.md @@ -1 +1,2 @@ -Automatically classify files within a .zip file to the corresponding DMS directory(s). +Automatically classify files within a .zip file to the corresponding DMS +directory(s). diff --git a/dms_auto_classification/readme/USAGE.md b/dms_auto_classification/readme/USAGE.md new file mode 100644 index 000000000..25514718d --- /dev/null +++ b/dms_auto_classification/readme/USAGE.md @@ -0,0 +1,9 @@ +1. Go to Documents / Auto Classification and select a template and a + .zip file. +2. Press the Analyze button +3. As many lines will be set as the number of files contained in the + .zip file and apply the filename pattern. +4. The full path to the file will be displayed in each detail line. +5. Press the Classify button +6. The files (dms.file) will be created in the corresponding + directories. diff --git a/dms_auto_classification/readme/USAGE.rst b/dms_auto_classification/readme/USAGE.rst deleted file mode 100644 index e2d1b1cba..000000000 --- a/dms_auto_classification/readme/USAGE.rst +++ /dev/null @@ -1,6 +0,0 @@ -#. Go to `Documents / Auto Classification` and select a template and a .zip file. -#. Press the `Analyze` button -#. As many lines will be set as the number of files contained in the .zip file and apply the filename pattern. -#. The full path to the file will be displayed in each detail line. -#. Press the `Classify` button -#. The files (dms.file) will be created in the corresponding directories. diff --git a/dms_auto_classification/static/description/index.html b/dms_auto_classification/static/description/index.html index 14521d156..32e18904d 100644 --- a/dms_auto_classification/static/description/index.html +++ b/dms_auto_classification/static/description/index.html @@ -369,8 +369,9 @@

    Auto classify documents into DMS

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:4b8df517cdad94a806c89521ecfd60b1505a9bf4f71ac75b281321313237b66e !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

    -

    Automatically classify files within a .zip file to the corresponding DMS directory(s).

    +

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

    +

    Automatically classify files within a .zip file to the corresponding DMS +directory(s).

    Table of contents

      @@ -388,24 +389,29 @@

      Auto classify documents into DMS

      Configuration

        -
      1. Go to Documents / Configuration / Classification Templates and create a new template.
      2. -
      3. You can set patterns (regex expressions) for filenames and directories.
      4. +
      5. Go to Documents / Configuration / Classification Templates and create +a new template.
      6. +
      7. You can set patterns (regex expressions) for filenames and +directories.
      -

      Example of filename pattern to use only .txt files: .txt$ -Directory pattern example 1: Documents -Directory pattern example 1: Documents / Data

      -

      If the pattern doesn’t contain path separators (/), the file name will be search across -all the subdirectories.

      +

      Example of filename pattern to use only .txt files: .txt$ Directory +pattern example 1: Documents Directory pattern example 1: Documents / +Data

      +

      If the pattern doesn’t contain path separators (/), the file name will +be search across all the subdirectories.

      Usage

        -
      1. Go to Documents / Auto Classification and select a template and a .zip file.
      2. -
      3. Press the Analyze button
      4. -
      5. As many lines will be set as the number of files contained in the .zip file and apply the filename pattern.
      6. +
      7. Go to Documents / Auto Classification and select a template and a +.zip file.
      8. +
      9. Press the Analyze button
      10. +
      11. As many lines will be set as the number of files contained in the +.zip file and apply the filename pattern.
      12. The full path to the file will be displayed in each detail line.
      13. -
      14. Press the Classify button
      15. -
      16. The files (dms.file) will be created in the corresponding directories.
      17. +
      18. Press the Classify button
      19. +
      20. The files (dms.file) will be created in the corresponding +directories.
      @@ -413,7 +419,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.

      @@ -445,7 +451,7 @@

      Maintainers

      promote its widespread use.

      Current maintainer:

      victoralmau

      -

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

      +

      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_auto_classification/views/dms_classification_template_views.xml b/dms_auto_classification/views/dms_classification_template_views.xml index 84c05c474..6eece1a6f 100644 --- a/dms_auto_classification/views/dms_classification_template_views.xml +++ b/dms_auto_classification/views/dms_classification_template_views.xml @@ -20,7 +20,9 @@
    -

    +

    + +

    From 9080feb7a12b91d1b94154f6620ee5452795aa4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Mon, 12 May 2025 10:12:37 +0200 Subject: [PATCH 07/15] [MIG] dms_auto_classification: Migration to 18.0 TT55506 --- dms_auto_classification/__manifest__.py | 2 +- .../tests/test_dms_auto_classification.py | 21 +++++++++-------- .../dms_classification_template_views.xml | 6 ++--- .../wizards/wizard_dms_classification.py | 8 +++---- .../wizard_dms_classification_views.xml | 23 +++++++------------ 5 files changed, 28 insertions(+), 32 deletions(-) diff --git a/dms_auto_classification/__manifest__.py b/dms_auto_classification/__manifest__.py index 33582293a..f2894c046 100644 --- a/dms_auto_classification/__manifest__.py +++ b/dms_auto_classification/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Auto classify documents into DMS", - "version": "16.0.1.1.1", + "version": "18.0.1.0.0", "category": "Document Management", "website": "https://github.com/OCA/dms", "author": "Tecnativa, Odoo Community Association (OCA)", diff --git a/dms_auto_classification/tests/test_dms_auto_classification.py b/dms_auto_classification/tests/test_dms_auto_classification.py index 4a007dc6f..3d276d6c8 100644 --- a/dms_auto_classification/tests/test_dms_auto_classification.py +++ b/dms_auto_classification/tests/test_dms_auto_classification.py @@ -1,9 +1,10 @@ -# Copyright 2024 Tecnativa - Víctor Martínez +# Copyright 2024-2025 Tecnativa - Víctor Martínez # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from base64 import b64encode from os import path +from odoo import Command from odoo.tests import Form, new_test_user from odoo.tests.common import users @@ -18,8 +19,8 @@ def setUpClass(cls): "dms_auto_classification.dms_classification_template_documents" ) cls.directory = cls.env.ref("dms.directory_01_demo") - cls.wizard = cls._create_wizard_dms_classification(cls, cls.template) - cls.extra_wizard = cls._create_wizard_dms_classification(cls, cls.template) + cls.wizard = cls._create_wizard_dms_classification(cls.template) + cls.extra_wizard = cls._create_wizard_dms_classification(cls.template) cls.user = new_test_user( cls.env, login="test_dms_user", groups="dms.group_dms_user" ) @@ -28,12 +29,13 @@ def setUpClass(cls): "name": "Test access group", "perm_create": True, "perm_write": True, - "explicit_user_ids": [(4, cls.user.id)], + "explicit_user_ids": [Command.set([cls.user.id])], } ) - cls.directory.group_ids = [(4, access_group.id)] + cls.directory.group_ids = [Command.set([access_group.id])] - def _data_file(self, filename, encoding=None): + @classmethod + def _data_file(cls, filename, encoding=None): mode = "rt" if encoding else "rb" with open(path.join(path.dirname(__file__), filename), mode) as file: data = file.read() @@ -41,10 +43,11 @@ def _data_file(self, filename, encoding=None): data = data.encode(encoding) return b64encode(data) - def _create_wizard_dms_classification(self, template): - wizard_form = Form(self.env["wizard.dms.classification"]) + @classmethod + def _create_wizard_dms_classification(cls, template): + wizard_form = Form(cls.env["wizard.dms.classification"]) wizard_form.template_id = template - wizard_form.data_file = self._data_file(self, "data/test.zip") + wizard_form.data_file = cls._data_file("data/test.zip") return wizard_form.save() @users("test_dms_user") diff --git a/dms_auto_classification/views/dms_classification_template_views.xml b/dms_auto_classification/views/dms_classification_template_views.xml index 6eece1a6f..e090494f5 100644 --- a/dms_auto_classification/views/dms_classification_template_views.xml +++ b/dms_auto_classification/views/dms_classification_template_views.xml @@ -5,13 +5,13 @@ dms.classification.template - + - + @@ -36,7 +36,7 @@ Classification Templates dms.classification.template - tree,form + list,form - + - + - + - + - + @@ -44,14 +37,14 @@ string="Analyze" type="object" class="btn-primary" - attrs="{'invisible' : [('state', '!=', 'draft')]}" + invisible="state!='draft'" />
    @@ -451,7 +451,7 @@

    Maintainers

    promote its widespread use.

    Current maintainer:

    victoralmau

    -

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

    +

    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.

    From cfa9fe717a56d79514767da1f13858a08048c759 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Tue, 26 May 2026 19:09:35 -0400 Subject: [PATCH 11/15] [MIG] dms_auto_classification: Migration to 19.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `groups_id` → `group_ids` on both `ir.actions.act_window` records (19.0 field rename) - Tests: replace `env.ref()` demo-data lookups with inline fixtures in `setUpClass` — OCA CI runs without demo data --- .../tests/test_dms_auto_classification.py | 36 +++++++++++++------ .../dms_classification_template_views.xml | 2 +- .../wizard_dms_classification_views.xml | 2 +- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/dms_auto_classification/tests/test_dms_auto_classification.py b/dms_auto_classification/tests/test_dms_auto_classification.py index 3d276d6c8..7b1ac3daf 100644 --- a/dms_auto_classification/tests/test_dms_auto_classification.py +++ b/dms_auto_classification/tests/test_dms_auto_classification.py @@ -15,24 +15,38 @@ class TestDmsAutoClassification(BaseCommon): @classmethod def setUpClass(cls): super().setUpClass() - cls.template = cls.env.ref( - "dms_auto_classification.dms_classification_template_documents" + # Create fixtures directly — OCA CI runs without demo data. + cls.storage = cls.env["dms.storage"].create( + {"name": "Test Storage", "save_type": "database"} ) - cls.directory = cls.env.ref("dms.directory_01_demo") - cls.wizard = cls._create_wizard_dms_classification(cls.template) - cls.extra_wizard = cls._create_wizard_dms_classification(cls.template) - cls.user = new_test_user( - cls.env, login="test_dms_user", groups="dms.group_dms_user" - ) - access_group = cls.env["dms.access.group"].create( + cls.access_group = cls.env["dms.access.group"].create( { "name": "Test access group", "perm_create": True, "perm_write": True, - "explicit_user_ids": [Command.set([cls.user.id])], } ) - cls.directory.group_ids = [Command.set([access_group.id])] + cls.directory = cls.env["dms.directory"].create( + { + "name": "Documents", + "is_root_directory": True, + "storage_id": cls.storage.id, + "group_ids": [Command.link(cls.access_group.id)], + } + ) + cls.template = cls.env["dms.classification.template"].create( + { + "name": "Documents template", + "filename_pattern": ".txt$", + "directory_pattern": "Documents", + } + ) + cls.user = new_test_user( + cls.env, login="test_dms_user", groups="dms.group_dms_user" + ) + cls.access_group.explicit_user_ids = [Command.link(cls.user.id)] + cls.wizard = cls._create_wizard_dms_classification(cls.template) + cls.extra_wizard = cls._create_wizard_dms_classification(cls.template) @classmethod def _data_file(cls, filename, encoding=None): diff --git a/dms_auto_classification/views/dms_classification_template_views.xml b/dms_auto_classification/views/dms_classification_template_views.xml index e090494f5..28c250f31 100644 --- a/dms_auto_classification/views/dms_classification_template_views.xml +++ b/dms_auto_classification/views/dms_classification_template_views.xml @@ -37,7 +37,7 @@ Classification Templates dms.classification.template list,form - + wizard.dms.classification form new - + Date: Wed, 27 May 2026 07:24:53 -0400 Subject: [PATCH 12/15] [FIX] dms_auto_classification: correct model_id for wizard detail ACL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit access_wizard_dms_classification_detail_user pointed to model_dms_classification_template instead of model_wizard_dms_classification_detail, so group_dms_user never got CRUD access to wizard.dms.classification.detail — causing AccessError when running the classify wizard as a regular DMS user. --- dms_auto_classification/security/ir.model.access.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dms_auto_classification/security/ir.model.access.csv b/dms_auto_classification/security/ir.model.access.csv index 6df2109ab..23e9e5a83 100644 --- a/dms_auto_classification/security/ir.model.access.csv +++ b/dms_auto_classification/security/ir.model.access.csv @@ -2,5 +2,5 @@ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink access_dms_classification_template_user,dms_classification_template_user,model_dms_classification_template,dms.group_dms_user,1,0,0,0 access_dms_classification_template_manager,dms_classification_template_manager,model_dms_classification_template,dms.group_dms_manager,1,1,1,1 access_wizard_dms_classification_manager,wizard_dms_classification_manager,model_wizard_dms_classification,dms.group_dms_user,1,1,1,1 -access_wizard_dms_classification_detail_user,wizard_dms_classification_detail_user,model_dms_classification_template,dms.group_dms_user,1,1,1,0 +access_wizard_dms_classification_detail_user,wizard_dms_classification_detail_user,model_wizard_dms_classification_detail,dms.group_dms_user,1,1,1,0 access_wizard_dms_classification_detail_manager,wizard_dms_classification_detail_manager,model_wizard_dms_classification_detail,dms.group_dms_user,1,1,1,1 From 8c71c61f15a258dbe6c8edc5ef01c27b8d5d6ee4 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Wed, 27 May 2026 11:12:05 -0400 Subject: [PATCH 13/15] [FIX] dms_auto_classification: use self.env._() per prefer-env-translation pylint-odoo W8161 mandates self.env._() over the legacy _() lazy import. --- dms_auto_classification/wizards/wizard_dms_classification.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dms_auto_classification/wizards/wizard_dms_classification.py b/dms_auto_classification/wizards/wizard_dms_classification.py index e306d590e..788704084 100644 --- a/dms_auto_classification/wizards/wizard_dms_classification.py +++ b/dms_auto_classification/wizards/wizard_dms_classification.py @@ -5,7 +5,7 @@ import zipfile from io import BytesIO -from odoo import _, api, fields, models +from odoo import api, fields, models from odoo.exceptions import UserError @@ -54,7 +54,7 @@ def _is_zipfile(self): def _onchange_data_file(self): for item in self.filtered("data_file"): if not item._is_zipfile(): - raise UserError(_("Only .zip files are allowed")) + raise UserError(self.env._("Only .zip files are allowed")) def _return_item(self): return { From e921f98e77c8f96000feb342e01a0e658f41a5a3 Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Wed, 27 May 2026 11:18:41 -0400 Subject: [PATCH 14/15] [FIX] dms_auto_classification: remove parent_id.state from _compute_file_id to break 19.0 recursive invalidation loop --- dms_auto_classification/wizards/wizard_dms_classification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dms_auto_classification/wizards/wizard_dms_classification.py b/dms_auto_classification/wizards/wizard_dms_classification.py index 788704084..7002396c8 100644 --- a/dms_auto_classification/wizards/wizard_dms_classification.py +++ b/dms_auto_classification/wizards/wizard_dms_classification.py @@ -189,7 +189,7 @@ def _compute_directory_id(self): self.parent_id.template_id.directory_pattern, directories ) - @api.depends("file_name", "directory_id", "parent_id.state") + @api.depends("file_name", "directory_id") def _compute_file_id(self): for item in self.filtered(lambda x: x.file_name and x.directory_id): files = item.directory_id.file_ids.filtered( From 54b89d12591054e92905c8abf42acdff37c34d2b Mon Sep 17 00:00:00 2001 From: Don Kendall Date: Thu, 28 May 2026 16:34:20 -0400 Subject: [PATCH 15/15] [FIX] dms_auto_classification: replace fields.first() with recordset[:1] (removed in 19.0) --- dms_auto_classification/wizards/wizard_dms_classification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dms_auto_classification/wizards/wizard_dms_classification.py b/dms_auto_classification/wizards/wizard_dms_classification.py index 7002396c8..eaab6b38d 100644 --- a/dms_auto_classification/wizards/wizard_dms_classification.py +++ b/dms_auto_classification/wizards/wizard_dms_classification.py @@ -195,7 +195,7 @@ def _compute_file_id(self): files = item.directory_id.file_ids.filtered( lambda x, item=item: x.name == item.file_name ) - item.file_id = fields.first(files) + item.file_id = files[:1] @api.depends("file_id") def _compute_state(self):