diff --git a/dms_auto_classification/README.rst b/dms_auto_classification/README.rst new file mode 100644 index 000000000..c1cda5082 --- /dev/null +++ b/dms_auto_classification/README.rst @@ -0,0 +1,120 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +================================ +Auto classify documents into DMS +================================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:764296a8363524adc63d649264fc1229333327133ac0ea2a5f9f57c653767218 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdms-lightgray.png?logo=github + :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-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=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). + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +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. + +Usage +===== + +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 +=========== + +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..a371d58f4 --- /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": "19.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/ar.po b/dms_auto_classification/i18n/ar.po new file mode 100644 index 000000000..33a29ddae --- /dev/null +++ b/dms_auto_classification/i18n/ar.po @@ -0,0 +1,204 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_auto_classification +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2026-05-15 00:52+0000\n" +"Last-Translator: Mohamed Essam Salem \n" +"Language-Team: none\n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n" +"X-Generator: Weblate 5.15.2\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 +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__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__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 +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__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 +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_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 +#: 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__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 +#. odoo-python +#: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 +msgid "Only .zip files are allowed" +msgstr "يُسمح فقط بملفات .zip" + +#. 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/dms_auto_classification.pot b/dms_auto_classification/i18n/dms_auto_classification.pot new file mode 100644 index 000000000..48aec686a --- /dev/null +++ b/dms_auto_classification/i18n/dms_auto_classification.pot @@ -0,0 +1,200 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_auto_classification +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.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 +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__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__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 +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__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 +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_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 +#: 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__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 +#. odoo-python +#: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 +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..5a50b2c50 --- /dev/null +++ b/dms_auto_classification/i18n/es.po @@ -0,0 +1,207 @@ +# 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: 2026-02-19 14:40+0000\n" +"Last-Translator: herminioelx \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: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.15.2\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 +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__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__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 +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__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 "Contenido del fichero" + +#. 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" + +#. 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_wizard_dms_classification_detail__full_path +msgid "Full path" +msgstr "Ruta entera" + +#. 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__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 "Nombre" + +#. module: dms_auto_classification +#. odoo-python +#: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 +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 "Asistente Dms Clasificación" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification_detail +msgid "Wizard Dms Classification Detail" +msgstr "Asistente de Clasificación Dms Detalle" + +#~ msgid "Last Modified on" +#~ msgstr "Última Modificación el" diff --git a/dms_auto_classification/i18n/it.po b/dms_auto_classification/i18n/it.po new file mode 100644 index 000000000..402666133 --- /dev/null +++ b/dms_auto_classification/i18n/it.po @@ -0,0 +1,206 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_auto_classification +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-10-03 10:06+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: dms_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 "Analizza" + +#. 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 "Classificazione automatica" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Cancel" +msgstr "Annulla" + +#. 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 "Modello classificazione" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification_detail__state__classified +msgid "Classified" +msgstr "Classificato" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Classify" +msgstr "Classifica" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__company_id +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__company_id +msgid "Company" +msgstr "Azienda" + +#. 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 "Creato da" + +#. 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 "Creato il" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_filename +msgid "Data Filename" +msgstr "Nome file dati" + +#. 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 "Dettagli" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__directory_id +msgid "Directory" +msgstr "Cartella" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__directory_pattern +msgid "Directory Pattern" +msgstr "Schema cartella" + +#. 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 "Nome visualizzato" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_dms_classification_template +msgid "Dms Classification Template" +msgstr "Modello classificazione DMS" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification__state__draft +msgid "Draft" +msgstr "Bozza" + +#. 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__file_id +msgid "File" +msgstr "File" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file +msgid "File content" +msgstr "Contenuto file" + +#. 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 "Nome file" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__filename_pattern +msgid "Filename Pattern" +msgstr "Schema nome file" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__full_path +msgid "Full path" +msgstr "Percorso completo" + +#. 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__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 "Ultimo aggiornamento di" + +#. 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 "Ultimo aggiornamento il" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__name +msgid "Name" +msgstr "Nome" + +#. module: dms_auto_classification +#. odoo-python +#: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 +msgid "Only .zip files are allowed" +msgstr "Sono consentiti solo file .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 "Sequenza" + +#. 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 "Stato" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__template_id +msgid "Template" +msgstr "Modello" + +#. 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 "Da classificare" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification +msgid "Wizard Dms Classification" +msgstr "Procedura guidata classificazione DMS" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification_detail +msgid "Wizard Dms Classification Detail" +msgstr "Procedura guidata dettagli classificazione DMS" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" diff --git a/dms_auto_classification/i18n/sl.po b/dms_auto_classification/i18n/sl.po new file mode 100644 index 000000000..7188fa00a --- /dev/null +++ b/dms_auto_classification/i18n/sl.po @@ -0,0 +1,204 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_auto_classification +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2026-06-22 09:32+0000\n" +"Last-Translator: Matjaz Mozetic \n" +"Language-Team: none\n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3;\n" +"X-Generator: Weblate 5.15.2\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 "Analiziraj" + +#. 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 "Samodejna klasifikacija" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Cancel" +msgstr "Prekliči" + +#. 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 "Predloge klasifikacije" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification_detail__state__classified +msgid "Classified" +msgstr "Klasificirano" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Classify" +msgstr "Klasificiraj" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__company_id +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__company_id +msgid "Company" +msgstr "Družba" + +#. 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 "Ustvaril" + +#. 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 "Ustvarjeno" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_filename +msgid "Data Filename" +msgstr "Naziv datoteke" + +#. 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 "Podrobnosti" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__directory_id +msgid "Directory" +msgstr "Mapa" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__directory_pattern +msgid "Directory Pattern" +msgstr "Vzorčenje map" + +#. 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 "Prikazani naziv" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_dms_classification_template +msgid "Dms Classification Template" +msgstr "DMS predloga klasifikacije" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification__state__draft +msgid "Draft" +msgstr "Osnutek" + +#. 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__file_id +msgid "File" +msgstr "Datoteka" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file +msgid "File content" +msgstr "Vsebina datoteke" + +#. 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 "Naziv datoteke" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__filename_pattern +msgid "Filename Pattern" +msgstr "Vzorčenje datoteke" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__full_path +msgid "Full path" +msgstr "Polna pot" + +#. 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__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 "Zadnji posodobil" + +#. 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 "Zadnjič posodobljeno" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__name +msgid "Name" +msgstr "Naziv" + +#. module: dms_auto_classification +#. odoo-python +#: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 +msgid "Only .zip files are allowed" +msgstr "Dovoljene so le .zip datoteke" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__parent_id +msgid "Parent" +msgstr "Nadrejeni" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__sequence +msgid "Sequence" +msgstr "Zaporedje" + +#. 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 "Stanje" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__template_id +msgid "Template" +msgstr "Predloga" + +#. 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 "Za klasifikacijo" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification +msgid "Wizard Dms Classification" +msgstr "Čarovnik DMS klasifikacija" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification_detail +msgid "Wizard Dms Classification Detail" +msgstr "Čarovnik DMS podrobnosti klasifikacije" diff --git a/dms_auto_classification/i18n/sv.po b/dms_auto_classification/i18n/sv.po new file mode 100644 index 000000000..85dd93e26 --- /dev/null +++ b/dms_auto_classification/i18n/sv.po @@ -0,0 +1,203 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dms_auto_classification +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-09-18 17:42+0000\n" +"Last-Translator: jakobkrabbe \n" +"Language-Team: none\n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.10.4\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 "Objekta" + +#. 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 "Klassificering av bilar" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Cancel" +msgstr "Avbryt" + +#. 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 "Klassificeringsmallar" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification_detail__state__classified +msgid "Classified" +msgstr "Klassificerad" + +#. module: dms_auto_classification +#: model_terms:ir.ui.view,arch_db:dms_auto_classification.view_wizard_dms_classification_form +msgid "Classify" +msgstr "Klassificera" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__company_id +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__company_id +msgid "Company" +msgstr "Bolag" + +#. 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 "Skapad av" + +#. 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 "Skapad på" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__data_filename +msgid "Data Filename" +msgstr "Datum Filnamn" + +#. 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 "Detaljer" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__directory_id +msgid "Directory" +msgstr "Katalog" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__directory_pattern +msgid "Directory Pattern" +msgstr "Katalogmönster" + +#. 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 "Visningsnamn" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_dms_classification_template +msgid "Dms Classification Template" +msgstr "Mall för Dms-klassificering" + +#. module: dms_auto_classification +#: model:ir.model.fields.selection,name:dms_auto_classification.selection__wizard_dms_classification__state__draft +msgid "Draft" +msgstr "Utkast" + +#. 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__file_id +msgid "File" +msgstr "Fil" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__data_file +msgid "File content" +msgstr "Filens innehåll" + +#. 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 "Filens namn" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__filename_pattern +msgid "Filename Pattern" +msgstr "Mönster för filnamn" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__full_path +msgid "Full path" +msgstr "Fullständig sökväg" + +#. 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__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 "Senast uppdaterad av" + +#. 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 "Senast uppdaterad den" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__name +msgid "Name" +msgstr "Namn" + +#. module: dms_auto_classification +#. odoo-python +#: code:addons/dms_auto_classification/wizards/wizard_dms_classification.py:0 +msgid "Only .zip files are allowed" +msgstr "Endast .zip-filer är tillåtna" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification_detail__parent_id +msgid "Parent" +msgstr "Överordnad" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_dms_classification_template__sequence +msgid "Sequence" +msgstr "Sekvens" + +#. 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 "Stat" + +#. module: dms_auto_classification +#: model:ir.model.fields,field_description:dms_auto_classification.field_wizard_dms_classification__template_id +msgid "Template" +msgstr "Mall" + +#. 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 "Att klassificera" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification +msgid "Wizard Dms Classification" +msgstr "Wizard Dms Klassificering" + +#. module: dms_auto_classification +#: model:ir.model,name:dms_auto_classification.model_wizard_dms_classification_detail +msgid "Wizard Dms Classification Detail" +msgstr "Wizard Dms Klassificering Detalj" 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/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/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/DESCRIPTION.md b/dms_auto_classification/readme/DESCRIPTION.md new file mode 100644 index 000000000..2a8faa89d --- /dev/null +++ b/dms_auto_classification/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +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/security/ir.model.access.csv b/dms_auto_classification/security/ir.model.access.csv new file mode 100644 index 000000000..6df2109ab --- /dev/null +++ b/dms_auto_classification/security/ir.model.access.csv @@ -0,0 +1,6 @@ +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_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/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 000000000..9fd5b327a Binary files /dev/null and b/dms_auto_classification/static/description/icon.png differ diff --git a/dms_auto_classification/static/description/icon.svg b/dms_auto_classification/static/description/icon.svg new file mode 100644 index 000000000..38e821a45 --- /dev/null +++ b/dms_auto_classification/static/description/icon.svg @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dms_auto_classification/static/description/index.html b/dms_auto_classification/static/description/index.html new file mode 100644 index 000000000..67ad93df3 --- /dev/null +++ b/dms_auto_classification/static/description/index.html @@ -0,0 +1,466 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

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

+

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. The full path to the file will be displayed in each detail line.
  8. +
  9. Press the Classify button
  10. +
  11. The files (dms.file) will be created in the corresponding +directories.
  12. +
+
+
+

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 000000000..78f317a00 Binary files /dev/null and b/dms_auto_classification/tests/data/test.zip differ 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..3d276d6c8 --- /dev/null +++ b/dms_auto_classification/tests/test_dms_auto_classification.py @@ -0,0 +1,192 @@ +# 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 + +from odoo.addons.base.tests.common import BaseCommon + + +class TestDmsAutoClassification(BaseCommon): + @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.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( + { + "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])] + + @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() + if encoding: + data = data.encode(encoding) + return b64encode(data) + + @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 = cls._data_file("data/test.zip") + return wizard_form.save() + + @users("test_dms_user") + def test_wizard_dms_clasification_process_01(self): + self.wizard = self.wizard.with_user(self.env.user) + 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) + full_paths = self.wizard.mapped("detail_ids.full_path") + self.assertIn("test/file-1.txt", full_paths) + self.assertIn("test/file-2.txt", full_paths) + 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 = 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) + 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_01(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_filename_pattern_02(self): + self.template.filename_pattern = "test2/.txt$" + 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_filename_pattern_03(self): + self.template.filename_pattern = "test.*.txt$" + self.assertEqual(self.wizard.state, "draft") + self.wizard.action_analyze() + self.assertEqual(self.wizard.state, "analyze") + self.assertEqual(len(self.wizard.detail_ids), 2) + full_paths = self.wizard.mapped("detail_ids.full_path") + self.assertIn("test/file-1.txt", full_paths) + self.assertIn("test/file-2.txt", full_paths) + file_names = self.wizard.mapped("detail_ids.file_name") + self.assertIn("file-1.txt", file_names) + self.assertIn("file-2.txt", file_names) + + def test_wizard_dms_clasification_process_filename_pattern_04(self): + self.template.filename_pattern = "test1.*.txt$" + 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_filename_pattern_05(self): + self.template.filename_pattern = "test.*.file-1.txt$" + self.assertEqual(self.wizard.state, "draft") + self.wizard.action_analyze() + self.assertEqual(self.wizard.state, "analyze") + self.assertEqual(len(self.wizard.detail_ids), 1) + full_paths = self.wizard.mapped("detail_ids.full_path") + self.assertIn("test/file-1.txt", full_paths) + self.assertNotIn("test/file-2.txt", full_paths) + file_names = self.wizard.mapped("detail_ids.file_name") + self.assertIn("file-1.txt", file_names) + self.assertNotIn("file-2.txt", file_names) + + @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) + full_paths = self.wizard.mapped("detail_ids.full_path") + self.assertIn("test/file-1.txt", full_paths) + self.assertIn("test/file-2.txt", full_paths) + 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..28c250f31 --- /dev/null +++ b/dms_auto_classification/views/dms_classification_template_views.xml @@ -0,0 +1,50 @@ + + + + + dms.classification.template + + + + + + + + + + + + dms.classification.template + +
+ +
+

+ +

+
+ + + + + +
+
+
+
+ + Classification Templates + dms.classification.template + list,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..788704084 --- /dev/null +++ b/dms_auto_classification/wizards/wizard_dms_classification.py @@ -0,0 +1,216 @@ +# Copyright 2024-2026 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" + + company_id = fields.Many2one( + comodel_name="res.company", + required=True, + default=lambda self: self.env.company, + string="Company", + ) + state = fields.Selection( + selection=[ + ("draft", "Draft"), + ("analyze", "Analyze"), + ], + default="draft", + ) + template_id = fields.Many2one( + comodel_name="dms.classification.template", + string="Template", + required=True, + domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", + ) + data_file = fields.Binary( + string="File", + required=True, + ) + data_filename = fields.Char() + 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(self.env._("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 zip_info in zip_file.infolist(): + if zip_info.is_dir(): + continue + filename = zip_info.filename + 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, full_path, data_file): + """Method to set the values of each detail. May be extended by other modules. + Clean full_path (remove / from folders).""" + return { + "full_path": full_path, + "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"] = "list" + action["views"] = [(False, "list")] + 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", + ) + full_path = fields.Char( + string="Full path", + required=True, + readonly=True, + ) + file_name = fields.Char( + compute="_compute_file_name", + store=True, + string="File name", + ) + data_file = fields.Binary( + string="File content", + 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("full_path") + def _compute_file_name(self): + """File_name field is used to set file_id.""" + for item in self: + name = item.full_path + if "/" in name: + name = name.split("/")[-1] + item.file_name = name + + @api.depends("file_name") + def _compute_directory_id(self): + domain = [("company_id", "=", self.parent_id.company_id.id)] + directories = self.env["dms.directory"].search(domain) + 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, item=item: 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..b25123d26 --- /dev/null +++ b/dms_auto_classification/wizards/wizard_dms_classification_views.xml @@ -0,0 +1,69 @@ + + + + + wizard.dms.classification + +
+
+ +
+ + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + Auto Classification + wizard.dms.classification + form + new + + + +