Browse Source

Merge PR #1756 into 12.0

Signed-off-by sebastienbeau
12.0-mig-module_prototyper_last
OCA-git-bot 4 years ago
parent
commit
f4ab1d6f05
  1. 1
      attachment_queue/__init__.py
  2. 23
      attachment_queue/__manifest__.py
  3. 16
      attachment_queue/data/cron.xml
  4. 7
      attachment_queue/data/ir_config_parameter.xml
  5. 16
      attachment_queue/data/mail_template.xml
  6. 10
      attachment_queue/demo/attachment_queue_demo.xml
  7. 1
      attachment_queue/models/__init__.py
  8. 111
      attachment_queue/models/attachment_queue.py
  9. 4
      attachment_queue/readme/CONTRIBUTORS.rst
  10. 3
      attachment_queue/readme/DESCRIPTION.rst
  11. 17
      attachment_queue/readme/USAGE.rst
  12. 3
      attachment_queue/security/ir.model.access.csv
  13. BIN
      attachment_queue/static/description/form.png
  14. BIN
      attachment_queue/static/description/icon.png
  15. BIN
      attachment_queue/static/description/tree.png
  16. 3
      attachment_queue/tests/__init__.py
  17. 39
      attachment_queue/tests/test_attachment_queue.py
  18. 106
      attachment_queue/views/attachment_queue_view.xml

1
attachment_queue/__init__.py

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

23
attachment_queue/__manifest__.py

@ -0,0 +1,23 @@
# 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 adding the concept of queue for processing files",
"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,
}

16
attachment_queue/data/cron.xml

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

7
attachment_queue/data/ir_config_parameter.xml

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

16
attachment_queue/data/mail_template.xml

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

10
attachment_queue/demo/attachment_queue_demo.xml

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

1
attachment_queue/models/__init__.py

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

111
attachment_queue/models/attachment_queue.py

@ -0,0 +1,111 @@
# 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="Comma-separated list of email addresses to 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
def _run(self):
self.ensure_one()
_logger.info("Starting processing of attachment queue id %d", self.id)
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"})

4
attachment_queue/readme/CONTRIBUTORS.rst

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

3
attachment_queue/readme/DESCRIPTION.rst

@ -0,0 +1,3 @@
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.
A use case of this module can be found in the attachment_synchronize module.

17
attachment_queue/readme/USAGE.rst

@ -0,0 +1,17 @@
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
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

3
attachment_queue/security/ir.model.access.csv

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

BIN
attachment_queue/static/description/form.png

After

Width: 925  |  Height: 780  |  Size: 75 KiB

BIN
attachment_queue/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

BIN
attachment_queue/static/description/tree.png

After

Width: 1171  |  Height: 270  |  Size: 41 KiB

3
attachment_queue/tests/__init__.py

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

39
attachment_queue/tests/test_attachment_queue.py

@ -0,0 +1,39 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
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"
)
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")

106
attachment_queue/views/attachment_queue_view.xml

@ -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" domain="[]" context="{'group_by':'create_uid'}"/>
<filter string="Type" name="type" domain="[]" context="{'group_by':'type'}" groups="base.group_no_one"/>
<filter string="Company" name="company" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
<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="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>
Loading…
Cancel
Save