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)
Related
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.
this question already asked by someone, this in an example question
How to hide the edit button form only when invoice' state is 'paid' Odoo v8?
but i dont get true answer, somebody can help me, i really need to hide or disabled this button.
For your information im using odoo v.10
Thanks in advance
The only way to this is by Javascript you need to add this behavior to your form view
build a custom addon and just add this javascript file to your backend assets template
//file: static/src/js/disable_edit_for_paid_invoice.js
openerp.your_addon_name = function(instance, local) {
var instance = openerp;
var FormView = instance.web.FormView;
// override load_record
FormView.include({
load_record: function(record) {
// disable only for cancel and paid account.invoice
if (record){
if (this.model == 'account.invoice' & _.contains(['paid', 'cancel'], record.state)){
$('button.oe_form_button_edit').hide()
}else {
$('button.oe_form_button_edit').show()
}
}
// call super
return this._super(record);
}
});
}
Add this to backend asset template
<template id="assets_backend" name="disable edit paid invoice assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/your_addon_name/static/src/js/disable_edit_for_paid_invoice.js"></script>
</xpath>
</template>
Don't forget to replace your_addon_name by the real addon name that you create.
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" />
How can I change the number of visible items in the dropdownlist?
model:
category = fields.Many2one('my.category', 'Category', required=True)
view usage inside form:
<field name="category" options="{'no_quick_create':True,'no_create_edit':True}"/>
I just have 9 categories to display & the dropdown list only shows 7 categories + the 'Search more'.
It would be nice to show all categories, if necessary with a scroll bar.
Any help is appreciated. Thanks.
if yout want to change limit in dropdown view, you can find in web->static->src->js->view_from.js. and change the limit values for show many2one list.
create file new_widget.js:
(function() {
var instance = openerp;
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
instance.web.form.CompletionFieldMixin = {
init: function() {
this.limit = 10;
this.orderer = new instance.web.DropMisordered();
},};})();
and write in xml :
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="assets_backend" name="MyModule assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/MyModule/static/src/js/new_widget.js"></script>
</xpath>
</template>
</data>
</openerp>
Actually this works well for V14: https://apps.odoo.com/apps/modules/14.0/web_m2x_options/
I am trying to add a button in the tree view of sale order module, next to create and import buttons. That button will execute a python method.
I have created my custom module, extending sale order module and then, I have followed these steps:
Step 1: Create the button in my_module/static/src/xml/qweb.xml:
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-extend="ListView.buttons">
<t t-jquery="button.o_list_button_add" t-operation="after">
<t t-if="widget.model=='sale.order'">
<button class="btn btn-sm btn-primary update_sales_button" type="button">Run my stuff</button>
</t>
</t>
</t>
</templates>
Step 2: Add the file to the qweb section in __openerp.py__ of my module:
'depends': ['sale'],
'data': [],
'qweb': ['static/src/xml/qweb.xml'],
Now, the button appears.
Step 3: Create the python method to give functionality to the button in my_module/my_python_file.py:
from openerp import api, fields, models, _
class SaleOrderExtended(models.Model):
_inherit = ['sale.order']
#api.multi
def update_sales_button(self):
...
Note: The python method has been tested outside of odoo and works fine.
How can I link this python method with the button?
You need to extend the 'ListView' widget adding a click listener.
Also add the '#api.model' decorator to your method, so you can call it from js with the 'call' method.
Something like this:
ListView = require('web.ListView')
ListView.include({
render_buttons: function() {
// GET BUTTON REFERENCE
this._super.apply(this, arguments)
if (this.$buttons) {
var btn = this.$buttons.find('.update_sales_button')
}
// PERFORM THE ACTION
btn.on('click', this.proxy('do_new_button'))
},
do_new_button: function() {
instance.web.Model('sale.order')
.call('update_sale_button', [[]])
.done(function(result) {
< do your stuff, if you don't need to do anything remove the 'done' function >
})
})
I'm using odoo 11 and I had to replace widget.model with widget.modelName in the topic starter's template (the former is an object, the latter is a string). Also, to append the button to the end of row I've changed t-operation to "append" while looking for the parent div:
<t t-extend="ListView.buttons">
<t t-jquery="div.o_list_buttons" t-operation="append">
<t t-if="widget.modelName=='sale.order'">
<button class="btn btn-sm btn-default import_email_button" type="button">
Import E-mail Order
</button>
</t>
</t>
</t>