I would like to retrieve a config parameter from database in a custom QWeb Report.
What shall I do?
Specifically, I want to get the equivalent (in the model):
self.env['ir.config_parameter'].get_param('my_param', '')
Could someone highlight where to start?
As additional information, the report I am trying to use inherits report.minimal_layout:
<?xml version="1.0"?>
<odoo>
<data>
<template id="report_saleorder_css" inherit_id="report.minimal_layout">
<xpath expr="html/head/*[position() = last()]" position="after">
<style>
body {
color: <t t-esc="color"/>;
}
</style>
</xpath>
</template>
</data>
</odoo>
And this is the custom render function I have tried:
class CustomReport(models.AbstractModel):
_name = 'report.mymodule.report_saleorder_css'
#api.model
def render_html(self, data=None):
report_obj = self.env['report']
report = report_obj._get_report_from_name('mymodule.report_saleorder_css')
docargs = {
'doc_ids': self._ids,
'doc_model': report.model,
'docs': self,
'color': 'red'
}
return report_obj.render('mymodule.report_saleorder_css', docargs)
without success
In simple word you want to retrieve a config parameter whenever you print qweb report.
we can not directly use self.env in qweb report, but we can call a function which do that operation and return config parameter value. To do that first create python function in your model.
#api.model
def get_system_para(self):
para_value = self.env['ir.config_parameter'].get_param('web.base.url','')
return para_value
Now call this function in your qweb report
<span t-esc="docs.get_system_para()"/>
You have to retrieve the value beforehand and pass it to your template for usage.
You can do this by defining your own parser for your report, check the documentation.
See under Custom Reports on how you can create your own parser (Python class) and how you can use the docargs. Basically within the render_html method you search for your value, insert it on docargs and then pass it on the render method. Then you can use it from your template like:
<t t-esc="my_param" />
Related
I'm creating a new sector on the settings page of my module, where I have a value and an update icon, which aims to update the field value when I click on the icon.
But when I call the function to execute the function, the page is reloaded and I never get the value, but the value is printed in the terminal with a logger, does anyone have any suggestions?
My XML code:
<button type="object" name="refresh_credits" class="btn-link" icon="fa-refresh"/>
<span class="btn-link">Credits</span>
<field name="new_credits"/>
My python code inside a class:
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
new_credits = fields.Integer()
def refresh_credits(self):
data_details_credits = self.env['show.credits'].content_credits_info()
_logger.info(self.env['show.credits'].content_credits_info()[4])
self.new_credits = data_details_credits[4]
You have to override set_values and get_values method to update the values in settings. We cannot directly update the values in general settings.
Below is the example:
def set_values(self):
super(ResConfigSettings, self).set_values()
self.env['ir.config_parameter'].sudo().set_param('MODULE_NAME.new_credits',
self.new_credits)
#api.model
def get_values(self):
res = super(ResConfigSettings, self).get_values()
config = self.env['ir.config_parameter'].sudo()
config_key = config.get_param('MODULE_NAME.new_credits')
if config_zoom_key:
res.update(
field_name=config_key
)
return res
And also for better understanding, watch this video:
Add fields general settings
I want to create a custom button in the odoo employee model, which creates and downloads a pdf with the working contract of this employee. I tried to reverse engineer the given buttons in odoo, but every approach of mine failed. Does someone have a tip on where to start? Thanks a lot!
I usually return an URL action with the download button, and write a controller for the URL. The result is clicking the button actually downloading a file.
First step is to write your Qweb report. I'll write a sample one here. Note that the report ID is action_report_test_contract which is used later in the controller.
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<report string="Test Contract" id="action_report_test_contract" model="hr.contract" name="your_module_folder_name.test_contract_report" file="your_module_folder_name.test_contract_report" report_type="qweb-pdf" print_report_name="'%s - Contract' % (object.name)" />
<template id="test_contract_report">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="doc">
<t t-call="web.internal_layout">
<div class="page">
<h1><t t-esc="doc.name"/></h1>
<h2>Employee: <t t-esc="doc.employee_id.name"/></h2>
<h2>Start Date: <t t-esc="doc.date_start"/></h2>
</div>
</t>
</t>
</t>
</template>
</odoo>
Don't forget to add the report file path to your manufest. Test print the report from a contract, yes the sample works. Now inherit the hr.employee module to add the download method.
class HrEmployee(models.Model):
_inherit = "hr.employee"
def button_download_contract(self):
if not self.contract_id:
return
return {
'type' : 'ir.actions.act_url',
'url': '/web/download/test-contract-report?contract_id=%s'%(self.contract_id.id),
'target': 'self',
}
Also, inherit the view to add the download button:
<button name="button_download_contract" type="object" string="Download Contract" icon="fa-download"/>
Finally, finish the controller:
from odoo import http
from odoo.http import request, content_disposition, route
class testDownload(http.Controller):
#route(['/web/download/test-contract-report'], type='http', auth="user")
def download_pdf(self, contract_id, **kw):
employee_contract = request.env['hr.contract'].sudo().search([('id','=',contract_id)], limit=1)
if not employee_contract:
return None
pdf, _ = request.env.ref('your_module_folder_name.action_report_test_contract').sudo().render_qweb_pdf([int(contract_id)])
pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf)),('Content-Disposition', content_disposition('%s - Contract.PDF' % (employee_contract.name)))]
return request.make_response(pdf, headers=pdfhttpheaders)
Note that the method render_qweb_pdf relies on the report object. So action_report_test_contract is used, not test_contract_report.
I want to use Chatter for students model, so that, when value of some field is changed then it is logged under student form
To achieve this, I did the following things:
1. Added this div
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
in the student form.
It added the chatter, but when i clicked on New Message button, it gave the following error.
This could be because i haven't inherited mail.thread in student model.
Then i inherited this class in student model.
Then it again gave an error as shown below
I search this topic, but couldn't found anything.
It would be appreciated if someone could help me out.
In order to log changes of specific fields you need so set the track_visibility attribute on each field you want to track:
class OpStudent(models.Model):
_name = 'op.student'
_inherits = {
'res.partner': 'partner_id',
}
_inherit = [
'mail.thread',
'ir.needaction_mixin',
]
foo = fields.Char(track_visibility='always')
You may read more about it in the official documentation.
You're using Chatter for keeping the track on student details.
So I'll suggest another module which is working absolutely fine and keeps the track on student or any other model you want as I have personally used it.
I used audit log. It tracks all the CRUD operations. It will create Audit
the menu in setting tab from there you can set the model which you want to track.
For reference you can check this image also.
I had the same problem, but with res.company, I solved it like this:
class ResCompany(models.Model):
_name = 'res.company'
_inherit = ['res.company','mail.thread', 'mail.activity.mixin']
date_end = fields.Date(string="Fin Date",tracking=True)
and in xml:
<xpath expr="//form/sheet" position="after">
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread" />
</div>
</xpath>
I hope, that it serves you.
Is it possible get web page url in xml template?
<field name="body_html">
<![CDATA[
<p>Get url here</p>
]]>
</field>
Note: ${object.id}
return id eg. 10
In my opinion, QWeb has some fallbacks when it comes to doing what would otherwise be a simple thing in Python, such as accessing env to browse, search, or get other data like dbname or the company parameters like base_url.
What I've done in the past is just create a helper to have Python do the dirty work for you so that you can keep QWeb simple.
your_module/helpers/mixins.py
class CanGenerateUrl:
def generate_url(self):
"""
Build the URL to the record's form view.
- Base URL + Database Name + Record ID + Model Name
:param self: any Odoo record browse object (with access to env, _cr, and _model)
:return: string with url
"""
self.ensure_one()
base_url = self.env['ir.config_parameter'].get_param('web.base.url')
if base_url and base_url[-1:] != '/':
base_url += '/'
db = self._cr.dbname
return "{}web?db={}#id={}&view_type=form&model={}".format(base_url, db, self.id, self._model)
your_module/models/model.py
from openerp.addons.your_module.helpers.mixins import CanGenerateUrl
class YourModel(models.Model, CanGenerateUrl):
your_module/views/report.xml
<p><a href="${object.generate_url()}">${object.name or 'None'}<a/></p>
Reports Documentation
QWeb Documentation
How can I display a field when printing an invoice from sales and hiding it if the report is printed from accounting? Is there any way to access the active module from qweb template? Something similar to the following code:
<template id="report_invoice_document" inherit_id="account.report_invoice_document">
<xpath expr="//div[#class='page']" position="replace">
<div t-if="o.active_module == account" class="page">
<!-- Hide Here -->
</div>
<div t-else="" class="page">
<!-- Show Here -->
</div>
</xpath>
</template>
You can create a custom report or override the existing report with your custom report. Evaluate the active model in the python code and pass an argument to your report for qweb evaluation. You could pass an argument to your qweb just like the one you suggested and then use the exact same logic you used in your suggested code.
import logging
_logger = logging.getLogger(__name__)
class YourReport(models.AbstractModel):
_name = 'report.your_addon.report_template_id'
#api.multi
def render_html(self, data=None):
_logger.info("RUNNING REPORT")
report_obj = self.env['report']
report = report_obj._get_report_from_name('your_addon.report_template_id')
docs = self.env.context.get('active_ids')
docargs = {
'doc_model': report.model,
'active_model': self.env.context.get('active_model'),
'docs': docs,
}
return report_obj.render('your_addon.report_template_id', docargs)