[IMP] report_async: black, isort, prettier

pull/568/head
newtratip 2021-12-20 15:29:29 +07:00 committed by Kitti U
parent e0f8b7b531
commit 266f4b1933
17 changed files with 359 additions and 646 deletions

View File

@ -1 +1,2 @@
server-tools server-tools
queue

View File

@ -14,13 +14,13 @@ Report Async
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3 :alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
:target: https://github.com/OCA/reporting-engine/tree/12.0/report_async :target: https://github.com/OCA/reporting-engine/tree/13.0/report_async
:alt: OCA/reporting-engine :alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-report_async :target: https://translation.odoo-community.org/projects/reporting-engine-13-0/reporting-engine-13-0-report_async
:alt: Translate me on Weblate :alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/143/12.0 :target: https://runbot.odoo-community.org/runbot/143/13.0
:alt: Try me on Runbot :alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5| |badge1| |badge2| |badge3| |badge4| |badge5|
@ -76,7 +76,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/OCA/reporting-engine/issues>`_. Bugs are tracked on `GitHub Issues <https://github.com/OCA/reporting-engine/issues>`_.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_async%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. `feedback <https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_async%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues. Do not contact contributors directly about support or help with technical issues.
@ -92,6 +92,7 @@ Contributors
~~~~~~~~~~~~ ~~~~~~~~~~~~
* Kitti U. <kittiu@ecosoft.co.th> * Kitti U. <kittiu@ecosoft.co.th>
* Saran Lim. <saranl@ecosoft.co.th>
Maintainers Maintainers
~~~~~~~~~~~ ~~~~~~~~~~~
@ -114,6 +115,6 @@ Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-kittiu| |maintainer-kittiu|
This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/12.0/report_async>`_ project on GitHub. This module is part of the `OCA/reporting-engine <https://github.com/OCA/reporting-engine/tree/13.0/report_async>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@ -1,27 +1,23 @@
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) # Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
{ {
'name': 'Report Async', "name": "Report Async",
'summary': 'Central place to run reports live or async', "summary": "Central place to run reports live or async",
'version': '12.0.1.0.1', "version": "14.0.1.0.0",
'author': 'Ecosoft, Odoo Community Association (OCA)', "author": "Ecosoft, Odoo Community Association (OCA)",
'license': 'AGPL-3', "license": "AGPL-3",
'website': 'https://github.com/OCA/reporting-engine', "website": "https://github.com/OCA/reporting-engine",
'category': 'Generic Modules', "category": "Generic Modules",
'depends': [ "depends": ["queue_job"],
'queue_job', "data": [
"security/ir.model.access.csv",
"security/ir_rule.xml",
"data/mail_template.xml",
"views/report_async.xml",
"wizard/print_report_wizard.xml",
], ],
'data': [ "demo": ["demo/report_async_demo.xml"],
'security/ir.model.access.csv', "installable": True,
'security/ir_rule.xml', "maintainers": ["kittiu"],
'data/mail_template.xml', "development_status": "Beta",
'views/report_async.xml',
'wizard/print_report_wizard.xml',
],
'demo': [
'demo/report_async_demo.xml',
],
'installable': True,
'maintainers': ['kittiu'],
'development_status': 'Beta',
} }

View File

@ -1,46 +1,73 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<data noupdate="1"> <data noupdate="1">
<record id="async_report_delivery" model="mail.template"> <record id="async_report_delivery" model="mail.template">
<field name="name">Report Async: New Report Available</field> <field name="name">Report Async: New Report Available</field>
<field name="model_id" ref="base.model_ir_attachment"/> <field name="model_id" ref="base.model_ir_attachment" />
<field name="subject">Your report is available, ${object.name}</field> <field name="subject">Your report is available, ${object.name}</field>
<field name="email_from">${object.company_id.partner_id.email_formatted|safe}</field> <field
name="email_from"
>${object.company_id.partner_id.email_formatted|safe}</field>
<field name="partner_to">${user.partner_id.id}</field> <field name="partner_to">${user.partner_id.id}</field>
<field name="body_html" type="html"> <field name="body_html" type="html">
<table border="0" cellpadding="0" cellspacing="0" style="background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;"> <table
<tr> border="0"
<td align="center"> cellpadding="0"
<table border="0" cellpadding="0" cellspacing="0" width="590" style="padding: 16px; background-color: white; color: #454748; border-collapse:separate;"> cellspacing="0"
<tbody> style="background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;"
>
<tr> <tr>
<td align="center" style="min-width: 590px;"> <td align="center">
<table border="0" cellpadding="0" cellspacing="0" width="590" style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;"> <table
<tr> border="0"
<td valign="top" style="font-size: 13px;"> cellpadding="0"
cellspacing="0"
width="590"
style="padding: 16px; background-color: white; color: #454748; border-collapse:separate;"
>
<tbody>
<tr>
<td align="center" style="min-width: 590px;">
<table
border="0"
cellpadding="0"
cellspacing="0"
width="590"
style="min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;"
>
<tr>
<td
valign="top"
style="font-size: 13px;"
>
% set base_url = object.env['ir.config_parameter'].sudo().get_param('web.base.url') % set base_url = object.env['ir.config_parameter'].sudo().get_param('web.base.url')
% set download_url = '%s/web/content/ir.attachment/%s/datas/%s?download=true' % (base_url, object.id, object.name, ) % set download_url = '%s/web/content/ir.attachment/%s/datas/%s?download=true' % (base_url, object.id, object.name, )
<div> <div>
Dear ${object.create_uid.partner_id.name or ''}, Dear ${object.create_uid.partner_id.name or ''},
<br/><br/> <br /><br />
Your requested report, ${object.name}, is available for <b><a href='${download_url}'>download</a></b>. Your requested report, ${object.name}, is available for <b
<br/><br/> >
<a
href='${download_url}'
>download</a>
</b>.
<br /><br />
Have a nice day!<br /> Have a nice day!<br />
--<br/>${object.company_id.name} --<br />${object.company_id.name}
</div> </div>
</td> </td>
</tr> </tr>
</table>
</td>
</tr>
</tbody>
</table> </table>
</td> </td>
</tr> </tr>
</tbody> </table>
</table>
</td>
</tr>
</table>
</field> </field>
<field name="auto_delete" eval="True"/> <field name="auto_delete" eval="True" />
<field name="user_signature" eval="False"/> <field name="user_signature" eval="False" />
</record> </record>
</data> </data>
</odoo> </odoo>

View File

@ -1,9 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="report_async_print_document" model="report.async"> <record id="report_async_print_document" model="report.async">
<field name="action_id" eval="ref('report_async.action_print_report_wizard')"/> <field name="action_id" eval="ref('report_async.action_print_report_wizard')" />
<field name="allow_async" eval="0"/> <field name="allow_async" eval="0" />
</record> </record>
</odoo> </odoo>

View File

@ -1,378 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * report_async
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2021-03-13 20:45+0000\n"
"Last-Translator: Pedro Castro Silva <pedrocs@exo.pt>\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: report_async
#: model:mail.template,body_html:report_async.async_report_delivery
msgid "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;\">\n"
" <tr>\n"
" <td align=\"center\">\n"
" <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"590\" style=\"padding: 16px; background-color: white; color: #454748; border-collapse:separate;\">\n"
" <tbody>\n"
" <tr>\n"
" <td align=\"center\" style=\"min-width: 590px;\">\n"
" <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"590\" style=\"min-width: 590px; background-color: white; padding: 0px 8px 0px 8px; border-collapse:separate;\">\n"
" <tr>\n"
" <td valign=\"top\" style=\"font-size: 13px;\">\n"
" % set base_url = object.env['ir.config_parameter'].sudo().get_param('web.base.url')\n"
" % set download_url = '%s/web/content/ir.attachment/%s/datas/%s?download=true' % (base_url, object.id, object.name, )\n"
" <div>\n"
" Dear ${object.create_uid.partner_id.name or ''},\n"
" <br/><br/>\n"
" Your requested report, ${object.name}, is available for <b><a href=\"${download_url}\">download</a></b>.\n"
" <br/><br/>\n"
" Have a nice day!<br/>\n"
" --<br/>${object.company_id.name}\n"
" </div>\n"
" </td>\n"
" </tr>\n"
" </table>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </td>\n"
" </tr>\n"
"</table>\n"
" "
msgstr ""
"<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"background-"
"color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width:"
" 100%; border-collapse:separate;\">\n"
" <tr>\n"
" <td align=\"center\">\n"
" <table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width="
"\"590\" style=\"padding: 16px; background-color: white; color: #454748; "
"border-collapse:separate;\">\n"
" <tbody>\n"
" <tr>\n"
" <td align=\"center\" style=\"min-width: 590px;\">\n"
" <table border=\"0\" cellpadding=\"0\" "
"cellspacing=\"0\" width=\"590\" style=\"min-width: 590px; background-color: "
"white; padding: 0px 8px 0px 8px; border-collapse:separate;\">\n"
" <tr>\n"
" <td valign=\"top\" style=\"font-size: "
"13px;\">\n"
" % set base_url = object.env['ir."
"config_parameter'].sudo().get_param('web.base.url')\n"
" % set download_url = '%s/web/content/"
"ir.attachment/%s/datas/%s?download=true' % (base_url, object.id, "
"object.name, )\n"
" <div>\n"
" Caro ${"
"object.create_uid.partner_id.name or ''},\n"
" <br/><br/>\n"
" O seu relatório solicitado, "
"${object.name}, está disponível para <b><a href=\"${download_url}\""
">download</a></b>.\n"
" <br/><br/>\n"
" Tenha um bom dia!<br/>\n"
" --<br/>${object.company_id.name}"
"\n"
" </div>\n"
" </td>\n"
" </tr>\n"
" </table>\n"
" </td>\n"
" </tr>\n"
" </tbody>\n"
" </table>\n"
" </td>\n"
" </tr>\n"
"</table>\n"
" "
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__allow_async
msgid "Allow Async"
msgstr "Permitir Assincronia"
#. module: report_async
#: code:addons/report_async/models/report_async.py:108
#, python-format
msgid "Background process not allowed."
msgstr "Processo background não permitido."
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.print_report_wizard
msgid "Cancel"
msgstr "Cancelar"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard__create_uid
#: model:ir.model.fields,field_description:report_async.field_report_async__create_uid
msgid "Created by"
msgstr "Criado por"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard__create_date
#: model:ir.model.fields,field_description:report_async.field_report_async__create_date
msgid "Created on"
msgstr "Criado em"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard__display_name
#: model:ir.model.fields,field_description:report_async.field_report_async__display_name
msgid "Display Name"
msgstr "Nome a Exibir"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard__reference
msgid "Document"
msgstr "Documento"
#. module: report_async
#: selection:report.async,job_status:0
msgid "Done"
msgstr "Concluído"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__email_notify
msgid "Email Notification"
msgstr "Notificação de Email"
#. module: report_async
#: selection:report.async,job_status:0
msgid "Enqueued"
msgstr "Enfileirado"
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.print_report_wizard
msgid "Execute"
msgstr "Executar"
#. module: report_async
#: selection:report.async,job_status:0
msgid "Failed"
msgstr "Falhou"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__file_ids
msgid "File"
msgstr "Ficheiro"
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_form
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_tree
msgid "Files"
msgstr "Ficheiros"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__group_ids
msgid "Groups"
msgstr "Grupos"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard__id
#: model:ir.model.fields,field_description:report_async.field_report_async__id
msgid "ID"
msgstr "ID"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__job_ids
msgid "Job"
msgstr "Trabalho"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__job_info
msgid "Job Info"
msgstr "Informações do Trabalho"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__job_status
msgid "Job Status"
msgstr "Estado do Trabalho"
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_form
msgid "Jobs"
msgstr "Jobs"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard____last_update
#: model:ir.model.fields,field_description:report_async.field_report_async____last_update
msgid "Last Modified on"
msgstr "Última Modificação em"
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_form
msgid "Last Run Job Error"
msgstr "Erro na última execução do trabalho"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard__write_uid
#: model:ir.model.fields,field_description:report_async.field_report_async__write_uid
msgid "Last Updated by"
msgstr "Última Atualização por"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard__write_date
#: model:ir.model.fields,field_description:report_async.field_report_async__write_date
msgid "Last Updated on"
msgstr "Última Atualização em"
#. module: report_async
#: model:ir.model.fields,help:report_async.field_report_async__job_info
msgid "Latest Job Error Message"
msgstr "Mensagem de Erro do Trabalho Mais Recente"
#. module: report_async
#: model:ir.model.fields,help:report_async.field_report_async__job_status
msgid "Latest Job Status"
msgstr "Estado do Trabalho Mais Recente"
#. module: report_async
#: model:ir.model.fields,help:report_async.field_report_async__file_ids
msgid "List all files created by this report background process"
msgstr ""
"Listar todos os arquivos criados por este processo de relatório em background"
#. module: report_async
#: model:ir.model.fields,help:report_async.field_report_async__job_ids
msgid "List all jobs related to this running report"
msgstr "Listar todos os trabalhos relacionados a este relatório em curso"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__name
msgid "Name"
msgstr "Nome"
#. module: report_async
#: model_terms:ir.actions.act_window,help:report_async.action_view_files
msgid "No files found"
msgstr "Nenhum arquivo encontrado"
#. module: report_async
#: model:ir.model.fields,help:report_async.field_report_async__group_ids
msgid "Only user in selected groups can use this report.If left blank, everyone can use"
msgstr ""
"Apenas utilizadores em grupos selecionados podem usar este relatório. Se "
"deixado vazio, qualquer um o pode usar"
#. module: report_async
#: selection:report.async,job_status:0
msgid "Pending"
msgstr "Pendente"
#. module: report_async
#: model:ir.actions.act_window,name:report_async.action_print_report_wizard
msgid "Print Document"
msgstr "Imprimir Documento"
#. module: report_async
#: model:ir.model,name:report_async.model_print_report_wizard
msgid "Print Report Wizard"
msgstr "Assistente de Impressão de Relatório"
#. module: report_async
#: model:ir.model,name:report_async.model_ir_actions_report
msgid "Report Action"
msgstr "Ação de Relatório"
#. module: report_async
#: model:ir.model,name:report_async.model_report_async
msgid "Report Async"
msgstr "Relatório Async"
#. module: report_async
#: model:ir.actions.act_window,name:report_async.action_report_async
#: model:ir.ui.menu,name:report_async.menu_report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_search
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_tree
msgid "Report Center"
msgstr "Centro de Relatórios"
#. module: report_async
#: model:ir.actions.act_window,name:report_async.action_view_files
msgid "Report Files"
msgstr "Ficheiros de Relatórios"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_print_report_wizard__action_report_id
msgid "Report Template"
msgstr "Modelo de Relatório"
#. module: report_async
#: model:ir.model.fields,field_description:report_async.field_report_async__action_id
msgid "Reports"
msgstr "Relatórios"
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_form
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_tree
msgid "Run Background"
msgstr "Executar Background"
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_form
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_tree
msgid "Run Now"
msgstr "Executar Agora"
#. module: report_async
#: model_terms:ir.actions.act_window,help:report_async.action_report_async
msgid "Run reports asyncronously"
msgstr "Executar relatórios de forma assíncrona"
#. module: report_async
#: model:ir.model.fields,help:report_async.field_report_async__email_notify
msgid "Send email with link to report, when it is ready"
msgstr "Enviar e-mail com link para o relatório quando este estiver pronto"
#. module: report_async
#: selection:report.async,job_status:0
msgid "Started"
msgstr "Iniciado"
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_form
msgid "The last <i class=\"fa fa-cogs\"/> <b>running job</b> was failed.\n"
" Please contact your system administrator."
msgstr ""
"O último <i class=\"fa fa-cogs\"/> <b>trabalho em curso</b> falhou. Por "
"favor, contacte o administrador do sistema."
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_form
msgid "The last <i class=\"fa fa-cogs\"/> <b>running job</b> was succeed.\n"
" You can check the result in <i class=\"fa fa-copy\"/><b> Files</b>"
msgstr ""
"O último <i class=\"fa fa-cogs\"/> <b>trabalho em curso</b> foi bem sucedido."
"\n"
" Pode verificar o resultado em <i class=\"fa fa-copy\""
"/><b> Ficheiros</b>"
#. module: report_async
#: model_terms:ir.ui.view,arch_db:report_async.view_report_async_form
msgid "The report will be running by <i class=\"fa fa-cogs\"/>\n"
" <b>job</b>, and will be available at\n"
" <i class=\"fa fa-copy\"/><b> Files</b>"
msgstr ""
"O relatório será executado por <i class=\"fa fa-cogs\"/> <b>trabalho</b> e "
"estará disponível em <i class=\"fa fa-copy\"/><b> Arquivos</b>"
#. module: report_async
#: model:ir.model.fields,help:report_async.field_report_async__allow_async
msgid "This is not automatic field, please check if you want to allow this report in background process"
msgstr ""
"Este campo não é automático. Por favor, verifique se deseja permitir este "
"relatório em processo background"
#. module: report_async
#: model:mail.template,subject:report_async.async_report_delivery
msgid "Your report is available, ${object.name}"
msgstr "Seu relatório está disponível, ${object.name}"

View File

@ -1,28 +1,23 @@
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) # Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from odoo import api, models from odoo import models
# Define all supported report_type # Define all supported report_type
REPORT_TYPES = ['qweb-pdf', 'qweb-text', REPORT_TYPES = ["qweb-pdf", "qweb-text", "qweb-xml", "csv", "excel", "xlsx"]
'qweb-xml', 'csv',
'excel', 'xlsx']
class Report(models.Model): class Report(models.Model):
_inherit = 'ir.actions.report' _inherit = "ir.actions.report"
@api.noguess
def report_action(self, docids, data=None, config=True): def report_action(self, docids, data=None, config=True):
res = super(Report, self).report_action(docids, data=data, res = super(Report, self).report_action(docids, data=data, config=config)
config=config) if res["context"].get("async_process", False):
if res['context'].get('async_process', False): rpt_async_id = res["context"]["active_id"]
rpt_async_id = res['context']['active_id'] report_async = self.env["report.async"].browse(rpt_async_id)
report_async = self.env['report.async'].browse(rpt_async_id) if res["report_type"] in REPORT_TYPES:
if res['report_type'] in REPORT_TYPES:
report_async.with_delay().run_report( report_async.with_delay().run_report(
res['context'].get('active_ids', []), data, res["context"].get("active_ids", []), data, self.id, self._uid
self.id, self._uid) )
return {} return {}
return res return res

View File

@ -2,93 +2,104 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
import base64 import base64
from odoo import api, fields, models, _
from odoo.tools.safe_eval import safe_eval from odoo import _, api, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.tools.safe_eval import safe_eval
from odoo.addons.queue_job.job import job from odoo.addons.queue_job.job import job
# Define all supported report_type # Define all supported report_type
REPORT_TYPES_FUNC = {'qweb-pdf': 'render_qweb_pdf', REPORT_TYPES_FUNC = {
'qweb-text': 'render_qweb_text', "qweb-pdf": "render_qweb_pdf",
'qweb-xml': 'render_qweb_xml', "qweb-text": "render_qweb_text",
'csv': 'render_csv', "qweb-xml": "render_qweb_xml",
'excel': 'render_excel', "csv": "render_csv",
'xlsx': 'render_xlsx', } "excel": "render_excel",
"xlsx": "render_xlsx",
}
class ReportAsync(models.Model): class ReportAsync(models.Model):
_name = 'report.async' _name = "report.async"
_description = 'Report Async' _description = "Report Async"
action_id = fields.Many2one( action_id = fields.Many2one(
comodel_name='ir.actions.act_window', comodel_name="ir.actions.act_window",
string='Reports', string="Reports",
required=True, required=True,
) )
allow_async = fields.Boolean( allow_async = fields.Boolean(
string='Allow Async', string="Allow Async",
default=False, default=False,
help="This is not automatic field, please check if you want to allow " help="This is not automatic field, please check if you want to allow "
"this report in background process", "this report in background process",
) )
name = fields.Char( name = fields.Char(
string='Name', string="Name",
related='action_id.display_name', related="action_id.display_name",
) )
email_notify = fields.Boolean( email_notify = fields.Boolean(
string='Email Notification', string="Email Notification",
help="Send email with link to report, when it is ready", help="Send email with link to report, when it is ready",
) )
group_ids = fields.Many2many( group_ids = fields.Many2many(
string='Groups', string="Groups",
comodel_name='res.groups', comodel_name="res.groups",
help="Only user in selected groups can use this report." help="Only user in selected groups can use this report."
"If left blank, everyone can use", "If left blank, everyone can use",
) )
job_ids = fields.Many2many( job_ids = fields.Many2many(
comodel_name='queue.job', comodel_name="queue.job",
compute='_compute_job', compute="_compute_job",
help="List all jobs related to this running report", help="List all jobs related to this running report",
) )
job_status = fields.Selection( job_status = fields.Selection(
selection=[('pending', 'Pending'), selection=[
('enqueued', 'Enqueued'), ("pending", "Pending"),
('started', 'Started'), ("enqueued", "Enqueued"),
('done', 'Done'), ("started", "Started"),
('failed', 'Failed')], ("done", "Done"),
compute='_compute_job', ("failed", "Failed"),
],
compute="_compute_job",
help="Latest Job Status", help="Latest Job Status",
) )
job_info = fields.Text( job_info = fields.Text(
compute='_compute_job', compute="_compute_job",
help="Latest Job Error Message", help="Latest Job Error Message",
) )
file_ids = fields.Many2many( file_ids = fields.Many2many(
comodel_name='ir.attachment', comodel_name="ir.attachment",
compute='_compute_file', compute="_compute_file",
help="List all files created by this report background process", help="List all files created by this report background process",
) )
@api.multi
def _compute_job(self): def _compute_job(self):
for rec in self: for rec in self:
rec.job_ids = self.sudo().env['queue.job'].search( rec.job_ids = (
[('func_string', 'like', 'report.async(%s,)' % rec.id), self.sudo()
('user_id', '=', self._uid)], .env["queue.job"]
order='id desc') .search(
rec.job_status = (rec.job_ids[0].sudo().state [
if rec.job_ids else False) ("func_string", "like", "report.async(%s,)" % rec.id),
rec.job_info = (rec.job_ids[0].sudo().exc_info ("user_id", "=", self._uid),
if rec.job_ids else False) ],
order="id desc",
)
)
rec.job_status = rec.job_ids[0].sudo().state if rec.job_ids else False
rec.job_info = rec.job_ids[0].sudo().exc_info if rec.job_ids else False
@api.multi
def _compute_file(self): def _compute_file(self):
files = self.env['ir.attachment'].search( files = self.env["ir.attachment"].search(
[('res_model', '=', 'report.async'), [
('res_id', 'in', self.ids), ("res_model", "=", "report.async"),
('create_uid', '=', self._uid)], ("res_id", "in", self.ids),
order='id desc') ("create_uid", "=", self._uid),
],
order="id desc",
)
for rec in self: for rec in self:
rec.file_ids = files.filtered(lambda l: l.res_id == rec.id) rec.file_ids = files.filtered(lambda l: l.res_id == rec.id)
@ -96,67 +107,72 @@ class ReportAsync(models.Model):
self.ensure_one() self.ensure_one()
action = self.env.ref(self.action_id.xml_id) action = self.env.ref(self.action_id.xml_id)
result = action.read()[0] result = action.read()[0]
ctx = safe_eval(result.get('context', {})) ctx = safe_eval(result.get("context", {}))
ctx.update({'async_process': False}) ctx.update({"async_process": False})
result['context'] = ctx result["context"] = ctx
return result return result
@api.multi
def run_async(self): def run_async(self):
self.ensure_one() self.ensure_one()
if not self.allow_async: if not self.allow_async:
raise UserError(_('Background process not allowed.')) raise UserError(_("Background process not allowed."))
action = self.env.ref(self.action_id.xml_id) action = self.env.ref(self.action_id.xml_id)
result = action.read()[0] result = action.read()[0]
ctx = safe_eval(result.get('context', {})) ctx = safe_eval(result.get("context", {}))
ctx.update({'async_process': True}) ctx.update({"async_process": True})
result['context'] = ctx result["context"] = ctx
return result return result
@api.multi
def view_files(self): def view_files(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('report_async.action_view_files') action = self.env.ref("report_async.action_view_files")
result = action.read()[0] result = action.read()[0]
result['domain'] = [('id', 'in', self.file_ids.ids)] result["domain"] = [("id", "in", self.file_ids.ids)]
return result return result
@api.multi
def view_jobs(self): def view_jobs(self):
self.ensure_one() self.ensure_one()
action = self.env.ref('queue_job.action_queue_job') action = self.env.ref("queue_job.action_queue_job")
result = action.read()[0] result = action.read()[0]
result['domain'] = [('id', 'in', self.job_ids.ids)] result["domain"] = [("id", "in", self.job_ids.ids)]
result['context'] = {} result["context"] = {}
return result return result
@api.model @api.model
@job @job
def run_report(self, docids, data, report_id, user_id): def run_report(self, docids, data, report_id, user_id):
report = self.env['ir.actions.report'].browse(report_id) report = self.env["ir.actions.report"].browse(report_id)
func = REPORT_TYPES_FUNC[report.report_type] func = REPORT_TYPES_FUNC[report.report_type]
# Run report # Run report
out_file, file_ext = getattr(report, func)(docids, data) out_file, file_ext = getattr(report, func)(docids, data)
out_file = base64.b64encode(out_file) out_file = base64.b64encode(out_file)
out_name = '%s.%s' % (report.name, file_ext) out_name = "{}.{}".format(report.name, file_ext)
# Save report to attachment # Save report to attachment
attachment = self.env['ir.attachment'].sudo().create({ attachment = (
'name': out_name, self.env["ir.attachment"]
'datas': out_file, .sudo()
'datas_fname': out_name, .create(
'type': 'binary', {
'res_model': 'report.async', "name": out_name,
'res_id': self.id, "datas": out_file,
}) "type": "binary",
self._cr.execute(""" "res_model": "report.async",
"res_id": self.id,
}
)
)
self._cr.execute(
"""
UPDATE ir_attachment SET create_uid = %s, write_uid = %s UPDATE ir_attachment SET create_uid = %s, write_uid = %s
WHERE id = %s""", (self._uid, self._uid, attachment.id)) WHERE id = %s""",
(self._uid, self._uid, attachment.id),
)
# Send email # Send email
if self.email_notify: if self.email_notify:
self._send_email(attachment) self._send_email(attachment)
def _send_email(self, attachment): def _send_email(self, attachment):
template = self.env.ref('report_async.async_report_delivery') template = self.env.ref("report_async.async_report_delivery")
template.send_mail(attachment.id, template.send_mail(
notif_layout='mail.mail_notification_light', attachment.id, notif_layout="mail.mail_notification_light", force_send=False
force_send=False) )

View File

@ -1 +1,2 @@
* Kitti U. <kittiu@ecosoft.co.th> * Kitti U. <kittiu@ecosoft.co.th>
* Saran Lim. <saranl@ecosoft.co.th>

View File

@ -1,23 +1,25 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="rule_report_async_access_by_group" model="ir.rule"> <record id="rule_report_async_access_by_group" model="ir.rule">
<field name="name">Report Async by Groups</field> <field name="name">Report Async by Groups</field>
<field name="model_id" ref="model_report_async"/> <field name="model_id" ref="model_report_async" />
<field name="groups" eval="[(4, ref('base.group_user'))]"/> <field name="groups" eval="[(4, ref('base.group_user'))]" />
<field name="perm_read" eval="True"/> <field name="perm_read" eval="True" />
<field name="perm_create" eval="False"/> <field name="perm_create" eval="False" />
<field name="perm_write" eval="False"/> <field name="perm_write" eval="False" />
<field name="perm_unlink" eval="False"/> <field name="perm_unlink" eval="False" />
<field name="domain_force">['|', ('group_ids', '=', False), ('group_ids', 'in', [g.id for g in user.groups_id])]</field> <field
name="domain_force"
>['|', ('group_ids', '=', False), ('group_ids', 'in', [g.id for g in user.groups_id])]</field>
</record> </record>
<record id="rule_report_async_access_all" model="ir.rule"> <record id="rule_report_async_access_all" model="ir.rule">
<field name="name">Report Async by Groups</field> <field name="name">Report Async by Groups</field>
<field name="model_id" ref="model_report_async"/> <field name="model_id" ref="model_report_async" />
<field name="groups" eval="[(4, ref('base.group_no_one'))]"/> <field name="groups" eval="[(4, ref('base.group_no_one'))]" />
<field name="perm_read" eval="True"/> <field name="perm_read" eval="True" />
<field name="perm_create" eval="True"/> <field name="perm_create" eval="True" />
<field name="perm_write" eval="True"/> <field name="perm_write" eval="True" />
<field name="perm_unlink" eval="True"/> <field name="perm_unlink" eval="True" />
<field name="domain_force">[(1,'=', 1)]</field> <field name="domain_force">[(1,'=', 1)]</field>
</record> </record>
</odoo> </odoo>

View File

@ -367,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !! !! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !! !! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/12.0/report_async"><img alt="OCA/reporting-engine" src="https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-report_async"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/143/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p> <p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/13.0/report_async"><img alt="OCA/reporting-engine" src="https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/reporting-engine-13-0/reporting-engine-13-0-report_async"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/143/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>The new menu “Report Center” is the central place to host your reports in one place. <p>The new menu “Report Center” is the central place to host your reports in one place.
From here, there are 2 ways to launch the report,</p> From here, there are 2 ways to launch the report,</p>
<ol class="arabic simple"> <ol class="arabic simple">
@ -424,7 +424,7 @@ report will be sent.</li>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>. <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/reporting-engine/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_async%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> <a class="reference external" href="https://github.com/OCA/reporting-engine/issues/new?body=module:%20report_async%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p> <p>Do not contact contributors directly about support or help with technical issues.</p>
</div> </div>
<div class="section" id="credits"> <div class="section" id="credits">
@ -439,6 +439,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<h2><a class="toc-backref" href="#id5">Contributors</a></h2> <h2><a class="toc-backref" href="#id5">Contributors</a></h2>
<ul class="simple"> <ul class="simple">
<li>Kitti U. &lt;<a class="reference external" href="mailto:kittiu&#64;ecosoft.co.th">kittiu&#64;ecosoft.co.th</a>&gt;</li> <li>Kitti U. &lt;<a class="reference external" href="mailto:kittiu&#64;ecosoft.co.th">kittiu&#64;ecosoft.co.th</a>&gt;</li>
<li>Saran Lim. &lt;<a class="reference external" href="mailto:saranl&#64;ecosoft.co.th">saranl&#64;ecosoft.co.th</a>&gt;</li>
</ul> </ul>
</div> </div>
<div class="section" id="maintainers"> <div class="section" id="maintainers">
@ -450,7 +451,7 @@ mission is to support the collaborative development of Odoo features and
promote its widespread use.</p> promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p> <p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/kittiu"><img alt="kittiu" src="https://github.com/kittiu.png?size=40px" /></a></p> <p><a class="reference external" href="https://github.com/kittiu"><img alt="kittiu" src="https://github.com/kittiu.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/12.0/report_async">OCA/reporting-engine</a> project on GitHub.</p> <p>This module is part of the <a class="reference external" href="https://github.com/OCA/reporting-engine/tree/13.0/report_async">OCA/reporting-engine</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p> <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div> </div>
</div> </div>

View File

@ -1,26 +1,26 @@
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) # Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from odoo.exceptions import UserError
from odoo.tests import common from odoo.tests import common
from odoo.tests.common import Form from odoo.tests.common import Form
from odoo.exceptions import UserError
class TestJobChannel(common.TransactionCase): class TestJobChannel(common.TransactionCase):
def setUp(self): def setUp(self):
super(TestJobChannel, self).setUp() super(TestJobChannel, self).setUp()
self.print_doc = self.env.ref('report_async.' self.print_doc = self.env.ref("report_async." "report_async_print_document")
'report_async_print_document') self.test_rec = self.env.ref("base.module_mail")
self.test_rec = self.env.ref('base.module_mail') self.test_rpt = self.env.ref("base.ir_module_reference_print")
self.test_rpt = self.env.ref('base.ir_module_reference_print')
def _print_wizard(self, res): def _print_wizard(self, res):
obj = self.env[res['res_model']] obj = self.env[res["res_model"]]
ctx = {'active_model': self.print_doc._name, ctx = {
'active_id': self.print_doc.id, } "active_model": self.print_doc._name,
ctx.update(res['context']) "active_id": self.print_doc.id,
}
ctx.update(res["context"])
with Form(obj.with_context(ctx)) as form: with Form(obj.with_context(ctx)) as form:
form.reference = '%s,%s' % (self.test_rec._name, self.test_rec.id) form.reference = "{},{}".format(self.test_rec._name, self.test_rec.id)
form.action_report_id = self.test_rpt form.action_report_id = self.test_rpt
print_wizard = form.save() print_wizard = form.save()
return print_wizard return print_wizard
@ -29,19 +29,18 @@ class TestJobChannel(common.TransactionCase):
"""Run now will return report action as normal""" """Run now will return report action as normal"""
res = self.print_doc.run_now() res = self.print_doc.run_now()
report_action = self._print_wizard(res).print_report() report_action = self._print_wizard(res).print_report()
self.assertEquals(report_action['type'], 'ir.actions.report') self.assertEquals(report_action["type"], "ir.actions.report")
def test_2_run_async(self): def test_2_run_async(self):
"""Run background will return nothing, job started""" """Run background will return nothing, job started"""
with self.assertRaises(UserError): with self.assertRaises(UserError):
self.print_doc.run_async() self.print_doc.run_async()
self.print_doc.write({'allow_async': True, self.print_doc.write({"allow_async": True, "email_notify": True})
'email_notify': True})
res = self.print_doc.run_async() res = self.print_doc.run_async()
print_wizard = self._print_wizard(res) print_wizard = self._print_wizard(res)
report_action = print_wizard.print_report() report_action = print_wizard.print_report()
self.assertEquals(report_action, {}) # Do not run report yet self.assertEquals(report_action, {}) # Do not run report yet
self.assertEquals(self.print_doc.job_status, 'pending') # Job started self.assertEquals(self.print_doc.job_status, "pending") # Job started
# Test produce file (as queue will not run in test mode) # Test produce file (as queue will not run in test mode)
docids = [print_wizard.reference.id] docids = [print_wizard.reference.id]
data = None data = None

View File

@ -1,133 +1,177 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="view_report_async_tree" model="ir.ui.view"> <record id="view_report_async_tree" model="ir.ui.view">
<field name="name">report.async.tree</field> <field name="name">report.async.tree</field>
<field name="model">report.async</field> <field name="model">report.async</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Report Center"> <tree string="Report Center">
<field name="action_id"/> <field name="action_id" />
<button type="object" name="run_now" string="Run Now" icon="fa-bolt"/> <button type="object" name="run_now" string="Run Now" icon="fa-bolt" />
<button type="object" name="run_async" string="Run Background" icon="fa-cogs" <button
attrs="{'invisible': [('allow_async', '=', False)]}"/> type="object"
<button type="object" name="view_files" string="Files" icon="fa-copy" name="run_async"
attrs="{'invisible': [('allow_async', '=', False)]}"/> string="Run Background"
<field name="allow_async" invisible="1"/> icon="fa-cogs"
<field name="job_status" attrs="{'invisible': [('allow_async', '=', False)]}"
attrs="{'invisible': [('allow_async', '=', False)]}"/> />
<field name="email_notify"/> <button
type="object"
name="view_files"
string="Files"
icon="fa-copy"
attrs="{'invisible': [('allow_async', '=', False)]}"
/>
<field name="allow_async" invisible="1" />
<field
name="job_status"
attrs="{'invisible': [('allow_async', '=', False)]}"
/>
<field name="email_notify" />
</tree> </tree>
</field> </field>
</record> </record>
<record id="view_report_async_form" model="ir.ui.view"> <record id="view_report_async_form" model="ir.ui.view">
<field name="name">report.async.form</field> <field name="name">report.async.form</field>
<field name="model">report.async</field> <field name="model">report.async</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<div class="alert alert-warning" <div
role="alert" class="alert alert-warning"
attrs="{'invisible': ['|', ('job_status', 'in', ['done', 'failed', False]), role="alert"
attrs="{'invisible': ['|', ('job_status', 'in', ['done', 'failed', False]),
('allow_async', '=', False)]}" ('allow_async', '=', False)]}"
style="margin-bottom:0px;"> style="margin-bottom:0px;"
>
<p> <p>
The report will be running by <i class="fa fa-cogs"/> The report will be running by <i class="fa fa-cogs" />
<b>job</b>, and will be available at <b>job</b>, and will be available at
<i class="fa fa-copy"/><b> Files</b> <i class="fa fa-copy" /><b> Files</b>
</p> </p>
</div> </div>
<div class="alert alert-danger" <div
role="alert" class="alert alert-danger"
attrs="{'invisible': ['|', ('job_status', '!=', 'failed'), role="alert"
attrs="{'invisible': ['|', ('job_status', '!=', 'failed'),
('allow_async', '=', False)]}" ('allow_async', '=', False)]}"
style="margin-bottom:0px;"> style="margin-bottom:0px;"
>
<p> <p>
The last <i class="fa fa-cogs"/> <b>running job</b> was failed. The last <i class="fa fa-cogs" /> <b>running job</b> was failed.
Please contact your system administrator. Please contact your system administrator.
</p> </p>
</div> </div>
<div class="alert alert-success" <div
role="alert" class="alert alert-success"
attrs="{'invisible': ['|', ('job_status', '!=', 'done'), role="alert"
attrs="{'invisible': ['|', ('job_status', '!=', 'done'),
('allow_async', '=', False)]}" ('allow_async', '=', False)]}"
style="margin-bottom:0px;"> style="margin-bottom:0px;"
>
<p> <p>
The last <i class="fa fa-cogs"/> <b>running job</b> was succeed. The last <i class="fa fa-cogs" /> <b
You can check the result in <i class="fa fa-copy"/><b> Files</b> >running job</b> was succeed.
You can check the result in <i class="fa fa-copy" /><b
> Files</b>
</p> </p>
</div> </div>
<sheet> <sheet>
<div class="oe_read_only oe_right oe_button_box" name="buttons"> <div class="oe_read_only oe_right oe_button_box" name="buttons">
<button type="object" name="run_now" string="Run Now" icon="fa-bolt"/> <button
<button type="object" name="run_async" string="Run Background" icon="fa-cogs" type="object"
attrs="{'invisible': [('allow_async', '=', False)]}"/> name="run_now"
<button type="object" name="view_files" string="Files" icon="fa-copy" string="Run Now"
attrs="{'invisible': [('allow_async', '=', False)]}"/> icon="fa-bolt"
<button type="object" name="view_jobs" string="Jobs" icon="fa-align-justify" />
groups="queue_job.group_queue_job_manager" <button
attrs="{'invisible': [('allow_async', '=', False)]}"/> type="object"
name="run_async"
string="Run Background"
icon="fa-cogs"
attrs="{'invisible': [('allow_async', '=', False)]}"
/>
<button
type="object"
name="view_files"
string="Files"
icon="fa-copy"
attrs="{'invisible': [('allow_async', '=', False)]}"
/>
<button
type="object"
name="view_jobs"
string="Jobs"
icon="fa-align-justify"
groups="queue_job.group_queue_job_manager"
attrs="{'invisible': [('allow_async', '=', False)]}"
/>
</div> </div>
<group> <group>
<group> <group>
<field name="action_id" options="{'no_open': True, 'no_create_edit': True}" /> <field
<field name="allow_async"/> name="action_id"
<field name="email_notify" options="{'no_open': True, 'no_create_edit': True}"
attrs="{'invisible': [('allow_async', '=', False)]}"/> />
<field name="allow_async" />
<field
name="email_notify"
attrs="{'invisible': [('allow_async', '=', False)]}"
/>
</group> </group>
<group> <group>
<field name="job_status" <field
attrs="{'invisible': [('allow_async', '=', False)]}"/> name="job_status"
<field name="group_ids" widget="many2many_tags"/> attrs="{'invisible': [('allow_async', '=', False)]}"
/>
<field name="group_ids" widget="many2many_tags" />
</group> </group>
<group name="job_info" string="Last Run Job Error" colspan="2" <group
attrs="{'invisible': ['|', ('job_info', '=', False), ('allow_async', '=', False)]}"> name="job_info"
<field nolabel="1" name="job_info"/> string="Last Run Job Error"
colspan="2"
attrs="{'invisible': ['|', ('job_info', '=', False), ('allow_async', '=', False)]}"
>
<field nolabel="1" name="job_info" />
</group> </group>
</group> </group>
</sheet> </sheet>
</form> </form>
</field> </field>
</record> </record>
<record id="view_report_async_search" model="ir.ui.view"> <record id="view_report_async_search" model="ir.ui.view">
<field name="name">report.async.search</field> <field name="name">report.async.search</field>
<field name="model">report.async</field> <field name="model">report.async</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Report Center"> <search string="Report Center">
<field name="action_id"/> <field name="action_id" />
</search> </search>
</field> </field>
</record> </record>
<record id="action_report_async" model="ir.actions.act_window"> <record id="action_report_async" model="ir.actions.act_window">
<field name="name">Report Center</field> <field name="name">Report Center</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">report.async</field> <field name="res_model">report.async</field>
<field name="view_type">form</field>
<field name="help">Run reports asyncronously</field> <field name="help">Run reports asyncronously</field>
</record> </record>
<menuitem <menuitem
id="menu_report_async" id="menu_report_async"
parent="base.menu_board_root" parent="base.menu_board_root"
action="action_report_async" action="action_report_async"
sequence="10"/> sequence="10"
/>
<record id="action_view_files" model="ir.actions.act_window"> <record id="action_view_files" model="ir.actions.act_window">
<field name="name">Report Files</field> <field name="name">Report Files</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">ir.attachment</field> <field name="res_model">ir.attachment</field>
<field name="view_type">form</field> <field name="view_id" eval="False" />
<field name="view_id" eval="False"/> <field name="search_view_id" ref="base.view_attachment_search" />
<field name="search_view_id" ref="base.view_attachment_search"/>
<field name="view_mode">kanban,tree,form</field> <field name="view_mode">kanban,tree,form</field>
<field name="domain">[('res_model', '=', 'report.async'), ('create_uid', '=', uid)]</field> <field
name="domain"
>[('res_model', '=', 'report.async'), ('create_uid', '=', uid)]</field>
<field name="help" type="html"> <field name="help" type="html">
<p class="o_view_nocontent_smiling_face"> <p class="o_view_nocontent_smiling_face">
No files found No files found
</p> </p>
</field> </field>
</record> </record>
</odoo> </odoo>

View File

@ -1,43 +1,45 @@
# Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/) # Copyright 2019 Ecosoft Co., Ltd (http://ecosoft.co.th/)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html) # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html)
from odoo import fields, models, api from odoo import api, fields, models
class PrintReportWizard(models.TransientModel): class PrintReportWizard(models.TransientModel):
_name = 'print.report.wizard' _name = "print.report.wizard"
_description = 'Print Report Wizard' _description = "Print Report Wizard"
reference = fields.Reference( reference = fields.Reference(
string='Document', string="Document",
selection='_reference_models', selection="_reference_models",
required=True, required=True,
) )
action_report_id = fields.Many2one( action_report_id = fields.Many2one(
comodel_name='ir.actions.report', comodel_name="ir.actions.report",
string='Report Template', string="Report Template",
required=True, required=True,
) )
@api.model @api.model
def _reference_models(self): def _reference_models(self):
excludes = ['res.company'] excludes = ["res.company"]
models = self.env['ir.model'].search([ models = self.env["ir.model"].search(
('state', '!=', 'manual'), ('transient', '=', False), [
('model', 'not in', excludes)]) ("state", "!=", "manual"),
("transient", "=", False),
("model", "not in", excludes),
]
)
return [(model.model, model.name) for model in models] return [(model.model, model.name) for model in models]
@api.onchange('reference') @api.onchange("reference")
def _onchange_reference(self): def _onchange_reference(self):
self.ensure_one() self.ensure_one()
domain = [('id', 'in', [])] domain = [("id", "in", [])]
self.action_report_id = False self.action_report_id = False
if self.reference: if self.reference:
domain = [('model', '=', self.reference._name)] domain = [("model", "=", self.reference._name)]
return {'domain': {'action_report_id': domain}} return {"domain": {"action_report_id": domain}}
@api.multi
def print_report(self): def print_report(self):
self.ensure_one() self.ensure_one()
return self.action_report_id.report_action(self.reference, return self.action_report_id.report_action(self.reference, config=False)
config=False)

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<record id="print_report_wizard" model="ir.ui.view"> <record id="print_report_wizard" model="ir.ui.view">
<field name="name">print.report.wizard</field> <field name="name">print.report.wizard</field>
<field name="model">print.report.wizard</field> <field name="model">print.report.wizard</field>
@ -8,29 +7,31 @@
<form> <form>
<group> <group>
<group> <group>
<field name="reference"/> <field name="reference" />
</group> </group>
<group> <group>
<field name="action_report_id" options="{'no_open': True, 'no_create_edit': True}"/> <field
name="action_report_id"
options="{'no_open': True, 'no_create_edit': True}"
/>
</group> </group>
</group> </group>
<footer> <footer>
<button name="print_report" <button
type="object" string="Execute" name="print_report"
class="oe_highlight"/> type="object"
<button special="cancel" string="Execute"
string="Cancel"/> class="oe_highlight"
/>
<button special="cancel" string="Cancel" />
</footer> </footer>
</form> </form>
</field> </field>
</record> </record>
<record id="action_print_report_wizard" model="ir.actions.act_window"> <record id="action_print_report_wizard" model="ir.actions.act_window">
<field name="name">Print Document</field> <field name="name">Print Document</field>
<field name="res_model">print.report.wizard</field> <field name="res_model">print.report.wizard</field>
<field name="view_type">form</field>
<field name="view_mode">form</field> <field name="view_mode">form</field>
<field name="target">new</field> <field name="target">new</field>
</record> </record>
</odoo> </odoo>

View File

@ -0,0 +1 @@
../../../../report_async

View File

@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)