callbacks.py 8.66 KB
Newer Older
LE GAC Renaud's avatar
LE GAC Renaud committed
1 2 3 4
"""a collections of functions to be used in _before_delete, before_insert
and _before_update callbacks.

"""
5 6 7
from .check_tools import (duplicate_article,
                          duplicate_conference,
                          duplicate_report)
LE GAC Renaud's avatar
LE GAC Renaud committed
8
from gluon import current
9 10
from plugin_dbui import (CALLBACK_ERRORS,
                         get_id,
11 12 13
                         get_where_query)


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


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

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

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

27
    """
28
    setquery = set_records.query
29

30 31
    # protection
    # the query of the set should be "table.id == 45"
32
    if setquery.op.__name__ != "eq":
33
        return False
34

35 36 37
    db = current.db
    field = setquery.first

38 39 40 41 42 43 44 45 46 47 48
    # 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)
49

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

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

57
    if db(query).count():
58
        field._table[CALLBACK_ERRORS] = current.T(MSG_DUPLICATE)
59 60 61
        return True

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


64 65 66 67 68 69 70 71 72 73 74 75 76
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

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

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

    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
94
                    id_categories=values["id_categories"])
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 123

    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
124 125
def INHIBIT_DUPLICATE_PUBLICATION(publication):
    """Inhibit the insert operation when the publication already exists.
126

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

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

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

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

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

LE GAC Renaud's avatar
LE GAC Renaud committed
145
            db.publications[CALLBACK_ERRORS] = [
LE GAC Renaud's avatar
LE GAC Renaud committed
146 147 148 149 150
                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
151
                T("See publication id(s) %s") % ", ".join(ids)]
152

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

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

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

            db.publications[CALLBACK_ERRORS] = [
LE GAC Renaud's avatar
LE GAC Renaud committed
165 166 167 168 169
                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
170
                T("See publication id(s) %s") % ", ".join(ids)]
171

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

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

LE GAC Renaud's avatar
LE GAC Renaud committed
177 178 179 180 181
    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
182 183
                T("Can't insert the report."),
                T("A report already exists with the same title"),
LE GAC Renaud's avatar
LE GAC Renaud committed
184
                T("See publication id(s) %s") % ", ".join(ids)]
185

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

    return False


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

194 195 196 197 198 199
        * 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.
200

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

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

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

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

216
    if id_harvester is None:
217 218 219 220 221
        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
222
    if id_category != harvester["id_categories"]:
223 224 225 226

        code = db.categories[id_category].code

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

        return True

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

    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
250 251 252 253 254
    return False


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

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

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

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

    # 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)"

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

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

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


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

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

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

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

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

301
    id_rec = s.query.second
302

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

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