def loaded_resources_report(): """For debug only: returns a list or count of loaded objects.""" objects = { 'organisations': Organisation, 'libraries': Library, 'locations': Location, 'circ_policies': CircPolicy, 'item_types': ItemType, 'patron_types': PatronType, 'patrons': Patron, 'documents': Document, 'items': Item, 'holdings': Holding } report = {} for object in objects: object_pids = objects[object].get_all_pids() report[object] = len(list(object_pids)) item_details = [] if object == 'items': for item in object_pids: item_details.append({ 'item_pid': item, 'item_status': objects[object].get_record_by_pid(item).status, 'requests': objects[object].get_record_by_pid( item).number_of_requests(), 'loans': get_loan_for_item(item_pid_to_object(item)) }) report['item_details'] = item_details return report
def test_loans_build_refs(item_lib_martigny, patron_martigny, document): """Test functions buildings refs.""" # Create "virtual" Loan (not registered) loan = Loan({ 'item_pid': item_pid_to_object(item_lib_martigny.pid), 'document_pid': document.pid, 'patron_pid': patron_martigny.pid }) assert loan_build_item_ref(None, loan) == \ get_ref_for_pid('items', item_lib_martigny.pid) assert loan_build_document_ref(None, loan) == \ get_ref_for_pid('doc', document.pid) assert loan_build_patron_ref(None, loan) == \ get_ref_for_pid('patrons', patron_martigny.pid)
def test_location_disallow_request(item_lib_martigny, loc_public_martigny, loc_public_martigny_data, lib_martigny, patron_martigny): """Test a request when location disallow request.""" # update location to disallow request location = loc_public_martigny location['allow_request'] = False location.update(location, dbcommit=True, reindex=True) # Create "virtual" Loan (not registered) loan = Loan({ 'item_pid': item_pid_to_object(item_lib_martigny.pid), 'library_pid': lib_martigny.pid, 'patron_pid': patron_martigny.pid }) assert not can_be_requested(loan) # reset the location to original data location.update(loc_public_martigny_data, dbcommit=True, reindex=True)
def item(item_barcode): """HTTP GET request for requested loans for a library item and patron.""" item = Item.get_item_by_barcode(item_barcode, current_librarian.organisation_pid) if not item: abort(404) loan = get_loan_for_item(item_pid_to_object(item.pid)) if loan: loan = Loan.get_record_by_pid(loan.get('pid')).dumps_for_circulation() item_dumps = item.dumps_for_circulation() patron_pid = flask_request.args.get('patron_pid') if patron_pid: patron = Patron.get_record_by_pid(patron_pid) organisation_pid = item.organisation_pid library_pid = item.library_pid patron_type_pid = patron.patron_type_pid item_type_pid = item.item_type_circulation_category_pid circ_policy = CircPolicy.provide_circ_policy( organisation_pid=organisation_pid, library_pid=library_pid, patron_type_pid=patron_type_pid, item_type_pid=item_type_pid) new_actions = [] # If circulation policy doesn't allow checkout operation no need to # perform special check describe below. if circ_policy.can_checkout: for action in item_dumps.get('actions', []): if action == 'checkout': if (item.number_of_requests() > 0 and item.patron_request_rank(patron) == 1 or item.number_of_requests() <= 0): new_actions.append(action) elif action == 'receive' and item.number_of_requests() == 0: new_actions.append('checkout') item_dumps['actions'] = new_actions return jsonify({'metadata': {'item': item_dumps, 'loan': loan}})
def test_checkout_item_transit(client, item2_lib_martigny, librarian_martigny_no_email, librarian_saxon_no_email, patron_martigny_no_email, loc_public_saxon, lib_martigny, loc_public_martigny, circulation_policies): """Test checkout of an item in transit.""" assert item2_lib_martigny.available # request login_user_via_session(client, librarian_martigny_no_email.user) loc_public_martigny['notification_email'] = '*****@*****.**' loc_public_martigny['send_notification'] = True loc_public_martigny.update( loc_public_martigny.dumps(), dbcommit=True, reindex=True ) res, data = postdata( client, 'api_item.librarian_request', dict( item_pid=item2_lib_martigny.pid, pickup_location_pid=loc_public_saxon.pid, patron_pid=patron_martigny_no_email.pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid ) ) assert res.status_code == 200 actions = data.get('action_applied') loan_pid = actions[LoanAction.REQUEST].get('pid') assert not item2_lib_martigny.available loan = Loan.get_record_by_pid(loan_pid) assert loan['state'] == LoanState.PENDING # reset the location del loc_public_martigny['notification_email'] del loc_public_martigny['send_notification'] loc_public_martigny.update( loc_public_martigny.dumps(), dbcommit=True, reindex=True ) # validate request res, _ = postdata( client, 'api_item.validate_request', dict( item_pid=item2_lib_martigny.pid, pid=loan_pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid ) ) assert res.status_code == 200 assert not item2_lib_martigny.available item = Item.get_record_by_pid(item2_lib_martigny.pid) assert not item.available loan = Loan.get_record_by_pid(loan_pid) assert loan['state'] == LoanState.ITEM_IN_TRANSIT_FOR_PICKUP login_user_via_session(client, librarian_saxon_no_email.user) # receive res, _ = postdata( client, 'api_item.receive', dict( item_pid=item2_lib_martigny.pid, pid=loan_pid, transaction_library_pid=lib_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid ) ) assert res.status_code == 200 assert not item2_lib_martigny.available item = Item.get_record_by_pid(item2_lib_martigny.pid) assert not item.available loan_before_checkout = get_loan_for_item(item_pid_to_object(item.pid)) assert loan_before_checkout.get('state') == LoanState.ITEM_AT_DESK # checkout res, _ = postdata( client, 'api_item.checkout', dict( item_pid=item2_lib_martigny.pid, patron_pid=patron_martigny_no_email.pid, transaction_location_pid=loc_public_martigny.pid, transaction_user_pid=librarian_martigny_no_email.pid, ) ) assert res.status_code == 200 item = Item.get_record_by_pid(item2_lib_martigny.pid) loan_after_checkout = get_loan_for_item(item_pid_to_object(item.pid)) assert loan_after_checkout.get('state') == LoanState.ITEM_ON_LOAN assert loan_before_checkout.get('pid') == loan_after_checkout.get('pid')
def test_item_item_location_retriever(item_lib_martigny, loc_public_martigny, loc_restricted_martigny): """Test location retriever for invenio-circulation.""" assert item_location_retriever(item_pid_to_object( item_lib_martigny.pid)) == loc_public_martigny.pid
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