Commit 609ae0a7 authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

Remove the plugin_report since it is much simpler to use inline script

and Ext.grid.Panel
parent 23b41790
""" plugin_reports controllers
"""
import traceback
from plugin_report import MySelector, Report
def index():
""" Generate report(s) according to sqltable definition
and selector requirement (experimental).
Handle the following URLs:
application/plugin_report/index
application/plugin_report/index?id_report_objects=2
"""
# get user requirements from the selector widget
selector_name = plugins.report.selector_name
selector = MySelector(virtdb[selector_name])
# the configuration of the table can be chosen via the URL
if request.vars.id_report_objects:
selector.id_report_objects = request.vars.id_report_objects
# instantiate the report and link it to a selector
report = Report(selector)
# build the report content
try:
report()
except BaseException, e:
msg = '<br><br><hr/>'
msg += CODE(traceback.format_exc()).xml()
msg += '<hr/>'
return msg
# give the hand to the view for the rendering
return dict(report=report)
......@@ -183,7 +183,6 @@
'List of trainee': 'Liste des stagiaires',
'Liste': 'Liste',
'Lists': 'Listes',
'Lists (inline)': 'Lists (inline)',
'Logged in': 'Logged in',
'Login': 'Login',
'Logout': 'Logout',
......@@ -252,12 +251,9 @@
'Registration identifier': 'Registration identifier',
'Registration key': 'Registration key',
'Registration successful': 'Registration successful',
'report_configurations': 'report_configurations',
'report_functions': 'report_functions',
'report_objects': 'report_objects',
'report_virtualfields': 'report_virtualfields',
'Reports': 'Rapports',
'reports_virtualfields': 'reports_virtualfields',
'Reports (new)': 'Rapports (new)',
'Reports (old)': 'Rapports (old)',
'Reset Password key': 'Reset Password key',
'responsibilities': 'responsabilités',
'Responsibility': 'Responsabilité',
......
......@@ -62,9 +62,6 @@ tables = ['auth_group',
'people',
'people_categories',
'projects',
'report_objects',
'report_functions',
'report_virtualfields',
'teams',
'views']
......
# -*- coding: utf-8 -*-
""" plugin_report
Define the plugin constants
Define the database tables to configure the reports.
Customize the table interface
"""
from plugin_report import SET_NAME
#-------------------------------------------------------------------------------
#
# PLUGIN CONSTANTS -- Default value
#
#-------------------------------------------------------------------------------
plugins = PluginManager('report',
selector_name="my_list_selector")
#-------------------------------------------------------------------------------
#
# TABLES
#
#-------------------------------------------------------------------------------
#
# report_functions
#
func_code = "def repr_xxx(value, row):\n"\
" return value\n"
db.define_table("report_functions",
Field("function", "string", length=255, default= "repr_xxx", notnull=True, unique=True),
Field("python_code", "text", default=func_code),
Field("tests", "text", notnull=True, default='Not yet implemented'),
migrate="report_functions.table")
db.report_functions._before_insert.append(SET_NAME("function"))
db.report_functions._before_update.append(SET_NAME("function"))
#
# report_objects
#
tp_alignments = \
T("Dictionary associating a column and its alignment (left, center, right). "
"The key is a column name encoded as tablename.fieldname ")
tp_columns = \
T("List of column to be displayed in the table. "
"The column is identified by its name encoded as 'tablename.fieldname. "
"The column can contains a virtual field 'tablename.virtualfield. "
"The function associated to the virtual field has to be defined in "
"the database table report_virtual_fields. "
"The column can contains the operator AVG, COUNT, MIN, MAX and SUM. "
"In that case the syntax is operator(tablename.fieldname. "
"The operator make sense with the group by directive. ")
tp_conditions = \
T("Can be applied on any field of the table using the SQL WHERE syntax. "
"Be aware that foreign key are not resolved "
"(more information in the smart_query in the web2py documentation).")
tp_formats = \
T("Dictionary associating the column and the function "
"used to represent the field. "
"The key is a column name encoded as tablename.fieldname "
"or operator(tablename.fieldname) ."
"The value is a name of the function defined in the table report_functions.")
tp_groupby = \
T("List of columns defining the group by directive. "
"The column is encode as 'tablename.fiedlname. ")
tp_labels = \
T("Dictionary associating the column name with the column label. "
"The key is a column name encoded as tablename.fieldname. "
"The value is a string.")
tp_name = T("Name of the object.")
tp_orderby = \
T("List of columns defining the order by directive. "
"The column is identified by its name encoded as tablename.fieldname. "
"Descending order are obtained using the syntax ~tablename.fieldname.")
tp_table = \
T("Name of the database table which will be displayed in the report. "
"Any fields of this table can be shown including foreign fields.")
tp_totals = \
T("List of columns appearing in the total row. "
"The column names are encoded as 'tablename.fieldname' "
"or 'operator(tablename.fieldname)'. ")
db.define_table("report_objects",
Field("name", "string", length=255, notnull=True, unique=True, comment=tp_name),
Field("type", "string", length=255, notnull=True, default='sqltable'),
Field("tablename", "string", length=255, notnull=True, comment=tp_table),
Field("conditions", "text", comment=tp_conditions),
Field("columns", "list:string", notnull=True, comment=tp_columns),
Field("labels", "json", comment=tp_labels),
Field("formats", "json", comment=tp_formats),
Field("alignments", "json", comment=tp_alignments),
Field("orderby", "list:string", comment=tp_orderby),
Field("groupby", "list:string", comment=tp_groupby),
Field("totals", "list:string", comment=tp_totals),
Field("note", "text"),
migrate="report_objects.table")
db.report_objects.tablename.requires = IS_IN_SET(db.tables())
db.report_objects.type.requires = IS_IN_SET(('sqltable',))
# NOTE in web2py 2.4.6 the validator for JSON field is not working
db.report_objects.alignments.requires = None
db.report_objects.formats.requires = None
db.report_objects.labels.requires = None
#
# report_virtualfields
#
virtualfield_code = "def xxx(row):\n"\
" return None\n"
db.define_table("report_virtualfields",
Field("field", "string", length=255, default="xxx", notnull=True, unique=True),
Field("python_code", "text", default=virtualfield_code),
Field("tests", "text", notnull=True, default='Not yet implemented'),
migrate="report_virtualfields.table")
db.report_virtualfields._before_insert.append(SET_NAME("field"))
db.report_virtualfields._before_update.append(SET_NAME("field"))
#-------------------------------------------------------------------------------
#
# FIELDS
#
#-------------------------------------------------------------------------------
#
# report_functions
#
fieldsModifier = dbui.FieldsModifier('report_functions')
fieldsModifier.configure_field('function', hidden=True)
fieldsModifier.configure_field('python_code',
height=230,
hideLabel=True,
xtype='xaceeditorfield')
fieldsModifier.configure_field('tests', hidden=True)
#
# report_objects
#
fieldsModifier = dbui.FieldsModifier('report_objects')
fieldsModifier.configure_field('columns',
header='tablename.fieldname',
height=197,
hideLabel=True,
minimumRows=8)
fieldsModifier.configure_field('conditions', height=120)
fieldsModifier.configure_field('labels',
dictCfg={},
headers=['tablename.fieldname', 'label'],
height=197,
hideLabel=True,
modifyKeys=True)
fieldsModifier.configure_field('formats',
dictCfg={},
headers=['tablename.fieldname', 'function'],
height=197,
hideLabel=True,
modifyKeys=True)
fieldsModifier.configure_field('alignments',
dictCfg={},
headers=['tablename.fieldname', 'alignment'],
height=197,
hideLabel=True,
modifyKeys=True)
fieldsModifier.configure_field('orderby',
header='tablename.fieldname',
height=197,
hideLabel=True,
minimumRows=8)
fieldsModifier.configure_field('groupby',
header='tablename.fieldname',
height=197,
hideLabel=True,
minimumRows=8)
fieldsModifier.configure_field('totals',
header='tablename.fieldname',
height=197,
hideLabel=True,
minimumRows=8)
fieldsModifier.configure_field('note',
height=197,
hideLabel=True)
#
# report_virtualfields
#
fieldsModifier = dbui.FieldsModifier('report_virtualfields')
fieldsModifier.configure_field('field', hidden=True)
fieldsModifier.configure_field('python_code',
height=230,
hideLabel=True,
xtype='xaceeditorfield')
fieldsModifier.configure_field('tests', hidden=True)
#-------------------------------------------------------------------------------
#
# FORMS
#
#-------------------------------------------------------------------------------
#
# report_functions
#
formModifier = dbui.FormModifier('report_functions')
formModifier.configure(buttonAlign='right',
width=605,
height=300)
#
# report_objects
#
formModifier = dbui.FormModifier('report_objects')
formModifier.merge_fields('name',
'type',
'tablename',
'conditions',
title=T('General'))
formModifier.merge_fields('columns',
title=T('Columns'))
formModifier.merge_fields('labels',
title=T('Labels'))
formModifier.merge_fields('formats',
title=T('Formats'))
formModifier.merge_fields('alignments',
title=T('Alignments'))
formModifier.merge_fields('orderby',
title=T('Order by'))
formModifier.merge_fields('groupby',
title=T('Group by'))
formModifier.merge_fields('totals',
title=T('Total Row'))
formModifier.merge_fields('note',
title=T('Note'))
formModifier.set_mapper(dbui.map_tabpanel)
formModifier.configure(buttonAlign='right',
labelWidth=70,
labelAlign='left',
width=400)
#
# report_virtualfields
#
formModifier = dbui.FormModifier('report_virtualfields')
formModifier.configure(buttonAlign='right',
width=605,
height=300)
#-------------------------------------------------------------------------------
#
# GRIDS
#
#-------------------------------------------------------------------------------
#
# report_functions
#
gridModifier = dbui.GridModifier('report_functions')
gridModifier.hide_columns('python_code', 'tests')
#
# report_objects
#
gridModifier = dbui.GridModifier('report_objects')
gridModifier.configure_column('tablename', width=30)
gridModifier.configure_column('type', width=30)
gridModifier.hide_columns('alignments',
'columns',
'formats',
'groupby',
'labels',
'orderby',
'totals')
#
# report_virtualfields
#
gridModifier = dbui.GridModifier('report_virtualfields')
gridModifier.hide_columns('python_code', 'tests')
#-------------------------------------------------------------------------------
#
# STORES
#
#-------------------------------------------------------------------------------
......@@ -32,9 +32,7 @@ if "auth" in globals():
cfgListNode = Node(T('Configure lists'))
cfgListNode.add_child(T('events'), to_grid('events'))
cfgListNode.add_child(T('report_objects'), to_grid('report_objects'))
cfgListNode.add_child(T('report_functions'), to_grid('report_functions'))
cfgListNode.add_child(T('report_virtualfields'), to_grid('report_virtualfields'))
cfgListNode.add_child(T('Configure views'), to_grid('views'))
#-------------------------------------------------------------------------------
#
......@@ -89,11 +87,10 @@ helpNode.sort_children()
#-------------------------------------------------------------------------------
#
# LIST NODE (NEW APPROACH BASE ON IONLINE SCRIPT -- 2014)
# REPORT NODE (NEW APPROACH BASE ON IONLINE SCRIPT -- 2014)
#
#-------------------------------------------------------------------------------
listNode2 = Node(T('Lists (inline)'))
listNode2.add_child(T('Configure views'), to_grid('views'))
reportNode2 = Node(T('Reports (new)'))
# add the lists defined in the database
for row in db(db.views.id > 0).select():
......@@ -103,7 +100,7 @@ for row in db(db.views.id > 0).select():
baseParams={'id_views': row.id},
extField='format')
listNode2.add_child(row.view, leaf)
reportNode2.add_child(row.view, leaf)
# add the metric
leaf1 = PanelWithUrlSelector(virtdb.metric_selector,
......@@ -122,34 +119,15 @@ leaf4 = PanelWithUrlSelector(virtdb.metric_selector,
baseParams={'group': 'people_categories.code'},
baseUrl=URL('list2', 'metric_per_year'))
listNode2.add_child(T('Metrics / category'), leaf1)
listNode2.add_child(T('Metrics / quality'), leaf2)
listNode2.add_child(T('Metric / year / category'), leaf3)
listNode2.add_child(T('Metric / year / quality'), leaf4)
listNode2.sort_children()
reportNode2.add_child(T('Metrics / category'), leaf1)
reportNode2.add_child(T('Metrics / quality'), leaf2)
reportNode2.add_child(T('Metric / year / category'), leaf3)
reportNode2.add_child(T('Metric / year / quality'), leaf4)
reportNode2.sort_children()
#-------------------------------------------------------------------------------
#
# LIST NODE (NEW APPROACH FOR REPORTING -- 2013)
#
#-------------------------------------------------------------------------------
listNode = Node(T('Lists'))
url = URL('plugin_report', 'index')
for row in db(db.report_objects.id > 0).select():
leaf = PanelWithUrlSelector(virtdb.my_list_selector,
baseUrl=url,
baseParams={'id_report_objects': row.id},
extField='format')
listNode.add_child(row.name, leaf)
listNode.sort_children()
#-------------------------------------------------------------------------------
#
# REPORT NODE
# REPORT NODE (OBSOLETE)
#
#-------------------------------------------------------------------------------
hardwareLeaf = PanelWithUrlSelector(virtdb.hardware_selector,
......@@ -184,7 +162,7 @@ peopleTeamLeaf = PanelWithUrlSelector(virtdb.people_selector,
baseUrl=URL('metric', 'people_per_team'),
extField='format')
reportNode = dbui.Node(T('Reports'))
reportNode = dbui.Node(T('Reports (old)'))
reportNode.add_child(T('List'), listLeaf)
reportNode.add_child(T('List of hardware'), hardwareLeaf)
reportNode.add_child(T('List of people'), listPeopleLeaf)
......@@ -224,8 +202,7 @@ nodes = [helpNode,
cfgTeamNode,
wizardNode,
dataPeopleNode,
listNode2,
listNode,
reportNode2,
reportNode]
viewportModifier = dbui.ViewportModifier()
......
"""
@author: R.Le Gac
"""
from callbacks import (SET_NAME)
from report import (decode_column,
ExtractAndFormat,
MySelector,
Report,
sandbox,
SelectorActiveItems)
\ No newline at end of file
""" collection of callbacks for the database tables defining the reports.
@author: R. Le Gac
"""
import re
from gluon import current
from plugin_dbui import CALLBACK_ERRORS
class SET_NAME(object):
"""Callback to set the value of a field is equal to the name
of the function defined in the field python_code.
@note: It can be used with insert and update operation.
"""
def __init__(self, fieldname):
"""
@type fieldname: str
@param fieldname: the name of the field which will receive
the name of the python function.
"""
self._db = current.globalenv['db']
self._fieldname = fieldname
self._T = current.T
def __call__(self, *args, **kwargs):
"""The arguments depends on the insert and update action.
"""
db, T = self._db, self._T
# the position of the dictionary containing the value depends on
# the operation 0 for insert, 1 for update
index = len(args) -1
# python code is not modified -- exit
if not (args and 'python_code' in args[index]):
return False
# protection
f_code = args[index]['python_code'].strip()
if not f_code.startswith('def'):
db.report_functions[CALLBACK_ERRORS] = \
T("The python code does not correspond to a function !")
return True
# get the name of the function
m = re.match('def +([a-zA-Z0-9_]+) *\(', f_code)
if not m:
db.report_functions[CALLBACK_ERRORS] = \
T("Can't extract the name of the %s from the code !" % self._fieldname)
return True
args[index][self._fieldname] = m.group(1)
return False
\ No newline at end of file
This diff is collapsed.
--------------------------------- CHANGE LOG ----------------------------------
HEAD
- Migrate to plugin_dbui 0.6.1.0 and Web2py 2.9.5.
- Migrate to plugin_dbui 0.6.1.6 and Web2py 2.9.5.
- Define the length of each string field to garanty Web2py compatibility.
- Use the controllers plugin_dbui/about, documentations and versions.
- Implement new reporting tools based on the javascrip inline script
technique, the Ext.grid.Panel widget and on the views database table.
- Remove the reporting tools based on the plugin_report which is much
more complicated with respect to the new approach.
05d5393 (Mar 14)
- Migrate to plugin_dbui 0.6.0.18 and ExtJS 4.2.1
......
{{
import traceback
from plugin_report import decode_column, ExtractAndFormat
#--------------------------------------------------------------------------
#
# Helper functions
#
#--------------------------------------------------------------------------
def align_column(table, icol, value):
"""Align the column.
@type table: gluon.sqlhtml.SQLTABLE
@param table: the table object.
@type icol: int
@param icol: the index of the column to be aligned.
@type value: str
@param value: one of the value center, left or right.
"""
for el in table.elements('tr'):
row = el.components
if len(row) >= icol and row[icol].tag == 'td':
row[icol].attributes["_style"] = "text-align: %s;" % value
pass
pass
return
def repr_id(value):
"""Replace the history id by a number counting the number of row
Do not move to always start at 1