lims_report_html: extend use of report templates

This commit is contained in:
Adrián Bernardi 2023-08-09 13:59:39 -03:00
parent 179d6d00f1
commit 0bbdddf87a
10 changed files with 186 additions and 24 deletions

View File

@ -3,6 +3,7 @@
# the full copyright notices and license terms. # the full copyright notices and license terms.
from trytond.pool import Pool from trytond.pool import Pool
from trytond.report import Report
from . import action from . import action
from . import html_template from . import html_template
from . import configuration from . import configuration
@ -15,6 +16,7 @@ from . import notebook
def register(): def register():
module = 'lims_report_html'
Pool.register( Pool.register(
action.ActionReport, action.ActionReport,
html_template.ReportTemplate, html_template.ReportTemplate,
@ -36,13 +38,15 @@ def register():
results_report.GenerateReportStart, results_report.GenerateReportStart,
results_report.RelateAttachmentResultsReportStart, results_report.RelateAttachmentResultsReportStart,
notebook.Notebook, notebook.Notebook,
module='lims_report_html', type_='model') module=module, type_='model')
Pool.register( Pool.register(
action.ReportTranslationSet, action.ReportTranslationSet,
sample.CreateSample, sample.CreateSample,
results_report.GenerateReport, results_report.GenerateReport,
results_report.RelateAttachmentResultsReport, results_report.RelateAttachmentResultsReport,
module='lims_report_html', type_='wizard') module=module, type_='wizard')
Pool.register( Pool.register(
results_report.ResultReport, results_report.ResultReport,
module='lims_report_html', type_='report') module=module, type_='report')
Pool.register_mixin(html_template.LimsReport, Report,
module=module)

View File

@ -2,13 +2,23 @@
# The COPYRIGHT file at the top level of this repository contains # The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms. # the full copyright notices and license terms.
from trytond.model import fields
from trytond.pool import PoolMeta from trytond.pool import PoolMeta
from trytond.pyson import Eval
from trytond.transaction import Transaction from trytond.transaction import Transaction
class ActionReport(metaclass=PoolMeta): class ActionReport(metaclass=PoolMeta):
__name__ = 'ir.action.report' __name__ = 'ir.action.report'
lims_template = fields.Many2One('lims.report.template', 'Report Template',
domain=[
('report_name', '=', Eval('report_name')),
('type', 'in', [None, 'base']),
],
states={'invisible': Eval('template_extension') != 'lims'},
depends=['report_name', 'template_extension'])
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
super().__setup__() super().__setup__()

View File

@ -0,0 +1,11 @@
<tryton>
<data>
<record model="ir.ui.view" id="action_report_view_form">
<field name="model">ir.action.report</field>
<field name="inherit" ref="ir.action_report_view_form"/>
<field name="name">action_report_form</field>
</record>
</data>
</tryton>

View File

@ -19,7 +19,6 @@ from mimetypes import guess_type as mime_guess_type
from sql import Literal from sql import Literal
from trytond.model import ModelSQL, ModelView, DeactivableMixin, fields from trytond.model import ModelSQL, ModelView, DeactivableMixin, fields
from trytond.report import Report
from trytond.pool import Pool from trytond.pool import Pool
from trytond.pyson import Eval, Bool, Or from trytond.pyson import Eval, Bool, Or
from trytond.transaction import Transaction from trytond.transaction import Transaction
@ -311,13 +310,51 @@ class ReportTemplateSection(ModelSQL, ModelView):
raise UserError(gettext('lims_report_html.msg_section_pdf')) raise UserError(gettext('lims_report_html.msg_section_pdf'))
class LimsReport(Report): class LimsReport:
__slots__ = ()
@classmethod
def get_action(cls, data):
pool = Pool()
ActionReport = pool.get('ir.action.report')
action_id = data.get('action_id')
if action_id is None:
action_reports = ActionReport.search([
('report_name', '=', cls.__name__),
])
assert action_reports, '%s not found' % cls
action = action_reports[0]
else:
action = ActionReport(action_id)
return action, action.model or data.get('model')
@classmethod
def execute(cls, ids, data):
cls.check_access()
action, model = cls.get_action(data)
if action.template_extension != 'lims' or action.lims_template is None:
return super().execute(ids, data)
if data is None:
data = {}
current_data = data.copy()
template = action.lims_template
if template.type == 'base': # HTML
result = cls.execute_html_lims_report(ids, current_data)
else:
current_data['action_id'] = None
if template.report:
current_data['action_id'] = template.report.id
result = cls.execute_custom_lims_report(ids, current_data)
return result
@classmethod @classmethod
def execute_custom_lims_report(cls, ids, data): def execute_custom_lims_report(cls, ids, data):
pool = Pool() pool = Pool()
ActionReport = pool.get('ir.action.report') ActionReport = pool.get('ir.action.report')
cls.check_access()
action_id = data.get('action_id') action_id = data.get('action_id')
if action_id is None: if action_id is None:
@ -364,7 +401,6 @@ class LimsReport(Report):
def execute_html_lims_report(cls, ids, data): def execute_html_lims_report(cls, ids, data):
pool = Pool() pool = Pool()
ActionReport = pool.get('ir.action.report') ActionReport = pool.get('ir.action.report')
cls.check_access()
action_reports = ActionReport.search([ action_reports = ActionReport.search([
('report_name', '=', cls.__name__), ('report_name', '=', cls.__name__),
@ -385,11 +421,11 @@ class LimsReport(Report):
@classmethod @classmethod
def _execute_html_lims_report(cls, records, data, action): def _execute_html_lims_report(cls, records, data, action):
record = records[0] record = records[0]
template_id, tcontent, theader, tfooter = ( template, tcontent, theader, tfooter = (
cls.get_lims_template(action, record)) cls.get_lims_template(action, record))
context = Transaction().context context = Transaction().context
context['template'] = template_id context['template'] = template.id
if not template_id: if not template:
context['default_translations'] = os.path.join( context['default_translations'] = os.path.join(
os.path.dirname(__file__), 'report', 'translations') os.path.dirname(__file__), 'report', 'translations')
with Transaction().set_context(**context): with Transaction().set_context(**context):
@ -409,8 +445,8 @@ class LimsReport(Report):
if tfooter: if tfooter:
stylesheets += cls.parse_stylesheets(tfooter) stylesheets += cls.parse_stylesheets(tfooter)
page_orientation = (record.template and page_orientation = (template and
record.template.page_orientation or 'portrait') template.page_orientation or 'portrait')
document = PdfGenerator(content, document = PdfGenerator(content,
header_html=header, footer_html=footer, header_html=header, footer_html=footer,
@ -418,17 +454,21 @@ class LimsReport(Report):
stylesheets=stylesheets, stylesheets=stylesheets,
page_orientation=page_orientation).render_html().write_pdf() page_orientation=page_orientation).render_html().write_pdf()
if record.previous_sections or record.following_sections: previous_sections = (hasattr(record, 'previous_sections') and
record.previous_sections or [])
following_sections = (hasattr(record, 'following_sections') and
record.following_sections or [])
if previous_sections or following_sections:
merger = PdfFileMerger(strict=False) merger = PdfFileMerger(strict=False)
# Previous Sections # Previous Sections
for section in record.previous_sections: for section in previous_sections:
filedata = BytesIO(section.data) filedata = BytesIO(section.data)
merger.append(filedata) merger.append(filedata)
# Main Report # Main Report
filedata = BytesIO(document) filedata = BytesIO(document)
merger.append(filedata) merger.append(filedata)
# Following Sections # Following Sections
for section in record.following_sections: for section in following_sections:
filedata = BytesIO(section.data) filedata = BytesIO(section.data)
merger.append(filedata) merger.append(filedata)
output = BytesIO() output = BytesIO()
@ -441,22 +481,22 @@ class LimsReport(Report):
@classmethod @classmethod
def get_lims_template(cls, action, record): def get_lims_template(cls, action, record):
template_id, content, header, footer = None, None, None, None template, content, header, footer = None, None, None, None
if record.template: template = action.lims_template or record.template
template_id = record.template if template:
content = '<body>%s</body>' % record.template.content content = '<body>%s</body>' % template.content
header = (record.template.header and header = (template.header and
'<header id="header">%s</header>' % '<header id="header">%s</header>' %
record.template.header.content) template.header.content)
footer = (record.template.footer and footer = (template.footer and
'<footer id="footer">%s</footer>' % '<footer id="footer">%s</footer>' %
record.template.footer.content) template.footer.content)
if not content: if not content:
content = (action.report_content and content = (action.report_content and
action.report_content.decode('utf-8')) action.report_content.decode('utf-8'))
if not content: if not content:
raise UserError(gettext('lims_report_html.msg_no_template')) raise UserError(gettext('lims_report_html.msg_no_template'))
return template_id, content, header, footer return template, content, header, footer
@classmethod @classmethod
def render_lims_template(cls, action, template_string, def render_lims_template(cls, action, template_string,

View File

@ -28,6 +28,39 @@
<field name="name">template_section_list</field> <field name="name">template_section_list</field>
</record> </record>
<!-- Report Template -->
<record model="ir.ui.view" id="template_view_form">
<field name="model">lims.report.template</field>
<field name="type">form</field>
<field name="name">template_form</field>
</record>
<record model="ir.ui.view" id="template_view_list">
<field name="model">lims.report.template</field>
<field name="type">tree</field>
<field name="name">template_list</field>
</record>
<record model="ir.action.act_window" id="act_template_list">
<field name="name">Report Templates</field>
<field name="res_model">lims.report.template</field>
</record>
<record model="ir.action.act_window.view" id="act_template_view_list">
<field name="sequence" eval="10"/>
<field name="view" ref="template_view_list"/>
<field name="act_window" ref="act_template_list"/>
</record>
<record model="ir.action.act_window.view" id="act_template_view_form">
<field name="sequence" eval="20"/>
<field name="view" ref="template_view_form"/>
<field name="act_window" ref="act_template_list"/>
</record>
<menuitem action="act_template_list"
id="menu_template_list"
parent="ir.menu_action" sequence="21"
icon="tryton-list"/>
<!-- Results Report Template --> <!-- Results Report Template -->
<record model="ir.ui.view" id="result_template_view_form"> <record model="ir.ui.view" id="result_template_view_form">

View File

@ -2,6 +2,10 @@
msgid "" msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n" msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:ir.action.report,lims_template:"
msgid "Report Template"
msgstr "Plantilla de Informe"
msgctxt "field:lims.analysis,result_template:" msgctxt "field:lims.analysis,result_template:"
msgid "Report Template" msgid "Report Template"
msgstr "Plantilla de Informe" msgstr "Plantilla de Informe"
@ -257,6 +261,10 @@ msgctxt "model:ir.action,name:act_result_template_list"
msgid "Results Report Templates" msgid "Results Report Templates"
msgstr "Plantillas de Informe de resultados" msgstr "Plantillas de Informe de resultados"
msgctxt "model:ir.action,name:act_template_list"
msgid "Report Templates"
msgstr "Plantillas de Informe"
msgctxt "model:ir.action,name:report_result_report_html" msgctxt "model:ir.action,name:report_result_report_html"
msgid "Results Report" msgid "Results Report"
msgstr "Informe de resultados" msgstr "Informe de resultados"
@ -290,6 +298,10 @@ msgctxt "model:ir.ui.menu,name:menu_result_template_list"
msgid "Results Report Templates" msgid "Results Report Templates"
msgstr "Plantillas de Informe" msgstr "Plantillas de Informe"
msgctxt "model:ir.ui.menu,name:menu_template_list"
msgid "Report Templates"
msgstr "Plantillas de Informe"
msgctxt "model:lims.report.template,name:" msgctxt "model:lims.report.template,name:"
msgid "Report Template" msgid "Report Template"
msgstr "Plantilla de Informe" msgstr "Plantilla de Informe"

View File

@ -3,6 +3,7 @@ version=6.0.0
depends: depends:
lims lims
xml: xml:
action.xml
html_template.xml html_template.xml
configuration.xml configuration.xml
laboratory.xml laboratory.xml

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<data>
<xpath
expr="/form/notebook/page[@id='general']/field[@name='extension']"
position="after">
<label name="lims_template"/>
<field name="lims_template"/>
</xpath>
</data>

View File

@ -0,0 +1,35 @@
<?xml version="1.0"?>
<form>
<label name="report_name"/>
<field name="report_name"/>
<label name="name"/>
<field name="name"/>
<label name="type"/>
<field name="type"/>
<label name="report"/>
<field name="report"/>
<label name="page_orientation"/>
<field name="page_orientation"/>
<label name="active"/>
<field name="active" xexpand="0" width="25"/>
<notebook>
<page name="content">
<field name="content" colspan="4" widget="html"/>
</page>
<page id="header_footer" string="Header and Footer">
<label name="header"/>
<field name="header"
view_ids="lims_report_html.template_view_list,lims_report_html.template_view_form"/>
<label name="footer"/>
<field name="footer"
view_ids="lims_report_html.template_view_list,lims_report_html.template_view_form"/>
</page>
<page name="translations">
<field name="translations" colspan="4"/>
</page>
<page name="sections">
<field name="previous_sections" colspan="4"/>
<field name="following_sections" colspan="4"/>
</page>
</notebook>
</form>

View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<tree>
<field name="report_name"/>
<field name="name" expand="2"/>
<field name="type"/>
<field name="report"/>
</tree>