예제 #1
0
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
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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}})
예제 #5
0
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')
예제 #6
0
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
예제 #7
0
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