[MIG] openerp.report: convert to the new API
This commit is contained in:
@@ -1,18 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import openerp
|
||||
from openerp import api
|
||||
import interface
|
||||
import print_xml
|
||||
import print_fnc
|
||||
import custom
|
||||
import render
|
||||
import int_to_text
|
||||
|
||||
import report_sxw
|
||||
|
||||
import printscreen
|
||||
from . import custom
|
||||
from . import int_to_text
|
||||
from . import interface
|
||||
from . import print_fnc
|
||||
from . import print_xml
|
||||
from . import printscreen
|
||||
from . import render
|
||||
from . import report_sxw
|
||||
|
||||
def render_report(cr, uid, ids, name, data, context=None):
|
||||
"""
|
||||
|
||||
+54
-71
@@ -1,23 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import cStringIO
|
||||
import os
|
||||
import time
|
||||
|
||||
from lxml import etree
|
||||
from pychart import area, arrow, axis, bar_plot, canvas, category_coord, \
|
||||
fill_style, legend, line_plot, line_style, pie_plot, theme
|
||||
|
||||
import openerp
|
||||
import openerp.tools as tools
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
import print_xml
|
||||
import render
|
||||
from interface import report_int
|
||||
import common
|
||||
from openerp.osv.orm import BaseModel
|
||||
from pychart import *
|
||||
import misc
|
||||
import cStringIO
|
||||
from lxml import etree
|
||||
from openerp.tools.translate import _
|
||||
from openerp.exceptions import UserError
|
||||
from openerp.models import BaseModel
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
from openerp.tools.translate import _
|
||||
from . import common
|
||||
from . import misc
|
||||
from . import render
|
||||
from .interface import report_int
|
||||
|
||||
|
||||
class external_pdf(render.render):
|
||||
def __init__(self, pdf):
|
||||
@@ -37,6 +39,7 @@ theme.use_color = 1
|
||||
class report_custom(report_int):
|
||||
def __init__(self, name):
|
||||
report_int.__init__(self, name)
|
||||
|
||||
#
|
||||
# PRE:
|
||||
# fields = [['address','city'],['name'], ['zip']]
|
||||
@@ -104,26 +107,18 @@ class report_custom(report_int):
|
||||
result.append(row)
|
||||
return result
|
||||
|
||||
|
||||
def create(self, cr, uid, ids, datas, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
self.pool = openerp.registry(cr.dbname)
|
||||
report = self.pool['ir.report.custom'].browse(cr, uid, [datas['report_id']])[0]
|
||||
env = openerp.api.Environment(cr, uid, context or {})
|
||||
report = env['ir.report.custom'].browse([datas['report_id']])
|
||||
datas['model'] = report.model_id.model
|
||||
if report.menu_id:
|
||||
ids = self.pool[report.model_id.model].search(cr, uid, [])
|
||||
ids = env[report.model_id.model].search([]).ids
|
||||
datas['ids'] = ids
|
||||
|
||||
report_id = datas['report_id']
|
||||
report = self.pool['ir.report.custom'].read(cr, uid, [report_id], context=context)[0]
|
||||
fields = self.pool['ir.report.custom.fields'].read(cr, uid, report['fields_child0'], context=context)
|
||||
|
||||
fields.sort(lambda x,y : x['sequence'] - y['sequence'])
|
||||
|
||||
if report['field_parent']:
|
||||
parent_field = self.pool['ir.model.fields'].read(cr, uid, [report['field_parent'][0]], ['model'])
|
||||
model_name = self.pool['ir.model'].read(cr, uid, [report['model_id'][0]], ['model'], context=context)[0]['model']
|
||||
report = report.read()[0]
|
||||
fields = env['ir.report.custom.fields'].browse(report['fields_child0']).read()
|
||||
fields.sort(key=lambda x: x['sequence'])
|
||||
model_name = env['ir.model'].browse(report['model_id'][0]).model
|
||||
|
||||
fct = {
|
||||
'id': lambda x: x,
|
||||
@@ -139,7 +134,7 @@ class report_custom(report_int):
|
||||
field_child = f['field_child'+str(i)]
|
||||
if field_child:
|
||||
row.append(
|
||||
self.pool['ir.model.fields'].read(cr, uid, [field_child[0]], ['name'], context=context)[0]['name']
|
||||
env['ir.model.fields'].browse(field_child[0]).name
|
||||
)
|
||||
if f['fc'+str(i)+'_operande']:
|
||||
fct_name = 'id'
|
||||
@@ -152,7 +147,7 @@ class report_custom(report_int):
|
||||
cond.append(None)
|
||||
new_fields.append(row)
|
||||
new_cond.append(cond)
|
||||
objs = self.pool[model_name].browse(cr, uid, ids)
|
||||
objs = env[model_name].browse(ids)
|
||||
|
||||
# Group by
|
||||
groupby = None
|
||||
@@ -167,9 +162,9 @@ class report_custom(report_int):
|
||||
if report['field_parent']:
|
||||
level = []
|
||||
def build_tree(obj, level, depth):
|
||||
res = self._row_get(cr, uid,[obj], new_fields, new_cond)
|
||||
res = self._row_get(cr, uid, [obj], new_fields, new_cond)
|
||||
level.append(depth)
|
||||
new_obj = safe_eval('obj.'+report['field_parent'][1],{'obj': obj})
|
||||
new_obj = safe_eval('obj.'+report['field_parent'][1], {'obj': obj})
|
||||
if not isinstance(new_obj, list) :
|
||||
new_obj = [new_obj]
|
||||
for o in new_obj:
|
||||
@@ -180,7 +175,7 @@ class report_custom(report_int):
|
||||
for obj in objs:
|
||||
results += build_tree(obj, level, 0)
|
||||
else:
|
||||
results = self._row_get(cr, uid,objs, new_fields, new_cond, group_by=groupby)
|
||||
results = self._row_get(cr, uid, objs, new_fields, new_cond, group_by=groupby)
|
||||
|
||||
fct = {
|
||||
'calc_sum': lambda l: reduce(lambda x,y: float(x)+float(y), filter(None, l), 0),
|
||||
@@ -214,7 +209,7 @@ class report_custom(report_int):
|
||||
row.append(fct[str(fields[col]['operation'])](map(lambda x: x[col], res_dic[key])))
|
||||
new_res.append(row)
|
||||
results = new_res
|
||||
|
||||
|
||||
if report['type']=='table':
|
||||
if report['field_parent']:
|
||||
res = self._create_tree(uid, ids, report, fields, level, results, context)
|
||||
@@ -225,12 +220,13 @@ class report_custom(report_int):
|
||||
sort_idx = idx
|
||||
break
|
||||
try :
|
||||
results.sort(lambda x,y : cmp(float(x[sort_idx]),float(y[sort_idx])))
|
||||
results.sort(key=lambda x: float(x[sort_idx]))
|
||||
except :
|
||||
results.sort(lambda x,y : cmp(x[sort_idx],y[sort_idx]))
|
||||
results.sort(key=lambda x: x[sort_idx])
|
||||
if report['limitt']:
|
||||
results = results[:int(report['limitt'])]
|
||||
res = self._create_table(uid, ids, report, fields, None, results, context)
|
||||
|
||||
elif report['type'] in ('pie','bar', 'line'):
|
||||
results2 = []
|
||||
prev = False
|
||||
@@ -254,6 +250,7 @@ class report_custom(report_int):
|
||||
res = self._create_bars(cr,uid, ids, report, fields, results2, context)
|
||||
elif report['type']=='line':
|
||||
res = self._create_lines(cr,uid, ids, report, fields, results2, context)
|
||||
|
||||
return self.obj.get(), 'pdf'
|
||||
|
||||
def _create_tree(self, uid, ids, report, fields, level, results, context):
|
||||
@@ -262,7 +259,7 @@ class report_custom(report_int):
|
||||
pageSize=[pageSize[1],pageSize[0]]
|
||||
|
||||
new_doc = etree.Element('report')
|
||||
|
||||
|
||||
config = etree.SubElement(new_doc, 'config')
|
||||
|
||||
def _append_node(name, text):
|
||||
@@ -319,41 +316,34 @@ class report_custom(report_int):
|
||||
self.obj.render()
|
||||
return True
|
||||
|
||||
|
||||
def _create_lines(self, cr, uid, ids, report, fields, results, context):
|
||||
pool = openerp.registry(cr.dbname)
|
||||
env = openerp.api.Environment(cr, uid, context or {})
|
||||
pdf_string = cStringIO.StringIO()
|
||||
|
||||
can = canvas.init(fname=pdf_string, format='pdf')
|
||||
|
||||
can.show(80,380,'/16/H'+report['title'])
|
||||
|
||||
|
||||
ar = area.T(size=(350,350),
|
||||
#x_coord = category_coord.T(['2005-09-01','2005-10-22'],0),
|
||||
x_axis = axis.X(label = fields[0]['name'], format="/a-30{}%s"),
|
||||
y_axis = axis.Y(label = ', '.join(map(lambda x : x['name'], fields[1:]))))
|
||||
|
||||
#x_coord = category_coord.T(['2005-09-01','2005-10-22'],0),
|
||||
x_axis=axis.X(label = fields[0]['name'], format="/a-30{}%s"),
|
||||
y_axis=axis.Y(label = ', '.join(map(lambda x : x['name'], fields[1:]))))
|
||||
|
||||
process_date = {
|
||||
'D': lambda x: reduce(lambda xx, yy: xx + '-' + yy, x.split('-')[1:3]),
|
||||
'M': lambda x: x.split('-')[1],
|
||||
'Y': lambda x: x.split('-')[0]
|
||||
}
|
||||
|
||||
order_date = {
|
||||
'D': lambda x: time.mktime((2005, int(x.split('-')[0]), int(x.split('-')[1]), 0, 0, 0, 0, 0, 0)),
|
||||
'M': lambda x: x,
|
||||
'Y': lambda x: x
|
||||
}
|
||||
|
||||
abscissa = []
|
||||
|
||||
|
||||
idx = 0
|
||||
date_idx = None
|
||||
fct = {}
|
||||
for f in fields:
|
||||
field_id = (f['field_child3'] and f['field_child3'][0]) or (f['field_child2'] and f['field_child2'][0]) or (f['field_child1'] and f['field_child1'][0]) or (f['field_child0'] and f['field_child0'][0])
|
||||
if field_id:
|
||||
type = pool['ir.model.fields'].read(cr, uid, [field_id],['ttype'])
|
||||
if type[0]['ttype'] == 'date':
|
||||
ttype = env['ir.model.fields'].browse(field_id).ttype
|
||||
if ttype == 'date':
|
||||
date_idx = idx
|
||||
fct[idx] = process_date[report['frequency']]
|
||||
else:
|
||||
@@ -411,7 +401,7 @@ class report_custom(report_int):
|
||||
ar.add_plot(plot)
|
||||
abscissa.update(fields_bar[idx])
|
||||
idx0 += 1
|
||||
|
||||
|
||||
abscissa = map(lambda x : [x, None], abscissa)
|
||||
ar.x_coord = category_coord.T(abscissa,0)
|
||||
ar.draw(can)
|
||||
@@ -422,30 +412,22 @@ class report_custom(report_int):
|
||||
pdf_string.close()
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def _create_bars(self, cr, uid, ids, report, fields, results, context):
|
||||
pool = openerp.registry(cr.dbname)
|
||||
env = openerp.api.Environment(cr, uid, context or {})
|
||||
pdf_string = cStringIO.StringIO()
|
||||
|
||||
can = canvas.init(fname=pdf_string, format='pdf')
|
||||
|
||||
can.show(80,380,'/16/H'+report['title'])
|
||||
|
||||
|
||||
process_date = {
|
||||
'D': lambda x: reduce(lambda xx, yy: xx + '-' + yy, x.split('-')[1:3]),
|
||||
'M': lambda x: x.split('-')[1],
|
||||
'Y': lambda x: x.split('-')[0]
|
||||
}
|
||||
|
||||
order_date = {
|
||||
'D': lambda x: time.mktime((2005, int(x.split('-')[0]), int(x.split('-')[1]), 0, 0, 0, 0, 0, 0)),
|
||||
'M': lambda x: x,
|
||||
'Y': lambda x: x
|
||||
}
|
||||
|
||||
ar = area.T(size=(350,350),
|
||||
x_axis = axis.X(label = fields[0]['name'], format="/a-30{}%s"),
|
||||
y_axis = axis.Y(label = ', '.join(map(lambda x : x['name'], fields[1:]))))
|
||||
x_axis=axis.X(label = fields[0]['name'], format="/a-30{}%s"),
|
||||
y_axis=axis.Y(label = ', '.join(map(lambda x : x['name'], fields[1:]))))
|
||||
|
||||
idx = 0
|
||||
date_idx = None
|
||||
@@ -453,8 +435,8 @@ class report_custom(report_int):
|
||||
for f in fields:
|
||||
field_id = (f['field_child3'] and f['field_child3'][0]) or (f['field_child2'] and f['field_child2'][0]) or (f['field_child1'] and f['field_child1'][0]) or (f['field_child0'] and f['field_child0'][0])
|
||||
if field_id:
|
||||
type = pool['ir.model.fields'].read(cr, uid, [field_id],['ttype'])
|
||||
if type[0]['ttype'] == 'date':
|
||||
ttype = env['ir.model.fields'].browse(field_id).ttype
|
||||
if ttype == 'date':
|
||||
date_idx = idx
|
||||
fct[idx] = process_date[report['frequency']]
|
||||
else:
|
||||
@@ -462,7 +444,7 @@ class report_custom(report_int):
|
||||
else:
|
||||
fct[idx] = lambda x : x
|
||||
idx+=1
|
||||
|
||||
|
||||
# plot are usually displayed year by year
|
||||
# so we do so if the first field is a date
|
||||
data_by_year = {}
|
||||
@@ -480,7 +462,7 @@ class report_custom(report_int):
|
||||
|
||||
nb_bar = len(data_by_year)*(len(fields)-1)
|
||||
colors = map(lambda x:fill_style.Plain(bgcolor=x), misc.choice_colors(nb_bar))
|
||||
|
||||
|
||||
abscissa = {}
|
||||
for line in data_by_year.keys():
|
||||
fields_bar = []
|
||||
@@ -508,7 +490,7 @@ class report_custom(report_int):
|
||||
data_cum.append([k, float(data[k])+float(prev)])
|
||||
if fields[idx+1]['cumulate']:
|
||||
prev += data[k]
|
||||
|
||||
|
||||
idx0 = 0
|
||||
plot = bar_plot.T(label=fields[idx+1]['name']+' '+str(line), data = data_cum, cluster=(idx0*(len(fields)-1)+idx,nb_bar), fill_style=colors[idx0*(len(fields)-1)+idx])
|
||||
ar.add_plot(plot)
|
||||
@@ -601,4 +583,5 @@ class report_custom(report_int):
|
||||
self.obj = render.rml(rml)
|
||||
self.obj.render()
|
||||
return True
|
||||
|
||||
report_custom('report.custom')
|
||||
|
||||
+29
-38
@@ -3,18 +3,15 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
import urllib
|
||||
|
||||
from lxml import etree
|
||||
|
||||
import openerp
|
||||
import openerp.tools as tools
|
||||
import openerp.modules
|
||||
import print_xml
|
||||
import render
|
||||
import urllib
|
||||
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.report.render.rml2pdf import customfonts
|
||||
from . import print_xml
|
||||
from . import render
|
||||
from openerp.modules import get_module_resource
|
||||
|
||||
#
|
||||
# coerce any type to a unicode string (to preserve non-ascii characters)
|
||||
@@ -24,6 +21,7 @@ def toxml(value):
|
||||
unicode_value = tools.ustr(value)
|
||||
return unicode_value.replace('&', '&').replace('<','<').replace('>','>')
|
||||
|
||||
|
||||
class report_int(object):
|
||||
|
||||
_reports = {}
|
||||
@@ -49,6 +47,7 @@ class report_int(object):
|
||||
def create(self, cr, uid, ids, datas, context=None):
|
||||
return False
|
||||
|
||||
|
||||
class report_rml(report_int):
|
||||
"""
|
||||
Automatically builds a document using the transformation process:
|
||||
@@ -73,27 +72,24 @@ class report_rml(report_int):
|
||||
'makohtml2html' :self.create_makohtml2html,
|
||||
}
|
||||
|
||||
def create(self, cr, uid, ids, datas, context):
|
||||
registry = openerp.registry(cr.dbname)
|
||||
def create(self, cr, uid, ids, datas, context=None):
|
||||
env = openerp.api.Environment(cr, uid, context or {})
|
||||
xml = self.create_xml(cr, uid, ids, datas, context)
|
||||
xml = tools.ustr(xml).encode('utf8')
|
||||
report_type = datas.get('report_type', 'pdf')
|
||||
if report_type == 'raw':
|
||||
return xml, report_type
|
||||
|
||||
registry['res.font'].font_scan(cr, SUPERUSER_ID, lazy=True, context=context)
|
||||
env['res.font'].sudo().font_scan(lazy=True)
|
||||
|
||||
rml = self.create_rml(cr, xml, uid, context)
|
||||
ir_actions_report_xml_obj = registry['ir.actions.report.xml']
|
||||
report_xml_ids = ir_actions_report_xml_obj.search(cr, uid, [('report_name', '=', self.name[7:])], context=context)
|
||||
self.title = report_xml_ids and ir_actions_report_xml_obj.browse(cr,uid,report_xml_ids)[0].name or 'OpenERP Report'
|
||||
reports = env['ir.actions.report.xml'].search([('report_name', '=', self.name[7:])])
|
||||
self.title = reports[0].name if reports else 'Odoo Report'
|
||||
create_doc = self.generators[report_type]
|
||||
pdf = create_doc(rml, title=self.title)
|
||||
return pdf, report_type
|
||||
|
||||
def create_xml(self, cr, uid, ids, datas, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
doc = print_xml.document(cr, uid, datas, {})
|
||||
self.bin_datas.update( doc.bin_datas or {})
|
||||
doc.parse(self.tmpl, ids, self.table, context)
|
||||
@@ -102,9 +98,6 @@ class report_rml(report_int):
|
||||
return self.post_process_xml_data(cr, uid, xml, context)
|
||||
|
||||
def post_process_xml_data(self, cr, uid, xml, context=None):
|
||||
|
||||
if not context:
|
||||
context={}
|
||||
# find the position of the 3rd tag
|
||||
# (skip the <?xml ...?> and the "root" tag)
|
||||
iter = re.finditer('<[^>]*>', xml)
|
||||
@@ -113,7 +106,7 @@ class report_rml(report_int):
|
||||
pos_xml = i.end()
|
||||
|
||||
doc = print_xml.document(cr, uid, {}, {})
|
||||
tmpl_path = openerp.modules.get_module_resource('base', 'report', 'corporate_defaults.xml')
|
||||
tmpl_path = get_module_resource('base', 'report', 'corporate_defaults.xml')
|
||||
doc.parse(tmpl_path, [uid], 'res.users', context)
|
||||
corporate_header = doc.xml_get()
|
||||
doc.close()
|
||||
@@ -131,10 +124,8 @@ class report_rml(report_int):
|
||||
def create_rml(self, cr, xml, uid, context=None):
|
||||
if self.tmpl=='' and not self.internal_header:
|
||||
self.internal_header=True
|
||||
if not context:
|
||||
context={}
|
||||
registry = openerp.registry(cr.dbname)
|
||||
ir_translation_obj = registry['ir.translation']
|
||||
env = openerp.api.Environment(cr, uid, context or {})
|
||||
Translation = env['ir.translation']
|
||||
|
||||
# In some case we might not use xsl ...
|
||||
if not self.xsl:
|
||||
@@ -172,17 +163,17 @@ class report_rml(report_int):
|
||||
if node.tail:
|
||||
tail = node.tail.strip().replace('\n',' ')
|
||||
if text:
|
||||
translation1 = ir_translation_obj._get_source(cr, uid, self.name2, 'xsl', lang, text)
|
||||
if translation1:
|
||||
node.text = node.text.replace(text, translation1)
|
||||
text1 = Translation._get_source(self.name2, 'xsl', lang, text)
|
||||
if text1:
|
||||
node.text = node.text.replace(text, text1)
|
||||
if tail:
|
||||
translation2 = ir_translation_obj._get_source(cr, uid, self.name2, 'xsl', lang, tail)
|
||||
if translation2:
|
||||
node.tail = node.tail.replace(tail, translation2)
|
||||
tail1 = Translation._get_source(self.name2, 'xsl', lang, tail)
|
||||
if tail1:
|
||||
node.tail = node.tail.replace(tail, tail1)
|
||||
translate_aux(node, lang, t)
|
||||
|
||||
if context.get('lang', False):
|
||||
translate(stylesheet.iter(), context['lang'])
|
||||
if env.lang:
|
||||
translate(stylesheet.iter(), env.lang)
|
||||
|
||||
transform = etree.XSLT(stylesheet)
|
||||
xml = etree.tostring(
|
||||
@@ -190,7 +181,7 @@ class report_rml(report_int):
|
||||
|
||||
return xml
|
||||
|
||||
def create_pdf(self, rml, localcontext = None, logo=None, title=None):
|
||||
def create_pdf(self, rml, localcontext=None, logo=None, title=None):
|
||||
if not localcontext:
|
||||
localcontext = {}
|
||||
localcontext.update({'internal_header':self.internal_header})
|
||||
@@ -203,7 +194,7 @@ class report_rml(report_int):
|
||||
obj.render()
|
||||
return obj.get()
|
||||
|
||||
def create_html(self, rml, localcontext = None, logo=None, title=None):
|
||||
def create_html(self, rml, localcontext=None, logo=None, title=None):
|
||||
obj = render.rml2html(rml, localcontext, self.bin_datas)
|
||||
obj.render()
|
||||
return obj.get()
|
||||
@@ -213,28 +204,28 @@ class report_rml(report_int):
|
||||
obj.render()
|
||||
return obj.get().encode('utf-8')
|
||||
|
||||
def create_html2html(self, rml, localcontext = None, logo=None, title=None):
|
||||
def create_html2html(self, rml, localcontext=None, logo=None, title=None):
|
||||
obj = render.html2html(rml, localcontext, self.bin_datas)
|
||||
obj.render()
|
||||
return obj.get()
|
||||
|
||||
|
||||
def create_raw(self,rml, localcontext = None, logo=None, title=None):
|
||||
def create_raw(self,rml, localcontext=None, logo=None, title=None):
|
||||
obj = render.odt2odt(etree.XML(rml),localcontext)
|
||||
obj.render()
|
||||
return etree.tostring(obj.get())
|
||||
|
||||
def create_sxw(self,rml,localcontext = None):
|
||||
def create_sxw(self,rml,localcontext=None):
|
||||
obj = render.odt2odt(rml,localcontext)
|
||||
obj.render()
|
||||
return obj.get()
|
||||
|
||||
def create_odt(self,rml,localcontext = None):
|
||||
def create_odt(self,rml,localcontext=None):
|
||||
obj = render.odt2odt(rml,localcontext)
|
||||
obj.render()
|
||||
return obj.get()
|
||||
|
||||
def create_makohtml2html(self,html,localcontext = None):
|
||||
def create_makohtml2html(self,html,localcontext=None):
|
||||
obj = render.makohtml2html(html,localcontext)
|
||||
obj.render()
|
||||
return obj.get()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from pychart import *
|
||||
from pychart import color
|
||||
|
||||
colorline = [color.T(r=((r+3) % 11)/10.0,
|
||||
g=((g+6) % 11)/10.0,
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from lxml import etree
|
||||
import re
|
||||
|
||||
from lxml import etree
|
||||
|
||||
rml_parents = ['tr','story','section']
|
||||
html_parents = ['tr','body','div']
|
||||
sxw_parents = ['{http://openoffice.org/2000/table}table-row','{http://openoffice.org/2000/office}body','{http://openoffice.org/2000/text}section']
|
||||
odt_parents = ['{urn:oasis:names:tc:opendocument:xmlns:office:1.0}body','{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table-row','{urn:oasis:names:tc:opendocument:xmlns:text:1.0}section']
|
||||
|
||||
|
||||
class report(object):
|
||||
def preprocess_rml(self, root_node,type='pdf'):
|
||||
_regex1 = re.compile("\[\[(.*?)(repeatIn\(.*?\s*,\s*[\'\"].*?[\'\"]\s*(?:,\s*(.*?)\s*)?\s*\))(.*?)\]\]")
|
||||
|
||||
+137
-138
@@ -2,15 +2,16 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from lxml import etree
|
||||
|
||||
import openerp
|
||||
import openerp.tools as tools
|
||||
from . import print_fnc
|
||||
from openerp.models import BaseModel
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
import print_fnc
|
||||
from openerp.osv.orm import BaseModel
|
||||
|
||||
|
||||
class InheritDict(dict):
|
||||
# Might be usefull when we're doing name lookup for call or eval.
|
||||
|
||||
# Might be useful when we're doing name lookup for call or eval.
|
||||
def __init__(self, parent=None):
|
||||
self.parent = parent
|
||||
|
||||
@@ -23,6 +24,7 @@ class InheritDict(dict):
|
||||
else:
|
||||
return self.parent[name]
|
||||
|
||||
|
||||
def tounicode(val):
|
||||
if isinstance(val, str):
|
||||
unicode_val = unicode(val, 'utf-8')
|
||||
@@ -32,14 +34,14 @@ def tounicode(val):
|
||||
unicode_val = unicode(val)
|
||||
return unicode_val
|
||||
|
||||
|
||||
class document(object):
|
||||
def __init__(self, cr, uid, datas, func=False):
|
||||
# create a new document
|
||||
self.cr = cr
|
||||
self.pool = openerp.registry(cr.dbname)
|
||||
self.func = func or {}
|
||||
self.datas = datas
|
||||
self.uid = uid
|
||||
self.datas = datas
|
||||
self.func = func or {}
|
||||
self.bin_datas = {}
|
||||
|
||||
def node_attrs_get(self, node):
|
||||
@@ -86,162 +88,159 @@ class document(object):
|
||||
return safe_eval(expr, {}, {'obj': record})
|
||||
|
||||
def parse_node(self, node, parent, browser, datas=None):
|
||||
attrs = self.node_attrs_get(node)
|
||||
if 'type' in attrs:
|
||||
if attrs['type']=='field':
|
||||
value = self.get_value(browser, attrs['name'])
|
||||
#TODO: test this
|
||||
if value == '' and 'default' in attrs:
|
||||
value = attrs['default']
|
||||
env = openerp.api.Environment(self.cr, self.uid, {})
|
||||
attrs = self.node_attrs_get(node)
|
||||
if 'type' in attrs:
|
||||
if attrs['type']=='field':
|
||||
value = self.get_value(browser, attrs['name'])
|
||||
#TODO: test this
|
||||
if value == '' and 'default' in attrs:
|
||||
value = attrs['default']
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = tounicode(value)
|
||||
#TODO: test this
|
||||
for key, value in attrs.iteritems():
|
||||
if key not in ('type', 'name', 'default'):
|
||||
el.set(key, value)
|
||||
|
||||
elif attrs['type']=='attachment':
|
||||
model = browser._name
|
||||
value = self.get_value(browser, attrs['name'])
|
||||
|
||||
atts = env['ir.attachment'].search([('res_model','=',model),('res_id','=',int(value))])
|
||||
datas = atts.read()
|
||||
|
||||
if len(datas):
|
||||
# if there are several, pick first
|
||||
datas = datas[0]
|
||||
fname = str(datas['datas_fname'])
|
||||
ext = fname.split('.')[-1].lower()
|
||||
if ext in ('jpg','jpeg', 'png'):
|
||||
import base64
|
||||
from StringIO import StringIO
|
||||
dt = base64.decodestring(datas['datas'])
|
||||
fp = StringIO()
|
||||
fp.write(dt)
|
||||
i = str(len(self.bin_datas))
|
||||
self.bin_datas[i] = fp
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = i
|
||||
|
||||
elif attrs['type']=='data':
|
||||
#TODO: test this
|
||||
txt = self.datas.get('form', {}).get(attrs['name'], '')
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = txt
|
||||
|
||||
elif attrs['type']=='function':
|
||||
if attrs['name'] in self.func:
|
||||
txt = self.func[attrs['name']](node)
|
||||
else:
|
||||
txt = print_fnc.print_fnc(attrs['name'], node)
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = txt
|
||||
|
||||
elif attrs['type']=='eval':
|
||||
value = self.eval(browser, attrs['expr'])
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = str(value)
|
||||
|
||||
elif attrs['type']=='fields':
|
||||
fields = attrs['name'].split(',')
|
||||
vals = {}
|
||||
for b in browser:
|
||||
value = tuple([self.get_value2(b, f) for f in fields])
|
||||
if not value in vals:
|
||||
vals[value]=[]
|
||||
vals[value].append(b)
|
||||
keys = vals.keys()
|
||||
keys.sort()
|
||||
|
||||
if 'order' in attrs and attrs['order']=='desc':
|
||||
keys.reverse()
|
||||
|
||||
v_list = [vals[k] for k in keys]
|
||||
for v in v_list:
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = tounicode(value)
|
||||
#TODO: test this
|
||||
for key, value in attrs.iteritems():
|
||||
if key not in ('type', 'name', 'default'):
|
||||
el.set(key, value)
|
||||
for el_cld in node:
|
||||
self.parse_node(el_cld, el, v)
|
||||
|
||||
elif attrs['type']=='attachment':
|
||||
model = browser._name
|
||||
value = self.get_value(browser, attrs['name'])
|
||||
elif attrs['type']=='call':
|
||||
if len(attrs['args']):
|
||||
#TODO: test this
|
||||
# fetches the values of the variables which names where passed in the args attribute
|
||||
args = [self.eval(browser, arg) for arg in attrs['args'].split(',')]
|
||||
else:
|
||||
args = []
|
||||
# get the object
|
||||
if 'model' in attrs:
|
||||
obj = env[attrs['model']]
|
||||
else:
|
||||
obj = browser # the record(set) is an instance of the model
|
||||
|
||||
ids = self.pool['ir.attachment'].search(self.cr, self.uid, [('res_model','=',model),('res_id','=',int(value))])
|
||||
datas = self.pool['ir.attachment'].read(self.cr, self.uid, ids)
|
||||
# get the ids
|
||||
if 'ids' in attrs:
|
||||
ids = self.eval(browser, attrs['ids'])
|
||||
else:
|
||||
ids = browser.ids
|
||||
|
||||
if len(datas):
|
||||
# if there are several, pick first
|
||||
datas = datas[0]
|
||||
fname = str(datas['datas_fname'])
|
||||
ext = fname.split('.')[-1].lower()
|
||||
if ext in ('jpg','jpeg', 'png'):
|
||||
import base64
|
||||
from StringIO import StringIO
|
||||
dt = base64.decodestring(datas['datas'])
|
||||
fp = StringIO()
|
||||
fp.write(dt)
|
||||
i = str(len(self.bin_datas))
|
||||
self.bin_datas[i] = fp
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = i
|
||||
# call the method itself
|
||||
newdatas = getattr(obj, attrs['name'])(*args)
|
||||
|
||||
elif attrs['type']=='data':
|
||||
#TODO: test this
|
||||
txt = self.datas.get('form', {}).get(attrs['name'], '')
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = txt
|
||||
def parse_result_tree(node, parent, datas):
|
||||
if not node.tag == etree.Comment:
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
atr = self.node_attrs_get(node)
|
||||
if 'value' in atr:
|
||||
if not isinstance(datas[atr['value']], (str, unicode)):
|
||||
txt = str(datas[atr['value']])
|
||||
else:
|
||||
txt = datas[atr['value']]
|
||||
el.text = txt
|
||||
else:
|
||||
for el_cld in node:
|
||||
parse_result_tree(el_cld, el, datas)
|
||||
if not isinstance(newdatas, (BaseModel, list)):
|
||||
newdatas = [newdatas]
|
||||
for newdata in newdatas:
|
||||
parse_result_tree(node, parent, newdata)
|
||||
|
||||
elif attrs['type']=='function':
|
||||
if attrs['name'] in self.func:
|
||||
txt = self.func[attrs['name']](node)
|
||||
elif attrs['type']=='zoom':
|
||||
value = self.get_value(browser, attrs['name'])
|
||||
if value:
|
||||
if not isinstance(value, (BaseModel, list)):
|
||||
v_list = [value]
|
||||
else:
|
||||
txt = print_fnc.print_fnc(attrs['name'], node)
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = txt
|
||||
|
||||
elif attrs['type']=='eval':
|
||||
value = self.eval(browser, attrs['expr'])
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
el.text = str(value)
|
||||
|
||||
elif attrs['type']=='fields':
|
||||
fields = attrs['name'].split(',')
|
||||
vals = {}
|
||||
for b in browser:
|
||||
value = tuple([self.get_value2(b, f) for f in fields])
|
||||
if not value in vals:
|
||||
vals[value]=[]
|
||||
vals[value].append(b)
|
||||
keys = vals.keys()
|
||||
keys.sort()
|
||||
|
||||
if 'order' in attrs and attrs['order']=='desc':
|
||||
keys.reverse()
|
||||
|
||||
v_list = [vals[k] for k in keys]
|
||||
v_list = value
|
||||
for v in v_list:
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
for el_cld in node:
|
||||
self.parse_node(el_cld, el, v)
|
||||
else:
|
||||
# if there is no "type" attribute in the node, copy it to the xml data and parse its children
|
||||
if not node.tag == etree.Comment:
|
||||
if node.tag == parent.tag:
|
||||
el = parent
|
||||
else:
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
for el_cld in node:
|
||||
self.parse_node(el_cld,el, browser)
|
||||
|
||||
elif attrs['type']=='call':
|
||||
if len(attrs['args']):
|
||||
#TODO: test this
|
||||
# fetches the values of the variables which names where passed in the args attribute
|
||||
args = [self.eval(browser, arg) for arg in attrs['args'].split(',')]
|
||||
else:
|
||||
args = []
|
||||
# get the object
|
||||
if 'model' in attrs:
|
||||
obj = self.pool[attrs['model']]
|
||||
else:
|
||||
obj = browser # the record(set) is an instance of the model
|
||||
|
||||
# get the ids
|
||||
if 'ids' in attrs:
|
||||
ids = self.eval(browser, attrs['ids'])
|
||||
else:
|
||||
ids = browse.ids
|
||||
|
||||
# call the method itself
|
||||
newdatas = getattr(obj, attrs['name'])(self.cr, self.uid, ids, *args)
|
||||
|
||||
def parse_result_tree(node, parent, datas):
|
||||
if not node.tag == etree.Comment:
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
atr = self.node_attrs_get(node)
|
||||
if 'value' in atr:
|
||||
if not isinstance(datas[atr['value']], (str, unicode)):
|
||||
txt = str(datas[atr['value']])
|
||||
else:
|
||||
txt = datas[atr['value']]
|
||||
el.text = txt
|
||||
else:
|
||||
for el_cld in node:
|
||||
parse_result_tree(el_cld, el, datas)
|
||||
if not isinstance(newdatas, (BaseModel, list)):
|
||||
newdatas = [newdatas]
|
||||
for newdata in newdatas:
|
||||
parse_result_tree(node, parent, newdata)
|
||||
|
||||
elif attrs['type']=='zoom':
|
||||
value = self.get_value(browser, attrs['name'])
|
||||
if value:
|
||||
if not isinstance(value, (BaseModel, list)):
|
||||
v_list = [value]
|
||||
else:
|
||||
v_list = value
|
||||
for v in v_list:
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
for el_cld in node:
|
||||
self.parse_node(el_cld, el, v)
|
||||
else:
|
||||
# if there is no "type" attribute in the node, copy it to the xml data and parse its children
|
||||
if not node.tag == etree.Comment:
|
||||
if node.tag == parent.tag:
|
||||
el = parent
|
||||
else:
|
||||
el = etree.SubElement(parent, node.tag)
|
||||
for el_cld in node:
|
||||
self.parse_node(el_cld,el, browser)
|
||||
def xml_get(self):
|
||||
return etree.tostring(self.doc,encoding="utf-8",xml_declaration=True,pretty_print=True)
|
||||
|
||||
def parse_tree(self, ids, model, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
browser = self.pool[model].browse(self.cr, self.uid, ids, context)
|
||||
env = openerp.api.Environment(self.cr, self.uid, context or {})
|
||||
browser = env[model].browse(ids)
|
||||
self.parse_node(self.dom, self.doc, browser)
|
||||
|
||||
def parse_string(self, xml, ids, model, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
# parses the xml template to memory
|
||||
self.dom = etree.XML(xml)
|
||||
# create the xml data from the xml template
|
||||
self.parse_tree(ids, model, context)
|
||||
|
||||
def parse(self, filename, ids, model, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
# parses the xml template to memory
|
||||
src_file = tools.file_open(filename)
|
||||
try:
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import ps_list
|
||||
import ps_form
|
||||
from . import ps_list
|
||||
from . import ps_form
|
||||
|
||||
|
||||
""" A special report, that is automatically formatted to look like the
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import openerp
|
||||
from openerp.report.interface import report_int
|
||||
import openerp.tools as tools
|
||||
import os
|
||||
import time
|
||||
|
||||
from openerp.report import render
|
||||
from lxml import etree
|
||||
|
||||
import time, os
|
||||
import openerp
|
||||
import openerp.tools as tools
|
||||
from openerp.report import render
|
||||
from openerp.report.interface import report_int
|
||||
|
||||
|
||||
class report_printscreen_list(report_int):
|
||||
def __init__(self, name):
|
||||
report_int.__init__(self, name)
|
||||
|
||||
def _parse_node(self, root_node):
|
||||
result = []
|
||||
for node in root_node:
|
||||
@@ -36,19 +34,18 @@ class report_printscreen_list(report_int):
|
||||
def create(self, cr, uid, ids, datas, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
env = openerp.api.Environment(cr, uid, context)
|
||||
datas['ids'] = ids
|
||||
registry = openerp.registry(cr.dbname)
|
||||
model = registry[datas['model']]
|
||||
records = env[datas['model']].browse(ids)
|
||||
# title come from description of model which are specified in py file.
|
||||
self.title = model._description
|
||||
result = model.fields_view_get(cr, uid, view_type='form', context=context)
|
||||
self.title = records._description
|
||||
result = records.fields_view_get(view_type='form')
|
||||
|
||||
fields_order = self._parse_string(result['arch'])
|
||||
rows = model.read(cr, uid, datas['ids'], result['fields'].keys() )
|
||||
self._create_table(uid, datas['ids'], result['fields'], fields_order, rows, context, model._description)
|
||||
rows = records.read(list(result['fields']))
|
||||
self._create_table(uid, datas['ids'], result['fields'], fields_order, rows, context, records._description)
|
||||
return self.obj.get(), 'pdf'
|
||||
|
||||
|
||||
def _create_table(self, uid, ids, fields, fields_order, results, context, title=''):
|
||||
pageSize=[297.0,210.0]
|
||||
|
||||
@@ -113,4 +110,5 @@ class report_printscreen_list(report_int):
|
||||
self.obj = render.rml(rml, self.title)
|
||||
self.obj.render()
|
||||
return True
|
||||
|
||||
report_printscreen_list('report.printscreen.form')
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import openerp
|
||||
from openerp.report.interface import report_int
|
||||
import openerp.tools as tools
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
from lxml import etree
|
||||
from openerp.report import render, report_sxw
|
||||
import locale
|
||||
|
||||
import time, os
|
||||
from operator import itemgetter
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from lxml import etree
|
||||
|
||||
import openerp
|
||||
import openerp.tools as tools
|
||||
from openerp.report import render, report_sxw
|
||||
from openerp.report.interface import report_int
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
|
||||
|
||||
class report_printscreen_list(report_int):
|
||||
def __init__(self, name):
|
||||
report_int.__init__(self, name)
|
||||
super(report_printscreen_list, self).__init__(name)
|
||||
self.context = {}
|
||||
self.groupby = []
|
||||
self.cr=''
|
||||
self.cr = ''
|
||||
|
||||
def _parse_node(self, root_node):
|
||||
result = []
|
||||
@@ -43,25 +44,23 @@ class report_printscreen_list(report_int):
|
||||
|
||||
def create(self, cr, uid, ids, datas, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
self.cr=cr
|
||||
context = {}
|
||||
self.cr = cr
|
||||
self.context = context
|
||||
self.groupby = context.get('group_by',[])
|
||||
self.groupby_no_leaf = context.get('group_by_no_leaf',False)
|
||||
registry = openerp.registry(cr.dbname)
|
||||
model = registry[datas['model']]
|
||||
model_id = registry['ir.model'].search(cr, uid, [('model','=',model._name)])
|
||||
model_desc = model._description
|
||||
if model_id:
|
||||
model_desc = registry['ir.model'].browse(cr, uid, model_id[0], context).name
|
||||
self.groupby_no_leaf = context.get('group_by_no_leaf', False)
|
||||
env = openerp.api.Environment(cr, uid, context)
|
||||
Model = env[datas['model']]
|
||||
model = env['ir.model'].search([('model', '=', Model._name)])
|
||||
model_desc = model.name or Model._description
|
||||
self.title = model_desc
|
||||
datas['ids'] = ids
|
||||
result = model.fields_view_get(cr, uid, view_type='tree', context=context)
|
||||
result = Model.fields_view_get(view_type='tree')
|
||||
fields_order = self.groupby + self._parse_string(result['arch'])
|
||||
if self.groupby:
|
||||
rows = []
|
||||
def get_groupby_data(groupby = [], domain = []):
|
||||
records = model.read_group(cr, uid, domain, fields_order, groupby , 0, None, context)
|
||||
records = Model.read_group(domain, fields_order, groupby, 0, None)
|
||||
for rec in records:
|
||||
rec['__group'] = True
|
||||
rec['__no_leaf'] = self.groupby_no_leaf
|
||||
@@ -79,18 +78,17 @@ class report_printscreen_list(report_int):
|
||||
else:
|
||||
if self.groupby_no_leaf:
|
||||
continue
|
||||
child_ids = model.search(cr, uid, inner_domain)
|
||||
res = model.read(cr, uid, child_ids, result['fields'].keys(), context)
|
||||
res.sort(lambda x,y: cmp(ids.index(x['id']), ids.index(y['id'])))
|
||||
children = Model.search(inner_domain)
|
||||
res = children.read(list(result['fields']))
|
||||
res.sort(key=lambda x: ids.index(x['id']))
|
||||
rows.extend(res)
|
||||
dom = [('id','in',ids)]
|
||||
if self.groupby_no_leaf and len(ids) and not ids[0]:
|
||||
dom = datas.get('_domain',[])
|
||||
get_groupby_data(self.groupby, dom)
|
||||
else:
|
||||
rows = model.read(cr, uid, datas['ids'], result['fields'].keys(), context)
|
||||
ids2 = map(itemgetter('id'), rows) # getting the ids from read result
|
||||
if datas['ids'] != ids2: # sorted ids were not taken into consideration for print screen
|
||||
rows = Model.browse(ids).read(list(result['fields']))
|
||||
if datas['ids'] != rows.ids: # sorted ids were not taken into consideration for print screen
|
||||
rows_new = []
|
||||
for id in datas['ids']:
|
||||
rows_new += [elem for elem in rows if elem['id'] == id]
|
||||
@@ -98,7 +96,6 @@ class report_printscreen_list(report_int):
|
||||
res = self._create_table(uid, datas['ids'], result['fields'], fields_order, rows, context, model_desc)
|
||||
return self.obj.get(), 'pdf'
|
||||
|
||||
|
||||
def _create_table(self, uid, ids, fields, fields_order, results, context, title=''):
|
||||
pageSize=[297.0, 210.0]
|
||||
|
||||
@@ -116,10 +113,10 @@ class report_printscreen_list(report_int):
|
||||
_append_node('PageHeight', '%.2f' %(pageSize[1] * 2.8346,))
|
||||
_append_node('report-header', title)
|
||||
|
||||
registry = openerp.registry(self.cr.dbname)
|
||||
_append_node('company', registry['res.users'].browse(self.cr,uid,uid).company_id.name)
|
||||
rpt_obj = registry['res.users']
|
||||
rml_obj=report_sxw.rml_parse(self.cr, uid, rpt_obj._name,context)
|
||||
env = openerp.api.Environment(self.cr, uid, {})
|
||||
Users = env['res.users']
|
||||
_append_node('company', Users.browse(uid).company_id.name)
|
||||
rml_obj = report_sxw.rml_parse(self.cr, uid, Users._name, context)
|
||||
_append_node('header-date', str(rml_obj.formatLang(time.strftime("%Y-%m-%d"),date=True))+' ' + str(time.strftime("%H:%M")))
|
||||
l = []
|
||||
t = 0
|
||||
@@ -249,4 +246,5 @@ class report_printscreen_list(report_int):
|
||||
self.obj = render.rml(rml, title=self.title)
|
||||
self.obj.render()
|
||||
return True
|
||||
|
||||
report_printscreen_list('report.printscreen.list')
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from simple import simple
|
||||
from rml import rml, rml2html, rml2txt, odt2odt , html2html, makohtml2html
|
||||
from render import render
|
||||
|
||||
from .simple import simple
|
||||
from .rml import rml, rml2html, rml2txt, odt2odt , html2html, makohtml2html
|
||||
from .render import render
|
||||
|
||||
try:
|
||||
from PIL import Image
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from html2html import parseString
|
||||
from .html2html import parseString
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.report.render.rml2pdf import utils
|
||||
import copy
|
||||
import base64
|
||||
import copy
|
||||
import cStringIO
|
||||
import re
|
||||
|
||||
from reportlab.lib.utils import ImageReader
|
||||
|
||||
from openerp.report.render.rml2pdf import utils
|
||||
|
||||
_regex = re.compile('\[\[(.+?)\]\]')
|
||||
utils._regex = re.compile('\[\[\s*(.+?)\s*\]\]',re.DOTALL)
|
||||
class html2html(object):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from makohtml2html import parseNode
|
||||
from .makohtml2html import parseNode
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import logging
|
||||
import mako
|
||||
from lxml import etree
|
||||
from mako.template import Template
|
||||
from mako.lookup import TemplateLookup
|
||||
import os
|
||||
|
||||
import mako
|
||||
from mako.lookup import TemplateLookup
|
||||
from mako.template import Template
|
||||
from lxml import etree
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class makohtml2html(object):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odt2odt import parseNode
|
||||
from .odt2odt import parseNode
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.report.render.rml2pdf import utils
|
||||
import copy
|
||||
|
||||
from openerp.report.render.rml2pdf import utils
|
||||
|
||||
class odt2odt(object):
|
||||
def __init__(self, odt, localcontext):
|
||||
self.localcontext = localcontext
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import render
|
||||
import rml2pdf
|
||||
import rml2html as htmlizer
|
||||
import rml2txt as txtizer
|
||||
import odt2odt as odt
|
||||
import html2html as html
|
||||
import makohtml2html as makohtml
|
||||
from . import render
|
||||
from . import rml2pdf
|
||||
from . import rml2html as htmlizer
|
||||
from . import rml2txt as txtizer
|
||||
from . import odt2odt as odt
|
||||
from . import html2html as html
|
||||
from . import makohtml2html as makohtml
|
||||
|
||||
|
||||
class rml(render.render):
|
||||
@@ -18,10 +18,10 @@ class rml(render.render):
|
||||
self.output_type = 'pdf'
|
||||
self.title=title
|
||||
|
||||
|
||||
def _render(self):
|
||||
return rml2pdf.parseNode(self.rml, self.localcontext, images=self.bin_datas, path=self.path,title=self.title)
|
||||
|
||||
|
||||
class rml2html(render.render):
|
||||
def __init__(self, rml,localcontext = None, datas=None):
|
||||
super(rml2html, self).__init__(datas)
|
||||
@@ -32,6 +32,7 @@ class rml2html(render.render):
|
||||
def _render(self):
|
||||
return htmlizer.parseString(self.rml,self.localcontext)
|
||||
|
||||
|
||||
class rml2txt(render.render):
|
||||
def __init__(self, rml, localcontext= None, datas=None):
|
||||
super(rml2txt, self).__init__(datas)
|
||||
@@ -42,6 +43,7 @@ class rml2txt(render.render):
|
||||
def _render(self):
|
||||
return txtizer.parseString(self.rml, self.localcontext)
|
||||
|
||||
|
||||
class odt2odt(render.render):
|
||||
def __init__(self, rml, localcontext=None, datas=None):
|
||||
render.render.__init__(self, datas)
|
||||
@@ -52,6 +54,7 @@ class odt2odt(render.render):
|
||||
def _render(self):
|
||||
return odt.parseNode(self.rml_dom,self.localcontext)
|
||||
|
||||
|
||||
class html2html(render.render):
|
||||
def __init__(self, rml, localcontext=None, datas=None):
|
||||
render.render.__init__(self, datas)
|
||||
@@ -62,6 +65,7 @@ class html2html(render.render):
|
||||
def _render(self):
|
||||
return html.parseString(self.rml_dom,self.localcontext)
|
||||
|
||||
|
||||
class makohtml2html(render.render):
|
||||
def __init__(self, html, localcontext = None):
|
||||
render.render.__init__(self)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from rml2html import parseString
|
||||
from .rml2html import parseString
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import sys
|
||||
import cStringIO
|
||||
from lxml import etree
|
||||
import copy
|
||||
import cStringIO
|
||||
import sys
|
||||
|
||||
from lxml import etree
|
||||
|
||||
from openerp.report.render.rml2pdf import utils
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from trml2pdf import parseString, parseNode
|
||||
from .trml2pdf import parseString, parseNode
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from reportlab.lib import colors
|
||||
import re
|
||||
|
||||
from reportlab.lib import colors
|
||||
|
||||
allcols = colors.getAllNamedColors()
|
||||
|
||||
regex_t = re.compile('\(([0-9\.]*),([0-9\.]*),([0-9\.]*)\)')
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from reportlab import rl_config
|
||||
import logging
|
||||
import glob
|
||||
import logging
|
||||
import os
|
||||
|
||||
from reportlab import rl_config
|
||||
|
||||
# .apidoc title: TTF Font Table
|
||||
|
||||
"""This module allows the mapping of some system-available TTF fonts to
|
||||
|
||||
@@ -1,27 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
|
||||
import sys
|
||||
import copy
|
||||
import reportlab
|
||||
import re
|
||||
from reportlab.pdfgen import canvas
|
||||
from reportlab import platypus
|
||||
import utils
|
||||
import color
|
||||
import os
|
||||
import logging
|
||||
import traceback
|
||||
from lxml import etree
|
||||
import base64
|
||||
import copy
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
from distutils.version import LooseVersion
|
||||
from reportlab.platypus.doctemplate import ActionFlowable
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
from reportlab.lib.units import inch,cm,mm
|
||||
from openerp.tools.misc import file_open
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.lib.pagesizes import A4, letter
|
||||
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
@@ -29,8 +16,21 @@ try:
|
||||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
|
||||
import reportlab
|
||||
from reportlab import platypus
|
||||
from reportlab.lib.pagesizes import A4, letter
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfgen import canvas
|
||||
from reportlab.platypus.doctemplate import ActionFlowable
|
||||
from lxml import etree
|
||||
|
||||
from openerp.tools.misc import file_open
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
from . import color
|
||||
from . import utils
|
||||
|
||||
try:
|
||||
from customfonts import SetCustomFonts
|
||||
from .customfonts import SetCustomFonts
|
||||
except ImportError:
|
||||
SetCustomFonts=lambda x:None
|
||||
|
||||
@@ -271,7 +271,6 @@ class _rml_doc(object):
|
||||
|
||||
def setTTFontMapping(self,face, fontname, filename, mode='all'):
|
||||
from reportlab.lib.fonts import addMapping
|
||||
from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
|
||||
if mode:
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
|
||||
import copy
|
||||
import locale
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
import reportlab
|
||||
|
||||
import openerp.tools as tools
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from rml2txt import parseString, parseNode
|
||||
from .rml2txt import parseString, parseNode
|
||||
|
||||
|
||||
""" This engine is the minimalistic renderer of RML documents into text files,
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
|
||||
import sys
|
||||
import StringIO
|
||||
|
||||
from lxml import etree
|
||||
|
||||
import utils
|
||||
from . import utils
|
||||
|
||||
Font_size= 10.0
|
||||
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
|
||||
import copy
|
||||
import re
|
||||
|
||||
import reportlab
|
||||
import reportlab.lib.units
|
||||
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
|
||||
_regex = re.compile('\[\[(.+?)\]\]')
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import render
|
||||
|
||||
from cStringIO import StringIO
|
||||
import copy
|
||||
import xml.dom.minidom
|
||||
from cStringIO import StringIO
|
||||
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table
|
||||
import reportlab.lib
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph
|
||||
from reportlab.lib.units import mm
|
||||
from reportlab.lib.pagesizes import A4
|
||||
import reportlab.lib
|
||||
|
||||
import copy
|
||||
from . import render
|
||||
|
||||
|
||||
class simple(render.render):
|
||||
def _render(self):
|
||||
|
||||
@@ -1,27 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from lxml import etree
|
||||
import StringIO
|
||||
import cStringIO
|
||||
|
||||
import base64
|
||||
from datetime import datetime
|
||||
import cStringIO
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import StringIO
|
||||
import time
|
||||
from interface import report_rml
|
||||
import preprocess
|
||||
import logging
|
||||
import openerp.tools as tools
|
||||
import zipfile
|
||||
import common
|
||||
from openerp.exceptions import AccessError
|
||||
from datetime import datetime
|
||||
|
||||
from lxml import etree
|
||||
|
||||
import openerp
|
||||
from openerp import SUPERUSER_ID
|
||||
import openerp.tools as tools
|
||||
from . import common
|
||||
from . import preprocess
|
||||
from .interface import report_rml
|
||||
from openerp.exceptions import AccessError
|
||||
from openerp.osv.fields import float as float_field, function as function_field, datetime as datetime_field
|
||||
from openerp.tools.translate import _
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.tools.safe_eval import safe_eval
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -59,11 +61,11 @@ def get_date_length(date_format=DEFAULT_SERVER_DATE_FORMAT):
|
||||
class rml_parse(object):
|
||||
def __init__(self, cr, uid, name, parents=rml_parents, tag=rml_tag, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
context = {}
|
||||
self.cr = cr
|
||||
self.uid = uid
|
||||
self.pool = openerp.registry(cr.dbname)
|
||||
user = self.pool['res.users'].browse(cr, uid, uid, context=context)
|
||||
env = openerp.api.Environment(cr, uid, context)
|
||||
user = env['res.users'].browse(uid)
|
||||
self.localcontext = {
|
||||
'user': user,
|
||||
'setCompany': self.setCompany,
|
||||
@@ -93,7 +95,7 @@ class rml_parse(object):
|
||||
self.lang_dict = {}
|
||||
self.default_lang = {}
|
||||
self.lang_dict_called = False
|
||||
self._transl_regex = re.compile('(\[\[.+?\]\])')
|
||||
self._transl_regex = re.compile(r'(\[\[.+?\]\])')
|
||||
|
||||
def setTag(self, oldtag, newtag, attrs=None):
|
||||
return newtag, attrs
|
||||
@@ -123,19 +125,19 @@ class rml_parse(object):
|
||||
def removeParentNode(self, tag=None):
|
||||
raise GeneratorExit('Skip')
|
||||
|
||||
def set_html_image(self,id,model=None,field=None,context=None):
|
||||
if not id :
|
||||
def set_html_image(self, id, model=None, field=None, context=None):
|
||||
if not id:
|
||||
return ''
|
||||
if not model:
|
||||
model = 'ir.attachment'
|
||||
try :
|
||||
id = int(id)
|
||||
res = self.pool[model].read(self.cr,self.uid,id)
|
||||
if field :
|
||||
try:
|
||||
env = openerp.api.Environment(self.cr, self.uid, {})
|
||||
res = env[model].browse(int(id)).read()[0]
|
||||
if field:
|
||||
return res[field]
|
||||
elif model =='ir.attachment' :
|
||||
elif model =='ir.attachment':
|
||||
return res['datas']
|
||||
else :
|
||||
else:
|
||||
return ''
|
||||
except Exception:
|
||||
return ''
|
||||
@@ -148,13 +150,14 @@ class rml_parse(object):
|
||||
self.objects = self.objects.with_env(env)
|
||||
|
||||
def _get_lang_dict(self):
|
||||
pool_lang = self.pool['res.lang']
|
||||
env = openerp.api.Environment(self.cr, self.uid, {})
|
||||
Lang = env['res.lang']
|
||||
lang = self.localcontext.get('lang', 'en_US') or 'en_US'
|
||||
lang_ids = pool_lang.search(self.cr,self.uid,[('code','=',lang)])
|
||||
if not lang_ids:
|
||||
lang_ids = pool_lang.search(self.cr,self.uid,[('code','=','en_US')])
|
||||
lang_obj = pool_lang.browse(self.cr,self.uid,lang_ids[0])
|
||||
self.lang_dict.update({'lang_obj':lang_obj,'date_format':lang_obj.date_format,'time_format':lang_obj.time_format})
|
||||
lang_obj = Lang.search([('code', '=', lang)], limit=1) or \
|
||||
Lang.search([('code', '=', 'en_US')])
|
||||
self.lang_dict.update({'lang_obj': lang_obj,
|
||||
'date_format': lang_obj.date_format,
|
||||
'time_format':lang_obj.time_format})
|
||||
self.default_lang[lang] = self.lang_dict.copy()
|
||||
return True
|
||||
|
||||
@@ -165,10 +168,10 @@ class rml_parse(object):
|
||||
def get_digits(self, obj=None, f=None, dp=None):
|
||||
d = DEFAULT_DIGITS = 2
|
||||
if dp:
|
||||
decimal_precision_obj = self.pool['decimal.precision']
|
||||
d = decimal_precision_obj.precision_get(self.cr, self.uid, dp)
|
||||
env = openerp.api.Environment(self.cr, self.uid, {})
|
||||
d = env['decimal.precision'].precision_get(dp)
|
||||
elif obj and f:
|
||||
res_digits = getattr(obj._columns[f], 'digits', lambda x: ((16, DEFAULT_DIGITS)))
|
||||
res_digits = getattr(obj._fields[f], 'digits', lambda x: ((16, DEFAULT_DIGITS)))
|
||||
if isinstance(res_digits, tuple):
|
||||
d = res_digits[1]
|
||||
else:
|
||||
@@ -243,13 +246,14 @@ class rml_parse(object):
|
||||
def _translate(self,text):
|
||||
lang = self.localcontext['lang']
|
||||
if lang and text and not text.isspace():
|
||||
transl_obj = self.pool['ir.translation']
|
||||
env = openerp.api.Environment(self.cr, self.uid, {})
|
||||
Translation = env['ir.translation']
|
||||
piece_list = self._transl_regex.split(text)
|
||||
for pn in range(len(piece_list)):
|
||||
if not self._transl_regex.match(piece_list[pn]):
|
||||
source_string = piece_list[pn].replace('\n', ' ').strip()
|
||||
if len(source_string):
|
||||
translated_string = transl_obj._get_source(self.cr, self.uid, self.name, ('report', 'rml'), lang, source_string)
|
||||
translated_string = Translation._get_source(self.name, ('report', 'rml'), lang, source_string)
|
||||
if translated_string:
|
||||
piece_list[pn] = piece_list[pn].replace(source_string, translated_string)
|
||||
text = ''.join(piece_list)
|
||||
@@ -273,7 +277,7 @@ class rml_parse(object):
|
||||
found.getparent().replace(found,tag)
|
||||
return True
|
||||
|
||||
def set_context(self, objects, data, ids, report_type = None):
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
self.localcontext['data'] = data
|
||||
self.localcontext['objects'] = objects
|
||||
self.localcontext['digits_fmt'] = self.digits_fmt
|
||||
@@ -296,6 +300,7 @@ class rml_parse(object):
|
||||
# will have to call setCompany() inside the main repeatIn loop.
|
||||
self.setCompany(objects[0].company_id)
|
||||
|
||||
|
||||
class report_sxw(report_rml, preprocess.report):
|
||||
"""
|
||||
The register=True kwarg has been added to help remove the
|
||||
@@ -319,8 +324,8 @@ class report_sxw(report_rml, preprocess.report):
|
||||
self.internal_header=True
|
||||
|
||||
def getObjects(self, cr, uid, ids, context):
|
||||
table_obj = openerp.registry(cr.dbname)[self.table]
|
||||
return table_obj.browse(cr, uid, ids, context=context)
|
||||
env = openerp.api.Environment(cr, uid, context or {})
|
||||
return env[self.table].browse(ids)
|
||||
|
||||
def create(self, cr, uid, ids, data, context=None):
|
||||
context = dict(context or {})
|
||||
@@ -329,15 +334,12 @@ class report_sxw(report_rml, preprocess.report):
|
||||
|
||||
# skip osv.fields.sanitize_binary_value() because we want the raw bytes in all cases
|
||||
context.update(bin_raw=True)
|
||||
registry = openerp.registry(cr.dbname)
|
||||
ir_obj = registry['ir.actions.report.xml']
|
||||
registry['res.font'].font_scan(cr, SUPERUSER_ID, lazy=True, context=context)
|
||||
env = openerp.api.Environment(cr, uid, context)
|
||||
env['res.font'].sudo().font_scan(lazy=True)
|
||||
ir_obj = env['ir.actions.report.xml']
|
||||
|
||||
report_xml_ids = ir_obj.search(cr, uid,
|
||||
[('report_name', '=', self.name[7:])], context=context)
|
||||
if report_xml_ids:
|
||||
report_xml = ir_obj.browse(cr, uid, report_xml_ids[0], context=context)
|
||||
else:
|
||||
report_xml = ir_obj.search([('report_name', '=', self.name[7:])], limit=1)
|
||||
if not report_xml:
|
||||
title = ''
|
||||
report_file = tools.file_open(self.tmpl, subdir=None)
|
||||
try:
|
||||
@@ -384,8 +386,8 @@ class report_sxw(report_rml, preprocess.report):
|
||||
|
||||
def create_source_pdf(self, cr, uid, ids, data, report_xml, context=None):
|
||||
if not context:
|
||||
context={}
|
||||
registry = openerp.registry(cr.dbname)
|
||||
context = {}
|
||||
env = openerp.api.Environment(cr, uid, context)
|
||||
attach = report_xml.attachment
|
||||
if attach:
|
||||
objs = self.getObjects(cr, uid, ids, context)
|
||||
@@ -394,12 +396,11 @@ class report_sxw(report_rml, preprocess.report):
|
||||
aname = safe_eval(attach, {'object':obj, 'time':time})
|
||||
result = False
|
||||
if report_xml.attachment_use and aname and context.get('attachment_use', True):
|
||||
aids = registry['ir.attachment'].search(cr, uid, [('datas_fname','=',aname+'.pdf'),('res_model','=',self.table),('res_id','=',obj.id)])
|
||||
if aids:
|
||||
brow_rec = registry['ir.attachment'].browse(cr, uid, aids[0])
|
||||
if not brow_rec.datas:
|
||||
att = env['ir.attachment'].search([('datas_fname','=',aname+'.pdf'),('res_model','=',self.table),('res_id','=',obj.id)], limit=1)
|
||||
if att:
|
||||
if not att.datas:
|
||||
continue
|
||||
d = base64.decodestring(brow_rec.datas)
|
||||
d = base64.decodestring(att.datas)
|
||||
results.append((d,'pdf'))
|
||||
continue
|
||||
result = self.create_single_pdf(cr, uid, [obj.id], data, report_xml, context)
|
||||
@@ -414,14 +415,13 @@ class report_sxw(report_rml, preprocess.report):
|
||||
# field.
|
||||
ctx = dict(context)
|
||||
ctx.pop('default_type', None)
|
||||
registry['ir.attachment'].create(cr, uid, {
|
||||
env['ir.attachment'].with_context(ctx).create({
|
||||
'name': aname,
|
||||
'datas': base64.encodestring(result[0]),
|
||||
'datas_fname': name,
|
||||
'res_model': self.table,
|
||||
'res_id': obj.id,
|
||||
}, context=ctx
|
||||
)
|
||||
})
|
||||
except AccessError:
|
||||
#TODO: should probably raise a proper osv_except instead, shouldn't we? see LP bug #325632
|
||||
_logger.info('Could not create saved report attachment', exc_info=True)
|
||||
|
||||
Reference in New Issue
Block a user