Browse Source

Add module sql_export_mail

pull/1604/head
Florian da Costa 8 years ago
parent
commit
225780aa80
  1. 65
      sql_export_mail/README.rst
  2. 1
      sql_export_mail/__init__.py
  3. 39
      sql_export_mail/__openerp__.py
  4. 94
      sql_export_mail/i18n/fr.po
  5. 89
      sql_export_mail/i18n/sql_export_mail.pot
  6. 28
      sql_export_mail/mail_template.xml
  7. 1
      sql_export_mail/models/__init__.py
  8. 155
      sql_export_mail/models/sql_export.py
  9. 2
      sql_export_mail/tests/__init__.py
  10. 33
      sql_export_mail/tests/test_sql_query_mail.py
  11. 31
      sql_export_mail/views/sql_export_view.xml
  12. 1
      sql_export_mail/wizard/__init__.py
  13. 106
      sql_export_mail/wizard/wizard_file.py
  14. 27
      sql_export_mail/wizard/wizard_file_view.xml

65
sql_export_mail/README.rst

@ -0,0 +1,65 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:alt: License: AGPL-3
SQL Export Mail
===============
Allow to send the result of a query (made with the module sql_export) by mail.
Configuration
=============
To configure this module, you need to:
#. Go to the sql query for which you want users to be notified by e-mail.
#. Add users to be notified in the field Users Notified by e-mail.
#. Click on the button create a cron and then configure the cron to run when
you want to. If you already have created a cron for another query, you can
use it again for other queries
Usage
=====
To use this module, you need to:
#. Go to ...
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/149/10.0
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/server-tools/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
=======
Images
------
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_.
Contributors
------------
* Florian da Costa <florian.dacosta@akretion.com>
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.

1
sql_export_mail/__init__.py

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

39
sql_export_mail/__openerp__.py

@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2015 Akretion (<http://www.akretion.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'SQL Export Mail',
'version': '8.0.1.0.0',
'author': 'Akretion,Odoo Community Association (OCA)',
'website': 'http://www.akretion.com',
'license': 'AGPL-3',
'category': 'Generic Modules/Others',
'summary': 'Export data in csv file with SQL requests',
'depends': [
'sql_export',
'mail',
],
'data': [
'views/sql_export_view.xml',
'mail_template.xml',
],
'installable': True,
}

94
sql_export_mail/i18n/fr.po

@ -0,0 +1,94 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sql_export_mail
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-18 13:15+0000\n"
"PO-Revision-Date: 2017-07-18 13:15+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: sql_export_mail
#: model:email.template,body_html:sql_export_mail.sql_export_mailer
msgid "\n"
"<div style=\"font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
"\n"
"<p>You will find the report ${object.name or ''} as an attachment of the mail.</p>\n"
"\n"
"</div>\n"
" "
msgstr "\n"
"<div style=\"font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
"\n"
"<p>Vous trouverez le rapport ${object.name or ''} en pièce jointe de ce mail.</p>\n"
"\n"
"</div>\n"
" "
#. module: sql_export_mail
#: model:email.template,subject:sql_export_mail.sql_export_mailer
msgid "${object.name or ''}"
msgstr "${object.name or ''}"
#. module: sql_export_mail
#: help:sql.export,mail_user_ids:0
msgid "Add the users who want to receive the report by e-mail. You need to link the sql query with a cron to send mail automatically"
msgstr "Ajoutez les utilisateurs voulant recevoir le rapport par mail. Vous devez ensuite créer une tâche planifiée pour envoyer le mail automatiquement."
#. module: sql_export_mail
#: view:sql.export:sql_export_mail.sql_export_mail_view_form
msgid "Create Cron"
msgstr "Créer une tâche planfiée"
#. module: sql_export_mail
#: model:ir.model.fields,field_description:sql_export_mail.field_sql_export_cron_ids
#: view:sql.export:sql_export_mail.sql_export_mail_view_form
#: field:sql.export,cron_ids:0
msgid "Crons"
msgstr "Tâches planifiées"
#. module: sql_export_mail
#: selection:sql.export,mail_condition:0
msgid "File Not Empty"
msgstr "Fichier non vide."
#. module: sql_export_mail
#: code:addons/sql_export_mail/models/sql_export.py:126
#, python-format
msgid "It is not possible to execute and send a query automatically by e-mail if there are parameters to fill"
msgstr "Il n'est pas possible d'exécuter en envoyer le résultat d'une requête par mail si celle-ci contient des paramètres."
#. module: sql_export_mail
#: model:ir.model.fields,field_description:sql_export_mail.field_sql_export_mail_condition
#: field:sql.export,mail_condition:0
msgid "Mail condition"
msgstr "Condition d'envoi par mail"
#. module: sql_export_mail
#: model:ir.model,name:sql_export_mail.model_sql_export
msgid "SQL export"
msgstr "Export SQL"
#. module: sql_export_mail
#: code:addons/sql_export_mail/models/sql_export.py:135
#, python-format
msgid "The user does not have any e-mail address."
msgstr "L'utilisateur selectionné n'a pas d'addresse mail."
#. module: sql_export_mail
#: model:ir.model.fields,field_description:sql_export_mail.field_sql_export_mail_user_ids
#: field:sql.export,mail_user_ids:0
msgid "User to notify"
msgstr "Utilisateurs à notifier par mail"
#. module: sql_export_mail
#: view:sql.export:sql_export_mail.sql_export_mail_view_form
msgid "Users Notified by e-mail"
msgstr "Utilisateurs notifiés par mail"

89
sql_export_mail/i18n/sql_export_mail.pot

@ -0,0 +1,89 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sql_export_mail
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-18 13:24+0000\n"
"PO-Revision-Date: 2017-07-18 13:24+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: sql_export_mail
#: model:email.template,body_html:sql_export_mail.sql_export_mailer
msgid "\n"
"<div style=\"font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
"\n"
"<p>You will find the report ${object.name or ''} as an attachment of the mail.</p>\n"
"\n"
"</div>\n"
" "
msgstr ""
#. module: sql_export_mail
#: model:email.template,subject:sql_export_mail.sql_export_mailer
msgid "${object.name or ''}"
msgstr ""
#. module: sql_export_mail
#: help:sql.export,mail_user_ids:0
msgid "Add the users who want to receive the report by e-mail. You need to link the sql query with a cron to send mail automatically"
msgstr ""
#. module: sql_export_mail
#: view:sql.export:sql_export_mail.sql_export_mail_view_form
msgid "Create Cron"
msgstr ""
#. module: sql_export_mail
#: model:ir.model.fields,field_description:sql_export_mail.field_sql_export_cron_ids
#: view:sql.export:sql_export_mail.sql_export_mail_view_form
#: field:sql.export,cron_ids:0
msgid "Crons"
msgstr ""
#. module: sql_export_mail
#: selection:sql.export,mail_condition:0
msgid "File Not Empty"
msgstr ""
#. module: sql_export_mail
#: code:addons/sql_export_mail/models/sql_export.py:126
#, python-format
msgid "It is not possible to execute and send a query automatically by e-mail if there are parameters to fill"
msgstr ""
#. module: sql_export_mail
#: model:ir.model.fields,field_description:sql_export_mail.field_sql_export_mail_condition
#: field:sql.export,mail_condition:0
msgid "Mail condition"
msgstr ""
#. module: sql_export_mail
#: model:ir.model,name:sql_export_mail.model_sql_export
msgid "SQL export"
msgstr ""
#. module: sql_export_mail
#: code:addons/sql_export_mail/models/sql_export.py:135
#, python-format
msgid "The user does not have any e-mail address."
msgstr ""
#. module: sql_export_mail
#: model:ir.model.fields,field_description:sql_export_mail.field_sql_export_mail_user_ids
#: field:sql.export,mail_user_ids:0
msgid "User to notify"
msgstr ""
#. module: sql_export_mail
#: view:sql.export:sql_export_mail.sql_export_mail_view_form
msgid "Users Notified by e-mail"
msgstr ""

28
sql_export_mail/mail_template.xml

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017 Akretion (http://www.akretion.com/)
The licence is in the file __openerp__.py
-->
<openerp>
<data noupdate="1">
<!-- Error Email template -->
<record id="sql_export_mailer" model="email.template">
<field name="name">SQL Export</field>
<field name="email_from">admin@example.com</field>
<field name="email_to">${object.get_email_address_for_template()}</field>
<field name="subject">${object.name or ''}</field>
<field name="model_id" ref="sql_export.model_sql_export"/>
<field name="auto_delete" eval="True"/>
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucida Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; ">
<p>You will find the report ${object.name or ''} as an attachment of the mail.</p>
</div>
]]></field>
</record>
</data>
</openerp>

1
sql_export_mail/models/__init__.py

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

155
sql_export_mail/models/sql_export.py

@ -0,0 +1,155 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2017 Akretion (<http://www.akretion.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, fields, api, _
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.exceptions import Warning as UserError
from datetime import datetime, timedelta
from openerp import SUPERUSER_ID
class SqlExport(models.Model):
_inherit = 'sql.export'
mail_user_ids = fields.Many2many(
'res.users',
'mail_user_sqlquery_rel',
'sql_id',
'user_id',
'User to notify',
help='Add the users who want to receive the report by e-mail. You '
'need to link the sql query with a cron to send mail automatically')
cron_ids = fields.Many2many(
'ir.cron',
'cron_sqlquery_rel',
'sql_id',
'cron_id',
'Crons')
# We could implement other conditions, that is why it is a selection field
mail_condition = fields.Selection(
[('not_empty', 'File Not Empty')], default='not_empty')
@api.multi
def create_cron(self):
self.ensure_one()
nextcall = datetime.now() + timedelta(hours=2)
nextcall_fmt = datetime.strftime(nextcall,
DEFAULT_SERVER_DATETIME_FORMAT)
cron_vals = {
'active': True,
'model': 'sql.export',
'function': '_run_all_sql_export_for_cron',
'name': 'SQL Export : %s' % self.name,
'nextcall': nextcall_fmt,
'doall': False,
'numbercall': -1,
'user_id': SUPERUSER_ID,
}
cron = self.env['ir.cron'].create(cron_vals)
write_vals = {'args': '[[%s]]' % cron.id}
cron.write(write_vals)
self.write({'cron_ids': [(4, cron.id)]})
@api.one
def send_mail(self, params=None):
mail_template = self.env.ref('sql_export_mail.sql_export_mailer')
now_time = datetime.strftime(datetime.now(),
DEFAULT_SERVER_DATETIME_FORMAT)
attach_obj = self.env['ir.attachment']
if self.mail_condition == 'not_empty':
res = self._execute_sql_request(
params=params, mode='fetchone')
if not res:
return
binary = self._execute_sql_request(
params=params, mode='stdout', copy_options=self.copy_options)
attach_vals = {
'name': now_time + ' - ' + self.name,
'datas_fname': now_time + ' - ' + self.name + '.csv',
'datas': binary,
}
attachment = attach_obj.create(attach_vals)
msg_id = mail_template.send_mail(self.id, force_send=False)
mail = self.env['mail.mail'].browse(msg_id)
mail.write({'attachment_ids': [(4, attachment.id)]})
@api.model
def _run_all_sql_export_for_cron(self, cron_ids):
exports = self.search([('cron_ids', 'in', cron_ids)])
for export in exports:
if "%(company_id)s" in export.query and \
"%(user_id)s" not in export.query:
variable_dict = {}
companies = self.env['res.company'].search([])
for company in companies:
users = export.mail_user_ids.filtered(
lambda u: u.company_id == company)
if users:
variable_dict['company_id'] = users[0].company_id.id
export.with_context(mail_to=users.ids).send_mail(
params=variable_dict)
elif "%(user_id)s" in export.query:
variable_dict = {}
for user in export.mail_user_ids:
variable_dict['user_id'] = user.id
if "%(company_id)s" in export.query:
variable_dict['company_id'] = user.company_id.id
export.with_context(mail_to=[user.id]).send_mail(
params=variable_dict)
else:
export.send_mail()
@api.one
@api.constrains('field_ids', 'mail_user_ids')
def check_no_parameter_if_sent_by_mail(self):
if self.field_ids and self.mail_user_ids:
raise UserError(_(
"It is not possible to execute and send a query automatically"
" by e-mail if there are parameters to fill"))
@api.one
@api.constrains('mail_user_ids')
def check_mail_user(self):
for user in self.mail_user_ids:
if not user.email:
raise UserError(_(
"The user does not have any e-mail address."))
@api.multi
def get_email_address_for_template(self):
"""
Called from mail template
"""
self.ensure_one()
if self.env.context.get('mail_to'):
mail_users = self.env['res.users'].browse(
self.env.context.get('mail_to'))
else:
mail_users = self.mail_user_ids
emails = ''
for user in mail_users:
if emails and user.email:
emails += ',' + user.email
elif user.email:
emails += user.email
return emails

2
sql_export_mail/tests/__init__.py

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import test_sql_query_mail

33
sql_export_mail/tests/test_sql_query_mail.py

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017 Akretion (<http://www.akretion.com>)
# @author: Florian da Costa
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp.tests.common import TransactionCase
from openerp import SUPERUSER_ID
class TestExportSqlQueryMail(TransactionCase):
def setUp(self):
super(TestExportSqlQueryMail, self).setUp()
self.sql_report_demo = self.env.ref('sql_export.sql_export_partner')
self.sql_report_demo.write({'mail_user_ids': [(4, SUPERUSER_ID)]})
def test_sql_query_create_cron(self):
self.sql_report_demo.create_cron()
self.assertTrue(self.sql_report_demo.cron_ids)
cron = self.sql_report_demo.cron_ids
self.assertEqual(cron.function, '_run_all_sql_export_for_cron')
def test_sql_query_mail(self):
mail_obj = self.env['mail.mail']
mails = mail_obj.search(
[('model', '=', 'sql.export'),
('res_id', '=', self.sql_report_demo.id)])
self.assertFalse(mails)
self.sql_report_demo.send_mail()
mails = mail_obj.search(
[('model', '=', 'sql.export'),
('res_id', '=', self.sql_report_demo.id)])
self.assertTrue(mails)

31
sql_export_mail/views/sql_export_view.xml

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="sql_export_mail_view_form" model="ir.ui.view">
<field name="model">sql.export</field>
<field name="inherit_id" ref="sql_export.sql_export_view_form" />
<field name="arch" type="xml">
<button name="export_sql_query" position="after">
<button name="create_cron" string="Create Cron" type="object" groups="base.group_system"
attrs="{'invisible': ['|', ('state', '=', 'draft'), ('mail_user_ids', '=', [(6, False, [])])]}"/>
</button>
<field name="copy_options" position="after">
<field name="mail_condition" attrs="{'invisible': [('cron_ids', '=', [(6, False, [])])]}"/>
</field>
<group name="parameters" position="after">
<group groups="sql_request_abstract.group_sql_request_user">
<group string="Users Notified by e-mail">
<field name="mail_user_ids" nolabel="1"/>
</group>
<group string="Crons" groups="base.group_system">
<field name="cron_ids" nolabel="1" domain="[('function', '=', '_run_all_sql_export_for_cron')]"/>
</group>
</group>
</group>
</field>
</record>
</data>
</openerp>

1
sql_export_mail/wizard/__init__.py

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

106
sql_export_mail/wizard/wizard_file.py

@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2015 Akretion (<http://www.akretion.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime
from lxml import etree
from openerp import models, fields, api, osv
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
class SqlFileWizard(models.TransientModel):
_name = "sql.file.wizard"
_description = "Allow the user to save the file with sql request's data"
binary_file = fields.Binary('File', readonly=True)
file_name = fields.Char('File Name', readonly=True)
sql_export_id = fields.Many2one(comodel_name='sql.export', required=True)
@api.model
def fields_view_get(self, view_id=None, view_type='form',
toolbar=False, submenu=False):
"""
Display dinamicaly parameter fields depending on the sql_export.
"""
res = super(SqlFileWizard, self).fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar,
submenu=submenu)
export_obj = self.env['sql.export']
if view_type == 'form':
sql_export = export_obj.browse(self._context.get('active_id'))
if sql_export.field_ids:
eview = etree.fromstring(res['arch'])
group = etree.Element(
'group', name="variables_group", colspan="4")
toupdate_fields = []
for field in sql_export.field_ids:
kwargs = {'name': "%s" % field.name}
toupdate_fields.append(field.name)
view_field = etree.SubElement(group, 'field', **kwargs)
osv.orm.setup_modifiers(
view_field, self.fields_get(field.name))
res['fields'].update(self.fields_get(toupdate_fields))
placeholder = eview.xpath(
"//separator[@string='variables_placeholder']")[0]
placeholder.getparent().replace(
placeholder, group)
res['arch'] = etree.tostring(eview, pretty_print=True)
return res
@api.multi
def export_sql(self):
self.ensure_one()
sql_export = self.sql_export_id
# Manage Params
variable_dict = {}
today = datetime.datetime.now()
today_tz = fields.Datetime.context_timestamp(
sql_export, today)
date = today_tz.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
if sql_export.field_ids:
for field in sql_export.field_ids:
variable_dict[field.name] = self[field.name]
if "%(company_id)s" in sql_export.query:
variable_dict['company_id'] = self.env.user.company_id.id
if "%(user_id)s" in sql_export.query:
variable_dict['user_id'] = self._uid
# Execute Request
res = sql_export._execute_sql_request(
params=variable_dict, mode='stdout',
copy_options=sql_export.copy_options)
self.write({
'binary_file': res,
'file_name': sql_export.name + '_' + date + '.csv'
})
return {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'sql.file.wizard',
'res_id': self.id,
'type': 'ir.actions.act_window',
'target': 'new',
'context': self._context,
'nodestroy': True,
}

27
sql_export_mail/wizard/wizard_file_view.xml

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="sql_file_wizard_view_form" model="ir.ui.view">
<field name="name">sql.file.wizard.view.form</field>
<field name="model">sql.file.wizard</field>
<field name="arch" type="xml">
<form string="Csv File">
<separator string="variables_placeholder" colspan="4" invisible="1"/>
<separator string="Export file" colspan="4"
attrs="{'invisible': [('binary_file', '=', False)]}"/>
<field name="binary_file" filename="file_name"/>
<field name="file_name" invisible="1"/>
<footer>
<button name="export_sql" string="Export" type="object"
icon="gtk-apply" />
or
<button special="cancel" string="Cancel" type="object"
icon="gtk-cancel" />
</footer>
</form>
</field>
</record>
</data>
</openerp>
Loading…
Cancel
Save