[REF] apply black on the code

pull/2560/head
Sébastien BEAU 2020-05-11 14:45:56 +02:00 committed by Florian da Costa
parent 8d469681fd
commit 68bbb49fec
8 changed files with 80 additions and 84 deletions

View File

@ -2,27 +2,22 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{ {
'name': 'Attachment Queue', "name": "Attachment Queue",
'version': '12.0.1.0.0', "version": "12.0.1.0.0",
'author': 'Akretion,Odoo Community Association (OCA)', "author": "Akretion,Odoo Community Association (OCA)",
'summary': "Base module that add the concept of queue for processing file", "summary": "Base module adding the concept of queue for processing file",
'website': 'https://github.com/OCA/server-tools', "website": "https://github.com/OCA/server-tools",
'maintainers': ['florian-dacosta', 'sebastienbeau'], "maintainers": ["florian-dacosta", "sebastienbeau"],
'license': 'AGPL-3', "license": "AGPL-3",
'category': 'Generic Modules', "category": "Generic Modules",
'depends': [ "depends": ["base", "mail"],
'base', "data": [
'mail', "views/attachment_queue_view.xml",
"security/ir.model.access.csv",
"data/cron.xml",
"data/ir_config_parameter.xml",
"data/mail_template.xml",
], ],
'data': [ "demo": ["demo/attachment_queue_demo.xml"],
'views/attachment_queue_view.xml', "installable": True,
'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,
} }

View File

@ -1,36 +1,42 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging import logging
from odoo import api, fields, models, registry
from odoo import api, fields, models, registry
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
class AttachmentQueue(models.Model): class AttachmentQueue(models.Model):
_name = 'attachment.queue' _name = "attachment.queue"
_inherits = {'ir.attachment': 'attachment_id'} _inherits = {"ir.attachment": "attachment_id"}
_inherit = ['mail.thread'] _inherit = ["mail.thread"]
attachment_id = fields.Many2one( attachment_id = fields.Many2one(
'ir.attachment', required=True, ondelete='cascade', "ir.attachment",
help="Link to ir.attachment model ") required=True,
ondelete="cascade",
help="Link to ir.attachment model ",
)
file_type = fields.Selection( file_type = fields.Selection(
selection=[], selection=[],
help="The file type determines an import method to be used " 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() date_done = fields.Datetime()
state = fields.Selection([ state = fields.Selection(
('pending', 'Pending'), [("pending", "Pending"), ("failed", "Failed"), ("done", "Done")],
('failed', 'Failed'), readonly=False,
('done', 'Done'), required=True,
], readonly=False, required=True, default='pending') default="pending",
)
state_message = fields.Text() state_message = fields.Text()
failure_emails = fields.Char( failure_emails = fields.Char(
compute='_compute_failure_emails', compute="_compute_failure_emails",
string="Failure Emails", string="Failure Emails",
help="list of email (separated by comma) which should be notified in " help="Comma-separated list of email addresses to be notified in case of"
"case of failure") "failure",
)
def _compute_failure_emails(self): def _compute_failure_emails(self):
for attach in self: for attach in self:
@ -44,10 +50,10 @@ class AttachmentQueue(models.Model):
@api.model @api.model
def run_attachment_queue_scheduler(self, domain=None): def run_attachment_queue_scheduler(self, domain=None):
if domain is None: if domain is None:
domain = [('state', '=', 'pending')] domain = [("state", "=", "pending")]
batch_limit = self.env.ref( batch_limit = self.env.ref(
'attachment_queue.attachment_queue_cron_batch_limit') \ "attachment_queue.attachment_queue_cron_batch_limit"
.value ).value
if batch_limit and batch_limit.isdigit(): if batch_limit and batch_limit.isdigit():
limit = int(batch_limit) limit = int(batch_limit)
else: else:
@ -62,12 +68,14 @@ class AttachmentQueue(models.Model):
Run the process for each attachment queue Run the process for each attachment queue
""" """
failure_tmpl = self.env.ref( failure_tmpl = self.env.ref(
'attachment_queue.attachment_failure_notification') "attachment_queue.attachment_failure_notification"
)
for attachment in self: for attachment in self:
with api.Environment.manage(): with api.Environment.manage():
with registry(self.env.cr.dbname).cursor() as new_cr: with registry(self.env.cr.dbname).cursor() as new_cr:
new_env = api.Environment( 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) attach = attachment.with_env(new_env)
try: try:
attach._run() attach._run()
@ -75,32 +83,29 @@ class AttachmentQueue(models.Model):
except Exception as e: except Exception as e:
attach.env.cr.rollback() attach.env.cr.rollback()
_logger.exception(str(e)) _logger.exception(str(e))
attach.write({ attach.write(
'state': 'failed', {"state": "failed", "state_message": str(e)}
'state_message': str(e), )
})
emails = attach.failure_emails emails = attach.failure_emails
if emails: if emails:
failure_tmpl.send_mail(attach.id) failure_tmpl.send_mail(attach.id)
attach.env.cr.commit() attach.env.cr.commit()
else: else:
vals = { vals = {
'state': 'done', "state": "done",
'date_done': fields.Datetime.now(), "date_done": fields.Datetime.now(),
} }
attach.write(vals) attach.write(vals)
attach.env.cr.commit() attach.env.cr.commit()
return True return True
@api.multi
def _run(self): def _run(self):
self.ensure_one() 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): def set_done(self):
""" """
Manually set to done Manually set to done
""" """
message = "Manually set to done by %s" % self.env.user.name 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"})

View File

@ -1,5 +1,3 @@
This module implement a queue for processing file. 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.
File are stored in Odoo standard ir.attachment.
The attachments will be processed depending on their type.
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.

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -1,18 +1,20 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
import odoo import odoo
from odoo import api from odoo import api
from odoo.tests.common import TransactionCase
class TestAttachmentBaseQueue(TransactionCase): class TestAttachmentBaseQueue(TransactionCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.registry.enter_test_mode(self.env.cr) self.registry.enter_test_mode(self.env.cr)
self.env = api.Environment(self.registry.test_cr, self.env.uid, self.env = api.Environment(
self.env.context) self.registry.test_cr, self.env.uid, self.env.context
self.attachment = self.env.ref('attachment_queue.attachment_queue_demo') )
self.attachment = self.env.ref(
"attachment_queue.attachment_queue_demo"
)
def tearDown(self): def tearDown(self):
self.registry.leave_test_mode() self.registry.leave_test_mode()
@ -21,30 +23,17 @@ class TestAttachmentBaseQueue(TransactionCase):
def test_attachment_queue(self): def test_attachment_queue(self):
"""Test run_attachment_queue_scheduler to ensure set state to done """Test run_attachment_queue_scheduler to ensure set state to done
""" """
self.assertEqual( self.assertEqual(self.attachment.state, "pending")
self.attachment.state, self.env["attachment.queue"].run_attachment_queue_scheduler()
'pending'
)
self.env['attachment.queue'].run_attachment_queue_scheduler()
self.env.cache.invalidate() self.env.cache.invalidate()
with odoo.registry(self.env.cr.dbname).cursor() as new_cr: with odoo.registry(self.env.cr.dbname).cursor() as new_cr:
new_env = api.Environment( new_env = api.Environment(new_cr, self.env.uid, self.env.context)
new_cr, self.env.uid, self.env.context)
attach = self.attachment.with_env(new_env) attach = self.attachment.with_env(new_env)
self.assertEqual( self.assertEqual(attach.state, "done")
attach.state,
'done'
)
def test_set_done(self): def test_set_done(self):
"""Test set_done manually """Test set_done manually
""" """
self.assertEqual( self.assertEqual(self.attachment.state, "pending")
self.attachment.state,
'pending'
)
self.attachment.set_done() self.attachment.set_done()
self.assertEqual( self.assertEqual(self.attachment.state, "done")
self.attachment.state,
'done'
)

View File

@ -63,10 +63,10 @@
<filter string="Failed" name="failed" domain="[('state', '=', 'failed')]"/> <filter string="Failed" name="failed" domain="[('state', '=', 'failed')]"/>
<filter string="Done" name="done" domain="[('state', '=', 'done')]"/> <filter string="Done" name="done" domain="[('state', '=', 'done')]"/>
<group expand="0" string="Group By"> <group expand="0" string="Group By">
<filter string="Owner" name="owner" icon="terp-personal" domain="[]" context="{'group_by':'create_uid'}"/> <filter string="Owner" name="owner" domain="[]" context="{'group_by':'create_uid'}"/>
<filter string="Type" name="type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'type'}" groups="base.group_no_one"/> <filter string="Type" name="type" domain="[]" context="{'group_by':'type'}" groups="base.group_no_one"/>
<filter string="Company" name="company" icon="terp-gtk-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/> <filter string="Company" name="company" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
<filter string="Creation Month" name="creation_month" icon="terp-go-month" domain="[]" context="{'group_by':'create_date'}"/> <filter string="Creation Month" name="creation_month" domain="[]" context="{'group_by':'create_date'}"/>
<filter string="State" name="state" domain="[]" context="{'group_by': 'state'}"/> <filter string="State" name="state" domain="[]" context="{'group_by': 'state'}"/>
<filter string="File type" name="file_type" domain="[]" context="{'group_by': 'file_type'}"/> <filter string="File type" name="file_type" domain="[]" context="{'group_by': 'file_type'}"/>
</group> </group>