diff --git a/attachment_queue/__manifest__.py b/attachment_queue/__manifest__.py index ece97f5a2..54b8225a5 100644 --- a/attachment_queue/__manifest__.py +++ b/attachment_queue/__manifest__.py @@ -2,27 +2,22 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). { - 'name': 'Attachment Queue', - 'version': '12.0.1.0.0', - 'author': 'Akretion,Odoo Community Association (OCA)', - 'summary': "Base module that add the concept of queue for processing file", - 'website': 'https://github.com/OCA/server-tools', - 'maintainers': ['florian-dacosta', 'sebastienbeau'], - 'license': 'AGPL-3', - 'category': 'Generic Modules', - 'depends': [ - 'base', - 'mail', + "name": "Attachment Queue", + "version": "12.0.1.0.0", + "author": "Akretion,Odoo Community Association (OCA)", + "summary": "Base module adding the concept of queue for processing file", + "website": "https://github.com/OCA/server-tools", + "maintainers": ["florian-dacosta", "sebastienbeau"], + "license": "AGPL-3", + "category": "Generic Modules", + "depends": ["base", "mail"], + "data": [ + "views/attachment_queue_view.xml", + "security/ir.model.access.csv", + "data/cron.xml", + "data/ir_config_parameter.xml", + "data/mail_template.xml", ], - 'data': [ - 'views/attachment_queue_view.xml', - 'security/ir.model.access.csv', - 'data/cron.xml', - 'data/ir_config_parameter.xml', - 'data/mail_template.xml', - ], - 'demo': [ - 'demo/attachment_queue_demo.xml' - ], - 'installable': True, + "demo": ["demo/attachment_queue_demo.xml"], + "installable": True, } diff --git a/attachment_queue/models/attachment_queue.py b/attachment_queue/models/attachment_queue.py index 72e057ced..4c058dac3 100644 --- a/attachment_queue/models/attachment_queue.py +++ b/attachment_queue/models/attachment_queue.py @@ -1,36 +1,42 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). import logging -from odoo import api, fields, models, registry +from odoo import api, fields, models, registry _logger = logging.getLogger(__name__) class AttachmentQueue(models.Model): - _name = 'attachment.queue' - _inherits = {'ir.attachment': 'attachment_id'} - _inherit = ['mail.thread'] + _name = "attachment.queue" + _inherits = {"ir.attachment": "attachment_id"} + _inherit = ["mail.thread"] attachment_id = fields.Many2one( - 'ir.attachment', required=True, ondelete='cascade', - help="Link to ir.attachment model ") + "ir.attachment", + required=True, + ondelete="cascade", + help="Link to ir.attachment model ", + ) file_type = fields.Selection( selection=[], help="The file type determines an import method to be used " - "to parse and transform data before their import in ERP or an export") + "to parse and transform data before their import in ERP or an export", + ) date_done = fields.Datetime() - state = fields.Selection([ - ('pending', 'Pending'), - ('failed', 'Failed'), - ('done', 'Done'), - ], readonly=False, required=True, default='pending') + state = fields.Selection( + [("pending", "Pending"), ("failed", "Failed"), ("done", "Done")], + readonly=False, + required=True, + default="pending", + ) state_message = fields.Text() failure_emails = fields.Char( - compute='_compute_failure_emails', + compute="_compute_failure_emails", string="Failure Emails", - help="list of email (separated by comma) which should be notified in " - "case of failure") + help="Comma-separated list of email addresses to be notified in case of" + "failure", + ) def _compute_failure_emails(self): for attach in self: @@ -44,10 +50,10 @@ class AttachmentQueue(models.Model): @api.model def run_attachment_queue_scheduler(self, domain=None): if domain is None: - domain = [('state', '=', 'pending')] + domain = [("state", "=", "pending")] batch_limit = self.env.ref( - 'attachment_queue.attachment_queue_cron_batch_limit') \ - .value + "attachment_queue.attachment_queue_cron_batch_limit" + ).value if batch_limit and batch_limit.isdigit(): limit = int(batch_limit) else: @@ -62,12 +68,14 @@ class AttachmentQueue(models.Model): Run the process for each attachment queue """ failure_tmpl = self.env.ref( - 'attachment_queue.attachment_failure_notification') + "attachment_queue.attachment_failure_notification" + ) for attachment in self: with api.Environment.manage(): with registry(self.env.cr.dbname).cursor() as new_cr: new_env = api.Environment( - new_cr, self.env.uid, self.env.context) + new_cr, self.env.uid, self.env.context + ) attach = attachment.with_env(new_env) try: attach._run() @@ -75,32 +83,29 @@ class AttachmentQueue(models.Model): except Exception as e: attach.env.cr.rollback() _logger.exception(str(e)) - attach.write({ - 'state': 'failed', - 'state_message': str(e), - }) + attach.write( + {"state": "failed", "state_message": str(e)} + ) emails = attach.failure_emails if emails: failure_tmpl.send_mail(attach.id) attach.env.cr.commit() else: vals = { - 'state': 'done', - 'date_done': fields.Datetime.now(), + "state": "done", + "date_done": fields.Datetime.now(), } attach.write(vals) attach.env.cr.commit() return True - @api.multi def _run(self): self.ensure_one() - _logger.info('Start to process attachment queue id %d', self.id) + _logger.info("Starting processing of attachment queue id %d", self.id) - @api.multi def set_done(self): """ Manually set to done """ message = "Manually set to done by %s" % self.env.user.name - self.write({'state_message': message, 'state': 'done'}) + self.write({"state_message": message, "state": "done"}) diff --git a/attachment_queue/readme/DESCRIPTION.rst b/attachment_queue/readme/DESCRIPTION.rst index a5e20daee..57bac75fd 100644 --- a/attachment_queue/readme/DESCRIPTION.rst +++ b/attachment_queue/readme/DESCRIPTION.rst @@ -1,5 +1,3 @@ -This module implement a queue for processing file. -File are stored in Odoo standard ir.attachment. -The attachments will be processed depending on their type. +This module adds async processing capabilities to attachments by implementing a new model attachment.queue that wraps attachments and stores additional information so that it can be processed in an asynchronous way. -An example of the use of this module, can be found in the module `attachment_synchronize`. +A use case of this module can be found in the attachment_synchronize module. diff --git a/attachment_queue/readme/USAGE.rst b/attachment_queue/readme/USAGE.rst index ec276d247..a97a271e5 100644 --- a/attachment_queue/readme/USAGE.rst +++ b/attachment_queue/readme/USAGE.rst @@ -6,3 +6,12 @@ Configure the batch limit for attachments that can be sync by the cron task at a Settings > Technical > System parameters > attachment_queue_cron_batch_limit + +image:: ../static/description/tree.png + + +This module can be used in combination with attachment_synchronize to control file processing workflow + + +image:: ../static/description/form.png + diff --git a/attachment_queue/static/description/form.png b/attachment_queue/static/description/form.png new file mode 100644 index 000000000..fbc9f6aa6 Binary files /dev/null and b/attachment_queue/static/description/form.png differ diff --git a/attachment_queue/static/description/tree.png b/attachment_queue/static/description/tree.png new file mode 100644 index 000000000..d4dcc92fe Binary files /dev/null and b/attachment_queue/static/description/tree.png differ diff --git a/attachment_queue/tests/test_attachment_queue.py b/attachment_queue/tests/test_attachment_queue.py index fc29f902f..74d368f2b 100644 --- a/attachment_queue/tests/test_attachment_queue.py +++ b/attachment_queue/tests/test_attachment_queue.py @@ -1,18 +1,20 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo.tests.common import TransactionCase import odoo from odoo import api +from odoo.tests.common import TransactionCase class TestAttachmentBaseQueue(TransactionCase): - def setUp(self): super().setUp() self.registry.enter_test_mode(self.env.cr) - self.env = api.Environment(self.registry.test_cr, self.env.uid, - self.env.context) - self.attachment = self.env.ref('attachment_queue.attachment_queue_demo') + self.env = api.Environment( + self.registry.test_cr, self.env.uid, self.env.context + ) + self.attachment = self.env.ref( + "attachment_queue.attachment_queue_demo" + ) def tearDown(self): self.registry.leave_test_mode() @@ -21,30 +23,17 @@ class TestAttachmentBaseQueue(TransactionCase): def test_attachment_queue(self): """Test run_attachment_queue_scheduler to ensure set state to done """ - self.assertEqual( - self.attachment.state, - 'pending' - ) - self.env['attachment.queue'].run_attachment_queue_scheduler() + self.assertEqual(self.attachment.state, "pending") + self.env["attachment.queue"].run_attachment_queue_scheduler() self.env.cache.invalidate() with odoo.registry(self.env.cr.dbname).cursor() as new_cr: - new_env = api.Environment( - new_cr, self.env.uid, self.env.context) + new_env = api.Environment(new_cr, self.env.uid, self.env.context) attach = self.attachment.with_env(new_env) - self.assertEqual( - attach.state, - 'done' - ) + self.assertEqual(attach.state, "done") def test_set_done(self): """Test set_done manually """ - self.assertEqual( - self.attachment.state, - 'pending' - ) + self.assertEqual(self.attachment.state, "pending") self.attachment.set_done() - self.assertEqual( - self.attachment.state, - 'done' - ) + self.assertEqual(self.attachment.state, "done") diff --git a/attachment_queue/views/attachment_queue_view.xml b/attachment_queue/views/attachment_queue_view.xml index f8bc7c9d3..f83f60a72 100644 --- a/attachment_queue/views/attachment_queue_view.xml +++ b/attachment_queue/views/attachment_queue_view.xml @@ -63,10 +63,10 @@ - - - - + + + +