Initial commit: OCA Technical packages (595 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:03 +02:00
commit 2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions

View file

@ -0,0 +1,129 @@
======================
Attachment Synchronize
======================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0f1a47ff1d87a76dc1e0bce4178fc538be9abc93414fbcec5bfd3a6299aa2dcd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fserver--tools-lightgray.png?logo=github
:target: https://github.com/OCA/server-tools/tree/16.0/attachment_synchronize
:alt: OCA/server-tools
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-tools-16-0/server-tools-16-0-attachment_synchronize
: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/server-tools&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allows to **import/export files** from/to backend servers.
A backend server is defined by the basic `fs_storage <https://github.com/OCA/storage/tree/16.0/fs_storage>`_ OCA module, while it can be configured (amazon S3, sftp,...) with additional modules fs python libraries
The imported files (and the files to be exported) are stored in Odoo as ``attachment.queue`` objects, defined by the `attachment_queue <https://github.com/OCA/server-tools/tree/16.0/attachment_queue>`_ module while the importation itself (resp. exportation) is realized by **"Attachments Import Tasks"** (resp. "Attachments Export Tasks") defined by this current module.
**Table of contents**
.. contents::
:local:
Usage
=====
As importation and exportation are different processes, they are triggered in different ways :
**To import files**, you need to create an *"Attachment Import Task"* (menu *Settings > Technical > Attachments Import Tasks*) which defines :
- where to find the files to import from the backend server (path to the files, selection pattern)
- what to do with the source files in the backend server (avoid duplicates, delete/rename after import...)
- how the files will be processed once imported (through the **File Type** field).
.. image:: https://raw.githubusercontent.com/OCA/server-tools/16.0/attachment_synchronize/static/description/import_task.png
.. epigraph::
🔎 The **File Type** options are defined by other modules built to process the Attachments Queues with the same "File Type".
**To export files**, you need first to register them as *"Attachments Queues"* objects linked to an *"Attachment Export Task"* (which set automatically their **File Type** to *"Export File (External Location)"*).
Then, you can export one file at a time from the *Attachment Queue*'s form view, or export all the *Attachments Queues* in a pending state related to the same *Export Task* from the given *Export Task* form view (menu *Settings > Technical > Attachments Export Tasks*) :
.. image:: https://raw.githubusercontent.com/OCA/server-tools/16.0/attachment_synchronize/static/description/export_task.png
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/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 <https://github.com/OCA/server-tools/issues/new?body=module:%20attachment_synchronize%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Akretion
Contributors
~~~~~~~~~~~~
`Akretion <https://www.akretion.com/>`_ :
- Valentin CHEMIERE
- Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
- Florian DA COSTA <florian.dacosta@akretion.com>
- Clément MOMBEREAU <clement.mombereau@akretion.com.br>
GS Lab:
- Giovanni SERRA <giovanni@gslab.it>
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-florian-dacosta| image:: https://github.com/florian-dacosta.png?size=40px
:target: https://github.com/florian-dacosta
:alt: florian-dacosta
.. |maintainer-sebastienbeau| image:: https://github.com/sebastienbeau.png?size=40px
:target: https://github.com/sebastienbeau
:alt: sebastienbeau
.. |maintainer-GSLabIt| image:: https://github.com/GSLabIt.png?size=40px
:target: https://github.com/GSLabIt
:alt: GSLabIt
.. |maintainer-bealdav| image:: https://github.com/bealdav.png?size=40px
:target: https://github.com/bealdav
:alt: bealdav
Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-florian-dacosta| |maintainer-sebastienbeau| |maintainer-GSLabIt| |maintainer-bealdav|
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/16.0/attachment_synchronize>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1 @@
from . import models

View file

@ -0,0 +1,28 @@
# @ 2016 florian DA COSTA @ Akretion
# © 2016 @author Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
# @ 2020 Giovanni Serra @ GSlab.it
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Attachment Synchronize",
"version": "16.0.1.0.1",
"author": "Akretion,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/server-tools",
"maintainers": ["florian-dacosta", "sebastienbeau", "GSLabIt", "bealdav"],
"license": "AGPL-3",
"category": "Generic Modules",
"depends": [
"attachment_queue",
"fs_storage", # https://github.com/OCA/storage
],
"data": [
"views/attachment_queue_views.xml",
"views/attachment_synchronize_task_views.xml",
"views/storage_backend_views.xml",
"data/cron.xml",
"security/ir.model.access.csv",
],
"demo": ["demo/attachment_synchronize_task_demo.xml"],
"installable": True,
"development_status": "Beta",
}

View file

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<record model="ir.cron" id="cronjob_run_attachment_synchronize_task_import">
<field name='name'>Run attachment tasks import</field>
<field name='interval_number'>30</field>
<field name='interval_type'>minutes</field>
<field name="numbercall">-1</field>
<field name="active">False</field>
<field name="doall" eval="False" />
<field name="model_id" ref="model_attachment_synchronize_task" />
<field name="state">code</field>
<field name="code">model.run_task_import_scheduler()</field>
</record>
</odoo>

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="import_from_filestore" model="attachment.synchronize.task">
<field name="name">TEST Import</field>
<field name="backend_id" ref="fs_storage.default_fs_storage" />
<field name="method_type">import</field>
<field name="filepath">test_import</field>
<field name="avoid_duplicated_files" eval="True" />
</record>
<record id="import_from_filestore_delete" model="attachment.synchronize.task">
<field name="name">TEST Import then delete</field>
<field name="backend_id" ref="fs_storage.default_fs_storage" />
<field name="method_type">import</field>
<field name="after_import">delete</field>
<field name="filepath">test_import</field>
</record>
<record id="import_from_filestore_rename" model="attachment.synchronize.task">
<field name="name">TEST Import then rename</field>
<field name="backend_id" ref="fs_storage.default_fs_storage" />
<field name="method_type">import</field>
<field name="after_import">rename</field>
<field name="filepath">test_import</field>
<field name="new_name">test-${obj.name}</field>
</record>
<record id="import_from_filestore_move" model="attachment.synchronize.task">
<field name="name">TEST Import then move</field>
<field name="backend_id" ref="fs_storage.default_fs_storage" />
<field name="method_type">import</field>
<field name="after_import">move</field>
<field name="filepath">test_import</field>
<field name="move_path">test_archived</field>
</record>
<record id="import_from_filestore_move_rename" model="attachment.synchronize.task">
<field name="name">TEST Import then move and rename</field>
<field name="backend_id" ref="fs_storage.default_fs_storage" />
<field name="method_type">import</field>
<field name="after_import">move_rename</field>
<field name="filepath">test_import</field>
<field name="move_path">test_archived</field>
<field name="new_name">foo.txt</field>
</record>
<record id="export_to_filestore" model="attachment.synchronize.task">
<field name="name">TEST Export</field>
<field name="backend_id" ref="fs_storage.default_fs_storage" />
<field name="method_type">export</field>
<field name="filepath">test_export</field>
</record>
<record id="attachment_queue_imported_demo" model="attachment.queue">
<field name="datas">bWlncmF0aW9uIHRlc3Q=</field>
<field name="name">attachment_queue_imported_demo.doc</field>
<field name="task_id" ref="import_from_filestore" />
</record>
</odoo>

View file

@ -0,0 +1,440 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * attachment_synchronize
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Fail</span>"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Pending</span>"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Success</span>"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__after_import
msgid "Action after import a file"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__after_import
msgid "After Import"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Archived"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__assigned_attachment_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__assigned_attachment_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__assigned_attachment_ids
msgid "Assigned Attachments"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__attachment_ids
msgid "Attachment"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_attachment_queue
msgid "Attachment Queue"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Attachment Task"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_attachment_synchronize_task
msgid "Attachment synchronize task"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Attachments"
msgstr ""
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_export_task
#: model:ir.ui.menu,name:attachment_synchronize.menu_attachment_export_task
msgid "Attachments Export Tasks"
msgstr ""
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_import_task
#: model:ir.ui.menu,name:attachment_synchronize.menu_attachment_import_task
msgid "Attachments Import Tasks"
msgstr ""
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_queue_related
msgid "Attachments Queue"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__avoid_duplicated_files
msgid "Avoid importing duplicated files"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__backend_id
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Backend"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__changeset_change_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__changeset_change_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__changeset_change_ids
msgid "Changeset Changes"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__changeset_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__changeset_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__changeset_ids
msgid "Changesets"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_done
msgid "Count Attachment Done"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_failed
msgid "Count Attachment Failed"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_pending
msgid "Count Attachment Pending"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_changesets
msgid "Count Changesets"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_pending_changeset_changes
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_pending_changeset_changes
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_pending_changeset_changes
msgid "Count Pending Changeset Changes"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_pending_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_pending_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_pending_changesets
msgid "Count Pending Changesets"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__create_uid
msgid "Created by"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__create_date
msgid "Created on"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__delete
msgid "Delete"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__display_name
msgid "Display Name"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Done attachments"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Duplicate"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__active
msgid "Enabled"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_queue__file_type__export
msgid "Export File (External location)"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__method_type__export
msgid "Export Task"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__export_task_count
msgid "Export Tasks"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_fs_storage
msgid "FS Storage"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Failed attachments"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__failure_emails
msgid "Failure Emails"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__filepath
msgid "File Path"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__file_type
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__file_type
msgid "File Type"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__fs_storage_id
msgid "Filestore Storage"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__id
msgid "ID"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__avoid_duplicated_files
msgid ""
"If checked, a file will not be imported if an Attachment Queue with the same"
" name already exists."
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__method_type__import
msgid "Import Task"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__import_task_count
msgid "Import Tasks"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Importation"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__move_path
msgid "Imported File will be moved to this path"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__new_name
msgid ""
"Imported File will be renamed to this name.\n"
"New Name can use 'mako' template where 'obj' is the original file's name.\n"
"For instance : ${obj.name}-${obj.create_date}.csv"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task____last_update
msgid "Last Modified on"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__write_uid
msgid "Last Updated by"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__write_date
msgid "Last Updated on"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__method_type
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__method_type
msgid "Method Type"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__move
msgid "Move"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__move_rename
msgid "Move & Rename"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__move_path
msgid "Move Path"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__name
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Name"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__new_name
msgid "New Name"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Notification"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__filepath
msgid "Path to imported/exported files in the Backend"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__pattern
msgid ""
"Pattern used to select the files to be imported following the 'fnmatch' special characters (e.g. '*.txt' to catch all the text files).\n"
"If empty, import all the files found in 'File Path'."
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Pending attachments"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__rename
msgid "Rename"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Run"
msgstr ""
#. module: attachment_synchronize
#: model:ir.actions.server,name:attachment_synchronize.cronjob_run_attachment_synchronize_task_import_ir_actions_server
#: model:ir.cron,cron_name:attachment_synchronize.cronjob_run_attachment_synchronize_task_import
msgid "Run attachment tasks import"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__pattern
msgid "Selection Pattern"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__smart_search
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__smart_search
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__smart_search
msgid "Smart Search"
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Storage Location"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__task_id
msgid "Task"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__synchronize_task_ids
msgid "Tasks"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__file_type
msgid ""
"The file type determines an import method to be used to parse and transform "
"data before their import in ERP or an export"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_pending_changeset_changes
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_pending_changeset_changes
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_pending_changeset_changes
msgid "The number of pending changes of this record"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_pending_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_pending_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_pending_changesets
msgid "The number of pending changesets of this record"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_changesets
msgid "The overall number of changesets of this record"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__failure_emails
msgid ""
"Used to fill the 'Failure Emails' field in the 'Attachments Queues' related to this task.\n"
"An alert will be sent to these emails if any operation on these Attachment Queue's file type fails."
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__file_type
msgid ""
"Used to fill the 'File Type' field in the imported 'Attachments Queues'.\n"
"Further operations will be realized on these Attachments Queues depending on their 'File Type' value."
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__user_can_see_changeset
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__user_can_see_changeset
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__user_can_see_changeset
msgid "User Can See Changeset"
msgstr ""

View file

@ -0,0 +1,440 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * attachment_synchronize
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Fail</span>"
msgstr "<span class=\"o_stat_text\">Neuspjeh</span>"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Pending</span>"
msgstr "<span class=\"o_stat_text\">Na čekanju</span>"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Success</span>"
msgstr "<span class=\"o_stat_text\">Uspjeh</span>"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__after_import
msgid "Action after import a file"
msgstr "Akcija nakon uvoza datoteke"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__after_import
msgid "After Import"
msgstr "Nakon uvoza"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Archived"
msgstr "Arhivirano"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__assigned_attachment_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__assigned_attachment_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__assigned_attachment_ids
msgid "Assigned Attachments"
msgstr "Dodijeljeni prilozi"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__attachment_ids
msgid "Attachment"
msgstr "Prilog"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_attachment_queue
msgid "Attachment Queue"
msgstr "Red čekanja priloga"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Attachment Task"
msgstr "Zadatak priloga"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_attachment_synchronize_task
msgid "Attachment synchronize task"
msgstr "Zadatak sinhronizacije priloga"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Attachments"
msgstr "Prilozi"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_export_task
#: model:ir.ui.menu,name:attachment_synchronize.menu_attachment_export_task
msgid "Attachments Export Tasks"
msgstr "Zadaci izvoza priloga"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_import_task
#: model:ir.ui.menu,name:attachment_synchronize.menu_attachment_import_task
msgid "Attachments Import Tasks"
msgstr "Zadaci uvoza priloga"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_queue_related
msgid "Attachments Queue"
msgstr "Red čekanja priloga"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__avoid_duplicated_files
msgid "Avoid importing duplicated files"
msgstr "Izbjegni uvoziranje dupliciranih datoteka"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__backend_id
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Backend"
msgstr "U pozadinu"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__changeset_change_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__changeset_change_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__changeset_change_ids
msgid "Changeset Changes"
msgstr "Promjene skupa promjena"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__changeset_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__changeset_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__changeset_ids
msgid "Changesets"
msgstr "Skupovi promjena"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_done
msgid "Count Attachment Done"
msgstr "Broj završenih priloga"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_failed
msgid "Count Attachment Failed"
msgstr "Broj neuspješnih priloga"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_pending
msgid "Count Attachment Pending"
msgstr "Broj čekajućih priloga"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_changesets
msgid "Count Changesets"
msgstr "Broj skupova promjena"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_pending_changeset_changes
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_pending_changeset_changes
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_pending_changeset_changes
msgid "Count Pending Changeset Changes"
msgstr "Broj čekajućih promjena skupa promjena"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_pending_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_pending_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_pending_changesets
msgid "Count Pending Changesets"
msgstr "Broj čekajućih skupova promjena"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__create_uid
msgid "Created by"
msgstr "Kreirao"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__create_date
msgid "Created on"
msgstr "Kreirano"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__delete
msgid "Delete"
msgstr "Obriši"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__display_name
msgid "Display Name"
msgstr "Prikazani naziv"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Done attachments"
msgstr "Završeni prilozi"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Duplicate"
msgstr "Dupliciraj"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__active
msgid "Enabled"
msgstr "Omogućeno"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_queue__file_type__export
msgid "Export File (External location)"
msgstr "Izvozi datoteku (Vanjska lokacija)"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__method_type__export
msgid "Export Task"
msgstr "Zadatak izvoza"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__export_task_count
msgid "Export Tasks"
msgstr "Zadaci izvoza"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_fs_storage
msgid "FS Storage"
msgstr "FS skladištenje"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Failed attachments"
msgstr "Neuspješni prilozi"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__failure_emails
msgid "Failure Emails"
msgstr "E-mail adrese za neuspjeh"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__filepath
msgid "File Path"
msgstr "Putanja datoteke"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__file_type
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__file_type
msgid "File Type"
msgstr "Tip datoteke"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__fs_storage_id
msgid "Filestore Storage"
msgstr "Filestore skladištenje"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__id
msgid "ID"
msgstr "ID"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__avoid_duplicated_files
msgid ""
"If checked, a file will not be imported if an Attachment Queue with the same"
" name already exists."
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__method_type__import
msgid "Import Task"
msgstr "Zadatak uvoza"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__import_task_count
msgid "Import Tasks"
msgstr "Zadaci uvoza"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Importation"
msgstr "Uvoziranje"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__move_path
msgid "Imported File will be moved to this path"
msgstr "Uvozena datoteka će biti premještena na ovu putanju"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__new_name
msgid ""
"Imported File will be renamed to this name.\n"
"New Name can use 'mako' template where 'obj' is the original file's name.\n"
"For instance : ${obj.name}-${obj.create_date}.csv"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task____last_update
msgid "Last Modified on"
msgstr "Zadnje mijenjano"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__write_uid
msgid "Last Updated by"
msgstr "Zadnji ažurirao"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__write_date
msgid "Last Updated on"
msgstr "Zadnje ažurirano"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__method_type
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__method_type
msgid "Method Type"
msgstr "Tip metode"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__move
msgid "Move"
msgstr "Kretanje"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__move_rename
msgid "Move & Rename"
msgstr "Premjesti i preimenuj"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__move_path
msgid "Move Path"
msgstr "Putanja premještanja"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__name
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Name"
msgstr "Naziv:"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__new_name
msgid "New Name"
msgstr "Novi naziv"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Notification"
msgstr "Obavještenje"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__filepath
msgid "Path to imported/exported files in the Backend"
msgstr "Putanja do uvozenih/izvozenih datoteka u Backend-u"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__pattern
msgid ""
"Pattern used to select the files to be imported following the 'fnmatch' special characters (e.g. '*.txt' to catch all the text files).\n"
"If empty, import all the files found in 'File Path'."
msgstr ""
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Pending attachments"
msgstr "Čekajući prilozi"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__rename
msgid "Rename"
msgstr "Preimenuj"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Run"
msgstr "Pokrenut"
#. module: attachment_synchronize
#: model:ir.actions.server,name:attachment_synchronize.cronjob_run_attachment_synchronize_task_import_ir_actions_server
#: model:ir.cron,cron_name:attachment_synchronize.cronjob_run_attachment_synchronize_task_import
msgid "Run attachment tasks import"
msgstr "Pokreni uvoz zadataka priloga"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__pattern
msgid "Selection Pattern"
msgstr "Obrazac odabira"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__smart_search
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__smart_search
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__smart_search
msgid "Smart Search"
msgstr "Pametna pretraga"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Storage Location"
msgstr "Lokacija skladištenja"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__task_id
msgid "Task"
msgstr "Zadatak"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__synchronize_task_ids
msgid "Tasks"
msgstr "Zadaci"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__file_type
msgid ""
"The file type determines an import method to be used to parse and transform "
"data before their import in ERP or an export"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_pending_changeset_changes
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_pending_changeset_changes
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_pending_changeset_changes
msgid "The number of pending changes of this record"
msgstr "Broj čekajućih promjena ovog zapisa"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_pending_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_pending_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_pending_changesets
msgid "The number of pending changesets of this record"
msgstr "Broj čekajućih skupova promjena ovog zapisa"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_changesets
msgid "The overall number of changesets of this record"
msgstr "Ukupan broj skupova promjena ovog zapisa"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__failure_emails
msgid ""
"Used to fill the 'Failure Emails' field in the 'Attachments Queues' related to this task.\n"
"An alert will be sent to these emails if any operation on these Attachment Queue's file type fails."
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__file_type
msgid ""
"Used to fill the 'File Type' field in the imported 'Attachments Queues'.\n"
"Further operations will be realized on these Attachments Queues depending on their 'File Type' value."
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__user_can_see_changeset
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__user_can_see_changeset
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__user_can_see_changeset
msgid "User Can See Changeset"
msgstr "Korisnik može vidjeti skup promjena"

View file

@ -0,0 +1,467 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * attachment_synchronize
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-02-13 00:08+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: none\n"
"Language: es\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 4.17\n"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Fail</span>"
msgstr "<span class=\"o_stat_text\">Suspendido</span>"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Pending</span>"
msgstr "<span class=\"o_stat_text\">Pendiente</span>"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Success</span>"
msgstr "<span class=\"o_stat_text\">Éxito</span>"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__after_import
msgid "Action after import a file"
msgstr "Acción tras importar un archivo"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__after_import
msgid "After Import"
msgstr "Después de Importar"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Archived"
msgstr "Archivado"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__assigned_attachment_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__assigned_attachment_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__assigned_attachment_ids
msgid "Assigned Attachments"
msgstr "Archivos Adjuntos Asignados"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__attachment_ids
msgid "Attachment"
msgstr "Archivo Adjunto"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_attachment_queue
msgid "Attachment Queue"
msgstr "Cola de Archivos Adjuntos"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Attachment Task"
msgstr "Tarea Adjunta"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_attachment_synchronize_task
msgid "Attachment synchronize task"
msgstr "Adjuntar tarea de sincronización"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Attachments"
msgstr "Archivos Adjuntos"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_export_task
#: model:ir.ui.menu,name:attachment_synchronize.menu_attachment_export_task
msgid "Attachments Export Tasks"
msgstr "Tareas de Exportación de Anexos"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_import_task
#: model:ir.ui.menu,name:attachment_synchronize.menu_attachment_import_task
msgid "Attachments Import Tasks"
msgstr "Tareas de Importación de Anexos"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_queue_related
msgid "Attachments Queue"
msgstr "Cola de Archivos Adjuntos"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__avoid_duplicated_files
msgid "Avoid importing duplicated files"
msgstr "Evitar la importación de archivos duplicados"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__backend_id
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Backend"
msgstr "Servidor"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__changeset_change_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__changeset_change_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__changeset_change_ids
msgid "Changeset Changes"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__changeset_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__changeset_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__changeset_ids
msgid "Changesets"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_done
msgid "Count Attachment Done"
msgstr "Recuento Adjunto Realizado"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_failed
msgid "Count Attachment Failed"
msgstr "Recuento Adjunto Fallido"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_pending
msgid "Count Attachment Pending"
msgstr "Recuento Adjunto Pendiente"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_changesets
msgid "Count Changesets"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_pending_changeset_changes
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_pending_changeset_changes
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_pending_changeset_changes
msgid "Count Pending Changeset Changes"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_pending_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_pending_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_pending_changesets
msgid "Count Pending Changesets"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__create_date
msgid "Created on"
msgstr "Creado el"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__delete
msgid "Delete"
msgstr "Borrar"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__display_name
msgid "Display Name"
msgstr "Mostrar Nombre"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Done attachments"
msgstr "Archivos adjuntos realizados"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Duplicate"
msgstr "Duplicado"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__active
msgid "Enabled"
msgstr "Habilitado"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_queue__file_type__export
msgid "Export File (External location)"
msgstr "Exportar Archivo (Ubicación externa)"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__method_type__export
msgid "Export Task"
msgstr "Exportar Tarea"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__export_task_count
msgid "Export Tasks"
msgstr "Exportar Tareas"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_fs_storage
msgid "FS Storage"
msgstr "Almacenamiento FS"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Failed attachments"
msgstr "Archivos adjuntos fallidos"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__failure_emails
msgid "Failure Emails"
msgstr "Correos electrónicos fallidos"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__filepath
msgid "File Path"
msgstr "Ruta del Archivo"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__file_type
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__file_type
msgid "File Type"
msgstr "Tipo de Archivo"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__fs_storage_id
msgid "Filestore Storage"
msgstr "Almacenamiento de Archivos"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__id
msgid "ID"
msgstr "ID"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__avoid_duplicated_files
msgid ""
"If checked, a file will not be imported if an Attachment Queue with the same "
"name already exists."
msgstr ""
"Si está marcada, no se importará un archivo si ya existe una Cola de "
"Adjuntos con el mismo nombre."
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__method_type__import
msgid "Import Task"
msgstr "Importar Tarea"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__import_task_count
msgid "Import Tasks"
msgstr "Importar Tareas"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Importation"
msgstr "Importación"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__move_path
msgid "Imported File will be moved to this path"
msgstr "El Archivo Importado se moverá a esta ruta"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__new_name
msgid ""
"Imported File will be renamed to this name.\n"
"New Name can use 'mako' template where 'obj' is the original file's name.\n"
"For instance : ${obj.name}-${obj.create_date}.csv"
msgstr ""
"El Archivo Importado será renombrado a este nombre.\n"
"El Nuevo Nombre puede utilizar la plantilla 'mako' donde 'obj' es el nombre "
"del archivo original.\n"
"Por instancia: ${obj.name}-${obj.create_date}.csv"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task____last_update
msgid "Last Modified on"
msgstr "Última Modificación el"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__write_date
msgid "Last Updated on"
msgstr "Última Actualización el"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__method_type
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__method_type
msgid "Method Type"
msgstr "Tipo de Método"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__move
msgid "Move"
msgstr "Movimiento"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__move_rename
msgid "Move & Rename"
msgstr "Mover y Renombrar"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__move_path
msgid "Move Path"
msgstr "Mover Ruta"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__name
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Name"
msgstr "Nombre"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__new_name
msgid "New Name"
msgstr "Nombre Nuevo"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Notification"
msgstr "Notificación"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__filepath
msgid "Path to imported/exported files in the Backend"
msgstr "Ruta a los archivos importados/exportados en el Servidor"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__pattern
msgid ""
"Pattern used to select the files to be imported following the 'fnmatch' "
"special characters (e.g. '*.txt' to catch all the text files).\n"
"If empty, import all the files found in 'File Path'."
msgstr ""
"Patrón utilizado para seleccionar los archivos que se importarán siguiendo "
"los caracteres especiales 'fnmatch' (por ejemplo, '*.txt' para capturar "
"todos los archivos de texto).\n"
"Si está vacío, importa todos los archivos encontrados en 'File Path'."
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Pending attachments"
msgstr "Archivos adjuntos pendientes"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__rename
msgid "Rename"
msgstr "Renombrar"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Run"
msgstr "Ejecutar"
#. module: attachment_synchronize
#: model:ir.actions.server,name:attachment_synchronize.cronjob_run_attachment_synchronize_task_import_ir_actions_server
#: model:ir.cron,cron_name:attachment_synchronize.cronjob_run_attachment_synchronize_task_import
msgid "Run attachment tasks import"
msgstr "Ejecutar la importación de tareas adjuntas"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__pattern
msgid "Selection Pattern"
msgstr "Patrón de Selección"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__smart_search
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__smart_search
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__smart_search
msgid "Smart Search"
msgstr "Búsqueda Inteligente"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Storage Location"
msgstr "Lugar de Almacenamiento"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__task_id
msgid "Task"
msgstr "Tarea"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__synchronize_task_ids
msgid "Tasks"
msgstr "Tareas"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__file_type
msgid ""
"The file type determines an import method to be used to parse and transform "
"data before their import in ERP or an export"
msgstr ""
"El tipo de archivo determina el método de importación que se utilizará para "
"analizar y transformar los datos antes de importarlos al ERP o exportarlos"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_pending_changeset_changes
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_pending_changeset_changes
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_pending_changeset_changes
msgid "The number of pending changes of this record"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_pending_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_pending_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_pending_changesets
msgid "The number of pending changesets of this record"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_changesets
msgid "The overall number of changesets of this record"
msgstr ""
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__failure_emails
msgid ""
"Used to fill the 'Failure Emails' field in the 'Attachments Queues' related "
"to this task.\n"
"An alert will be sent to these emails if any operation on these Attachment "
"Queue's file type fails."
msgstr ""
"Se utiliza para rellenar el campo \" Correos electrónicos fallidos\" en las "
"\"Colas de archivos adjuntos\" relacionadas con esta tarea.\n"
"Se enviará una alerta a estos correos electrónicos si falla alguna operación "
"en el tipo de archivo de esta cola de archivos adjuntos."
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__file_type
msgid ""
"Used to fill the 'File Type' field in the imported 'Attachments Queues'.\n"
"Further operations will be realized on these Attachments Queues depending on "
"their 'File Type' value."
msgstr ""
"Se utiliza para rellenar el campo \"Tipo de archivo\" en las \"Colas de "
"archivos adjuntos\" importadas.\n"
"Se realizarán otras operaciones en estas colas de archivos adjuntos en "
"función de su valor de \"Tipo de archivo\"."
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__user_can_see_changeset
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__user_can_see_changeset
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__user_can_see_changeset
msgid "User Can See Changeset"
msgstr ""

View file

@ -0,0 +1,467 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * attachment_synchronize
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-01-16 16:06+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\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: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Fail</span>"
msgstr "<span class=\"o_stat_text\">Fallito</span>"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Pending</span>"
msgstr "<span class=\"o_stat_text\">In attesa</span>"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "<span class=\"o_stat_text\">Success</span>"
msgstr "<span class=\"o_stat_text\">Riuscito</span>"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__after_import
msgid "Action after import a file"
msgstr "Azione dopo l'importazione del file"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__after_import
msgid "After Import"
msgstr "Dopo l'importazione"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Archived"
msgstr "In archivio"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__assigned_attachment_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__assigned_attachment_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__assigned_attachment_ids
msgid "Assigned Attachments"
msgstr "Allegati assegnati"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__attachment_ids
msgid "Attachment"
msgstr "Allegato"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_attachment_queue
msgid "Attachment Queue"
msgstr "Coda allegato"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Attachment Task"
msgstr "Lavoro allegato"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_attachment_synchronize_task
msgid "Attachment synchronize task"
msgstr "Sincronizza lavoro allegato"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Attachments"
msgstr "Allegati"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_export_task
#: model:ir.ui.menu,name:attachment_synchronize.menu_attachment_export_task
msgid "Attachments Export Tasks"
msgstr "Lavori esportazione allegati"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_import_task
#: model:ir.ui.menu,name:attachment_synchronize.menu_attachment_import_task
msgid "Attachments Import Tasks"
msgstr "Lavori importazione allegati"
#. module: attachment_synchronize
#: model:ir.actions.act_window,name:attachment_synchronize.action_attachment_queue_related
msgid "Attachments Queue"
msgstr "Coda allegati"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__avoid_duplicated_files
msgid "Avoid importing duplicated files"
msgstr "Evita importazione file duplicati"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__backend_id
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_search
msgid "Backend"
msgstr "Backend"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__changeset_change_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__changeset_change_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__changeset_change_ids
msgid "Changeset Changes"
msgstr "Modifiche dell'insieme di modifiche"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__changeset_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__changeset_ids
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__changeset_ids
msgid "Changesets"
msgstr "Insiemi di modifiche"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_done
msgid "Count Attachment Done"
msgstr "Conteggio allegati completati"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_failed
msgid "Count Attachment Failed"
msgstr "Conteggio allegati falliti"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_attachment_pending
msgid "Count Attachment Pending"
msgstr "Conteggio allegati in attesa"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_changesets
msgid "Count Changesets"
msgstr "Conta insiemi di modifiche"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_pending_changeset_changes
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_pending_changeset_changes
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_pending_changeset_changes
msgid "Count Pending Changeset Changes"
msgstr "Conteggio modifiche dell'insieme di modifiche in attesa"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__count_pending_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__count_pending_changesets
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__count_pending_changesets
msgid "Count Pending Changesets"
msgstr "Conteggio insieme di modifiche in attesa"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__create_uid
msgid "Created by"
msgstr "Creato da"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__create_date
msgid "Created on"
msgstr "Creato il"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__delete
msgid "Delete"
msgstr "Cancella"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__display_name
msgid "Display Name"
msgstr "Nome visualizzato"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Done attachments"
msgstr "Allegati completati"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Duplicate"
msgstr "Duplica"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__active
msgid "Enabled"
msgstr "Abilitata"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_queue__file_type__export
msgid "Export File (External location)"
msgstr "Esporta file (ubicazione esterna)"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__method_type__export
msgid "Export Task"
msgstr "Lavoro esportazione"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__export_task_count
msgid "Export Tasks"
msgstr "Lavori esportazione"
#. module: attachment_synchronize
#: model:ir.model,name:attachment_synchronize.model_fs_storage
msgid "FS Storage"
msgstr "Deposito FS"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Failed attachments"
msgstr "Allegati falliti"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__failure_emails
msgid "Failure Emails"
msgstr "E-mail fallite"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__filepath
msgid "File Path"
msgstr "Percorso file"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__file_type
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__file_type
msgid "File Type"
msgstr "Tipo file"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__fs_storage_id
msgid "Filestore Storage"
msgstr "Deposito filesystem"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__id
msgid "ID"
msgstr "ID"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__avoid_duplicated_files
msgid ""
"If checked, a file will not be imported if an Attachment Queue with the same "
"name already exists."
msgstr ""
"Se selezionata, un file non verrà importato se esiste già una coda allegato "
"con lo stesso nome."
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__method_type__import
msgid "Import Task"
msgstr "Lavoro importazione"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__import_task_count
msgid "Import Tasks"
msgstr "Lavori importazione"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Importation"
msgstr "Importazione"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__move_path
msgid "Imported File will be moved to this path"
msgstr "I file importati verranno spostati in questo percorso"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__new_name
msgid ""
"Imported File will be renamed to this name.\n"
"New Name can use 'mako' template where 'obj' is the original file's name.\n"
"For instance : ${obj.name}-${obj.create_date}.csv"
msgstr ""
"I file importati verranno rinominati con questo nome.\n"
"Il nuovo nome può usare il modello 'mako' dove 'obj' è il nome originale del "
"file.\n"
"Per esempio: ${obj.name}-${obj.create_date}.csv"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task____last_update
msgid "Last Modified on"
msgstr "Ultima modifica il"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__write_uid
msgid "Last Updated by"
msgstr "Ultimo aggiornamento di"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__write_date
msgid "Last Updated on"
msgstr "Ultimo aggiornamento il"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__method_type
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__method_type
msgid "Method Type"
msgstr "Tipo metodo"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__move
msgid "Move"
msgstr "Sposta"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__move_rename
msgid "Move & Rename"
msgstr "Sposta e rinomina"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__move_path
msgid "Move Path"
msgstr "Percorso spostamento"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__name
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Name"
msgstr "Nome"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__new_name
msgid "New Name"
msgstr "Nuovo nome"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Notification"
msgstr "Notifica"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__filepath
msgid "Path to imported/exported files in the Backend"
msgstr "Percorso ai file importati/esportati nel backend"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__pattern
msgid ""
"Pattern used to select the files to be imported following the 'fnmatch' "
"special characters (e.g. '*.txt' to catch all the text files).\n"
"If empty, import all the files found in 'File Path'."
msgstr ""
"Schema utilizzato per selezionare i file da importate seguendo i caratteri "
"speciali 'fnmatch' (es. '*.txt' per selezionare tutti i file testo).\n"
"Se vuoto, importa tutti i file che si trovano nel 'Percorso file'."
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Pending attachments"
msgstr "Allegati in attesa"
#. module: attachment_synchronize
#: model:ir.model.fields.selection,name:attachment_synchronize.selection__attachment_synchronize_task__after_import__rename
msgid "Rename"
msgstr "Rinomina"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_tree
msgid "Run"
msgstr "Esegui"
#. module: attachment_synchronize
#: model:ir.actions.server,name:attachment_synchronize.cronjob_run_attachment_synchronize_task_import_ir_actions_server
#: model:ir.cron,cron_name:attachment_synchronize.cronjob_run_attachment_synchronize_task_import
msgid "Run attachment tasks import"
msgstr "Esegui lavori importazione allegato"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__pattern
msgid "Selection Pattern"
msgstr "Schema selezione"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__smart_search
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__smart_search
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__smart_search
msgid "Smart Search"
msgstr "Ricerca intelligente"
#. module: attachment_synchronize
#: model_terms:ir.ui.view,arch_db:attachment_synchronize.view_attachment_task_form
msgid "Storage Location"
msgstr "Ubicazione archiviazione"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__task_id
msgid "Task"
msgstr "Lavoro"
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__synchronize_task_ids
msgid "Tasks"
msgstr "Lavori"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__file_type
msgid ""
"The file type determines an import method to be used to parse and transform "
"data before their import in ERP or an export"
msgstr ""
"Il tipo di file determina il metodo di importazione da utilizzare per "
"elaborare e trasformare i dati prima dell'importazione nell'ERP o per "
"l'esportazione"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_pending_changeset_changes
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_pending_changeset_changes
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_pending_changeset_changes
msgid "The number of pending changes of this record"
msgstr "Numero di modifiche di questo record in attesa"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_pending_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_pending_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_pending_changesets
msgid "The number of pending changesets of this record"
msgstr "Numero di insiemi di modifiche in attesa di questo record"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_queue__count_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__count_changesets
#: model:ir.model.fields,help:attachment_synchronize.field_fs_storage__count_changesets
msgid "The overall number of changesets of this record"
msgstr "Numero totale di insiemi di modifiche di questo record"
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__failure_emails
msgid ""
"Used to fill the 'Failure Emails' field in the 'Attachments Queues' related "
"to this task.\n"
"An alert will be sent to these emails if any operation on these Attachment "
"Queue's file type fails."
msgstr ""
"Utilizzato per riempire il campo 'E-mail fallite' nel 'Coda allegati' "
"relativo a questo lavoro.\n"
"Un avviso verrà inviato a questa e.mail se una operazione su questo file "
"della coda allegato fallisce."
#. module: attachment_synchronize
#: model:ir.model.fields,help:attachment_synchronize.field_attachment_synchronize_task__file_type
msgid ""
"Used to fill the 'File Type' field in the imported 'Attachments Queues'.\n"
"Further operations will be realized on these Attachments Queues depending on "
"their 'File Type' value."
msgstr ""
"Utilizzato per compilare il campo 'Tipo file' nella 'Coda allegati' "
"importati.\n"
"Altre operazioni verranno eseguite in questa coda allegati in funzione del "
"loro valore 'Tipo file'."
#. module: attachment_synchronize
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_queue__user_can_see_changeset
#: model:ir.model.fields,field_description:attachment_synchronize.field_attachment_synchronize_task__user_can_see_changeset
#: model:ir.model.fields,field_description:attachment_synchronize.field_fs_storage__user_can_see_changeset
msgid "User Can See Changeset"
msgstr "L'utente può vedere l'insieme delle modifiche"

View file

@ -0,0 +1 @@
from . import attachment_queue, attachment_synchronize_task, storage_backend

View file

@ -0,0 +1,65 @@
# @ 2016 Florian DA COSTA @ Akretion
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import base64
from odoo import api, fields, models
from odoo.addons.queue_job.exception import RetryableJobError
class AttachmentQueue(models.Model):
_inherit = "attachment.queue"
task_id = fields.Many2one("attachment.synchronize.task", string="Task")
method_type = fields.Selection(related="task_id.method_type")
fs_storage_id = fields.Many2one(
"fs.storage",
string="Filestore Storage",
related="task_id.backend_id",
store=True,
)
file_type = fields.Selection(
selection_add=[("export", "Export File (External location)")]
)
def _write_file_to_remote(self, fs, full_path):
self.ensure_one()
data = base64.b64decode(self.datas)
with fs.open(full_path, "wb") as f:
f.write(data)
def _run(self):
res = super()._run()
if self.file_type == "export":
try:
fs = self.fs_storage_id.fs
folder_path = self.task_id.filepath
full_path = (
folder_path and fs.sep.join([folder_path, self.name]) or self.name
)
# create missing folders if necessary :
if folder_path and not fs.exists(folder_path):
fs.makedirs(folder_path)
self._write_file_to_remote(fs, full_path)
except TimeoutError as err:
raise RetryableJobError(
str(err),
seconds=self._timeout_retry_seconds(),
) from err
return res
def _timeout_retry_seconds(self):
return 60 * 60 * 4
def _get_failure_emails(self):
res = super()._get_failure_emails()
if self.task_id.failure_emails:
res = self.task_id.failure_emails
return res
@api.onchange("task_id")
def onchange_task_id(self):
for attachment in self:
if attachment.task_id.method_type == "export":
attachment.file_type = "export"

View file

@ -0,0 +1,258 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import base64
import datetime
import logging
from odoo import api, fields, models, tools
from odoo.osv import expression
_logger = logging.getLogger(__name__)
try:
# We use a jinja2 sandboxed environment to render mako templates.
# Note that the rendering does not cover all the mako syntax, in particular
# arbitrary Python statements are not accepted, and not all expressions are
# allowed: only "public" attributes (not starting with '_') of objects may
# be accessed.
# This is done on purpose: it prevents incidental or malicious execution of
# Python code that may break the security of the server.
from jinja2.sandbox import SandboxedEnvironment
mako_template_env = SandboxedEnvironment(
variable_start_string="${",
variable_end_string="}",
line_statement_prefix="%",
trim_blocks=True, # do not output newline after blocks
)
mako_template_env.globals.update(
{
"str": str,
"datetime": datetime,
"len": len,
"abs": abs,
"min": min,
"max": max,
"sum": sum,
"filter": filter,
"map": map,
"round": round,
}
)
except ImportError:
_logger.warning("jinja2 not available, templating features will not work!")
class AttachmentSynchronizeTask(models.Model):
_name = "attachment.synchronize.task"
_description = "Attachment synchronize task"
name = fields.Char(required=True)
method_type = fields.Selection(
[("import", "Import Task"), ("export", "Export Task")], required=True
)
pattern = fields.Char(
string="Selection Pattern",
help="Pattern used to select the files to be imported following the 'fnmatch' "
"special characters (e.g. '*.txt' to catch all the text files).\n"
"If empty, import all the files found in 'File Path'.",
)
filepath = fields.Char(
string="File Path", help="Path to imported/exported files in the Backend"
)
backend_id = fields.Many2one("fs.storage", string="Backend")
attachment_ids = fields.One2many("attachment.queue", "task_id", string="Attachment")
move_path = fields.Char(help="Imported File will be moved to this path")
new_name = fields.Char(
help="Imported File will be renamed to this name.\n"
"New Name can use 'mako' template where 'obj' is the original file's name.\n"
"For instance : ${obj.name}-${obj.create_date}.csv",
)
after_import = fields.Selection(
selection=[
("rename", "Rename"),
("move", "Move"),
("move_rename", "Move & Rename"),
("delete", "Delete"),
],
help="Action after import a file",
)
file_type = fields.Selection(
selection=[],
help="Used to fill the 'File Type' field in the imported 'Attachments Queues'."
"\nFurther operations will be realized on these Attachments Queues depending "
"on their 'File Type' value.",
)
active = fields.Boolean("Enabled", default=True)
avoid_duplicated_files = fields.Boolean(
string="Avoid importing duplicated files",
help="If checked, a file will not be imported if an Attachment Queue with the "
"same name already exists.",
)
failure_emails = fields.Char(
help="Used to fill the 'Failure Emails' field in the 'Attachments Queues' "
"related to this task.\nAn alert will be sent to these emails if any operation "
"on these Attachment Queue's file type fails.",
)
count_attachment_failed = fields.Integer(compute="_compute_count_state")
count_attachment_pending = fields.Integer(compute="_compute_count_state")
count_attachment_done = fields.Integer(compute="_compute_count_state")
def _compute_count_state(self):
for record in self:
for state in ["failed", "pending", "done"]:
record["count_attachment_{}".format(state)] = len(
record.attachment_ids.filtered(lambda r: r.state == state)
)
def _prepare_attachment_vals(self, data, filename):
self.ensure_one()
vals = {
"name": filename,
"datas": data,
"task_id": self.id,
"file_type": self.file_type or False,
}
return vals
@api.model
def _template_render(self, template, record):
try:
template = mako_template_env.from_string(tools.ustr(template))
except Exception:
_logger.exception("Failed to load template '{}'".format(template))
variables = {"obj": record}
try:
render_result = template.render(variables)
except Exception:
_logger.exception(
"Failed to render template '{}'' using values '{}'".format(
template, variables
)
)
render_result = ""
if render_result == "False":
render_result = ""
return render_result
@api.model
def run_task_import_scheduler(self, domain=None):
if domain is None:
domain = []
domain = expression.AND([domain, [("method_type", "=", "import")]])
for task in self.search(domain):
try:
task.run_import()
except Exception as e:
self.env.cr.rollback()
# log exception and continue in order to no block all task from all
# remote servers one is unavailable
_logger.warning(
"Task import %s failed with error %s" % (task.name, str(e))
)
def run(self):
for record in self:
method = "run_{}".format(record.method_type)
if not hasattr(self, method):
raise NotImplementedError
else:
getattr(record, method)()
def _get_files(self):
self.ensure_one()
fs = self.backend_id.fs
filepath = self.filepath or ""
filepath = filepath.rstrip(fs.sep)
if filepath and not fs.exists(filepath):
return []
if self.pattern:
path = filepath and fs.sep.join([filepath, self.pattern]) or self.pattern
file_path_names = fs.glob(path)
else:
file_path_names = fs.ls(filepath, detail=False)
if self.avoid_duplicated_files:
file_path_names = self._filter_duplicates(file_path_names)
return file_path_names
def _manage_file_after_import(self, file_name, fullpath, attachment):
self.ensure_one()
fs = self.backend_id.fs
new_name = False
if self.after_import == "rename":
new_name = self._template_render(self.new_name, attachment)
path = self.filepath or ""
elif self.after_import == "move":
new_name = file_name
path = self.move_path or ""
elif self.after_import == "move_rename":
new_name = self._template_render(self.new_name, attachment)
path = self.move_path or ""
if new_name:
new_full_path = fs.sep.join([path.rstrip(fs.sep), new_name])
fs.move(fullpath, new_full_path)
if self.after_import == "delete":
fs.rm(fullpath)
def run_import(self):
self.ensure_one()
attach_obj = self.env["attachment.queue"]
file_path_names = self._get_files()
total_import = 0
fs = self.backend_id.fs
for file_path in file_path_names:
if fs.isdir(file_path):
continue
# we need to commit after each file because it may be renamed, deleted
# moved on remote and if it fails later, we would could lose the file
# forever.
with self.env.registry.cursor() as new_cr:
new_env = api.Environment(new_cr, self.env.uid, self.env.context)
file_name = file_path.split(fs.sep)[-1]
data = base64.b64encode(fs.cat_file(file_path))
attach_vals = self.with_env(new_env)._prepare_attachment_vals(
data, file_name
)
attachment = attach_obj.with_env(new_env).create(attach_vals)
self.with_env(new_env)._manage_file_after_import(
file_name, file_path, attachment
)
total_import += 1
_logger.info("Run import complete! Imported {} files".format(total_import))
def _filter_duplicates(self, file_path_names):
fs = self.backend_id.fs
self.ensure_one()
if self.filepath:
filenames = [x.split(fs.sep)[-1] for x in file_path_names]
else:
filenames = file_path_names
imported = (
self.env["attachment.queue"]
.search([("name", "in", filenames)])
.mapped("name")
)
file_path_names_no_duplicate = [
x for x in file_path_names if x.split(fs.sep)[-1] not in imported
]
return file_path_names_no_duplicate
def run_export(self):
for task in self:
for att in task.attachment_ids.filtered(lambda a: a.state == "pending"):
att.run_as_job()
def button_duplicate_record(self):
# due to orm limitation method call from ui should not have params
# so we need to define this method to be able to copy
# if we do not do this the context will be injected in default params
self.copy()
def copy(self, default=None):
if default is None:
default = {}
if "active" not in default:
default["active"] = False
return super().copy(default=default)

View file

@ -0,0 +1,67 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class FsStorage(models.Model):
_inherit = "fs.storage"
synchronize_task_ids = fields.One2many(
"attachment.synchronize.task", "backend_id", string="Tasks"
)
import_task_count = fields.Integer(
"Import Tasks", compute="_compute_import_task_count"
)
export_task_count = fields.Integer(
"Export Tasks", compute="_compute_export_task_count"
)
def _compute_import_task_count(self):
for rec in self:
rec.import_task_count = len(
rec.synchronize_task_ids.filtered(lambda t: t.method_type == "import")
)
def _compute_export_task_count(self):
for rec in self:
rec.export_task_count = len(
rec.synchronize_task_ids.filtered(lambda t: t.method_type == "export")
)
def action_related_import_task(self):
self.ensure_one()
act_window_xml_id = "attachment_synchronize.action_attachment_import_task"
act_window = self.env["ir.actions.act_window"]._for_xml_id(act_window_xml_id)
domain = [
("id", "in", self.synchronize_task_ids.ids),
("method_type", "=", "import"),
]
act_window["domain"] = domain
if self.import_task_count == 1:
form = self.env.ref("attachment_synchronize.view_attachment_task_form")
act_window["views"] = [(form.id, "form")]
act_window["res_id"] = (
self.env["attachment.synchronize.task"].search(domain).id
)
return act_window
def action_related_export_task(self):
self.ensure_one()
act_window_xml_id = "attachment_synchronize.action_attachment_export_task"
act_window = self.env["ir.actions.act_window"]._for_xml_id(act_window_xml_id)
domain = [
("id", "in", self.synchronize_task_ids.ids),
("method_type", "=", "export"),
]
act_window["domain"] = domain
if self.export_task_count == 1:
form = self.env.ref("attachment_synchronize.view_attachment_task_form")
act_window["views"] = [(form.id, "form")]
act_window["res_id"] = (
self.env["attachment.synchronize.task"].search(domain).id
)
return act_window

View file

@ -0,0 +1,10 @@
`Akretion <https://www.akretion.com/>`_ :
- Valentin CHEMIERE
- Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
- Florian DA COSTA <florian.dacosta@akretion.com>
- Clément MOMBEREAU <clement.mombereau@akretion.com.br>
GS Lab:
- Giovanni SERRA <giovanni@gslab.it>

View file

@ -0,0 +1,5 @@
This module allows to **import/export files** from/to backend servers.
A backend server is defined by the basic `fs_storage <https://github.com/OCA/storage/tree/16.0/fs_storage>`_ OCA module, while it can be configured (amazon S3, sftp,...) with additional modules fs python libraries
The imported files (and the files to be exported) are stored in Odoo as ``attachment.queue`` objects, defined by the `attachment_queue <https://github.com/OCA/server-tools/tree/16.0/attachment_queue>`_ module while the importation itself (resp. exportation) is realized by **"Attachments Import Tasks"** (resp. "Attachments Export Tasks") defined by this current module.

View file

@ -0,0 +1,19 @@
As importation and exportation are different processes, they are triggered in different ways :
**To import files**, you need to create an *"Attachment Import Task"* (menu *Settings > Technical > Attachments Import Tasks*) which defines :
- where to find the files to import from the backend server (path to the files, selection pattern)
- what to do with the source files in the backend server (avoid duplicates, delete/rename after import...)
- how the files will be processed once imported (through the **File Type** field).
.. image:: ../static/description/import_task.png
.. epigraph::
🔎 The **File Type** options are defined by other modules built to process the Attachments Queues with the same "File Type".
**To export files**, you need first to register them as *"Attachments Queues"* objects linked to an *"Attachment Export Task"* (which set automatically their **File Type** to *"Export File (External Location)"*).
Then, you can export one file at a time from the *Attachment Queue*'s form view, or export all the *Attachments Queues* in a pending state related to the same *Export Task* from the given *Export Task* form view (menu *Settings > Technical > Attachments Export Tasks*) :
.. image:: ../static/description/export_task.png

View file

@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_attachment_synchronize_task_manager,attachment.synchronize.task.manager,model_attachment_synchronize_task,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_attachment_synchronize_task_manager attachment.synchronize.task.manager model_attachment_synchronize_task base.group_system 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View file

@ -0,0 +1,449 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Attachment Synchronize</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* 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 }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="attachment-synchronize">
<h1 class="title">Attachment Synchronize</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0f1a47ff1d87a76dc1e0bce4178fc538be9abc93414fbcec5bfd3a6299aa2dcd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/server-tools/tree/16.0/attachment_synchronize"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/server-tools-16-0/server-tools-16-0-attachment_synchronize"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/server-tools&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows to <strong>import/export files</strong> from/to backend servers.</p>
<p>A backend server is defined by the basic <a class="reference external" href="https://github.com/OCA/storage/tree/16.0/fs_storage">fs_storage</a> OCA module, while it can be configured (amazon S3, sftp,…) with additional modules fs python libraries</p>
<p>The imported files (and the files to be exported) are stored in Odoo as <tt class="docutils literal">attachment.queue</tt> objects, defined by the <a class="reference external" href="https://github.com/OCA/server-tools/tree/16.0/attachment_queue">attachment_queue</a> module while the importation itself (resp. exportation) is realized by <strong>“Attachments Import Tasks”</strong> (resp. “Attachments Export Tasks”) defined by this current module.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
<p>As importation and exportation are different processes, they are triggered in different ways :</p>
<p><strong>To import files</strong>, you need to create an <em>“Attachment Import Task”</em> (menu <em>Settings &gt; Technical &gt; Attachments Import Tasks</em>) which defines :</p>
<ul class="simple">
<li>where to find the files to import from the backend server (path to the files, selection pattern)</li>
<li>what to do with the source files in the backend server (avoid duplicates, delete/rename after import…)</li>
<li>how the files will be processed once imported (through the <strong>File Type</strong> field).</li>
</ul>
<img alt="https://raw.githubusercontent.com/OCA/server-tools/16.0/attachment_synchronize/static/description/import_task.png" src="https://raw.githubusercontent.com/OCA/server-tools/16.0/attachment_synchronize/static/description/import_task.png" />
<blockquote class="epigraph">
🔎 The <strong>File Type</strong> options are defined by other modules built to process the Attachments Queues with the same “File Type”.</blockquote>
<p><strong>To export files</strong>, you need first to register them as <em>“Attachments Queues”</em> objects linked to an <em>“Attachment Export Task”</em> (which set automatically their <strong>File Type</strong> to <em>“Export File (External Location)”</em>).</p>
<p>Then, you can export one file at a time from the <em>Attachment Queue</em>s form view, or export all the <em>Attachments Queues</em> in a pending state related to the same <em>Export Task</em> from the given <em>Export Task</em> form view (menu <em>Settings &gt; Technical &gt; Attachments Export Tasks</em>) :</p>
<img alt="https://raw.githubusercontent.com/OCA/server-tools/16.0/attachment_synchronize/static/description/export_task.png" src="https://raw.githubusercontent.com/OCA/server-tools/16.0/attachment_synchronize/static/description/export_task.png" />
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-tools/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/server-tools/issues/new?body=module:%20attachment_synchronize%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
<ul class="simple">
<li>Akretion</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<p><a class="reference external" href="https://www.akretion.com/">Akretion</a> :</p>
<ul class="simple">
<li>Valentin CHEMIERE</li>
<li>Mourad EL HADJ MIMOUNE &lt;<a class="reference external" href="mailto:mourad.elhadj.mimoune&#64;akretion.com">mourad.elhadj.mimoune&#64;akretion.com</a>&gt;</li>
<li>Florian DA COSTA &lt;<a class="reference external" href="mailto:florian.dacosta&#64;akretion.com">florian.dacosta&#64;akretion.com</a>&gt;</li>
<li>Clément MOMBEREAU &lt;<a class="reference external" href="mailto:clement.mombereau&#64;akretion.com.br">clement.mombereau&#64;akretion.com.br</a>&gt;</li>
</ul>
<p>GS Lab:</p>
<ul class="simple">
<li>Giovanni SERRA &lt;<a class="reference external" href="mailto:giovanni&#64;gslab.it">giovanni&#64;gslab.it</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainers</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/florian-dacosta"><img alt="florian-dacosta" src="https://github.com/florian-dacosta.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/sebastienbeau"><img alt="sebastienbeau" src="https://github.com/sebastienbeau.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/GSLabIt"><img alt="GSLabIt" src="https://github.com/GSLabIt.png?size=40px" /></a> <a class="reference external image-reference" href="https://github.com/bealdav"><img alt="bealdav" src="https://github.com/bealdav.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-tools/tree/16.0/attachment_synchronize">OCA/server-tools</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,2 @@
from . import test_import
from . import test_export

View file

@ -0,0 +1,54 @@
# Copyright 2020 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import base64
from odoo.tests.common import TransactionCase
class SyncCommon(TransactionCase):
def _clean_testing_directory(self):
for test_dir in [
self.directory_input,
self.directory_output,
self.directory_archived,
]:
fs = self.backend.fs
if not fs.exists(test_dir):
fs.makedirs(test_dir)
for filename in fs.ls(test_dir, detail=False):
fs.rm(filename)
def _create_test_file(self):
fs = self.backend.fs
path = fs.sep.join([self.directory_input, "bar.txt"])
with fs.open(path, "wb") as f:
f.write(self.filedata)
def setUp(self):
super().setUp()
self.backend = self.env.ref("fs_storage.default_fs_storage")
self.filedata = base64.b64encode(b"This is a simple file")
self.directory_input = "test_import"
self.directory_output = "test_export"
self.directory_archived = "test_archived"
self._clean_testing_directory()
self._create_test_file()
self.task = self.env.ref("attachment_synchronize.import_from_filestore")
self.task_delete = self.env.ref(
"attachment_synchronize.import_from_filestore_delete"
)
self.task_move = self.env.ref(
"attachment_synchronize.import_from_filestore_move"
)
self.task_rename = self.env.ref(
"attachment_synchronize.import_from_filestore_rename"
)
self.task_move_rename = self.env.ref(
"attachment_synchronize.import_from_filestore_move_rename"
)
def tearDown(self):
self._clean_testing_directory()
super().tearDown()

View file

@ -0,0 +1,43 @@
# Copyright 2020 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from unittest import mock
from odoo.tools import mute_logger
from .common import SyncCommon
def raising_side_effect(*args, **kwargs):
raise Exception("Boom")
class TestExport(SyncCommon):
def setUp(self):
super().setUp()
self.task = self.env.ref("attachment_synchronize.export_to_filestore")
self.attachment = self.env["attachment.queue"].create(
{
"name": "foo.txt",
"task_id": self.task.id,
"file_type": "export",
"datas": self.filedata,
}
)
def test_export(self):
self.attachment.run()
result = self.backend.fs.ls("test_export", detail=False)
self.assertEqual(result, ["test_export/foo.txt"])
@mute_logger("odoo.addons.attachment_queue.models.attachment_queue")
def test_failing_export(self):
with mock.patch.object(
type(self.backend.fs),
"open",
side_effect=raising_side_effect,
):
self.attachment.with_context(queue_job__no_delay=True).run_as_job()
self.assertEqual(self.attachment.state, "failed")
self.assertEqual(self.attachment.state_message, "Boom")

View file

@ -0,0 +1,87 @@
# Copyright 2020 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api
from .common import SyncCommon
class TestImport(SyncCommon):
def tearDown(self):
self.registry.leave_test_mode()
super().tearDown()
def setUp(self):
super().setUp()
self.registry.enter_test_mode(self.env.cr)
self.env = api.Environment(
self.registry.test_cr, self.env.uid, self.env.context
)
@property
def archived_files(self):
return self.backend.fs.ls(self.directory_archived, detail=False)
@property
def input_files(self):
return self.backend.fs.ls(self.directory_input, detail=False)
def _check_attachment_created(self, count=1):
with self.env.registry.cursor() as new_cr:
attachment = self.env(cr=new_cr)["attachment.queue"].search(
[("name", "=", "bar.txt")]
)
self.assertEqual(len(attachment), count)
def test_import_with_rename(self):
self.task_rename.run_import()
self._check_attachment_created()
self.assertEqual(self.input_files, ["test_import/test-bar.txt"])
self.assertEqual(self.archived_files, [])
def test_import_with_move(self):
self.task_move.run_import()
self._check_attachment_created()
self.assertEqual(self.input_files, [])
self.assertEqual(self.archived_files, ["test_archived/bar.txt"])
def test_import_with_move_and_rename(self):
self.task_move_rename.run_import()
self._check_attachment_created()
self.assertEqual(self.input_files, [])
self.assertEqual(self.archived_files, ["test_archived/foo.txt"])
def test_import_with_delete(self):
self.task_delete.run_import()
self._check_attachment_created()
self.assertEqual(self.input_files, [])
self.assertEqual(self.archived_files, [])
def test_import_twice(self):
self.task_delete.run_import()
self._check_attachment_created(count=1)
self._create_test_file()
self.task_delete.run_import()
self._check_attachment_created(count=2)
def test_import_twice_no_duplicate(self):
self.task.run_import()
self._check_attachment_created(count=1)
self._create_test_file()
self.task.run_import()
self._check_attachment_created(count=1)
def test_running_cron(self):
self.env["attachment.synchronize.task"].search(
[("id", "!=", self.task.id)]
).write({"active": False})
self.env["attachment.synchronize.task"].run_task_import_scheduler()
self._check_attachment_created(count=1)
def test_running_cron_disable_task(self):
self.env["attachment.synchronize.task"].search([]).write({"active": False})
self.env["attachment.synchronize.task"].run_task_import_scheduler()
self._check_attachment_created(count=0)

View file

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_attachment_queue_form" model="ir.ui.view">
<field name="model">attachment.queue</field>
<field name="inherit_id" ref="attachment_queue.view_attachment_queue_form" />
<field name="arch" type="xml">
<!-- Add Related Task and Backend -->
<xpath expr="//field[@name='url']" position="after">
<field name="method_type" invisible="1" />
<field
name="task_id"
domain="[('method_type', '!=', 'import')]"
attrs="{'required': [('file_type', '=', 'export')], 'readonly': [('method_type', '=', 'import')]}"
/>
<field name="fs_storage_id" />
</xpath>
</field>
</record>
<record id="view_attachment_queue_tree" model="ir.ui.view">
<field name="model">attachment.queue</field>
<field name="inherit_id" ref="attachment_queue.view_attachment_queue_tree" />
<field name="arch" type="xml">
<xpath expr="//tree" position="attributes">
<attribute name="decoration-muted">state == 'done'</attribute>
</xpath>
<xpath expr="//field[@name='file_type']" position="after">
<field name="task_id" />
<field name="fs_storage_id" />
</xpath>
</field>
</record>
<record id="attachment_queue_view_search" model="ir.ui.view">
<field name="model">attachment.queue</field>
<field name="inherit_id" ref="attachment_queue.view_attachment_queue_search" />
<field name="arch" type="xml">
<field name="type" position="after">
<field name="task_id" filter_domain="[('task_id.name','ilike',self)]" />
</field>
</field>
</record>
<record id="action_attachment_queue_related" model="ir.actions.act_window">
<field name="name">Attachments Queue</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">attachment.queue</field>
<field name="view_mode">tree,form</field>
<field name="view_id" eval="False" />
<field name="domain">[('task_id', '=', active_id)]</field>
<field
name="search_view_id"
ref="attachment_queue.view_attachment_queue_search"
/>
</record>
</odoo>

View file

@ -0,0 +1,236 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_attachment_task_form" model="ir.ui.view">
<field name="model">attachment.synchronize.task</field>
<field name="arch" type="xml">
<form>
<header>
<button
name="run"
type="object"
string="Run"
class="oe_read_only oe_highlight"
icon="fa-play-circle"
attrs="{'invisible': [('active','=', False)]}"
/>
</header>
<sheet>
<field name="active" invisible="1" />
<widget
name="web_ribbon"
title="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
<div class="oe_button_box" name="button_box">
<button
name="%(action_attachment_queue_related)d"
type="action"
class="oe_stat_button"
icon="fa-thumbs-o-down"
title="Failed attachments"
context="{'search_default_failed': 1}"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field
name="count_attachment_failed"
widget="statinfo"
nolabel="1"
/>
</span>
<span class="o_stat_text">Fail</span>
</div>
</button>
<button
name="%(action_attachment_queue_related)d"
type="action"
class="oe_stat_button"
icon="fa-spinner"
title="Pending attachments"
context="{'search_default_pending': 1}"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field
name="count_attachment_pending"
widget="statinfo"
nolabel="1"
/>
</span>
<span class="o_stat_text">Pending</span>
</div>
</button>
<button
name="%(action_attachment_queue_related)d"
type="action"
class="oe_stat_button"
icon="fa-thumbs-o-up"
title="Done attachments"
context="{'search_default_done': 1}"
>
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field
name="count_attachment_done"
widget="statinfo"
nolabel="1"
/>
</span>
<span class="o_stat_text">Success</span>
</div>
</button>
</div>
<div class="oe_title">
<label class="oe_edit_only" for="name" string="Name" />
<h1>
<field name="name" class="oe_inline" />
</h1>
<field name="create_date" invisible="1" />
<field
name="method_type"
widget="radio"
options="{'horizontal': true}"
attrs="{'readonly':[('create_date', '!=', False)]}"
/>
</div>
<group string="Storage Location" class="col-12 col-lg-6">
<field name="backend_id" />
<field name="filepath" />
<field
name="pattern"
attrs="{'invisible':[('method_type','!=','import')]}"
/>
</group>
<group
name="action"
string="Importation"
attrs="{'invisible':[('method_type','!=','import')]}"
class="col-12 col-lg-6"
>
<field name="avoid_duplicated_files" />
<field name="after_import" />
<field
name="move_path"
attrs="{'invisible':[('after_import','not in',('move', 'move_rename'))], 'required': [('after_import', 'in', ('move', 'move_rename'))]}"
/>
<field
name="new_name"
attrs="{'invisible': [('after_import','not in',('rename', 'move_rename'))], 'required': [('after_import', 'in', ('rename', 'move_rename'))]}"
/>
<field name="file_type" />
</group>
<group string="Notification">
<field name="failure_emails" />
</group>
</sheet>
</form>
</field>
</record>
<record id="view_attachment_task_tree" model="ir.ui.view">
<field name="model">attachment.synchronize.task</field>
<field name="arch" type="xml">
<tree decoration-muted="active == False">
<field name="name" select="1" />
<field name="backend_id" />
<field name="filepath" />
<button name="run" type="object" string="Run" icon="fa-play-circle" />
<field name="count_attachment_failed" string=" " />
<button
name="%(action_attachment_queue_related)d"
type="action"
icon="fa-thumbs-o-down"
title="Failed attachments"
context="{'search_default_failed': 1}"
/>
<field name="count_attachment_pending" string=" " />
<button
name="%(action_attachment_queue_related)d"
type="action"
icon="fa-spinner"
title="Pending attachments"
context="{'search_default_pending': 1}"
/>
<field name="count_attachment_done" string=" " />
<button
name="%(action_attachment_queue_related)d"
type="action"
icon="fa-thumbs-o-up"
title="Done attachments"
context="{'search_default_done': 1}"
/>
<field name="active" widget="boolean_toggle" />
<button
name="button_duplicate_record"
type="object"
icon="fa-clone"
title="Duplicate"
/>
</tree>
</field>
</record>
<record id="view_attachment_task_search" model="ir.ui.view">
<field name="model">attachment.synchronize.task</field>
<field name="arch" type="xml">
<search string="Attachments">
<field
name="name"
filter_domain="[('name','ilike',self)]"
string="Attachment Task"
/>
<field name="create_date" />
<filter
string="Backend"
name="backend"
context="{'group_by':'backend_id'}"
/>
</search>
</field>
</record>
<!-- Attachments Import Tasks Menu -->
<record id="action_attachment_import_task" model="ir.actions.act_window">
<field name="name">Attachments Import Tasks</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">attachment.synchronize.task</field>
<field name="view_mode">tree,form</field>
<field name="view_id" eval="False" />
<field name="search_view_id" ref="view_attachment_task_search" />
<field name="domain">[('method_type', '=', 'import')]</field>
<field
name="context"
>{'default_method_type': 'import', "active_test": False}</field>
</record>
<menuitem
id="menu_attachment_import_task"
parent="fs_storage.menu_storage"
sequence="21"
action="action_attachment_import_task"
/>
<!-- Attachments Export Tasks Menu -->
<record id="action_attachment_export_task" model="ir.actions.act_window">
<field name="name">Attachments Export Tasks</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">attachment.synchronize.task</field>
<field name="view_mode">tree,form</field>
<field name="view_id" eval="False" />
<field name="search_view_id" ref="view_attachment_task_search" />
<field name="domain">[('method_type', '=', 'export')]</field>
<field
name="context"
>{'default_method_type': 'export', "active_test": False}</field>
</record>
<menuitem
id="menu_attachment_export_task"
parent="fs_storage.menu_storage"
sequence="22"
action="action_attachment_export_task"
/>
</odoo>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_fs_storage_form" model="ir.ui.view">
<field name="model">fs.storage</field>
<field name="inherit_id" ref="fs_storage.fs_storage_form_view" />
<field name="priority" eval="250" />
<field name="arch" type="xml">
<xpath expr="//div[hasclass('oe_title')]" position="before">
<div class="oe_button_box" name="button_box">
<button
class="oe_stat_button"
type="object"
attrs="{'invisible': [('import_task_count', '&lt;', 1)]}"
name="action_related_import_task"
icon="fa-download"
>
<field name="import_task_count" widget="statinfo" />
</button>
<button
class="oe_stat_button"
type="object"
attrs="{'invisible': [('export_task_count', '&lt;', 1)]}"
name="action_related_export_task"
icon="fa-upload"
>
<field name="export_task_count" widget="statinfo" />
</button>
</div>
</xpath>
</field>
</record>
</odoo>