Skip to content

Commit

Permalink
Merge 3b0bba5 into d708db0
Browse files Browse the repository at this point in the history
  • Loading branch information
apineux committed Apr 19, 2019
2 parents d708db0 + 3b0bba5 commit 4547f53
Show file tree
Hide file tree
Showing 13 changed files with 305 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -20,6 +20,7 @@ addon | version | summary
[queue_job](queue_job/) | 12.0.1.0.0 | Job Queue
[queue_job_cron](queue_job_cron/) | 12.0.1.0.1 | Scheduled Actions as Queue Jobs
[test_queue_job](test_queue_job/) | 12.0.1.0.0 | Queue Job Tests
[base_export_async](base_export_async/) | 12.0.1.0.0 | Export (CSV and XLS) files in the background


Unported addons
Expand Down
59 changes: 59 additions & 0 deletions base_export_async/README.rst
@@ -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.
4 changes: 4 additions & 0 deletions base_export_async/__init__.py
@@ -0,0 +1,4 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import models
24 changes: 24 additions & 0 deletions base_export_async/__manifest__.py
@@ -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']
}
4 changes: 4 additions & 0 deletions base_export_async/models/__init__.py
@@ -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
92 changes: 92 additions & 0 deletions base_export_async/models/delay_export.py
@@ -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,
})
2 changes: 2 additions & 0 deletions base_export_async/security/ir.model.access.csv
@@ -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
Binary file added base_export_async/static/description/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 89 additions & 0 deletions base_export_async/static/src/js/data_export.js
@@ -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);
}
},
});
});
15 changes: 15 additions & 0 deletions base_export_async/static/src/xml/base.xml
@@ -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>
8 changes: 8 additions & 0 deletions base_export_async/views/assets.xml
@@ -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>
1 change: 1 addition & 0 deletions setup/base_export_async/odoo/addons/base_export_async
6 changes: 6 additions & 0 deletions setup/base_export_async/setup.py
@@ -0,0 +1,6 @@
import setuptools

setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)

0 comments on commit 4547f53

Please sign in to comment.