diff --git a/rero_ils/manual_translations.txt b/rero_ils/manual_translations.txt index 5ed94d191f..3da78f6b4b 100644 --- a/rero_ils/manual_translations.txt +++ b/rero_ils/manual_translations.txt @@ -61,6 +61,10 @@ _('rdami:1002') _('rdami:1003') _('rdami:1004') +# Color content +_('rdacc:1002') +_('rdacc:1003') + # oneOff contribution types _('Link to person entity') _('Person') 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,