callbacks.py 8.69 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 4 5 6 7 8 9
"""a collections of functions to be used in _before_delete, before_insert
and _before_update callbacks.

"""
from check_tools import (duplicate_article,
                         duplicate_conference,
                         duplicate_report)
from gluon import current
10 11
from plugin_dbui import (CALLBACK_ERRORS,
                         get_id,
12 13 14
                         get_where_query)


LE GAC Renaud's avatar
LE GAC Renaud committed
15 16 17 18
MSG_DUPLICATE = \
    "Can't delete this record since several publications refer to it."


19
def INHIBIT_CASCADE_DELETE(set_records):
20
    """Inhibit the delete when the entry is referenced in another table(s).
21

22 23
    Args:
        set_records (gluon.dal.Set): set object used for delete.
24

25 26
    Returns:
        bool: ``True`` when the delete is inhibited
27

28
    """
29
    db, T = current.db, current.T
30
    field = set_records.query.first
31

32 33
    # protection
    # the query of the set should be "table.id == 45"
34
    if field._db._adapter.EQ != set_records.query.op:
35
        return False
36

37 38 39 40 41 42 43 44 45 46 47
    # protection
    # check that the table is ones of the publication reference tables
    tables = (db.authors_roles,
              db.categories,
              db.collaborations,
              db.countries,
              db.projects,
              db.publishers,
              db.reports,
              db.status,
              db.teams)
48

49 50
    if field._table not in tables:
        return False
51

52 53
    # inhibit the delete if publications use the reference field
    query = get_where_query(db.publications)
54
    query = (query) & (set_records.query)
55

56
    if db(query).count():
LE GAC Renaud's avatar
LE GAC Renaud committed
57
        field._table[CALLBACK_ERRORS] = T(MSG_DUPLICATE)
58 59 60
        return True

    return False
LE GAC Renaud's avatar
LE GAC Renaud committed
61 62


63 64 65 66 67 68 69 70 71 72 73 74 75
def INHIBIT_CONTROLLER_INSERT(values):
    """Inhibit the insert of duplicate controller.

    The pair controller, category is unique
    The category is used only once.

    Args:
        values (dict): data passed to insert.

    Returns:
        bool: ``True`` when the insert is inhibited

    """
76
    db, T = current.db, current.T
77 78

    # check the pair
LE GAC Renaud's avatar
LE GAC Renaud committed
79 80
    if "id" in values:
        del values["id"]
81 82 83 84 85 86 87 88 89 90 91 92

    id_rec = get_id(db.controllers, **values)

    if id_rec is not None:
        db.controllers[CALLBACK_ERRORS] = [
            T("Can't insert the harvester."),
            T("The pair (harvester, category) already exists !")]

        return True

    # check the category
    id_rec = get_id(db.controllers,
LE GAC Renaud's avatar
LE GAC Renaud committed
93
                    id_categories=values["id_categories"])
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122

    if id_rec is None:
        return False

    db.controllers[CALLBACK_ERRORS] = [
        T("Can't insert the harvester."),
        T("The category is used twice !")]

    return True


def INHIBIT_CONTROLLER_UPDATE(setrow, values):
    """Inhibit the controller on update against identical pair.
    A pair is defined by a controller and a category.

    Args:
        setrow (gluon.dal.Set): set object used for update.
        values (dict): the dict of fields passed to update.

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

    """
    data = setrow.select().first().as_dict()
    data.update(values)

    return INHIBIT_CONTROLLER_INSERT(data)


LE GAC Renaud's avatar
LE GAC Renaud committed
123 124
def INHIBIT_DUPLICATE_PUBLICATION(publication):
    """Inhibit the insert operation when the publication already exists.
125

126 127
    Args:
        publication (dict): publications fields passed to insert.
128

129 130
    Returns:
        bool: ``True`` when the insert is inhibited
131

LE GAC Renaud's avatar
LE GAC Renaud committed
132
    """
133
    db, T = current.db, current.T
LE GAC Renaud's avatar
LE GAC Renaud committed
134
    categories = db.categories
LE GAC Renaud's avatar
LE GAC Renaud committed
135
    id_category = publication["id_categories"]
136

LE GAC Renaud's avatar
LE GAC Renaud committed
137
    # articles
LE GAC Renaud's avatar
LE GAC Renaud committed
138
    id_cats = (get_id(categories, code="ACL"), get_id(categories, code="ACLN"))
LE GAC Renaud's avatar
LE GAC Renaud committed
139 140 141 142

    if id_category in id_cats:
        ids = duplicate_article(publication)
        if ids:
143

LE GAC Renaud's avatar
LE GAC Renaud committed
144
            db.publications[CALLBACK_ERRORS] = [
LE GAC Renaud's avatar
LE GAC Renaud committed
145 146 147 148 149
                T("Can't insert the article."),
                T("An article already exists with the same:"),
                T("• title, publisher, volume and pages"),
                T("• or publisher, volume and pages"),
                T("• or publisher and title."),
LE GAC Renaud's avatar
LE GAC Renaud committed
150
                T("See publication id(s) %s") % ", ".join(ids)]
151

LE GAC Renaud's avatar
LE GAC Renaud committed
152
            return True
153

LE GAC Renaud's avatar
LE GAC Renaud committed
154
    # talks and proceedings
LE GAC Renaud's avatar
LE GAC Renaud committed
155 156 157
    id_cats = (get_id(categories, code="ACTI"),
               get_id(categories, code="ACTN"),
               get_id(categories, code="COM"))
158

LE GAC Renaud's avatar
LE GAC Renaud committed
159
    if id_category in id_cats:
160
        ids = duplicate_conference(publication, id_category != id_cats[2])
LE GAC Renaud's avatar
LE GAC Renaud committed
161 162 163
        if ids:

            db.publications[CALLBACK_ERRORS] = [
LE GAC Renaud's avatar
LE GAC Renaud committed
164 165 166 167 168
                T("Can't insert the talk/proceeding."),
                T("A talk/proceeding already exists with the same:"),
                T("• title, conference title, date and town"),
                T("• or title, conference date and town"),
                T("• or title, conference title and town"),
LE GAC Renaud's avatar
LE GAC Renaud committed
169
                T("See publication id(s) %s") % ", ".join(ids)]
170

LE GAC Renaud's avatar
LE GAC Renaud committed
171
            return True
172

LE GAC Renaud's avatar
LE GAC Renaud committed
173
    # reports
LE GAC Renaud's avatar
LE GAC Renaud committed
174
    id_cats = (get_id(categories, code="AP"),)
175

LE GAC Renaud's avatar
LE GAC Renaud committed
176 177 178 179 180
    if id_category in id_cats:
        ids = duplicate_report(publication)
        if ids:

            db.publications[CALLBACK_ERRORS] = [
LE GAC Renaud's avatar
LE GAC Renaud committed
181 182
                T("Can't insert the report."),
                T("A report already exists with the same title"),
LE GAC Renaud's avatar
LE GAC Renaud committed
183
                T("See publication id(s) %s") % ", ".join(ids)]
184

LE GAC Renaud's avatar
LE GAC Renaud committed
185
            return True
186 187 188 189

    return False


190 191
def INHIBIT_HARVESTER(harvester):
    """Inhibit the insert of similar harvesters:
192

193 194 195 196 197 198
        * For a project, one automaton can only proceed publication
          of the same code, e.g ACL or ACLN but not both, but automatons
          can scan different stores.

        * Reject identical harvester, same project, controller, store,
          collection and category.
199

200 201
    Args:
        harvester (dict): harvester fields passed to insert.
202

203 204
    Returns:
        bool: ``True`` when the insert is inhibited
205 206

    """
207
    db, T = current.db, current.T
208 209 210

    # a new harvester
    id_harvester = get_id(db.harvesters,
LE GAC Renaud's avatar
LE GAC Renaud committed
211 212 213
                          controller=harvester["controller"],
                          id_projects=harvester["id_projects"],
                          id_teams=harvester["id_teams"])
214

215
    if id_harvester is None:
216 217 218 219 220
        return False

    # for a project, one automaton can only proceed publication
    # of the same code, e.g ACL or ACLN but not both
    id_category = db.harvesters[id_harvester].id_categories
LE GAC Renaud's avatar
LE GAC Renaud committed
221
    if id_category != harvester["id_categories"]:
222 223 224 225

        code = db.categories[id_category].code

        db.harvesters[CALLBACK_ERRORS] = [
LE GAC Renaud's avatar
LE GAC Renaud committed
226 227 228
            T("Can't insert the harvester."),
            T("Harvester already exists with the same automaton "),
            T("but with different category: %s") % code]
229 230 231

        return True

232 233
    # duplicate harvesters
    id_harvester = get_id(db.harvesters,
LE GAC Renaud's avatar
LE GAC Renaud committed
234 235 236 237 238 239
                          collections=harvester["collections"],
                          controller=harvester["controller"],
                          host=harvester["host"],
                          id_categories=harvester["id_categories"],
                          id_projects=harvester["id_projects"],
                          id_teams=harvester["id_teams"])
240 241 242 243 244 245 246 247 248

    if id_harvester is not None:

        db.harvesters[CALLBACK_ERRORS] = [
            T("Can't insert the harvester. "),
            T("Identical harvester already exists.")]

        return True

LE GAC Renaud's avatar
LE GAC Renaud committed
249 250 251 252 253
    return False


def INHIBIT_PUBLICATION_DELETE_ON_OK(s):
    """Inhibit the delete operation when the status of the publication is OK.
254

255 256
    Args:
        s (gluon.dal.Set]: set object used for delete.
257

258 259
    Returns:
        bool: ``True`` when the delete is inhibited.
260

LE GAC Renaud's avatar
LE GAC Renaud committed
261
    """
262
    db, T = current.db, current.T
LE GAC Renaud's avatar
LE GAC Renaud committed
263
    id_ok = get_id(db.status, code="OK")
LE GAC Renaud's avatar
LE GAC Renaud committed
264 265 266 267 268

    # also call in cascade delete (teams, ...)
    # in normal case the query is "publications.id = 567"
    # in cascade delete the query is "publications.id_teams IN (21)"

269
    if s.query.first is not db.publications.id:
270 271
        return False

272 273
    id_rec = s.query.second
    if db.publications[id_rec].id_status == id_ok:
274
        db.publications[CALLBACK_ERRORS] = \
LE GAC Renaud's avatar
LE GAC Renaud committed
275
            T("Can't delete a publication marked OK.")
276
        return True
277

LE GAC Renaud's avatar
LE GAC Renaud committed
278 279 280 281 282
    return False


def INHIBIT_PUBLICATION_UPDATE_ON_OK(s, f):
    """Inhibit the update operation when the status of the publication is OK.
283

284 285 286
    Args:
        s (gluon.dal.Set): set object used for update.
        f (dict): the dict of publications fields passed to update.
287

288 289
    Returns:
        bool: ``True`` when the update is inhibited.
290

LE GAC Renaud's avatar
LE GAC Renaud committed
291
    """
292
    db, T = current.db, current.T
LE GAC Renaud's avatar
LE GAC Renaud committed
293
    id_ok = get_id(db.status, code="OK")
LE GAC Renaud's avatar
LE GAC Renaud committed
294

295 296
    # protection
    # the query of the set should be "publications.id == 45"
297
    if s.query.first is not db.publications.id:
298 299
        return False

300
    id_rec = s.query.second
301

302
    if db.publications[id_rec].id_status == id_ok:
LE GAC Renaud's avatar
LE GAC Renaud committed
303
        db.publications[CALLBACK_ERRORS] = \
LE GAC Renaud's avatar
LE GAC Renaud committed
304
            T("Can't updated a publication marked OK.")
LE GAC Renaud's avatar
LE GAC Renaud committed
305
        return True
306

LE GAC Renaud's avatar
LE GAC Renaud committed
307
    return False