Commit 3bce7718 authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

First implementation of a new class Selector usefull for reporting.

parent 92c528ef
""" $Id$ """
def index():
"""Main Controller handling report.
return 'Report section'
def articles():
"""Return the URL arguments
s = ""
for k in request.vars:
s += "<br>%s: %s" % (k, request.vars[k])
return '<h3>report_2</h3>'+s
\ No newline at end of file
""" List controllers """
from reporting_tools import Selector
def hardware():
""" Active hardware for a given period of time, team, ...
return 'hardware'
def index():
return 'List section'
def people():
"""Active people for a given period of time, team, ...
selector = Selector(db)
query = selector.query('history',
exclude_fields=('period_start', 'period_end'))
# complete the query to select active period during the date range
print query
# select the record
print db(query).select()
return str(selector)
\ No newline at end of file
......@@ -30,9 +30,11 @@
'Filter responsibilities': 'Filter les responsabilities',
'Filter teams': 'Filtrer les équipes',
'First Name': 'Prénom',
'Format': 'Format',
'Forms': 'Formulaire',
'Grade': 'Grade',
'HDR': 'HDR',
'Hardware': 'Hardware',
'Hdr': 'Hdr',
'Hdr Date': 'Hdr Date',
'Hdr defense date': "Date de soutenace de l'hdr",
......@@ -41,6 +43,8 @@
'Last Name': 'Nom de famille',
'Level': 'Niveau',
'Line': 'Ligne',
'List of people': 'List of people',
'Lists': 'Lists',
'Max Records': 'Max Records',
'Model': 'Modèle',
'Name': 'Nom',
......@@ -48,8 +52,11 @@
'Notified': 'Notifié',
'Organization': 'Organisation',
'PHD': 'PHD',
'People': 'People',
'Percentage': 'Pourcentage',
'Period': 'Periode',
'Period End': 'Period End',
'Period Start': 'Period Start',
'Person': 'Persone',
'PhD': 'PhD',
'Phd': 'Phd',
......@@ -6,4 +6,45 @@
virtdb = DAL(None)
\ No newline at end of file
virtdb = DAL(None)
# hardware selector
Field('period_start', 'date'),
Field('period_end', 'date'),
Field('id_people', db.people, label='Person'),
Field('id_teams', db.teams, label='Team'),
Field('id_projects', db.projects, label='Project'),
Field('format', 'string', default='html'))
virtdb.hardware_selector.id_people.requires = \
IS_IN_DB(db, '', 'people.last_name')
virtdb.hardware_selector.id_projects.requires = \
IS_IN_DB(db, '', 'projects.project')
virtdb.hardware_selector.id_teams.requires = \
IS_IN_DB(db, '', '')
virtdb.hardware_selector.format.requires = IS_IN_SET(['html'])
# people selector
Field('period_start', 'date'),
Field('period_end', 'date'),
Field('id_teams', db.teams, label='Team'),
Field('id_projects', db.projects, label='Project'),
Field('format', 'string', default='html'))
virtdb.people_selector.id_projects.requires = \
IS_IN_DB(db, '', 'projects.project')
virtdb.people_selector.id_teams.requires = \
IS_IN_DB(db, '', '')
virtdb.people_selector.format.requires = IS_IN_SET(['html'])
......@@ -30,10 +30,18 @@ fieldsModifier.configure_field('hdr_flag', flex=0.1)
fieldsModifier.configure_field('hdr_date', flex=1)
fieldsModifier.merge_fields('hdr_flag', 'hdr_date', fieldLabel=T('Hdr'))
# people selector
fieldsModifier = dbui.FieldsModifier('people_selector')
fieldsModifier.configure_field('period_start', flex=1)
fieldsModifier.configure_field('period_end', flex=1)
fieldsModifier.merge_fields('period_start', 'period_end', fieldLabel=T('Period'))
# responsibilities
fieldsModifier = dbui.FieldsModifier('responsabilities')
fieldsModifier = dbui.FieldsModifier('responsibilities')
fieldsModifier.configure_field('start_date', flex=1)
fieldsModifier.configure_field('end_date', flex=1)
fieldsModifier.merge_fields('start_date', 'end_date', fieldLabel=T('Period'))
......@@ -9,6 +9,34 @@ gridNode = dbui.Node(T('Tables'))
configurator = lambda tablename: dbui.to_gridPanel(db[tablename])
gridNode.add_children(db.tables, func=configurator)
# the list node
fields = dbui.to_fields(virtdb.people_selector)
selector = dbui.FieldSet(items=fields,
url = '/'+request.application+'/list/people'
peopleNode = dbui.PanelWithUrlSelector(baseUrl=url,
fields = dbui.to_fields(virtdb.hardware_selector)
selector = dbui.FieldSet(items=fields,
url = '/'+request.application+'/list/hardware'
hardwareNode = dbui.PanelWithUrlSelector(baseUrl=url,
listNode = dbui.Node(T('Lists'))
listNode.add_child(T('Hardware'), hardwareNode)
listNode.add_child(T('People'), peopleNode)
# The tool node for the navigation tree
......@@ -24,4 +52,4 @@ toolNode.sort_children()
# The viewport with its navigation tree
viewportModifier = dbui.ViewportModifier()
viewportModifier.add_node(gridNode, toolNode)
viewportModifier.add_node(gridNode, listNode, toolNode)
"""reporting tools module
A collection of tools to build reports in controllers.
from gluon import current
from gluon.html import IFRAME, URL
from import Storage
from plugin_dbui import (decode_field,
class Selector(Storage):
"""Basic tool to build a report.
Decode the data send by the selector widget.
Build the query for a given table of the database.
def __init__(self, db, extfield='format'):
self._db = db
self._ext_field = extfield
self._extension = None
# Decode the current request
for key in current.request.vars:
t = decode_field(key)
if len(t) != 2 :
field = t[1]
if field == self._ext_field:
self._extension = current.request.vars[key]
elif field != 'id':
self[field] = current.request.vars[key]
def __str__(self):
li = []
for k in self.fields():
li.append('%s: %s' % (k, self[k]))
return '<br>'.join(li)
def download(self):
"""The report can be download and receive as a file with a given format.
this method initiate this process by return and IFRAME.
The IFRAME is used by the browser to download the file.
The file format is defined by one of the field of the list selector.
By default is it 'format'. It can be changed via the argument extfield
of the constructor.
The IFRAME contain and URL. it it the same as the one defined in the
current request (application/controller/function) but the extension
is defined by the format field.
In this process all data conversion are performed by the view.
if self._extension and self._extension != 'html':
# remove the field use to select the file format
# in order to avoid circular loop
for key in current.request.vars:
t = decode_field(key)
if self._ext_field in t:
del current.request.vars[key]
# The new URL is equal to the one defined in the current
# request but with the proper extension
url = URL(current.request.function, extension=self._extension,
# Return the IFRAME
# the browser will request the file locate at the URL of the IFRAME
# The IFRAME occupy all the space in the receiving container
# Useful for embedded pdf application.
return IFRAME(_frameborder=0,
return None
def fields(self):
"""Lists of fields defined in the selector.
li = []
for k in self:
if not k.startswith('_'):
return li
def query(self, tablename, exclude_fields=()):
"""Build the database query for the table tablename
including inner join for foreign key and selector constraints.
The extfield as well as fields in the exclude_fields tuple are
not take into account.
db = self._db
query = None
table = self._db[tablename]
# inner join for foreign keys
if is_table_with_foreign_fields(table):
for field in table:
if is_foreign_field(field):
k_table, k_field, k_id = get_foreign_field(field)
q = field == db[k_table][k_id]
if query:
query = (query) & (q)
query = q
# constraint from the selector
for fieldname in self.fields():
if not self[fieldname] or \
fieldname in exclude_fields or \
fieldname == self._ext_field:
q = db[tablename][fieldname] == self[fieldname]
if query:
query = (query) & (q)
query = q
return query
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment