diff --git a/external_file_location/__init__.py b/external_file_location/__init__.py new file mode 100644 index 00000000..258d23ad --- /dev/null +++ b/external_file_location/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Module for OpenERP +# Copyright (C) 2014 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################### + +from . import attachment +from . import location +from . import task +from . import tasks + diff --git a/external_file_location/__openerp__.py b/external_file_location/__openerp__.py new file mode 100644 index 00000000..04c1063f --- /dev/null +++ b/external_file_location/__openerp__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Module for OpenERP +# Copyright (C) 2015 Akretion (http://www.akretion.com). +# @author Valentin CHEMIERE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################### + +{ + 'name': 'external_file_location', + 'version': '0.0.1', + 'author': 'Akretion', + 'website': 'www.akretion.com', + 'license': 'AGPL-3', + 'category': 'Generic Modules', + 'description': """ + File exchange system with multiple protocol (SFTP, FTP, Filestore) + """, + 'depends': [ + 'base', + 'ir_attachment_metadata', + ], + 'data': [ + 'attachment_view.xml', + 'menu.xml', + 'location_view.xml', + 'task_view.xml', + 'cron.xml', + ], + 'installable': True, + 'application': True, +} diff --git a/external_file_location/abstract_task.py b/external_file_location/abstract_task.py new file mode 100755 index 00000000..c9397318 --- /dev/null +++ b/external_file_location/abstract_task.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from base64 import b64encode + + +class AbstractTask(object): + + def create_file(self, filename, data): + ir_attachment_id = self.env['ir.attachment'].create( + { + 'name': filename, + 'datas': b64encode(data), + 'datas_fname': filename, + 'task_id': self.task.id, + 'location_id': self.task.location_id.id, + 'external_hash': self.ext_hash + } + ) + return ir_attachment_id diff --git a/external_file_location/attachment.py b/external_file_location/attachment.py new file mode 100644 index 00000000..410da1db --- /dev/null +++ b/external_file_location/attachment.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Module for OpenERP +# Copyright (C) 2014 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################### + +from openerp import models, fields + + +class IrAttachment(models.Model): + _inherit = 'ir.attachment' + + sync_date = fields.Datetime() + state = fields.Selection([ + ('pending', 'Pending'), + ('failed', 'Failed'), + ('done', 'Done'), + ], readonly=False, required=True, default='pending') + state_message = fields.Text() + 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 + ) diff --git a/external_file_location/attachment_view.xml b/external_file_location/attachment_view.xml new file mode 100644 index 00000000..d545c346 --- /dev/null +++ b/external_file_location/attachment_view.xml @@ -0,0 +1,99 @@ + + + + + + ir.attachment + + + + + + + + + + + + + + ir.attachment + + + + + + + + + + + + + + + ir.attachment + + + + + + + + + + + + + + + + + + + + + + + + + + Attachments + ir.actions.act_window + ir.attachment + form + kanban,tree,form + + [('task_id', '!=', False)] + + + + + + kanban + + + + + + + tree + + + + + + + + diff --git a/external_file_location/cron.xml b/external_file_location/cron.xml new file mode 100644 index 00000000..a18f5f6a --- /dev/null +++ b/external_file_location/cron.xml @@ -0,0 +1,18 @@ + + + + + + Run file exchange tasks + 30 + minutes + -1 + True + + external.file.task + _run + ([]) + + + + diff --git a/external_file_location/helper.py b/external_file_location/helper.py new file mode 100644 index 00000000..3e0b93a6 --- /dev/null +++ b/external_file_location/helper.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Author: Joel Grand-Guillaume +# Copyright 2011-2012 Camptocamp SA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +def itersubclasses(cls, _seen=None): + """ + itersubclasses(cls) + Generator over all subclasses of a given class, in depth first order. + >>> list(itersubclasses(int)) == [bool] + True + >>> class A(object): pass + >>> class B(A): pass + >>> class C(A): pass + >>> class D(B,C): pass + >>> class E(D): pass + >>> + >>> for cls in itersubclasses(A): + ... print(cls.__name__) + B + D + E + C + >>> # get ALL (new-style) classes currently defined + >>> [cls.__name__ for cls in itersubclasses(object)] #doctest: +ELLIPSIS + ['type', ...'tuple', ...] + """ + #import pdb; pdb.set_trace() + if not isinstance(cls, type): + raise TypeError('itersubclasses must be called with ' + 'new-style classes, not %.100r' % cls + ) + if _seen is None: + _seen = set() + try: + subs = cls.__subclasses__() + except TypeError: # fails only when cls is type + subs = cls.__subclasses__(cls) + for sub in subs: + if sub not in _seen: + _seen.add(sub) + yield sub + for sub in itersubclasses(sub, _seen): + yield sub diff --git a/external_file_location/location.py b/external_file_location/location.py new file mode 100644 index 00000000..8d26e462 --- /dev/null +++ b/external_file_location/location.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Module for OpenERP +# Copyright (C) 2015 Akretion (http://www.akretion.com). +# @author Valentin CHEMIERE +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################### + +from openerp import models, fields +from abstract_task import AbstractTask +from helper import itersubclasses + +class Location(models.Model): + _name = 'external.file.location' + _description = 'Description' + + name = fields.Char(string='Name') + protocol = fields.Selection(selection='_get_protocol') + address = fields.Char(string='Address') + port = fields.Integer() + login = fields.Char() + password = fields.Char() + task_ids = fields.One2many('external.file.task', 'location_id') + + + def _get_protocol(self): + res = [] + for cls in itersubclasses(AbstractTask): + if not cls._synchronize_type: + cls_info = (cls._key, cls._name) + res.append(cls_info) + return res + diff --git a/external_file_location/location_view.xml b/external_file_location/location_view.xml new file mode 100644 index 00000000..da11c6d6 --- /dev/null +++ b/external_file_location/location_view.xml @@ -0,0 +1,64 @@ + + + + + + external.file.location + +
+ + +
+
+ + + + + + + + + + + + + + +