From 929cfa7e85635082c548b086efc0fc80ded14d0e Mon Sep 17 00:00:00 2001 From: PascalRepond Date: Wed, 14 Jun 2023 11:38:18 +0200 Subject: [PATCH] circulation: allow checkout from never open library - Closes #2419. Co-Authored-by: Pascal Repond --- rero_ils/modules/items/api/circulation.py | 14 ++-- rero_ils/modules/libraries/api.py | 2 +- .../test_actions_views_checkout.py | 69 +++++++++++++++++++ 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/rero_ils/modules/items/api/circulation.py b/rero_ils/modules/items/api/circulation.py index 6138872c11..55a02078bf 100644 --- a/rero_ils/modules/items/api/circulation.py +++ b/rero_ils/modules/items/api/circulation.py @@ -45,6 +45,7 @@ from ...errors import NoCirculationAction from ...item_types.api import ItemType from ...libraries.api import Library +from ...libraries.exceptions import LibraryNeverOpen from ...loans.api import Loan, get_last_transaction_loc_for_item, \ get_request_by_item_pid_by_patron_pid from ...loans.models import LoanAction, LoanState @@ -420,10 +421,15 @@ def checkout(self, current_loan, **kwargs): transaction_library_pid = self.library_pid library = Library.get_record_by_pid(transaction_library_pid) if not library.is_open(action_params['end_date'], True): - new_end_date = library.next_open(action_params['end_date']) - new_end_date = new_end_date.astimezone()\ - .replace(microsecond=0).isoformat() - action_params['end_date'] = new_end_date + try: + new_end_date = library.next_open(action_params['end_date']) + new_end_date = new_end_date.astimezone()\ + .replace(microsecond=0).isoformat() + action_params['end_date'] = new_end_date + except LibraryNeverOpen: + # If library has no open dates, keep the default due date + # to avoid circulation errors + pass # Call invenio_circulation for 'checkout' trigger loan = current_circulation.circulation.trigger( current_loan, diff --git a/rero_ils/modules/libraries/api.py b/rero_ils/modules/libraries/api.py index 1ed723cbe7..fe18b574c5 100644 --- a/rero_ils/modules/libraries/api.py +++ b/rero_ils/modules/libraries/api.py @@ -241,7 +241,7 @@ def is_open(self, date=None, day_only=False): # is into this periods (depending of `day_only` method argument). day_name = date.strftime("%A").lower() regular_rule = [ - rule for rule in self['opening_hours'] + rule for rule in self.get('opening_hours', []) if rule['day'] == day_name ] if regular_rule: diff --git a/tests/api/circulation/test_actions_views_checkout.py b/tests/api/circulation/test_actions_views_checkout.py index cba183c57f..04fde7c776 100644 --- a/tests/api/circulation/test_actions_views_checkout.py +++ b/tests/api/circulation/test_actions_views_checkout.py @@ -20,6 +20,7 @@ import ciso8601 from invenio_accounts.testutils import login_user_via_session +from invenio_db import db from utils import postdata from rero_ils.modules.items.models import ItemStatus @@ -155,3 +156,71 @@ def test_checkout( transaction_end_date = ciso8601.parse_datetime(transaction_end_date) next_open_date = lib_martigny.next_open(next_saturday) assert next_open_date.date() == transaction_end_date.date() + + # Test checkout from library with no opening hours + res, _ = postdata( + client, + 'api_item.checkin', + dict( + item_pid=item.pid, + transaction_library_pid=lib_martigny.pid, + transaction_user_pid=librarian_martigny.pid + ) + ) + assert res.status_code == 200 + assert item.status == ItemStatus.ON_SHELF + + lib_martigny['opening_hours'] = [ + { + "day": "monday", + "is_open": False, + "times": [] + }, + { + "day": "tuesday", + "is_open": False, + "times": [] + }, + { + "day": "wednesday", + "is_open": False, + "times": [] + }, + { + "day": "thursday", + "is_open": False, + "times": [] + }, + { + "day": "friday", + "is_open": False, + "times": [] + }, + { + "day": "saturday", + "is_open": False, + "times": [] + }, + { + "day": "sunday", + "is_open": False, + "times": [] + } + ] + db.session.commit() + + params = dict( + item_pid=item.pid, + patron_pid=patron_martigny.pid, + transaction_user_pid=librarian_martigny.pid, + transaction_location_pid=loc_public_martigny.pid + ) + + res, _ = postdata( + client, + 'api_item.checkout', + params + ) + + assert res.status_code == 200 + db.session.rollback()