Browse Source
Merge pull request #516 from akretion/9-external-file-location
Merge pull request #516 from akretion/9-external-file-location
9 external file locationpull/799/head
Dave Lasley
8 years ago
committed by
GitHub
27 changed files with 1841 additions and 0 deletions
-
69external_file_location/README.rst
-
3external_file_location/__init__.py
-
35external_file_location/__openerp__.py
-
18external_file_location/data/cron.xml
-
99external_file_location/demo/task_demo.xml
-
347external_file_location/i18n/external_file_location.pot
-
347external_file_location/i18n/fr.po
-
3external_file_location/models/__init__.py
-
33external_file_location/models/attachment.py
-
68external_file_location/models/location.py
-
212external_file_location/models/task.py
-
5external_file_location/security/ir.model.access.csv
-
3external_file_location/tasks/__init__.py
-
27external_file_location/tasks/filestore.py
-
30external_file_location/tasks/ftp.py
-
30external_file_location/tasks/sftp.py
-
4external_file_location/tests/__init__.py
-
32external_file_location/tests/common.py
-
74external_file_location/tests/mock_server.py
-
50external_file_location/tests/test_filestore.py
-
86external_file_location/tests/test_ftp.py
-
85external_file_location/tests/test_sftp.py
-
28external_file_location/views/attachment_view.xml
-
70external_file_location/views/location_view.xml
-
12external_file_location/views/menu.xml
-
70external_file_location/views/task_view.xml
-
1requirements.txt
@ -0,0 +1,69 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
====================== |
|||
External File Location |
|||
====================== |
|||
|
|||
This module was written to extend the functionality of ir.attachment to support remote communication and allow you to import/export file to a remote server. |
|||
For now, FTP, SFTP and local filestore are handled by the module. |
|||
|
|||
Installation |
|||
============ |
|||
|
|||
To install this module, you need to: |
|||
|
|||
* fs python module at version 0.5.4 or under |
|||
* Paramiko python module |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
To use this module, you need to: |
|||
|
|||
* Add a location with your server infos |
|||
* Create a task with your file info and remote communication method |
|||
* A cron task will trigger each task |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/149/9.0 |
|||
|
|||
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 smashing it by providing a detailed and welcomed feedback. |
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Images |
|||
------ |
|||
|
|||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_. |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Valentin CHEMIERE <valentin.chemiere@akretion.com> |
|||
* Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com> |
|||
* Florian DA COSTA <florian.dacosta@akretion.com> |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
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. |
|||
|
|||
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +1,3 @@ |
|||
from . import models |
|||
from . import tasks |
|||
from . import tests |
@ -0,0 +1,35 @@ |
|||
# coding: utf-8 |
|||
# @ 2016 florian DA COSTA @ Akretion |
|||
# © 2016 @author Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
{ |
|||
'name': 'External File Location', |
|||
'version': '9.0.1.0.0', |
|||
'author': 'Akretion,Odoo Community Association (OCA)', |
|||
'website': 'www.akretion.com', |
|||
'license': 'AGPL-3', |
|||
'category': 'Generic Modules', |
|||
'depends': [ |
|||
'attachment_base_synchronize', |
|||
], |
|||
'external_dependencies': { |
|||
'python': [ |
|||
'fs', |
|||
'paramiko', |
|||
], |
|||
}, |
|||
'data': [ |
|||
'views/menu.xml', |
|||
'views/attachment_view.xml', |
|||
'views/location_view.xml', |
|||
'views/task_view.xml', |
|||
'data/cron.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
'demo': [ |
|||
'demo/task_demo.xml', |
|||
], |
|||
'installable': True, |
|||
'application': False, |
|||
} |
@ -0,0 +1,18 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record model="ir.cron" id="cronjob_run_exchange_tasks"> |
|||
<field name='name'>Run file exchange tasks</field> |
|||
<field name='interval_number'>30</field> |
|||
<field name='interval_type'>minutes</field> |
|||
<field name="numbercall">-1</field> |
|||
<field name="active">True</field> |
|||
<field name="doall" eval="False" /> |
|||
<field name="model">external.file.task</field> |
|||
<field name="function">run_task_scheduler</field> |
|||
<field name="args">([[('method_type', '=', 'import')]])</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,99 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="location_ftp" model="external.file.location"> |
|||
<field name="name">TEST FTP</field> |
|||
<field name="protocol">ftp</field> |
|||
<field name="address">my-ftp-address</field> |
|||
<field name="login">my-ftp-user</field> |
|||
<field name="password">my-ftp-password</field> |
|||
<field name="port">21</field> |
|||
</record> |
|||
<record id="location_sftp" model="external.file.location"> |
|||
<field name="name">TEST SFTP</field> |
|||
<field name="protocol">sftp</field> |
|||
<field name="address">my-sftp-address</field> |
|||
<field name="login">my-sftp-user</field> |
|||
<field name="password">my-sftp-password</field> |
|||
<field name="port">22</field> |
|||
</record> |
|||
<record id="location_filestore" model="external.file.location"> |
|||
<field name="name">TEST File Store</field> |
|||
<field name="protocol">file_store</field> |
|||
<field name="filestore_rootpath">/</field> |
|||
</record> |
|||
|
|||
<record id="ftp_import_task" model="external.file.task"> |
|||
<field name="method_type">import</field> |
|||
<field name="location_id" eval="ref('external_file_location.location_ftp')"/> |
|||
<field name="filename">test-import-ftp.txt</field> |
|||
<field name="filepath">/home/user/test</field> |
|||
<field name="name">Import FTP Task</field> |
|||
</record> |
|||
|
|||
<record id="ftp_export_task" model="external.file.task"> |
|||
<field name="method_type">export</field> |
|||
<field name="location_id" eval="ref('external_file_location.location_ftp')"/> |
|||
<field name="filepath">/home/user/test</field> |
|||
<field name="name">Export FTP Task</field> |
|||
</record> |
|||
|
|||
<record id="sftp_import_task" model="external.file.task"> |
|||
<field name="method_type">import</field> |
|||
<field name="location_id" eval="ref('external_file_location.location_sftp')"/> |
|||
<field name="filename">test-import-sftp.txt</field> |
|||
<field name="filepath">/home/user/test</field> |
|||
<field name="name">Import SFTP Task</field> |
|||
</record> |
|||
|
|||
<record id="sftp_export_task" model="external.file.task"> |
|||
<field name="method_type">export</field> |
|||
<field name="location_id" eval="ref('external_file_location.location_sftp')"/> |
|||
<field name="filepath">/home/user/test</field> |
|||
<field name="name">Export SFTP Task</field> |
|||
</record> |
|||
|
|||
<record id="filestore_import_task" model="external.file.task"> |
|||
<field name="method_type">import</field> |
|||
<field name="location_id" eval="ref('external_file_location.location_filestore')"/> |
|||
<field name="filename">test-import-filestore.txt</field> |
|||
<field name="filepath">/home/user/test</field> |
|||
<field name="name">Import filestore Task</field> |
|||
</record> |
|||
|
|||
<record id="filestore_export_task" model="external.file.task"> |
|||
<field name="method_type">export</field> |
|||
<field name="location_id" eval="ref('external_file_location.location_filestore')"/> |
|||
<field name="filepath">/home/user/test</field> |
|||
<field name="name">Export filestore Task</field> |
|||
</record> |
|||
|
|||
<record id="ir_attachment_export_file_sftp" model="ir.attachment.metadata"> |
|||
<field name="name">Sftp text export file</field> |
|||
<field name="datas">dGVzdCBzZnRwIGZpbGUgZXhwb3J0</field> |
|||
<field name="datas_fname">sftp_test_export.txt</field> |
|||
<field name="task_id" eval="ref('external_file_location.sftp_export_task')"/> |
|||
<field name="file_type">export_external_location</field> |
|||
</record> |
|||
|
|||
<record id="ir_attachment_export_file_ftp" model="ir.attachment.metadata"> |
|||
<field name="name">ftp text export file</field> |
|||
<field name="datas">dGVzdCBmdHAgZmlsZSBleHBvcnQ=</field> |
|||
<field name="datas_fname">ftp_test_export.txt</field> |
|||
<field name="task_id" eval="ref('external_file_location.ftp_export_task')"/> |
|||
<field name="file_type">export_external_location</field> |
|||
</record> |
|||
|
|||
<record id="ir_attachment_export_file_filestore" model="ir.attachment.metadata"> |
|||
<field name="name">filestore text export file</field> |
|||
<field name="datas">dGVzdCBmaWxlc3RvcmUgZmlsZSBleHBvcnQ=</field> |
|||
<field name="datas_fname">filestore_test_export.txt</field> |
|||
<field name="task_id" eval="ref('external_file_location.filestore_export_task')"/> |
|||
<field name="file_type">export_external_location</field> |
|||
</record> |
|||
|
|||
|
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,347 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * external_file_location |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 9.0c\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-08-10 16:51+0000\n" |
|||
"PO-Revision-Date: 2016-08-10 16:51+0000\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: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_needaction |
|||
msgid "Action Needed" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_after_import |
|||
msgid "Action after import a file" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_address |
|||
msgid "Address" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_after_import |
|||
msgid "After import" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_attachment_ids |
|||
msgid "Attachment" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_md5_check |
|||
msgid "Control file integrity after import with a md5 file" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_create_uid |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_create_uid |
|||
msgid "Created by" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_create_date |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_create_date |
|||
msgid "Created on" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_form |
|||
msgid "Data importation setting" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_last_post |
|||
msgid "Date of the last message posted on the record." |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model,name:external_file_location.model_external_file_location |
|||
msgid "Description" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_display_name |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_display_name |
|||
msgid "Display Name" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: selection:external.file.task,method_type:0 |
|||
msgid "Export" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model,name:external_file_location.model_external_file_task |
|||
msgid "External file task" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_location_tree |
|||
msgid "File Location" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.actions.act_window,name:external_file_location.action_location |
|||
#: model:ir.ui.menu,name:external_file_location.menu_ir_location |
|||
msgid "File Locations" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.menu,name:external_file_location.menu_file_exchange |
|||
msgid "File exchange" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_filename |
|||
msgid "File name which is imported.You can use file pattern like *.txtto import all txt files" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_file_type |
|||
msgid "File type" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_filestore_rootpath |
|||
msgid "FileStore Root Path" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_filename |
|||
msgid "Filename" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_filepath |
|||
msgid "Filepath" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_follower_ids |
|||
msgid "Followers" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_channel_ids |
|||
msgid "Followers (Channels)" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_partner_ids |
|||
msgid "Followers (Partners)" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_hide_login |
|||
msgid "Hide login" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_hide_password |
|||
msgid "Hide password" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_hide_port |
|||
msgid "Hide port" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_id |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_id |
|||
msgid "ID" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_unread |
|||
msgid "If checked new messages require your attention." |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_needaction |
|||
msgid "If checked, new messages require your attention." |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: selection:external.file.task,method_type:0 |
|||
msgid "Import" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_move_path |
|||
msgid "Imported File will be moved to this path" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_new_name |
|||
msgid "Imported File will be renamed to this nameName can use mako template where obj is an ir_attachement. template exemple : ${obj.name}-${obj.create_date}.csv" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_is_follower |
|||
msgid "Is Follower" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_last_post |
|||
msgid "Last Message Date" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location___last_update |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task___last_update |
|||
msgid "Last Modified on" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_write_uid |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_write_uid |
|||
msgid "Last Updated by" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_write_date |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_write_date |
|||
msgid "Last Updated on" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_location_id |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_location_id |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_location_form |
|||
msgid "Location" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_login |
|||
msgid "Login" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_md5_check |
|||
msgid "Md5 check" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_ids |
|||
msgid "Messages" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_method_type |
|||
msgid "Method type" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_move_path |
|||
msgid "Move path" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_name |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_name |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_location_form |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_form |
|||
msgid "Name" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_new_name |
|||
msgid "New name" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_needaction_counter |
|||
msgid "Number of Actions" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_needaction_counter |
|||
msgid "Number of messages which requires an action" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_unread_counter |
|||
msgid "Number of unread messages" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_password |
|||
msgid "Password" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_filepath |
|||
msgid "Path to imported/exported file" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_port |
|||
msgid "Port" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_protocol |
|||
msgid "Protocol" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_form |
|||
msgid "Run" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_location_filestore_rootpath |
|||
msgid "Server's root path" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_task_id |
|||
msgid "Task" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_task_ids |
|||
msgid "Task ids" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_location_form |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_form |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_tree |
|||
msgid "Tasks" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_file_type |
|||
msgid "The file type determines an import method to be used to parse and transform data before their import in ERP" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_unread |
|||
msgid "Unread Messages" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_unread_counter |
|||
msgid "Unread Messages Counter" |
|||
msgstr "" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model,name:external_file_location.model_ir_attachment_metadata |
|||
msgid "ir.attachment.metadata" |
|||
msgstr "" |
|||
|
@ -0,0 +1,347 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * external_file_location |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 9.0c\n" |
|||
"Report-Msgid-Bugs-To: \n" |
|||
"POT-Creation-Date: 2016-08-10 16:51+0000\n" |
|||
"PO-Revision-Date: 2016-08-10 16:51+0000\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: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_needaction |
|||
msgid "Action Needed" |
|||
msgstr "A besoin d'une action" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_after_import |
|||
msgid "Action after import a file" |
|||
msgstr "Action après l'import du fichier" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_address |
|||
msgid "Address" |
|||
msgstr "Addresse" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_after_import |
|||
msgid "After import" |
|||
msgstr "Après import" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_attachment_ids |
|||
msgid "Attachment" |
|||
msgstr "Pièce jointe" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_md5_check |
|||
msgid "Control file integrity after import with a md5 file" |
|||
msgstr "Contrôle l'intégrité du fichier après l'import avec un fichier md5" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_create_uid |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_create_uid |
|||
msgid "Created by" |
|||
msgstr "Créé par" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_create_date |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_create_date |
|||
msgid "Created on" |
|||
msgstr "Créé le" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_form |
|||
msgid "Data importation setting" |
|||
msgstr "Data importation setting" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_last_post |
|||
msgid "Date of the last message posted on the record." |
|||
msgstr "Date du dernier message publié sur cet enregistrement" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model,name:external_file_location.model_external_file_location |
|||
msgid "Description" |
|||
msgstr "Description" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_display_name |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_display_name |
|||
msgid "Display Name" |
|||
msgstr "Afficher le nom" |
|||
|
|||
#. module: external_file_location |
|||
#: selection:external.file.task,method_type:0 |
|||
msgid "Export" |
|||
msgstr "Export" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model,name:external_file_location.model_external_file_task |
|||
msgid "External file task" |
|||
msgstr "Tache" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_location_tree |
|||
msgid "File Location" |
|||
msgstr "Emplacement fichier" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.actions.act_window,name:external_file_location.action_location |
|||
#: model:ir.ui.menu,name:external_file_location.menu_ir_location |
|||
msgid "File Locations" |
|||
msgstr "Emplacements fichiers" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.menu,name:external_file_location.menu_file_exchange |
|||
msgid "File exchange" |
|||
msgstr "Echange de fichier" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_filename |
|||
msgid "File name which is imported.You can use file pattern like *.txtto import all txt files" |
|||
msgstr "Nom du fichier importé. Vous pouvez utiliser une expression comme *.txt pour importer tous les fichiers txt" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_file_type |
|||
msgid "File type" |
|||
msgstr "Type de fichier" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_filestore_rootpath |
|||
msgid "FileStore Root Path" |
|||
msgstr "Emplacement racine" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_filename |
|||
msgid "Filename" |
|||
msgstr "Nom du fichier" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_filepath |
|||
msgid "Filepath" |
|||
msgstr "Chemin" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_follower_ids |
|||
msgid "Followers" |
|||
msgstr "Abonnés" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_channel_ids |
|||
msgid "Followers (Channels)" |
|||
msgstr "Abonnés (Canaux)" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_partner_ids |
|||
msgid "Followers (Partners)" |
|||
msgstr "Abonnés (Partenaires)" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_hide_login |
|||
msgid "Hide login" |
|||
msgstr "Cacher le login" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_hide_password |
|||
msgid "Hide password" |
|||
msgstr "Cacher le mot de passe" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_hide_port |
|||
msgid "Hide port" |
|||
msgstr "Cacher le port" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_id |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_id |
|||
msgid "ID" |
|||
msgstr "Identifiant" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_unread |
|||
msgid "If checked new messages require your attention." |
|||
msgstr "Si coché, de nouveaux messages demandent votre attention." |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_needaction |
|||
msgid "If checked, new messages require your attention." |
|||
msgstr "si elle est cochée, de nouveaux messages requièrent votre attention." |
|||
|
|||
#. module: external_file_location |
|||
#: selection:external.file.task,method_type:0 |
|||
msgid "Import" |
|||
msgstr "Import" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_move_path |
|||
msgid "Imported File will be moved to this path" |
|||
msgstr "Le fichier importé sera déplacé dans cet emplacement" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_new_name |
|||
msgid "Imported File will be renamed to this nameName can use mako template where obj is an ir_attachement. template exemple : ${obj.name}-${obj.create_date}.csv" |
|||
msgstr "Imported File will be renamed to this nameName can use mako template where obj is an ir_attachement. template exemple : ${obj.name}-${obj.create_date}.csv" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_is_follower |
|||
msgid "Is Follower" |
|||
msgstr "Est un abonné" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_last_post |
|||
msgid "Last Message Date" |
|||
msgstr "Date du dernier message" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location___last_update |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task___last_update |
|||
msgid "Last Modified on" |
|||
msgstr "Dernière modification le" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_write_uid |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_write_uid |
|||
msgid "Last Updated by" |
|||
msgstr "Dernière mise à jour par" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_write_date |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_write_date |
|||
msgid "Last Updated on" |
|||
msgstr "Dernière mise à jour le" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_location_id |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_location_id |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_location_form |
|||
msgid "Location" |
|||
msgstr "Emplacement" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_login |
|||
msgid "Login" |
|||
msgstr "Identifiant" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_md5_check |
|||
msgid "Md5 check" |
|||
msgstr "Md5 check" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_ids |
|||
msgid "Messages" |
|||
msgstr "Messages" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_method_type |
|||
msgid "Method type" |
|||
msgstr "Type de méthode" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_move_path |
|||
msgid "Move path" |
|||
msgstr "chemin des archives" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_name |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_name |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_location_form |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_form |
|||
msgid "Name" |
|||
msgstr "Nom" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_task_new_name |
|||
msgid "New name" |
|||
msgstr "Nouveau nom" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_needaction_counter |
|||
msgid "Number of Actions" |
|||
msgstr "Nombre d'Actions" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_needaction_counter |
|||
msgid "Number of messages which requires an action" |
|||
msgstr "Nombre de messages demandant une action" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_ir_attachment_metadata_message_unread_counter |
|||
msgid "Number of unread messages" |
|||
msgstr "Nombre de messages non lus" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_password |
|||
msgid "Password" |
|||
msgstr "Mot de passe" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_filepath |
|||
msgid "Path to imported/exported file" |
|||
msgstr "Path to imported/exported file" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_port |
|||
msgid "Port" |
|||
msgstr "Port" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_protocol |
|||
msgid "Protocol" |
|||
msgstr "Protocole" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_form |
|||
msgid "Run" |
|||
msgstr "Run" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_location_filestore_rootpath |
|||
msgid "Server's root path" |
|||
msgstr "Chemin racine du serveur" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_task_id |
|||
msgid "Task" |
|||
msgstr "Tache" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_external_file_location_task_ids |
|||
msgid "Task ids" |
|||
msgstr "Task ids" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_location_form |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_form |
|||
#: model:ir.ui.view,arch_db:external_file_location.view_task_tree |
|||
msgid "Tasks" |
|||
msgstr "Taches" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,help:external_file_location.field_external_file_task_file_type |
|||
msgid "The file type determines an import method to be used to parse and transform data before their import in ERP" |
|||
msgstr "Le type de fichier détermine la méthode d'import utilisée pour parser le fichier et transformer les données avant l'import dans l'ERP" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_unread |
|||
msgid "Unread Messages" |
|||
msgstr "Messages non lus" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model.fields,field_description:external_file_location.field_ir_attachment_metadata_message_unread_counter |
|||
msgid "Unread Messages Counter" |
|||
msgstr "Compteur de messages non lus" |
|||
|
|||
#. module: external_file_location |
|||
#: model:ir.model,name:external_file_location.model_ir_attachment_metadata |
|||
msgid "ir.attachment.metadata" |
|||
msgstr "ir.attachment.metadata" |
|||
|
@ -0,0 +1,3 @@ |
|||
from . import attachment |
|||
from . import location |
|||
from . import task |
@ -0,0 +1,33 @@ |
|||
# coding: utf-8 |
|||
# @ 2016 Florian DA COSTA @ Akretion |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from openerp import models, fields, api |
|||
import base64 |
|||
import os |
|||
|
|||
|
|||
class IrAttachmentMetadata(models.Model): |
|||
_inherit = 'ir.attachment.metadata' |
|||
|
|||
task_id = fields.Many2one('external.file.task', string='Task') |
|||
location_id = fields.Many2one( |
|||
'external.file.location', string='Location', |
|||
related='task_id.location_id', store=True) |
|||
file_type = fields.Selection( |
|||
selection_add=[ |
|||
('export_external_location', |
|||
'Export File (External location)') |
|||
]) |
|||
|
|||
@api.multi |
|||
def _run(self): |
|||
super(IrAttachmentMetadata, self)._run() |
|||
if self.file_type == 'export_external_location': |
|||
protocols = self.env['external.file.location']._get_classes() |
|||
location = self.location_id |
|||
cls = protocols.get(location.protocol)[1] |
|||
path = os.path.join(self.task_id.filepath, self.datas_fname) |
|||
with cls.connect(location) as conn: |
|||
datas = base64.decodestring(self.datas) |
|||
conn.setcontents(path, data=datas) |
@ -0,0 +1,68 @@ |
|||
# coding: utf-8 |
|||
# @ 2015 Valentin CHEMIERE @ Akretion |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from openerp import models, fields, api |
|||
from ..tasks.filestore import FileStoreTask |
|||
from ..tasks.ftp import FtpTask |
|||
from ..tasks.sftp import SftpTask |
|||
|
|||
|
|||
class Location(models.Model): |
|||
_name = 'external.file.location' |
|||
_description = 'Location' |
|||
|
|||
name = fields.Char(string='Name', required=True) |
|||
protocol = fields.Selection(selection='_get_protocol', required=True) |
|||
address = fields.Char( |
|||
string='Address') |
|||
filestore_rootpath = fields.Char( |
|||
string='FileStore Root Path', |
|||
help="Server's root path") |
|||
port = fields.Integer() |
|||
login = fields.Char() |
|||
password = fields.Char() |
|||
task_ids = fields.One2many('external.file.task', 'location_id') |
|||
hide_login = fields.Boolean() |
|||
hide_password = fields.Boolean() |
|||
hide_port = fields.Boolean() |
|||
company_id = fields.Many2one( |
|||
'res.company', 'Company', |
|||
default=lambda self: self.env['res.company']._company_default_get( |
|||
'external.file.location')) |
|||
|
|||
@api.model |
|||
def _get_classes(self): |
|||
"surcharge this method to add new protocols" |
|||
return { |
|||
'ftp': ('FTP', FtpTask), |
|||
'sftp': ('SFTP', SftpTask), |
|||
'file_store': ('File Store', FileStoreTask), |
|||
} |
|||
|
|||
@api.model |
|||
def _get_protocol(self): |
|||
protocols = self._get_classes() |
|||
selection = [] |
|||
for key, val in protocols.iteritems(): |
|||
selection.append((key, val[0])) |
|||
return selection |
|||
|
|||
@api.onchange('protocol') |
|||
def onchange_protocol(self): |
|||
protocols = self._get_classes() |
|||
if self.protocol: |
|||
cls = protocols.get(self.protocol)[1] |
|||
self.port = cls._default_port |
|||
if cls._hide_login: |
|||
self.hide_login = True |
|||
else: |
|||
self.hide_login = False |
|||
if cls._hide_password: |
|||
self.hide_password = True |
|||
else: |
|||
self.hide_password = False |
|||
if cls._hide_port: |
|||
self.hide_port = True |
|||
else: |
|||
self.hide_port = False |
@ -0,0 +1,212 @@ |
|||
# coding: utf-8 |
|||
# @ 2015 Valentin CHEMIERE @ Akretion |
|||
# © @author Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from openerp import models, fields, api |
|||
import openerp |
|||
from openerp import tools |
|||
from base64 import b64encode |
|||
import os |
|||
import datetime |
|||
import logging |
|||
|
|||
_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, |
|||
'reduce': reduce, |
|||
'map': map, |
|||
'round': round, |
|||
}) |
|||
except ImportError: |
|||
_logger.warning("jinja2 not available, templating features will not work!") |
|||
|
|||
|
|||
class Task(models.Model): |
|||
_name = 'external.file.task' |
|||
_description = 'External file task' |
|||
|
|||
name = fields.Char(required=True) |
|||
|
|||
method_type = fields.Selection( |
|||
[('import', 'Import'), ('export', 'Export')], |
|||
required=True) |
|||
|
|||
filename = fields.Char(help='File name which is imported.' |
|||
'You can use file pattern like *.txt' |
|||
'to import all txt files') |
|||
filepath = fields.Char(help='Path to imported/exported file') |
|||
|
|||
location_id = fields.Many2one('external.file.location', string='Location', |
|||
required=True) |
|||
|
|||
attachment_ids = fields.One2many('ir.attachment.metadata', 'task_id', |
|||
string='Attachment') |
|||
|
|||
move_path = fields.Char(string='Move Path', |
|||
help='Imported File will be moved to this path') |
|||
|
|||
new_name = fields.Char(string='New Name', |
|||
help='Imported File will be renamed to this name' |
|||
'Name can use mako template where obj is an ' |
|||
'ir_attachement. template exemple : ' |
|||
' ${obj.name}-${obj.create_date}.csv') |
|||
|
|||
md5_check = fields.Boolean(help='Control file integrity after import with' |
|||
' a md5 file') |
|||
|
|||
after_import = fields.Selection(selection='_get_action', |
|||
help='Action after import a file') |
|||
|
|||
company_id = fields.Many2one( |
|||
'res.company', 'Company', |
|||
default=lambda self: self.env['res.company']._company_default_get( |
|||
'external.file.task')) |
|||
|
|||
file_type = fields.Selection( |
|||
selection=[], |
|||
string="File Type", |
|||
help="The file type determines an import method to be used " |
|||
"to parse and transform data before their import in ERP") |
|||
|
|||
active = fields.Boolean(default=True) |
|||
|
|||
def _get_action(self): |
|||
return [('rename', 'Rename'), |
|||
('move', 'Move'), |
|||
('move_rename', 'Move & Rename'), |
|||
('delete', 'Delete'), |
|||
] |
|||
|
|||
@api.multi |
|||
def _prepare_attachment_vals(self, datas, filename, md5_datas): |
|||
self.ensure_one() |
|||
vals = { |
|||
'name': filename, |
|||
'datas': b64encode(datas), |
|||
'datas_fname': filename, |
|||
'task_id': self.id, |
|||
'external_hash': md5_datas, |
|||
'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 %r", template) |
|||
|
|||
variables = {'obj': record} |
|||
try: |
|||
render_result = template.render(variables) |
|||
except Exception: |
|||
_logger.exception( |
|||
"Failed to render template %r using values %r" % |
|||
(template, variables)) |
|||
render_result = u"" |
|||
if render_result == u"False": |
|||
render_result = u"" |
|||
return render_result |
|||
|
|||
@api.model |
|||
def run_task_scheduler(self, domain=None): |
|||
if domain is None: |
|||
domain = [] |
|||
tasks = self.env['external.file.task'].search(domain) |
|||
for task in tasks: |
|||
if task.method_type == 'import': |
|||
task.run_import() |
|||
elif task.method_type == 'export': |
|||
task.run_export() |
|||
|
|||
@api.multi |
|||
def run_import(self): |
|||
self.ensure_one() |
|||
protocols = self.env['external.file.location']._get_classes() |
|||
cls = protocols.get(self.location_id.protocol)[1] |
|||
attach_obj = self.env['ir.attachment.metadata'] |
|||
with cls.connect(self.location_id) as conn: |
|||
md5_datas = '' |
|||
for file_name in conn.listdir(path=self.filepath, |
|||
wildcard=self.filename or '', |
|||
files_only=True): |
|||
with api.Environment.manage(): |
|||
with openerp.registry( |
|||
self.env.cr.dbname).cursor() as new_cr: |
|||
new_env = api.Environment(new_cr, self.env.uid, |
|||
self.env.context) |
|||
try: |
|||
full_path = os.path.join(self.filepath, file_name) |
|||
file_data = conn.open(full_path, 'rb') |
|||
datas = file_data.read() |
|||
if self.md5_check: |
|||
md5_file = conn.open(full_path + '.md5', 'rb') |
|||
md5_datas = md5_file.read().rstrip('\r\n') |
|||
attach_vals = self._prepare_attachment_vals( |
|||
datas, file_name, md5_datas) |
|||
attachment = attach_obj.with_env(new_env).create( |
|||
attach_vals) |
|||
new_full_path = False |
|||
if self.after_import == 'rename': |
|||
new_name = self._template_render( |
|||
self.new_name, attachment) |
|||
new_full_path = os.path.join( |
|||
self.filepath, new_name) |
|||
elif self.after_import == 'move': |
|||
new_full_path = os.path.join( |
|||
self.move_path, file_name) |
|||
elif self.after_import == 'move_rename': |
|||
new_name = self._template_render( |
|||
self.new_name, attachment) |
|||
new_full_path = os.path.join( |
|||
self.move_path, new_name) |
|||
if new_full_path: |
|||
conn.rename(full_path, new_full_path) |
|||
if self.md5_check: |
|||
conn.rename( |
|||
full_path + '.md5', |
|||
new_full_path + '/md5') |
|||
if self.after_import == 'delete': |
|||
conn.remove(full_path) |
|||
if self.md5_check: |
|||
conn.remove(full_path + '.md5') |
|||
except Exception, e: |
|||
new_env.cr.rollback() |
|||
raise e |
|||
else: |
|||
new_env.cr.commit() |
|||
|
|||
@api.multi |
|||
def run_export(self): |
|||
self.ensure_one() |
|||
attachment_obj = self.env['ir.attachment.metadata'] |
|||
attachments = attachment_obj.search( |
|||
[('task_id', '=', self.id), ('state', '!=', 'done')]) |
|||
for attachment in attachments: |
|||
attachment.run() |
@ -0,0 +1,5 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
access_external_file_location_manager,external.file.location.manager,model_external_file_location,base.group_system,1,1,1,1 |
|||
access_external_file_location_user,external.file.location.user,model_external_file_location,base.group_user,1,0,0,0 |
|||
access_external_file_task_manager,external.file.task.manager,model_external_file_task,base.group_system,1,1,1,1 |
|||
access_external_file_task_user,external.file.task.user,model_external_file_task,base.group_user,1,0,0,0 |
@ -0,0 +1,3 @@ |
|||
from . import ftp |
|||
from . import sftp |
|||
from . import filestore |
@ -0,0 +1,27 @@ |
|||
# coding: utf-8 |
|||
# @ 2016 Florian DA COSTA @ Akretion |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import logging |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
try: |
|||
from fs import osfs |
|||
except ImportError: |
|||
_logger.debug('Cannot `import fs`.') |
|||
|
|||
|
|||
class FileStoreTask(osfs.OSFS): |
|||
|
|||
_key = 'filestore' |
|||
_name = 'File Store' |
|||
_default_port = None |
|||
_hide_login = True |
|||
_hide_password = True |
|||
_hide_port = True |
|||
|
|||
@staticmethod |
|||
def connect(location): |
|||
rootpath = location.filestore_rootpath or '/' |
|||
conn = FileStoreTask(rootpath) |
|||
return conn |
@ -0,0 +1,30 @@ |
|||
# coding: utf-8 |
|||
# @ 2016 Florian DA COSTA @ Akretion |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import logging |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
try: |
|||
from fs import ftpfs |
|||
except ImportError: |
|||
_logger.debug('Cannot `import fs`.') |
|||
|
|||
|
|||
class FtpTask(ftpfs.FTPFS): |
|||
|
|||
_key = 'sftp' |
|||
_name = 'SFTP' |
|||
_synchronize_type = None |
|||
_default_port = 22 |
|||
_hide_login = False |
|||
_hide_password = False |
|||
_hide_port = False |
|||
|
|||
@staticmethod |
|||
def connect(location): |
|||
conn = FtpTask(location.address, |
|||
location.login, |
|||
location.password, |
|||
location.port) |
|||
return conn |
@ -0,0 +1,30 @@ |
|||
# coding: utf-8 |
|||
# @ 2016 Florian DA COSTA @ Akretion |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import logging |
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
try: |
|||
from fs import sftpfs |
|||
except ImportError: |
|||
_logger.debug('Cannot `import fs`.') |
|||
|
|||
|
|||
class SftpTask(sftpfs.SFTPFS): |
|||
|
|||
_key = 'sftp' |
|||
_name = 'SFTP' |
|||
_synchronize_type = None |
|||
_default_port = 22 |
|||
_hide_login = False |
|||
_hide_password = False |
|||
_hide_port = False |
|||
|
|||
@staticmethod |
|||
def connect(location): |
|||
connection_string = "{}:{}".format(location.address, location.port) |
|||
conn = SftpTask(connection=connection_string, |
|||
username=location.login, |
|||
password=location.password) |
|||
return conn |
@ -0,0 +1,4 @@ |
|||
from . import mock_server |
|||
from . import test_ftp |
|||
from . import test_sftp |
|||
from . import test_filestore |
@ -0,0 +1,32 @@ |
|||
# coding: utf-8 |
|||
# @ 2016 Florian da Costa @ Akretion |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
import openerp.tests.common as common |
|||
from openerp import api |
|||
from StringIO import StringIO |
|||
|
|||
|
|||
class ContextualStringIO(StringIO): |
|||
""" |
|||
snippet from http://bit.ly/1HfH6uW (stackoverflow) |
|||
""" |
|||
|
|||
def __enter__(self): |
|||
return self |
|||
|
|||
def __exit__(self, *args): |
|||
self.close() |
|||
return False |
|||
|
|||
|
|||
class TestConnection(common.TransactionCase): |
|||
|
|||
def setUp(self): |
|||
super(TestConnection, self).setUp() |
|||
self.registry.enter_test_mode() |
|||
self.env = api.Environment(self.registry.test_cr, self.env.uid, |
|||
self.env.context) |
|||
|
|||
def tearDown(self): |
|||
self.registry.leave_test_mode() |
|||
super(TestConnection, self).tearDown() |
@ -0,0 +1,74 @@ |
|||
# coding: utf-8 |
|||
# Copyright (C) 2014 initOS GmbH & Co. KG (<http://www.initos.com>). |
|||
# @ 2015 Valentin CHEMIERE @ Akretion |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import mock |
|||
from contextlib import contextmanager |
|||
from collections import defaultdict |
|||
|
|||
|
|||
class MultiResponse(dict): |
|||
pass |
|||
|
|||
|
|||
class ConnMock(object): |
|||
|
|||
def __init__(self, response): |
|||
self.response = response |
|||
self._calls = [] |
|||
self.call_count = defaultdict(int) |
|||
|
|||
def __getattribute__(self, method): |
|||
if method not in ('_calls', 'response', 'call_count'): |
|||
def callable(*args, **kwargs): |
|||
self._calls.append({ |
|||
'method': method, |
|||
'args': args, |
|||
'kwargs': kwargs, |
|||
}) |
|||
call = self.response[method] |
|||
if isinstance(call, MultiResponse): |
|||
call = call[self.call_count[method]] |
|||
self.call_count[method] += 1 |
|||
return call |
|||
|
|||
return callable |
|||
else: |
|||
return super(ConnMock, self).__getattribute__(method) |
|||
|
|||
def __call__(self, *args, **kwargs): |
|||
return self |
|||
|
|||
def __enter__(self, *args, **kwargs): |
|||
return self |
|||
|
|||
def __exit__(self, *args, **kwargs): |
|||
pass |
|||
|
|||
def __repr__(self, *args, **kwargs): |
|||
return self |
|||
|
|||
def __getitem__(self, key): |
|||
return |
|||
|
|||
|
|||
@contextmanager |
|||
def server_mock_sftp(response): |
|||
with mock.patch('openerp.addons.external_file_location.tasks.sftp.' |
|||
'SftpTask', ConnMock(response)) as SFTPFS: |
|||
yield SFTPFS._calls |
|||
|
|||
|
|||
@contextmanager |
|||
def server_mock_ftp(response): |
|||
with mock.patch('openerp.addons.external_file_location.tasks.ftp.' |
|||
'FtpTask', ConnMock(response)) as FTPFS: |
|||
yield FTPFS._calls |
|||
|
|||
|
|||
@contextmanager |
|||
def server_mock_filestore(response): |
|||
with mock.patch('openerp.addons.external_file_location.tasks.filestore.' |
|||
'FileStoreTask', ConnMock(response)) as FTPFS: |
|||
yield FTPFS._calls |
@ -0,0 +1,50 @@ |
|||
# coding: utf-8 |
|||
# @ 2015 Valentin CHEMIERE @ Akretion |
|||
# ©2016 @author Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
import logging |
|||
from base64 import b64decode |
|||
from .common import TestConnection, ContextualStringIO |
|||
from .mock_server import server_mock_filestore |
|||
|
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
class TestfilestoreConnection(TestConnection): |
|||
|
|||
def setUp(self): |
|||
super(TestfilestoreConnection, self).setUp() |
|||
self.test_file_filestore = ContextualStringIO() |
|||
self.test_file_filestore.write('import filestore') |
|||
self.test_file_filestore.seek(0) |
|||
|
|||
def test_00_filestore_import(self): |
|||
self.task = self.env.ref( |
|||
'external_file_location.filestore_import_task') |
|||
with server_mock_filestore( |
|||
{'open': self.test_file_filestore, |
|||
'listdir': ['test-import-filestore.txt']}): |
|||
self.task.run_import() |
|||
search_file = self.env['ir.attachment.metadata'].search( |
|||
[('name', '=', 'test-import-filestore.txt')]) |
|||
self.assertEqual(len(search_file), 1) |
|||
self.assertEqual(b64decode(search_file[0].datas), 'import filestore') |
|||
|
|||
def test_01_filestore_export(self): |
|||
self.task = self.env.ref( |
|||
'external_file_location.filestore_export_task') |
|||
self.filestore_attachment = self.env.ref( |
|||
'external_file_location.ir_attachment_export_file_filestore') |
|||
with server_mock_filestore( |
|||
{'setcontents': ''}) as Fakefilestore: |
|||
self.task.run_export() |
|||
if Fakefilestore: |
|||
self.assertEqual('setcontents', Fakefilestore[-1]['method']) |
|||
self.assertEqual('done', self.filestore_attachment.state) |
|||
self.assertEqual( |
|||
'/home/user/test/filestore_test_export.txt', |
|||
Fakefilestore[-1]['args'][0]) |
|||
self.assertEqual( |
|||
'test filestore file export', |
|||
Fakefilestore[-1]['kwargs']['data']) |
@ -0,0 +1,86 @@ |
|||
# coding: utf-8 |
|||
# @ 2015 Valentin CHEMIERE @ Akretion |
|||
# ©2016 @author Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
import logging |
|||
from base64 import b64decode |
|||
import hashlib |
|||
from .common import TestConnection, ContextualStringIO |
|||
from .mock_server import server_mock_ftp |
|||
from .mock_server import MultiResponse |
|||
from openerp.exceptions import UserError |
|||
|
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
class TestFtpConnection(TestConnection): |
|||
|
|||
def setUp(self): |
|||
super(TestFtpConnection, self).setUp() |
|||
self.test_file_ftp = ContextualStringIO() |
|||
self.test_file_ftp.write('import ftp') |
|||
self.test_file_ftp.seek(0) |
|||
|
|||
def test_00_ftp_import(self): |
|||
self.task = self.env.ref('external_file_location.ftp_import_task') |
|||
with server_mock_ftp( |
|||
{'open': self.test_file_ftp, |
|||
'listdir': ['test-import-ftp.txt']}): |
|||
self.task.run_import() |
|||
search_file = self.env['ir.attachment.metadata'].search( |
|||
[('name', '=', 'test-import-ftp.txt')]) |
|||
self.assertEqual(len(search_file), 1) |
|||
self.assertEqual(b64decode(search_file[0].datas), 'import ftp') |
|||
|
|||
def test_01_ftp_export(self): |
|||
self.task = self.env.ref('external_file_location.ftp_export_task') |
|||
self.ftp_attachment = self.env.ref( |
|||
'external_file_location.ir_attachment_export_file_ftp') |
|||
with server_mock_ftp( |
|||
{'setcontents': ''}) as FakeFTP: |
|||
self.task.run_export() |
|||
if FakeFTP: |
|||
self.assertEqual('setcontents', FakeFTP[-1]['method']) |
|||
self.assertEqual('done', self.ftp_attachment.state) |
|||
self.assertEqual( |
|||
'/home/user/test/ftp_test_export.txt', |
|||
FakeFTP[-1]['args'][0]) |
|||
self.assertEqual( |
|||
'test ftp file export', |
|||
FakeFTP[-1]['kwargs']['data']) |
|||
|
|||
def test_02_ftp_import_md5(self): |
|||
md5_file = ContextualStringIO() |
|||
md5_file.write(hashlib.md5('import ftp').hexdigest()) |
|||
md5_file.seek(0) |
|||
task = self.env.ref('external_file_location.ftp_import_task') |
|||
task.md5_check = True |
|||
with server_mock_ftp( |
|||
{'open': MultiResponse({ |
|||
1: md5_file, |
|||
0: self.test_file_ftp}), |
|||
'listdir': [task.filename]}) as Fakeftp: |
|||
task.run_import() |
|||
search_file = self.env['ir.attachment.metadata'].search( |
|||
(('name', '=', task.filename),)) |
|||
self.assertEqual(len(search_file), 1) |
|||
self.assertEqual(b64decode(search_file[0].datas), |
|||
'import ftp') |
|||
self.assertEqual('open', Fakeftp[-1]['method']) |
|||
self.assertEqual(hashlib.md5('import ftp').hexdigest(), |
|||
search_file.external_hash) |
|||
|
|||
def test_03_ftp_import_md5_corrupt_file(self): |
|||
md5_file = ContextualStringIO() |
|||
md5_file.write(hashlib.md5('import test ftp corrupted').hexdigest()) |
|||
md5_file.seek(0) |
|||
task = self.env.ref('external_file_location.ftp_import_task') |
|||
task.md5_check = True |
|||
with server_mock_ftp( |
|||
{'open': MultiResponse({ |
|||
1: md5_file, |
|||
0: self.test_file_ftp}), |
|||
'listdir': [task.filename]}): |
|||
with self.assertRaises(UserError): |
|||
task.run_import() |
@ -0,0 +1,85 @@ |
|||
# coding: utf-8 |
|||
# @ 2015 Valentin CHEMIERE @ Akretion |
|||
# ©2016 @author Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com> |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
import logging |
|||
from base64 import b64decode |
|||
import hashlib |
|||
from .common import TestConnection, ContextualStringIO |
|||
from .mock_server import server_mock_sftp |
|||
from .mock_server import MultiResponse |
|||
from openerp.exceptions import UserError |
|||
|
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
class TestSftpConnection(TestConnection): |
|||
|
|||
def setUp(self): |
|||
super(TestSftpConnection, self).setUp() |
|||
self.test_file_sftp = ContextualStringIO() |
|||
self.test_file_sftp.write('import sftp') |
|||
self.test_file_sftp.seek(0) |
|||
|
|||
def test_00_sftp_import(self): |
|||
task = self.env.ref('external_file_location.sftp_import_task') |
|||
with server_mock_sftp( |
|||
{'open': self.test_file_sftp, |
|||
'listdir': [task.filename]}): |
|||
task.run_import() |
|||
search_file = self.env['ir.attachment.metadata'].search( |
|||
[('name', '=', task.filename)]) |
|||
self.assertEqual(len(search_file), 1) |
|||
self.assertEqual(b64decode(search_file[0].datas), 'import sftp') |
|||
|
|||
def test_01_sftp_export(self): |
|||
self.task = self.env.ref('external_file_location.sftp_export_task') |
|||
self.sftp_attachment = self.env.ref( |
|||
'external_file_location.ir_attachment_export_file_sftp') |
|||
with server_mock_sftp( |
|||
{'setcontents': ''}) as FakeSFTP: |
|||
self.task.run_export() |
|||
if FakeSFTP: |
|||
self.assertEqual('setcontents', FakeSFTP[-1]['method']) |
|||
self.assertEqual( |
|||
'/home/user/test/sftp_test_export.txt', |
|||
FakeSFTP[-1]['args'][0]) |
|||
self.assertEqual( |
|||
'test sftp file export', |
|||
FakeSFTP[-1]['kwargs']['data']) |
|||
|
|||
def test_02_sftp_import_md5(self): |
|||
md5_file = ContextualStringIO() |
|||
md5_file.write(hashlib.md5('import sftp').hexdigest()) |
|||
md5_file.seek(0) |
|||
task = self.env.ref('external_file_location.sftp_import_task') |
|||
task.md5_check = True |
|||
with server_mock_sftp( |
|||
{'open': MultiResponse({ |
|||
1: md5_file, |
|||
0: self.test_file_sftp}), |
|||
'listdir': [task.filename]}) as FakeSFTP: |
|||
task.run_import() |
|||
search_file = self.env['ir.attachment.metadata'].search( |
|||
(('name', '=', task.filename),)) |
|||
self.assertEqual(len(search_file), 1) |
|||
self.assertEqual(b64decode(search_file[0].datas), |
|||
'import sftp') |
|||
self.assertEqual('open', FakeSFTP[-1]['method']) |
|||
self.assertEqual(hashlib.md5('import sftp').hexdigest(), |
|||
search_file.external_hash) |
|||
|
|||
def test_03_sftp_import_md5_corrupt_file(self): |
|||
md5_file = ContextualStringIO() |
|||
md5_file.write(hashlib.md5('import test sftp corrupted').hexdigest()) |
|||
md5_file.seek(0) |
|||
task = self.env.ref('external_file_location.sftp_import_task') |
|||
task.md5_check = True |
|||
with server_mock_sftp( |
|||
{'open': MultiResponse({ |
|||
1: md5_file, |
|||
0: self.test_file_sftp}), |
|||
'listdir': [task.filename]}): |
|||
with self.assertRaises(UserError): |
|||
task.run_import() |
@ -0,0 +1,28 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="view_attachment_improved_form" model="ir.ui.view"> |
|||
<field name="model">ir.attachment.metadata</field> |
|||
<field name="inherit_id" ref="attachment_base_synchronize.view_attachment_improved_form" /> |
|||
<field name="arch" type="xml"> |
|||
<field name="url" position="after"> |
|||
<field name="task_id" attrs="{'required': [('file_type', '=', 'export_external_location')]}"/> |
|||
<field name="location_id"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_external_attachment_tree" model="ir.ui.view"> |
|||
<field name="model">ir.attachment.metadata</field> |
|||
<field name="inherit_id" ref="attachment_base_synchronize.view_external_attachment_tree" /> |
|||
<field name="arch" type="xml"> |
|||
<field name="file_type" position="after"> |
|||
<field name="task_id"/> |
|||
<field name="location_id"/> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,70 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<record id="view_location_form" model="ir.ui.view"> |
|||
<field name="model">external.file.location</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Location" version="7.0"> |
|||
<sheet> |
|||
<group col="4"> |
|||
<div class="oe_title" style="width: 390px;" colspan="4"> |
|||
<label class="oe_edit_only" for="name" string="Name"/> |
|||
<h1><field name="name" class="oe_inline"/></h1> |
|||
</div> |
|||
<newline/> |
|||
<field name="protocol" colspan="2"/> |
|||
<newline/> |
|||
<field name="address" colspan="2" attrs="{'required': [('protocol', '!=', 'file_store')], 'invisible': [('protocol', '=', 'file_store')]}"/> |
|||
<field name="filestore_rootpath" colspan="2" attrs="{'required': [('protocol', '=', 'file_store')], 'invisible': [('protocol', '!=', 'file_store')]}"/> |
|||
<field name="port" colspan="2" attrs="{'invisible': [('hide_port', '=', True)], 'required': [('hide_port', '=', False)]}"/> |
|||
<field name="company_id" colspan="2"/> |
|||
<field name="login" colspan="2" attrs="{'invisible': [('hide_login', '=', True)], 'required': [('hide_login', '=', False)]}"/> |
|||
<field name="password" password="1" colspan="2" attrs="{'invisible': [('hide_password', '=', True)]}"/> |
|||
<separator string="Tasks" colspan="4"/> |
|||
<field name="task_ids" colspan="4" nolabel="1" context="{'hide_location': True, 'protocol': protocol}"> |
|||
<tree> |
|||
<field name="name"/> |
|||
<field name="name"/> |
|||
<field name="method_type"/> |
|||
<field name="filename"/> |
|||
<field name="filepath"/> |
|||
</tree> |
|||
</field> |
|||
<field name="hide_login" invisible="1"/> |
|||
<field name="hide_password" invisible="1"/> |
|||
<field name="hide_port" invisible="1"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_location_tree" model="ir.ui.view"> |
|||
<field name="model">external.file.location</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="File Location"> |
|||
<field name="name" select="1"/> |
|||
<field name="protocol"/> |
|||
<field name="address"/> |
|||
<field name="login"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_location" model="ir.actions.act_window"> |
|||
<field name="name">File Locations</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="res_model">external.file.location</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_id" eval="False"/> |
|||
</record> |
|||
|
|||
<menuitem id="menu_ir_location" |
|||
parent="base.menu_automation" |
|||
sequence="20" |
|||
action="action_location"/> |
|||
|
|||
</data> |
|||
</openerp> |
|||
|
@ -0,0 +1,12 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
|
|||
<menuitem id="menu_file_exchange" |
|||
parent="base.menu_administration" |
|||
sequence="20" |
|||
name="File exchange" |
|||
/> |
|||
|
|||
</data> |
|||
</openerp> |
@ -0,0 +1,70 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<openerp> |
|||
<data> |
|||
<!-- © 2014-2016 Akretion (http://www.akretion.com) |
|||
# @ 2015 Valentin CHEMIERE @ Akretion |
|||
@author Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com> |
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> |
|||
<record id="view_task_form" model="ir.ui.view"> |
|||
<field name="model">external.file.task</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Tasks" version="7.0"> |
|||
<header> |
|||
<button name="run_import" type="object" string="Run" icon="gtk-execute" attrs="{'invisible': [('method_type', '!=', 'import')]}"/> |
|||
<button name="run_export" type="object" string="Run" icon="gtk-execute" attrs="{'invisible': [('method_type', '!=', 'export')]}"/> |
|||
</header> |
|||
<sheet> |
|||
<field name="method_type" invisible="1"/> |
|||
<group col="4"> |
|||
<div class="oe_title" style="width: 390px;" colspan="4"> |
|||
<label class="oe_edit_only" for="name" string="Name"/> |
|||
<h1><field name="name" class="oe_inline"/></h1> |
|||
</div> |
|||
<field name="method_type" colspan="2"/> |
|||
<span colspan="2"/> |
|||
<field name="filename" colspan="4" attrs="{'invisible':[('method_type','!=','import')], 'required':[('method_type', '=', 'import')]}"/> |
|||
<field name="filepath" colspan="4" /> |
|||
<field name="company_id" colspan="4"/> |
|||
</group> |
|||
<group col="6"> |
|||
<field name="after_import" attrs="{'invisible':[('method_type','!=','import')]}"/> |
|||
<group col="4" colspan="4" > |
|||
<field name="move_path" colspan="4" |
|||
attrs="{'invisible':['|', '&', |
|||
('after_import','!=','move'), |
|||
('after_import','!=','move_rename'), |
|||
('method_type','!=','import')]}"/> |
|||
<field name="new_name" colspan="4" |
|||
attrs="{'invisible': ['|', '&', |
|||
('after_import','!=','rename'), |
|||
('after_import','!=','move_rename'), |
|||
('method_type','!=','import')]}"/> |
|||
</group> |
|||
<field name="md5_check" colspan="2" |
|||
attrs="{'invisible': |
|||
[('method_type','!=','import')]}" |
|||
/> |
|||
<field name="active" colspan="2"/> |
|||
</group> |
|||
<group string="Data importation setting"> |
|||
<field name="file_type" attrs="{'invisible':[('method_type','!=','import')]}"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="view_task_tree" model="ir.ui.view"> |
|||
<field name="model">external.file.task</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Tasks" > |
|||
<field name="name" select="1"/> |
|||
<field name="method_type"/> |
|||
<field name="filename"/> |
|||
<field name="filepath"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
</data> |
|||
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue