From f793697c066429147f2b4c48ab3b62968c105df2 Mon Sep 17 00:00:00 2001 From: Renaud Michotte Date: Thu, 19 Nov 2020 14:00:17 +0100 Subject: [PATCH] circulation: allow overriding exception Sometimes, restrictions can disallow to execute a circulation operation. Adding the "override_blocking" parameter to the API url allows to bypass all restrictions. This commit also corrects some string for translations (color content RDA codes) Closes rero/rero-ils#1488 Co-Authored-by: Renaud Michotte --- .../document_color_content-v0.0.1.json | 4 ++-- rero_ils/modules/items/decorators.py | 23 ++++++++++++------- tests/api/circulation/test_borrow_limits.py | 19 ++++++++++++++- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/rero_ils/modules/documents/jsonschemas/documents/document_color_content-v0.0.1.json b/rero_ils/modules/documents/jsonschemas/documents/document_color_content-v0.0.1.json index 12341e063a..4cf902f30e 100644 --- a/rero_ils/modules/documents/jsonschemas/documents/document_color_content-v0.0.1.json +++ b/rero_ils/modules/documents/jsonschemas/documents/document_color_content-v0.0.1.json @@ -15,11 +15,11 @@ "type": "selectWithSort", "options": [ { - "label": "Monochrome", + "label": "rdacc:1002", "value": "rdacc:1002" }, { - "label": "Polychrome", + "label": "rdacc:1003", "value": "rdacc:1003" } ], diff --git a/rero_ils/modules/items/decorators.py b/rero_ils/modules/items/decorators.py index 03bc87cf68..18fe2741d9 100644 --- a/rero_ils/modules/items/decorators.py +++ b/rero_ils/modules/items/decorators.py @@ -20,7 +20,7 @@ from functools import wraps -from flask import current_app +from flask import current_app, request from invenio_circulation.errors import CirculationException from invenio_records_rest.utils import obj_or_import_string @@ -70,6 +70,10 @@ def wrapper(item, *args, **kwargs): def check_operation_allowed(action): """Check if a specific action is allowed on an item. + Check if we received an 'ovrride_blocking' query string parameter. If this + param is present and set to True (or corresponding True values [1, 'true', + , True, ...]) then no CIRCULATION_ACTIONS_VALIDATION should be tested. + Check the CIRCULATION_ACTIONS_VALIDATION configuration file and execute function corresponding to the action specified. All function are execute until one return False (action denied) or all actions are successful. @@ -80,13 +84,16 @@ def check_operation_allowed(action): def inner_function(func): @wraps(func) def decorated_view(*args, **kwargs): - actions = current_app.config.get( - 'CIRCULATION_ACTIONS_VALIDATION', {}) - for func_name in actions.get(action, []): - func_callback = obj_or_import_string(func_name) - can, reasons = func_callback(args[0], **kwargs) - if not can: - raise CirculationException(description=reasons[0]) + override_blocking = request.args.get('override_blocking', False) + override_blocking = bool(override_blocking) + if not override_blocking: + actions = current_app.config.get( + 'CIRCULATION_ACTIONS_VALIDATION', {}) + for func_name in actions.get(action, []): + func_callback = obj_or_import_string(func_name) + can, reasons = func_callback(args[0], **kwargs) + if not can: + raise CirculationException(description=reasons[0]) return func(*args, **kwargs) return decorated_view return inner_function diff --git a/tests/api/circulation/test_borrow_limits.py b/tests/api/circulation/test_borrow_limits.py index 77ea0a3cbc..0ac39c61a6 100644 --- a/tests/api/circulation/test_borrow_limits.py +++ b/tests/api/circulation/test_borrow_limits.py @@ -149,10 +149,27 @@ def test_checkout_library_limit( assert 'error' == data['messages'][0]['type'] assert 'Checkout denied' in data['messages'][0]['content'] + # try a checkout with 'override_blocking' parameter. + # --> the restriction is no longer checked, the checkout will be success. + res, data = postdata(client, 'api_item.checkout', dict( + item_pid=item3.pid, + patron_pid=patron.pid, + transaction_location_pid=loc_public_martigny.pid, + transaction_user_pid=librarian_martigny_no_email.pid, + ), url_data={'override_blocking': 'true'}) + assert res.status_code == 200 + loan3_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') + # reset fixtures - # --> checkin both loaned item + # --> checkin three loaned item # --> reset patron_type to original value # --> reset items to original values + res, data = postdata(client, 'api_item.checkin', dict( + item_pid=item3.pid, + pid=loan3_pid, + transaction_location_pid=loc_public_martigny.pid, + transaction_user_pid=librarian_martigny_no_email.pid, + )) res, data = postdata(client, 'api_item.checkin', dict( item_pid=item2.pid, pid=loan2_pid,