From 3078caca7037b989c7182b4ff16f47f98c647462 Mon Sep 17 00:00:00 2001 From: Guewen Baconnier Date: Thu, 21 Nov 2019 15:40:40 +0100 Subject: [PATCH 01/15] Support several recipient users in base_export_async The UI still send it to the current user, but it will allow reusing the module for other purposes: plan a regular export to users. Setting the recipient_ids instead of the email_to in mail.mail means that we can still send the email, it will stay in the failed emails, allowing to correct the user. --- base_export_async/__manifest__.py | 35 ++--- base_export_async/i18n/base_export_async.pot | 4 +- base_export_async/i18n/de.po | 4 +- base_export_async/i18n/zh_CN.po | 4 +- .../migrations/12.0.1.1.0/post-migrate.py | 23 +++ .../migrations/12.0.1.1.0/pre-migrate.py | 9 ++ base_export_async/models/delay_export.py | 134 +++++++++--------- base_export_async/readme/CONTRIBUTORS.rst | 3 +- base_export_async/security/ir_rule.xml | 2 +- .../static/src/js/data_export.js | 1 + .../tests/test_base_export_async.py | 74 +++++----- 11 files changed, 170 insertions(+), 123 deletions(-) create mode 100644 base_export_async/migrations/12.0.1.1.0/post-migrate.py create mode 100644 base_export_async/migrations/12.0.1.1.0/pre-migrate.py diff --git a/base_export_async/__manifest__.py b/base_export_async/__manifest__.py index a39844c499..9dba8ddd5e 100644 --- a/base_export_async/__manifest__.py +++ b/base_export_async/__manifest__.py @@ -2,23 +2,26 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - "name": "Base Export Async", - "summary": """ + '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://github.com/OCA/queue", - "depends": ["web", "queue_job"], - "data": [ - "views/assets.xml", - "security/ir.model.access.csv", - "security/ir_rule.xml", - "data/config_parameter.xml", - "data/cron.xml", + 'version': '12.0.1.1.0', + 'license': 'AGPL-3', + 'author': 'ACSONE SA/NV, Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/queue', + 'depends': [ + 'web', + 'queue_job' ], - "demo": [], - "qweb": ["static/src/xml/base.xml"], - "installable": False, + 'data': [ + 'views/assets.xml', + 'security/ir.model.access.csv', + 'security/ir_rule.xml', + 'data/config_parameter.xml', + 'data/cron.xml', + ], + 'demo': [ + ], + 'qweb': ['static/src/xml/base.xml'] } diff --git a/base_export_async/i18n/base_export_async.pot b/base_export_async/i18n/base_export_async.pot index 3f450bb117..a10ca1b424 100644 --- a/base_export_async/i18n/base_export_async.pot +++ b/base_export_async/i18n/base_export_async.pot @@ -114,8 +114,8 @@ msgid "The user doesn't have an email address." msgstr "" #. module: base_export_async -#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_id -msgid "User" +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids +msgid "Users" msgstr "" #. module: base_export_async diff --git a/base_export_async/i18n/de.po b/base_export_async/i18n/de.po index 72d0bdfbc3..b60d61be23 100644 --- a/base_export_async/i18n/de.po +++ b/base_export_async/i18n/de.po @@ -126,8 +126,8 @@ msgid "The user doesn't have an email address." msgstr "Der Benutzer hat keine Email-Adresse." #. module: base_export_async -#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_id -msgid "User" +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids +msgid "Users" msgstr "Benutzer" #. module: base_export_async diff --git a/base_export_async/i18n/zh_CN.po b/base_export_async/i18n/zh_CN.po index 356e6aac6a..2ade00d5d1 100644 --- a/base_export_async/i18n/zh_CN.po +++ b/base_export_async/i18n/zh_CN.po @@ -125,8 +125,8 @@ msgid "The user doesn't have an email address." msgstr "用户没有电子邮件地址。" #. module: base_export_async -#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_id -msgid "User" +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids +msgid "Users" msgstr "用户" #. module: base_export_async diff --git a/base_export_async/migrations/12.0.1.1.0/post-migrate.py b/base_export_async/migrations/12.0.1.1.0/post-migrate.py new file mode 100644 index 0000000000..14f426ab3b --- /dev/null +++ b/base_export_async/migrations/12.0.1.1.0/post-migrate.py @@ -0,0 +1,23 @@ +# Copyright 2019 Camptocamp +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, SUPERUSER_ID +from odoo.tools.sql import column_exists + + +def migrate(cr, version): + if not column_exists(cr, "delay_export", "__temp_user_id"): + return + with api.Environment.manage(): + env = api.Environment(cr, SUPERUSER_ID, {}) + field = env["delay.export"]._fields["user_ids"] + rel, id1, id2 = field.relation, field.column1, field.column2 + env.cr.execute( + """ + INSERT INTO %s (%s, %s) + SELECT id, __temp_user_id + FROM delay_export + """ + % (rel, id1, id2) + ) + env.cr.execute("ALTER TABLE delay_export DROP COLUMN __temp_user_id;") diff --git a/base_export_async/migrations/12.0.1.1.0/pre-migrate.py b/base_export_async/migrations/12.0.1.1.0/pre-migrate.py new file mode 100644 index 0000000000..51ca5be7bf --- /dev/null +++ b/base_export_async/migrations/12.0.1.1.0/pre-migrate.py @@ -0,0 +1,9 @@ +# Copyright 2019 Camptocamp +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo.tools.sql import column_exists, rename_column + + +def migrate(cr, version): + if column_exists(cr, "delay_export", "user_id"): + rename_column(cr, "delay_export", "user_id", "__temp_user_id") diff --git a/base_export_async/models/delay_export.py b/base_export_async/models/delay_export.py index 7881af001b..7246768185 100644 --- a/base_export_async/models/delay_export.py +++ b/base_export_async/models/delay_export.py @@ -1,13 +1,13 @@ # Copyright 2019 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import base64 -import json import logging +import json import operator - +import base64 from dateutil.relativedelta import relativedelta -from odoo import _, api, fields, models + +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 UserError @@ -17,49 +17,50 @@ class DelayExport(models.Model): - _name = "delay.export" - _description = "Allow to delay the export" + _name = 'delay.export' + _description = 'Asynchronous Export' - user_id = fields.Many2one("res.users", string="User", index=True) + user_ids = fields.Many2many('res.users', string='Users', index=True) @api.model def delay_export(self, data): - params = json.loads(data.get("data")) + """Delay the export, called from js""" + params = json.loads(data.get('data')) if not self.env.user.email: raise UserError(_("You must set an email address to your user.")) self.with_delay().export(params) @api.model def _get_file_content(self, params): - export_format = params.get("format") - raw_data = export_format != "csv" + export_format = params.get('format') + raw_data = export_format != 'csv' - item_names = ("model", "fields", "ids", "domain", "import_compat", "context") - items = operator.itemgetter(item_names)(params) - model_name, fields_name, ids, domain, import_compat, context = items - user = self.env["res.users"].browse([context.get("uid")]) - if not user or not user.email: - raise UserError(_("The user doesn't have an email address.")) + items = operator.itemgetter( + 'model', 'fields', 'ids', 'domain', + 'import_compat', 'context', 'user_ids' + )(params) + (model_name, fields_name, ids, domain, + import_compat, context, user_ids) = items model = self.env[model_name].with_context( - import_compat=import_compat, **context - ) + import_compat=import_compat, **context) records = model.browse(ids) or model.search( - domain, offset=0, limit=False, order=False - ) + 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"] + 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", []) + 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] + columns_headers = [val['label'].strip() for val in fields_name] - if export_format == "csv": + if export_format == 'csv': csv = CSVExport() return csv.from_data(columns_headers, import_data) else: @@ -69,72 +70,77 @@ def _get_file_content(self, params): @api.model @job def export(self, params): + """Delayed export of a file sent by email + + The ``params`` is a dict of parameters, contains: + + * format: csv/excel + * model: model to export + * fields: list of fields to export, a list of dict: + [{'label': '', 'name': ''}] + * ids: list of ids to export + * domain: domain for the export + * context: context for the export (language, ...) + * import_compat: if the export is export/import compatible (boolean) + * user_ids: optional list of user ids who receive the file + """ content = self._get_file_content(params) - model_name, context, export_format = operator.itemgetter( - "model", "context", "format" + items = operator.itemgetter( + 'model', 'context', 'format', 'user_ids' )(params) - user = self.env["res.users"].browse([context.get("uid")]) + model_name, context, export_format, user_ids = items + users = self.env['res.users'].browse(user_ids) - export_record = self.sudo().create({"user_id": user.id}) + export_record = self.sudo().create({'user_ids': [(6, 0, users.ids)]}) name = "{}.{}".format(model_name, export_format) - attachment = self.env["ir.attachment"].create( - { - "name": name, - "datas": base64.b64encode(content), - "datas_fname": name, - "type": "binary", - "res_model": self._name, - "res_id": export_record.id, - } - ) + attachment = self.env['ir.attachment'].create({ + 'name': name, + 'datas': base64.b64encode(content), + 'datas_fname': name, + 'type': 'binary', + 'res_model': self._name, + 'res_id': export_record.id, + }) url = "{}/web/content/ir.attachment/{}/datas/{}?download=true".format( - self.env["ir.config_parameter"].sudo().get_param("web.base.url"), + self.env['ir.config_parameter'].sudo().get_param('web.base.url'), attachment.id, attachment.name, ) - time_to_live = ( - self.env["ir.config_parameter"].sudo().get_param("attachment.ttl", 7) - ) + time_to_live = self.env['ir.config_parameter'].sudo(). \ + get_param('attachment.ttl', 7) date_today = fields.Date.today() expiration_date = fields.Date.to_string( - date_today + relativedelta(days=+int(time_to_live)) - ) + date_today + relativedelta(days=+int(time_to_live))) # TODO : move to email template odoo_bot = self.sudo().env.ref("base.partner_root") email_from = odoo_bot.email model_description = self.env[model_name]._description - self.env["mail.mail"].create( - { - "email_from": email_from, - "reply_to": email_from, - "email_to": user.email, - "subject": _("Export {} {}").format( - model_description, fields.Date.to_string(fields.Date.today()) - ), - "body_html": _( - """ + self.env['mail.mail'].create({ + 'email_from': email_from, + 'reply_to': email_from, + 'recipient_ids': [(6, 0, users.mapped('partner_id').ids)], + 'subject': _("Export {} {}").format( + model_description, fields.Date.to_string(fields.Date.today())), + 'body_html': _("""

Your export is available here.

It will be automatically deleted the {}.

 

This is an automated message please do not reply.

- """ - ).format(url, expiration_date), - "auto_delete": True, - } - ) + """).format(url, expiration_date), + 'auto_delete': True, + }) @api.model def cron_delete(self): - time_to_live = ( - self.env["ir.config_parameter"].sudo().get_param("attachment.ttl", 7) - ) + time_to_live = self.env['ir.config_parameter'].sudo(). \ + get_param('attachment.ttl', 7) date_today = fields.Date.today() date_to_delete = date_today + relativedelta(days=-int(time_to_live)) - self.search([("create_date", "<=", date_to_delete)]).unlink() + self.search([('create_date', '<=', date_to_delete)]).unlink() diff --git a/base_export_async/readme/CONTRIBUTORS.rst b/base_export_async/readme/CONTRIBUTORS.rst index ede63fcc0d..b1a90f9127 100644 --- a/base_export_async/readme/CONTRIBUTORS.rst +++ b/base_export_async/readme/CONTRIBUTORS.rst @@ -1 +1,2 @@ -Arnaud Pineux (ACSONE SA/NV) authored the initial prototype. +* Arnaud Pineux (ACSONE SA/NV) authored the initial prototype. +* Guewen Baconnier (Camptocamp) diff --git a/base_export_async/security/ir_rule.xml b/base_export_async/security/ir_rule.xml index 7ed488ed37..575df5b6b6 100644 --- a/base_export_async/security/ir_rule.xml +++ b/base_export_async/security/ir_rule.xml @@ -8,6 +8,6 @@ - [('user_id', '=', user.id)] + [('user_ids', 'in', user.id)] diff --git a/base_export_async/static/src/js/data_export.js b/base_export_async/static/src/js/data_export.js index 06a7af02a0..9e5065cd2a 100644 --- a/base_export_async/static/src/js/data_export.js +++ b/base_export_async/static/src/js/data_export.js @@ -84,6 +84,7 @@ odoo.define('base_export_async.DataExport', function(require) { .filter( ':checked' ).val(), + user_ids: [this.record.context.uid], }) }], }).then(function(result) { diff --git a/base_export_async/tests/test_base_export_async.py b/base_export_async/tests/test_base_export_async.py index fae4b6264d..a8a7965c70 100644 --- a/base_export_async/tests/test_base_export_async.py +++ b/base_export_async/tests/test_base_export_async.py @@ -2,13 +2,14 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import json - -import odoo.tests.common as common from dateutil.relativedelta import relativedelta + +import freezegun + from odoo import fields +import odoo.tests.common as common -data_csv = { - "data": """{"format": "csv", "model": "res.partner", +data_csv = {'data': """{"format": "csv", "model": "res.partner", "fields": [{"name": "id", "label": "External ID"}, {"name": "display_name", "label": "Display Name"}, {"name": "email", "label": "Email"}, @@ -16,11 +17,11 @@ "ids": false, "domain": [], "context": {"lang": "en_US", "tz": "Europe/Brussels", "uid": 2}, - "import_compat": false}""" -} + "import_compat": false, + "user_ids": [2] + }"""} -data_xls = { - "data": """{"format": "xls", "model": "res.partner", +data_xls = {'data': """{"format": "xls", "model": "res.partner", "fields": [{"name": "id", "label": "External ID"}, {"name": "display_name", "label": "Display Name"}, {"name": "email", "label": "Email"}, @@ -28,15 +29,17 @@ "ids": false, "domain": [], "context": {"lang": "en_US", "tz": "Europe/Brussels", "uid": 2}, - "import_compat": false}""" -} + "import_compat": false, + "user_ids": [2] + }"""} 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"] + 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""" @@ -47,39 +50,40 @@ def test_delay_export(self): 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([]) - attachments = self.env["ir.attachment"].search([]) + params = json.loads(data_csv.get('data')) + mails = self.env['mail.mail'].search([]) + attachments = self.env['ir.attachment'].search([]) self.delay_export_obj.export(params) - new_mail = self.env["mail.mail"].search([]) - mails - new_attachment = self.env["ir.attachment"].search([]) - attachments + new_mail = self.env['mail.mail'].search([]) - mails + new_attachment = self.env['ir.attachment'].search([]) - attachments self.assertEqual(len(new_mail), 1) - self.assertEqual(new_attachment.datas_fname, "res.partner.csv") + self.assertEqual(new_attachment.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([]) - attachments = self.env["ir.attachment"].search([]) + params = json.loads(data_xls.get('data')) + mails = self.env['mail.mail'].search([]) + attachments = self.env['ir.attachment'].search([]) self.delay_export_obj.export(params) - new_mail = self.env["mail.mail"].search([]) - mails - new_attachment = self.env["ir.attachment"].search([]) - attachments + new_mail = self.env['mail.mail'].search([]) - mails + new_attachment = self.env['ir.attachment'].search([]) - attachments self.assertEqual(len(new_mail), 1) - self.assertEqual(new_attachment.datas_fname, "res.partner.xls") + self.assertEqual(new_attachment.datas_fname, + "res.partner.xls") def test_cron_delete(self): """ Check that cron delete attachment after TTL""" - params = json.loads(data_csv.get("data")) - attachments = self.env["ir.attachment"].search([]) + params = json.loads(data_csv.get('data')) + attachments = self.env['ir.attachment'].search([]) self.delay_export_obj.export(params) - new_attachment = self.env["ir.attachment"].search([]) - attachments - time_to_live = ( - self.env["ir.config_parameter"].sudo().get_param("attachment.ttl", 7) - ) - date_today = fields.Date.today() - date_to_delete = date_today + relativedelta(days=-int(time_to_live)) - # Update create_date with today - TTL - self.delay_export_obj.search([]).write({"create_date": date_to_delete}) - self.delay_export_obj.sudo().cron_delete() + new_attachment = self.env['ir.attachment'].search([]) - attachments + time_to_live = self.env['ir.config_parameter'].sudo(). \ + get_param('attachment.ttl', 7) + date_today = fields.Datetime.now() + date_past_ttl = date_today + relativedelta(days=int(time_to_live)) + with freezegun.freeze_time(date_past_ttl): + self.delay_export_obj.cron_delete() + # The attachment must be deleted self.assertFalse(new_attachment.exists()) From 749ae1258b503b0cd49a0a8ab27f2727635db79d Mon Sep 17 00:00:00 2001 From: oca-travis Date: Thu, 11 Jun 2020 19:00:51 +0000 Subject: [PATCH 02/15] [UPD] Update base_export_async.pot --- base_export_async/i18n/base_export_async.pot | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/base_export_async/i18n/base_export_async.pot b/base_export_async/i18n/base_export_async.pot index a10ca1b424..dc3e413254 100644 --- a/base_export_async/i18n/base_export_async.pot +++ b/base_export_async/i18n/base_export_async.pot @@ -14,7 +14,7 @@ msgstr "" "Plural-Forms: \n" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:112 +#: code:addons/base_export_async/models/delay_export.py:129 #, python-format msgid "\n" "

Your export is available here.

\n" @@ -35,7 +35,7 @@ msgstr "" #. module: base_export_async #: model:ir.model,name:base_export_async.model_delay_export -msgid "Allow to delay the export" +msgid "Asynchronous Export" msgstr "" #. module: base_export_async @@ -68,7 +68,7 @@ msgid "Display Name" msgstr "" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:110 +#: code:addons/base_export_async/models/delay_export.py:127 #, python-format msgid "Export {} {}" msgstr "" @@ -107,26 +107,20 @@ msgstr "" msgid "Please select fields to export..." msgstr "" -#. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:42 -#, python-format -msgid "The user doesn't have an email address." -msgstr "" - #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids msgid "Users" msgstr "" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:29 +#: code:addons/base_export_async/models/delay_export.py:30 #, python-format msgid "You must set an email address to your user." msgstr "" #. module: base_export_async #. openerp-web -#: code:addons/base_export_async/static/src/js/data_export.js:91 +#: code:addons/base_export_async/static/src/js/data_export.js:92 #, python-format msgid "You will receive the export file by email as soon as it is finished." msgstr "" From f42a2777cadce9082c0e0164cc3f51ad8b408b0b Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 11 Jun 2020 19:22:27 +0000 Subject: [PATCH 03/15] [UPD] README.rst --- base_export_async/README.rst | 3 ++- base_export_async/static/description/index.html | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/base_export_async/README.rst b/base_export_async/README.rst index 57652068e6..aeb47ac6c0 100644 --- a/base_export_async/README.rst +++ b/base_export_async/README.rst @@ -63,7 +63,8 @@ Authors Contributors ~~~~~~~~~~~~ -Arnaud Pineux (ACSONE SA/NV) authored the initial prototype. +* Arnaud Pineux (ACSONE SA/NV) authored the initial prototype. +* Guewen Baconnier (Camptocamp) Maintainers ~~~~~~~~~~~ diff --git a/base_export_async/static/description/index.html b/base_export_async/static/description/index.html index 7620c7e958..a3b0940f19 100644 --- a/base_export_async/static/description/index.html +++ b/base_export_async/static/description/index.html @@ -408,7 +408,10 @@

Authors

Contributors

-

Arnaud Pineux (ACSONE SA/NV) authored the initial prototype.

+
    +
  • Arnaud Pineux (ACSONE SA/NV) authored the initial prototype.
  • +
  • Guewen Baconnier (Camptocamp)
  • +

Maintainers

From b59205a9b56b5e3271283974d4b4ceb220c97812 Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Thu, 11 Jun 2020 19:22:37 +0000 Subject: [PATCH 04/15] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: queue-12.0/queue-12.0-base_export_async Translate-URL: https://translation.odoo-community.org/projects/queue-12-0/queue-12-0-base_export_async/ --- base_export_async/i18n/de.po | 31 +++++++++++++++++-------------- base_export_async/i18n/zh_CN.po | 31 +++++++++++++++++-------------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/base_export_async/i18n/de.po b/base_export_async/i18n/de.po index b60d61be23..e99c126cb7 100644 --- a/base_export_async/i18n/de.po +++ b/base_export_async/i18n/de.po @@ -1,6 +1,6 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * base_export_async +# * base_export_async # msgid "" msgstr "" @@ -17,9 +17,10 @@ msgstr "" "X-Generator: Weblate 3.7.1\n" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:112 +#: code:addons/base_export_async/models/delay_export.py:129 #, python-format -msgid "\n" +msgid "" +"\n" "

Your export is available here.

\n" "

It will be automatically deleted the {}.

\n" "

 

\n" @@ -47,8 +48,10 @@ msgstr "(Der Export wird per Mail bereitgestellt.)" #. module: base_export_async #: model:ir.model,name:base_export_async.model_delay_export -msgid "Allow to delay the export" -msgstr "Verzögerung des Exports erlauben" +#, fuzzy +#| msgid "Asynchronous export" +msgid "Asynchronous Export" +msgstr "Asynchroner Export" #. module: base_export_async #. openerp-web @@ -80,7 +83,7 @@ msgid "Display Name" msgstr "Anzeigename" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:110 +#: code:addons/base_export_async/models/delay_export.py:127 #, python-format msgid "Export {} {}" msgstr "Export {} {}" @@ -119,19 +122,13 @@ msgstr "Zuletzt aktualisiert am" msgid "Please select fields to export..." msgstr "Bitte Felder für den Export auswählen..." -#. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:42 -#, python-format -msgid "The user doesn't have an email address." -msgstr "Der Benutzer hat keine Email-Adresse." - #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids msgid "Users" msgstr "Benutzer" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:29 +#: code:addons/base_export_async/models/delay_export.py:30 #, python-format msgid "You must set an email address to your user." msgstr "" @@ -139,8 +136,14 @@ msgstr "" #. module: base_export_async #. openerp-web -#: code:addons/base_export_async/static/src/js/data_export.js:91 +#: code:addons/base_export_async/static/src/js/data_export.js:92 #, python-format msgid "You will receive the export file by email as soon as it is finished." msgstr "" "Die Export-Datei wird per Email versendet, sobald der Export beendet ist." + +#~ msgid "Allow to delay the export" +#~ msgstr "Verzögerung des Exports erlauben" + +#~ msgid "The user doesn't have an email address." +#~ msgstr "Der Benutzer hat keine Email-Adresse." diff --git a/base_export_async/i18n/zh_CN.po b/base_export_async/i18n/zh_CN.po index 2ade00d5d1..c1045fa04b 100644 --- a/base_export_async/i18n/zh_CN.po +++ b/base_export_async/i18n/zh_CN.po @@ -1,6 +1,6 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * base_export_async +# * base_export_async # msgid "" msgstr "" @@ -17,9 +17,10 @@ msgstr "" "X-Generator: Weblate 3.7.1\n" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:112 +#: code:addons/base_export_async/models/delay_export.py:129 #, python-format -msgid "\n" +msgid "" +"\n" "

Your export is available here.

\n" "

It will be automatically deleted the {}.

\n" "

 

\n" @@ -46,8 +47,10 @@ msgstr "(您将通过电子邮件收到导出)" #. module: base_export_async #: model:ir.model,name:base_export_async.model_delay_export -msgid "Allow to delay the export" -msgstr "允许延迟导出" +#, fuzzy +#| msgid "Asynchronous export" +msgid "Asynchronous Export" +msgstr "异步导出" #. module: base_export_async #. openerp-web @@ -79,7 +82,7 @@ msgid "Display Name" msgstr "显示名称" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:110 +#: code:addons/base_export_async/models/delay_export.py:127 #, python-format msgid "Export {} {}" msgstr "导出{} {}" @@ -118,26 +121,26 @@ msgstr "最后更新时间" msgid "Please select fields to export..." msgstr "请选择要导出的字段..." -#. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:42 -#, python-format -msgid "The user doesn't have an email address." -msgstr "用户没有电子邮件地址。" - #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids msgid "Users" msgstr "用户" #. module: base_export_async -#: code:addons/base_export_async/models/delay_export.py:29 +#: code:addons/base_export_async/models/delay_export.py:30 #, python-format msgid "You must set an email address to your user." msgstr "您必须为您的用户设置电子邮件地址。" #. module: base_export_async #. openerp-web -#: code:addons/base_export_async/static/src/js/data_export.js:91 +#: code:addons/base_export_async/static/src/js/data_export.js:92 #, python-format msgid "You will receive the export file by email as soon as it is finished." msgstr "完成后,您将通过电子邮件收到导出文件。" + +#~ msgid "Allow to delay the export" +#~ msgstr "允许延迟导出" + +#~ msgid "The user doesn't have an email address." +#~ msgstr "用户没有电子邮件地址。" From 3a8c5d526d794fbef7d41d671e69d131fc2e7ee2 Mon Sep 17 00:00:00 2001 From: Yann Papouin Date: Fri, 20 Nov 2020 16:34:02 +0000 Subject: [PATCH 05/15] Added translation using Weblate (French) --- base_export_async/i18n/fr.po | 127 +++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 base_export_async/i18n/fr.po diff --git a/base_export_async/i18n/fr.po b/base_export_async/i18n/fr.po new file mode 100644 index 0000000000..b7a3ab34b8 --- /dev/null +++ b/base_export_async/i18n/fr.po @@ -0,0 +1,127 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_export_async +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:129 +#, python-format +msgid "\n" +"

Your export is available here.

\n" +"

It will be automatically deleted the {}.

\n" +"

 

\n" +"

\n" +" This is an automated message please do not reply.\n" +"

\n" +" " +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/xml/base.xml:9 +#, python-format +msgid "(You will receive the export by email)" +msgstr "" + +#. module: base_export_async +#: model:ir.model,name:base_export_async.model_delay_export +msgid "Asynchronous Export" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/xml/base.xml:9 +#, python-format +msgid "Asynchronous export" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_uid +msgid "Created by" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_date +msgid "Created on" +msgstr "" + +#. module: base_export_async +#: model:ir.actions.server,name:base_export_async.to_delete_attachment_ir_actions_server +#: model:ir.cron,cron_name:base_export_async.to_delete_attachment +#: model:ir.cron,name:base_export_async.to_delete_attachment +msgid "Delete Generated Exports" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__display_name +msgid "Display Name" +msgstr "" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:127 +#, python-format +msgid "Export {} {}" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:47 +#, python-format +msgid "External ID" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__id +msgid "ID" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export____last_update +msgid "Last Modified on" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:39 +#, python-format +msgid "Please select fields to export..." +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids +msgid "Users" +msgstr "" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:30 +#, python-format +msgid "You must set an email address to your user." +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:92 +#, python-format +msgid "You will receive the export file by email as soon as it is finished." +msgstr "" From c005e7302e5fa968ed7c21a62ed658bc30c4b7b9 Mon Sep 17 00:00:00 2001 From: Yann Papouin Date: Fri, 20 Nov 2020 16:40:28 +0000 Subject: [PATCH 06/15] Translated using Weblate (French) Currently translated at 100.0% (18 of 18 strings) Translation: queue-12.0/queue-12.0-base_export_async Translate-URL: https://translation.odoo-community.org/projects/queue-12-0/queue-12-0-base_export_async/fr/ --- base_export_async/i18n/fr.po | 46 ++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/base_export_async/i18n/fr.po b/base_export_async/i18n/fr.po index b7a3ab34b8..6884cb9e94 100644 --- a/base_export_async/i18n/fr.po +++ b/base_export_async/i18n/fr.po @@ -6,13 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2020-11-20 16:54+0000\n" +"Last-Translator: Yann Papouin \n" "Language-Team: none\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.10\n" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:129 @@ -26,102 +28,110 @@ msgid "\n" "

\n" " " msgstr "" +"\n" +"

Votre export est disponible ici.

\n" +"

Il sera automatiquement supprimé le {}.

\n" +"

 

\n" +"

\n" +" Ceci est un message automatisé, merci de ne pas répondre.\n" +"

\n" +" " #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/xml/base.xml:9 #, python-format msgid "(You will receive the export by email)" -msgstr "" +msgstr "(Vous recevrez cet export par courriel)" #. module: base_export_async #: model:ir.model,name:base_export_async.model_delay_export msgid "Asynchronous Export" -msgstr "" +msgstr "Export asynchrone" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/xml/base.xml:9 #, python-format msgid "Asynchronous export" -msgstr "" +msgstr "Export asynchrone" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_uid msgid "Created by" -msgstr "" +msgstr "Créé par" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_date msgid "Created on" -msgstr "" +msgstr "Créé le" #. module: base_export_async #: model:ir.actions.server,name:base_export_async.to_delete_attachment_ir_actions_server #: model:ir.cron,cron_name:base_export_async.to_delete_attachment #: model:ir.cron,name:base_export_async.to_delete_attachment msgid "Delete Generated Exports" -msgstr "" +msgstr "Supprimer les exports générés" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__display_name msgid "Display Name" -msgstr "" +msgstr "Nom affiché" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:127 #, python-format msgid "Export {} {}" -msgstr "" +msgstr "Export {} {}" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/js/data_export.js:47 #, python-format msgid "External ID" -msgstr "" +msgstr "Identifiant externe" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__id msgid "ID" -msgstr "" +msgstr "ID" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export____last_update msgid "Last Modified on" -msgstr "" +msgstr "Dernière modification le" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_uid msgid "Last Updated by" -msgstr "" +msgstr "Dernière mise à jour par" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_date msgid "Last Updated on" -msgstr "" +msgstr "Dernière mise à jour le" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/js/data_export.js:39 #, python-format msgid "Please select fields to export..." -msgstr "" +msgstr "Veuillez choisir les champs à exporter..." #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids msgid "Users" -msgstr "" +msgstr "Utilisateurs" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:30 #, python-format msgid "You must set an email address to your user." -msgstr "" +msgstr "Vous devez définir une adresse e-mail pour votre utilisateur." #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/js/data_export.js:92 #, python-format msgid "You will receive the export file by email as soon as it is finished." -msgstr "" +msgstr "Vous recevrez le fichier d'export par courriel dès qu'il sera terminé." From d7a761131555d2e7ad6864f8e3ac1f1eb3073b6e Mon Sep 17 00:00:00 2001 From: OCA Transbot Date: Sun, 22 Nov 2020 18:29:07 +0000 Subject: [PATCH 07/15] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: queue-12.0/queue-12.0-base_export_async Translate-URL: https://translation.odoo-community.org/projects/queue-12-0/queue-12-0-base_export_async/ --- base_export_async/i18n/de.po | 1 - base_export_async/i18n/zh_CN.po | 1 - 2 files changed, 2 deletions(-) diff --git a/base_export_async/i18n/de.po b/base_export_async/i18n/de.po index e99c126cb7..fec4ceff06 100644 --- a/base_export_async/i18n/de.po +++ b/base_export_async/i18n/de.po @@ -49,7 +49,6 @@ msgstr "(Der Export wird per Mail bereitgestellt.)" #. module: base_export_async #: model:ir.model,name:base_export_async.model_delay_export #, fuzzy -#| msgid "Asynchronous export" msgid "Asynchronous Export" msgstr "Asynchroner Export" diff --git a/base_export_async/i18n/zh_CN.po b/base_export_async/i18n/zh_CN.po index c1045fa04b..3845e29031 100644 --- a/base_export_async/i18n/zh_CN.po +++ b/base_export_async/i18n/zh_CN.po @@ -48,7 +48,6 @@ msgstr "(您将通过电子邮件收到导出)" #. module: base_export_async #: model:ir.model,name:base_export_async.model_delay_export #, fuzzy -#| msgid "Asynchronous export" msgid "Asynchronous Export" msgstr "异步导出" From 3e99c3d8f59b921e012c1329c83925194e7ef738 Mon Sep 17 00:00:00 2001 From: Hans Henrik Gabelgaard Date: Sun, 7 Feb 2021 15:03:55 +0000 Subject: [PATCH 08/15] Added translation using Weblate (Danish) --- base_export_async/i18n/da.po | 127 +++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 base_export_async/i18n/da.po diff --git a/base_export_async/i18n/da.po b/base_export_async/i18n/da.po new file mode 100644 index 0000000000..cd616fbbdb --- /dev/null +++ b/base_export_async/i18n/da.po @@ -0,0 +1,127 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_export_async +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:129 +#, python-format +msgid "\n" +"

Your export is available here.

\n" +"

It will be automatically deleted the {}.

\n" +"

 

\n" +"

\n" +" This is an automated message please do not reply.\n" +"

\n" +" " +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/xml/base.xml:9 +#, python-format +msgid "(You will receive the export by email)" +msgstr "" + +#. module: base_export_async +#: model:ir.model,name:base_export_async.model_delay_export +msgid "Asynchronous Export" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/xml/base.xml:9 +#, python-format +msgid "Asynchronous export" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_uid +msgid "Created by" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_date +msgid "Created on" +msgstr "" + +#. module: base_export_async +#: model:ir.actions.server,name:base_export_async.to_delete_attachment_ir_actions_server +#: model:ir.cron,cron_name:base_export_async.to_delete_attachment +#: model:ir.cron,name:base_export_async.to_delete_attachment +msgid "Delete Generated Exports" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__display_name +msgid "Display Name" +msgstr "" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:127 +#, python-format +msgid "Export {} {}" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:47 +#, python-format +msgid "External ID" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__id +msgid "ID" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export____last_update +msgid "Last Modified on" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:39 +#, python-format +msgid "Please select fields to export..." +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids +msgid "Users" +msgstr "" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:30 +#, python-format +msgid "You must set an email address to your user." +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:92 +#, python-format +msgid "You will receive the export file by email as soon as it is finished." +msgstr "" From 47beebe1360252efa6b3072e206bfa8b9bc81f33 Mon Sep 17 00:00:00 2001 From: Hans Henrik Gabelgaard Date: Sun, 7 Feb 2021 15:09:15 +0000 Subject: [PATCH 09/15] Translated using Weblate (Danish) Currently translated at 100.0% (18 of 18 strings) Translation: queue-12.0/queue-12.0-base_export_async Translate-URL: https://translation.odoo-community.org/projects/queue-12-0/queue-12-0-base_export_async/da/ --- base_export_async/i18n/da.po | 46 ++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/base_export_async/i18n/da.po b/base_export_async/i18n/da.po index cd616fbbdb..3dc0d789ed 100644 --- a/base_export_async/i18n/da.po +++ b/base_export_async/i18n/da.po @@ -6,13 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2021-02-07 17:45+0000\n" +"Last-Translator: Hans Henrik Gabelgaard \n" "Language-Team: none\n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.3.2\n" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:129 @@ -26,102 +28,110 @@ msgid "\n" "

\n" " " msgstr "" +"\n" +"

Din export er tilgængelig her.

\n" +"

Den vil atutomatisk blive slettet den {}.

\n" +"

 

\n" +"

\n" +" Dette er en automatisk besked. Undlad venlisgt at besvare.\n" +"

\n" +" " #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/xml/base.xml:9 #, python-format msgid "(You will receive the export by email)" -msgstr "" +msgstr "(Du vil modtage eksporten via mail)" #. module: base_export_async #: model:ir.model,name:base_export_async.model_delay_export msgid "Asynchronous Export" -msgstr "" +msgstr "Asynkron export" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/xml/base.xml:9 #, python-format msgid "Asynchronous export" -msgstr "" +msgstr "Asynkron export" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_uid msgid "Created by" -msgstr "" +msgstr "Oprettet af" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_date msgid "Created on" -msgstr "" +msgstr "Oprettet den" #. module: base_export_async #: model:ir.actions.server,name:base_export_async.to_delete_attachment_ir_actions_server #: model:ir.cron,cron_name:base_export_async.to_delete_attachment #: model:ir.cron,name:base_export_async.to_delete_attachment msgid "Delete Generated Exports" -msgstr "" +msgstr "Slet genererede eksporter" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__display_name msgid "Display Name" -msgstr "" +msgstr "Vist navn" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:127 #, python-format msgid "Export {} {}" -msgstr "" +msgstr "Eksport {} {}" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/js/data_export.js:47 #, python-format msgid "External ID" -msgstr "" +msgstr "External ID" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__id msgid "ID" -msgstr "" +msgstr "ID" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export____last_update msgid "Last Modified on" -msgstr "" +msgstr "Senest rettet den" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_uid msgid "Last Updated by" -msgstr "" +msgstr "Senest rettet af" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_date msgid "Last Updated on" -msgstr "" +msgstr "Senest rettet den" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/js/data_export.js:39 #, python-format msgid "Please select fields to export..." -msgstr "" +msgstr "Vælg venligst felter til eksporten..." #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids msgid "Users" -msgstr "" +msgstr "Brugere" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:30 #, python-format msgid "You must set an email address to your user." -msgstr "" +msgstr "Du skal have en email adresse på dit brugeropsæt." #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/js/data_export.js:92 #, python-format msgid "You will receive the export file by email as soon as it is finished." -msgstr "" +msgstr "Du vil modtage et link til eksporten så snart den er færdig." From 04982a9cacea01b21334f62c7f2c2390fe3817cc Mon Sep 17 00:00:00 2001 From: Pedro Castro Silva Date: Thu, 4 Mar 2021 14:29:20 +0000 Subject: [PATCH 10/15] Added translation using Weblate (Portuguese) --- base_export_async/i18n/pt.po | 127 +++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 base_export_async/i18n/pt.po diff --git a/base_export_async/i18n/pt.po b/base_export_async/i18n/pt.po new file mode 100644 index 0000000000..6969b0ed97 --- /dev/null +++ b/base_export_async/i18n/pt.po @@ -0,0 +1,127 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_export_async +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:129 +#, python-format +msgid "\n" +"

Your export is available here.

\n" +"

It will be automatically deleted the {}.

\n" +"

 

\n" +"

\n" +" This is an automated message please do not reply.\n" +"

\n" +" " +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/xml/base.xml:9 +#, python-format +msgid "(You will receive the export by email)" +msgstr "" + +#. module: base_export_async +#: model:ir.model,name:base_export_async.model_delay_export +msgid "Asynchronous Export" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/xml/base.xml:9 +#, python-format +msgid "Asynchronous export" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_uid +msgid "Created by" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_date +msgid "Created on" +msgstr "" + +#. module: base_export_async +#: model:ir.actions.server,name:base_export_async.to_delete_attachment_ir_actions_server +#: model:ir.cron,cron_name:base_export_async.to_delete_attachment +#: model:ir.cron,name:base_export_async.to_delete_attachment +msgid "Delete Generated Exports" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__display_name +msgid "Display Name" +msgstr "" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:127 +#, python-format +msgid "Export {} {}" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:47 +#, python-format +msgid "External ID" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__id +msgid "ID" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export____last_update +msgid "Last Modified on" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:39 +#, python-format +msgid "Please select fields to export..." +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids +msgid "Users" +msgstr "" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:30 +#, python-format +msgid "You must set an email address to your user." +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:92 +#, python-format +msgid "You will receive the export file by email as soon as it is finished." +msgstr "" From 7203c3d8c804beffcff3be2c72dfaf50c0745f1e Mon Sep 17 00:00:00 2001 From: Pedro Castro Silva Date: Thu, 4 Mar 2021 14:34:10 +0000 Subject: [PATCH 11/15] Translated using Weblate (Portuguese) Currently translated at 94.4% (17 of 18 strings) Translation: queue-12.0/queue-12.0-base_export_async Translate-URL: https://translation.odoo-community.org/projects/queue-12-0/queue-12-0-base_export_async/pt/ --- base_export_async/i18n/pt.po | 44 +++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/base_export_async/i18n/pt.po b/base_export_async/i18n/pt.po index 6969b0ed97..263957b21e 100644 --- a/base_export_async/i18n/pt.po +++ b/base_export_async/i18n/pt.po @@ -6,13 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2021-03-04 16:45+0000\n" +"Last-Translator: Pedro Castro Silva \n" "Language-Team: none\n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.3.2\n" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:129 @@ -26,60 +28,69 @@ msgid "\n" "

\n" " " msgstr "" +"\n" +"

A sua exportação está disponível aqui.

\n" +"

Será automaticamente eliminada em {}.

\n" +"

 

\n" +"

\n" +" Esta é uma mensagem automática. Por favor, não responda.\n" +"

\n" +" " #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/xml/base.xml:9 #, python-format msgid "(You will receive the export by email)" -msgstr "" +msgstr "(Receberá a exportação por email)" #. module: base_export_async #: model:ir.model,name:base_export_async.model_delay_export msgid "Asynchronous Export" -msgstr "" +msgstr "Exportação Assíncrona" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/xml/base.xml:9 #, python-format msgid "Asynchronous export" -msgstr "" +msgstr "Exportação assíncrona" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_uid msgid "Created by" -msgstr "" +msgstr "Criada por" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_date msgid "Created on" -msgstr "" +msgstr "Criado em" #. module: base_export_async #: model:ir.actions.server,name:base_export_async.to_delete_attachment_ir_actions_server #: model:ir.cron,cron_name:base_export_async.to_delete_attachment #: model:ir.cron,name:base_export_async.to_delete_attachment msgid "Delete Generated Exports" -msgstr "" +msgstr "Eliminar Exportações Geradas" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__display_name msgid "Display Name" -msgstr "" +msgstr "Nome a Apresentar" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:127 #, python-format msgid "Export {} {}" -msgstr "" +msgstr "Exportar {} {}" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/js/data_export.js:47 #, python-format msgid "External ID" -msgstr "" +msgstr "ID Externo" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__id @@ -89,35 +100,35 @@ msgstr "" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export____last_update msgid "Last Modified on" -msgstr "" +msgstr "Última Modificação em" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_uid msgid "Last Updated by" -msgstr "" +msgstr "Última Atualização por" #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_date msgid "Last Updated on" -msgstr "" +msgstr "Última Atualização em" #. module: base_export_async #. openerp-web #: code:addons/base_export_async/static/src/js/data_export.js:39 #, python-format msgid "Please select fields to export..." -msgstr "" +msgstr "Por favor, selecione os campos a exportar..." #. module: base_export_async #: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids msgid "Users" -msgstr "" +msgstr "Utilizadores" #. module: base_export_async #: code:addons/base_export_async/models/delay_export.py:30 #, python-format msgid "You must set an email address to your user." -msgstr "" +msgstr "Tem que atribuir um email ao seu utilizador." #. module: base_export_async #. openerp-web @@ -125,3 +136,4 @@ msgstr "" #, python-format msgid "You will receive the export file by email as soon as it is finished." msgstr "" +"Receberá o ficheiro de exportação por email assim que este estiver terminado." From 2e698034c87259949d673a50307d7d9a07492164 Mon Sep 17 00:00:00 2001 From: Sergio Zanchetta Date: Tue, 6 Jul 2021 10:15:20 +0000 Subject: [PATCH 12/15] Added translation using Weblate (Italian) --- base_export_async/i18n/it.po | 127 +++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 base_export_async/i18n/it.po diff --git a/base_export_async/i18n/it.po b/base_export_async/i18n/it.po new file mode 100644 index 0000000000..371d470376 --- /dev/null +++ b/base_export_async/i18n/it.po @@ -0,0 +1,127 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_export_async +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:129 +#, python-format +msgid "\n" +"

Your export is available here.

\n" +"

It will be automatically deleted the {}.

\n" +"

 

\n" +"

\n" +" This is an automated message please do not reply.\n" +"

\n" +" " +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/xml/base.xml:9 +#, python-format +msgid "(You will receive the export by email)" +msgstr "" + +#. module: base_export_async +#: model:ir.model,name:base_export_async.model_delay_export +msgid "Asynchronous Export" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/xml/base.xml:9 +#, python-format +msgid "Asynchronous export" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_uid +msgid "Created by" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__create_date +msgid "Created on" +msgstr "" + +#. module: base_export_async +#: model:ir.actions.server,name:base_export_async.to_delete_attachment_ir_actions_server +#: model:ir.cron,cron_name:base_export_async.to_delete_attachment +#: model:ir.cron,name:base_export_async.to_delete_attachment +msgid "Delete Generated Exports" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__display_name +msgid "Display Name" +msgstr "" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:127 +#, python-format +msgid "Export {} {}" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:47 +#, python-format +msgid "External ID" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__id +msgid "ID" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export____last_update +msgid "Last Modified on" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:39 +#, python-format +msgid "Please select fields to export..." +msgstr "" + +#. module: base_export_async +#: model:ir.model.fields,field_description:base_export_async.field_delay_export__user_ids +msgid "Users" +msgstr "" + +#. module: base_export_async +#: code:addons/base_export_async/models/delay_export.py:30 +#, python-format +msgid "You must set an email address to your user." +msgstr "" + +#. module: base_export_async +#. openerp-web +#: code:addons/base_export_async/static/src/js/data_export.js:92 +#, python-format +msgid "You will receive the export file by email as soon as it is finished." +msgstr "" From 9367a2c728d5bd631cf267fe6794de1af70fb4bd Mon Sep 17 00:00:00 2001 From: vincent-cowboy Date: Tue, 17 Jan 2023 12:37:06 +0100 Subject: [PATCH 13/15] [IMP] base_export_async: black, isort, prettier --- .pre-commit-config.yaml | 1 - base_export_async/__manifest__.py | 34 +++--- base_export_async/data/config_parameter.xml | 2 +- base_export_async/data/cron.xml | 4 +- .../migrations/12.0.1.1.0/post-migrate.py | 2 +- base_export_async/models/delay_export.py | 114 ++++++++++-------- base_export_async/security/ir_rule.xml | 14 +-- .../static/src/js/data_export.js | 103 +++++++--------- base_export_async/static/src/xml/base.xml | 7 +- .../tests/test_base_export_async.py | 66 +++++----- base_export_async/views/assets.xml | 13 +- .../odoo/addons/base_export_async | 1 + setup/base_export_async/setup.py | 6 + 13 files changed, 187 insertions(+), 180 deletions(-) create mode 120000 setup/base_export_async/odoo/addons/base_export_async create mode 100644 setup/base_export_async/setup.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2530918092..a6cb1b5d61 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,6 @@ exclude: | (?x) # NOT INSTALLABLE ADDONS - ^base_export_async/| ^base_import_async/| ^test_base_import_async/| # END NOT INSTALLABLE ADDONS diff --git a/base_export_async/__manifest__.py b/base_export_async/__manifest__.py index 9dba8ddd5e..2cb7fd87be 100644 --- a/base_export_async/__manifest__.py +++ b/base_export_async/__manifest__.py @@ -2,26 +2,22 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Base Export Async', - 'summary': """ + "name": "Base Export Async", + "summary": """ Asynchronous export with job queue """, - 'version': '12.0.1.1.0', - 'license': 'AGPL-3', - 'author': 'ACSONE SA/NV, Odoo Community Association (OCA)', - 'website': 'https://github.com/OCA/queue', - 'depends': [ - 'web', - 'queue_job' + "version": "12.0.1.1.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/queue", + "depends": ["web", "queue_job"], + "data": [ + "views/assets.xml", + "security/ir.model.access.csv", + "security/ir_rule.xml", + "data/config_parameter.xml", + "data/cron.xml", ], - 'data': [ - 'views/assets.xml', - 'security/ir.model.access.csv', - 'security/ir_rule.xml', - 'data/config_parameter.xml', - 'data/cron.xml', - ], - 'demo': [ - ], - 'qweb': ['static/src/xml/base.xml'] + "demo": [], + "qweb": ["static/src/xml/base.xml"], } diff --git a/base_export_async/data/config_parameter.xml b/base_export_async/data/config_parameter.xml index e3c1e5e35e..38ff75fd6e 100644 --- a/base_export_async/data/config_parameter.xml +++ b/base_export_async/data/config_parameter.xml @@ -1,4 +1,4 @@ - + attachment.ttl diff --git a/base_export_async/data/cron.xml b/base_export_async/data/cron.xml index ba42369ac3..7e12c92a02 100644 --- a/base_export_async/data/cron.xml +++ b/base_export_async/data/cron.xml @@ -1,8 +1,8 @@ - + Delete Generated Exports - + code model.cron_delete() 1 diff --git a/base_export_async/migrations/12.0.1.1.0/post-migrate.py b/base_export_async/migrations/12.0.1.1.0/post-migrate.py index 14f426ab3b..6ace97b1df 100644 --- a/base_export_async/migrations/12.0.1.1.0/post-migrate.py +++ b/base_export_async/migrations/12.0.1.1.0/post-migrate.py @@ -1,7 +1,7 @@ # Copyright 2019 Camptocamp # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import api, SUPERUSER_ID +from odoo import SUPERUSER_ID, api from odoo.tools.sql import column_exists diff --git a/base_export_async/models/delay_export.py b/base_export_async/models/delay_export.py index 7246768185..6e399c9a34 100644 --- a/base_export_async/models/delay_export.py +++ b/base_export_async/models/delay_export.py @@ -1,66 +1,66 @@ # Copyright 2019 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import logging +import base64 import json +import logging import operator -import base64 + from dateutil.relativedelta import relativedelta -from odoo import api, fields, models, _ +from odoo import _, api, fields, models +from odoo.exceptions import UserError + from odoo.addons.queue_job.job import job from odoo.addons.web.controllers.main import CSVExport, ExcelExport -from odoo.exceptions import UserError _logger = logging.getLogger(__name__) class DelayExport(models.Model): - _name = 'delay.export' - _description = 'Asynchronous Export' + _name = "delay.export" + _description = "Asynchronous Export" - user_ids = fields.Many2many('res.users', string='Users', index=True) + user_ids = fields.Many2many("res.users", string="Users", index=True) @api.model def delay_export(self, data): """Delay the export, called from js""" - params = json.loads(data.get('data')) + params = json.loads(data.get("data")) if not self.env.user.email: raise UserError(_("You must set an email address to your user.")) self.with_delay().export(params) @api.model def _get_file_content(self, params): - export_format = params.get('format') - raw_data = export_format != 'csv' + export_format = params.get("format") + raw_data = export_format != "csv" items = operator.itemgetter( - 'model', 'fields', 'ids', 'domain', - 'import_compat', 'context', 'user_ids' + "model", "fields", "ids", "domain", "import_compat", "context", "user_ids" )(params) - (model_name, fields_name, ids, domain, - import_compat, context, user_ids) = items + (model_name, fields_name, ids, domain, import_compat, context, user_ids) = items model = self.env[model_name].with_context( - import_compat=import_compat, **context) + import_compat=import_compat, **context + ) records = model.browse(ids) or model.search( - domain, offset=0, limit=False, order=False) + 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'] + 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', []) + 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] + columns_headers = [val["label"].strip() for val in fields_name] - if export_format == 'csv': + if export_format == "csv": csv = CSVExport() return csv.from_data(columns_headers, import_data) else: @@ -86,61 +86,69 @@ def export(self, params): """ content = self._get_file_content(params) - items = operator.itemgetter( - 'model', 'context', 'format', 'user_ids' - )(params) + items = operator.itemgetter("model", "context", "format", "user_ids")(params) model_name, context, export_format, user_ids = items - users = self.env['res.users'].browse(user_ids) + users = self.env["res.users"].browse(user_ids) - export_record = self.sudo().create({'user_ids': [(6, 0, users.ids)]}) + export_record = self.sudo().create({"user_ids": [(6, 0, users.ids)]}) name = "{}.{}".format(model_name, export_format) - attachment = self.env['ir.attachment'].create({ - 'name': name, - 'datas': base64.b64encode(content), - 'datas_fname': name, - 'type': 'binary', - 'res_model': self._name, - 'res_id': export_record.id, - }) + attachment = self.env["ir.attachment"].create( + { + "name": name, + "datas": base64.b64encode(content), + "datas_fname": name, + "type": "binary", + "res_model": self._name, + "res_id": export_record.id, + } + ) url = "{}/web/content/ir.attachment/{}/datas/{}?download=true".format( - self.env['ir.config_parameter'].sudo().get_param('web.base.url'), + self.env["ir.config_parameter"].sudo().get_param("web.base.url"), attachment.id, attachment.name, ) - time_to_live = self.env['ir.config_parameter'].sudo(). \ - get_param('attachment.ttl', 7) + time_to_live = ( + self.env["ir.config_parameter"].sudo().get_param("attachment.ttl", 7) + ) date_today = fields.Date.today() expiration_date = fields.Date.to_string( - date_today + relativedelta(days=+int(time_to_live))) + date_today + relativedelta(days=+int(time_to_live)) + ) # TODO : move to email template odoo_bot = self.sudo().env.ref("base.partner_root") email_from = odoo_bot.email model_description = self.env[model_name]._description - self.env['mail.mail'].create({ - 'email_from': email_from, - 'reply_to': email_from, - 'recipient_ids': [(6, 0, users.mapped('partner_id').ids)], - 'subject': _("Export {} {}").format( - model_description, fields.Date.to_string(fields.Date.today())), - 'body_html': _(""" + self.env["mail.mail"].create( + { + "email_from": email_from, + "reply_to": email_from, + "recipient_ids": [(6, 0, users.mapped("partner_id").ids)], + "subject": _("Export {} {}").format( + model_description, fields.Date.to_string(fields.Date.today()) + ), + "body_html": _( + """

Your export is available here.

It will be automatically deleted the {}.

 

This is an automated message please do not reply.

- """).format(url, expiration_date), - 'auto_delete': True, - }) + """ + ).format(url, expiration_date), + "auto_delete": True, + } + ) @api.model def cron_delete(self): - time_to_live = self.env['ir.config_parameter'].sudo(). \ - get_param('attachment.ttl', 7) + time_to_live = ( + self.env["ir.config_parameter"].sudo().get_param("attachment.ttl", 7) + ) date_today = fields.Date.today() date_to_delete = date_today + relativedelta(days=-int(time_to_live)) - self.search([('create_date', '<=', date_to_delete)]).unlink() + self.search([("create_date", "<=", date_to_delete)]).unlink() diff --git a/base_export_async/security/ir_rule.xml b/base_export_async/security/ir_rule.xml index 575df5b6b6..d5bbd85e41 100644 --- a/base_export_async/security/ir_rule.xml +++ b/base_export_async/security/ir_rule.xml @@ -1,13 +1,13 @@ - + Only user can read delay.export - - - - - - + + + + + + [('user_ids', 'in', user.id)] diff --git a/base_export_async/static/src/js/data_export.js b/base_export_async/static/src/js/data_export.js index 9e5065cd2a..225dde0b70 100644 --- a/base_export_async/static/src/js/data_export.js +++ b/base_export_async/static/src/js/data_export.js @@ -1,11 +1,11 @@ -odoo.define('base_export_async.DataExport', function(require) { +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 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({ @@ -14,84 +14,71 @@ odoo.define('base_export_async.DataExport', function(require) { A flag (checkbox) Async is added and if checked, call the delay export instead of the standard export. */ - start: function() { + start: function () { this._super.apply(this, arguments); - this.async = this.$('#async_export'); + this.async = this.$("#async_export"); }, - export_data: function() { + export_data: function () { var self = this; if (self.async.is(":checked")) { /* Checks from the standard method */ - var exported_fields = this.$( - '.o_fields_list option').map( - function() { + var exported_fields = this.$(".o_fields_list option") + .map(function () { return { - name: (self.records[this.value] || - this).value, - label: this.textContent || - this.innerText + name: (self.records[this.value] || this).value, + label: this.textContent || this.innerText, }; - }).get(); + }) + .get(); if (_.isEmpty(exported_fields)) { - Dialog.alert(this, _t( - "Please select fields to export..." - )); + Dialog.alert(this, _t("Please select fields to export...")); return; } if (!this.isCompatibleMode) { exported_fields.unshift({ - name: 'id', - label: _t('External ID') + name: "id", + label: _t("External ID"), }); } - var export_format = this.$export_format_inputs - .filter(':checked').val(); + var export_format = this.$export_format_inputs.filter(":checked").val(); /* Call the delay export if Async is checked */ 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() - ] + 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: Boolean( + this.$import_compat_radios.filter(":checked").val() ), - import_compat: - !! - this - .$import_compat_radios - .filter( - ':checked' - ).val(), - user_ids: [this.record.context.uid], - }) - }], - }).then(function(result) { + user_ids: [this.record.context.uid], + }), + }, + ], + }).then(function (result) { framework.unblockUI(); - Dialog.alert(this, _t( - "You will receive the export file by email as soon as it is finished." - )); + Dialog.alert( + this, + _t( + "You will receive the export file by email as soon as it is finished." + ) + ); }); } else { /* diff --git a/base_export_async/static/src/xml/base.xml b/base_export_async/static/src/xml/base.xml index 24f53a000f..387189bc7b 100644 --- a/base_export_async/static/src/xml/base.xml +++ b/base_export_async/static/src/xml/base.xml @@ -1,12 +1,13 @@ - +
diff --git a/base_export_async/tests/test_base_export_async.py b/base_export_async/tests/test_base_export_async.py index a8a7965c70..1c6e6bbd18 100644 --- a/base_export_async/tests/test_base_export_async.py +++ b/base_export_async/tests/test_base_export_async.py @@ -2,14 +2,15 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import json -from dateutil.relativedelta import relativedelta import freezegun +from dateutil.relativedelta import relativedelta -from odoo import fields import odoo.tests.common as common +from odoo import fields -data_csv = {'data': """{"format": "csv", "model": "res.partner", +data_csv = { + "data": """{"format": "csv", "model": "res.partner", "fields": [{"name": "id", "label": "External ID"}, {"name": "display_name", "label": "Display Name"}, {"name": "email", "label": "Email"}, @@ -19,9 +20,11 @@ "context": {"lang": "en_US", "tz": "Europe/Brussels", "uid": 2}, "import_compat": false, "user_ids": [2] - }"""} + }""" +} -data_xls = {'data': """{"format": "xls", "model": "res.partner", +data_xls = { + "data": """{"format": "xls", "model": "res.partner", "fields": [{"name": "id", "label": "External ID"}, {"name": "display_name", "label": "Display Name"}, {"name": "email", "label": "Email"}, @@ -31,55 +34,54 @@ "context": {"lang": "en_US", "tz": "Europe/Brussels", "uid": 2}, "import_compat": false, "user_ids": [2] - }"""} + }""" +} 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'] + 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""" + """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([]) - attachments = self.env['ir.attachment'].search([]) + """Check that the export generate an attachment and email""" + params = json.loads(data_csv.get("data")) + mails = self.env["mail.mail"].search([]) + attachments = self.env["ir.attachment"].search([]) self.delay_export_obj.export(params) - new_mail = self.env['mail.mail'].search([]) - mails - new_attachment = self.env['ir.attachment'].search([]) - attachments + new_mail = self.env["mail.mail"].search([]) - mails + new_attachment = self.env["ir.attachment"].search([]) - attachments self.assertEqual(len(new_mail), 1) - self.assertEqual(new_attachment.datas_fname, - "res.partner.csv") + self.assertEqual(new_attachment.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([]) - attachments = self.env['ir.attachment'].search([]) + """Check that the export generate an attachment and email""" + params = json.loads(data_xls.get("data")) + mails = self.env["mail.mail"].search([]) + attachments = self.env["ir.attachment"].search([]) self.delay_export_obj.export(params) - new_mail = self.env['mail.mail'].search([]) - mails - new_attachment = self.env['ir.attachment'].search([]) - attachments + new_mail = self.env["mail.mail"].search([]) - mails + new_attachment = self.env["ir.attachment"].search([]) - attachments self.assertEqual(len(new_mail), 1) - self.assertEqual(new_attachment.datas_fname, - "res.partner.xls") + self.assertEqual(new_attachment.datas_fname, "res.partner.xls") def test_cron_delete(self): - """ Check that cron delete attachment after TTL""" - params = json.loads(data_csv.get('data')) - attachments = self.env['ir.attachment'].search([]) + """Check that cron delete attachment after TTL""" + params = json.loads(data_csv.get("data")) + attachments = self.env["ir.attachment"].search([]) self.delay_export_obj.export(params) - new_attachment = self.env['ir.attachment'].search([]) - attachments - time_to_live = self.env['ir.config_parameter'].sudo(). \ - get_param('attachment.ttl', 7) + new_attachment = self.env["ir.attachment"].search([]) - attachments + time_to_live = ( + self.env["ir.config_parameter"].sudo().get_param("attachment.ttl", 7) + ) date_today = fields.Datetime.now() date_past_ttl = date_today + relativedelta(days=int(time_to_live)) with freezegun.freeze_time(date_past_ttl): diff --git a/base_export_async/views/assets.xml b/base_export_async/views/assets.xml index f0a778851c..24f276ba7e 100644 --- a/base_export_async/views/assets.xml +++ b/base_export_async/views/assets.xml @@ -1,8 +1,15 @@ - + -