def test_loan_utils(client, patron_martigny_no_email, patron2_martigny_no_email, circulation_policies, loan_pending_martigny, item_lib_martigny): """Test loan utils.""" loan = { 'item_pid': item_lib_martigny.pid, 'patron_pid': patron_martigny_no_email.pid } assert can_be_requested(loan) del loan['item_pid'] with pytest.raises(Exception): assert can_be_requested(loan) assert loan_pending_martigny.patron_pid == patron2_martigny_no_email.pid assert not loan_pending_martigny.is_active with pytest.raises(TypeError): assert get_loans_by_patron_pid() assert get_loans_by_patron_pid(patron2_martigny_no_email.pid) with pytest.raises(TypeError): assert get_last_transaction_loc_for_item() assert loan_pending_martigny.organisation_pid new_loan = deepcopy(loan_pending_martigny) assert new_loan.organisation_pid del new_loan['item_pid'] assert not new_loan.organisation_pid
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_loan_utils(client, patron_martigny_no_email, patron2_martigny_no_email, circulation_policies, loan_pending_martigny, item_lib_martigny, loc_public_martigny): """Test loan utils.""" loan_metadata = dict(item_lib_martigny) if 'item_pid' not in loan_metadata: loan_metadata['item_pid'] = item_lib_martigny.pid if 'patron_pid' not in loan_metadata: loan_metadata['patron_pid'] = patron_martigny_no_email.pid # Create "virtual" Loan (not registered) loan = Loan(loan_metadata) assert can_be_requested(loan) del loan['item_pid'] with pytest.raises(Exception): assert can_be_requested(loan) assert loan_pending_martigny.patron_pid == patron2_martigny_no_email.pid assert not loan_pending_martigny.is_active with pytest.raises(TypeError): assert get_loans_by_patron_pid() assert get_loans_by_patron_pid(patron2_martigny_no_email.pid) with pytest.raises(TypeError): assert get_last_transaction_loc_for_item() assert loan_pending_martigny.organisation_pid new_loan = deepcopy(loan_pending_martigny) assert new_loan.organisation_pid del new_loan['item_pid'] with pytest.raises(IlsRecordError.PidDoesNotExist): new_loan.organisation_pid new_loan = deepcopy(loan_pending_martigny) assert can_be_requested(new_loan) loc_public_martigny['allow_request'] = False loc_public_martigny.update( loc_public_martigny, dbcommit=True, reindex=True ) flush_index(LocationsSearch.Meta.index) assert not can_be_requested(new_loan) loc_public_martigny['allow_request'] = True loc_public_martigny.update( loc_public_martigny, dbcommit=True, reindex=True ) flush_index(LocationsSearch.Meta.index)
def test_loan_utils(client, patron_martigny_no_email, patron2_martigny_no_email, circulation_policies, item_lib_martigny, librarian_martigny_no_email, loc_public_martigny): """Test loan utils methods.""" loan_metadata = dict(item_lib_martigny) loan_metadata['item_pid'] = item_pid_to_object(item_lib_martigny.pid) if 'patron_pid' not in loan_metadata: loan_metadata['patron_pid'] = patron_martigny_no_email.pid # Create "virtual" Loan (not registered) loan = Loan(loan_metadata) # test that loan can successfully move to the pending state assert can_be_requested(loan) # test that loan without an item may not move to the pending state del loan['item_pid'] with pytest.raises(Exception): assert can_be_requested(loan) # test a pending loan will be attached at the right organisation and # will not be considered as an active loan params = { 'patron_pid': patron2_martigny_no_email.pid, 'transaction_location_pid': loc_public_martigny.pid, 'transaction_user_pid': librarian_martigny_no_email.pid, 'pickup_location_pid': loc_public_martigny.pid } item, loan_pending_martigny = item_record_to_a_specific_loan_state( item=item_lib_martigny, loan_state=LoanState.PENDING, params=params, copy_item=True) assert loan_pending_martigny.patron_pid == patron2_martigny_no_email.pid assert not loan_pending_martigny.is_active assert loan_pending_martigny.organisation_pid # test required parameters for get_loans_by_patron_pid with pytest.raises(TypeError): assert get_loans_by_patron_pid() assert get_loans_by_patron_pid(patron2_martigny_no_email.pid) # test required parameters for get_last_transaction_loc_for_item with pytest.raises(TypeError): assert get_last_transaction_loc_for_item() # test the organisation of the loan is based on the item new_loan = deepcopy(loan_pending_martigny) assert new_loan.organisation_pid del new_loan['item_pid'] with pytest.raises(IlsRecordError.PidDoesNotExist): new_loan.organisation_pid assert not can_be_requested(loan_pending_martigny) # test the allow request at the location level loc_public_martigny['allow_request'] = False loc_public_martigny.update( loc_public_martigny, dbcommit=True, reindex=True ) flush_index(LocationsSearch.Meta.index) new_loan = { 'patron_pid': patron_martigny_no_email.pid, 'transaction_location_pid': loc_public_martigny.pid, 'transaction_user_pid': librarian_martigny_no_email.pid, 'pickup_location_pid': loc_public_martigny.pid } with pytest.raises(RecordCannotBeRequestedError): item, loan_pending_martigny = item_record_to_a_specific_loan_state( item=item_lib_martigny, loan_state=LoanState.PENDING, params=params, copy_item=True) loc_public_martigny['allow_request'] = True loc_public_martigny.update( loc_public_martigny, dbcommit=True, reindex=True ) flush_index(LocationsSearch.Meta.index) item, loan_pending_martigny = item_record_to_a_specific_loan_state( item=item_lib_martigny, loan_state=LoanState.PENDING, params=params, copy_item=True) assert loan_pending_martigny['state'] == LoanState.PENDING
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)