Пример #1
0
def test_recall_notification_without_email(
        client, patron_sion_without_email1, lib_martigny, json_header,
        patron2_martigny, item3_lib_martigny, librarian_martigny,
        circulation_policies, loc_public_martigny, mailbox):
    """Test recall notification."""
    mailbox.clear()
    login_user_via_session(client, librarian_martigny.user)
    res, data = postdata(
        client, 'api_item.checkout',
        dict(
            item_pid=item3_lib_martigny.pid,
            patron_pid=patron_sion_without_email1.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')
    loan = Loan.get_record_by_pid(loan_pid)

    assert not loan.is_notified(
        notification_type=Notification.RECALL_NOTIFICATION_TYPE)
    # test notification
    res, data = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item3_lib_martigny.pid,
             pickup_location_pid=loc_public_martigny.pid,
             patron_pid=patron2_martigny.pid,
             transaction_library_pid=lib_martigny.pid,
             transaction_user_pid=librarian_martigny.pid))
    assert res.status_code == 200

    request_loan_pid = data.get('action_applied')[LoanAction.REQUEST].get(
        'pid')

    flush_index(NotificationsSearch.Meta.index)

    assert loan.is_notified(
        notification_type=Notification.RECALL_NOTIFICATION_TYPE)
    notification = get_notification(
        loan, notification_type=Notification.RECALL_NOTIFICATION_TYPE)
    assert notification.loan_pid == loan.pid
    assert not loan.is_notified(
        notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE)
    assert not get_notification(
        loan, notification_type=Notification.AVAILABILITY_NOTIFICATION_TYPE)

    # one new email for the librarian
    assert mailbox[0].recipients == [
        lib_martigny.email_notification_type(notification['notification_type'])
    ]
    mailbox.clear()
Пример #2
0
def test_patron_information(client, librarian_martigny,
                            selfcheck_patron_martigny, loc_public_martigny,
                            item_lib_martigny, item2_lib_martigny,
                            circulation_policies, lib_martigny):
    """Test patron information."""
    login_user_via_session(client, librarian_martigny.user)
    # checkout
    res, data = postdata(
        client, 'api_item.checkout',
        dict(item_pid=item_lib_martigny.pid,
             patron_pid=selfcheck_patron_martigny.pid,
             transaction_user_pid=librarian_martigny.pid,
             transaction_location_pid=loc_public_martigny.pid))
    assert res.status_code == 200
    actions = data.get('action_applied')
    loan_pid = actions[LoanAction.CHECKOUT].get('pid')
    loan = Loan.get_record_by_pid(loan_pid)
    assert not loan.is_loan_overdue()
    # set loan on overdue
    end_date = datetime.now(timezone.utc) - timedelta(days=7)
    loan['end_date'] = end_date.isoformat()
    loan.update(loan, dbcommit=True, reindex=True)
    loan = Loan.get_record_by_pid(loan_pid)
    assert loan.is_loan_overdue()
    loan.create_notification(
        notification_type=Notification.OVERDUE_NOTIFICATION_TYPE)
    flush_index(NotificationsSearch.Meta.index)
    flush_index(LoansSearch.Meta.index)
    assert number_of_reminders_sent(loan) == 1
    # create request
    res, data = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item2_lib_martigny.pid,
             patron_pid=selfcheck_patron_martigny.pid,
             pickup_location_pid=loc_public_martigny.pid,
             transaction_library_pid=lib_martigny.pid,
             transaction_user_pid=librarian_martigny.pid))
    assert res.status_code == 200
    # get patron information
    response = patron_information(
        selfcheck_patron_martigny.get('patron', {}).get('barcode')[0])
    assert response

    # checkin
    res, _ = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item_lib_martigny.pid,
             pid=loan_pid,
             transaction_user_pid=librarian_martigny.pid,
             transaction_location_pid=loc_public_martigny.pid))
    assert res.status_code == 200
Пример #3
0
def test_local_fields_post_put_delete(client, org_sion, document,
                                      local_field_sion_data, json_header):
    """Test POST and PUT on local fields."""
    lf_pid = local_field_sion_data['pid']
    item_url = url_for('invenio_records_rest.lofi_item', pid_value=lf_pid)
    list_url = url_for('invenio_records_rest.lofi_list', q=f'pid:{lf_pid}')

    res, data = postdata(client, 'invenio_records_rest.lofi_list',
                         local_field_sion_data)
    assert res.status_code == 201

    assert data['metadata'] == local_field_sion_data

    res = client.get(item_url)
    assert res.status_code == 200
    data = get_json(res)
    assert local_field_sion_data == data['metadata']

    data = deepcopy(local_field_sion_data)
    data['fields']['field_2'] = ['field 2']
    res = client.put(
        item_url,
        data=json.dumps(data),
        headers=json_header
    )
    assert res.status_code == 200

    data = get_json(res)
    assert data['metadata']['fields']['field_2'][0] == 'field 2'

    res = client.get(list_url)
    assert res.status_code == 200
    data = get_json(res)['hits']['hits'][0]
    assert data['metadata']['fields']['field_2'][0] == 'field 2'

    # Check duplicate record
    res, _ = postdata(client, 'invenio_records_rest.lofi_list', data)
    assert res.status_code == 400

    res = client.get(url_for(
        'invenio_records_rest.lofi_list',
        q=f'organisation.pid:{data["metadata"]["organisation"]["pid"]}'))
    data = get_json(res)
    assert data['hits']['total']['value'] == 1

    # Delete record
    res = client.delete(item_url)
    assert res.status_code == 204

    res = client.get(item_url)
    assert res.status_code == 410
Пример #4
0
def test_checking_out_external_items_at_non_circ_library(
        client, librarian_martigny, lib_martigny, lib_martigny_bourg,
        patron_martigny, loc_public_martigny, loc_public_martigny_bourg,
        item_lib_martigny_bourg, circulation_policies, item_lib_martigny,
        librarian_martigny_bourg):
    """Test checkout of external items at non-circ library."""
    login_user_via_session(client, librarian_martigny_bourg.user)
    # A non-circulation library (has no pickup configured) and library hours is
    # well configured
    opening_hours = [
      {
        "day": "monday",
        "is_open": True,
        "times": [
          {
            "start_time": "07:00",
            "end_time": "19:00"
          }
        ]
      }
    ]
    lib_martigny_bourg['opening_hours'] = opening_hours
    lib_martigny_bourg.update(lib_martigny_bourg, dbcommit=True, reindex=True)
    # a librarian from the non-circulating library can checkout items from
    # another library into his library
    params = dict(
        item_pid=item_lib_martigny.pid,
        patron_pid=patron_martigny.pid,
        transaction_user_pid=librarian_martigny_bourg.pid,
        transaction_library_pid=lib_martigny_bourg.pid,
    )
    res, data = postdata(
        client,
        'api_item.checkout',
        params
    )
    assert res.status_code == 200
    # the checkin is possible at the non-circulating library and the item goes
    # directly to in-transit
    res, data = postdata(
        client,
        'api_item.checkin',
        dict(
            item_pid=item_lib_martigny.pid,
            transaction_library_pid=lib_martigny_bourg.pid,
            transaction_user_pid=librarian_martigny_bourg.pid,
        )
    )
    assert res.status_code == 200
    item = Item.get_record_by_pid(item_lib_martigny.pid)
    assert item.status == ItemStatus.IN_TRANSIT
Пример #5
0
def test_create_over_and_due_soon_notifications_task(
        client, librarian_martigny_no_email, patron_martigny_no_email,
        item_lib_martigny, circ_policy_short_martigny, loc_public_martigny,
        lib_martigny):
    """Test overdue and due_soon loans."""
    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
    # checkout
    res, data = postdata(client, 'api_item.checkout',
                         dict(item_pid=item_pid, patron_pid=patron_pid))
    assert res.status_code == 200

    loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid')
    loan = Loan.get_record_by_pid(loan_pid)

    # test due_soon notification
    end_date = datetime.now(timezone.utc) + timedelta(days=3)
    loan['end_date'] = end_date.isoformat()
    loan.update(loan, dbcommit=True, reindex=True)

    due_soon_loans = get_due_soon_loans()

    assert due_soon_loans[0].get('pid') == loan_pid

    create_over_and_due_soon_notifications()
    flush_index(NotificationsSearch.Meta.index)
    flush_index(LoansSearch.Meta.index)

    assert loan.is_notified(notification_type='due_soon')

    # test overdue notification
    end_date = datetime.now(timezone.utc) - timedelta(days=7)
    loan['end_date'] = end_date.isoformat()
    loan.update(loan, dbcommit=True, reindex=True)

    overdue_loans = get_overdue_loans()
    assert overdue_loans[0].get('pid') == loan_pid

    create_over_and_due_soon_notifications()
    flush_index(NotificationsSearch.Meta.index)
    flush_index(LoansSearch.Meta.index)

    assert loan.is_notified(notification_type='overdue')
    assert number_of_reminders_sent(loan) == 1

    # 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))
    assert res.status_code == 200
Пример #6
0
def test_patron_authenticate(client, patron_martigny, patron_martigny_data,
                             system_librarian_martigny):
    """Test for patron authenticate."""
    # parameters
    token = 'Or7DTg1WT34cLKuSMcS7WzhdhxtKklpTizb1Hn2H0aaV5Vig6nden63VEqBE'
    token_url_data = {'access_token': token}
    username = patron_martigny_data['username']
    password = patron_martigny_data['birth_date']

    create_personal(name='token_test',
                    user_id=system_librarian_martigny['user_id'],
                    access_token=token)

    # Missing access_token parameter
    res, _ = postdata(client, 'api_patrons.patron_authenticate')
    assert res.status_code == 401

    # Missing parameters (username and password)
    res, _ = postdata(client,
                      'api_patrons.patron_authenticate',
                      url_data=token_url_data)
    assert res.status_code == 400

    # User not found
    post_data = {'username': '******', 'password': '******'}
    res, _ = postdata(client,
                      'api_patrons.patron_authenticate',
                      post_data,
                      url_data=token_url_data)
    assert res.status_code == 404

    # User found, bad password
    post_data = {'username': username, 'password': '******'}
    res, _ = postdata(client,
                      'api_patrons.patron_authenticate',
                      post_data,
                      url_data=token_url_data)
    assert res.status_code == 401

    # User found
    post_data = {'username': username, 'password': password}
    res, output = postdata(client,
                           'api_patrons.patron_authenticate',
                           post_data,
                           url_data=token_url_data)
    assert res.status_code == 200
    assert output['city'] == patron_martigny_data['city']
    assert output['fullname'] == patron_martigny_data['first_name'] + ' ' +\
        patron_martigny_data['last_name']
    assert 'blocked' not in output
Пример #7
0
def test_item_different_actions(client, librarian_martigny_no_email,
                                lib_martigny, patron_martigny_no_email,
                                loc_public_martigny, item_lib_martigny,
                                json_header, item_type_standard_martigny,
                                circ_policy_short_martigny,
                                patron_type_children_martigny, lib_saxon,
                                loc_public_saxon, librarian_saxon_no_email):
    """Test item possible actions other scenarios."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    circ_policy_origin = deepcopy(circ_policy_short_martigny)
    circ_policy = circ_policy_short_martigny

    patron_pid = patron_martigny_no_email.pid
    res = client.get(
        url_for('api_item.item',
                item_barcode='does not exist',
                patron_pid=patron_pid))
    assert res.status_code == 404

    res, data = postdata(
        client, 'api_item.checkout',
        dict(item_pid=item_lib_martigny.pid, patron_pid=patron_pid))
    assert res.status_code == 200
    loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid')

    record = Item.get_record_by_pid(item_lib_martigny.pid)

    res, _ = postdata(
        client,
        'api_item.checkin',
        dict(item_pid='does not exist',
             pid=loan_pid,
             transaction_location_pid=loc_public_saxon.pid),
    )
    assert res.status_code == 404

    res, data = postdata(
        client,
        'api_item.checkin',
        dict(item_pid=item_lib_martigny.pid,
             pid=loan_pid,
             transaction_location_pid=loc_public_saxon.pid),
    )
    assert res.status_code == 200
    loan_pid = data.get('action_applied')[LoanAction.CHECKIN].get('pid')

    data = {'pid': loan_pid}
    params, actions = item_lib_martigny.prior_checkout_actions(data)
    assert 'cancel' in actions
Пример #8
0
def test_recall_notification(client, patron_martigny_no_email, lib_martigny,
                             json_header, patron2_martigny_no_email,
                             item_lib_martigny, librarian_martigny_no_email,
                             circulation_policies, loc_public_martigny):
    """Test recall notification."""
    # process all notifications still in the queue
    Notification.process_notifications()

    login_user_via_session(client, librarian_martigny_no_email.user)
    res, data = postdata(
        client,
        'api_item.checkout',
        dict(
            item_pid=item_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
    loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid')
    loan = Loan.get_record_by_pid(loan_pid)

    assert not loan.is_notified(notification_type='recall')
    # test notification permissions
    res, _ = postdata(
        client,
        'api_item.librarian_request',
        dict(
            item_pid=item_lib_martigny.pid,
            pickup_location_pid=loc_public_martigny.pid,
            patron_pid=patron2_martigny_no_email.pid,
            transaction_library_pid=lib_martigny.pid,
            transaction_user_pid=librarian_martigny_no_email.pid
        )
    )
    assert res.status_code == 200

    flush_index(NotificationsSearch.Meta.index)

    assert loan.is_notified(notification_type='recall')

    notification = get_recall_notification(loan)
    assert notification.loan_pid == loan.pid

    assert not loan.is_notified(notification_type='availability')
    assert not get_availability_notification(loan)
    assert Notification.process_notifications() == {
        'send': 1, 'reject': 0, 'error': 0}
Пример #9
0
def test_document_with_one_item_attached_bug(
        client, librarian_martigny_no_email, patron_martigny_no_email,
        patron2_martigny_no_email, loc_public_martigny,
        item_type_standard_martigny, item_lib_martigny, json_header,
        circulation_policies, lib_martigny):
    """Test document with one item."""
    login_user_via_session(client, librarian_martigny_no_email.user)

    # checkout first item1 to patron
    res, data = postdata(
        client, 'api_item.checkout',
        dict(item_pid=item_lib_martigny.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.CHECKOUT].get('pid')

    # request first item by patron2
    res, data = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item_lib_martigny.pid,
             pickup_location_pid=loc_public_martigny.pid,
             patron_pid=patron2_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')
    loan2_pid = actions[LoanAction.REQUEST].get('pid')

    # checkin the first item
    res, data = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item_lib_martigny.pid,
             pid=loan_pid,
             transaction_location_pid=loc_public_martigny.pid,
             transaction_user_pid=librarian_martigny_no_email.pid))
    assert res.status_code == 200

    assert item_lib_martigny.number_of_requests() == 1
    res, data = postdata(
        client, 'api_item.cancel_item_request',
        dict(pid=loan2_pid,
             transaction_location_pid=loc_public_martigny.pid,
             transaction_user_pid=librarian_martigny_no_email.pid))
    assert res.status_code == 200
    assert item_lib_martigny.number_of_requests() == 0
Пример #10
0
def test_patron_can_delete(client, librarian_martigny_no_email,
                           patron_martigny_no_email, loc_public_martigny,
                           item_lib_martigny, json_header, lib_martigny,
                           circulation_policies):
    """Test patron can delete."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    item = item_lib_martigny
    patron = patron_martigny_no_email
    location = loc_public_martigny

    data = deepcopy(patron_martigny_no_email)
    del data['patron']['type']
    assert not data.get_organisation()

    # request
    res, data = postdata(
        client,
        'api_item.librarian_request',
        dict(
            item_pid=item.pid,
            pickup_location_pid=location.pid,
            patron_pid=patron.pid,
            transaction_library_pid=lib_martigny.pid,
            transaction_user_pid=librarian_martigny_no_email.pid
        )
    )
    assert res.status_code == 200
    loan_pid = data.get('action_applied')[LoanAction.REQUEST].get('pid')

    links = patron_martigny_no_email.get_links_to_me()
    assert 'loans' in links

    assert not patron_martigny_no_email.can_delete

    reasons = patron_martigny_no_email.reasons_not_to_delete()
    assert 'links' in reasons

    res, data = postdata(
        client,
        'api_item.cancel_item_request',
        dict(
            pid=loan_pid,
            transaction_location_pid=loc_public_martigny.pid,
            transaction_user_pid=librarian_martigny_no_email.pid
        )
    )
    assert res.status_code == 200
    assert item.status == ItemStatus.ON_SHELF
Пример #11
0
def test_acq_order_secure_api_create(client, json_header,
                                     org_martigny,
                                     vendor_martigny, vendor2_martigny,
                                     acq_order_fiction_martigny,
                                     librarian_martigny,
                                     librarian_sion,
                                     acq_order_fiction_saxon,
                                     system_librarian_martigny):
    """Test acq order secure api create."""
    # Martigny
    login_user_via_session(client, librarian_martigny.user)
    post_entrypoint = 'invenio_records_rest.acor_list'

    data = acq_order_fiction_saxon
    del acq_order_fiction_saxon['pid']
    res, _ = postdata(
        client,
        post_entrypoint,
        data
    )
    assert res.status_code == 403

    data = deepcopy(acq_order_fiction_martigny)
    del data['pid']
    res, _ = postdata(
        client,
        post_entrypoint,
        data
    )
    assert res.status_code == 201

    login_user_via_session(client, system_librarian_martigny.user)
    res, _ = postdata(
        client,
        post_entrypoint,
        data
    )
    assert res.status_code == 201

    # Sion
    login_user_via_session(client, librarian_sion.user)

    res, _ = postdata(
        client,
        post_entrypoint,
        acq_order_fiction_saxon
    )
    assert res.status_code == 403
Пример #12
0
def test_request_notifications_temp_item_type(
    client, patron_martigny, patron_sion, lib_martigny, lib_fully,
    item_lib_martigny, librarian_martigny, loc_public_martigny,
    circulation_policies, loc_public_fully, item_type_missing_martigny, mailbox
):
    """Test request notifications with item type with negative availability."""
    mailbox.clear()
    login_user_via_session(client, librarian_martigny.user)
    item_lib_martigny['temporary_item_type'] = {
        '$ref': get_ref_for_pid('itty', item_type_missing_martigny.pid)
    }
    item_lib_martigny.update(item_lib_martigny, dbcommit=True, reindex=True)

    res, data = postdata(
        client,
        'api_item.librarian_request',
        dict(
            item_pid=item_lib_martigny.pid,
            pickup_location_pid=loc_public_fully.pid,
            patron_pid=patron_martigny.pid,
            transaction_library_pid=lib_martigny.pid,
            transaction_user_pid=librarian_martigny.pid
        )
    )
    assert res.status_code == 200

    request_loan_pid = data.get(
        'action_applied')[LoanAction.REQUEST].get('pid')

    flush_index(NotificationsSearch.Meta.index)
    assert len(mailbox) == 0

    # cancel request
    res, _ = postdata(
        client,
        'api_item.cancel_item_request',
        dict(
            item_pid=item_lib_martigny.pid,
            pid=request_loan_pid,
            transaction_user_pid=librarian_martigny.pid,
            transaction_library_pid=lib_martigny.pid
        )
    )
    assert res.status_code == 200
    mailbox.clear()

    del(item_lib_martigny['temporary_item_type'])
    item_lib_martigny.update(item_lib_martigny, dbcommit=True, reindex=True)
Пример #13
0
def test_items_extend_end_date(client, librarian_martigny_no_email,
                               patron_martigny_no_email, loc_public_martigny,
                               item_type_standard_martigny, item_lib_martigny,
                               json_header, circ_policy_short_martigny):
    """Test correct renewal due date for items."""
    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

    # 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')
    loan = Loan.get_record_by_pid(loan_pid)
    assert not item.get_extension_count()

    max_count = get_extension_params(loan=loan, parameter_name='max_count')
    renewal_duration_policy = circ_policy_short_martigny['renewal_duration']
    renewal_duration = get_extension_params(loan=loan,
                                            parameter_name='duration_default')
    assert renewal_duration_policy <= renewal_duration.days

    # extend loan
    res, data = postdata(client, 'api_item.extend_loan',
                         dict(item_pid=item_pid, pid=loan_pid))

    assert res.status_code == 200

    # Compare expected loan date with processed one
    # first get loan UTC date
    actions = data.get('action_applied')
    loan_pid = actions[LoanAction.EXTEND].get('pid')
    loan = Loan.get_record_by_pid(loan_pid)
    loan_date = loan.get('end_date')
    # then process a date with current UTC date + renewal
    current_date = datetime.now(timezone.utc)
    calc_date = current_date + renewal_duration
    # finally the comparison should give the same date (in UTC)!
    assert (calc_date.strftime('%Y-%m-%d') == ciso8601.parse_datetime(
        loan_date).astimezone(timezone.utc).strftime('%Y-%m-%d'))

    # checkin
    res, _ = postdata(client, 'api_item.checkin',
                      dict(item_pid=item_pid, pid=loan_pid))
    assert res.status_code == 200
Пример #14
0
def test_item_secure_api_create(client, json_header, item_lib_martigny,
                                librarian_martigny,
                                librarian_sion,
                                item_lib_martigny_data,
                                item_lib_saxon_data,
                                system_librarian_martigny):
    """Test item secure api create."""
    # Martigny
    login_user_via_session(client, librarian_martigny.user)
    post_url = 'invenio_records_rest.item_list'

    del item_lib_martigny_data['pid']
    res, _ = postdata(
        client,
        post_url,
        item_lib_martigny_data
    )
    # librarian can create items on its affiliated library
    assert res.status_code == 201

    del item_lib_saxon_data['pid']
    res, _ = postdata(
        client,
        post_url,
        item_lib_saxon_data
    )
    # librarian can not create items for another library
    assert res.status_code == 403

    login_user_via_session(client, system_librarian_martigny.user)
    res, _ = postdata(
        client,
        post_url,
        item_lib_saxon_data
    )
    # sys_librarian can create items for any library
    assert res.status_code == 201

    # Sion
    login_user_via_session(client, librarian_sion.user)

    res, _ = postdata(
        client,
        post_url,
        item_lib_martigny_data
    )
    # librarian can not create items in another organisation
    assert res.status_code == 403
Пример #15
0
def test_requested_loans_to_validate(client, librarian_martigny,
                                     loc_public_martigny,
                                     item_type_standard_martigny,
                                     item2_lib_martigny, json_header,
                                     patron_sion, circulation_policies):
    """Test requested loans to validate."""
    login_user_via_session(client, librarian_martigny.user)
    library_pid = librarian_martigny\
        .replace_refs()['libraries'][0]['pid']

    res, _ = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item2_lib_martigny.pid,
             patron_pid=patron_sion.pid,
             pickup_location_pid=loc_public_martigny.pid,
             transaction_user_pid=librarian_martigny.pid,
             transaction_location_pid=loc_public_martigny.pid))

    res = client.get(
        url_for('api_item.requested_loans', library_pid=library_pid))
    assert res.status_code == 200
    data = get_json(res)
    assert 1 == data['hits']['total']['value']
    requested_loan = data['hits']['hits'][0]
    assert item2_lib_martigny.pid == requested_loan['item']['pid']
    assert item2_lib_martigny.pid == \
        requested_loan['loan']['item_pid']['value']
    assert LoanState.PENDING == requested_loan['loan']['state']
    assert patron_sion.pid == requested_loan['loan']['patron_pid']
Пример #16
0
def test_patrons_post_without_email(client, lib_martigny,
                                    patron_type_children_martigny,
                                    patron_martigny_data_tmp, json_header,
                                    roles, mailbox):
    """Test record retrieval."""
    patron_data = patron_martigny_data_tmp

    pids = Patron.count()
    assert len(mailbox) == 0

    # Create record / POST
    del patron_data['pid']
    del patron_data['email']
    patron_data['patron']['communication_channel'] = 'mail'
    patron_data['patron']['additional_communication_email'] = '*****@*****.**'
    patron_data['username'] = '******'

    res, _ = postdata(client, 'invenio_records_rest.ptrn_list', patron_data)

    assert res.status_code == 201
    assert Patron.count() == pids + 1
    assert len(mailbox) == 0

    # Check that the returned record matches the given data
    data = get_json(res)
    # remove dynamic property
    del data['metadata']['user_id']
    del data['metadata']['pid']
    assert data['metadata'] == patron_data
Пример #17
0
def test_acq_receipt_lines_post_put_delete(client, org_martigny,
                                           vendor2_martigny,
                                           acq_order_line_fiction_saxon,
                                           acq_receipt_fiction_sion,
                                           acq_receipt_line_fiction_saxon,
                                           json_header):
    """Test record retrieval."""
    # Create record / POST
    item_url = url_for('invenio_records_rest.acrl_item', pid_value='1')
    list_url = url_for('invenio_records_rest.acrl_list', q='pid:1')

    acq_receipt_line_fiction_saxon['pid'] = '1'
    res, data = postdata(
        client,
        'invenio_records_rest.acrl_list',
        acq_receipt_line_fiction_saxon
    )
    assert res.status_code == 201

    # Check that the returned record matches the given data
    assert data['metadata'] == acq_receipt_line_fiction_saxon

    res = client.get(item_url)
    assert res.status_code == 200
    data = get_json(res)
    assert acq_receipt_line_fiction_saxon == data['metadata']

    # Update record/PUT
    data = acq_receipt_line_fiction_saxon
    notes = [{'content': 'test', 'type': AcqReceiptLineNoteType.STAFF}]
    data['notes'] = notes
    res = client.put(
        item_url,
        data=json.dumps(data),
        headers=json_header
    )
    assert res.status_code == 200

    # Check that the returned record matches the given data
    data = get_json(res)
    assert data['metadata']['notes'] == notes

    res = client.get(item_url)
    assert res.status_code == 200

    data = get_json(res)
    assert data['metadata']['notes'] == notes

    res = client.get(list_url)
    assert res.status_code == 200

    data = get_json(res)['hits']['hits'][0]
    assert data['metadata']['notes'] == notes

    # Delete record/DELETE
    res = client.delete(item_url)
    assert res.status_code == 204

    res = client.get(item_url)
    assert res.status_code == 410
Пример #18
0
def test_issues_permissions(client, json_header,
                            holding_lib_martigny_w_patterns,
                            librarian_martigny):
    """Test specific items issues permissions."""

    # receive a regular issue
    holding = holding_lib_martigny_w_patterns
    holding = Holding.get_record_by_pid(holding.pid)
    login_user_via_session(client, librarian_martigny.user)
    res, data = postdata(client,
                         'api_holding.receive_regular_issue',
                         url_data=dict(holding_pid=holding.pid))
    assert res.status_code == 200
    data = get_json(res)
    issue_item = Item.get_record_by_pid(data.get('issue', {}).get('pid'))
    assert issue_item is not None
    assert issue_item.issue_is_regular

    # a regular issue cannot be deleted
    res = client.get(
        url_for('api_blueprint.permissions',
                route_name='items',
                record_pid=issue_item.pid))
    assert res.status_code == 200
    data = get_json(res)
    assert not data['delete']['can']
Пример #19
0
def test_vendor_post_update_delete(client, librarian_martigny_no_email,
                                   vendor3_martigny_data, json_header):
    """Test CRUD on vendor."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    item_url = url_for('invenio_records_rest.vndr_item', pid_value='vndr3')

    # create
    vendor3_martigny_data['pid'] = 'vndr3'
    res, data = postdata(client, 'invenio_records_rest.vndr_list',
                         vendor3_martigny_data)
    assert res.status_code == 201

    # read
    res = client.get(item_url)
    assert res.status_code == 200
    data = get_json(res)
    assert data['metadata'] == vendor3_martigny_data

    # update
    data = vendor3_martigny_data
    data['name'] = 'Test update Name'
    res = client.put(item_url, data=json.dumps(data), headers=json_header)
    assert res.status_code == 200

    # Check that the returned record matches the given data
    data = get_json(res)
    assert data['metadata']['name'] == 'Test update Name'

    # delete
    res = client.delete(item_url)
    assert res.status_code == 204

    res = client.get(item_url)
    assert res.status_code == 410
Пример #20
0
def test_operation_logs_rest(client, loan_pending_martigny, librarian_martigny,
                             json_header, loan_overdue_martigny):
    """Test operation logs REST API."""
    login_user_via_session(client, librarian_martigny.user)
    item_url = url_for('invenio_records_rest.oplg_item', pid_value='1')
    item_list = url_for('invenio_records_rest.oplg_list')

    res = client.get(item_url)
    assert res.status_code == 404

    res = client.get(item_list)
    assert res.status_code == 200
    data = get_json(res)
    assert data['hits']['total']['value'] > 0
    pid = data['hits']['hits'][0]['metadata']['pid']
    assert pid
    assert data['hits']['hits'][0]['id'] == pid
    assert data['hits']['hits'][0]['created']
    assert data['hits']['hits'][0]['updated']

    res, _ = postdata(client, 'invenio_records_rest.oplg_list', {})
    assert res.status_code == 403

    res = client.put(url_for('invenio_records_rest.oplg_item', pid_value='1'),
                     data={},
                     headers=json_header)
    assert res.status_code == 404

    res = client.delete(item_url)
    assert res.status_code == 404
def test_circ_policies_permissions(
        client, circ_policy_default_martigny, json_header):
    """Test policy retrieval."""
    item_url = url_for('invenio_records_rest.cipo_item', pid_value='cipo1')

    res = client.get(item_url)
    assert res.status_code == 401

    res, _ = postdata(
        client,
        'invenio_records_rest.cipo_list',
        {}
    )
    assert res.status_code == 401

    res = client.put(
        url_for('invenio_records_rest.cipo_item', pid_value='cipo1'),
        data={},
        headers=json_header
    )

    res = client.delete(item_url)
    assert res.status_code == 401

    res = client.get(url_for('circ_policies.name_validate', name='standard'))
    assert res.status_code == 401
Пример #22
0
def test_selfcheck_checkout(client, sip2_librarian_martigny_no_email,
                            sip2_patron_martigny_no_email, loc_public_martigny,
                            item_lib_martigny, librarian2_martigny_no_email,
                            circulation_policies):
    """Test selfcheck checkout."""
    patron_barcode = sip2_patron_martigny_no_email \
        .get('patron', {}).get('barcode')
    item_barcode = item_lib_martigny.get('barcode')

    # selfcheck checkout
    checkout = selfcheck_checkout(
        user_pid=sip2_librarian_martigny_no_email.pid,
        institution_id=sip2_librarian_martigny_no_email.library_pid,
        patron_barcode=patron_barcode,
        item_barcode=item_barcode,
    )
    assert checkout
    assert checkout.is_success
    assert checkout.due_date

    # librarian checkin
    login_user_via_session(client, librarian2_martigny_no_email.user)
    res, _ = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item_lib_martigny.pid,
             transaction_user_pid=librarian2_martigny_no_email.pid,
             transaction_location_pid=loc_public_martigny.pid))
    assert res.status_code == 200
Пример #23
0
def test_selfcheck_checkout(client, selfcheck_librarian_martigny,
                            selfcheck_patron_martigny, loc_public_martigny,
                            item_lib_martigny, librarian_martigny,
                            librarian2_martigny, circulation_policies):
    """Test selfcheck checkout."""
    patron_barcode = selfcheck_patron_martigny \
        .get('patron', {}).get('barcode')[0]
    item_barcode = item_lib_martigny.get('barcode')

    # selfcheck checkout
    checkout = selfcheck_checkout(transaction_user_pid=librarian_martigny.pid,
                                  item_barcode=item_barcode,
                                  patron_barcode=patron_barcode,
                                  terminal=selfcheck_librarian_martigny.name)
    assert checkout
    assert checkout.is_success
    assert checkout.due_date

    # librarian checkin
    login_user_via_session(client, librarian2_martigny.user)
    res, _ = postdata(
        client, 'api_item.checkin',
        dict(item_pid=item_lib_martigny.pid,
             transaction_user_pid=librarian2_martigny.pid,
             transaction_location_pid=loc_public_martigny.pid))
    assert res.status_code == 200
Пример #24
0
def test_loans_logged_permissions(client, loan_pending_martigny,
                                  librarian_martigny_no_email,
                                  json_header):
    """Test record retrieval."""
    login_user_via_session(client, librarian_martigny_no_email.user)
    item_url = url_for('invenio_records_rest.loanid_item', pid_value='1')

    res = client.get(item_url)
    assert res.status_code == 200

    res, _ = postdata(
        client,
        'invenio_records_rest.loanid_list',
        {}
    )
    assert res.status_code == 403

    res = client.put(
        url_for('invenio_records_rest.loanid_item', pid_value='1'),
        data={},
        headers=json_header
    )

    res = client.delete(item_url)
    assert res.status_code == 403
Пример #25
0
def test_patrons_post_without_email(app, client, lib_martigny,
                                    patron_type_children_martigny,
                                    patron_martigny_data_tmp, json_header,
                                    roles, mailbox):
    """Test record retrieval."""
    patron_data = deepcopy(patron_martigny_data_tmp)
    patron_data['email'] = '*****@*****.**'
    patron_data['username'] = '******'
    del patron_data['pid']
    del patron_data['email']
    patron_data['patron']['communication_channel'] = 'mail'
    patron_data = create_user_from_data(patron_data)

    pids = Patron.count()
    assert len(mailbox) == 0

    # Create record / POST
    res, _ = postdata(client, 'invenio_records_rest.ptrn_list', patron_data)

    assert res.status_code == 201
    assert Patron.count() == pids + 1
    assert len(mailbox) == 0

    # Check that the returned record matches the given data
    data = get_json(res)
    data['metadata']['patron']['communication_channel'] = 'mail'

    ds = app.extensions['invenio-accounts'].datastore
    ds.delete_user(ds.find_user(id=patron_data['user_id']))
Пример #26
0
def test_patrons_permissions(client, librarian_martigny_no_email,
                             json_header):
    """Test record retrieval."""
    item_url = url_for(
        'invenio_records_rest.ptrn_item',
        pid_value=librarian_martigny_no_email.pid)

    res = client.get(item_url)
    assert res.status_code == 401

    res, _ = postdata(
        client,
        'invenio_records_rest.ptrn_list',
        {}
    )
    assert res.status_code == 401

    res = client.put(
        item_url,
        data={},
        headers=json_header
    )

    res = client.delete(item_url)
    assert res.status_code == 401
Пример #27
0
def test_ilsrecord_pid_after_validationerror(client, loc_online_martigny_data,
                                             librarian_martigny_no_email):
    """Check PID before and after a ValidationError: it should be the same"""
    loc = Location.create(loc_online_martigny_data, delete_pid=True)
    next_pid = str(int(loc.pid) + 1)

    # post invalid data and post them
    login_user_via_session(client, librarian_martigny_no_email.user)
    res, _ = postdata(
        client, 'invenio_records_rest.loc_list', {
            '$schema':
            'https://ils.rero.ch/schemas/locations/location-v0.0.1.json',
            'library': {
                '$ref': 'https://ils.rero.ch/api/libraries/lib1'
            },
            'name': 'Library of Foo'
        })

    # check http status for invalid record
    assert res.status_code == 400

    # the pid should be unchanged
    loc.provider.identifier.query.first().recid == loc.pid

    # check that we can create a new location
    loc2 = Location.create(loc_online_martigny_data, delete_pid=True)
    loc2.pid == next_pid
Пример #28
0
def test_notifications_permissions(
        client, notification_availability_martigny, json_header):
    """Test notification permissions."""

    notif = notification_availability_martigny
    pid = notif.get('pid')
    item_url = url_for('invenio_records_rest.notif_item', pid_value=pid)

    res = client.get(item_url)
    assert res.status_code == 401

    res, _ = postdata(
        client,
        'invenio_records_rest.notif_list',
        {}
    )
    assert res.status_code == 401

    res = client.put(
        item_url,
        data={},
        headers=json_header
    )

    res = client.delete(item_url)
    assert res.status_code == 401
Пример #29
0
def test_items_deny_requests(client, librarian_martigny_no_email,
                             patron_martigny_no_email, loc_public_martigny,
                             item_type_standard_martigny, item_lib_martigny,
                             json_header, circ_policy_short_martigny):
    """Test items when requests are denied."""
    location = loc_public_martigny
    circ_policy_short_martigny['allow_requests'] = False
    circ_policy_short_martigny.update(data=circ_policy_short_martigny,
                                      dbcommit=True,
                                      reindex=True)
    flush_index(CircPoliciesSearch.Meta.index)
    login_user_via_session(client, librarian_martigny_no_email.user)
    item = item_lib_martigny
    item_pid = item.pid
    patron = patron_martigny_no_email
    patron_pid = patron.pid

    # request
    res, _ = postdata(
        client, 'api_item.librarian_request',
        dict(item_pid=item_pid,
             pickup_location_pid=location.pid,
             patron_pid=patron_pid))
    assert res.status_code == 403

    circ_policy_short_martigny['allow_requests'] = True
    circ_policy_short_martigny.update(data=circ_policy_short_martigny,
                                      dbcommit=True,
                                      reindex=True)
    flush_index(CircPoliciesSearch.Meta.index)
    assert circ_policy_short_martigny.get('allow_requests')
Пример #30
0
def test_create_fee(client, librarian_martigny_no_email,
                    librarian_sion_no_email, patron_martigny_no_email,
                    loc_public_martigny, item_type_standard_martigny,
                    item_lib_martigny, json_header,
                    circ_policy_short_martigny):
    """Test overdue loans."""
    login_user_via_session(client, librarian_martigny_no_email.user)

    # checkout
    res, data = postdata(
        client, 'api_item.checkout',
        dict(item_pid=item_lib_martigny.pid,
             patron_pid=patron_martigny_no_email.pid))
    assert res.status_code == 200

    loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('pid')
    loan = Loan.get_record_by_pid(loan_pid)
    end_date = datetime.now(timezone.utc) - timedelta(days=7)
    loan['end_date'] = end_date.isoformat()
    loan.update(loan, dbcommit=True, reindex=True)

    overdue_loans = get_overdue_loans()
    assert overdue_loans[0].get('pid') == loan_pid

    notification = loan.create_notification(notification_type='overdue')
    flush_index(NotificationsSearch.Meta.index)
    flush_index(LoansSearch.Meta.index)

    fee = list(notification.fees)[0]
    assert fee.get('amount') == 2
    assert fee.get('currency') == 'CHF'

    fee_url = url_for('invenio_records_rest.fee_item', pid_value=fee.pid)

    res = client.get(fee_url)
    assert res.status_code == 200

    login_user_via_session(client, librarian_sion_no_email.user)

    res = client.get(fee_url)
    assert res.status_code == 403

    login_user_via_session(client, librarian_martigny_no_email.user)
    # checkin
    res, _ = postdata(client, 'api_item.checkin',
                      dict(item_pid=item_lib_martigny.pid, pid=loan_pid))
    assert res.status_code == 200