[REF] Rename to attachement_queue

pull/2560/head
Sébastien BEAU 2020-05-11 14:41:08 +02:00 committed by Florian da Costa
parent a35eb5ef07
commit 8d469681fd
16 changed files with 364 additions and 0 deletions

View File

@ -0,0 +1 @@
from . import models

View File

@ -0,0 +1,28 @@
# Copyright 2015 Florian DA COSTA @ Akretion
# 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',
],
'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,
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo noupdate="1">
<record model="ir.cron" id="cronjob_run_attachment_queue">
<field name='name'>Run Attachments Queue</field>
<field name='interval_number'>30</field>
<field name='interval_type'>minutes</field>
<field name="numbercall">-1</field>
<field name="active">False</field>
<field name="doall" eval="False" />
<field name="model_id" ref="model_attachment_queue"/>
<field name="state">code</field>
<field name="code">model.run_attachment_queue_scheduler()</field>
</record>
</odoo>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="attachment_queue_cron_batch_limit" model="ir.config_parameter">
<field name="key">attachment_queue_cron_batch_limit</field>
<field name="value">200</field>
</record>
</odoo>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="attachment_failure_notification" model="mail.template">
<field name="email_to">${object.failure_emails}</field>
<field name="name">Attachment Failure notification</field>
<field name="subject">The attachment ${object.name} has failed</field>
<field name="model_id" ref="attachment_queue.model_attachment_queue"/>
<field name="body_html"><![CDATA[
<p style="margin:0px 0px 10px 0px;font-size:13px;font-family:&quot;Lucida Grande&quot;, Helvetica, Verdana, Arial, sans-serif;">Hello,<br><br></p>
<p style="margin:0px 0px 10px 0px;font-size:13px;font-family:&quot;Lucida Grande&quot;, Helvetica, Verdana, Arial, sans-serif;">The attachment ${object.name} has failed with the following error message : <br>${object.state_message}<br></p><p style="margin:0px 0px 10px 0px;font-size:13px;font-family:&quot;Lucida Grande&quot;, Helvetica, Verdana, Arial, sans-serif;"></p>
<p style="margin:0px 0px 10px 0px;font-size:13px;font-family:&quot;Lucida Grande&quot;, Helvetica, Verdana, Arial, sans-serif;">Regards,<br></p>
]]></field>
</record>
</odoo>

View File

@ -0,0 +1,10 @@
<?xml version="1.0"?>
<odoo noupdate="1">
<record id="attachment_queue_demo" model="attachment.queue">
<field name="datas">bWlncmF0aW9uIHRlc3Q=</field>
<field name="datas_fname">attachment_queue_demo.doc</field>
<field name="name">attachment_queue_demo.doc</field>
</record>
</odoo>

View File

@ -0,0 +1 @@
from . import attachment_queue

View File

@ -0,0 +1,106 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
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']
attachment_id = fields.Many2one(
'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")
date_done = fields.Datetime()
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',
string="Failure Emails",
help="list of email (separated by comma) which should be notified in "
"case of failure")
def _compute_failure_emails(self):
for attach in self:
attach.failure_emails = attach._get_failure_emails()
def _get_failure_emails(self):
# to be overriden in submodules implementing the file_type
self.ensure_one()
return ""
@api.model
def run_attachment_queue_scheduler(self, domain=None):
if domain is None:
domain = [('state', '=', 'pending')]
batch_limit = self.env.ref(
'attachment_queue.attachment_queue_cron_batch_limit') \
.value
if batch_limit and batch_limit.isdigit():
limit = int(batch_limit)
else:
limit = 200
attachments = self.search(domain, limit=limit)
if attachments:
return attachments.run()
return True
def run(self):
"""
Run the process for each attachment queue
"""
failure_tmpl = self.env.ref(
'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)
attach = attachment.with_env(new_env)
try:
attach._run()
# pylint: disable=broad-except
except Exception as e:
attach.env.cr.rollback()
_logger.exception(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(),
}
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)
@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'})

View File

@ -0,0 +1,4 @@
* Valentin CHEMIERE <valentin.chemiere@akretion.com>
* Florian da Costa <florian.dacosta@akretion.com>
* Angel Moya <http://angelmoya.es>
* Dan Kiplangat <dan@sunflowerweb.nl>

View File

@ -0,0 +1,5 @@
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.
An example of the use of this module, can be found in the module `attachment_synchronize`.

View File

@ -0,0 +1,8 @@
Go the menu Settings > Technical > Database Structure > Attachments Queue
You can create / see standard attachments with additional fields
Configure the batch limit for attachments that can be sync by the cron task at a go:
Settings > Technical > System parameters > attachment_queue_cron_batch_limit

View File

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_attachment_queue_user,attachment.queue.user,model_attachment_queue,,1,0,0,0
access_attachment_queue_manager,attachment.queue.manager,model_attachment_queue,base.group_no_one,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_attachment_queue_user attachment.queue.user model_attachment_queue 1 0 0 0
3 access_attachment_queue_manager attachment.queue.manager model_attachment_queue base.group_no_one 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import test_attachment_queue

View File

@ -0,0 +1,50 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.tests.common import TransactionCase
import odoo
from odoo import api
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')
def tearDown(self):
self.registry.leave_test_mode()
super().tearDown()
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.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)
attach = self.attachment.with_env(new_env)
self.assertEqual(
attach.state,
'done'
)
def test_set_done(self):
"""Test set_done manually
"""
self.assertEqual(
self.attachment.state,
'pending'
)
self.attachment.set_done()
self.assertEqual(
self.attachment.state,
'done'
)

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="view_attachment_queue_form" model="ir.ui.view">
<field name="model">attachment.queue</field>
<field name="inherit_id" ref="base.view_attachment_form"/>
<field name="arch" type="xml">
<xpath expr="/form/*" position="before">
<header>
<button name="run" states="pending,failed"
string="Run" type="object" class="oe_highlight"/>
<button name="set_done" states="pending,failed"
string="Set to Done" type="object"/>
</header>
</xpath>
<field name="url" position="after">
<field name="date_done"/>
<field name="state"/>
<field name="file_type"/>
</field>
<group name="description_group">
<group name="state_message" string="Error" colspan="4">
<field name="state_message" nolabel="1"/>
</group>
</group>
</field>
</record>
<record id="view_attachment_queue_tree" model="ir.ui.view">
<field name="model">attachment.queue</field>
<field name="arch" type="xml">
<tree default_order='create_date desc'>
<field name="name"/>
<field name="datas_fname"/>
<field name="file_type"/>
<field name="type"/>
<field name="create_date"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="view_attachment_queue_search" model="ir.ui.view">
<field name="model">attachment.queue</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 name="url"
string="URL"
domain="[('type','=','url')]"/>
<filter name="binary"
string="Binary"
domain="[('type','=','binary')]"/>
<separator/>
<filter name="my_documents_filter"
string="My Document(s)"
domain="[('create_uid','=',uid)]"
help="Filter on my documents"/>
<field name="create_uid"/>
<field name="type"/>
<filter string="Pending" name="pending" domain="[('state', '=', 'pending')]"/>
<filter string="Failed" name="failed" domain="[('state', '=', 'failed')]"/>
<filter string="Done" name="done" domain="[('state', '=', 'done')]"/>
<group expand="0" string="Group By">
<filter string="Owner" name="owner" icon="terp-personal" 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="Company" name="company" icon="terp-gtk-home" 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="State" name="state" domain="[]" context="{'group_by': 'state'}"/>
<filter string="File type" name="file_type" domain="[]" context="{'group_by': 'file_type'}"/>
</group>
</search>
</field>
</record>
<record id="action_attachment_queue" model="ir.actions.act_window">
<field name="name">Attachments Queue</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">attachment.queue</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" eval="False"/>
<field name="search_view_id" ref="view_attachment_queue_search"/>
</record>
<record id="act_open_attachment_que_view_tree" model="ir.actions.act_window.view">
<field eval="10" name="sequence"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="view_attachment_queue_tree"/>
<field name="act_window_id" ref="action_attachment_queue"/>
</record>
<record id="act_open_attachment_que_view_form" model="ir.actions.act_window.view">
<field eval="10" name="sequence"/>
<field name="view_mode">form</field>
<field name="view_id" ref="view_attachment_queue_form"/>
<field name="act_window_id" ref="action_attachment_queue"/>
</record>
<menuitem id="menu_attachment_queue"
parent="base.next_id_9"
sequence="20"
action="action_attachment_queue"/>
</odoo>