I'm currently creating a custom report for a module. I use Odoo 8.
This is my code :
sale_plan_emballage_report.xml :
<?xml version="1.0" encoding="utf-8"?> <openerp> <data> <report id="plan_emballage_qweb_id" model="sale.order.line" string="Sale plan emballage with QWeb" report_type="qweb-pdf" file="sale_plan_emballage.mysaleplanemballage_report" name="sale_plan_emballage.plan_emballage_qweb" /> <template id="plan_emballage_qweb"> <t t-call="report.external_layout"> <div class="page"> <h3 align="center"> Production d'emballage par commande – Semaine <span t-esc="hello_world()"/> </h3> <h4 align="center"> <strong>Requis Pour Lundi [[get_FirstDateOfWeek(0, False)]]</strong> </h4> <table class="table" border="1"> <thead> <tr> <th>Item</th> <th class="text-center">Qté</th> <th class="text-center">Metal</th> <th class="text-center">Bois</th> <th class="text-center">Tissus</th> <th class="text-center">PG</th> <th class="text-center">Pattes</th> <th class="text-center">Config</th> </tr> </thead> <tbody> <tr> <td>Item</td> <td class="text-center">Qté</td> <td class="text-center">Metal</td> <td class="text-center">Bois</td> <td class="text-center">Tissus</td> <td class="text-center">PG</td> <td class="text-center">Pattes</td> <td class="text-center">Config</td> </tr> </tbody> </table> </div> </t> </template>
plan.py :
# -*- coding: utf-8 -*- from openerp.report import report_sxw from openerp import models #MK from openerp.osv import osv #MK import time import datetime class plan(report_sxw.rml_parse): def __init__(self, cr, uid, name, context=None): super(plan, self).__init__(cr, uid, name, context=context) self.localcontext.update({ 'time': time, 'get_jours':self._get_jours, 'get_OrdersJour':self._get_OrdersJour, 'get_LinesOrderJour':self._get_LinesOrderJour, 'get_FirstDateOfWeek':self._get_FirstDateOfWeek, 'getLines': self.getLines, 'getLinesBois': self.getLinesBois, 'getLinesMetal': self.getLinesMetal, 'getLinesTissus': self.getLinesTissus, 'getLinesTeint': self.getLinesTeint, 'getLinesPeint': self.getLinesPeint, 'hello_world': self._hello_world, #MK }) tabMoisFr = ['janvier','fevrier','mars','avril','mai','juin','juillet','aout','septembre','octobre','novembre','decembre'] def _get_FirstDateOfWeek(self, offset=0, year=True): today = datetime.date.today() first = today - datetime.timedelta(days=today.weekday()-offset) ret = str(first.day) + ' ' + self.tabMoisFr[first.month-1] if year: ret += ' ' + str(first.year) return ret tabJour = ['Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi','Dimanche'] def getLinesTissus (self, objects): obj = self.getFctFiltre('tissu')(objects) return self.checkQtyField(self.getLines(obj),'qtyRembourage') def getLinesMetal (self, objects): obj = self.getFctFiltre('metal')(objects) return self.checkQtyField(self.getLines(obj),'qtyMetal') def getLinesBois (self, objects): obj = self.getFctFiltre('bois')(objects) return self.checkQtyField(self.getLines(obj),'qtyBois') def getLinesTeint (self, objects): obj = self.getFctFiltre('bois')(objects) return self.checkQtyField(self.getLines(obj),'qtyTeinture') def getLinesPeint (self, objects): obj = self.getFctFiltre('metal')(objects) return self.checkQtyField(self.getLines(obj),'qtyPeinture') def checkQtyField (self, objects, field): for i in range(len(objects)): for cmd in objects[i]['commandes'].keys(): removeItem = 0 for j in range(len (objects[i]['commandes'][cmd]['items'])): if objects[i]['commandes'][cmd]['items'][j - removeItem][field] <= 0: del objects[i]['commandes'][cmd]['items'][j - removeItem] removeItem += 1 if len (objects[i]['commandes'][cmd]['items']) == 0: del objects[i]['commandes'][cmd] return objects def getLines (self, objects): tabData = [] print objects for i in range (7): tabData.append({}) tabData [i] ['jour'] = self.tabJour [i] tabData [i] ['commandes'] = {} for o in objects: indJour = int(o.jour) - 1 if indJour not in range(7): continue commande = o.order_id.name print "yyyyyyyyyyyyoooooooooooooooooooooolllllllllllllllllllllooooooooooooooooooooooooooo" if not (tabData [indJour]['commandes'].has_key (commande)): tabData [indJour]['commandes'][commande] = {} tabData [indJour]['commandes'][commande]['items'] = [] tabData [indJour]['commandes'][commande]['partner'] = o.order_partner_id.name bois = o.bois1.code_fini bois2 = o.bois2.code_fini metal = o.metal.code_fini tissus = o.tissu.code_fini poignee = o.poignee.code_fini patte = o.patte.code_fini cfg = o.config optionTissu = o.tissu.couleur_finifr qty = int(o.product_uom_qty) qtyEmballe = o.qte_emb and int(o.qte_emb) or 0 qtyPeinture = qty - qtyEmballe - int(o.FabPeint) qtyTeinture = qty - qtyEmballe - int(o.FabTeint) qtyRembourage = qty - qtyEmballe - int(o.ProdFTissus) qtyMetal = qtyPeinture - int(o.ProdFMetal) qtyBois = qtyTeinture - int(o.ProdFBois) if not (qtyMetal) or qtyMetal < 0: qtyMetal = 0 if not (qtyBois) or qtyBois < 0: qtyBois = 0 if not (qtyPeinture) or qtyPeinture < 0: qtyPeinture = 0 if not (qtyTeinture) or qtyTeinture < 0: qtyTeinture = 0 if not (qtyRembourage) or qtyRembourage < 0: qtyRembourage = 0 if bois == '.': bois = None if bois2 == '.': bois2 = None if metal == '.': metal = None if tissus == '.': tissus = None if poignee == '.': poignee = None if patte == '.': patte = None if cfg == '.': cfg = None if optionTissu == "NONE": optionTissu=None tabData [indJour]['commandes'][commande]['items'].append ({ 'item': o.product_id.default_code, 'qty': qty, 'metal': metal, 'bois': bois, 'bois2': bois2, 'tissus': tissus, 'poignee': poignee, 'patte': patte, 'optionTissu': optionTissu, 'cfg': cfg, 'notes': o.notes, 'qtyEmballe': qtyEmballe, 'qtyMetal': qtyMetal, 'qtyBois': qtyBois, 'qtyPeinture': qtyPeinture, 'qtyTeinture': qtyTeinture, 'qtyRembourage': qtyRembourage, }) print "FIN" return tabData def getStrJour (self, i): jour = False if 0 <= i and i <= 7: jour = self.tabJour[int(i) - 1] return jour def getIndJour (self, jour): try: return self.tabJour.index(jour) + 1 except: return False def noFilter(self, objects): return objects def filtreBois (self, objects): return filter(lambda l: l.bois1.code_fini != None and l.bois1.code_fini != '.', objects) def filtreMetal (self, objects): return filter(lambda l: l.metal.code_fini != None and l.metal.code_fini != '.', objects) def filtreTissus (self, objects): return filter(lambda l: l.tissu.code_fini != None and l.tissu.code_fini != '.', objects) def getFctFiltre(self, filtre): ret = self.noFilter if filtre == 'bois': ret = self.filtreBois elif filtre == 'metal': ret = self.filtreMetal elif filtre == 'tissu': ret = self.filtreTissus elif filtre == 'all': ret = self.noFilter return ret; def _get_jours(self, objects, filtre): obj = self.getFctFiltre(filtre)(objects) if obj == None: return False res=[] try: tabOrder = [] for o in obj: if o.jour is not False and o.jour not in tabOrder: tabOrder.append(o.jour) tabOrder.sort() for i in tabOrder: res.append( (i, self.getStrJour(int(i)) ) ) except: return False return res def _get_OrdersJour (self, objects, jour, filtre): ids = [] ret = [] obj = self.getFctFiltre(filtre)(objects) for o in obj: if o.jour != jour: continue if o.order_id.id not in ids: ids.append (o.order_id.id) ret.append ((o.order_id.id, o.order_id.name)) return ret def getInfosBois(self, o): bois1 = o.bois1.code_fini bois2 = o.bois2.code_fini poignee = o.poignee.code_fini patte = o.patte.code_fini cfg = o.config if bois1 == '.': bois1 = None if bois2 == '.': bois2 = None if poignee == '.': poignee = None if patte == '.': patte = None if cfg == '.': cfg = None return (o.product_id.default_code, o.product_uom_qty, bois1, bois2, poignee, patte, cfg, o.order_partner_id.name, o.notes) def getInfosMetal(self, o): metal = o.metal.code_fini poignee = o.poignee.code_fini patte = o.patte.code_fini cfg = o.config qty = o.product_uom_qty - o.FabPeint - o.ProdFMetal if metal == '.': metal = None if poignee == '.': poignee = None if patte == '.': patte = None if cfg == '.': cfg = None return (o.product_id.default_code, qty, metal, poignee, patte, cfg, o.order_partner_id.name, o.notes) def getInfosTissu(self, o): tissu = o.tissu.code_finifr nomTissu = o.tissu.couleur_finifr if tissu == '.': tissu = None return (o.product_id.default_code, o.product_uom_qty, tissu,nomTissu, o.order_partner_id.name, o.notes) def getInfos(self, o): bois = o.bois1.code_fini metal = o.metal.code_fini tissus = o.tissu.code_fini poignee = o.poignee.code_fini patte = o.patte.code_fini cfg = o.config if bois == '.': bois = None if metal == '.': metal = None if tissus == '.': tissus = None if poignee == '.': poignee = None if patte == '.': patte = None if cfg == '.': cfg = None return (o.product_id.default_code, o.product_uom_qty, '', metal, bois, tissus, poignee, patte, cfg, o.order_partner_id.name, o.notes) def getInfosFiltre(self, filtre): ret = self.getInfos if filtre == 'bois': ret = self.getInfosBois elif filtre == 'metal': ret = self.getInfosMetal elif filtre == 'tissu': ret = self.getInfosTissu elif filtre == 'all': ret = self.getInfos return ret; def _get_LinesOrderJour(self, objects, order, jour, filtre): ret = [] obj = self.getFctFiltre(filtre)(objects) for o in obj: if o.jour != jour or o.order_id.id != order: continue ret.append(self.getInfosFiltre(filtre)(o)) return ret def _hello_world(self): return "Hello World!" #MK class report_saleorderqweb(models.AbstractModel): _name = 'report.sale_plan_emballage.plan_emballage_qweb' _inherit = 'report.abstract_report' _template = 'sale_plan_emballage.plan_emballage_qweb' _wrapped_report_class = plan report_sxw.report_sxw('report.plan_teinture', 'sale.order.line', 'addons/sale_plan_emballage/report/plan_teinture.rml', parser=plan, header="external") report_sxw.report_sxw('report.plan_peinture', 'sale.order.line', 'addons/sale_plan_emballage/report/plan_peinture.rml', parser=plan, header="external") report_sxw.report_sxw('report.plan_rembourage', 'sale.order.line', 'addons/sale_plan_emballage/report/plan_rembourage.rml', parser=plan, header="external") report_sxw.report_sxw('report.plan_metal', 'sale.order.line', 'addons/sale_plan_emballage/report/plan_metal.rml', parser=plan, header="external") report_sxw.report_sxw('report.plan_bois', 'sale.order.line', 'addons/sale_plan_emballage/report/plan_bois.rml', parser=plan, header="external") report_sxw.report_sxw('report.plan_emballage', 'sale.order.line', 'addons/sale_plan_emballage/report/plan_emballage.rml', parser=plan, header="external")
I have read a lot of tutorials and forum post,but the problem is still there. Odoo says this :
Traceback (most recent call last): File "/opt/odoo/odoo-server/addons/report/controllers/main.py", line 116, in report_download response = self.report_routes(reportname, docids=docids, converter='pdf') File "/opt/odoo/odoo-server/openerp/http.py", line 405, in response_wrap response = f(*args, **kw) File "/opt/odoo/odoo-server/addons/report/controllers/main.py", line 65, in report_routes pdf = report_obj.get_pdf(cr, uid, docids, reportname, data=options_data, context=context) File "/opt/odoo/odoo-server/openerp/api.py", line 268, in wrapper return old_api(self, *args, **kwargs) File "/opt/odoo/odoo-server/addons/report/models/report.py", line 192, in get_pdf html = self.get_html(cr, uid, ids, report_name, data=data, context=context) File "/opt/odoo/odoo-server/openerp/api.py", line 268, in wrapper return old_api(self, *args, **kwargs) File "/opt/odoo/odoo-server/addons/report/models/report.py", line 177, in get_html return self.render(cr, uid, [], report.report_name, docargs, context=context) File "/opt/odoo/odoo-server/openerp/api.py", line 268, in wrapper return old_api(self, *args, **kwargs) File "/opt/odoo/odoo-server/addons/report/models/report.py", line 153, in render return view_obj.render(cr, uid, template, values, context=context) File "/opt/odoo/odoo-server/openerp/api.py", line 268, in wrapper return old_api(self, *args, **kwargs) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_ui_view.py", line 1022, in render return self.pool[engine].render(cr, uid, id_or_xml_id, qcontext, loader=loader, context=context) File "/opt/odoo/odoo-server/openerp/api.py", line 268, in wrapper return old_api(self, *args, **kwargs) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 263, in render return self.render_node(self.get_template(id_or_xml_id, qwebcontext), qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 302, in render_node result = self.render_element(element, template_attributes, generated_attributes, qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 323, in render_element g_inner.append(self.render_node(current_node, qwebcontext)) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 300, in render_node result = self._render_tag[t_render](self, element, template_attributes, generated_attributes, qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 438, in render_tag_call d[0] = self.render_element(element, template_attributes, generated_attributes, d) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 323, in render_element g_inner.append(self.render_node(current_node, qwebcontext)) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 302, in render_node result = self.render_element(element, template_attributes, generated_attributes, qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 323, in render_element g_inner.append(self.render_node(current_node, qwebcontext)) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 302, in render_node result = self.render_element(element, template_attributes, generated_attributes, qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 323, in render_element g_inner.append(self.render_node(current_node, qwebcontext)) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 300, in render_node result = self._render_tag[t_render](self, element, template_attributes, generated_attributes, qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 375, in render_tag_esc inner = widget.format(template_attributes['esc'], options, qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 1000, in format return escape(self._format(inner, options, qwebcontext)) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 997, in _format return self.pool['ir.qweb'].eval_str(inner, qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 215, in eval_str val = self.eval(expr, qwebcontext) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 207, in eval raise_qweb_exception(message="Could not evaluate expression %r" % expr, expression=expr, template=template) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 204, in eval return qwebcontext.safe_eval(expr) File "/opt/odoo/odoo-server/openerp/addons/base/ir/ir_qweb.py", line 89, in safe_eval return eval(expr, None, locals_dict, nocopy=True, locals_builtins=True) File "/opt/odoo/odoo-server/openerp/tools/safe_eval.py", line 314, in safe_eval return eval(c, globals_dict, locals_dict) File "", line 1, in <module> QWebException: "'NoneType' object is not callable" while evaluating 'hello_world()'
I think i have correctly configure the parser. Any suggestions ?
are you working with sxw report or qweb-report?