def test_items_extend(client, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, json_header, circulation_policies): """Test item renewal.""" login_user_via_session(client, librarian_martigny_no_email.user) item = item_lib_martigny item_pid = item.pid patron_pid = patron_martigny_no_email.pid location = loc_public_martigny # checkout res, data = postdata(client, 'api_item.checkout', dict(item_pid=item_pid, patron_pid=patron_pid)) assert res.status_code == 200 actions = data.get('action_applied') loan_pid = actions[LoanAction.CHECKOUT].get('pid') assert not item.get_extension_count() # extend loan res, data = postdata(client, 'api_item.extend_loan', dict(item_pid=item_pid, pid=loan_pid)) assert res.status_code == 200 item_data = data.get('metadata') actions = data.get('action_applied') assert item_data.get('status') == ItemStatus.ON_LOAN assert actions.get(LoanAction.EXTEND) assert item.get_extension_count() == 1 # Get library timezone lib = Library.get_record_by_pid(item.library_pid) lib_tz = lib.get_timezone() # test renewal due date hour extended_loan = Loan.get_record_by_pid(loan_pid) end_date = ciso8601.parse_datetime(extended_loan.get('end_date')) check_timezone_date(lib_tz, end_date) # second extenion res, _ = postdata(client, 'api_item.extend_loan', dict(item_pid=item_pid, pid=loan_pid)) assert res.status_code == 403 # checkin res, _ = postdata(client, 'api_item.checkin', dict(item_pid=item_pid, pid=loan_pid)) assert res.status_code == 200
def test_due_soon_loans(client, librarian_martigny, patron_martigny, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, circ_policy_short_martigny): """Test overdue loans.""" login_user_via_session(client, librarian_martigny.user) item = item_lib_martigny item_pid = item.pid patron_pid = patron_martigny.pid assert not get_last_transaction_loc_for_item(item_pid) assert not item.patron_has_an_active_loan_on_item(patron_martigny) assert item.can_delete assert item.available from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy( item.organisation_pid, item.library_pid, patron_martigny.patron_type_pid, item.item_type_pid) circ_policy['reminders'][0]['days_delay'] = 7 circ_policy['checkout_duration'] = 3 circ_policy.update(circ_policy, dbcommit=True, reindex=True) # checkout res, data = postdata( client, 'api_item.checkout', dict( item_pid=item_pid, patron_pid=patron_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid, )) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') due_soon_loans = get_due_soon_loans() assert due_soon_loans[0].get('pid') == loan_pid # test due date regarding multiple timezones checkout_loan = Loan.get_record_by_pid(loan_pid) loan_date = ciso8601.parse_datetime(checkout_loan.get('end_date')) # as instance timezone is Europe/Zurich, it should be either 21 or 22 check_timezone_date(pytz.utc, loan_date, [21, 22]) # should be 14:59/15:59 in US/Pacific (because of daylight saving time) check_timezone_date(pytz.timezone('US/Pacific'), loan_date, [14, 15]) check_timezone_date(pytz.timezone('Europe/Amsterdam'), loan_date) # checkin the item to put it back to it's original state res, _ = postdata( client, 'api_item.checkin', dict(item_pid=item_pid, pid=loan_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid)) assert res.status_code == 200
def test_timezone_due_date(client, librarian_martigny_no_email, patron_martigny_no_email, loc_public_martigny, item_type_standard_martigny, item3_lib_martigny, circ_policy_short_martigny, lib_martigny): """Test that timezone affects due date regarding library location.""" # Login to perform action login_user_via_session(client, librarian_martigny_no_email.user) # Close the library all days. Except Monday. del lib_martigny['opening_hours'] del lib_martigny['exception_dates'] lib_martigny['opening_hours'] = [ { "day": "monday", "is_open": True, "times": [ { "start_time": "07:00", "end_time": "19:00" } ] }, { "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": [] } ] lib_martigny.update(lib_martigny, dbcommit=True, reindex=True) # Change circulation policy checkout_duration = 3 item = item3_lib_martigny item_pid = item.pid patron_pid = patron_martigny_no_email.pid from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy( item.library_pid, patron_martigny_no_email.patron_type_pid, item.item_type_pid ) circ_policy['number_of_days_before_due_date'] = 7 circ_policy['checkout_duration'] = checkout_duration circ_policy.update( circ_policy, dbcommit=True, reindex=True ) # Checkout the item res, data = postdata( client, 'api_item.checkout', dict( item_pid=item_pid, patron_pid=patron_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid, ) ) assert res.status_code == 200 # Get Loan date (should be in UTC) loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') loan = Loan.get_record_by_pid(loan_pid) loan_end_date = loan.get('end_date') # Get next library open date (should be next monday after X-1 days) where # X is checkout_duration soon = datetime.now(pytz.utc) + timedelta(days=(checkout_duration-1)) lib = Library.get_record_by_pid(item.library_pid) lib_datetime = lib.next_open(soon) # Loan date should be in UTC (as lib_datetime). loan_datetime = ciso8601.parse_datetime(loan_end_date) # Compare year, month and date for Loan due date: should be the same! fail_msg = "Check timezone for Loan and Library. \ It should be the same date, even if timezone changed." assert loan_datetime.year == lib_datetime.year, fail_msg assert loan_datetime.month == lib_datetime.month, fail_msg assert loan_datetime.day == lib_datetime.day, fail_msg # Loan date differs regarding timezone, and day of the year (GMT+1/2). check_timezone_date(pytz.utc, loan_datetime, [21, 22])
def test_due_soon_loans(client, librarian_martigny, lib_martigny_data, lib_martigny, patron_martigny, loc_public_martigny, item_type_standard_martigny, item_lib_martigny, circ_policy_short_martigny, yesterday): """Test overdue loans.""" login_user_via_session(client, librarian_martigny.user) item = item_lib_martigny item_pid = item.pid patron_pid = patron_martigny.pid can, reasons = item.can_delete assert can assert reasons == {} assert item.available assert not get_last_transaction_loc_for_item(item_pid) assert not item.patron_has_an_active_loan_on_item(patron_martigny) from rero_ils.modules.circ_policies.api import CircPolicy circ_policy = CircPolicy.provide_circ_policy( item.organisation_pid, item.library_pid, patron_martigny.patron_type_pid, item.item_type_pid) circ_policy['reminders'][0]['days_delay'] = 7 circ_policy['checkout_duration'] = 3 circ_policy.update(circ_policy, dbcommit=True, reindex=True) # Remove library exception date to ensure to not been annoyed by # closed dates. custom_lib_data = deepcopy(lib_martigny_data) custom_lib_data['exception_dates'] = [] lib_martigny.update(custom_lib_data, dbcommit=True, reindex=True) flush_index(LibrariesSearch.Meta.index) # checkout res, data = postdata( client, 'api_item.checkout', dict( item_pid=item_pid, patron_pid=patron_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid, )) assert res.status_code == 200 loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid') # To be considerate as 'due_soon', we need to update the loan start date # to figure than start_date occurs before due_date. loan = Loan.get_record_by_pid(loan_pid) start_date = ciso8601.parse_datetime(loan.get('start_date')) loan['start_date'] = (start_date - timedelta(days=30)).isoformat() loan.update(loan, dbcommit=True, reindex=True) due_soon_loans = list(get_due_soon_loans()) assert due_soon_loans[0].get('pid') == loan_pid # test due date regarding multiple timezones checkout_loan = Loan.get_record_by_pid(loan_pid) loan_date = ciso8601.parse_datetime(checkout_loan.get('end_date')) # as instance timezone is Europe/Zurich, it should be either 21 or 22 check_timezone_date(pytz.utc, loan_date, [21, 22]) # should be 14:59/15:59 in US/Pacific (because of daylight saving time) check_timezone_date(pytz.timezone('US/Pacific'), loan_date, [14, 15]) check_timezone_date(pytz.timezone('Europe/Amsterdam'), loan_date) # checkin the item to put it back to it's original state res, _ = postdata( client, 'api_item.checkin', dict(item_pid=item_pid, pid=loan_pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny.pid)) assert res.status_code == 200 # reset lib lib_martigny.update(lib_martigny_data, dbcommit=True, reindex=True)