callbacks.py 3.81 KB
Newer Older
LE GAC Renaud's avatar
LE GAC Renaud committed
1
# -*- coding: utf-8 -*-
LE GAC Renaud's avatar
LE GAC Renaud committed
2 3
"""a collections of functions to be used in _before_delete, before_insert
and _before_update callbacks.
4 5

"""
6 7 8 9
import json


from dataframes import to_extjs_gridcolumns
10
from event import Event
11 12 13 14
from gluon import current
from plugin_dbui import CALLBACK_ERRORS, get_where_query


15 16 17
MSG_INHIBIT_DELETE = \
    "Can't delete this record since several transactions refer to it."

18 19
MSG_NO_DATA = \
    "Can not fill the field 'columns' since there is no available data in %i"
20

21

22
def INHIBIT_CASCADE_DELETE(myset):
LE GAC Renaud's avatar
LE GAC Renaud committed
23 24 25 26 27
    """Inhibit the delete.

    The *history* table is linked to several foreign tables.
    This function inhibits the delete of a row, belonging to a foreign table,
    when the row is referenced in the *history* table.
LE GAC Renaud's avatar
LE GAC Renaud committed
28

LE GAC Renaud's avatar
LE GAC Renaud committed
29
    Args:
LE GAC Renaud's avatar
LE GAC Renaud committed
30
        myset (gluon.dal.Set): object describing the row to be deleted.
LE GAC Renaud's avatar
LE GAC Renaud committed
31

LE GAC Renaud's avatar
LE GAC Renaud committed
32 33
    Returns:
        bool: ``True`` when the delete is inhibited
LE GAC Renaud's avatar
LE GAC Renaud committed
34

35
    """
36
    db, T = current.db, current.T
37
    field = myset.query.first
LE GAC Renaud's avatar
LE GAC Renaud committed
38

39 40
    # protection
    # the query of the set should be "table.id == 45"
41
    if field._db._adapter.EQ != myset.query.op:
42
        return False
LE GAC Renaud's avatar
LE GAC Renaud committed
43

44 45 46 47 48 49 50 51
    # protection
    # check that the table is ones of the transactions reference tables
    tables = (db.events,
              db.fundings,
              db.people,
              db.people_categories,
              db.projects,
              db.teams)
LE GAC Renaud's avatar
LE GAC Renaud committed
52

53 54
    if field._table not in tables:
        return False
LE GAC Renaud's avatar
LE GAC Renaud committed
55

56 57
    # inhibit the delete if at least one history row use the reference field
    query = get_where_query(db.history)
58
    query = (query) & (myset.query)
LE GAC Renaud's avatar
LE GAC Renaud committed
59

60
    if db(query).count():
61
        field._table[CALLBACK_ERRORS] = T(MSG_INHIBIT_DELETE)
62 63
        return True

64
    return False
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86


def ON_CREATE_LISTS2(values):
    """Fill the field column with values when it is empty:

        * The values depend on the source.
        * The DataFrame is instantiated for the source, the event and the
          current year.
        * The handler has to be called before the creation of a List2 record.

    Args:
        values (dict): field, value pairs

    Returns:
        bool: ``True`` when the record is rejected.

    """
    if len(values["columns"]) > 0:
        return False

    # try to instantiate the DataFrame with a minimal set of criteria
    year = current.request.now.year
87 88 89 90 91 92

    criteria = dict(
        id_events=values["id_events"],
        year_start=year,
        year_end=year)

93
    func = Event.get_source(values["source"])
94 95 96

    df = func(**criteria)

LE GAC Renaud's avatar
LE GAC Renaud committed
97
    # generate the configuration for Ext.grid.column.Column
98
    if df.empty:
LE GAC Renaud's avatar
LE GAC Renaud committed
99 100 101 102 103 104
        lst = [dict(xtype="rownumberer"),
               dict(dataIndex="?",
                    flex=1,
                    hidden=False,
                    text="?",
                    xtype="gridcolumn")]
105

LE GAC Renaud's avatar
LE GAC Renaud committed
106 107
    else:
        lst = to_extjs_gridcolumns(df)
108

LE GAC Renaud's avatar
LE GAC Renaud committed
109
    values["columns"] = json.dumps(lst, indent=4, sort_keys=True)
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
    return False


def ON_UPDATE_LISTS2(myset, values):
    """Fill the field column with values when it is empty:

        * The values depend on the source.
        * The DataFrame is instantiated for the source, the event and the
          current year.
        * The handler has to be called before updating a List2 record.

    Args:
        myset (gluon.dal.Set): object describing the row to be updated.
        values (dict): field, value pairs

    Returns:
        bool: ``True`` when the update is rejected.

    """
    if ("columns" not in values) \
        or ("columns" in values and len(values["columns"]) > 0):
        return False

133
    db = current.db
134 135 136 137 138 139 140 141 142 143

    # get the id_events and source
    if "id_events" not in values or "source" not in values:
        row = db.lists2[values["id"]]
        if "id_events" not in values:
            values["id_events"] = row.id_events
        if "source" not in values:
            values["source"] = row.source

    return ON_CREATE_LISTS2(values)