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
-
18external_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 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 |
|||
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 |
@ -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