├── .copier-answers.yml ├── .editorconfig ├── .github └── workflows │ ├── pre-commit.yml │ ├── stale.yml │ └── test.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .pylintrc ├── .pylintrc-mandatory ├── .ruff.toml ├── LICENSE ├── README.md ├── base_comment_template ├── README.rst ├── __init__.py ├── __manifest__.py ├── i18n │ ├── am.po │ ├── ar.po │ ├── base_comment_template.pot │ ├── bg.po │ ├── bs.po │ ├── ca.po │ ├── cs.po │ ├── da.po │ ├── de.po │ ├── el_GR.po │ ├── en_GB.po │ ├── es.po │ ├── es_AR.po │ ├── es_CL.po │ ├── es_CO.po │ ├── es_CR.po │ ├── es_DO.po │ ├── es_EC.po │ ├── es_ES.po │ ├── es_MX.po │ ├── es_PE.po │ ├── es_PY.po │ ├── es_VE.po │ ├── et.po │ ├── eu.po │ ├── fa.po │ ├── fi.po │ ├── fr.po │ ├── fr_CA.po │ ├── fr_CH.po │ ├── gl.po │ ├── gl_ES.po │ ├── he.po │ ├── hr.po │ ├── hr_HR.po │ ├── hu.po │ ├── id.po │ ├── it.po │ ├── ja.po │ ├── ko.po │ ├── lt.po │ ├── lt_LT.po │ ├── lv.po │ ├── mk.po │ ├── mn.po │ ├── nb.po │ ├── nb_NO.po │ ├── nl.po │ ├── nl_BE.po │ ├── nl_NL.po │ ├── pl.po │ ├── pt.po │ ├── pt_BR.po │ ├── pt_PT.po │ ├── ro.po │ ├── ru.po │ ├── sk.po │ ├── sl.po │ ├── sr.po │ ├── sr@latin.po │ ├── sv.po │ ├── th.po │ ├── tr.po │ ├── tr_TR.po │ ├── uk.po │ ├── vi.po │ ├── vi_VN.po │ ├── zh_CN.po │ └── zh_TW.po ├── models │ ├── __init__.py │ ├── base_comment_template.py │ ├── comment_template.py │ ├── ir_model.py │ └── res_partner.py ├── pyproject.toml ├── readme │ ├── CONFIGURE.md │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── security │ ├── ir.model.access.csv │ └── security.xml ├── static │ └── description │ │ ├── icon.png │ │ └── index.html ├── tests │ ├── __init__.py │ ├── fake_models.py │ └── test_base_comment_template.py ├── views │ ├── base_comment_template_view.xml │ └── res_partner_view.xml └── wizard │ ├── __init__.py │ ├── base_comment_template_preview.py │ └── base_comment_template_preview_views.xml ├── bi_sql_editor ├── README.rst ├── __init__.py ├── __manifest__.py ├── demo │ ├── bi_sql_view_demo.xml │ └── res_groups_demo.xml ├── hooks.py ├── i18n │ ├── am.po │ ├── ar.po │ ├── bg.po │ ├── bi_sql_editor.pot │ ├── bs.po │ ├── ca.po │ ├── cs.po │ ├── da.po │ ├── de.po │ ├── el_GR.po │ ├── en_GB.po │ ├── es.po │ ├── es_AR.po │ ├── es_CL.po │ ├── es_CO.po │ ├── es_CR.po │ ├── es_DO.po │ ├── es_EC.po │ ├── es_ES.po │ ├── es_MX.po │ ├── es_PE.po │ ├── es_PY.po │ ├── es_VE.po │ ├── et.po │ ├── eu.po │ ├── fa.po │ ├── fi.po │ ├── fr.po │ ├── fr_CA.po │ ├── fr_CH.po │ ├── gl.po │ ├── gl_ES.po │ ├── he.po │ ├── hr.po │ ├── hr_HR.po │ ├── hu.po │ ├── id.po │ ├── it.po │ ├── ja.po │ ├── ko.po │ ├── lt.po │ ├── lt_LT.po │ ├── lv.po │ ├── mk.po │ ├── mn.po │ ├── nb.po │ ├── nb_NO.po │ ├── nl.po │ ├── nl_BE.po │ ├── nl_NL.po │ ├── pl.po │ ├── pt.po │ ├── pt_BR.po │ ├── pt_PT.po │ ├── ro.po │ ├── ru.po │ ├── sk.po │ ├── sl.po │ ├── sr.po │ ├── sr@latin.po │ ├── sv.po │ ├── th.po │ ├── tr.po │ ├── tr_TR.po │ ├── uk.po │ ├── vi.po │ ├── vi_VN.po │ ├── zh_CN.po │ └── zh_TW.po ├── models │ ├── __init__.py │ ├── bi_sql_view.py │ ├── bi_sql_view_field.py │ └── ir_model.py ├── pyproject.toml ├── readme │ ├── CONFIGURE.md │ ├── CONTRIBUTORS.md │ ├── CREDITS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── security │ └── ir.model.access.csv ├── static │ └── description │ │ ├── 01_sql_request.png │ │ ├── 02_security_access.png │ │ ├── 03_field_mapping.png │ │ ├── 04_materialized_view_setting.png │ │ ├── 05_reporting_pivot.png │ │ ├── icon.png │ │ └── index.html ├── tests │ ├── __init__.py │ └── test_bi_sql_view.py └── views │ └── view_bi_sql_view.xml ├── checklog-odoo.cfg ├── eslint.config.cjs ├── pdf_xml_attachment ├── README.rst ├── __init__.py ├── __manifest__.py ├── i18n │ ├── es.po │ ├── hr.po │ ├── it.po │ ├── pdf_helper.pot │ └── pdf_xml_attachment.pot ├── models │ ├── __init__.py │ └── helper.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── static │ └── description │ │ ├── icon.png │ │ └── index.html ├── tests │ ├── __init__.py │ ├── fixtures │ │ └── pdf_with_xml_test.pdf │ └── test_helper.py └── utils.py ├── prettier.config.cjs ├── report_csv ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── demo │ └── report.xml ├── i18n │ ├── es.po │ ├── it.po │ ├── pt_BR.po │ └── report_csv.pot ├── models │ ├── __init__.py │ └── ir_report.py ├── pyproject.toml ├── readme │ ├── CONFIGURE.md │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── report │ ├── __init__.py │ ├── report_csv.py │ └── report_partner_csv.py ├── static │ ├── description │ │ ├── icon.png │ │ └── index.html │ └── src │ │ └── js │ │ └── report │ │ └── qwebactionmanager.esm.js ├── tests │ ├── __init__.py │ └── test_report.py └── views │ └── ir_actions_views.xml ├── report_py3o ├── LICENSE ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── demo │ ├── report_py3o.xml │ └── res_user.odt ├── i18n │ ├── am.po │ ├── ar.po │ ├── bg.po │ ├── bs.po │ ├── ca.po │ ├── cs.po │ ├── da.po │ ├── de.po │ ├── el_GR.po │ ├── en_GB.po │ ├── es.po │ ├── es_AR.po │ ├── es_CL.po │ ├── es_CO.po │ ├── es_CR.po │ ├── es_DO.po │ ├── es_EC.po │ ├── es_ES.po │ ├── es_MX.po │ ├── es_PE.po │ ├── es_PY.po │ ├── es_VE.po │ ├── et.po │ ├── eu.po │ ├── fa.po │ ├── fi.po │ ├── fr.po │ ├── fr_CA.po │ ├── fr_CH.po │ ├── gl.po │ ├── gl_ES.po │ ├── he.po │ ├── hr.po │ ├── hr_HR.po │ ├── hu.po │ ├── id.po │ ├── it.po │ ├── ja.po │ ├── ko.po │ ├── lt.po │ ├── lt_LT.po │ ├── lv.po │ ├── mk.po │ ├── mn.po │ ├── nb.po │ ├── nb_NO.po │ ├── nl.po │ ├── nl_BE.po │ ├── nl_NL.po │ ├── pl.po │ ├── pt.po │ ├── pt_BR.po │ ├── pt_PT.po │ ├── report_py3o.pot │ ├── ro.po │ ├── ru.po │ ├── sk.po │ ├── sl.po │ ├── sr.po │ ├── sr@latin.po │ ├── sv.po │ ├── th.po │ ├── tr.po │ ├── tr_TR.po │ ├── uk.po │ ├── vi.po │ ├── vi_VN.po │ ├── zh_CN.po │ └── zh_TW.po ├── models │ ├── __init__.py │ ├── _py3o_parser_context.py │ ├── ir_actions_report.py │ ├── py3o_report.py │ └── py3o_template.py ├── pyproject.toml ├── readme │ ├── CONFIGURE.md │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ ├── INSTALL.md │ ├── ROADMAP.md │ └── USAGE.md ├── security │ └── ir.model.access.csv ├── static │ ├── description │ │ ├── icon.png │ │ └── index.html │ └── src │ │ └── js │ │ └── py3oactionservice.esm.js ├── tests │ ├── __init__.py │ └── test_report_py3o.py └── views │ ├── ir_actions_report.xml │ └── py3o_template.xml ├── report_py3o_fusion_server ├── README.rst ├── __init__.py ├── __manifest__.py ├── demo │ ├── py3o_pdf_options.xml │ └── report_py3o.xml ├── i18n │ ├── am.po │ ├── ar.po │ ├── bg.po │ ├── bs.po │ ├── ca.po │ ├── cs.po │ ├── da.po │ ├── de.po │ ├── el_GR.po │ ├── en_GB.po │ ├── es.po │ ├── es_AR.po │ ├── es_CL.po │ ├── es_CO.po │ ├── es_CR.po │ ├── es_DO.po │ ├── es_EC.po │ ├── es_ES.po │ ├── es_MX.po │ ├── es_PE.po │ ├── es_PY.po │ ├── es_VE.po │ ├── et.po │ ├── eu.po │ ├── fa.po │ ├── fi.po │ ├── fr.po │ ├── fr_CA.po │ ├── fr_CH.po │ ├── gl.po │ ├── gl_ES.po │ ├── he.po │ ├── hr.po │ ├── hr_HR.po │ ├── hu.po │ ├── id.po │ ├── it.po │ ├── ja.po │ ├── ko.po │ ├── lt.po │ ├── lt_LT.po │ ├── lv.po │ ├── mk.po │ ├── mn.po │ ├── nb.po │ ├── nb_NO.po │ ├── nl.po │ ├── nl_BE.po │ ├── nl_NL.po │ ├── pl.po │ ├── pt.po │ ├── pt_BR.po │ ├── pt_PT.po │ ├── report_py3o_fusion_server.pot │ ├── ro.po │ ├── ru.po │ ├── sk.po │ ├── sl.po │ ├── sr.po │ ├── sr@latin.po │ ├── sv.po │ ├── th.po │ ├── tr.po │ ├── tr_TR.po │ ├── uk.po │ ├── vi.po │ ├── vi_VN.po │ ├── zh_CN.po │ └── zh_TW.po ├── models │ ├── __init__.py │ ├── ir_actions_report.py │ ├── py3o_pdf_options.py │ ├── py3o_report.py │ └── py3o_server.py ├── pyproject.toml ├── readme │ ├── CONFIGURE.md │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ ├── INSTALL.md │ └── ROADMAP.md ├── security │ └── ir.model.access.csv ├── static │ └── description │ │ ├── icon.png │ │ └── index.html ├── tests │ ├── __init__.py │ └── test_report_py3o_fusion_server.py └── views │ ├── ir_actions_report.xml │ ├── py3o_pdf_options.xml │ └── py3o_server.xml ├── report_qweb_element_page_visibility ├── README.rst ├── __init__.py ├── __manifest__.py ├── i18n │ ├── it.po │ └── report_qweb_element_page_visibility.pot ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── CREDITS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── static │ └── description │ │ ├── icon.png │ │ └── index.html └── views │ └── layouts.xml ├── report_qweb_parameter ├── README.rst ├── __init__.py ├── __manifest__.py ├── demo │ └── test_report_field_length.xml ├── i18n │ ├── ca.po │ ├── es.po │ ├── fr.po │ ├── it.po │ ├── pt.po │ └── report_qweb_parameter.pot ├── models │ ├── __init__.py │ └── ir_qweb.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── static │ └── description │ │ ├── icon.png │ │ └── index.html └── tests │ ├── __init__.py │ └── test_report_qweb_parameter.py ├── report_qweb_pdf_cover ├── README.rst ├── __init__.py ├── __manifest__.py ├── i18n │ ├── es.po │ ├── it.po │ └── report_qweb_pdf_cover.pot ├── models │ ├── __init__.py │ └── ir_actions_report.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── static │ └── description │ │ ├── icon.png │ │ └── index.html └── views │ └── ir_actions_views.xml ├── report_qweb_pdf_watermark ├── README.rst ├── __init__.py ├── __manifest__.py ├── demo │ └── report.xml ├── i18n │ ├── ca.po │ ├── da.po │ ├── de.po │ ├── el_GR.po │ ├── es.po │ ├── es_CO.po │ ├── fr.po │ ├── gl.po │ ├── hr.po │ ├── hr_HR.po │ ├── it.po │ ├── nb_NO.po │ ├── nl.po │ ├── nl_NL.po │ ├── pl.po │ ├── pt.po │ ├── pt_BR.po │ ├── pt_PT.po │ ├── report_qweb_pdf_watermark.pot │ ├── sl.po │ ├── tr.po │ └── tr_TR.po ├── models │ ├── __init__.py │ ├── report.py │ └── res_company.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ ├── HISTORY.md │ ├── INSTALL.md │ ├── ROADMAP.md │ └── USAGE.md ├── static │ ├── description │ │ ├── icon.png │ │ └── index.html │ └── src │ │ └── css │ │ └── report_qweb_pdf_watermark.css ├── tests │ ├── __init__.py │ └── test_report_qweb_pdf_watermark.py └── views │ ├── ir_actions_report_xml.xml │ └── res_company.xml ├── report_wkhtmltopdf_param ├── README.rst ├── __init__.py ├── __manifest__.py ├── i18n │ ├── am.po │ ├── ar.po │ ├── bg.po │ ├── bs.po │ ├── ca.po │ ├── cs.po │ ├── da.po │ ├── de.po │ ├── el_GR.po │ ├── en_GB.po │ ├── es.po │ ├── es_AR.po │ ├── es_CL.po │ ├── es_CO.po │ ├── es_CR.po │ ├── es_DO.po │ ├── es_EC.po │ ├── es_ES.po │ ├── es_MX.po │ ├── es_PE.po │ ├── es_PY.po │ ├── es_VE.po │ ├── et.po │ ├── eu.po │ ├── fa.po │ ├── fi.po │ ├── fr.po │ ├── fr_CA.po │ ├── fr_CH.po │ ├── gl.po │ ├── gl_ES.po │ ├── he.po │ ├── hr.po │ ├── hr_HR.po │ ├── hu.po │ ├── id.po │ ├── it.po │ ├── ja.po │ ├── ko.po │ ├── lt.po │ ├── lt_LT.po │ ├── lv.po │ ├── mk.po │ ├── mn.po │ ├── nb.po │ ├── nb_NO.po │ ├── nl.po │ ├── nl_BE.po │ ├── nl_NL.po │ ├── pl.po │ ├── pt.po │ ├── pt_BR.po │ ├── pt_PT.po │ ├── report_wkhtmltopdf_param.pot │ ├── ro.po │ ├── ru.po │ ├── sk.po │ ├── sl.po │ ├── sr.po │ ├── sr@latin.po │ ├── sv.po │ ├── th.po │ ├── tr.po │ ├── tr_TR.po │ ├── uk.po │ ├── vi.po │ ├── vi_VN.po │ ├── zh_CN.po │ └── zh_TW.po ├── models │ ├── __init__.py │ ├── report.py │ ├── report_paperformat.py │ └── report_paperformat_parameter.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── CREDITS.md │ ├── DESCRIPTION.md │ └── USAGE.md ├── security │ └── ir.model.access.csv ├── static │ └── description │ │ ├── icon.png │ │ └── index.html ├── tests │ ├── __init__.py │ └── test_report_paperformat.py └── views │ └── paperformat.xml ├── report_xlsx ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── demo │ └── report.xml ├── i18n │ ├── ca.po │ ├── de.po │ ├── es.po │ ├── fr.po │ ├── hr.po │ ├── hr_HR.po │ ├── it.po │ ├── nl_NL.po │ ├── pt.po │ ├── pt_PT.po │ ├── report_xlsx.pot │ ├── sv.po │ └── tr.po ├── models │ ├── __init__.py │ └── ir_report.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ ├── INSTALL.md │ └── USAGE.md ├── report │ ├── __init__.py │ ├── report_abstract_xlsx.py │ └── report_partner_xlsx.py ├── static │ ├── description │ │ ├── icon.png │ │ └── index.html │ └── src │ │ └── js │ │ └── report │ │ └── action_manager_report.esm.js └── tests │ ├── __init__.py │ └── test_report.py ├── report_xlsx_helper ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── main.py ├── i18n │ ├── ca.po │ ├── es.po │ ├── fr.po │ ├── it.po │ └── report_xlsx_helper.pot ├── models │ ├── __init__.py │ └── ir_actions_report.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ ├── INSTALL.md │ └── USAGE.md ├── report │ ├── __init__.py │ ├── report_xlsx_abstract.py │ ├── report_xlsx_format.py │ └── test_partner_report_xlsx.py ├── static │ └── description │ │ ├── icon.png │ │ └── index.html └── tests │ ├── __init__.py │ └── test_report_xlsx_helper.py ├── report_xml ├── README.rst ├── __init__.py ├── __manifest__.py ├── controllers │ ├── __init__.py │ └── report.py ├── demo │ ├── demo_report.xml │ ├── demo_report.xsd │ └── report.xml ├── hooks.py ├── i18n │ ├── am.po │ ├── ar.po │ ├── bg.po │ ├── bs.po │ ├── ca.po │ ├── cs.po │ ├── da.po │ ├── de.po │ ├── el_GR.po │ ├── en_GB.po │ ├── es.po │ ├── es_AR.po │ ├── es_CL.po │ ├── es_CO.po │ ├── es_CR.po │ ├── es_DO.po │ ├── es_EC.po │ ├── es_ES.po │ ├── es_MX.po │ ├── es_PE.po │ ├── es_PY.po │ ├── es_VE.po │ ├── et.po │ ├── eu.po │ ├── fa.po │ ├── fi.po │ ├── fr.po │ ├── fr_CA.po │ ├── fr_CH.po │ ├── gl.po │ ├── gl_ES.po │ ├── he.po │ ├── hr.po │ ├── hr_HR.po │ ├── hu.po │ ├── id.po │ ├── it.po │ ├── ja.po │ ├── ko.po │ ├── lt.po │ ├── lt_LT.po │ ├── lv.po │ ├── mk.po │ ├── mn.po │ ├── nb.po │ ├── nb_NO.po │ ├── nl.po │ ├── nl_BE.po │ ├── nl_NL.po │ ├── pl.po │ ├── pt.po │ ├── pt_BR.po │ ├── pt_PT.po │ ├── report_xml.pot │ ├── ro.po │ ├── ru.po │ ├── sk.po │ ├── sl.po │ ├── sr.po │ ├── sr@latin.po │ ├── sv.po │ ├── th.po │ ├── tr.po │ ├── tr_TR.po │ ├── uk.po │ ├── vi.po │ ├── vi_VN.po │ ├── zh_CN.po │ └── zh_TW.po ├── models │ ├── __init__.py │ └── ir_actions_report.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── CREDITS.md │ ├── DESCRIPTION.md │ ├── INSTALL.md │ └── USAGE.md ├── reports │ ├── __init__.py │ └── report_report_xml_abstract.py ├── static │ ├── description │ │ ├── icon.png │ │ ├── icon.svg │ │ └── index.html │ └── src │ │ └── js │ │ └── report │ │ └── action_manager_report.esm.js ├── tests │ ├── __init__.py │ └── test_report_xml.py └── views │ └── ir_actions_report_view.xml ├── requirements.txt ├── setup └── _metapackage │ └── pyproject.toml ├── sql_export ├── README.rst ├── __init__.py ├── __manifest__.py ├── demo │ └── sql_export.xml ├── i18n │ ├── am.po │ ├── ar.po │ ├── bg.po │ ├── bs.po │ ├── ca.po │ ├── ca_ES.po │ ├── cs.po │ ├── da.po │ ├── de.po │ ├── el_GR.po │ ├── en_AU.po │ ├── en_GB.po │ ├── es.po │ ├── es_AR.po │ ├── es_CL.po │ ├── es_CO.po │ ├── es_CR.po │ ├── es_DO.po │ ├── es_EC.po │ ├── es_ES.po │ ├── es_MX.po │ ├── es_PE.po │ ├── es_PY.po │ ├── es_VE.po │ ├── et.po │ ├── eu.po │ ├── fa.po │ ├── fi.po │ ├── fr.po │ ├── fr_CA.po │ ├── fr_CH.po │ ├── fr_FR.po │ ├── gl.po │ ├── gl_ES.po │ ├── he.po │ ├── hi.po │ ├── hr.po │ ├── hr_HR.po │ ├── hu.po │ ├── id.po │ ├── it.po │ ├── ja.po │ ├── ko.po │ ├── lo.po │ ├── lt.po │ ├── lt_LT.po │ ├── lv.po │ ├── mk.po │ ├── mn.po │ ├── nb.po │ ├── nb_NO.po │ ├── nl.po │ ├── nl_BE.po │ ├── nl_NL.po │ ├── pl.po │ ├── pt.po │ ├── pt_BR.po │ ├── pt_PT.po │ ├── ro.po │ ├── ru.po │ ├── sk.po │ ├── sl.po │ ├── sql_export.pot │ ├── sr.po │ ├── sr@latin.po │ ├── sv.po │ ├── th.po │ ├── tr.po │ ├── tr_TR.po │ ├── uk.po │ ├── vi.po │ ├── vi_VN.po │ ├── zh_CN.po │ └── zh_TW.po ├── models │ ├── __init__.py │ └── sql_export.py ├── pyproject.toml ├── readme │ ├── CONTRIBUTORS.md │ ├── DESCRIPTION.md │ ├── ROADMAP.md │ └── USAGE.md ├── security │ ├── ir.model.access.csv │ └── sql_export_security.xml ├── static │ ├── description │ │ ├── icon.png │ │ └── index.html │ └── src │ │ └── scss │ │ └── modal_properties.scss ├── tests │ ├── __init__.py │ └── test_sql_query.py ├── views │ └── sql_export_view.xml └── wizard │ ├── __init__.py │ ├── wizard_file.py │ └── wizard_file_view.xml ├── sql_export_excel ├── README.rst ├── __init__.py ├── __manifest__.py ├── i18n │ ├── ca.po │ ├── es.po │ ├── it.po │ └── sql_export_excel.pot ├── models │ ├── __init__.py │ └── sql_export.py ├── pyproject.toml ├── readme │ ├── CONFIGURE.md │ ├── CONTRIBUTORS.md │ └── DESCRIPTION.md ├── static │ └── description │ │ ├── icon.png │ │ └── index.html ├── tests │ ├── __init__.py │ └── test_sql_query_excel.py └── views │ └── sql_export_view.xml └── sql_request_abstract ├── README.rst ├── __init__.py ├── __manifest__.py ├── i18n ├── am.po ├── ar.po ├── bg.po ├── bs.po ├── ca.po ├── cs.po ├── da.po ├── de.po ├── el_GR.po ├── en_GB.po ├── es.po ├── es_AR.po ├── es_CL.po ├── es_CO.po ├── es_CR.po ├── es_DO.po ├── es_EC.po ├── es_ES.po ├── es_MX.po ├── es_PE.po ├── es_PY.po ├── es_VE.po ├── et.po ├── eu.po ├── fa.po ├── fi.po ├── fr.po ├── fr_CA.po ├── fr_CH.po ├── gl.po ├── gl_ES.po ├── he.po ├── hr.po ├── hr_HR.po ├── hu.po ├── id.po ├── it.po ├── ja.po ├── ko.po ├── lt.po ├── lt_LT.po ├── lv.po ├── mk.po ├── mn.po ├── nb.po ├── nb_NO.po ├── nl.po ├── nl_BE.po ├── nl_NL.po ├── pl.po ├── pt.po ├── pt_BR.po ├── pt_PT.po ├── ro.po ├── ru.po ├── sk.po ├── sl.po ├── sql_request_abstract.pot ├── sr.po ├── sr@latin.po ├── sv.po ├── th.po ├── tr.po ├── tr_TR.po ├── uk.po ├── vi.po ├── vi_VN.po ├── zh_CN.po └── zh_TW.po ├── models ├── __init__.py └── sql_request_mixin.py ├── pyproject.toml ├── readme ├── CONFIGURE.md ├── CONTRIBUTORS.md ├── CREDITS.md ├── DESCRIPTION.md ├── DEVELOP.md └── USAGE.md ├── security ├── ir.model.access.csv ├── ir_module_category.xml └── res_groups.xml ├── sql_db.py ├── static ├── description │ ├── icon.png │ └── index.html ├── lib │ └── ace │ │ └── mode-pgsql.js └── src │ └── js │ └── code_editor.esm.js └── views └── view_sql_request_mixin.xml /.copier-answers.yml: -------------------------------------------------------------------------------- 1 | # Do NOT update manually; changes here will be overwritten by Copier 2 | _commit: v1.29 3 | _src_path: git+https://github.com/OCA/oca-addons-repo-template 4 | additional_ruff_rules: [] 5 | ci: GitHub 6 | convert_readme_fragments_to_markdown: true 7 | enable_checklog_odoo: true 8 | generate_requirements_txt: true 9 | github_check_license: true 10 | github_ci_extra_env: {} 11 | github_enable_codecov: true 12 | github_enable_makepot: true 13 | github_enable_stale_action: true 14 | github_enforce_dev_status_compatibility: true 15 | include_wkhtmltopdf: false 16 | odoo_test_flavor: Both 17 | odoo_version: 18.0 18 | org_name: Odoo Community Association (OCA) 19 | org_slug: OCA 20 | rebel_module_groups: [] 21 | repo_description: reporting-engine 22 | repo_name: reporting-engine 23 | repo_slug: reporting-engine 24 | repo_website: https://github.com/OCA/reporting-engine 25 | use_pyproject_toml: true 26 | use_ruff: true 27 | 28 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Configuration for known file extensions 2 | [*.{css,js,json,less,md,py,rst,sass,scss,xml,yaml,yml}] 3 | charset = utf-8 4 | end_of_line = lf 5 | indent_size = 4 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.{json,yml,yaml,rst,md}] 11 | indent_size = 2 12 | 13 | # Do not configure editor for libs and autogenerated content 14 | [{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}] 15 | charset = unset 16 | end_of_line = unset 17 | indent_size = unset 18 | indent_style = unset 19 | insert_final_newline = false 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit.yml: -------------------------------------------------------------------------------- 1 | name: pre-commit 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "18.0*" 7 | push: 8 | branches: 9 | - "18.0" 10 | - "18.0-ocabot-*" 11 | 12 | jobs: 13 | pre-commit: 14 | runs-on: ubuntu-22.04 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: actions/setup-python@v5 18 | with: 19 | python-version: "3.11" 20 | - name: Get python version 21 | run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV 22 | - uses: actions/cache@v4 23 | with: 24 | path: ~/.cache/pre-commit 25 | key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} 26 | - name: Install pre-commit 27 | run: pip install pre-commit 28 | - name: Run pre-commit 29 | run: pre-commit run --all-files --show-diff-on-failure --color=always 30 | env: 31 | # Consider valid a PR that changes README fragments but doesn't 32 | # change the README.rst file itself. It's not really a problem 33 | # because the bot will update it anyway after merge. This way, we 34 | # lower the barrier for functional contributors that want to fix the 35 | # readme fragments, while still letting developers get README 36 | # auto-generated (which also helps functionals when using runboat). 37 | # DOCS https://pre-commit.com/#temporarily-disabling-hooks 38 | SKIP: oca-gen-addon-readme 39 | - name: Check that all files generated by pre-commit are in git 40 | run: | 41 | newfiles="$(git ls-files --others --exclude-from=.gitignore)" 42 | if [ "$newfiles" != "" ] ; then 43 | echo "Please check-in the following files:" 44 | echo "$newfiles" 45 | exit 1 46 | fi 47 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "18.0*" 7 | push: 8 | branches: 9 | - "18.0" 10 | - "18.0-ocabot-*" 11 | 12 | jobs: 13 | unreleased-deps: 14 | runs-on: ubuntu-latest 15 | name: Detect unreleased dependencies 16 | steps: 17 | - uses: actions/checkout@v4 18 | - run: | 19 | for reqfile in requirements.txt test-requirements.txt ; do 20 | if [ -f ${reqfile} ] ; then 21 | result=0 22 | # reject non-comment lines that contain a / (i.e. URLs, relative paths) 23 | grep "^[^#].*/" ${reqfile} || result=$? 24 | if [ $result -eq 0 ] ; then 25 | echo "Unreleased dependencies found in ${reqfile}." 26 | exit 1 27 | fi 28 | fi 29 | done 30 | test: 31 | runs-on: ubuntu-22.04 32 | container: ${{ matrix.container }} 33 | name: ${{ matrix.name }} 34 | strategy: 35 | fail-fast: false 36 | matrix: 37 | include: 38 | - container: ghcr.io/oca/oca-ci/py3.10-odoo18.0:latest 39 | name: test with Odoo 40 | - container: ghcr.io/oca/oca-ci/py3.10-ocb18.0:latest 41 | name: test with OCB 42 | makepot: "true" 43 | services: 44 | postgres: 45 | image: postgres:12.0 46 | env: 47 | POSTGRES_USER: odoo 48 | POSTGRES_PASSWORD: odoo 49 | POSTGRES_DB: odoo 50 | ports: 51 | - 5432:5432 52 | env: 53 | OCA_ENABLE_CHECKLOG_ODOO: "1" 54 | steps: 55 | - uses: actions/checkout@v4 56 | with: 57 | persist-credentials: false 58 | - name: Install addons and dependencies 59 | run: oca_install_addons 60 | - name: Check licenses 61 | run: manifestoo -d . check-licenses 62 | - name: Check development status 63 | run: manifestoo -d . check-dev-status --default-dev-status=Beta 64 | - name: Initialize test db 65 | run: oca_init_test_database 66 | - name: Run tests 67 | run: oca_run_tests 68 | - uses: codecov/codecov-action@v4 69 | with: 70 | token: ${{ secrets.CODECOV_TOKEN }} 71 | - name: Update .pot files 72 | run: oca_export_and_push_pot https://x-access-token:${{ secrets.GIT_PUSH_TOKEN }}@github.com/${{ github.repository }} 73 | if: ${{ matrix.makepot == 'true' && github.event_name == 'push' && github.repository_owner == 'OCA' }} 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | /.venv 5 | /.pytest_cache 6 | /.ruff_cache 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | bin/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | eggs/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | *.eggs 27 | 28 | # Windows installers 29 | *.msi 30 | 31 | # Debian packages 32 | *.deb 33 | 34 | # Redhat packages 35 | *.rpm 36 | 37 | # MacOS packages 38 | *.dmg 39 | *.pkg 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .coverage 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | 53 | # Translations 54 | *.mo 55 | 56 | # Pycharm 57 | .idea 58 | 59 | # Eclipse 60 | .settings 61 | 62 | # Visual Studio cache/options directory 63 | .vs/ 64 | .vscode 65 | 66 | # OSX Files 67 | .DS_Store 68 | 69 | # Django stuff: 70 | *.log 71 | 72 | # Mr Developer 73 | .mr.developer.cfg 74 | .project 75 | .pydevproject 76 | 77 | # Rope 78 | .ropeproject 79 | 80 | # Sphinx documentation 81 | docs/_build/ 82 | 83 | # Backup files 84 | *~ 85 | *.swp 86 | 87 | # OCA rules 88 | !static/lib/ 89 | -------------------------------------------------------------------------------- /.ruff.toml: -------------------------------------------------------------------------------- 1 | 2 | target-version = "py310" 3 | fix = true 4 | 5 | [lint] 6 | extend-select = [ 7 | "B", 8 | "C90", 9 | "E501", # line too long (default 88) 10 | "I", # isort 11 | "UP", # pyupgrade 12 | ] 13 | extend-safe-fixes = ["UP008"] 14 | exclude = ["setup/*"] 15 | 16 | [format] 17 | exclude = ["setup/*"] 18 | 19 | [lint.per-file-ignores] 20 | "__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py 21 | "__manifest__.py" = ["B018"] # useless expression 22 | 23 | [lint.isort] 24 | section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"] 25 | 26 | [lint.isort.sections] 27 | "odoo" = ["odoo"] 28 | "odoo-addons" = ["odoo.addons"] 29 | 30 | [lint.mccabe] 31 | max-complexity = 16 32 | -------------------------------------------------------------------------------- /base_comment_template/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 2 | 3 | from . import models 4 | from . import wizard 5 | -------------------------------------------------------------------------------- /base_comment_template/__manifest__.py: -------------------------------------------------------------------------------- 1 | # © 2013-2014 Nicolas Bessi (Camptocamp SA) 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | 4 | { 5 | "name": "Base Comments Templates", 6 | "summary": "Add conditional mako template to any report" 7 | "on models that inherits comment.template.", 8 | "version": "18.0.1.0.1", 9 | "category": "Reporting", 10 | "website": "https://github.com/OCA/reporting-engine", 11 | "author": "Camptocamp, Odoo Community Association (OCA)", 12 | "license": "AGPL-3", 13 | "installable": True, 14 | "depends": ["base", "mail"], 15 | "data": [ 16 | "security/ir.model.access.csv", 17 | "security/security.xml", 18 | "wizard/base_comment_template_preview_views.xml", 19 | "views/base_comment_template_view.xml", 20 | "views/res_partner_view.xml", 21 | ], 22 | } 23 | -------------------------------------------------------------------------------- /base_comment_template/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import base_comment_template 2 | from . import comment_template 3 | from . import ir_model 4 | from . import res_partner 5 | -------------------------------------------------------------------------------- /base_comment_template/models/ir_model.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 NextERP Romania SRL 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class IrModel(models.Model): 8 | _inherit = "ir.model" 9 | 10 | is_comment_template = fields.Boolean( 11 | string="Comment Template", 12 | default=False, 13 | help="Whether this model supports in reports to add comment templates.", 14 | ) 15 | 16 | def _reflect_model_params(self, model): 17 | vals = super()._reflect_model_params(model) 18 | vals["is_comment_template"] = issubclass( 19 | type(model), self.pool["comment.template"] 20 | ) 21 | return vals 22 | 23 | @api.model 24 | def _instanciate(self, model_data): 25 | model_class = super()._instanciate(model_data) 26 | if ( 27 | model_data.get("is_comment_template") 28 | and model_class._name != "comment.template" 29 | ): 30 | parents = model_class._inherit or [] 31 | parents = [parents] if isinstance(parents, str) else parents 32 | model_class._inherit = parents + ["comment.template"] 33 | return model_class 34 | -------------------------------------------------------------------------------- /base_comment_template/models/res_partner.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 NextERP Romania SRL 2 | # Copyright 2021 Tecnativa - Víctor Martínez 3 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 4 | 5 | from odoo import api, fields, models 6 | 7 | 8 | class ResPartner(models.Model): 9 | _inherit = "res.partner" 10 | 11 | base_comment_template_ids = fields.Many2many( 12 | comodel_name="base.comment.template", 13 | relation="base_comment_template_res_partner_rel", 14 | column1="res_partner_id", 15 | column2="base_comment_template_id", 16 | string="Comment Templates", 17 | help="Specific partner comments that can be included in reports", 18 | ) 19 | 20 | @api.model 21 | def _commercial_fields(self): 22 | """Add comment templates to commercial fields""" 23 | return super()._commercial_fields() + ["base_comment_template_ids"] 24 | -------------------------------------------------------------------------------- /base_comment_template/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /base_comment_template/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | Go to *Settings \> Technical \> Reporting \> Comment Templates* and 2 | start designing you comment templates. 3 | 4 | This module is the base module for following modules: 5 | 6 | - sale_comment_template 7 | - purchase_comment_template 8 | - invoice_comment_template 9 | - stock_picking_comment_template 10 | -------------------------------------------------------------------------------- /base_comment_template/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Xavier Jimenez \<\> 2 | - Nicolas Bessi \<\> 3 | - Yannick Vaucher \<\> 4 | - Guewen Baconnier \<\> 5 | - Simone Rubino \<\> 6 | - [DynApps](https://www.dynapps.be): 7 | - Raf Ven \<\> 8 | - [Druidoo](https://www.druidoo.io): 9 | - Iván Todorovich \<\> 10 | - Pierre Verkest \<\> 11 | - [NextERP Romania](https://www.nexterp.ro): 12 | - Fekete Mihai \<\> 13 | - [Tecnativa](https://www.tecnativa.com): 14 | - Carlos Roca 15 | - Víctor Martínez 16 | - [Jarsa](https://www.jarsa.com): 17 | - Alan Ramos \<\> 18 | - [Bloopark systems](https://www.bloopark.de/): 19 | - Achraf Mhadhbi \<\> 20 | -------------------------------------------------------------------------------- /base_comment_template/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | Add a new mixin class to define templates of comments to print on 2 | documents. The comment templates can be defined like make templates, so 3 | you can use variables from linked models. 4 | 5 | Two positions are available for the comments: 6 | 7 | - above document lines (before_lines) 8 | - below document lines (after_lines) 9 | 10 | The template are general, and can be attached to any Model and based on 11 | some domain defined in the template. You can define one default template 12 | per Model and domain, which can be overwritten for any company and 13 | partners. It has a priority field (smaller number = higher priority) 14 | 15 | In existing reports, if you add this line will get the comment template 16 | if you created one like 17 | 18 | - \ ( or without any parameter) 21 | 22 | This module is the base module for following modules: 23 | 24 | - sale_comment_template 25 | - purchase_comment_template 26 | - account_comment_template 27 | - stock_picking_comment_template 28 | -------------------------------------------------------------------------------- /base_comment_template/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | 1. Go to *Settings* and activate the developer mode. 2 | 2. Go to *Settings \> Technical \> Reporting \> Comment Templates*. 3 | 3. Create a new record. 4 | 4. Define the Company the template is linked or leave default for all 5 | companies. 6 | 5. Define the Partner the template is linked or leave default for all 7 | partners. 8 | 6. Define the Model, Domain the template is linked. 9 | 7. Define the Position where the template will be printed: 10 | - above document lines 11 | - below document lines 12 | 13 | You should have at least one template with Default field set, if you 14 | choose a Partner the template is deselected as a Default one. If you 15 | create a new template with the same configuration (Model, Domain, 16 | Position) and set it as Default, the previous one will be deselected as 17 | a default one. 18 | 19 | The template is a html field which will be rendered just like a mail 20 | template, so you can use variables like {{object}}, {{user}}, {{ctx}} to 21 | add dynamic content. 22 | 23 | Change the report related to the model from configuration and add a 24 | statement like: 25 | 26 | \ 27 | \
28 | 29 | \ 30 | 31 | \ 32 | \
33 | 34 | \ 35 | 36 | You should always use t-if since the method returns False if no template 37 | is found. 38 | 39 | If you want to use Qweb templates, or different context, you can specify 40 | it just like in mail.render.mixin with parameters: 41 | 42 | - engine: "inline_template", "qweb" or "qweb_view", 43 | - add_context: dict with your own context, 44 | - post_process: perform a post processing on rendered result 45 | 46 | so you could use it : 47 | 48 | \ 49 | \
51 | 52 | \ 53 | -------------------------------------------------------------------------------- /base_comment_template/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_base_comment_template,access_base_comment_template no one,model_base_comment_template,base.group_no_one,1,1,1,1 3 | access_base_comment_template_preview,access.base.comment.template.preview,model_base_comment_template_preview,base.group_user,1,1,1,0 4 | -------------------------------------------------------------------------------- /base_comment_template/security/security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Base comment multi-company 5 | 6 | 7 | 8 | ['|',('company_id','=',False),('company_id','in',company_ids)] 9 | 10 | 11 | -------------------------------------------------------------------------------- /base_comment_template/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/base_comment_template/static/description/icon.png -------------------------------------------------------------------------------- /base_comment_template/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 2 | from . import test_base_comment_template 3 | -------------------------------------------------------------------------------- /base_comment_template/tests/fake_models.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 LasLabs Inc. 2 | # Copyright 2018 ACSONE 3 | # Copyright 2018 Camptocamp 4 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). 5 | 6 | from odoo import models 7 | 8 | 9 | def setup_test_model(env, model_cls): 10 | """Pass a test model class and initialize it. 11 | 12 | Courtesy of SBidoul from https://github.com/OCA/mis-builder :) 13 | """ 14 | model_cls._build_model(env.registry, env.cr) 15 | env.registry.setup_models(env.cr) 16 | env.registry.init_models( 17 | env.cr, [model_cls._name], dict(env.context, update_custom_fields=True) 18 | ) 19 | 20 | 21 | def teardown_test_model(env, model_cls): 22 | """Pass a test model class and deinitialize it. 23 | 24 | Courtesy of SBidoul from https://github.com/OCA/mis-builder :) 25 | """ 26 | if not getattr(model_cls, "_teardown_no_delete", False): 27 | del env.registry.models[model_cls._name] 28 | env.registry.setup_models(env.cr) 29 | 30 | 31 | class ResUsers(models.Model): 32 | _name = "res.users" 33 | _inherit = ["res.users", "comment.template"] 34 | _teardown_no_delete = True 35 | -------------------------------------------------------------------------------- /base_comment_template/views/res_partner_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | res.partner 4 | 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /base_comment_template/wizard/__init__.py: -------------------------------------------------------------------------------- 1 | from . import base_comment_template_preview 2 | -------------------------------------------------------------------------------- /bi_sql_editor/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 2 | 3 | from . import models 4 | from .hooks import uninstall_hook 5 | -------------------------------------------------------------------------------- /bi_sql_editor/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) 2 | # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) 3 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 4 | 5 | { 6 | "name": "BI SQL Editor", 7 | "summary": "BI Views builder, based on Materialized or Normal SQL Views", 8 | "version": "18.0.1.0.2", 9 | "license": "AGPL-3", 10 | "category": "Reporting", 11 | "author": "GRAP,Odoo Community Association (OCA)", 12 | "website": "https://github.com/OCA/reporting-engine", 13 | "depends": [ 14 | "spreadsheet_dashboard", 15 | "sql_request_abstract", 16 | ], 17 | "data": [ 18 | "security/ir.model.access.csv", 19 | "views/view_bi_sql_view.xml", 20 | ], 21 | "demo": ["demo/res_groups_demo.xml", "demo/bi_sql_view_demo.xml"], 22 | "installable": True, 23 | "uninstall_hook": "uninstall_hook", 24 | "maintainers": ["legalsylvain"], 25 | } 26 | -------------------------------------------------------------------------------- /bi_sql_editor/demo/bi_sql_view_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Draft Incorrect SQL View 10 | incorrect_view 11 | 18 | 19 | 20 | 21 | Partners View 22 | partners_view 23 | 24 | 34 | 35 | 36 | 37 | Modules by Authors 38 | modules_view 39 | 40 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /bi_sql_editor/demo/res_groups_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /bi_sql_editor/hooks.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015-2017 Onestein () 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | 4 | 5 | def uninstall_hook(env): 6 | recs = env["bi.sql.view"].search([]) 7 | for rec in recs: 8 | rec.button_set_draft() 9 | -------------------------------------------------------------------------------- /bi_sql_editor/models/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 2 | 3 | from . import bi_sql_view 4 | from . import bi_sql_view_field 5 | from . import ir_model 6 | -------------------------------------------------------------------------------- /bi_sql_editor/models/ir_model.py: -------------------------------------------------------------------------------- 1 | from odoo import models 2 | 3 | 4 | class IrModelFields(models.Model): 5 | _inherit = "ir.model.fields" 6 | 7 | def _add_manual_fields(self, model): 8 | res = super()._add_manual_fields(model) 9 | self.env["bi.sql.view"].check_manual_fields(model) 10 | return res 11 | -------------------------------------------------------------------------------- /bi_sql_editor/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /bi_sql_editor/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | - Go to Dashboard / Configuration / SQL Views 2 | 3 | - tip your SQL request 4 | 5 | ![](../static/description/01_sql_request.png) 6 | 7 | - Select the group(s) that could have access to the view 8 | 9 | ![](../static/description/02_security_access.png) 10 | 11 | Optionnaly, you can add a domain. 12 | 13 | A tipical domain in a multi company context is to write 14 | `['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]` 15 | to make reporting depending on the current companies of the user. 16 | 17 | - Click on the button 'Validate SQL Expression' 18 | 19 | - Once the sql request checked, the module analyses the column of the 20 | view, and propose field mapping. For each field, you can decide to 21 | create an index and set if it will be displayed on the pivot graph as 22 | a column, a row or a measure. 23 | 24 | ![](../static/description/03_field_mapping.png) 25 | 26 | - Click on the button 'Create SQL elements'. (this step could take a 27 | while, if view is materialized) 28 | 29 | - If it's a MATERIALIZED view: 30 | 31 | > - a cron task is created to refresh the view. You can so define the 32 | > frequency of the refresh. 33 | > - the size of view (and the indexes is displayed) 34 | 35 | ![](../static/description/04_materialized_view_setting.png) 36 | 37 | - Before applying the final step, you will need to add a specific Parent Menu to 38 | use when creating the UI Menu for the report. By default, it will be set with 39 | the `SQL Views` menu, which can be changed before creating the UI elements in 40 | order to have the report accessible from a different place within Odoo. 41 | 42 | - Finally, click on 'Create UI', to create new menu, action, graph view 43 | and search view. 44 | -------------------------------------------------------------------------------- /bi_sql_editor/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Sylvain LE GAL () 2 | 3 | - Richard deMeester, WilldooIT () 4 | 5 | - David James, WilldooIT () 6 | 7 | - Guillem Casassas 8 | 9 | - Thien Vo 10 | 11 | - This module is highly inspired by the work of 12 | - Onestein: () Module: 13 | OCA/server-tools/bi_view_editor. Link: 14 | 15 | - Anybox: () Module : 16 | OCA/server-tools/materialized_sql_view link: 17 | 18 | - GRAP, Groupement Régional Alimentaire de Proximité: 19 | () Module: 20 | grap/odoo-addons-misc/pos_sale_reporting link: 21 | 22 | -------------------------------------------------------------------------------- /bi_sql_editor/readme/CREDITS.md: -------------------------------------------------------------------------------- 1 | The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp. 2 | -------------------------------------------------------------------------------- /bi_sql_editor/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module extends the functionality of reporting, to support creation 2 | of extra custom reports. It allows user to write a custom SQL request. 3 | (Generally, admin users) 4 | 5 | Once written, a new model is generated, and user can map the selected 6 | field with odoo fields. Then user ends the process, creating new menu, 7 | action and graph view. 8 | 9 | Technically, the module create SQL View (or materialized view, if option 10 | is checked). Materialized view duplicates datas, but request are 11 | fastest. If materialized view is enabled, this module will create a cron 12 | task to refresh the data). 13 | 14 | By default, users member of 'SQL Request / User' can see all the views. 15 | You can specify extra groups that have the right to access to a specific 16 | view. 17 | 18 | ## Warning 19 | 20 | This module is intended for technician people in a company and for Odoo 21 | integrators. 22 | 23 | It requires the user to know SQL syntax and Odoo models. 24 | 25 | If you don't have such skills, do not try to use this module specially 26 | on a production environment. 27 | 28 | ## Use Cases 29 | 30 | this module is interesting for the following use cases 31 | 32 | - You want to realize technical SQL requests, that Odoo framework 33 | doesn't allow (For exemple, UNION with many SELECT) A typical use case 34 | is if you want to have Sale Orders and PoS Orders datas in a same 35 | table 36 | - You want to customize an Odoo report, removing some useless fields and 37 | adding some custom ones. In that case, you can simply select the 38 | fields of the original report (sale.report model for exemple), and add 39 | your custom fields 40 | - You have a lot of data, and classical SQL Views have very bad 41 | performance. In that case, MATERIALIZED VIEW will be a good solution 42 | to reduce display duration 43 | -------------------------------------------------------------------------------- /bi_sql_editor/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | To use this module, you need to: 2 | 3 | 1. Go to 'Dashboards \> SQL Reports' 4 | 2. Select the desired report 5 | 6 | > ![usage-image1](../static/description/05_reporting_pivot.png) 7 | 8 | - You can switch to 'Graph' or 'tree' views as any report. 9 | -------------------------------------------------------------------------------- /bi_sql_editor/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_bi_sql_view_all,access_bi_sql_view_all,model_bi_sql_view,,0,0,0,0 3 | access_bi_sql_view_manager,access_bi_sql_view_manager,model_bi_sql_view,sql_request_abstract.group_sql_request_manager,1,1,1,1 4 | ,,,,,,, 5 | access_bi_sql_view_field_all,access_bi_sql_view_field_all,model_bi_sql_view_field,,0,0,0,0 6 | access_bi_sql_view_field_manager,access_bi_sql_view_field_manager,model_bi_sql_view_field,sql_request_abstract.group_sql_request_manager,1,1,1,1 7 | -------------------------------------------------------------------------------- /bi_sql_editor/static/description/01_sql_request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/bi_sql_editor/static/description/01_sql_request.png -------------------------------------------------------------------------------- /bi_sql_editor/static/description/02_security_access.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/bi_sql_editor/static/description/02_security_access.png -------------------------------------------------------------------------------- /bi_sql_editor/static/description/03_field_mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/bi_sql_editor/static/description/03_field_mapping.png -------------------------------------------------------------------------------- /bi_sql_editor/static/description/04_materialized_view_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/bi_sql_editor/static/description/04_materialized_view_setting.png -------------------------------------------------------------------------------- /bi_sql_editor/static/description/05_reporting_pivot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/bi_sql_editor/static/description/05_reporting_pivot.png -------------------------------------------------------------------------------- /bi_sql_editor/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/bi_sql_editor/static/description/icon.png -------------------------------------------------------------------------------- /bi_sql_editor/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 2 | from . import test_bi_sql_view 3 | -------------------------------------------------------------------------------- /checklog-odoo.cfg: -------------------------------------------------------------------------------- 1 | [checklog-odoo] 2 | ignore= 3 | WARNING.* 0 failed, 0 error\(s\).* 4 | -------------------------------------------------------------------------------- /pdf_xml_attachment/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | -------------------------------------------------------------------------------- /pdf_xml_attachment/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Camptocamp SA 2 | # @author: Simone Orsi 3 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). 4 | 5 | { 6 | "name": "PDF XML attachment", 7 | "version": "18.0.1.0.0", 8 | "category": "Tools", 9 | "license": "LGPL-3", 10 | "summary": "Provides helpers to work w/ PDFs and XML attachments", 11 | "author": "Camptocamp, Odoo Community Association (OCA)", 12 | "maintainers": ["simahawk", "alexis-via"], 13 | "website": "https://github.com/OCA/reporting-engine", 14 | "depends": [ 15 | "base", 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /pdf_xml_attachment/i18n/es.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * pdf_xml_attachment 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 16.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2023-08-07 11:09+0000\n" 10 | "Last-Translator: Ivorra78 \n" 11 | "Language-Team: none\n" 12 | "Language: es\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 4.17\n" 18 | 19 | #. module: pdf_xml_attachment 20 | #: model:ir.model,name:pdf_xml_attachment.model_pdf_xml_tool 21 | msgid "PDF XML attachment" 22 | msgstr "Ayudante de PDF" 23 | -------------------------------------------------------------------------------- /pdf_xml_attachment/i18n/hr.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * pdf_xml_attachment 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 16.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2023-06-02 12:09+0000\n" 10 | "Last-Translator: Bole \n" 11 | "Language-Team: none\n" 12 | "Language: hr\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " 17 | "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" 18 | "X-Generator: Weblate 4.17\n" 19 | 20 | #. module: pdf_xml_attachment 21 | #: model:ir.model,name:pdf_xml_attachment.model_pdf_xml_tool 22 | msgid "PDF XML attachment" 23 | msgstr "PDF Pomoćnik" 24 | -------------------------------------------------------------------------------- /pdf_xml_attachment/i18n/it.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * pdf_xml_attachment 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 17.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2024-02-04 23:45+0000\n" 10 | "Last-Translator: mymage \n" 11 | "Language-Team: none\n" 12 | "Language: it\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 4.17\n" 18 | 19 | #. module: pdf_xml_attachment 20 | #: model:ir.model,name:pdf_xml_attachment.model_pdf_xml_tool 21 | msgid "PDF XML attachment" 22 | msgstr "Aiuto PDF" 23 | -------------------------------------------------------------------------------- /pdf_xml_attachment/i18n/pdf_helper.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * pdf_xml_attachment 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 17.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "Last-Translator: \n" 10 | "Language-Team: \n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: \n" 14 | "Plural-Forms: \n" 15 | 16 | #. module: pdf_xml_attachment 17 | #: model:ir.model,name:pdf_xml_attachment.model_pdf_xml_attachment 18 | msgid "PDF XML attachment" 19 | msgstr "" 20 | -------------------------------------------------------------------------------- /pdf_xml_attachment/i18n/pdf_xml_attachment.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * pdf_xml_attachment 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 18.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "Last-Translator: \n" 10 | "Language-Team: \n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: \n" 14 | "Plural-Forms: \n" 15 | 16 | #. module: pdf_xml_attachment 17 | #: model:ir.model,name:pdf_xml_attachment.model_pdf_xml_tool 18 | msgid "PDF XML attachment" 19 | msgstr "" 20 | -------------------------------------------------------------------------------- /pdf_xml_attachment/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import helper 2 | -------------------------------------------------------------------------------- /pdf_xml_attachment/models/helper.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Camptocamp SA 2 | # @author: Simone Orsi 3 | # Copyright 2023 Jacques-Etienne Baudoux (BCIM) 4 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). 5 | 6 | import io 7 | import logging 8 | 9 | from odoo import api, models 10 | from odoo.tools.pdf import NameObject, OdooPdfFileReader, OdooPdfFileWriter 11 | 12 | from ..utils import PDFParser 13 | 14 | _logger = logging.getLogger(__name__) 15 | 16 | 17 | class PDFHelper(models.AbstractModel): 18 | _name = "pdf.xml.tool" 19 | _description = "PDF XML attachment" 20 | 21 | _PDF_PARSER_KLASS = PDFParser 22 | 23 | @api.model 24 | def pdf_get_xml_files(self, pdf_file): 25 | """Extract XML attachments from pdf 26 | 27 | :param pdf_file: binary PDF file content 28 | :returns: a dict like {$filename: $parsed_xml_file_obj}. 29 | """ 30 | parser = self._PDF_PARSER_KLASS(pdf_file) 31 | try: 32 | return parser.get_xml_files() 33 | except parser.get_xml_files_swallable_exceptions() as err: 34 | _logger.error("PDF file parsing failed: %s", str(err)) 35 | return {} 36 | 37 | @api.model 38 | def pdf_embed_xml(self, pdf_content, xml_filename, xml_string): 39 | """Add an XML attachment in a pdf""" 40 | with io.BytesIO(pdf_content) as reader_buffer, io.BytesIO() as new_pdf_stream: 41 | reader = OdooPdfFileReader(reader_buffer, strict=False) 42 | writer = OdooPdfFileWriter() 43 | writer.cloneReaderDocumentRoot(reader) 44 | writer.addAttachment(xml_filename, xml_string, subtype="text/xml") 45 | # show attachments when opening PDF 46 | writer._root_object.update( 47 | {NameObject("/PageMode"): NameObject("/UseAttachments")} 48 | ) 49 | writer.write(new_pdf_stream) 50 | return new_pdf_stream.getvalue() 51 | -------------------------------------------------------------------------------- /pdf_xml_attachment/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /pdf_xml_attachment/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Simone Orsi \<\> 2 | - Alexis de Lattre \<\> 3 | - Jacques-Etienne Baudoux (BCIM) \<\> 4 | -------------------------------------------------------------------------------- /pdf_xml_attachment/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | Technical module to share easily deal with XML attachments in PDF files. 2 | -------------------------------------------------------------------------------- /pdf_xml_attachment/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | Inside Odoo env: 2 | 3 | res = env["pdf.xml.tool"].pdf_get_xml_files(pdf_filecontent) 4 | 5 | new_pdf_filecontent = env["pdf.xml.tool"].pdf_embed_xml(pdf_filecontent, filename, xml) 6 | 7 | Outside Odoo env: 8 | 9 | from odoo.addons.pdf_xml_attachment.utils import PDFParser 10 | [...] 11 | res = PDFParser(pdf_filecontent).get_xml_files() 12 | -------------------------------------------------------------------------------- /pdf_xml_attachment/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/pdf_xml_attachment/static/description/icon.png -------------------------------------------------------------------------------- /pdf_xml_attachment/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_helper 2 | -------------------------------------------------------------------------------- /pdf_xml_attachment/tests/fixtures/pdf_with_xml_test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/pdf_xml_attachment/tests/fixtures/pdf_with_xml_test.pdf -------------------------------------------------------------------------------- /pdf_xml_attachment/tests/test_helper.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Camptocamp SA 2 | # @author: Simone Orsi 3 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). 4 | import os 5 | 6 | from lxml import etree 7 | 8 | from odoo.tests.case import TestCase 9 | from odoo.tests.common import TransactionCase 10 | 11 | from odoo.addons.pdf_xml_attachment.utils import PDFParser 12 | 13 | 14 | def read_test_file(filename, mode="r"): 15 | path = os.path.join(os.path.dirname(__file__), "fixtures", filename) 16 | with open(path, mode) as thefile: 17 | return thefile.read() 18 | 19 | 20 | class TestPDFHelperUtils(TestCase): 21 | def test_parse_xml(self): 22 | pdf_content = read_test_file("pdf_with_xml_test.pdf", mode="rb") 23 | res = PDFParser(pdf_content).get_xml_files() 24 | fname, xml_root = tuple(res.items())[0] 25 | self.assertEqual(fname, "factur-x.xml") 26 | self.assertTrue(isinstance(xml_root, etree._Element)) 27 | 28 | 29 | class TestPDFHelper(TransactionCase): 30 | def test_get_xml(self): 31 | pdf_content = read_test_file("pdf_with_xml_test.pdf", mode="rb") 32 | res = self.env["pdf.xml.tool"].pdf_get_xml_files(pdf_content) 33 | fname, xml_root = tuple(res.items())[0] 34 | self.assertEqual(fname, "factur-x.xml") 35 | self.assertTrue(isinstance(xml_root, etree._Element)) 36 | 37 | def test_get_xml_fail(self): 38 | with self.assertLogs( 39 | "odoo.addons.pdf_xml_attachment.models.helper", level="ERROR" 40 | ) as log_catcher: 41 | self.env["pdf.xml.tool"].pdf_get_xml_files(b"") 42 | self.assertIn( 43 | "PDF file parsing failed: Cannot read an empty file", 44 | log_catcher.output[0], 45 | ) 46 | 47 | def _test_embed_xml(self): 48 | pdf_content = read_test_file("pdf_with_xml_test.pdf", mode="rb") 49 | filename = "test" 50 | xml = b"test" 51 | newpdf_content = self.env["pdf.xml.tool"].pdf_embed_xml( 52 | pdf_content, filename, xml 53 | ) 54 | attachments = self.env["pdf.xml.tool"].pdf_get_xml_files(newpdf_content) 55 | self.assertTrue(filename in attachments) 56 | etree_content = attachments[filename] 57 | self.assertEqual(xml, etree.tostring(etree_content)) 58 | -------------------------------------------------------------------------------- /pdf_xml_attachment/utils.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015-2021 Akretion France 2 | # @author: Alexis de Lattre 3 | # Copyright 2022 Camptocamp SA 4 | # @author: Simone Orsi 5 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). 6 | 7 | import logging 8 | from io import BytesIO 9 | from struct import error as StructError 10 | 11 | from lxml import etree 12 | 13 | from odoo.tools.pdf import OdooPdfFileReader, PdfReadError 14 | 15 | _logger = logging.getLogger(__name__) 16 | 17 | 18 | class PDFParser: 19 | def __init__(self, pdf_file): 20 | self.pdf_file = pdf_file 21 | 22 | def get_xml_files(self): 23 | """Parse PDF files to extract XML content. 24 | 25 | :param pdf_file: binary PDF file content 26 | :returns: a dict like {$filename: $parsed_xml_file_obj}. 27 | """ 28 | res = {} 29 | with BytesIO(self.pdf_file) as buffer: 30 | pdf_reader = OdooPdfFileReader(buffer, strict=False) 31 | 32 | # Process embedded files. 33 | for xml_name, content in pdf_reader.getAttachments(): 34 | try: 35 | res[xml_name] = etree.fromstring(content) 36 | except Exception: 37 | _logger.debug("Non XML file found in PDF") 38 | if res: 39 | _logger.debug("Valid XML files found in PDF: %s", list(res.keys())) 40 | return res 41 | 42 | def get_xml_files_swallable_exceptions(self): 43 | return (NotImplementedError, StructError, PdfReadError) 44 | -------------------------------------------------------------------------------- /prettier.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('prettier').Config} */ 2 | 3 | const config = { 4 | // https://github.com/prettier/prettier/issues/15388#issuecomment-1717746872 5 | plugins: [require.resolve("@prettier/plugin-xml")], 6 | bracketSpacing: false, 7 | printWidth: 88, 8 | proseWrap: "always", 9 | semi: true, 10 | trailingComma: "es5", 11 | xmlWhitespaceSensitivity: "preserve", 12 | }; 13 | 14 | module.exports = config; 15 | -------------------------------------------------------------------------------- /report_csv/__init__.py: -------------------------------------------------------------------------------- 1 | from . import controllers 2 | from . import models 3 | from . import report 4 | -------------------------------------------------------------------------------- /report_csv/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Creu Blanca 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). 3 | { 4 | "name": "Base report csv", 5 | "summary": "Base module to create csv report", 6 | "author": "Creu Blanca, Odoo Community Association (OCA)", 7 | "website": "https://github.com/OCA/reporting-engine", 8 | "category": "Reporting", 9 | "version": "18.0.1.0.0", 10 | "license": "AGPL-3", 11 | "depends": ["base", "web"], 12 | "demo": ["demo/report.xml"], 13 | "data": ["views/ir_actions_views.xml"], 14 | "assets": { 15 | "web.assets_backend": [ 16 | "report_csv/static/src/js/report/qwebactionmanager.esm.js" 17 | ] 18 | }, 19 | "development_status": "Production/Stable", 20 | "installable": True, 21 | } 22 | -------------------------------------------------------------------------------- /report_csv/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import main 2 | -------------------------------------------------------------------------------- /report_csv/demo/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | Print to CSV 9 | res.partner 10 | csv 11 | report_csv.partner_csv 12 | res_partner 13 | 14 | 15 | -------------------------------------------------------------------------------- /report_csv/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import ir_report 2 | -------------------------------------------------------------------------------- /report_csv/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_csv/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | In case the exported CSV report should be encoded in another system than 2 | UTF-8, following fields of the report record (*Settings \> Technical \> 3 | Reports*) should be populated accordingly. 4 | 5 | - Encoding: set an encoding system (such as cp932) 6 | - Encode Error Handling: select 'Ignore' or 'Replace' as necessary. 7 | - 'Ignore': in case of an encoding error, the problematic character 8 | will be removed from the exported file. 9 | - 'Replace': in case of an encoding error, the problematic character 10 | will be replaced with '?' symbol. 11 | - Leaving the field blank: in case of an encoding error, the report 12 | generation fails with an error message. 13 | -------------------------------------------------------------------------------- /report_csv/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Enric Tobella \<\> 2 | - Jaime Arroyo \<\> 3 | - Rattapong Chokmasermkul \<\> 4 | - [Quartile](https://www.quartile.co): 5 | - Aung Ko Ko Lin 6 | -------------------------------------------------------------------------------- /report_csv/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module provides a basic report class to generate csv report. 2 | -------------------------------------------------------------------------------- /report_csv/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | An example of CSV report for partners on a module called 2 | \`module_name\`: 3 | 4 | A python class : 5 | 6 | from odoo import models 7 | 8 | class PartnerCSV(models.AbstractModel): 9 | _name = 'report.report_csv.partner_csv' 10 | _inherit = 'report.report_csv.abstract' 11 | 12 | def generate_csv_report(self, writer, data, partners): 13 | writer.writeheader() 14 | for obj in partners: 15 | writer.writerow({ 16 | 'name': obj.name, 17 | 'email': obj.email, 18 | }) 19 | 20 | def csv_report_options(self): 21 | res = super().csv_report_options() 22 | res['fieldnames'].append('name') 23 | res['fieldnames'].append('email') 24 | res['delimiter'] = ';' 25 | res['quoting'] = csv.QUOTE_ALL 26 | return res 27 | 28 | A report XML record : 29 | 30 | 39 | 40 | Update encoding with an appropriate value (e.g. cp932) as necessary. 41 | -------------------------------------------------------------------------------- /report_csv/report/__init__.py: -------------------------------------------------------------------------------- 1 | from . import report_csv 2 | from . import report_partner_csv 3 | -------------------------------------------------------------------------------- /report_csv/report/report_partner_csv.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Creu Blanca 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). 3 | import csv 4 | 5 | from odoo import models 6 | 7 | 8 | class PartnerCSV(models.AbstractModel): 9 | _name = "report.report_csv.partner_csv" 10 | _inherit = "report.report_csv.abstract" 11 | _description = "Report Partner to CSV" 12 | 13 | def generate_csv_report(self, writer, data, partners): 14 | writer.writeheader() 15 | for obj in partners: 16 | writer.writerow({"name": obj.name, "email": obj.email}) 17 | 18 | def csv_report_options(self): 19 | res = super().csv_report_options() 20 | res["fieldnames"].append("name") 21 | res["fieldnames"].append("email") 22 | res["delimiter"] = ";" 23 | res["quoting"] = csv.QUOTE_ALL 24 | return res 25 | -------------------------------------------------------------------------------- /report_csv/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_csv/static/description/icon.png -------------------------------------------------------------------------------- /report_csv/static/src/js/report/qwebactionmanager.esm.js: -------------------------------------------------------------------------------- 1 | import {download} from "@web/core/network/download"; 2 | import {registry} from "@web/core/registry"; 3 | import {user} from "@web/core/user"; 4 | 5 | registry 6 | .category("ir.actions.report handlers") 7 | .add("csv_handler", async function (action, options, env) { 8 | if (action.report_type === "csv") { 9 | const type = action.report_type; 10 | let url = `/report/${type}/${action.report_name}`; 11 | const actionContext = action.context || {}; 12 | if (action.data && JSON.stringify(action.data) !== "{}") { 13 | // Build a query string with `action.data` (it's the place where reports 14 | // using a wizard to customize the output traditionally put their options) 15 | const action_options = encodeURIComponent(JSON.stringify(action.data)); 16 | const context = encodeURIComponent(JSON.stringify(actionContext)); 17 | url += `?options=${action_options}&context=${context}`; 18 | } else { 19 | if (actionContext.active_ids) { 20 | url += `/${actionContext.active_ids.join(",")}`; 21 | } 22 | if (type === "csv") { 23 | const context = encodeURIComponent(JSON.stringify(user.context)); 24 | url += `?context=${context}`; 25 | } 26 | } 27 | env.services.ui.block(); 28 | try { 29 | await download({ 30 | url: "/report/download", 31 | data: { 32 | data: JSON.stringify([url, action.report_type]), 33 | context: JSON.stringify(user.context), 34 | }, 35 | }); 36 | } finally { 37 | env.services.ui.unblock(); 38 | } 39 | const onClose = options.onClose; 40 | if (action.close_on_report_download) { 41 | return env.services.action.doAction( 42 | {type: "ir.actions.act_window_close"}, 43 | {onClose} 44 | ); 45 | } else if (onClose) { 46 | onClose(); 47 | } 48 | return Promise.resolve(true); 49 | } 50 | return Promise.resolve(false); 51 | }); 52 | -------------------------------------------------------------------------------- /report_csv/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_report 2 | -------------------------------------------------------------------------------- /report_csv/views/ir_actions_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ir.actions.report 5 | ir.actions.report 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /report_py3o/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | from . import controllers 3 | -------------------------------------------------------------------------------- /report_py3o/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013 XCG Consulting (http://odoo.consulting) 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | { 4 | "name": "Py3o Report Engine", 5 | "summary": "Reporting engine based on Libreoffice (ODT -> ODT, " 6 | "ODT -> PDF, ODT -> DOC, ODT -> DOCX, ODS -> ODS, etc.)", 7 | "version": "18.0.1.0.0", 8 | "category": "Reporting", 9 | "license": "AGPL-3", 10 | "author": "XCG Consulting, ACSONE SA/NV, Odoo Community Association (OCA)", 11 | "website": "https://github.com/OCA/reporting-engine", 12 | "depends": ["web"], 13 | "external_dependencies": { 14 | "python": ["py3o.template", "py3o.formats"], 15 | "deb": ["libreoffice"], 16 | }, 17 | "assets": { 18 | "web.assets_backend": [ 19 | "report_py3o/static/src/js/py3oactionservice.esm.js", 20 | ], 21 | }, 22 | "data": [ 23 | "security/ir.model.access.csv", 24 | "views/py3o_template.xml", 25 | "views/ir_actions_report.xml", 26 | "demo/report_py3o.xml", 27 | ], 28 | "installable": True, 29 | } 30 | -------------------------------------------------------------------------------- /report_py3o/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import main 2 | -------------------------------------------------------------------------------- /report_py3o/demo/report_py3o.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | Py3o Demo Report 7 | ir.actions.report 8 | res.users 9 | py3o_user_info 10 | py3o 11 | odt 12 | report_py3o 13 | demo/res_user.odt 14 | object.name.replace(' ', '_') + '-demo.odt' 17 | 18 | report 19 | 20 | 21 | -------------------------------------------------------------------------------- /report_py3o/demo/res_user.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_py3o/demo/res_user.odt -------------------------------------------------------------------------------- /report_py3o/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import py3o_template 2 | from . import ir_actions_report 3 | from . import py3o_report 4 | -------------------------------------------------------------------------------- /report_py3o/models/py3o_template.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013 XCG Consulting (http://odoo.consulting) 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | from odoo import fields, models 4 | 5 | 6 | class Py3oTemplate(models.Model): 7 | _name = "py3o.template" 8 | _description = "Py3o template" 9 | 10 | name = fields.Char(required=True) 11 | py3o_template_data = fields.Binary("LibreOffice Template") 12 | filetype = fields.Selection( 13 | selection=[ 14 | ("odt", "ODF Text Document"), 15 | ("ods", "ODF Spreadsheet"), 16 | ("odp", "ODF Presentation"), 17 | ("fodt", "ODF Text Document (Flat)"), 18 | ("fods", "ODF Spreadsheet (Flat)"), 19 | ("fodp", "ODF Presentation (Flat)"), 20 | ], 21 | string="LibreOffice Template File Type", 22 | required=True, 23 | default="odt", 24 | ) 25 | -------------------------------------------------------------------------------- /report_py3o/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_py3o/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Florent Aide (\[XCG Consulting\]()) 2 | - Laurent Mignon \<\<\>\>, 3 | - Alexis de Lattre \<\<\>\>, 4 | - Guewen Baconnier \<\<\>\> 5 | - Omar Casti??eira \<\<\>\> 6 | - Holger Brunn \<\<\>\> 7 | - Phuc Tran Thanh \<\<\>\> 8 | - Souheil Bejaoui \<\<\>\>, 9 | -------------------------------------------------------------------------------- /report_py3o/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | The py3o reporting engine is a reporting engine for Odoo based on 2 | \[Libreoffice\](): 3 | 4 | - the report is created with Libreoffice (ODT or ODS), 5 | - the report is stored on the server in OpenDocument format (.odt or 6 | .ods file) 7 | - the report is sent to the user in OpenDocument format or in any output 8 | format supported by Libreoffice (PDF, HTML, DOC, DOCX, Docbook, XLS, 9 | etc.) 10 | 11 | The key advantages of a Libreoffice based reporting engine are: 12 | 13 | - no need to be a developer to create or modify a report: the report is 14 | created and modified with Libreoffice. So this reporting engine has a 15 | full WYSIWYG report development tool! 16 | - For a PDF report in A4/Letter format, it's easier to develop it with a 17 | tool such as Libreoffice that is designed to create A4/Letter 18 | documents than to develop it in HTML/CSS, also some print 19 | peculiarities (backgrounds, margin boxes) are not very well supported 20 | by the HTML/CSS based solutions. 21 | - If you want your users to be able to modify the document after its 22 | generation by Odoo, just configure the document with ODT output (or 23 | DOC or DOCX) and the user will be able to modify the document with 24 | Libreoffice (or Word) after its generation by Odoo. 25 | - Easy development of spreadsheet reports in ODS format (XLS output 26 | possible). 27 | 28 | This module *report_py3o* is the base module for the Py3o reporting 29 | engine. If used alone, it will spawn a libreoffice process for each ODT 30 | to PDF (or ODT to DOCX, ..) document conversion. This is slow and can 31 | become a problem if you have a lot of reports to convert from ODT to 32 | another format. In this case, you should consider the additionnal module 33 | *report_py3o_fusion_server* which is designed to work with a libreoffice 34 | daemon. With *report_py3o_fusion_server*, the technical environnement is 35 | more complex to setup because you have to install additionnal software 36 | components and run 2 daemons, but you have much better performances and 37 | you can configure the libreoffice PDF export options in Odoo (allows to 38 | generate PDF forms, PDF/A documents, password-protected PDFs, 39 | watermarked PDFs, etc.). 40 | 41 | This reporting engine is an alternative to 42 | \[Aeroo\](): these two 43 | reporting engines have similar features but their implementation is 44 | entirely different. You cannot use aeroo templates as drop in 45 | replacement though, you'll have to change a few details. 46 | -------------------------------------------------------------------------------- /report_py3o/readme/INSTALL.md: -------------------------------------------------------------------------------- 1 | Install the required python libs: 2 | 3 | `` ` pip install py3o.template pip install py3o.formats ``\` 4 | 5 | To allow the conversion of ODT or ODS reports to other formats (PDF, 6 | DOC, DOCX, etc.), install libreoffice: 7 | 8 | `` ` apt-get --no-install-recommends install libreoffice ``\` 9 | -------------------------------------------------------------------------------- /report_py3o/readme/ROADMAP.md: -------------------------------------------------------------------------------- 1 | - generate barcode ? 2 | - add more detailed example in demo file to showcase features 3 | - add migration guide aeroo -\> py3o 4 | -------------------------------------------------------------------------------- /report_py3o/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | The templating language is \[extensively 2 | documented\](), 3 | the records are exposed in libreoffice as objects, on which you can also 4 | call functions. 5 | 6 | \## Available functions and objects 7 | 8 | user Browse record of current user 9 | 10 | lang The user's company's language as string (ISO code) 11 | 12 | b64decode base64.b64decode 13 | 14 | format_multiline_value(string) Generate the ODF equivalent of \
15 | and   for multiline fields (ODF is XML internally, so those would 16 | be skipped otherwise) 17 | 18 | html_sanitize(string) Sanitize HTML string 19 | 20 | time Python's time module 21 | 22 | display_address(partner) Return a formatted string of the partner's 23 | address 24 | 25 | o_format_lang(value, lang_code=False, digits=None, grouping=True, 26 | monetary=False, dp=False, currency_obj=False, no_break_space=True) 27 | Return a formatted numeric or monetary value according to the context 28 | language and timezone 29 | 30 | o_format_date(value, lang_code=False, date_format=False) Return a 31 | formatted date or time value according to the context language and 32 | timezone 33 | 34 | \## Sample report templates 35 | 36 | Sample py3o report templates for the main Odoo native reports (invoice, 37 | sale order, purchase order, picking, etc.) are available on the Github 38 | project 39 | \[odoo-py3o-report-templates\](). 40 | -------------------------------------------------------------------------------- /report_py3o/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_py3o_template_admin,access_py3o_template_admin,model_py3o_template,base.group_no_one,1,1,1,1 3 | access_py3o_template_user,access_py3o_template_user,model_py3o_template,base.group_user,1,0,0,0 4 | access_py3o_report_user,access_py3o_report_user,model_py3o_report,base.group_user,1,1,1,1 5 | -------------------------------------------------------------------------------- /report_py3o/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_py3o/static/description/icon.png -------------------------------------------------------------------------------- /report_py3o/static/src/js/py3oactionservice.esm.js: -------------------------------------------------------------------------------- 1 | /** @odoo-module **/ 2 | 3 | import {download} from "@web/core/network/download"; 4 | import {registry} from "@web/core/registry"; 5 | 6 | registry 7 | .category("ir.actions.report handlers") 8 | .add("py3o_handler", async function (action, options, env) { 9 | if (action.report_type === "py3o") { 10 | let url = `/report/py3o/${action.report_name}`; 11 | const actionContext = action.context || {}; 12 | if ( 13 | action.data === undefined || 14 | action.data === null || 15 | (typeof action.data === "object" && 16 | Object.keys(action.data).length === 0) 17 | ) { 18 | // Build a query string with `action.data` (it's the place where reports 19 | // using a wizard to customize the output traditionally put their options) 20 | if (actionContext.active_ids) { 21 | var activeIDsPath = "/" + actionContext.active_ids.join(","); 22 | url += activeIDsPath; 23 | } 24 | } else { 25 | var serializedOptionsPath = 26 | "?options=" + encodeURIComponent(JSON.stringify(action.data)); 27 | serializedOptionsPath += 28 | "&context=" + encodeURIComponent(JSON.stringify(actionContext)); 29 | url += serializedOptionsPath; 30 | } 31 | env.services.ui.block(); 32 | try { 33 | await download({ 34 | url: "/report/download", 35 | data: { 36 | data: JSON.stringify([url, action.report_type]), 37 | context: JSON.stringify(action.context), 38 | }, 39 | }); 40 | } finally { 41 | env.services.ui.unblock(); 42 | } 43 | const onClose = options.onClose; 44 | if (action.close_on_report_download) { 45 | return env.services.action.doAction( 46 | {type: "ir.actions.act_window_close"}, 47 | {onClose} 48 | ); 49 | } else if (onClose) { 50 | onClose(); 51 | } 52 | return Promise.resolve(true); 53 | } 54 | return Promise.resolve(false); 55 | }); 56 | -------------------------------------------------------------------------------- /report_py3o/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_report_py3o 2 | -------------------------------------------------------------------------------- /report_py3o/views/ir_actions_report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | py3o_report_view 6 | ir.actions.report 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | py3o_report_search_view 38 | ir.actions.report 39 | 40 | 41 | 42 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /report_py3o/views/py3o_template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | py3o.template.configuration.search.view 5 | py3o.template 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | py3o.template.configuration.form.view 22 | py3o.template 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | py3o.template.configuration.tree.view 35 | py3o.template 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Py3o Templates 45 | py3o.template 46 | list,form 47 | 48 | 54 |
55 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Therp BV 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | from . import models 4 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Therp BV 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | { 4 | "name": "Py3o Report Engine - Fusion server support", 5 | "summary": "Let the fusion server handle format conversion.", 6 | "version": "18.0.1.0.0", 7 | "category": "Reporting", 8 | "license": "AGPL-3", 9 | "author": "XCG Consulting," 10 | "ACSONE SA/NV," 11 | "Akretion," 12 | "Odoo Community Association (OCA)", 13 | "website": "https://github.com/OCA/reporting-engine", 14 | "depends": ["report_py3o"], 15 | "external_dependencies": { 16 | "python": ["py3o.template", "py3o.formats", "mock"], 17 | "deb": ["libreoffice"], 18 | }, 19 | "demo": ["demo/report_py3o.xml", "demo/py3o_pdf_options.xml"], 20 | "data": [ 21 | "views/ir_actions_report.xml", 22 | "security/ir.model.access.csv", 23 | "views/py3o_server.xml", 24 | "views/py3o_pdf_options.xml", 25 | ], 26 | "installable": True, 27 | } 28 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/demo/py3o_pdf_options.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | PDF/A (for Factur-X invoices) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/demo/report_py3o.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Therp BV 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | from . import ir_actions_report 4 | from . import py3o_pdf_options 5 | from . import py3o_report 6 | from . import py3o_server 7 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/models/py3o_server.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013 XCG Consulting (http://odoo.consulting) 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | from odoo import fields, models 4 | 5 | 6 | class Py3oServer(models.Model): 7 | _name = "py3o.server" 8 | _description = "Py3o server" 9 | _rec_name = "url" 10 | 11 | url = fields.Char( 12 | "Py3o Fusion Server URL", 13 | required=True, 14 | help="If your Py3o Fusion server is on the same machine and runs " 15 | "on the default port, the URL is http://localhost:8765/form", 16 | ) 17 | is_active = fields.Boolean("Active", default=True) 18 | pdf_options_id = fields.Many2one( 19 | "py3o.pdf.options", 20 | string="PDF Options", 21 | ondelete="restrict", 22 | help="PDF options can be set per Py3o Server but also per report. " 23 | "If both are defined, the options on the report are used.", 24 | ) 25 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | To configure the PDF export options: 2 | 3 | 1. Go to the menu *Settings \> Technical \> Reporting \> Py3o \> Py3o 4 | PDF Export Options* and create a PDF export options profile. 5 | 2. Set the PDF export options profile on the Py3o Server (menu 6 | *Settings \> Technical \> Reporting \> Py3o \> Py3o Servers*) or on 7 | a particular Py3o report with PDF output format (menu *Settings \> 8 | Technical \> Actions \> Reports*). 9 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Florent Aide ([XCG Consulting](http://odoo.consulting/)) 2 | - Laurent Mignon \<\>, 3 | - Alexis de Lattre \<\>, 4 | - Guewen Baconnier \<\> 5 | - Omar Castiñeira \<\> 6 | - Holger Brunn \<\> 7 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module was written to let a py3o fusion server handle format 2 | conversion instead of local libreoffice. If you install this module 3 | above the *report_py3o* module, you will have to deploy additionnal 4 | software components and run 3 daemons (libreoffice, py3o.fusion and 5 | py3o.renderserver). This additionnal complexiy comes with several 6 | advantages: 7 | 8 | - much better performances: Libreoffice runs permanently in the 9 | background, no need to spawn a new Libreoffice instance upon every 10 | document conversion. 11 | - ability to configure PDF export options in Odoo. This brings many new 12 | possibilities such as the ability to generate: 13 | - PDF forms 14 | - PDF/A documents (required by some electronic invoicing standards 15 | such as [Factur-X](http://fnfe-mpe.org/factur-x/factur-x_en/)) 16 | - watermarked PDF documents 17 | - password-protected PDF documents 18 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/readme/ROADMAP.md: -------------------------------------------------------------------------------- 1 | - Add support for PDF signatures (possible, but no easy because the 2 | signature certificate is a very particular PDF export option) 3 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_py3o_server_admin,access_py3o_server_admin,model_py3o_server,base.group_system,1,1,1,1 3 | access_py3o_server_user,access_py3o_server_user,model_py3o_server,base.group_user,1,0,0,0 4 | access_py3o_pdf_options_admin,Full access to PDF options to Settings grp,model_py3o_pdf_options,base.group_system,1,1,1,1 5 | access_py3o_pdf_options_user,Read-only access to PDF options to employees,model_py3o_pdf_options,base.group_user,1,0,0,0 6 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_py3o_fusion_server/static/description/icon.png -------------------------------------------------------------------------------- /report_py3o_fusion_server/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Therp BV 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | from . import test_report_py3o_fusion_server 4 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/views/ir_actions_report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ir.actions.report 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /report_py3o_fusion_server/views/py3o_server.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | py3o.server.configuration.form.view 5 | py3o.server 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 | py3o.server.configuration.tree.view 18 | py3o.server 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Py3o Servers 29 | py3o.server 30 | list,form 31 | 32 | 38 |
39 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Agile Business Group 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 Agile Business Group 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | 4 | { 5 | "name": "Report Qweb Element Page Visibility", 6 | "version": "18.0.1.0.0", 7 | "author": "Agile Business Group, Odoo Community Association (OCA)", 8 | "category": "Tools", 9 | "website": "https://github.com/OCA/reporting-engine", 10 | "license": "AGPL-3", 11 | "application": False, 12 | "installable": True, 13 | "data": ["views/layouts.xml"], 14 | "depends": ["web"], 15 | } 16 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/i18n/it.po: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_qweb_element_page_visibility/i18n/it.po -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/i18n/report_qweb_element_page_visibility.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # 4 | msgid "" 5 | msgstr "" 6 | "Project-Id-Version: Odoo Server 18.0\n" 7 | "Report-Msgid-Bugs-To: \n" 8 | "Last-Translator: \n" 9 | "Language-Team: \n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=UTF-8\n" 12 | "Content-Transfer-Encoding: \n" 13 | "Plural-Forms: \n" 14 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Nicola Malcontenti \<\> 2 | 3 | - Lorenzo Battistini \<\> 4 | 5 | - Alessio Gerace \<\> 6 | 7 | - Alex Comba \<\> 8 | 9 | - Saran Limpajitkutaporn \<\> 10 | 11 | - Pimolnat Suntian \<\> 12 | 13 | - Tharathip Chaweewongphan \<\> 14 | 15 | - [Trobz](https://trobz.com): 16 | - Hai Lang \<\> 17 | 18 | - Ángel Tornero Hernández \<\> 19 | 20 | - Daniel Lagin \<\> 21 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/readme/CREDITS.md: -------------------------------------------------------------------------------- 1 | The migration of this module from 14.0 to 14.0 was financially supported 2 | by Camptocamp 3 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module allows you to use 4 classes in QWEB reports: 2 | 3 | - not-first-page: shows element in every page but first 4 | - not-last-page: shows element in every page but last 5 | - first-page: shows element only on first page 6 | - last-page: shows element only on last page 7 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | To use this module, you need to: 2 | 3 | In the QWEB `ir.ui.views` used by your report, you can add an element 4 | with css class with any of the classes described above. For example if 5 | you need to improve invoice report header with invoice's number in every 6 | page but first, and sale order report header with order's name in every 7 | page but last, add this code to external_layout_header: 8 | 9 | 10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /report_qweb_element_page_visibility/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_qweb_element_page_visibility/static/description/icon.png -------------------------------------------------------------------------------- /report_qweb_parameter/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 2 | 3 | from . import models 4 | -------------------------------------------------------------------------------- /report_qweb_parameter/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | 4 | { 5 | "name": "Report QWeb Parameter", 6 | "version": "18.0.1.0.0", 7 | "license": "AGPL-3", 8 | "summary": """ 9 | Add new parameters for qweb templates in order to reduce field length 10 | and check minimal length 11 | """, 12 | "author": "Creu Blanca, Odoo Community Association (OCA)", 13 | "website": "https://github.com/OCA/reporting-engine", 14 | "category": "Technical Settings", 15 | "depends": ["web"], 16 | "demo": ["demo/test_report_field_length.xml"], 17 | "installable": True, 18 | } 19 | -------------------------------------------------------------------------------- /report_qweb_parameter/demo/test_report_field_length.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Length Report 5 | res.company 6 | qweb-html 7 | report_qweb_parameter.test_report_length 8 | 9 | 67 | 68 | -------------------------------------------------------------------------------- /report_qweb_parameter/i18n/ca.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_qweb_parameter 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 15.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2022-06-15 18:05+0000\n" 10 | "Last-Translator: jabelchi \n" 11 | "Language-Team: none\n" 12 | "Language: ca\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 4.3.2\n" 18 | 19 | #. module: report_qweb_parameter 20 | #: model:ir.actions.report,name:report_qweb_parameter.test_report_length_report_id 21 | msgid "Length Report" 22 | msgstr "Longitud de l'informe" 23 | 24 | #. module: report_qweb_parameter 25 | #. odoo-python 26 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 27 | #, python-format 28 | msgid "Length cannot be less than %s" 29 | msgstr "La longitut no pot ser menor que %s" 30 | 31 | #. module: report_qweb_parameter 32 | #. odoo-python 33 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 34 | #, python-format 35 | msgid "Length cannot be more than %s" 36 | msgstr "La llargada no pot ser més gran que %s" 37 | 38 | #. module: report_qweb_parameter 39 | #: model:ir.model,name:report_qweb_parameter.model_ir_qweb 40 | msgid "Qweb" 41 | msgstr "Qweb" 42 | -------------------------------------------------------------------------------- /report_qweb_parameter/i18n/es.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_qweb_parameter 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 12.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "POT-Creation-Date: \n" 10 | "PO-Revision-Date: \n" 11 | "Last-Translator: Carlos \n" 12 | "Language-Team: \n" 13 | "Language: es\n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 18 | "X-Generator: Poedit 2.0.6\n" 19 | 20 | #. module: report_qweb_parameter 21 | #: model:ir.actions.report,name:report_qweb_parameter.test_report_length_report_id 22 | msgid "Length Report" 23 | msgstr "Longitud del informe" 24 | 25 | #. module: report_qweb_parameter 26 | #. odoo-python 27 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 28 | #, python-format 29 | msgid "Length cannot be less than %s" 30 | msgstr "La longitud no puede ser menor a %s" 31 | 32 | #. module: report_qweb_parameter 33 | #. odoo-python 34 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 35 | #, python-format 36 | msgid "Length cannot be more than %s" 37 | msgstr "La longitud no puede ser mayor a %s" 38 | 39 | #. module: report_qweb_parameter 40 | #: model:ir.model,name:report_qweb_parameter.model_ir_qweb 41 | msgid "Qweb" 42 | msgstr "Qweb" 43 | -------------------------------------------------------------------------------- /report_qweb_parameter/i18n/fr.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_qweb_parameter 4 | # 5 | # Translators: 6 | # Nicolas JEUDY , 2018 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 11.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2018-01-05 17:53+0000\n" 12 | "PO-Revision-Date: 2018-01-05 17:53+0000\n" 13 | "Last-Translator: Nicolas JEUDY , 2018\n" 14 | "Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" 15 | "Language: fr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: \n" 19 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 20 | 21 | #. module: report_qweb_parameter 22 | #: model:ir.actions.report,name:report_qweb_parameter.test_report_length_report_id 23 | msgid "Length Report" 24 | msgstr "Longueur du rapport " 25 | 26 | #. module: report_qweb_parameter 27 | #. odoo-python 28 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 29 | #, python-format 30 | msgid "Length cannot be less than %s" 31 | msgstr "La longueur du rapport ne peut pas être inférieure à %s" 32 | 33 | #. module: report_qweb_parameter 34 | #. odoo-python 35 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 36 | #, python-format 37 | msgid "Length cannot be more than %s" 38 | msgstr "La longueur du rapport ne peut pas être supérieure à %s" 39 | 40 | #. module: report_qweb_parameter 41 | #: model:ir.model,name:report_qweb_parameter.model_ir_qweb 42 | msgid "Qweb" 43 | msgstr "" 44 | 45 | #~ msgid "ir.qweb" 46 | #~ msgstr "ir.qweb" 47 | -------------------------------------------------------------------------------- /report_qweb_parameter/i18n/it.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_qweb_parameter 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 13.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2020-11-20 23:36+0000\n" 10 | "Last-Translator: Alessandro Fiorino \n" 11 | "Language-Team: none\n" 12 | "Language: it\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 3.10\n" 18 | 19 | #. module: report_qweb_parameter 20 | #: model:ir.actions.report,name:report_qweb_parameter.test_report_length_report_id 21 | msgid "Length Report" 22 | msgstr "Lunghezza Report" 23 | 24 | #. module: report_qweb_parameter 25 | #. odoo-python 26 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 27 | #, python-format 28 | msgid "Length cannot be less than %s" 29 | msgstr "La lunghezza non può essere meno di %s" 30 | 31 | #. module: report_qweb_parameter 32 | #. odoo-python 33 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 34 | #, python-format 35 | msgid "Length cannot be more than %s" 36 | msgstr "La lunghezza non può essere più di %s" 37 | 38 | #. module: report_qweb_parameter 39 | #: model:ir.model,name:report_qweb_parameter.model_ir_qweb 40 | msgid "Qweb" 41 | msgstr "Qweb" 42 | -------------------------------------------------------------------------------- /report_qweb_parameter/i18n/pt.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_qweb_parameter 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 12.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2019-08-14 13:44+0000\n" 10 | "Last-Translator: Pedro Castro Silva \n" 11 | "Language-Team: none\n" 12 | "Language: pt\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n > 1;\n" 17 | "X-Generator: Weblate 3.7.1\n" 18 | 19 | #. module: report_qweb_parameter 20 | #: model:ir.actions.report,name:report_qweb_parameter.test_report_length_report_id 21 | msgid "Length Report" 22 | msgstr "Relatório de Comprimento" 23 | 24 | #. module: report_qweb_parameter 25 | #. odoo-python 26 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 27 | #, python-format 28 | msgid "Length cannot be less than %s" 29 | msgstr "Comprimento não pode ser superior a %s" 30 | 31 | #. module: report_qweb_parameter 32 | #. odoo-python 33 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 34 | #, python-format 35 | msgid "Length cannot be more than %s" 36 | msgstr "Comprimento não pode ser inferior a %s" 37 | 38 | #. module: report_qweb_parameter 39 | #: model:ir.model,name:report_qweb_parameter.model_ir_qweb 40 | msgid "Qweb" 41 | msgstr "" 42 | -------------------------------------------------------------------------------- /report_qweb_parameter/i18n/report_qweb_parameter.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_qweb_parameter 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 18.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "Last-Translator: \n" 10 | "Language-Team: \n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: \n" 14 | "Plural-Forms: \n" 15 | 16 | #. module: report_qweb_parameter 17 | #: model:ir.actions.report,name:report_qweb_parameter.test_report_length_report_id 18 | msgid "Length Report" 19 | msgstr "" 20 | 21 | #. module: report_qweb_parameter 22 | #. odoo-python 23 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 24 | msgid "Length cannot be less than %s" 25 | msgstr "" 26 | 27 | #. module: report_qweb_parameter 28 | #. odoo-python 29 | #: code:addons/report_qweb_parameter/models/ir_qweb.py:0 30 | msgid "Length cannot be more than %s" 31 | msgstr "" 32 | 33 | #. module: report_qweb_parameter 34 | #: model:ir.model,name:report_qweb_parameter.model_ir_qweb 35 | msgid "Qweb" 36 | msgstr "" 37 | -------------------------------------------------------------------------------- /report_qweb_parameter/models/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 2 | 3 | from . import ir_qweb 4 | -------------------------------------------------------------------------------- /report_qweb_parameter/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_qweb_parameter/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Enric Tobella \<\> 2 | 3 | - [Tecnativa](https://www.tecnativa.com): 4 | 5 | > - Carlos Roca 6 | 7 | - Iván Antón \<\> 8 | 9 | - [Sygel Technology](https://www.sygel.es): 10 | 11 | > - Valentin Vinagre 12 | -------------------------------------------------------------------------------- /report_qweb_parameter/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module allows you to add new parameters on QWeb reports. Currently, 2 | we have defined a field maximum on a report and a validation of maximal 3 | and minimal size. It is useful on xml reports in order to validate 4 | length. XML are sometimes XSD dependant and we must validate its format. 5 | For example, in spanish facturae 6 | (), where length and 7 | format must be validated in several fields in order to send an invoice. 8 | -------------------------------------------------------------------------------- /report_qweb_parameter/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | 1. Add a t-length attribute on report templates fields that will 2 | truncate the field 3 | 2. Add a t-minlength attribute on report template fields that will 4 | check the min length 5 | 3. Add a t-maxlength attribute on report template fields that will 6 | check the max length 7 | -------------------------------------------------------------------------------- /report_qweb_parameter/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_qweb_parameter/static/description/icon.png -------------------------------------------------------------------------------- /report_qweb_parameter/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 2 | 3 | from . import test_report_qweb_parameter 4 | -------------------------------------------------------------------------------- /report_qweb_parameter/tests/test_report_qweb_parameter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | 4 | import xml.etree.ElementTree as ET 5 | 6 | from odoo.tests import common 7 | 8 | from odoo.addons.base.models.ir_qweb import QWebException 9 | 10 | 11 | class TestReportQWebParameter(common.TransactionCase): 12 | def test_qweb_parameter(self): 13 | report_name = "report_qweb_parameter.test_report_length" 14 | report_obj = self.env["ir.actions.report"] 15 | report_object = report_obj 16 | docs = self.env["res.company"].create( 17 | { 18 | "name": "Test company", 19 | "street": "12345678901", 20 | "vat": "12345678901", 21 | "company_registry": "1234567890", 22 | } 23 | ) 24 | docs.website = "1234567890" # for avoding that Odoo adds http:// 25 | rep = report_object._render(report_name, docs.ids, False) 26 | root = ET.fromstring(rep[0]) 27 | 28 | # test length 29 | self.assertEqual(root[0].text, "1234567890") 30 | self.assertEqual(root[3].text, "1234567890") 31 | self.assertEqual(root[6].text, "1234567890") 32 | 33 | # test condicional length 34 | self.assertEqual(root[1].text, "Tes") 35 | self.assertEqual(root[4].text, "Test") 36 | self.assertEqual(root[7].text, "Test ") 37 | 38 | # test maxlength 39 | docs.update({"street": "123456789"}) 40 | with self.assertRaises(QWebException): 41 | report_object._render(report_name, docs.ids, False) 42 | docs.update({"street": "1234567890", "vat": "123456789"}) 43 | with self.assertRaises(QWebException): 44 | report_object._render(report_name, docs.ids, False) 45 | docs.update({"vat": "1234567890", "website": "12345678901"}) 46 | with self.assertRaises(QWebException): 47 | report_object._render(report_name, docs.ids, False) 48 | docs.update({"website": "1234567890", "company_registry": "12345678901"}) 49 | with self.assertRaises(QWebException): 50 | report_object._render(report_name, docs.ids, False) 51 | -------------------------------------------------------------------------------- /report_qweb_pdf_cover/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # Part of ForgeFlow. See LICENSE file for full copyright and licensing details. 3 | 4 | from . import models 5 | -------------------------------------------------------------------------------- /report_qweb_pdf_cover/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # Part of ForgeFlow. See LICENSE file for full copyright and licensing details. 3 | 4 | { 5 | "name": "Report QWeb PDF Cover", 6 | "summary": "Add front and back covers to your QWeb PDF reports", 7 | "author": "ForgeFlow, Odoo Community Association (OCA)", 8 | "website": "https://github.com/OCA/reporting-engine", 9 | "category": "Reporting", 10 | "version": "18.0.1.0.0", 11 | "license": "AGPL-3", 12 | "depends": ["web"], 13 | "data": ["views/ir_actions_views.xml"], 14 | "installable": True, 15 | "application": False, 16 | } 17 | -------------------------------------------------------------------------------- /report_qweb_pdf_cover/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 ForgeFlow S.L. (https://www.forgeflow.com) 2 | # Part of ForgeFlow. See LICENSE file for full copyright and licensing details. 3 | 4 | from . import ir_actions_report 5 | -------------------------------------------------------------------------------- /report_qweb_pdf_cover/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_qweb_pdf_cover/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Laura Cazorla \<\> 2 | -------------------------------------------------------------------------------- /report_qweb_pdf_cover/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module allows for front and back covers to be added to the 2 | generated PDF reports. They can be added as a separate page, at the 3 | beginning or the end of the report, but they can also overlap the first 4 | and last page of the actual report, respectively. 5 | -------------------------------------------------------------------------------- /report_qweb_pdf_cover/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | To add a cover to a report, you need to access to the report's 2 | configuration, more specifically to the Advanced Properties tab. There, 3 | you will find two checkboxes, one for the front cover and another for 4 | the back cover. They both work the same, so let's focus on the front 5 | cover with an example. 6 | 7 | - You must check the Use Front Cover checkbox to enable the front cover. 8 | You will see that a new checkbox and a PDF file widget appear. 9 | - If you want the front cover to overlap with the first page of the PDF 10 | report, you should also check the Overlap Front Cover checkbox. Leave 11 | it unchecked if you don't want the front cover to overlap with the 12 | first page. 13 | - The last step would be to upload the PDF file that will be used as the 14 | front cover. You can do this by clicking on the PDF file widget and 15 | selecting the file. 16 | - Important! The file must be a PDF file, and it should have only one 17 | page. If it has more pages, only the first one will be used. 18 | -------------------------------------------------------------------------------- /report_qweb_pdf_cover/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_qweb_pdf_cover/static/description/icon.png -------------------------------------------------------------------------------- /report_qweb_pdf_cover/views/ir_actions_views.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ir.actions.report 5 | 6 | 7 | 8 | 9 | 13 | 18 | 19 | 20 | 24 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/__init__.py: -------------------------------------------------------------------------------- 1 | # © 2016 Therp BV 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | 4 | from . import models 5 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/__manifest__.py: -------------------------------------------------------------------------------- 1 | # © 2016 Therp BV 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | { 4 | "name": "Pdf watermark", 5 | "version": "18.0.1.0.0", 6 | "author": "Therp BV, " "Odoo Community Association (OCA)", 7 | "license": "AGPL-3", 8 | "category": "Technical Settings", 9 | "development_status": "Production/Stable", 10 | "summary": "Add watermarks to your QWEB PDF reports", 11 | "website": "https://github.com/OCA/reporting-engine", 12 | "depends": ["web"], 13 | "data": [ 14 | "views/ir_actions_report_xml.xml", 15 | "views/res_company.xml", 16 | ], 17 | "assets": { 18 | "web.report_assets_pdf": [ 19 | "/report_qweb_pdf_watermark/static/src/css/report_qweb_pdf_watermark.css" 20 | ], 21 | }, 22 | "demo": ["demo/report.xml"], 23 | "installable": True, 24 | } 25 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/demo/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Watermark Demo report 5 | res.users 6 | qweb-pdf 7 | report_qweb_pdf_watermark.demo_report_view 8 | report_qweb_pdf_watermark.demo_report_view 9 | docs[:1].company_id.logo 10 | 11 | report 12 | 13 | 26 | 27 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/models/__init__.py: -------------------------------------------------------------------------------- 1 | # © 2016 Therp BV 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | 4 | from . import res_company 5 | from . import report 6 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/models/res_company.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 360 ERP () 2 | # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). 3 | 4 | from odoo import fields, models 5 | 6 | 7 | class ResCompany(models.Model): 8 | _inherit = "res.company" 9 | 10 | pdf_watermark = fields.Binary("Watermark") 11 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Holger Brunn \<\> 2 | - Stefan Rijnhart \<\> 3 | - Rod Schouteden \<\> 4 | - Robin Goots \<\> 5 | - Foram Shah \<\> 6 | - bosd \<\> 7 | - Sander Lienaerts \<\> 8 | - Anjeel Haria 9 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module was written to add watermarks (backgrounds) to PDF reports. 2 | Because of the way wkhtmltopdf handles headers and footers in the 3 | current versions, it is quite impossible to have a background for the 4 | complete page using HTML and CSS. That is why this module inserts the 5 | image at the PDF level. 6 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/readme/HISTORY.md: -------------------------------------------------------------------------------- 1 | ## 12.0.1.0.0 (2019-11-18) 2 | 3 | - \[MIG\] Migration to V12. 4 | 5 | ## 13.0.1.0.0 (2021-01-27) 6 | 7 | - \[MIG\] Migration to V13. 8 | 9 | ## 14.0.1.0.0 (2021-01-29) 10 | 11 | - \[MIG\] Migration to V14. 12 | 13 | ## 15.0.1.0.0 (2022-01-11) 14 | 15 | - \[MIG\] Migration to V15. 16 | - Define pdf watermark in company settings 17 | 18 | ## 16.0.1.0.0 (2023-03-13) 19 | 20 | - \[MIG\] Migration to V16. 21 | 22 | ## 17.0.1.0.0 (2024-01-12) 23 | 24 | - \[MIG\] Migration to V17. 25 | 26 | ## 18.0.1.0.0 (2025-01-06) 27 | 28 | - \[MIG\] Migration to V18. 29 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/readme/INSTALL.md: -------------------------------------------------------------------------------- 1 | As PyPDF is not supported in python3, you need to install PyPDF2: 2 | 3 | $ pip install pypdf2 4 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/readme/ROADMAP.md: -------------------------------------------------------------------------------- 1 | This module depends on support for transparent backgrounds in 2 | Wkhtmltopdf, which has been flaky in the past. This module has been 3 | reported to work with Wkhtmltopdf 0.12.6. 4 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | To use this module, you need to: 2 | 3 | 1. go to your report 4 | 2. select a PDF or image to use as watermark. Note that resolutions and 5 | size must match, otherwise you'll have funny results 6 | 3. You can also fill in an expression that returns the data (base64 7 | encoded) to be used as watermark 8 | 9 | To use the Company watermark, you need to: 10 | 11 | 1. go to settings --\> company --\> update info 12 | 2. upload an pdf watermark 13 | 3. go to settings --\> technical --\> reporting --\> reports 14 | 4. Select the report where you want to use it. 15 | 5. On the 'Advanced Properties' tab of the notebook check 'use company 16 | watermark' 17 | 18 | \### Demo And demo report is available (if you have demo data installed) 19 | on the users form view. 20 | 21 | 1. go to Configuration --\> users 22 | 2. Select an users 23 | 3. Click the print button --\> Watermark Demo report. 24 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_qweb_pdf_watermark/static/description/icon.png -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/static/src/css/report_qweb_pdf_watermark.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: transparent !important; 3 | } 4 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # © 2016 Therp BV 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 3 | 4 | from . import test_report_qweb_pdf_watermark 5 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/tests/test_report_qweb_pdf_watermark.py: -------------------------------------------------------------------------------- 1 | # © 2016 Therp BV 2 | # Copyright 2023 Onestein - Anjeel Haria 3 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 4 | from PIL import Image 5 | 6 | from odoo.tests.common import HttpCase 7 | 8 | 9 | class TestReportQwebPdfWatermark(HttpCase): 10 | def test_report_qweb_pdf_watermark(self): 11 | Image.init() 12 | # with our image, we have three 13 | self._test_report_images(3) 14 | 15 | self.env.ref("report_qweb_pdf_watermark.demo_report").write( 16 | {"pdf_watermark_expression": False} 17 | ) 18 | # without, we have two 19 | self._test_report_images(2) 20 | 21 | self.env.ref("report_qweb_pdf_watermark.demo_report").write( 22 | {"pdf_watermark": self.env.user.company_id.logo} 23 | ) 24 | # and now we should have three again 25 | self._test_report_images(3) 26 | 27 | # test use company watermark 28 | self.env.ref("report_qweb_pdf_watermark.demo_report").write( 29 | {"pdf_watermark": False} 30 | ) 31 | self.env.ref("report_qweb_pdf_watermark.demo_report").write( 32 | {"use_company_watermark": True} 33 | ) 34 | self.env.ref("base.main_company").write( 35 | {"pdf_watermark": self.env.user.company_id.logo} 36 | ) 37 | self._test_report_images(3) 38 | 39 | def _test_report_images(self, number): 40 | pdf, _ = ( 41 | self.env["ir.actions.report"] 42 | .with_context(force_report_rendering=True) 43 | ._render_qweb_pdf( 44 | "report_qweb_pdf_watermark.demo_report", 45 | self.env["res.users"].search([]).ids, 46 | ) 47 | ) 48 | self.assertEqual(pdf.count(b"/Subtype /Image"), number) 49 | 50 | def test_pdf_has_usable_pages(self): 51 | # test 0 52 | numpages = 0 53 | # pdf_has_usable_pages(self, pdf_watermark) 54 | with self.assertLogs(level="ERROR"): 55 | self.assertFalse( 56 | self.env["ir.actions.report"].pdf_has_usable_pages(numpages) 57 | ) 58 | # test 1 59 | numpages = 1 60 | self.assertTrue(self.env["ir.actions.report"].pdf_has_usable_pages(numpages)) 61 | # test 2 62 | numpages = 2 63 | self.assertTrue(self.env["ir.actions.report"].pdf_has_usable_pages(numpages)) 64 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/views/ir_actions_report_xml.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ir.actions.report 5 | 6 | 7 | 8 | 12 | 17 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /report_qweb_pdf_watermark/views/res_company.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | res.company 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Avoin.Systems 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | 4 | from . import models 5 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Avoin.Systems 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | 4 | # noinspection PyStatementEffect 5 | { 6 | "name": "Report Wkhtmltopdf Param", 7 | "version": "18.0.1.0.0", 8 | "license": "AGPL-3", 9 | "summary": """ 10 | Add new parameters for a paper format to be used by wkhtmltopdf 11 | command as arguments. 12 | """, 13 | "author": "Avoin.Systems, Eficent, Odoo Community Association (OCA)", 14 | "website": "https://github.com/OCA/reporting-engine", 15 | "category": "Technical Settings", 16 | "depends": ["web"], 17 | "data": ["security/ir.model.access.csv", "views/paperformat.xml"], 18 | "installable": True, 19 | "auto_install": False, 20 | "application": False, 21 | } 22 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/models/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Avoin.Systems 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | 4 | from . import report_paperformat_parameter 5 | from . import report_paperformat 6 | from . import report 7 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/models/report.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Avoin.Systems 2 | # Copyright 2017 Eficent Business and IT Consulting Services, S.L. 3 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 4 | 5 | from odoo import api, models 6 | 7 | 8 | class IrActionsReport(models.Model): 9 | _inherit = "ir.actions.report" 10 | 11 | @api.model 12 | def _build_wkhtmltopdf_args( 13 | self, 14 | paperformat_id, 15 | landscape, 16 | specific_paperformat_args=None, 17 | set_viewport_size=False, 18 | ): 19 | # noinspection PyUnresolvedReferences,PyProtectedMember 20 | command_args = super()._build_wkhtmltopdf_args( 21 | paperformat_id, landscape, specific_paperformat_args, set_viewport_size 22 | ) 23 | 24 | for param in paperformat_id.custom_params: 25 | command_args.extend([param.name]) 26 | if param.value: 27 | command_args.extend([param.value]) 28 | 29 | return command_args 30 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/models/report_paperformat.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Avoin.Systems 2 | # Copyright 2017 Eficent Business and IT Consulting Services, S.L. 3 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 4 | 5 | import logging 6 | 7 | from odoo import api, fields, models 8 | from odoo.exceptions import ValidationError 9 | 10 | _logger = logging.getLogger(__name__) 11 | 12 | 13 | class Paper(models.Model): 14 | _inherit = "report.paperformat" 15 | 16 | custom_params = fields.One2many( 17 | "report.paperformat.parameter", 18 | "paperformat_id", 19 | "Custom Parameters", 20 | help="Custom Parameters passed forward as wkhtmltopdf command arguments", 21 | ) 22 | 23 | @api.constrains("custom_params") 24 | def _check_recursion_custom_params(self): 25 | for paperformat in self: 26 | sample_html = """ 27 | 28 | 29 | 30 |
31 | Hello World! 32 |
33 | 34 | 35 | """ 36 | report = self.env["ir.actions.report"].new( 37 | {"paperformat_id": paperformat.id} 38 | ) 39 | content = report._run_wkhtmltopdf([sample_html]) 40 | if not content: 41 | raise ValidationError( 42 | self.env._("Failed to create a PDF using the provided parameters.") 43 | ) 44 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/models/report_paperformat_parameter.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Avoin.Systems 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 3 | 4 | from odoo import fields, models 5 | 6 | 7 | class ReportPaperformatParameter(models.Model): 8 | _name = "report.paperformat.parameter" 9 | _description = "wkhtmltopdf parameters" 10 | 11 | paperformat_id = fields.Many2one( 12 | "report.paperformat", 13 | "Paper Format", 14 | required=True, 15 | ) 16 | 17 | name = fields.Char( 18 | required=True, 19 | help="The command argument name. Remember to add prefix -- or -", 20 | ) 21 | 22 | value = fields.Char() 23 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Miku Laitinen \<\> 2 | - Jordi Ballester \<\> 3 | - Saran Lim. \<\> 4 | - Foram Shah \<\> 5 | - [Trobz](https://www.trobz.com): 6 | - Tris Doan \<\> 7 | - Nhan Tran \<\> 8 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/readme/CREDITS.md: -------------------------------------------------------------------------------- 1 | The migration of this module from 16.0 to 17.0 was financially supported 2 | by Camptocamp -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module allows you to add new parameters for a paper format which 2 | are then forwarded to wkhtmltopdf command as arguments. To display the 3 | arguments that wkhtmltopdf accepts go to your command line and type 4 | 'wkhtmltopdf -H'. 5 | 6 | A commonly used parameter in Odoo is *--disable-smart-shrinking*, that 7 | will disable the automatic resizing of the PDF when converting. This is 8 | important when you intend to have a layout that conforms to certain 9 | alignment. It is very common whenever you need to conform the PDF to a 10 | predefined layoyut (e.g. checks, official forms,...). 11 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | 1. Go to *Settings* and press 'Activate the developer mode (with 2 | assets)' 3 | 2. Go to *Settings - Technical - Reports - Paper Format* 4 | 3. Add additional parameters indicating the command argument name 5 | (remember to add prefix -- or -) and value. 6 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" 2 | "paperformat_parameter_access_portal","ir_actions_report_paperformat_parameter group_portal","model_report_paperformat_parameter","base.group_portal",1,0,0,0 3 | "paperformat_parameter_access_employee","ir_actions_report_paperformat_parameter group_hr_user","model_report_paperformat_parameter",base.group_user,1,0,1,0 4 | "paperformat_parameter_access_administration","ir_actions_report_paperformat_parameter group_system","model_report_paperformat_parameter","base.group_system",1,1,1,1 5 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_wkhtmltopdf_param/static/description/icon.png -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Avoin.Systems 2 | # Copyright 2017 Eficent Business and IT Consulting Services, S.L. 3 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 4 | 5 | from . import test_report_paperformat 6 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/tests/test_report_paperformat.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Avoin.Systems 2 | # Copyright 2017 Eficent Business and IT Consulting Services, S.L. 3 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). 4 | 5 | import logging 6 | 7 | import odoo.tests 8 | from odoo.exceptions import ValidationError 9 | from odoo.tests.common import tagged 10 | 11 | 12 | @tagged("post_install", "-at_install") 13 | class TestWkhtmltopdf(odoo.tests.TransactionCase): 14 | def test_wkhtmltopdf_incorrect_parameter(self): 15 | for report_paperformat in self.env["report.paperformat"].search([]): 16 | with ( 17 | self.assertRaises(ValidationError), 18 | self.assertLogs(level=logging.WARNING), 19 | ): 20 | report_paperformat.update( 21 | {"custom_params": [(0, 0, {"name": "bad-parameter"})]} 22 | ) 23 | 24 | def test_wkhtmltopdf_valid_parameter(self): 25 | for report_paperformat in self.env["report.paperformat"].search([]): 26 | error = False 27 | try: 28 | report_paperformat.update( 29 | {"custom_params": [(0, 0, {"name": "--disable-smart-shrinking"})]} 30 | ) 31 | except ValidationError: 32 | error = True 33 | self.assertEqual( 34 | error, 35 | False, 36 | "There was an error adding wkhtmltopdf " 37 | "parameter --disable-smart-shrinking", 38 | ) 39 | -------------------------------------------------------------------------------- /report_wkhtmltopdf_param/views/paperformat.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | paperformat with custom parameters 6 | report.paperformat 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /report_xlsx/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). 2 | 3 | from . import controllers 4 | from . import models 5 | from . import report 6 | -------------------------------------------------------------------------------- /report_xlsx/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 ACSONE SA/NV () 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). 3 | { 4 | "name": "Base report xlsx", 5 | "summary": "Base module to create xlsx report", 6 | "author": "ACSONE SA/NV," "Creu Blanca," "Odoo Community Association (OCA)", 7 | "website": "https://github.com/OCA/reporting-engine", 8 | "category": "Reporting", 9 | "version": "18.0.1.0.0", 10 | "development_status": "Mature", 11 | "license": "AGPL-3", 12 | "external_dependencies": {"python": ["xlsxwriter", "xlrd"]}, 13 | "depends": ["base", "web"], 14 | "demo": ["demo/report.xml"], 15 | "installable": True, 16 | "assets": { 17 | "web.assets_backend": [ 18 | "report_xlsx/static/src/js/report/action_manager_report.esm.js", 19 | ], 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /report_xlsx/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import main 2 | -------------------------------------------------------------------------------- /report_xlsx/demo/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | Print to XLSX 9 | res.partner 10 | xlsx 11 | report_xlsx.partner_xlsx 12 | res_partner 13 | 14 | 15 | -------------------------------------------------------------------------------- /report_xlsx/i18n/ca.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 15.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "PO-Revision-Date: 2022-04-22 13:05+0000\n" 10 | "Last-Translator: pablontura \n" 11 | "Language-Team: none\n" 12 | "Language: ca\n" 13 | "MIME-Version: 1.0\n" 14 | "Content-Type: text/plain; charset=UTF-8\n" 15 | "Content-Transfer-Encoding: \n" 16 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 17 | "X-Generator: Weblate 4.3.2\n" 18 | 19 | #. module: report_xlsx 20 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 21 | msgid "Abstract XLSX Report" 22 | msgstr "Informe XLSX abstracte" 23 | 24 | #. module: report_xlsx 25 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 26 | msgid "Partner XLSX Report" 27 | msgstr "Informe XLSX del soci" 28 | 29 | #. module: report_xlsx 30 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 31 | msgid "Print to XLSX" 32 | msgstr "Imprimeix a XLSX" 33 | 34 | #. module: report_xlsx 35 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 36 | msgid "Report Action" 37 | msgstr "Informe d'acció" 38 | 39 | #. module: report_xlsx 40 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 41 | msgid "Report Type" 42 | msgstr "Tipus d'informe" 43 | 44 | #. module: report_xlsx 45 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 46 | msgid "" 47 | "The type of the report that will be rendered, each one having its own " 48 | "rendering method. HTML means the report will be opened directly in your " 49 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 50 | "downloaded by the user." 51 | msgstr "" 52 | "El tipus d'informe que es renderà, cadascun amb el seu propi mètode de " 53 | "representació. HTML significa que l'informe s'obrirà directament al vostre " 54 | "navegador, PDF significa que l'informe es representarà amb Wkhtmltopdf i " 55 | "l'usuari el baixarà." 56 | 57 | #. module: report_xlsx 58 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 59 | msgid "XLSX" 60 | msgstr "XLSX" 61 | 62 | #, python-format 63 | #~ msgid "%s model was not found" 64 | #~ msgstr "No s'ha trobat el model %s" 65 | -------------------------------------------------------------------------------- /report_xlsx/i18n/fr.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | # Translators: 6 | # Nicolas JEUDY , 2018 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 11.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2018-01-05 17:53+0000\n" 12 | "PO-Revision-Date: 2018-01-05 17:53+0000\n" 13 | "Last-Translator: Nicolas JEUDY , 2018\n" 14 | "Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" 15 | "Language: fr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: \n" 19 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 20 | 21 | #. module: report_xlsx 22 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 23 | msgid "Abstract XLSX Report" 24 | msgstr "" 25 | 26 | #. module: report_xlsx 27 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 28 | msgid "Partner XLSX Report" 29 | msgstr "" 30 | 31 | #. module: report_xlsx 32 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 33 | msgid "Print to XLSX" 34 | msgstr "Imprimer en XLSX" 35 | 36 | #. module: report_xlsx 37 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 38 | msgid "Report Action" 39 | msgstr "" 40 | 41 | #. module: report_xlsx 42 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 43 | msgid "Report Type" 44 | msgstr "" 45 | 46 | #. module: report_xlsx 47 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 48 | msgid "" 49 | "The type of the report that will be rendered, each one having its own " 50 | "rendering method. HTML means the report will be opened directly in your " 51 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 52 | "downloaded by the user." 53 | msgstr "" 54 | 55 | #. module: report_xlsx 56 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 57 | msgid "XLSX" 58 | msgstr "" 59 | 60 | #, python-format 61 | #~ msgid "%s model was not found" 62 | #~ msgstr "model '%s' n'a pas été trouvé" 63 | 64 | #~ msgid "Display Name" 65 | #~ msgstr "Nom" 66 | 67 | #~ msgid "ID" 68 | #~ msgstr "ID" 69 | 70 | #~ msgid "Last Modified on" 71 | #~ msgstr "Dernière modification le" 72 | 73 | #~ msgid "report.report_xlsx.partner_xlsx" 74 | #~ msgstr "report.report_xlsx.partner_xlsx" 75 | 76 | #~ msgid "ir.actions.report" 77 | #~ msgstr "ir.actions.report" 78 | 79 | #~ msgid "report.report_xlsx.abstract" 80 | #~ msgstr "report.report_xlsx.abstract" 81 | -------------------------------------------------------------------------------- /report_xlsx/i18n/hr.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | # Translators: 6 | # OCA Transbot , 2017 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 10.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2017-05-31 03:52+0000\n" 12 | "PO-Revision-Date: 2023-01-04 03:24+0000\n" 13 | "Last-Translator: Bole \n" 14 | "Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n" 15 | "Language: hr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: \n" 19 | "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " 20 | "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" 21 | "X-Generator: Weblate 4.14.1\n" 22 | 23 | #. module: report_xlsx 24 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 25 | msgid "Abstract XLSX Report" 26 | msgstr "" 27 | 28 | #. module: report_xlsx 29 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 30 | msgid "Partner XLSX Report" 31 | msgstr "" 32 | 33 | #. module: report_xlsx 34 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 35 | msgid "Print to XLSX" 36 | msgstr "" 37 | 38 | #. module: report_xlsx 39 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 40 | msgid "Report Action" 41 | msgstr "" 42 | 43 | #. module: report_xlsx 44 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 45 | msgid "Report Type" 46 | msgstr "" 47 | 48 | #. module: report_xlsx 49 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 50 | msgid "" 51 | "The type of the report that will be rendered, each one having its own " 52 | "rendering method. HTML means the report will be opened directly in your " 53 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 54 | "downloaded by the user." 55 | msgstr "" 56 | 57 | #. module: report_xlsx 58 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 59 | msgid "XLSX" 60 | msgstr "" 61 | 62 | #, python-format 63 | #~ msgid "%s model was not found" 64 | #~ msgstr "%s model nije pronađen" 65 | 66 | #, python-format 67 | #~ msgid "" 68 | #~ "A popup window with your report was blocked. You may need to change your " 69 | #~ "browser settings to allow popup windows for this page." 70 | #~ msgstr "" 71 | #~ "Skočni prozor sa vašim izvještajem je blokiran. Možda trebate promijeniti " 72 | #~ "postavke pretraživača da dozvolite skočne prozore za ovu stranicu." 73 | 74 | #~ msgid "Display Name" 75 | #~ msgstr "Naziv za prikaz" 76 | 77 | #, fuzzy 78 | #~ msgid "ir.actions.report" 79 | #~ msgstr "ir.actions.report.xml" 80 | -------------------------------------------------------------------------------- /report_xlsx/i18n/hr_HR.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | # Translators: 6 | # Bole , 2016 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 10.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2016-11-01 20:11+0000\n" 12 | "PO-Revision-Date: 2016-11-01 20:11+0000\n" 13 | "Last-Translator: Bole , 2016\n" 14 | "Language-Team: Croatian (Croatia) (https://www.transifex.com/oca/teams/23907/" 15 | "hr_HR/)\n" 16 | "Language: hr_HR\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: \n" 20 | "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " 21 | "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" 22 | 23 | #. module: report_xlsx 24 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 25 | msgid "Abstract XLSX Report" 26 | msgstr "" 27 | 28 | #. module: report_xlsx 29 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 30 | msgid "Partner XLSX Report" 31 | msgstr "" 32 | 33 | #. module: report_xlsx 34 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 35 | msgid "Print to XLSX" 36 | msgstr "" 37 | 38 | #. module: report_xlsx 39 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 40 | msgid "Report Action" 41 | msgstr "" 42 | 43 | #. module: report_xlsx 44 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 45 | msgid "Report Type" 46 | msgstr "" 47 | 48 | #. module: report_xlsx 49 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 50 | msgid "" 51 | "The type of the report that will be rendered, each one having its own " 52 | "rendering method. HTML means the report will be opened directly in your " 53 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 54 | "downloaded by the user." 55 | msgstr "" 56 | 57 | #. module: report_xlsx 58 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 59 | msgid "XLSX" 60 | msgstr "" 61 | 62 | #, fuzzy 63 | #~ msgid "ir.actions.report" 64 | #~ msgstr "ir.actions.report.xml" 65 | -------------------------------------------------------------------------------- /report_xlsx/i18n/it.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | # Translators: 6 | # OCA Transbot , 2017 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 10.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2017-05-31 03:52+0000\n" 12 | "PO-Revision-Date: 2024-02-12 10:46+0000\n" 13 | "Last-Translator: mymage \n" 14 | "Language-Team: Italian (https://www.transifex.com/oca/teams/23907/it/)\n" 15 | "Language: it\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: \n" 19 | "Plural-Forms: nplurals=2; plural=n != 1;\n" 20 | "X-Generator: Weblate 4.17\n" 21 | 22 | #. module: report_xlsx 23 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 24 | msgid "Abstract XLSX Report" 25 | msgstr "Report XLSX astratto" 26 | 27 | #. module: report_xlsx 28 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 29 | msgid "Partner XLSX Report" 30 | msgstr "Resoconto XLSX partner" 31 | 32 | #. module: report_xlsx 33 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 34 | msgid "Print to XLSX" 35 | msgstr "Stampa su XLSX" 36 | 37 | #. module: report_xlsx 38 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 39 | msgid "Report Action" 40 | msgstr "Azione resoconto" 41 | 42 | #. module: report_xlsx 43 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 44 | msgid "Report Type" 45 | msgstr "Tipo resoconto" 46 | 47 | #. module: report_xlsx 48 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 49 | msgid "" 50 | "The type of the report that will be rendered, each one having its own " 51 | "rendering method. HTML means the report will be opened directly in your " 52 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 53 | "downloaded by the user." 54 | msgstr "" 55 | "Il tipo di resoconto che verrà generato, ognuno avente il suo metodo di " 56 | "generazione. HTML vuol dire che il resoconto sarà aperto direttamente nel " 57 | "tuo browser mentre PDF vuol dire che il resoconto sarà generato usando " 58 | "Wkhtmltopdf e scaricato dall'utente." 59 | 60 | #. module: report_xlsx 61 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 62 | msgid "XLSX" 63 | msgstr "XLSX" 64 | 65 | #, fuzzy 66 | #~ msgid "ir.actions.report" 67 | #~ msgstr "ir.actions.report.xml" 68 | -------------------------------------------------------------------------------- /report_xlsx/i18n/nl_NL.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | # Translators: 6 | # Peter Hageman , 2017 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 10.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2017-06-23 00:28+0000\n" 12 | "PO-Revision-Date: 2017-06-23 00:28+0000\n" 13 | "Last-Translator: Peter Hageman , 2017\n" 14 | "Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/" 15 | "teams/23907/nl_NL/)\n" 16 | "Language: nl_NL\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: \n" 20 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 21 | 22 | #. module: report_xlsx 23 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 24 | msgid "Abstract XLSX Report" 25 | msgstr "" 26 | 27 | #. module: report_xlsx 28 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 29 | msgid "Partner XLSX Report" 30 | msgstr "" 31 | 32 | #. module: report_xlsx 33 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 34 | msgid "Print to XLSX" 35 | msgstr "" 36 | 37 | #. module: report_xlsx 38 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 39 | msgid "Report Action" 40 | msgstr "" 41 | 42 | #. module: report_xlsx 43 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 44 | msgid "Report Type" 45 | msgstr "" 46 | 47 | #. module: report_xlsx 48 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 49 | msgid "" 50 | "The type of the report that will be rendered, each one having its own " 51 | "rendering method. HTML means the report will be opened directly in your " 52 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 53 | "downloaded by the user." 54 | msgstr "" 55 | 56 | #. module: report_xlsx 57 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 58 | msgid "XLSX" 59 | msgstr "" 60 | 61 | #, fuzzy 62 | #~ msgid "ir.actions.report" 63 | #~ msgstr "ir.actions.report.xml" 64 | -------------------------------------------------------------------------------- /report_xlsx/i18n/pt_PT.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | # Translators: 6 | # OCA Transbot , 2017 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 10.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2017-05-31 03:52+0000\n" 12 | "PO-Revision-Date: 2017-05-31 03:52+0000\n" 13 | "Last-Translator: OCA Transbot , 2017\n" 14 | "Language-Team: Portuguese (Portugal) (https://www.transifex.com/oca/" 15 | "teams/23907/pt_PT/)\n" 16 | "Language: pt_PT\n" 17 | "MIME-Version: 1.0\n" 18 | "Content-Type: text/plain; charset=UTF-8\n" 19 | "Content-Transfer-Encoding: \n" 20 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 21 | 22 | #. module: report_xlsx 23 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 24 | msgid "Abstract XLSX Report" 25 | msgstr "" 26 | 27 | #. module: report_xlsx 28 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 29 | msgid "Partner XLSX Report" 30 | msgstr "" 31 | 32 | #. module: report_xlsx 33 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 34 | msgid "Print to XLSX" 35 | msgstr "" 36 | 37 | #. module: report_xlsx 38 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 39 | msgid "Report Action" 40 | msgstr "" 41 | 42 | #. module: report_xlsx 43 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 44 | msgid "Report Type" 45 | msgstr "" 46 | 47 | #. module: report_xlsx 48 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 49 | msgid "" 50 | "The type of the report that will be rendered, each one having its own " 51 | "rendering method. HTML means the report will be opened directly in your " 52 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 53 | "downloaded by the user." 54 | msgstr "" 55 | 56 | #. module: report_xlsx 57 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 58 | msgid "XLSX" 59 | msgstr "" 60 | 61 | #, fuzzy 62 | #~ msgid "ir.actions.report" 63 | #~ msgstr "ir.actions.report.xml" 64 | -------------------------------------------------------------------------------- /report_xlsx/i18n/report_xlsx.pot: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | msgid "" 6 | msgstr "" 7 | "Project-Id-Version: Odoo Server 18.0\n" 8 | "Report-Msgid-Bugs-To: \n" 9 | "Last-Translator: \n" 10 | "Language-Team: \n" 11 | "MIME-Version: 1.0\n" 12 | "Content-Type: text/plain; charset=UTF-8\n" 13 | "Content-Transfer-Encoding: \n" 14 | "Plural-Forms: \n" 15 | 16 | #. module: report_xlsx 17 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 18 | msgid "Abstract XLSX Report" 19 | msgstr "" 20 | 21 | #. module: report_xlsx 22 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 23 | msgid "Partner XLSX Report" 24 | msgstr "" 25 | 26 | #. module: report_xlsx 27 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 28 | msgid "Print to XLSX" 29 | msgstr "" 30 | 31 | #. module: report_xlsx 32 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 33 | msgid "Report Action" 34 | msgstr "" 35 | 36 | #. module: report_xlsx 37 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 38 | msgid "Report Type" 39 | msgstr "" 40 | 41 | #. module: report_xlsx 42 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 43 | msgid "" 44 | "The type of the report that will be rendered, each one having its own " 45 | "rendering method. HTML means the report will be opened directly in your " 46 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 47 | "downloaded by the user." 48 | msgstr "" 49 | 50 | #. module: report_xlsx 51 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 52 | msgid "XLSX" 53 | msgstr "" 54 | -------------------------------------------------------------------------------- /report_xlsx/i18n/tr.po: -------------------------------------------------------------------------------- 1 | # Translation of Odoo Server. 2 | # This file contains the translation of the following modules: 3 | # * report_xlsx 4 | # 5 | # Translators: 6 | # OCA Transbot , 2017 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: Odoo Server 10.0\n" 10 | "Report-Msgid-Bugs-To: \n" 11 | "POT-Creation-Date: 2017-05-31 03:52+0000\n" 12 | "PO-Revision-Date: 2017-05-31 03:52+0000\n" 13 | "Last-Translator: OCA Transbot , 2017\n" 14 | "Language-Team: Turkish (https://www.transifex.com/oca/teams/23907/tr/)\n" 15 | "Language: tr\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: \n" 19 | "Plural-Forms: nplurals=2; plural=(n > 1);\n" 20 | 21 | #. module: report_xlsx 22 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_abstract 23 | msgid "Abstract XLSX Report" 24 | msgstr "" 25 | 26 | #. module: report_xlsx 27 | #: model:ir.model,name:report_xlsx.model_report_report_xlsx_partner_xlsx 28 | msgid "Partner XLSX Report" 29 | msgstr "" 30 | 31 | #. module: report_xlsx 32 | #: model:ir.actions.report,name:report_xlsx.partner_xlsx 33 | msgid "Print to XLSX" 34 | msgstr "" 35 | 36 | #. module: report_xlsx 37 | #: model:ir.model,name:report_xlsx.model_ir_actions_report 38 | msgid "Report Action" 39 | msgstr "" 40 | 41 | #. module: report_xlsx 42 | #: model:ir.model.fields,field_description:report_xlsx.field_ir_actions_report__report_type 43 | msgid "Report Type" 44 | msgstr "" 45 | 46 | #. module: report_xlsx 47 | #: model:ir.model.fields,help:report_xlsx.field_ir_actions_report__report_type 48 | msgid "" 49 | "The type of the report that will be rendered, each one having its own " 50 | "rendering method. HTML means the report will be opened directly in your " 51 | "browser PDF means the report will be rendered using Wkhtmltopdf and " 52 | "downloaded by the user." 53 | msgstr "" 54 | 55 | #. module: report_xlsx 56 | #: model:ir.model.fields.selection,name:report_xlsx.selection__ir_actions_report__report_type__xlsx 57 | msgid "XLSX" 58 | msgstr "" 59 | 60 | #, fuzzy 61 | #~ msgid "ir.actions.report" 62 | #~ msgstr "ir.actions.report.xml" 63 | -------------------------------------------------------------------------------- /report_xlsx/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import ir_report 2 | -------------------------------------------------------------------------------- /report_xlsx/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_xlsx/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Adrien Peiffer \<\> 2 | - Sébastien Alix \<\> 3 | - Stéphane Bidoul \<\> 4 | - Enric Tobella \<\> 5 | - Graeme Gellatly \<\> 6 | - Cristian Salamea \<\> 7 | - Rod Schouteden \<\> 8 | - Eugene Molotov \<\> 9 | - Christopher Ormaza \<\> 10 | - Houzéfa Abbasbhay \<\> 11 | - Le Dinh Tien \<\> 12 | -------------------------------------------------------------------------------- /report_xlsx/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module provides a basic report class to generate xlsx report. 2 | -------------------------------------------------------------------------------- /report_xlsx/readme/INSTALL.md: -------------------------------------------------------------------------------- 1 | Make sure you have `xlsxwriter` Python module installed: 2 | 3 | $ pip3 install xlsxwriter 4 | 5 | For testing it is also necessary `xlrd` Python module installed: 6 | 7 | $ pip3 install xlrd 8 | -------------------------------------------------------------------------------- /report_xlsx/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | An example of XLSX report for partners on a module called 2 | \`module_name\`: 3 | 4 | A python class : 5 | 6 | from odoo import models 7 | 8 | class PartnerXlsx(models.AbstractModel): 9 | _name = 'report.module_name.report_name' 10 | _inherit = 'report.report_xlsx.abstract' 11 | 12 | def generate_xlsx_report(self, workbook, data, partners): 13 | for obj in partners: 14 | report_name = obj.name 15 | # One sheet by partner 16 | sheet = workbook.add_worksheet(report_name[:31]) 17 | bold = workbook.add_format({'bold': True}) 18 | sheet.write(0, 0, obj.name, bold) 19 | 20 | To manipulate the `workbook` and `sheet` objects, refer to the 21 | [documentation](http://xlsxwriter.readthedocs.org/) of `xlsxwriter`. 22 | 23 | A report XML record : 24 | 25 | 26 | Print to XLSX 27 | res.partner 28 | xlsx 29 | module_name.report_name 30 | module_name.report_file 31 | 32 | report 33 | 34 | 35 | -------------------------------------------------------------------------------- /report_xlsx/report/__init__.py: -------------------------------------------------------------------------------- 1 | from . import report_abstract_xlsx 2 | from . import report_partner_xlsx 3 | -------------------------------------------------------------------------------- /report_xlsx/report/report_partner_xlsx.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). 3 | 4 | from odoo import models 5 | 6 | 7 | class PartnerXlsx(models.AbstractModel): 8 | _name = "report.report_xlsx.partner_xlsx" 9 | _inherit = "report.report_xlsx.abstract" 10 | _description = "Partner XLSX Report" 11 | 12 | def generate_xlsx_report(self, workbook, data, partners): 13 | sheet = workbook.add_worksheet("Report") 14 | for i, obj in enumerate(partners): 15 | bold = workbook.add_format({"bold": True}) 16 | sheet.write(i, 0, obj.name, bold) 17 | -------------------------------------------------------------------------------- /report_xlsx/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_xlsx/static/description/icon.png -------------------------------------------------------------------------------- /report_xlsx/static/src/js/report/action_manager_report.esm.js: -------------------------------------------------------------------------------- 1 | import {download} from "@web/core/network/download"; 2 | import {registry} from "@web/core/registry"; 3 | import {user} from "@web/core/user"; 4 | 5 | registry 6 | .category("ir.actions.report handlers") 7 | .add("xlsx_handler", async function (action, options, env) { 8 | if (action.report_type === "xlsx") { 9 | const type = action.report_type; 10 | let url = `/report/${type}/${action.report_name}`; 11 | const actionContext = action.context || {}; 12 | if (action.data && JSON.stringify(action.data) !== "{}") { 13 | // Build a query string with `action.data` (it's the place where reports 14 | // using a wizard to customize the output traditionally put their options) 15 | const action_options = encodeURIComponent(JSON.stringify(action.data)); 16 | const context = encodeURIComponent(JSON.stringify(actionContext)); 17 | url += `?options=${action_options}&context=${context}`; 18 | } else { 19 | if (actionContext.active_ids) { 20 | url += `/${actionContext.active_ids.join(",")}`; 21 | } 22 | if (type === "xlsx") { 23 | const context = encodeURIComponent(JSON.stringify(user.context)); 24 | url += `?context=${context}`; 25 | } 26 | } 27 | env.services.ui.block(); 28 | try { 29 | await download({ 30 | url: "/report/download", 31 | data: { 32 | data: JSON.stringify([url, action.report_type]), 33 | context: JSON.stringify(user.context), 34 | }, 35 | }); 36 | } finally { 37 | env.services.ui.unblock(); 38 | } 39 | const onClose = options.onClose; 40 | if (action.close_on_report_download) { 41 | return env.services.action.doAction( 42 | {type: "ir.actions.act_window_close"}, 43 | {onClose} 44 | ); 45 | } else if (onClose) { 46 | onClose(); 47 | } 48 | return Promise.resolve(true); 49 | } 50 | return Promise.resolve(false); 51 | }); 52 | -------------------------------------------------------------------------------- /report_xlsx/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_report 2 | -------------------------------------------------------------------------------- /report_xlsx_helper/__init__.py: -------------------------------------------------------------------------------- 1 | from . import controllers 2 | from . import models 3 | from . import report 4 | -------------------------------------------------------------------------------- /report_xlsx_helper/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009-2019 Noviat. 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | 4 | { 5 | "name": "Report xlsx helpers", 6 | "author": "Noviat, Odoo Community Association (OCA)", 7 | "website": "https://github.com/OCA/reporting-engine", 8 | "category": "Reporting", 9 | "version": "18.0.1.0.0", 10 | "license": "AGPL-3", 11 | "depends": ["report_xlsx"], 12 | "development_status": "Mature", 13 | "installable": True, 14 | } 15 | -------------------------------------------------------------------------------- /report_xlsx_helper/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from . import main 2 | -------------------------------------------------------------------------------- /report_xlsx_helper/controllers/main.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009-2018 Noviat. 2 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 3 | 4 | import json 5 | 6 | from odoo.http import content_disposition, request, route 7 | 8 | from odoo.addons.report_xlsx.controllers.main import ReportController 9 | 10 | 11 | class ReportController(ReportController): 12 | @route( 13 | [ 14 | "/report//", 15 | "/report///", 16 | ], 17 | type="http", 18 | auth="user", 19 | website=True, 20 | ) 21 | def report_routes(self, reportname, docids=None, converter=None, **data): 22 | report = request.env["ir.actions.report"]._get_report_from_name(reportname) 23 | if converter == "xlsx" and not report: 24 | context = dict(request.env.context) 25 | if docids: 26 | docids = [int(i) for i in docids.split(",")] 27 | if data.get("options"): 28 | data.update(json.loads(data.pop("options"))) 29 | if data.get("context"): 30 | data["context"] = json.loads(data["context"]) 31 | context.update(data["context"]) 32 | context["report_name"] = reportname 33 | 34 | xlsx = report.with_context(**context)._render_xlsx( 35 | reportname, docids, data=data 36 | )[0] 37 | report_file = context.get("report_file") 38 | if not report_file: 39 | active_model = context.get("active_model", "export") 40 | report_file = active_model.replace(".", "_") 41 | xlsxhttpheaders = [ 42 | ( 43 | "Content-Type", 44 | "application/vnd.openxmlformats-" 45 | "officedocument.spreadsheetml.sheet", 46 | ), 47 | ("Content-Length", len(xlsx)), 48 | ("Content-Disposition", content_disposition(report_file + ".xlsx")), 49 | ] 50 | return request.make_response(xlsx, headers=xlsxhttpheaders) 51 | return super().report_routes(reportname, docids, converter, **data) 52 | -------------------------------------------------------------------------------- /report_xlsx_helper/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import ir_actions_report 2 | -------------------------------------------------------------------------------- /report_xlsx_helper/models/ir_actions_report.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009-2018 Noviat. 2 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 3 | 4 | from odoo import _, api, models 5 | from odoo.exceptions import UserError 6 | 7 | 8 | class IrActionsReport(models.Model): 9 | _inherit = "ir.actions.report" 10 | 11 | @api.model 12 | def _render_xlsx(self, report_ref, docids, data): 13 | if not self and self.env.context.get("report_name"): 14 | report_model_name = "report.{}".format(self.env.context["report_name"]) 15 | report_model = self.env.get(report_model_name) 16 | if report_model is None: 17 | raise UserError(_("%s model was not found") % report_model_name) 18 | return report_model.create_xlsx_report(docids, data) 19 | return super()._render_xlsx(report_ref, docids, data) 20 | -------------------------------------------------------------------------------- /report_xlsx_helper/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_xlsx_helper/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Luc De Meyer \<\> 2 | 3 | - Rattapong Chokmasermkul \<\> 4 | 5 | - Saran Lim. \<\> 6 | 7 | - [Sinerkia Innovación y Desarrollo S.L.](https://www.sinerkia.com): 8 | - Luis Pomar 9 | -------------------------------------------------------------------------------- /report_xlsx_helper/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module provides a set of tools to facilitate the creation of excel 2 | reports with format xlsx. 3 | -------------------------------------------------------------------------------- /report_xlsx_helper/readme/INSTALL.md: -------------------------------------------------------------------------------- 1 | This module requires report_xlsx version 13.0.1.0.0 or higher. 2 | -------------------------------------------------------------------------------- /report_xlsx_helper/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | In order to create an Excel report you can define a report of type 2 | 'xlsx' in a static or dynamic way: 3 | 4 | - Static syntax: cf. `account_move_line_report_xls` for an example. 5 | - Dynamic syntax: cf. `report_xlsx_helper_demo` for an example 6 | 7 | The `AbstractReportXlsx` class contains a number of attributes and 8 | methods to facilitate the creation excel reports in Odoo. 9 | 10 | - Cell types 11 | 12 | string, number, boolean, datetime. 13 | 14 | - Cell formats 15 | 16 | The predefined cell formats result in a consistent look and feel of 17 | the Odoo Excel reports. 18 | 19 | - Cell formulas 20 | 21 | Cell formulas can be easily added with the help of the 22 | `_rowcol_to_cell()` method. 23 | 24 | - Excel templates 25 | 26 | It is possible to define Excel templates which can be adapted by 27 | 'inherited' modules. Download the `account_move_line_report_xls` 28 | module from as example. 29 | 30 | - Excel with multiple sheets 31 | 32 | Download the `account_asset_management_xls` module from 33 | as example. 34 | -------------------------------------------------------------------------------- /report_xlsx_helper/report/__init__.py: -------------------------------------------------------------------------------- 1 | from . import report_xlsx_format 2 | from . import report_xlsx_abstract 3 | from . import test_partner_report_xlsx 4 | -------------------------------------------------------------------------------- /report_xlsx_helper/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_xlsx_helper/static/description/icon.png -------------------------------------------------------------------------------- /report_xlsx_helper/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_report_xlsx_helper 2 | -------------------------------------------------------------------------------- /report_xlsx_helper/tests/test_report_xlsx_helper.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009-2019 Noviat. 2 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). 3 | 4 | 5 | from odoo.tests.common import TransactionCase 6 | 7 | 8 | class TestReportXlsxHelper(TransactionCase): 9 | @classmethod 10 | def setUpClass(cls): 11 | super().setUpClass() 12 | p1 = cls.env.ref("base.res_partner_1") 13 | p2 = cls.env.ref("base.res_partner_2") 14 | cls.partners = p1 + p2 15 | ctx = { 16 | "report_name": "report_xlsx_helper.test_partner_xlsx", 17 | "active_model": "res.partner", 18 | "active_ids": cls.partners.ids, 19 | } 20 | cls.report = cls.env["ir.actions.report"].with_context(**ctx) 21 | 22 | def test_report_xlsx_helper(self): 23 | report_xls = self.report._render_xlsx(None, None, None) 24 | self.assertEqual(report_xls[1], "xlsx") 25 | -------------------------------------------------------------------------------- /report_xml/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 2 | 3 | from . import controllers 4 | from . import models 5 | from . import reports 6 | from .hooks import post_init_hook 7 | -------------------------------------------------------------------------------- /report_xml/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2014-2015 Grupo ESOC 2 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 3 | { 4 | "name": "XML Reports", 5 | "version": "18.0.1.0.0", 6 | "category": "Reporting", 7 | "website": "https://github.com/OCA/reporting-engine", 8 | "development_status": "Production/Stable", 9 | "author": "Tecnativa, Odoo Community Association (OCA), Avoin.Systems", 10 | "license": "AGPL-3", 11 | "installable": True, 12 | "application": False, 13 | "summary": "Allow to generate XML reports", 14 | "depends": ["web"], 15 | "data": [ 16 | "views/ir_actions_report_view.xml", 17 | ], 18 | "assets": { 19 | "web.assets_backend": [ 20 | "report_xml/static/src/js/report/action_manager_report.esm.js", 21 | ], 22 | }, 23 | "demo": [ 24 | "demo/report.xml", # register report in the system 25 | "demo/demo_report.xml", # report body definition 26 | ], 27 | "external_dependencies": { 28 | "python": [ # Python third party libraries required for module 29 | "lxml" # XML and HTML with Python 30 | ] 31 | }, 32 | "post_init_hook": "post_init_hook", 33 | } 34 | -------------------------------------------------------------------------------- /report_xml/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 2 | 3 | from . import report 4 | -------------------------------------------------------------------------------- /report_xml/demo/demo_report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | 13 | -------------------------------------------------------------------------------- /report_xml/demo/demo_report.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /report_xml/demo/report.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo xml report 5 | res.company 6 | qweb-xml 7 | report_xml.demo_report_xml_view 8 | res_company 9 | 10 | report 11 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /report_xml/hooks.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 2 | 3 | import os 4 | 5 | 6 | def post_init_hook(env): 7 | """ 8 | Loaded after installing this module, and before the next module starts 9 | installing. 10 | 11 | Add XSD Validation Schema for a demo report if it's in the system. 12 | Demo data records are always created with `noupdate == True` and render of 13 | tag `report` doesn't support new `ir.actions.report` field `xsd_schema`. 14 | Thus it is impossible to define `xsd_schema` in the demo definition or add 15 | schema after that via xml update record. Therefore it possible to add value 16 | to `xsd_schema` field for demo record only via hook. 17 | 18 | Args: 19 | * env(odoo.api.Environment) - provides access to the models 20 | """ 21 | report_domain = [ 22 | ("report_name", "=", "report_xml.demo_report_xml_view") # report tech name 23 | ] 24 | demo_report = env["ir.actions.report"].search(report_domain, limit=1) 25 | if demo_report: 26 | dir_path = os.path.dirname(__file__) 27 | xsd_file_relative_path = "demo/demo_report.xsd" 28 | xsd_file_full_path = os.path.join(dir_path, xsd_file_relative_path) 29 | 30 | with open(xsd_file_full_path) as xsd: 31 | # `xsd_schema` is binary fields with an attribute 32 | # `attachment=True` so XSD Schema will be added as attachment 33 | attach_vals = { 34 | "name": "Demo Report.xsd", 35 | "datas": xsd.read(), 36 | "res_model": "ir.actions.report", 37 | "res_id": demo_report.id, 38 | "res_field": "xsd_schema", 39 | "type": "binary", 40 | } 41 | env["ir.attachment"].create(attach_vals) 42 | -------------------------------------------------------------------------------- /report_xml/models/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 2 | 3 | from . import ir_actions_report 4 | -------------------------------------------------------------------------------- /report_xml/models/ir_actions_report.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2014-2015 Grupo ESOC 2 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 3 | 4 | from odoo import api, fields, models 5 | 6 | 7 | class IrActionsReport(models.Model): 8 | _inherit = "ir.actions.report" 9 | 10 | report_type = fields.Selection( 11 | selection_add=[("qweb-xml", "XML")], ondelete={"qweb-xml": "set default"} 12 | ) 13 | xsd_schema = fields.Binary( 14 | string="XSD Validation Schema", 15 | attachment=True, 16 | help="File with XSD Schema for checking content of result report. Can be empty " 17 | "if validation is not required.", 18 | ) 19 | xml_encoding = fields.Selection( 20 | selection=[ 21 | ("UTF-8", "UTF-8") # will be used as default even if nothing is selected 22 | ], 23 | string="XML Encoding", 24 | help="Encoding for XML reports. If nothing is selected, then UTF-8 will be " 25 | "applied.", 26 | ) 27 | xml_declaration = fields.Boolean( 28 | string="XML Declaration", 29 | help='Add `` at the start of final report ' 30 | "file.", 31 | ) 32 | xml_extension = fields.Char( 33 | default="xml", 34 | help="Extension for XML Reports, by default is `xml`", 35 | ) 36 | 37 | @api.model 38 | def _render_qweb_xml(self, report_ref, res_ids, data=None): 39 | """ 40 | Call `generate_report` method of report abstract class 41 | `report.` or of standard class for XML report 42 | rendering - `report.report_xml.abstract` 43 | 44 | Args: 45 | * docids(list) - IDs of instances for those report will be generated 46 | * data(dict, None) - variables for report rendering 47 | 48 | Returns: 49 | * str - result content of report 50 | * str - type of result content 51 | """ 52 | report = self._get_report(report_ref) 53 | report_model = self.env.get( 54 | f"report.{report.report_name}", self.env["report.report_xml.abstract"] 55 | ) 56 | return report_model.generate_report( 57 | ir_report=report, # will be used to get settings of report 58 | docids=res_ids, 59 | data=data or {}, 60 | ) 61 | -------------------------------------------------------------------------------- /report_xml/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /report_xml/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Enric Tobella \<\> 2 | 3 | - [Tecnativa](https://www.tecnativa.com): 4 | - Jairo Llopis 5 | 6 | - [Avoin.Systems](https://avoin.systems/): 7 | - Tatiana Deribina 8 | 9 | - Iván Antón \<\> 10 | -------------------------------------------------------------------------------- /report_xml/readme/CREDITS.md: -------------------------------------------------------------------------------- 1 | - Icon taken from 2 | 3 | -------------------------------------------------------------------------------- /report_xml/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module was written to extend the functionality of the reporting 2 | engine to support XML reports and allow modules to generate them by code 3 | or by QWeb templates. 4 | -------------------------------------------------------------------------------- /report_xml/readme/INSTALL.md: -------------------------------------------------------------------------------- 1 | To install this module, you need to: 2 | 3 | - Install [lxml](http://lxml.de/) in Odoo's `$PYTHONPATH`. 4 | - Install the repository 5 | [reporting-engine](https://github.com/OCA/reporting-engine). 6 | 7 | But this module does nothing for the end user by itself, so if you have 8 | it installed it's probably because there is another module that depends 9 | on it. 10 | -------------------------------------------------------------------------------- /report_xml/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | This module is intended as a base engine for other modules to use it, so 2 | no direct result if you are a user. 3 | 4 | ## If you are a developer 5 | 6 | To learn from an example, just check the [demo 7 | report](https://github.com/OCA/reporting-engine/blob/13.0/report_xml/demo/demo_report.xml) 8 | on GitHub for the model `res.company` or check it in interface from 9 | companies views. 10 | 11 | To develop with this module, you need to: 12 | 13 | - Create a module. 14 | - Make it depend on this one. 15 | - Follow [instructions to create 16 | reports](https://www.odoo.com/documentation/13.0/reference/reports.html) 17 | having in mind that the `report_type` field in your 18 | `ir.actions.report` record must be `qweb-xml`. 19 | 20 | In case you want to create a [custom 21 | report](https://www.odoo.com/documentation/13.0/reference/reports.html#custom-reports), 22 | the instructions remain the same as for HTML reports, and the method 23 | that you must override is also called `_get_report_values`, even when 24 | this time you are creating a XML report. 25 | 26 | You can make your custom report inherit `report.report_xml.abstract`, 27 | name it in such way `report.`. Also you can add a 28 | XSD file for report validation into `xsd_schema` field of your report 29 | (check [report 30 | definition](https://github.com/OCA/reporting-engine/blob/13.0/report_xml/demo/report.xml)) 31 | and have XSD automatic checking for free. 32 | 33 | You can customize rendering process and validation way via changing 34 | logic of `generate_report` and `validate_report` methods in your report 35 | class. 36 | 37 | You can visit 38 | `http:///report/xml//` to see 39 | your XML report online as a web page. 40 | 41 | For further information, please visit: 42 | 43 | - 44 | - 45 | -------------------------------------------------------------------------------- /report_xml/reports/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 2 | 3 | from . import report_report_xml_abstract 4 | -------------------------------------------------------------------------------- /report_xml/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/report_xml/static/description/icon.png -------------------------------------------------------------------------------- /report_xml/static/src/js/report/action_manager_report.esm.js: -------------------------------------------------------------------------------- 1 | import {download} from "@web/core/network/download"; 2 | import {registry} from "@web/core/registry"; 3 | import {user} from "@web/core/user"; 4 | 5 | function getReportUrl({report_name, context, data}) { 6 | // Rough copy of action_service.js _getReportUrl method. 7 | let url = `/report/xml/${report_name}`; 8 | const actionContext = context || {}; 9 | if (data && JSON.stringify(data) !== "{}") { 10 | const encodedOptions = encodeURIComponent(JSON.stringify(data)); 11 | const encodedContext = encodeURIComponent(JSON.stringify(actionContext)); 12 | return `${url}?options=${encodedOptions}&context=${encodedContext}`; 13 | } 14 | if (actionContext.active_ids) { 15 | url += `/${actionContext.active_ids.join(",")}`; 16 | } 17 | const userContext = encodeURIComponent(JSON.stringify(user.context)); 18 | return `${url}?context=${userContext}`; 19 | } 20 | async function triggerDownload(action, {onClose}, env) { 21 | // Rough copy of action_service.js _triggerDownload method. 22 | env.services.ui.block(); 23 | const data = JSON.stringify([getReportUrl(action), action.report_type]); 24 | const context = JSON.stringify(user.context); 25 | try { 26 | await download({url: "/report/download", data: {data, context}}); 27 | } finally { 28 | env.services.ui.unblock(); 29 | } 30 | if (action.close_on_report_download) { 31 | return env.services.action.doAction( 32 | {type: "ir.actions.act_window_close"}, 33 | {onClose} 34 | ); 35 | } 36 | if (onClose) { 37 | onClose(); 38 | } 39 | } 40 | registry 41 | .category("ir.actions.report handlers") 42 | .add("xml_handler", async function (action, options, env) { 43 | if (action.report_type === "qweb-xml") { 44 | await triggerDownload(action, options, env); 45 | return true; 46 | } 47 | return false; 48 | }); 49 | -------------------------------------------------------------------------------- /report_xml/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html). 2 | 3 | from . import test_report_xml 4 | -------------------------------------------------------------------------------- /report_xml/tests/test_report_xml.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 Creu Blanca 2 | # License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl). 3 | 4 | import json 5 | 6 | from lxml import etree 7 | 8 | from odoo import http 9 | from odoo.tests import common 10 | 11 | 12 | class TestXmlReport(common.HttpCase): 13 | def test_xml(self): 14 | report_object = self.env["ir.actions.report"] 15 | report_name = "report_xml.demo_report_xml_view" 16 | report = report_object._get_report_from_name(report_name) 17 | docs = self.env["res.company"].search([], limit=1) 18 | self.assertEqual(report.report_type, "qweb-xml") 19 | result_report = report_object._render(report_name, docs.ids, {}) 20 | result_tree = etree.fromstring(result_report[0]) 21 | el = result_tree.xpath("/root/user/name") 22 | self.assertEqual(el[0].text, docs.ensure_one().name) 23 | 24 | def test_xml_extension(self): 25 | self.authenticate("admin", "admin") 26 | report_object = self.env["ir.actions.report"] 27 | report_name = "report_xml.demo_report_xml_view" 28 | report = report_object._get_report(report_name) 29 | # Test changing report to use ".svg" extension 30 | report.write({"xml_extension": "svg"}) 31 | filename = self.get_report_headers().headers.get("Content-Disposition") 32 | self.assertTrue(".svg" in filename) 33 | # Test changing report to use ".ffdata" extension 34 | report.write({"xml_extension": "ffdata"}) 35 | filename = self.get_report_headers().headers.get("Content-Disposition") 36 | self.assertTrue(".ffdata" in filename) 37 | 38 | def get_report_headers(self): 39 | return self.url_open( 40 | url="/report/download", 41 | data={ 42 | "data": json.dumps( 43 | ["/report/xml/report_xml.demo_report_xml_view/1", "qweb-xml"] 44 | ), 45 | "csrf_token": http.Request.csrf_token(self), 46 | }, 47 | ) 48 | -------------------------------------------------------------------------------- /report_xml/views/ir_actions_report_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ir.actions.report.view.form.report.xml 5 | ir.actions.report 6 | 7 | 8 | 13 | 14 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # generated from manifests external_dependencies 2 | lxml 3 | mock 4 | openpyxl 5 | py3o.formats 6 | py3o.template 7 | xlrd 8 | xlsxwriter 9 | -------------------------------------------------------------------------------- /setup/_metapackage/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "odoo-addons-oca-reporting-engine" 3 | version = "18.0.20250612.0" 4 | dependencies = [ 5 | "odoo-addon-base_comment_template==18.0.*", 6 | "odoo-addon-bi_sql_editor==18.0.*", 7 | "odoo-addon-pdf_xml_attachment==18.0.*", 8 | "odoo-addon-report_csv==18.0.*", 9 | "odoo-addon-report_py3o==18.0.*", 10 | "odoo-addon-report_py3o_fusion_server==18.0.*", 11 | "odoo-addon-report_qweb_element_page_visibility==18.0.*", 12 | "odoo-addon-report_qweb_parameter==18.0.*", 13 | "odoo-addon-report_qweb_pdf_cover==18.0.*", 14 | "odoo-addon-report_qweb_pdf_watermark==18.0.*", 15 | "odoo-addon-report_wkhtmltopdf_param==18.0.*", 16 | "odoo-addon-report_xlsx==18.0.*", 17 | "odoo-addon-report_xlsx_helper==18.0.*", 18 | "odoo-addon-report_xml==18.0.*", 19 | "odoo-addon-sql_export==18.0.*", 20 | "odoo-addon-sql_export_excel==18.0.*", 21 | "odoo-addon-sql_request_abstract==18.0.*", 22 | ] 23 | classifiers=[ 24 | "Programming Language :: Python", 25 | "Framework :: Odoo", 26 | "Framework :: Odoo :: 18.0", 27 | ] 28 | -------------------------------------------------------------------------------- /sql_export/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | from . import wizard 3 | -------------------------------------------------------------------------------- /sql_export/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2015 Akretion () 2 | # @author: Florian da Costa 3 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 4 | 5 | { 6 | "name": "SQL Export", 7 | "version": "18.0.1.0.0", 8 | "author": "Akretion,GRAP,Odoo Community Association (OCA)", 9 | "maintainers": ["legalsylvain", "florian-dacosta"], 10 | "website": "https://github.com/OCA/reporting-engine", 11 | "license": "AGPL-3", 12 | "category": "Generic Modules/Others", 13 | "summary": "Export data in csv file with SQL requests", 14 | "depends": [ 15 | "spreadsheet_dashboard", 16 | "sql_request_abstract", 17 | ], 18 | "data": [ 19 | "views/sql_export_view.xml", 20 | "wizard/wizard_file_view.xml", 21 | "security/sql_export_security.xml", 22 | "security/ir.model.access.csv", 23 | ], 24 | "demo": [ 25 | "demo/sql_export.xml", 26 | ], 27 | "assets": { 28 | "web.assets_backend": [ 29 | "sql_export/static/src/scss/modal_properties.scss", 30 | ] 31 | }, 32 | "installable": True, 33 | } 34 | -------------------------------------------------------------------------------- /sql_export/demo/sql_export.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Export Partners (Demo Data) 10 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | Export Partners With Variables (Demo Data) 25 | %(Date)s 33 | AND id = %(ID)s 34 | AND rel.category_id in %(Categories)s 35 | ]]> 36 | 37 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /sql_export/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import sql_export 2 | -------------------------------------------------------------------------------- /sql_export/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /sql_export/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - [Akretion](https://www.akretion.com): 2 | - Florian da Costa \<\> 3 | - Mourad EL HADJ MIMOUNE \<\> 4 | - Benoît GUILLOT \<\> 5 | - [Eficent](https://www.eficent.com): 6 | - Aaron Henriquez \<\> 7 | - [Codeforward](https://www.codeforward.nl): 8 | - Sander Lienaerts \<\> -------------------------------------------------------------------------------- /sql_export/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | Allow to export data in csv files FROM sql requests. There are some 2 | restrictions in the sql query, you can only read datas. No update, 3 | deletion or creation are possible. A new sub menu named Sql Export is 4 | available in the Dashboard main menu. 5 | -------------------------------------------------------------------------------- /sql_export/readme/ROADMAP.md: -------------------------------------------------------------------------------- 1 | - Some words are prohibited and can't be used is the query in anyways, 2 | even in a select query: 3 | - delete 4 | - drop 5 | - insert 6 | - alter 7 | - truncate 8 | - execute 9 | - create 10 | - update 11 | 12 | See sql_request_abstract module to fix this issue. 13 | 14 | - checking SQL request by execution and rollback is disabled in this 15 | module since variables features has been introduced. This can be fixed 16 | by overloading \_prepare_request_check_execution() function. 17 | -------------------------------------------------------------------------------- /sql_export/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | Dashboards \> Sql Export 2 | 3 | **Specific use with parameters** 4 | 5 | - %(company_id)s allows to set in the query the company id of the user 6 | - %(user_id)s allows to set in the query the user id 7 | - for any created property, you can use it with %(Property String)s 8 | syntax 9 | -------------------------------------------------------------------------------- /sql_export/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" 2 | "access_sql_export_all","access_sql_export_all","model_sql_export",sql_request_abstract.group_sql_request_user,1,0,0,0 3 | "access_sql_export_editor","access_sql_export_editor","model_sql_export",sql_request_abstract.group_sql_request_manager,1,1,1,1 4 | "access_sql_file_wizard","access_sql_file_wizard","model_sql_file_wizard",sql_request_abstract.group_sql_request_user,1,1,1,0 5 | -------------------------------------------------------------------------------- /sql_export/security/sql_export_security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SQL Export users and groups rules 5 | 6 | 7 | 8 | 9 | 10 | ['|', ('user_ids','=',user.id), ('group_ids','in', [x.id for x in user.groups_id])] 13 | 14 | 15 | -------------------------------------------------------------------------------- /sql_export/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/sql_export/static/description/icon.png -------------------------------------------------------------------------------- /sql_export/static/src/scss/modal_properties.scss: -------------------------------------------------------------------------------- 1 | .modal-body .o_field_property_add { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /sql_export/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_sql_query 2 | -------------------------------------------------------------------------------- /sql_export/wizard/__init__.py: -------------------------------------------------------------------------------- 1 | from . import wizard_file 2 | -------------------------------------------------------------------------------- /sql_export/wizard/wizard_file_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | sql.file.wizard.view.form 5 | sql.file.wizard 6 | 7 |
8 | 15 | 20 | 21 | 22 | 23 |
24 |
38 | 39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /sql_export_excel/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | -------------------------------------------------------------------------------- /sql_export_excel/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Akretion 2 | # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). 3 | 4 | { 5 | "name": "SQL Export Excel", 6 | "version": "18.0.1.0.1", 7 | "author": "Akretion,Odoo Community Association (OCA)", 8 | "maintainers": ["florian-dacosta"], 9 | "website": "https://github.com/OCA/reporting-engine", 10 | "license": "AGPL-3", 11 | "category": "Generic Modules/Others", 12 | "summary": "Allow to export a sql query to an excel file.", 13 | "depends": ["sql_export"], 14 | "external_dependencies": { 15 | "python": [ 16 | "openpyxl", 17 | ], 18 | }, 19 | "data": [ 20 | "views/sql_export_view.xml", 21 | ], 22 | "installable": True, 23 | } 24 | -------------------------------------------------------------------------------- /sql_export_excel/models/__init__.py: -------------------------------------------------------------------------------- 1 | from . import sql_export 2 | -------------------------------------------------------------------------------- /sql_export_excel/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /sql_export_excel/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | If you want Odoo to update an existing excel file, you should create an 2 | attachment with the excel file and configure this attachment on the 3 | query. Then, you can configure the query to indicate if Odoo should 4 | export the header and where it should insert the data. By default, it 5 | will insert it in the first sheet, at first row/column. 6 | -------------------------------------------------------------------------------- /sql_export_excel/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Florian da Costa \<\> 2 | - Helly kapatel \<\> 3 | -------------------------------------------------------------------------------- /sql_export_excel/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | Add the possibility to extract data from a sql query toward an excel 2 | file. It is also possible to provide an template excel file for a query. 3 | In this case, the data will be inserted in the specified sheet of the 4 | provided excel file. This is usefull when doing a lot of calculation in 5 | excel and the data is coming from Odoo. 6 | -------------------------------------------------------------------------------- /sql_export_excel/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/sql_export_excel/static/description/icon.png -------------------------------------------------------------------------------- /sql_export_excel/tests/__init__.py: -------------------------------------------------------------------------------- 1 | from . import test_sql_query_excel 2 | -------------------------------------------------------------------------------- /sql_export_excel/views/sql_export_view.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | sql.export 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /sql_request_abstract/__init__.py: -------------------------------------------------------------------------------- 1 | from . import models 2 | from . import sql_db 3 | -------------------------------------------------------------------------------- /sql_request_abstract/__manifest__.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 - Today: GRAP (http://www.grap.coop) 2 | # @author: Sylvain LE GAL (https://twitter.com/legalsylvain) 3 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 4 | 5 | { 6 | "name": "SQL Request Abstract", 7 | "version": "18.0.1.0.0", 8 | "author": "GRAP,Akretion,Odoo Community Association (OCA)", 9 | "maintainers": ["legalsylvain"], 10 | "website": "https://github.com/OCA/reporting-engine", 11 | "license": "AGPL-3", 12 | "category": "Tools", 13 | "summary": "Abstract Model to manage SQL Requests", 14 | "depends": ["mail"], 15 | "data": [ 16 | "security/ir_module_category.xml", 17 | "security/res_groups.xml", 18 | "security/ir.model.access.csv", 19 | "views/view_sql_request_mixin.xml", 20 | ], 21 | "assets": { 22 | "web._assets_core": [ 23 | "sql_request_abstract/static/src/js/code_editor.esm.js", 24 | ], 25 | "web.ace_lib": [ 26 | "sql_request_abstract/static/lib/ace/mode-pgsql.js", 27 | ], 28 | }, 29 | "installable": True, 30 | } 31 | -------------------------------------------------------------------------------- /sql_request_abstract/models/__init__.py: -------------------------------------------------------------------------------- 1 | # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). 2 | 3 | from . import sql_request_mixin 4 | -------------------------------------------------------------------------------- /sql_request_abstract/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["whool"] 3 | build-backend = "whool.buildapi" 4 | -------------------------------------------------------------------------------- /sql_request_abstract/readme/CONFIGURE.md: -------------------------------------------------------------------------------- 1 | To configure the use of an external database, you need to edit the main 2 | configuration file of your instance and add the external database 3 | configuration with following keys : \* external_db_user \* 4 | external_db_password \* external_db_name \* external_db_host \* 5 | external_db_port 6 | -------------------------------------------------------------------------------- /sql_request_abstract/readme/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | - Florian da Costa \<\> 2 | - Sylvain LE GAL () 3 | - Alfadil Tabar () 4 | - Helly kapatel \<\> 5 | - Nguyen Minh Chien \<\> 6 | - Vo Hong Thien \<\> 7 | -------------------------------------------------------------------------------- /sql_request_abstract/readme/CREDITS.md: -------------------------------------------------------------------------------- 1 | The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp. 2 | -------------------------------------------------------------------------------- /sql_request_abstract/readme/DESCRIPTION.md: -------------------------------------------------------------------------------- 1 | This module provides an abstract model to manage SQL Select requests on 2 | database. It is not usefull for itself. You can see an exemple of 3 | implementation in the 'sql_export' module. (same repository). 4 | 5 | ## Implemented features 6 | 7 | - Add some restrictions in the sql request: 8 | - you can only read datas. No update, deletion or creation are 9 | possible. 10 | - some tables are not allowed, because they could contains clear 11 | password or keys. For the time being ('ir_config_parameter'). 12 | 13 | - The request can be in a 'draft' or a 'SQL Valid' status. To be valid, 14 | the request has to be cleaned, checked and tested. All of this 15 | operations can be disabled in the inherited modules. 16 | 17 | - This module two new groups: 18 | - SQL Request / User : Can see all the sql requests by default and 19 | execute them, if they are valid. 20 | - SQL Request / Manager : has full access on sql requests. 21 | -------------------------------------------------------------------------------- /sql_request_abstract/readme/DEVELOP.md: -------------------------------------------------------------------------------- 1 | This module add the 'pgsql' mode syntax for the ace widget. (the ace 2 | widget is used in odoo web module, but only with the xml and python 3 | mode). 4 | 5 | The file is a copy of the file present here 6 | ( 7 | (Release 18 Oct 2022) 8 | -------------------------------------------------------------------------------- /sql_request_abstract/readme/USAGE.md: -------------------------------------------------------------------------------- 1 | Inherit the model: 2 | 3 | ``` python 4 | from odoo import models 5 | 6 | class MyModel(models.model) 7 | _name = 'my.model' 8 | _inherit = ['sql.request.mixin'] 9 | 10 | _sql_request_groups_relation = 'my_model_groups_rel' 11 | 12 | _sql_request_users_relation = 'my_model_users_rel' 13 | ``` 14 | 15 | See implementations in the modules `bi_sql_editor` and `sql_export`. 16 | (same OCA/reporting-engine repository) 17 | -------------------------------------------------------------------------------- /sql_request_abstract/security/ir.model.access.csv: -------------------------------------------------------------------------------- 1 | id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 2 | access_sql_request_mixin_all,access_sql_request_mixin_all,model_sql_request_mixin,,0,0,0,0 3 | access_sql_request_mixin_user,access_sql_request_mixin_user,model_sql_request_mixin,sql_request_abstract.group_sql_request_user,1,0,0,0 4 | access_sql_request_mixin_manager,access_sql_request_mixin_manager,model_sql_request_mixin,sql_request_abstract.group_sql_request_manager,1,1,1,1 5 | -------------------------------------------------------------------------------- /sql_request_abstract/security/ir_module_category.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SQL Request 5 | 6 | 7 | -------------------------------------------------------------------------------- /sql_request_abstract/security/res_groups.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | User 10 | 11 | 12 | 13 | Manager 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /sql_request_abstract/sql_db.py: -------------------------------------------------------------------------------- 1 | # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). 2 | 3 | from odoo import tools 4 | from odoo.sql_db import Connection, ConnectionPool, _Pool # noqa 5 | 6 | 7 | def connection_info_for_external_database(): 8 | db_name = tools.config.get("external_db_name") 9 | connection_info = {"database": db_name} 10 | for p in ("host", "port", "user", "password"): 11 | cfg = tools.config.get("external_db_" + p) 12 | if cfg: 13 | connection_info[p] = cfg 14 | return db_name, connection_info 15 | 16 | 17 | def get_external_cursor(): 18 | global _Pool 19 | if _Pool is None: 20 | _Pool = ConnectionPool(int(tools.config["db_maxconn"])) 21 | db, info = connection_info_for_external_database() 22 | return Connection(_Pool, db, info).cursor() 23 | -------------------------------------------------------------------------------- /sql_request_abstract/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OCA/reporting-engine/f90055fef7ba13347b13bc8bb9539a9c2aa18ea1/sql_request_abstract/static/description/icon.png -------------------------------------------------------------------------------- /sql_request_abstract/static/src/js/code_editor.esm.js: -------------------------------------------------------------------------------- 1 | import {CodeEditor} from "@web/core/code_editor/code_editor"; 2 | import {patch} from "@web/core/utils/patch"; 3 | 4 | patch(CodeEditor, { 5 | MODES: [...CodeEditor.MODES, "pgsql"], 6 | }); 7 | --------------------------------------------------------------------------------