Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
368 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg | ||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
|
||
================= | ||
Base Export Async | ||
================= | ||
|
||
Standard Export can be delayed in asynchronous jobs executed in the background and then send by email to the user. | ||
|
||
Configuration | ||
============= | ||
|
||
This module is using the Odoo Queue Modules. | ||
Please refer to that module for configuration. | ||
https://github.com/OCA/queue | ||
|
||
Usage | ||
===== | ||
|
||
During standard export, tick the "Asynchronous export" checkbox to make the export asynchronous. | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues | ||
<https://github.com/OCA/{project_repo}/issues>`_. In case of trouble, please | ||
check there if your issue has already been reported. If you spotted it first, | ||
help us smash it by providing detailed and welcomed feedback. | ||
|
||
Credits | ||
======= | ||
|
||
Contributors | ||
------------ | ||
|
||
* Pineux Arnaud <arnaud.pineux@acsone.eu> | ||
|
||
Funders | ||
------- | ||
|
||
The development of this module has been financially supported by: | ||
|
||
* ACSONE SA/NV | ||
|
||
Maintainer | ||
---------- | ||
|
||
.. image:: https://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
|
||
This module is maintained by the OCA. | ||
|
||
OCA, or the Odoo Community Association, is a nonprofit organization whose | ||
mission is to support the collaborative development of Odoo features and | ||
promote its widespread use. | ||
|
||
To contribute to this module, please visit https://odoo-community.org. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright 2019 ACSONE SA/NV | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Copyright 2019 ACSONE SA/NV | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
{ | ||
'name': 'Base Export Async', | ||
'summary': """ | ||
Asynchronous export with job queue | ||
""", | ||
'version': '12.0.1.0.0', | ||
'license': 'AGPL-3', | ||
'author': 'ACSONE SA/NV, Odoo Community Association (OCA)', | ||
'website': 'https://acsone.eu/', | ||
'depends': [ | ||
'web', | ||
'queue_job' | ||
], | ||
'data': [ | ||
'views/assets.xml', | ||
'security/ir.model.access.csv', | ||
], | ||
'demo': [ | ||
], | ||
'qweb': ['static/src/xml/base.xml'] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright 2019 ACSONE SA/NV | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from . import delay_export |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# Copyright 2019 ACSONE SA/NV | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
import logging | ||
import json | ||
import operator | ||
import base64 | ||
|
||
from odoo import api, fields, models, _ | ||
from odoo.addons.queue_job.job import job | ||
from odoo.addons.web.controllers.main import CSVExport, ExcelExport | ||
from odoo.exceptions import Warning | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class DelayExport(models.Model): | ||
|
||
_name = 'delay.export' | ||
_description = 'Allow to delay the export' | ||
|
||
@api.model | ||
def delay_export(self, data): | ||
params = json.loads(data.get('data')) | ||
context = params.get('context', {}) | ||
uid = context.get('uid', False) | ||
if not uid: | ||
raise Warning(_("A problem occurs during the job creation. \ | ||
Please contact your administrator")) | ||
user = self.env['res.users'].browse([uid]) | ||
if not user.email: | ||
raise Warning(_("You must set an email address to your user.")) | ||
self.with_delay().export(params) | ||
|
||
@api.model | ||
@job | ||
def export(self, params): | ||
export_format = params.get('format') | ||
raw_data = export_format != 'csv' | ||
|
||
model_name, fields_name, ids, domain, import_compat, context = \ | ||
operator.itemgetter('model', 'fields', 'ids', | ||
'domain', 'import_compat', 'context')(params) | ||
user = self.env['res.users'].browse([context.get('uid')]) | ||
if not user or not user.email: | ||
raise Warning(_("The user doesn't have an email address.")) | ||
|
||
model = self.env[model_name].with_context( | ||
import_compat=import_compat, **context) | ||
records = model.browse(ids) or model.search( | ||
domain, offset=0, limit=False, order=False) | ||
|
||
if not model._is_an_ordinary_table(): | ||
fields_name = [field for field in fields_name | ||
if field['name'] != 'id'] | ||
|
||
field_names = [f['name'] for f in fields_name] | ||
import_data = records.export_data( | ||
field_names, raw_data).get('datas', []) | ||
|
||
if import_compat: | ||
columns_headers = field_names | ||
else: | ||
columns_headers = [val['label'].strip() for val in fields_name] | ||
|
||
if export_format == 'csv': | ||
csv = CSVExport() | ||
result = csv.from_data(columns_headers, import_data) | ||
else: | ||
xls = ExcelExport() | ||
result = xls.from_data(columns_headers, import_data) | ||
|
||
attachment = self.env['ir.attachment'].create({ | ||
'name': "{}.{}".format(model_name, export_format), | ||
'datas': base64.b64encode(result), | ||
'datas_fname': "{}.{}".format(model_name, export_format), | ||
'type': 'binary' | ||
}) | ||
|
||
odoobot = self.env.ref("base.partner_root") | ||
email_from = odoobot.email | ||
self.env['mail.mail'].create({ | ||
'email_from': email_from, | ||
'reply_to': email_from, | ||
'email_to': user.email, | ||
'subject': _("Export {} {}").format( | ||
model_name, fields.Date.to_string(fields.Date.today())), | ||
'body_html': _("This is an automated \ | ||
message please do not reply."), | ||
'attachment_ids': [(4, attachment.id)], | ||
'auto_delete': True, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
access_delay_export,delay.export.user,model_delay_export,,1,1,1,1 |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
odoo.define('base_export_async.DataExport', function(require) { | ||
"use strict"; | ||
|
||
var core = require('web.core'); | ||
var DataExport = require('web.DataExport'); | ||
var framework = require('web.framework'); | ||
var pyUtils = require('web.py_utils'); | ||
var Dialog = require('web.Dialog'); | ||
var _t = core._t; | ||
|
||
DataExport.include({ | ||
start: function() { | ||
this._super.apply(this, arguments); | ||
this.async = this.$('#async_export'); | ||
}, | ||
export_data: function() { | ||
var self = this; | ||
if (self.async.is(":checked")) { | ||
var exported_fields = this.$( | ||
'.o_fields_list option').map( | ||
function() { | ||
return { | ||
name: (self.records[this.value] || | ||
this).value, | ||
label: this.textContent || | ||
this.innerText | ||
}; | ||
}).get(); | ||
|
||
if (_.isEmpty(exported_fields)) { | ||
Dialog.alert(this, _t( | ||
"Please select fields to export..." | ||
)); | ||
return; | ||
} | ||
if (!this.isCompatibleMode) { | ||
exported_fields.unshift({ | ||
name: 'id', | ||
label: _t('External ID') | ||
}); | ||
} | ||
|
||
var export_format = this.$export_format_inputs | ||
.filter(':checked').val(); | ||
|
||
framework.blockUI(); | ||
this._rpc({ | ||
model: 'delay.export', | ||
method: 'delay_export', | ||
args: [{ | ||
data: JSON.stringify({ | ||
format: export_format, | ||
model: this | ||
.record | ||
.model, | ||
fields: exported_fields, | ||
ids: this | ||
.ids_to_export, | ||
domain: this | ||
.domain, | ||
context: pyUtils | ||
.eval( | ||
'contexts', [ | ||
this | ||
.record | ||
.getContext() | ||
] | ||
), | ||
import_compat: | ||
!! | ||
this | ||
.$import_compat_radios | ||
.filter( | ||
':checked' | ||
).val(), | ||
}) | ||
}], | ||
}).then(function(result) { | ||
framework.unblockUI(); | ||
Dialog.alert(this, _t( | ||
"You will receive the export file by email as soon as it is finished." | ||
)); | ||
}); | ||
} else { | ||
this._super.apply(this, arguments); | ||
} | ||
}, | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<templates id="template" xml:space="preserve"> | ||
|
||
<t t-extend="ExportDialog"> | ||
<t t-jquery="div.row" t-operation="append"> | ||
<div class="col-lg-12"> | ||
<label> | ||
<input type="checkbox" name="async_export" id="async_export"/> | ||
<strong> Asynchronous export </strong> (You will receive the export by email) | ||
</label> | ||
</div> | ||
</t> | ||
</t> | ||
|
||
</templates> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright 2019 ACSONE SA/NV | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from . import test_base_export_async |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Copyright 2019 ACSONE SA/NV | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
import odoo.tests.common as common | ||
import json | ||
|
||
data_csv = {'data': """{"format": "csv", "model": "res.partner", | ||
"fields": [{"name": "id", "label": "External ID"}, | ||
{"name": "display_name", "label": "Display Name"}, | ||
{"name": "email", "label": "Email"}, | ||
{"name": "phone", "label": "Phone"}], | ||
"ids": false, | ||
"domain": [], | ||
"context": {"lang": "en_US", "tz": "Europe/Brussels", "uid": 2}, | ||
"import_compat": false}"""} | ||
|
||
data_xls = {'data': """{"format": "xls", "model": "res.partner", | ||
"fields": [{"name": "id", "label": "External ID"}, | ||
{"name": "display_name", "label": "Display Name"}, | ||
{"name": "email", "label": "Email"}, | ||
{"name": "phone", "label": "Phone"}], | ||
"ids": false, | ||
"domain": [], | ||
"context": {"lang": "en_US", "tz": "Europe/Brussels", "uid": 2}, | ||
"import_compat": false}"""} | ||
|
||
class TestBaseExportAsync(common.TransactionCase): | ||
|
||
def setUp(self): | ||
super(TestBaseExportAsync, self).setUp() | ||
self.delay_export_obj = self.env['delay.export'] | ||
self.job_obj = self.env['queue.job'] | ||
|
||
def test_delay_export(self): | ||
""" Check that the call create a new JOB""" | ||
nbr_job = len(self.job_obj.search([])) | ||
self.delay_export_obj.delay_export(data_csv) | ||
new_nbr_job = len(self.job_obj.search([])) | ||
self.assertEqual(new_nbr_job, nbr_job + 1) | ||
|
||
def test_export_csv(self): | ||
""" Check that the export generate an attachment and email""" | ||
params = json.loads(data_csv.get('data')) | ||
mails = self.env['mail.mail'].search([]) | ||
self.delay_export_obj.export(params) | ||
new_mail = self.env['mail.mail'].search([]) - mails | ||
self.assertEqual(len(new_mail), 1) | ||
self.assertEqual(new_mail.attachment_ids[0].datas_fname, | ||
"res.partner.csv") | ||
|
||
def test_export_xls(self): | ||
""" Check that the export generate an attachment and email""" | ||
params = json.loads(data_xls.get('data')) | ||
mails = self.env['mail.mail'].search([]) | ||
self.delay_export_obj.export(params) | ||
new_mail = self.env['mail.mail'].search([]) - mails | ||
self.assertEqual(len(new_mail), 1) | ||
self.assertEqual(new_mail.attachment_ids[0].datas_fname, | ||
"res.partner.xls") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<odoo> | ||
<template id="assets_backend" name="async export assets" inherit_id="web.assets_backend"> | ||
<xpath expr="." position="inside"> | ||
<script type="text/javascript" src="/base_export_async/static/src/js/data_export.js"/> | ||
</xpath> | ||
</template> | ||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../../base_export_async |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import setuptools | ||
|
||
setuptools.setup( | ||
setup_requires=['setuptools-odoo'], | ||
odoo_addon=True, | ||
) |