# -*- coding: utf-8 -*- """Definitions of the report tables """ import numpy as np import plugin_dbui as dbui from callbacks import (INHIBIT_CASCADE_DELETE, ON_CREATE_LISTS2, ON_UPDATE_LISTS2) from gluon import current, IS_IN_DB, IS_IN_SET from gluon.tools import PluginManager from pydal import Field AGGREGATE_FUNCS = { "max": np.max, "mean": np.min, "median": np.median, "min": np.min, "sem": np.max, "size": np.size, "sum": np.sum, "std": np.std, "var": np.var} DEF_COLUMNS_LISTS = \ """[{ "xtype": "rownumberer" }, { "dbfield": "?.?", "flex": 1, "text": "?", "xtype": "gridcolumn" }]""" DEF_COLUMNS_METRIC1D = \ """[{ "aggregate": "?", "align": "right", "dbfield": "?.?", "format": "0.0", "text": "?", "xtype": "numbercolumn" }]""" DEF_FEATURES = \ """[{ "ftype": "groupingsummary", "groupHeaderTpl": "{name}", "startCollapsed": false }, { "ftype": "summary" }]""" DEF_PLOT = \ """{ "kind": "?", "stacked": false }""" TP_AGG = \ "The aggregation function applies on the metric field. " \ "It is computed on the subset of row having a given values for " \ "the group_field x and y." TP_COLUMNS = "Configure the column of the grid displayed in the view." TP_CONDITIONS = \ "Database query to select history records:
" \ "(db.events.event == 'People') & (db.history.data.like('%cdd%'))
" TP_GROUP_FIELD_LISTS = \ "Row are grouped according to the value of that field. " \ "It can be any field of the history table including those of " \ "the foreign tables, the individual property of the history.data " \ "dictionary, or 'year'." TP_GROUP_FIELD_METRICS = \ "Metric are computed for each value of that field. " \ "It can be any field of the history table including those of the " \ "foreign tables, the individual property of the history.data dictionary " \ "or 'year'" TP_FEATURES = "Summary value can be computed for columns." TP_SORTERS = \ "Entries are sorted according to the value of these fields. " \ "It can be any field of the history table including those of the " \ "foreign tables, the individual property of the history.data dictionary, " \ "or 'year'. Descending order is obtained by using the '~field' construct." TP_SUMMARY_X = "To sum, for example, the content of each row." TP_SUMMARY_Y = "To sum, for example, the content of each column." class Report(object): """Create the tables for the reporting: lists, metrics1d, metrics2d, and graphs. """ @staticmethod def define_tables(db, T): """Define tables for the reporting. Args: db (pyDAL.DAL): database connection T (gluon.languages.translator): language translator """ Report.graphs(db, T) Report.lists(db, T) Report.lists2(db, T) Report.metrics1d(db, T) Report.metrics2d(db, T) Report.metrics2d2(db, T) @staticmethod def graphs(db, T): """graphs table Args: db (pyDAL.DAL): database connection T (gluon.languages.translator): language translator Returns: pyDAL.Table """ def_plot = (None if db._migrate else DEF_PLOT) table = db.define_table( "graphs", Field("name", "string", length=255, notnull=True, unique=True), Field("title", "string", length=255), Field("report_type", "string", length=255, notnull=True), Field("report_name", "string", length=255, notnull=True), Field("plot", "text", notnull=True, default=def_plot), Field("definition", "text"), migrate="graphs.table") return table @staticmethod def lists(db, T): """lists table Args: db (pyDAL.DAL): database connection T (gluon.languages.translator): language translator Returns: pyDAL.Table """ def_columns = (None if db._migrate else DEF_COLUMNS_LISTS) def_features = (None if db._migrate else DEF_FEATURES) table = db.define_table( "lists", Field("name", "string", length=255, notnull=True, unique=True), Field("title", "string", length=255), Field("conditions", "text", comment=T(TP_CONDITIONS)), Field("group_field", "string", length=255, comment=T(TP_GROUP_FIELD_LISTS)), Field("sorters", "list:string", comment=TP_SORTERS), Field("columns", "text", default=def_columns, comment=T(TP_COLUMNS), notnull=True), Field("features", "text", default=def_features, comment=T(TP_FEATURES)), Field("definition", "text"), migrate="lists.table") return table @staticmethod def lists2(db, T): """lists2 table Args: db (pyDAL.DAL): database connection T (gluon.languages.translator): language translator Returns: pyDAL.Table """ migrate = current.globalenv["MIGRATE"] def_features = (None if migrate else DEF_FEATURES) table = db.define_table( "lists2", Field("name", "string", length=255, notnull=True, unique=True), Field("title", "string", length=255), Field("definition", "text"), Field("source", "string", length=255, notnull=True), Field("id_events", "reference events", notnull=True, label="Event"), Field("eval", "text"), Field("query", "text"), Field("group_field", "string", length=255, comment=T(TP_GROUP_FIELD_LISTS)), Field("sorters", "list:string", comment=TP_SORTERS), # NOTE # - notnull when creating the database # - null later on in order to run callback ON_CREATE_LISTS, ... Field("columns", "text", notnull=migrate, comment=T(TP_COLUMNS)), Field("summary_group", "boolean", default=True, label=T("Summary row per group")), Field("summary_all", "boolean", default=True, label=T("Summary row")), migrate="lists2.table") sources = PluginManager("event").event.sources.keys() sources.sort() db.lists2.source.requires = IS_IN_SET(sources) db.lists2._before_insert.append(ON_CREATE_LISTS2) db.lists2._before_update.append(ON_UPDATE_LISTS2) return table @staticmethod def metrics1d(db, T): """metrics1d table Args: db (pyDAL.DAL): database connection T (gluon.languages.translator): language translator Returns: pyDAL.Table """ def_columns = (None if db._migrate else DEF_COLUMNS_METRIC1D) table = db.define_table( "metrics1d", Field("name", "string", length=255, notnull=True, unique=True), Field("title", "string", length=255), Field("conditions", "text", comment=T(TP_CONDITIONS)), Field("group_field", "string", length=255, comment=T(TP_GROUP_FIELD_METRICS), notnull=True), Field("columns", "text", default=def_columns, comment=T(TP_COLUMNS), notnull=True), Field("definition", "text"), migrate="metrics1d.table") @staticmethod def metrics2d(db, T): """metrics2d table Args: db (pyDAL.DAL): database connection T (gluon.languages.translator): language translator Returns: pyDAL.Table """ table = db.define_table( "metrics2d", Field("name", "string", length=255, notnull=True, unique=True), Field("title", "string", length=255), Field("conditions", "text", comment=T(TP_CONDITIONS)), Field("group_field_x", "string", length=255, notnull=True, comment=T(TP_GROUP_FIELD_METRICS)), Field("group_field_y", "string", length=255, notnull=True, comment=T(TP_GROUP_FIELD_METRICS)), Field("metric_field_z", "string", length=255, notnull=True, comment=T(TP_GROUP_FIELD_METRICS)), Field("aggregation_z", "string", length=255, notnull=True, comment=T(TP_AGG)), Field("definition", "text"), migrate="metrics2d.table") return table @staticmethod def metrics2d2(db, T): """metrics2d2 table Args: db (pyDAL.DAL): database connection T (gluon.languages.translator): language translator Returns: pyDAL.Table """ table = db.define_table( "metrics2d2", Field("name", "string", length=255, notnull=True, unique=True), Field("title", "string", length=255), Field("definition", "text"), Field("source", "string", length=255, notnull=True), Field("id_events", "reference events", label="Event", notnull=True), Field("eval", "text"), Field("query", "text"), Field("group_field_x", "string", comment=T(TP_GROUP_FIELD_METRICS), length=255, notnull=True, label="Group (x)"), Field("group_field_y", "string", comment=T(TP_GROUP_FIELD_METRICS), length=255, notnull=True, label="Group (y)"), Field("metric_field_z", "string", comment=T(TP_GROUP_FIELD_METRICS), label="Metric (z)", length=255, notnull=True), Field("aggregate_func_z", "string", comment=T(TP_AGG), default="sum", label="Aggregate (z)", length=255, notnull=True), Field("summary_x", "boolean", default=False, label="Per row"), Field("summary_func_x", "string", comment=T(TP_SUMMARY_X), default="sum", label="aggregate", length=255), Field("summary_label_x", "string", default=T("Sum"), label="label", length=255), Field("summary_y", "boolean", default=False, label="Per columns"), Field("summary_func_y", "string", comment=T(TP_SUMMARY_Y), default="sum", label="aggregate", length=255), Field("summary_label_y", "string", label="label", length=255), migrate="metrics2d2.table") sources = PluginManager("event").event.sources.keys() sources.sort() db.metrics2d2.source.requires = IS_IN_SET(sources) funcs = AGGREGATE_FUNCS.keys() funcs.sort() db.metrics2d2.aggregate_func_z.requires = IS_IN_SET(funcs) db.metrics2d2.summary_func_x.requires = IS_IN_SET(funcs) db.metrics2d2.summary_func_y.requires = IS_IN_SET(funcs) return table @staticmethod def tables(): """Tool returning the list of table names. Returns: list """ lst = ["graphs", "lists", "lists2", "metrics1d", "metrics2d" "metrics2d2"] return lst