Commit ff289164 authored by LE GAC Renaud's avatar LE GAC Renaud
Browse files

Merge branch 'master' into 'production'

Release 0.7.2

See merge request !34
parents 543a6cd8 e810b014
...@@ -2,16 +2,24 @@ ...@@ -2,16 +2,24 @@
"""plugin_event controllers """plugin_event controllers
""" """
import json
import traceback import traceback
import urllib import urllib
from datetime import datetime
from plugin_dbui import get_id
from plugin_event import (Graph, from plugin_event import (Graph,
List, List,
Metric2D, Metric2D,
ReportException, ReportException,
Source) Source)
MSG = T("%s entry(ies) modified in the history table. "
"DO NOT FORGET TO MODIFIED CONFIGURATION OF REPORT(s).")
MSG_CVT = T(" - Conversion error: %s.")
def grid(): def grid():
"""The list is rendered such as an ``Ext.grid.Panel`` widget. """The list is rendered such as an ``Ext.grid.Panel`` widget.
...@@ -103,3 +111,111 @@ def source(): ...@@ -103,3 +111,111 @@ def source():
response.view = "plugin_event/grid.html" response.view = "plugin_event/grid.html"
return dict(cfg_store=store, grid=grid, title=title) return dict(cfg_store=store, grid=grid, title=title)
def userModelConsistency():
""" A user data block is associated to each event.
It is configurable by the user and defined in the events table.
The definition of the user data block (model) and the content
of the history.data field have to be kept in synchronisation.
This job is done by this controller.
"""
# decode the request
changes = json.loads(request.vars.changes)
event = request.vars.fieldEvent
model = json.loads(request.vars.fieldData)
# build a map of the modified keys.
# each operation is a list containing (action, old key, new key).
# the action is equal to: add, destroy, update
#
# NOTE: add and delete action are handle via dictionary copy.
#
#
update_keys = {}
for action, oldkey, newkey in changes:
if action != "update":
continue
# simplify the case where key1 > key2 > key3 to key1 > key3
# remove the case where key1 > key2 > ... > key1
if update_keys:
ok = False
for k, v in update_keys.iteritems():
if oldkey == v:
update_keys[k] = newkey
ok = True
if k == newkey:
del update_keys[k]
break
if ok:
continue
# basic case
update_keys[oldkey] = newkey
# get the event id
id_event = get_id(db.events, event=event)
if id_event is None:
return
# set-up the default values dealing with data conversion
for key in model:
value = model[key]["value"]
vtype = model[key]["type"]
if value:
try:
if vtype == "boolean":
value = value.lower() in ("true", "vrai", "y", "yes", "1")
elif vtype == "date":
value = datetime.strptime(value, "%Y-%m-%d")
value = value.isoformat()
elif vtype == "float":
value = float(value)
elif vtype == "integer":
value = int(value)
if vtype == "string" and value[0] == "[" and value[-1] == "]":
# reference to a set, pick the first value as default
li = json.loads(value)
value = (li[0] if li else None)
elif vtype == "reference":
value = None
except ValueError as e:
return MSG_CVT % e
model[key]["value"] = value
# scan and modify the history table
# the delete of old key is implicit since they are not copied
query = db.history.id_events == id_event
rows = db(query).select()
for row in rows:
data = {}
rd = (row.data if isinstance(row.data, dict) else dict())
# copy existing key or add new key
for key in model:
data[key] = (rd[key] if key in rd else model[key]["value"])
# modify key name
for oldkey, newkey in update_keys.iteritems():
if oldkey in rd:
data[newkey] = rd[oldkey]
db(db.history.id == row.id).update(data=data)
return MSG % len(rows)
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
'': '', '': '',
'\nIt is possible to add new columns which are derived from existing ones using\n arithmetical expressions. Variables are column names while operator are:\n +, -, /, *, in, not in, &, |, and, or, etc. One assignment per line.\n For more details have a look to the function pandas.eval and to the\n method pandas.DataFrame.eval.\n': "Il est possible d'ajouter des colonnes définies à partir de celles existantes en utilsant des expressions arithmétiques. Les variables sont le nom des colonnes tandis que les opérateurs sont: +, -, /, *, in, not in, &, |, and, or, etc. Une assignation par ligne.\n Plus d'information dans la documentation de la fonction pandas.eval et celle de la méthode pandas.DataFrame.eval.", '\nIt is possible to add new columns which are derived from existing ones using\n arithmetical expressions. Variables are column names while operator are:\n +, -, /, *, in, not in, &, |, and, or, etc. One assignment per line.\n For more details have a look to the function pandas.eval and to the\n method pandas.DataFrame.eval.\n': "Il est possible d'ajouter des colonnes définies à partir de celles existantes en utilsant des expressions arithmétiques. Les variables sont le nom des colonnes tandis que les opérateurs sont: +, -, /, *, in, not in, &, |, and, or, etc. Une assignation par ligne.\n Plus d'information dans la documentation de la fonction pandas.eval et celle de la méthode pandas.DataFrame.eval.",
'\nIt is possible to filter the source by applying a query on its fields.\n Variables are column names while operator are: +, -, /, *, in, not in,\n &, |, and, or, etc. For more details have a look to the method\n pandas.DataFrame.query.\n': "Il est possible de filter la source en appliquant une requête sur ces champs. Les variables sont le nom des colonnes tandis que les opérateurs sont: +, -, /, *, in, not in,\n &, |, and, or, etc. Plus d'information dans la documentation de la méthode pandas.DataFrame.query.", '\nIt is possible to filter the source by applying a query on its fields.\n Variables are column names while operator are: +, -, /, *, in, not in,\n &, |, and, or, etc. For more details have a look to the method\n pandas.DataFrame.query.\n': "Il est possible de filter la source en appliquant une requête sur ces champs. Les variables sont le nom des colonnes tandis que les opérateurs sont: +, -, /, *, in, not in,\n &, |, and, or, etc. Plus d'information dans la documentation de la méthode pandas.DataFrame.query.",
' - %s entry(ies) modified in the history table.\n - DO NOT FORGET TO MODIFIED THE REPORT CONFIGURATION.': ' - %s entry(ies) modified in the history table.\n - DO NOT FORGET TO MODIFIED THE REPORT CONFIGURATION.',
' - %s entry(ies) modified in the history table. <br> - DO NOT FORGET TO MODIFIED THE REPORT CONFIGURATION.': " - %s entrée(s) modifiée(s) dans l'historique. <br> - N'OUBLIEZ PAS DE MODIFIER LES RAPPORTS.", ' - %s entry(ies) modified in the history table. <br> - DO NOT FORGET TO MODIFIED THE REPORT CONFIGURATION.': " - %s entrée(s) modifiée(s) dans l'historique. <br> - N'OUBLIEZ PAS DE MODIFIER LES RAPPORTS.",
' - Conversion error: %s.': ' - Erreur de conversion : %s.', ' - Conversion error: %s.': ' - Erreur de conversion : %s.',
'%s between %s and %s': '%s du %s au %s', '%s between %s and %s': '%s du %s au %s',
'%s entries modified in the history table.': "%s entrés ont été modifié dans l'historique.", '%s entry(ies) modified in the history table. DO NOT FORGET TO MODIFIED CONFIGURATION OF REPORT(s).': "%s enregistrement(s) ont été modifié(s) dans l'historique. N'oubliez pas de modifier la configuration des rapports.",
'%s in %s': '%s en %s', '%s in %s': '%s en %s',
'%Y-%m-%d': '%Y-%m-%d', '%Y-%m-%d': '%Y-%m-%d',
'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
...@@ -77,8 +78,8 @@ ...@@ -77,8 +78,8 @@
'Data base scheme': 'Schéma base de donnée', 'Data base scheme': 'Schéma base de donnée',
'Data model': 'Modèle des données', 'Data model': 'Modèle des données',
'Data people': 'Les données des personnes', 'Data people': 'Les données des personnes',
'Database schema': 'Schéma de la base de données',
'database schema': 'schéma de la base de données', 'database schema': 'schéma de la base de données',
'Database schema': 'Schéma de la base de données',
'Define a crude model for the data block associated to each event. The model contains a list of properties. A type is defined to each property or a default value. Valid types are boolean, date, number and string.': 'Defini le modèle du bloc de données associé à chaque évènement. Le modèle contiens une liste de propriétés. Un type est défini pour chaque propriété ou une valeur par défault. Les types sont boolean, date, number et string.', 'Define a crude model for the data block associated to each event. The model contains a list of properties. A type is defined to each property or a default value. Valid types are boolean, date, number and string.': 'Defini le modèle du bloc de données associé à chaque évènement. Le modèle contiens une liste de propriétés. Un type est défini pour chaque propriété ou une valeur par défault. Les types sont boolean, date, number et string.',
'Defined a year or a time period !!!': 'Defined a year or a time period !!!', 'Defined a year or a time period !!!': 'Defined a year or a time period !!!',
'Definition': 'Définition', 'Definition': 'Définition',
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
HEAD HEAD
0.7.1 (Apr 2017) 0.7.2 (Apr 2017)
- Major release which is non backward compatible. - Major release which is non backward compatible.
It introduces new mechanisms for the reporting based on pandas.DataFrame. It introduces new mechanisms for the reporting based on pandas.DataFrame.
- Required plugin_dbui 0.9.8 or higher. - Required plugin_dbui 0.9.8 or higher.
......
0.7.1 0.7.2
\ No newline at end of file \ 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