Browse Source
[WIP] Use pattern in file name & add move and rename file option
[WIP] Use pattern in file name & add move and rename file option
[WIP] use jinja to render new file name based on simple template [FIX] bug move and rename file option [ADD] add file type on task [FIX] add file type in attachemnt create method [WIP] test rename file [WIP] inherit view from attachment_metadata [FIX] bug of inherit view and menu from attachment_metadata [IMP] add move & rename test to test_sftp [IMP] move file location menu inside automation menu and rename it [IMP] add ir.model.access manager rule [FIX] typing mistake [FIX] access file store without login/password [IMP] reorganize task form view [FIX] api.multi in task run method [FIX] OCA guidelines [FIX] add authors and contributors [FIX] fix pylint [FIX] add oca_dependencies & fixe oca version format [FIX] fix pylint & oca_dependencies [FIX] fix views path [FIX] set application to False12.0-mig-module_prototyper_last
Mourad El Hadj Mimoune
9 years ago
committed by
David Beal
20 changed files with 365 additions and 225 deletions
-
5external_file_location/README.rst
-
4external_file_location/__init__.py
-
20external_file_location/__openerp__.py
-
99external_file_location/attachment_view.xml
-
0external_file_location/data/cron.xml
-
3external_file_location/models/__init__.py
-
0external_file_location/models/attachment.py
-
0external_file_location/models/helper.py
-
2external_file_location/models/location.py
-
115external_file_location/models/task.py
-
2external_file_location/security/ir.model.access.csv
-
86external_file_location/task.py
-
94external_file_location/tasks/abstract_fs.py
-
3external_file_location/tasks/abstract_task.py
-
2external_file_location/tasks/sftp.py
-
69external_file_location/tests/test_sftp.py
-
50external_file_location/views/attachment_view.xml
-
6external_file_location/views/location_view.xml
-
0external_file_location/views/menu.xml
-
30external_file_location/views/task_view.xml
@ -1,5 +1,3 @@ |
|||||
from . import attachment |
|
||||
from . import location |
|
||||
from . import task |
|
||||
|
from . import models |
||||
from . import tasks |
from . import tasks |
||||
from . import tests |
from . import tests |
@ -1,99 +0,0 @@ |
|||||
<?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_metadata.view_attachment_improved_form" /> |
|
||||
<field name="arch" type="xml"> |
|
||||
<field name="url" position="after"> |
|
||||
<field name="sync_date"/> |
|
||||
<field name="state"/> |
|
||||
<field name="state_message"/> |
|
||||
<field name="task_id"/> |
|
||||
<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="arch" type="xml"> |
|
||||
<tree string="Attachments" > |
|
||||
<field name="name"/> |
|
||||
<field name="datas_fname"/> |
|
||||
<field name="task_id"/> |
|
||||
<field name="location_id"/> |
|
||||
<field name="type"/> |
|
||||
<field name="create_date"/> |
|
||||
<field name="state"/> |
|
||||
</tree> |
|
||||
</field> |
|
||||
</record> |
|
||||
|
|
||||
<record id="view_external_attachment_search" model="ir.ui.view"> |
|
||||
<field name="model">ir.attachment.metadata</field> |
|
||||
<field name="arch" type="xml"> |
|
||||
<search string="Attachments"> |
|
||||
<field name="name" filter_domain="['|', ('name','ilike',self), ('datas_fname','ilike',self)]" string="Attachment"/> |
|
||||
<field name="create_date"/> |
|
||||
<filter icon="terp-stage" |
|
||||
string="URL" |
|
||||
domain="[('type','=','url')]"/> |
|
||||
<filter icon="terp-stock_align_left_24" |
|
||||
string="Binary" |
|
||||
domain="[('type','=','binary')]"/> |
|
||||
<separator/> |
|
||||
<filter name="my_documents_filter" |
|
||||
string="My Document(s)" |
|
||||
icon="terp-personal" |
|
||||
domain="[('create_uid','=',uid)]" |
|
||||
help="Filter on my documents"/> |
|
||||
<field name="create_uid"/> |
|
||||
<field name="type"/> |
|
||||
<filter string="Pending" domain="[('state', '=', 'pending')]"/> |
|
||||
<filter string="Failed" domain="[('state', '=', 'failed')]"/> |
|
||||
<filter string="Done" domain="[('state', '=', 'done')]"/> |
|
||||
<group expand="0" string="Group By"> |
|
||||
<filter string="Owner" icon="terp-personal" domain="[]" context="{'group_by':'create_uid'}"/> |
|
||||
<filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'type'}" groups="base.group_no_one"/> |
|
||||
<filter string="Company" icon="terp-gtk-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/> |
|
||||
<filter string="Creation Month" icon="terp-go-month" domain="[]" context="{'group_by':'create_date'}"/> |
|
||||
<filter string="State" domain="[]" context="{'group_by': 'state'}"/> |
|
||||
</group> |
|
||||
</search> |
|
||||
</field> |
|
||||
</record> |
|
||||
|
|
||||
<record id="action_attachment" model="ir.actions.act_window"> |
|
||||
<field name="name">Attachments</field> |
|
||||
<field name="type">ir.actions.act_window</field> |
|
||||
<field name="res_model">ir.attachment.metadata</field> |
|
||||
<field name="view_type">form</field> |
|
||||
<field name="view_mode">tree,form</field> |
|
||||
<field name="view_id" eval="False"/> |
|
||||
<!-- <field name="domain">[('task_id', '!=', False)]</field> --> |
|
||||
<field name="search_view_id" ref="view_external_attachment_search"/> |
|
||||
</record> |
|
||||
|
|
||||
<record id="ir_attachment_view2" model="ir.actions.act_window.view"> |
|
||||
<field eval="10" name="sequence"/> |
|
||||
<field name="view_mode">tree</field> |
|
||||
<field name="view_id" ref="view_external_attachment_tree"/> |
|
||||
<field name="act_window_id" ref="action_attachment"/> |
|
||||
</record> |
|
||||
|
|
||||
<record id="ir_attachment_view3" model="ir.actions.act_window.view"> |
|
||||
<field eval="10" name="sequence"/> |
|
||||
<field name="view_mode">form</field> |
|
||||
<field name="view_id" ref="view_attachment_improved_form"/> |
|
||||
<field name="act_window_id" ref="action_attachment"/> |
|
||||
</record> |
|
||||
|
|
||||
<menuitem id="menu_ir_attachment" |
|
||||
parent="menu_file_exchange" |
|
||||
sequence="20" |
|
||||
action="action_attachment"/> |
|
||||
|
|
||||
</data> |
|
||||
</openerp> |
|
@ -0,0 +1,3 @@ |
|||||
|
from . import attachment |
||||
|
from . import location |
||||
|
from . import task |
@ -0,0 +1,115 @@ |
|||||
|
# 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 |
||||
|
from .helper import itersubclasses, get_erp_module, is_module_installed |
||||
|
from ..tasks.abstract_task import AbstractTask |
||||
|
|
||||
|
|
||||
|
class Task(models.Model): |
||||
|
_name = 'external.file.task' |
||||
|
_description = 'External file task' |
||||
|
|
||||
|
name = fields.Char(required=True) |
||||
|
method = fields.Selection(selection='_get_method', required=True, |
||||
|
help='procotol and trasmitting info') |
||||
|
method_type = fields.Char() |
||||
|
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 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') |
||||
|
file_type = fields.Selection( |
||||
|
selection="_get_file_type", |
||||
|
string="File type", |
||||
|
help="The file type determines an import method to be used " |
||||
|
"to parse and transform data before their import in ERP") |
||||
|
|
||||
|
def _get_action(self): |
||||
|
return [('rename', 'Rename'), |
||||
|
('move', 'Move'), |
||||
|
('move_rename', 'Move & Rename'), |
||||
|
('delete', 'Delete'), |
||||
|
] |
||||
|
|
||||
|
def _get_file_type(self): |
||||
|
"""This is the method to be inherited for adding file types |
||||
|
The basic import do not apply any parsing or transform of the file. |
||||
|
The file is just added as an attachement |
||||
|
""" |
||||
|
return [('basic_import', 'Basic import')] |
||||
|
|
||||
|
def _get_method(self): |
||||
|
res = [] |
||||
|
for cls in itersubclasses(AbstractTask): |
||||
|
if not is_module_installed(self.env, get_erp_module(cls)): |
||||
|
continue |
||||
|
if cls._synchronize_type and ( |
||||
|
'protocol' not in self._context or |
||||
|
cls._key == self._context['protocol']): |
||||
|
cls_info = (cls._key + '_' + cls._synchronize_type, |
||||
|
cls._name + ' ' + cls._synchronize_type) |
||||
|
res.append(cls_info) |
||||
|
return res |
||||
|
|
||||
|
@api.onchange('method') |
||||
|
def onchange_method(self): |
||||
|
if self.method: |
||||
|
if 'import' in self.method: |
||||
|
self.method_type = 'import' |
||||
|
elif 'export' in self.method: |
||||
|
self.method_type = 'export' |
||||
|
|
||||
|
@api.model |
||||
|
def _run(self, domain=None): |
||||
|
if not domain: |
||||
|
domain = [] |
||||
|
tasks = self.env['external.file.task'].search(domain) |
||||
|
tasks.run() |
||||
|
|
||||
|
@api.multi |
||||
|
def run(self): |
||||
|
for tsk in self: |
||||
|
for cls in itersubclasses(AbstractTask): |
||||
|
if not is_module_installed(self.env, get_erp_module(cls)): |
||||
|
continue |
||||
|
cls_build = '%s_%s' % (cls._key, cls._synchronize_type) |
||||
|
if cls._synchronize_type and cls_build == tsk.method: |
||||
|
method_class = cls |
||||
|
config = { |
||||
|
'host': tsk.location_id.address, |
||||
|
# ftplib does not support unicode |
||||
|
'user': tsk.location_id.login and\ |
||||
|
tsk.location_id.login.encode('utf-8'), |
||||
|
'pwd': tsk.location_id.password and \ |
||||
|
tsk.location_id.password.encode('utf-8'), |
||||
|
'port': tsk.location_id.port, |
||||
|
'allow_dir_creation': False, |
||||
|
'file_name': tsk.filename, |
||||
|
'path': tsk.filepath, |
||||
|
'attachment_ids': tsk.attachment_ids, |
||||
|
'task': tsk, |
||||
|
'move_path': tsk.move_path, |
||||
|
'new_name': tsk.new_name, |
||||
|
'after_import': tsk.after_import, |
||||
|
'file_type': tsk.file_type, |
||||
|
'md5_check': tsk.md5_check, |
||||
|
} |
||||
|
conn = method_class(self.env, config) |
||||
|
conn.run() |
@ -1,3 +1,5 @@ |
|||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
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_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 |
access_external_file_task_user,external.file.task.user,model_external_file_task,base.group_user,1,0,0,0 |
@ -1,86 +0,0 @@ |
|||||
# 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 .helper import itersubclasses, get_erp_module, is_module_installed |
|
||||
from .abstract_task import AbstractTask |
|
||||
|
|
||||
|
|
||||
class Task(models.Model): |
|
||||
_name = 'external.file.task' |
|
||||
_description = 'Description' |
|
||||
|
|
||||
name = fields.Char(required=True) |
|
||||
method = fields.Selection(selection='_get_method', required=True, |
|
||||
help='procotol and trasmitting info') |
|
||||
method_type = fields.Char() |
|
||||
filename = fields.Char(help='File name which is imported') |
|
||||
filepath = fields.Char(help='Path to imported 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') |
|
||||
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') |
|
||||
|
|
||||
def _get_action(self): |
|
||||
return [('move', 'Move'), ('delete', 'Delete')] |
|
||||
|
|
||||
def _get_method(self): |
|
||||
res = [] |
|
||||
for cls in itersubclasses(AbstractTask): |
|
||||
if not is_module_installed(self.env, get_erp_module(cls)): |
|
||||
continue |
|
||||
if cls._synchronize_type and ( |
|
||||
'protocol' not in self._context or |
|
||||
cls._key == self._context['protocol']): |
|
||||
cls_info = (cls._key + '_' + cls._synchronize_type, |
|
||||
cls._name + ' ' + cls._synchronize_type) |
|
||||
res.append(cls_info) |
|
||||
return res |
|
||||
|
|
||||
@api.onchange('method') |
|
||||
def onchange_method(self): |
|
||||
if self.method: |
|
||||
if 'import' in self.method: |
|
||||
self.method_type = 'import' |
|
||||
elif 'export' in self.method: |
|
||||
self.method_type = 'export' |
|
||||
|
|
||||
@api.model |
|
||||
def _run(self, domain=None): |
|
||||
if not domain: |
|
||||
domain = [] |
|
||||
tasks = self.env['external.file.task'].search(domain) |
|
||||
tasks.run() |
|
||||
|
|
||||
@api.one |
|
||||
def run(self): |
|
||||
for cls in itersubclasses(AbstractTask): |
|
||||
if not is_module_installed(self.env, get_erp_module(cls)): |
|
||||
continue |
|
||||
cls_build = '%s_%s' % (cls._key, cls._synchronize_type) |
|
||||
if cls._synchronize_type and cls_build == self.method: |
|
||||
method_class = cls |
|
||||
config = { |
|
||||
'host': self.location_id.address, |
|
||||
# ftplib does not support unicode |
|
||||
'user': self.location_id.login.encode('utf-8'), |
|
||||
'pwd': self.location_id.password.encode('utf-8'), |
|
||||
'port': self.location_id.port, |
|
||||
'allow_dir_creation': False, |
|
||||
'file_name': self.filename, |
|
||||
'path': self.filepath, |
|
||||
'attachment_ids': self.attachment_ids, |
|
||||
'task': self, |
|
||||
'move_path': self.move_path, |
|
||||
'after_import': self.after_import, |
|
||||
'md5_check': self.md5_check, |
|
||||
} |
|
||||
conn = method_class(self.env, config) |
|
||||
conn.run() |
|
@ -0,0 +1,50 @@ |
|||||
|
<?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_metadata.view_attachment_improved_form" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="url" position="after"> |
||||
|
<field name="sync_date"/> |
||||
|
<field name="state"/> |
||||
|
<field name="state_message"/> |
||||
|
<field name="task_id"/> |
||||
|
<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_metadata.view_external_attachment_tree" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="file_type" position="after"> |
||||
|
<field name="task_id"/> |
||||
|
<field name="location_id"/> |
||||
|
<field name="type"/> |
||||
|
<field name="create_date"/> |
||||
|
<field name="state"/> |
||||
|
</field> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="view_external_attachment_search" model="ir.ui.view"> |
||||
|
<field name="model">ir.attachment.metadata</field> |
||||
|
<field name="inherit_id" ref="attachment_metadata.view_external_attachment_search" /> |
||||
|
<field name="arch" type="xml"> |
||||
|
<field name="type" position="after"> |
||||
|
<filter string="Pending" domain="[('state', '=', 'pending')]"/> |
||||
|
<filter string="Failed" domain="[('state', '=', 'failed')]"/> |
||||
|
<filter string="Done" domain="[('state', '=', 'done')]"/> |
||||
|
</field> |
||||
|
<filter string="Creation Month" position="after"> |
||||
|
<filter string="State" domain="[]" |
||||
|
context="{'group_by': 'state'}"/> |
||||
|
</filter> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</data> |
||||
|
</openerp> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue