我目前正在为模块创建自定义报告。我使用 Odoo 8。
这是我的代码:
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>
计划.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")
我已经阅读了很多教程和论坛帖子,但问题仍然存在。Odoo 说:
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()'
我想我已经正确配置了解析器。有什么建议么 ?