Пример #1
0
def test_send_only_to_test_recipients(app, users, testdata, mocker):
    """Tests that send only to test recipients works."""
    class TestMessage(BlockTemplatedMessage):
        def __init__(self, *args, **kwargs):
            template = "tests/subject_body_html.html"
            kwargs.pop("trigger", None)
            kwargs.pop("message_ctx", {})
            kwargs.setdefault("sender", app.config["MAIL_NOTIFY_SENDER"])
            super().__init__(template, **kwargs)

    app.config.update(
        dict(CELERY_TASK_ALWAYS_EAGER=True,
             ILS_MAIL_LOAN_MSG_LOADER=TestMessage,
             ILS_MAIL_ENABLE_TEST_RECIPIENTS=True))
    patron = Patron(users["patron1"].id)
    mocker.patch(
        "invenio_app_ils.records.api.Patron.get_patron",
        return_value=patron,
    )
    loan_data = testdata["loans"][-1]
    loan = Loan.get_record_by_pid(loan_data["pid"])
    fake_recipients = app.config["ILS_MAIL_NOTIFY_TEST_RECIPIENTS"]
    with app.extensions["mail"].record_messages() as outbox:
        assert len(outbox) == 0
        send_loan_mail("trigger", loan, subject="Test", body="Test")
        assert len(outbox) == 1
        assert outbox[0].recipients == fake_recipients
Пример #2
0
def test_loan_patron_resolver_for_anonymous_patron_pid(app, testdata):
    """Test item resolving from loan."""
    loan_pid = testdata["loans"][7]["pid"]
    loan = Loan.get_record_by_pid(loan_pid)
    loan = loan.replace_refs()
    assert loan["patron_pid"] == loan["patron"]["id"]
    assert loan["patron"]["name"] == "anonymous"
Пример #3
0
def test_loan_extend_permissions(app, client, json_headers, users, testdata,
                                 app_config, loan_params, user,
                                 expected_resp_code):
    """Test loan can be extended."""
    # Create a Loan for patron with pid 1
    login_user(users["librarian"])
    loan_data = testdata["loans"][0]
    loan = Loan.get_record_by_pid(loan_data["pid"])

    current_circulation.circulation.trigger(
        loan, **dict(loan_params, trigger="checkout"))

    user_login(client, "librarian", users)
    resp = client.get(url_for("invenio_records_rest.loanid_item",
                              pid_value=loan["pid"]),
                      headers=json_headers)
    loan = resp.get_json()

    # Remove payload params that break the request
    del loan_params["item_pid"]
    del loan_params["transaction_date"]
    extend_url = loan.get("links").get("actions").get("extend")

    user_login(client, user, users)
    extend_res = client.post(extend_url,
                             headers=json_headers,
                             data=json.dumps(loan_params))
    assert extend_res.status_code == expected_resp_code
Пример #4
0
def test_search_loans_by_pid(indexed_loans):
    """Test retrieve loan list belonging to an item."""
    item_pid = dict(type="itemid", value="item_pending_1")
    loans = list(search_by_pid(item_pid=item_pid).scan())
    assert len(loans) == 1
    loan = Loan.get_record_by_pid(loans[0]["pid"])
    assert loan["item_pid"] == item_pid
def check_user_activity(app, user_pid, client, json_headers):
    """ Check if there are records related to the user. """
    # wait ES refresh
    current_search.flush_and_refresh(index="*")

    AnonymousPatron = app.config["ILS_PATRON_ANONYMOUS_CLASS"]
    anonymous_patron_fields = AnonymousPatron().dumps_loader()

    loans = get_loans_by_patron_pid(user_pid).scan()
    for hit in loans:
        # test ES
        assert hit["patron"] == anonymous_patron_fields
        # test DB
        loan = Loan.get_record_by_pid(hit.pid)
        assert loan["patron"] == anonymous_patron_fields
        # test REST
        url = url_for("invenio_records_rest.loanid_item", pid_value=hit.pid)
        res = client.get(url, headers=json_headers)
        assert res.get_json()["metadata"]["patron"] == anonymous_patron_fields

    borrowing_requests = (
        BorrowingRequestsSearch().search_by_patron_pid(user_pid).scan())
    for hit in borrowing_requests:
        # test ES
        assert hit["patron"] == anonymous_patron_fields
        # test DB
        borrowing_request = BorrowingRequest.get_record_by_pid(hit.pid)
        assert borrowing_request["patron"] == anonymous_patron_fields
        # test REST
        url = url_for("invenio_records_rest.illbid_item", pid_value=hit.pid)
        res = client.get(url, headers=json_headers)
        assert res.get_json()["metadata"]["patron"] == anonymous_patron_fields

    document_requests = (
        DocumentRequestSearch().search_by_patron_pid(user_pid).scan())
    for hit in document_requests:
        # test ES
        assert hit["patron"] == anonymous_patron_fields
        # test DB
        document_request = DocumentRequest.get_record_by_pid(hit.pid)
        assert document_request["patron"] == anonymous_patron_fields
        # test REST
        url = url_for("invenio_records_rest.dreqid_item", pid_value=hit.pid)
        res = client.get(url, headers=json_headers)
        assert res.get_json()["metadata"]["patron"] == anonymous_patron_fields

    acquisitions = OrderSearch().search_by_patron_pid(user_pid).scan()
    for hit in acquisitions:
        # test ES
        assert hit["patron"] == anonymous_patron_fields
        # test DB
        acquisition = Order.get_record_by_pid(hit.pid)
        assert acquisition["patron"] == anonymous_patron_fields
        # test REST
        url = url_for("invenio_records_rest.acqoid_item", pid_value=hit.pid)
        res = client.get(url, headers=json_headers)
        assert res.get_json()["metadata"]["patron"] == anonymous_patron_fields
Пример #6
0
def test_loan_patron_resolver_for_non_existing_patron_pid(app, testdata):
    """Test item resolving from loan."""
    AnonymousPatron = app.config["ILS_PATRON_ANONYMOUS_CLASS"]
    loan_pid = testdata["loans"][6]["pid"]
    loan = Loan.get_record_by_pid(loan_pid)
    loan = loan.replace_refs()
    assert loan["patron_pid"] == str(20)
    assert loan["patron"]["id"] == str(AnonymousPatron.id)
    assert loan["patron"]["name"] == "anonymous"
Пример #7
0
def index_loans_after_item_indexed(item_pid):
    """Index loan to refresh item reference."""
    loan_search = search_by_pid(item_pid=item_pid)
    loan_ids = []
    for loan in loan_search.scan():
        record = Loan.get_record_by_pid(loan[Loan.pid_field])
        if record:
            loan_ids.append(record.id)

    RecordIndexer().bulk_index(loan_ids)
Пример #8
0
def test_email_on_loan_checkout(client, app_with_mail, users, testdata,
                                loan_params):
    """Test that an email is sent on loan checkout."""
    loan_data = testdata["loans"][1]
    loan = Loan.get_record_by_pid(loan_data["pid"])
    with app_with_mail.extensions["mail"].record_messages() as outbox:
        user_login(client, "admin", users)

        assert len(outbox) == 0
        current_circulation.circulation.trigger(
            loan, **dict(loan_params, trigger="checkout"))
        assert len(outbox) == 1
        msg = outbox[0]

    doc = Document.get_record_by_pid(loan_data["document_pid"])
    expected_subject = (
        """InvenioILS: your loan for "{0}" has started.""".format(
            doc["title"]))
    assert msg.subject == expected_subject

    edition_year = " ({edition} - {year})".format(edition=doc["edition"],
                                                  year=doc["publication_year"])
    full_title = "{title}, {author}{edition_year}".format(
        title=doc["title"],
        author=doc["authors"][0]["full_name"],
        edition_year=edition_year,
    )

    literature_url = "{host}{path}".format(
        host=current_app.config["SPA_HOST"],
        path=current_app.config["SPA_PATHS"]["literature"] %
        {"pid": doc["pid"]},
    )
    profile_url = "{host}{path}".format(
        host=current_app.config["SPA_HOST"],
        path=current_app.config["SPA_PATHS"]["profile"],
    )
    expected_body_plain = """Dear Patron One,

your loan for "{doc_full_title}" <{literature_url}> has started.

The due date is {loan_end_date}.

You can see your ongoing and past loans in your profile page <{profile_url}>.

Kind regards,
InvenioILS""".format(
        doc_full_title=full_title,
        literature_url=literature_url,
        loan_end_date=loan_data["end_date"],
        profile_url=profile_url,
    )
    assert msg.body == expected_body_plain
Пример #9
0
def test_email_on_loan_checkout(client, app_with_mail, users, testdata,
                                loan_params):
    """Test that an email is sent when an admin performs a loan checkout."""
    loan_data = testdata["loans"][1]
    loan = Loan.get_record_by_pid(loan_data["pid"])
    with app_with_mail.extensions["mail"].record_messages() as outbox:
        user_login(client, "admin", users)

        assert len(outbox) == 0
        current_circulation.circulation.trigger(
            loan, **dict(loan_params, trigger="checkout"))
        assert len(outbox) == 1
Пример #10
0
def test_email_on_overdue_loan(app, users, testdata, mocker):
    """Test that an email is sent when an admin performs a loan checkout."""
    app.config.update(CELERY_TASK_ALWAYS_EAGER=True)
    mocker.patch(
        "invenio_app_ils.records.api.Patron.get_patron",
        return_value=Patron(users["patron1"].id),
    )
    loan_data = testdata["loans"][-1]
    loan = Loan.get_record_by_pid(loan_data["pid"])
    with app.extensions["mail"].record_messages() as outbox:
        assert len(outbox) == 0
        send_loan_overdue_reminder_mail(loan)
        assert len(outbox) == 1
def test_search_loans_by_pid(indexed_loans):
    """Test retrieve loan list given belonging to an item."""
    loans = list(LoansSearch.search_loans_by_pid(item_pid='item_pending_1'))
    assert loans
    assert len(loans) == 1
    loan = Loan.get_record_by_pid(loans[0]['loan_pid'])
    assert loan.get('item_pid') == 'item_pending_1'

    loans = list(
        LoansSearch.search_loans_by_pid(
            item_pid='item_multiple_pending_on_loan_7',
            exclude_states=['ITEM_ON_LOAN'],
        ))
    assert len(loans) == 2
Пример #12
0
def test_email_on_loan_checkout(app, users, testdata, loan_params, mocker):
    """Test that an email is sent when an admin performs a loan checkout."""
    app.config.update(CELERY_TASK_ALWAYS_EAGER=True)

    loan_data = testdata["loans"][1]
    loan = Loan.get_record_by_pid(loan_data["pid"])
    with app.extensions["mail"].record_messages() as outbox:
        admin = users["admin"]
        login_user(admin)

        assert len(outbox) == 0
        current_circulation.circulation.trigger(
            loan, **dict(loan_params, trigger="checkout"))
        assert len(outbox) == 1
Пример #13
0
def cancel_expired_loan_requests():
    """Cancel loan requests after expiration date has passed."""
    SystemAgent = current_app.config["ILS_PATRON_SYSTEM_AGENT_CLASS"]
    system_agent_id = str(SystemAgent.id)

    for hit in get_all_expired_loans().scan():
        loan = Loan.get_record_by_pid(hit.pid)
        duration_days = current_app.config[
            "ILS_CIRCULATION_LOAN_REQUEST_DURATION_DAYS"]
        params = deepcopy(loan)
        params.update(
            dict(
                cancel_reason="The loan request has been automatically "
                "cancelled because {} days have passed.".format(duration_days),
                transaction_user_pid=system_agent_id,
            ))
        current_circulation.circulation.trigger(
            loan, **dict(params, trigger="cancel"))

        loan.commit()
        db.session.commit()
        current_circulation.loan_indexer().index(loan)
def cancel_active_loans(patron_pid, client, users):
    """Cancel active loans of a patron."""
    user = user_login(client, "admin", users)

    active_loans = get_active_loans_by_patron_pid(patron_pid).scan()

    for hit in active_loans:
        loan = Loan.get_record_by_pid(hit.pid)
        params = deepcopy(loan)
        params.update(
            dict(
                cancel_reason="Loan cancelled to anonymize user.",
                transaction_user_pid=str(user.id),
            ))
        current_circulation.circulation.trigger(
            loan, **dict(params, trigger="cancel"))

        loan.commit()
        db.session.commit()
        current_circulation.loan_indexer().index(loan)

    current_search.flush_and_refresh(index="*")
Пример #15
0
def test_loan_document_resolver(app, testdata):
    """Test item resolving from loan."""
    loan_pid = testdata["loans"][1]["pid"]
    loan = Loan.get_record_by_pid(loan_pid)
    loan = loan.replace_refs()
    assert loan["document"]["pid"] == loan["document_pid"]
Пример #16
0
 def get(self):
     """Return the loan for this borrowing request."""
     loan_pid = self.record.get("patron_loan", {}).get("pid")
     if not loan_pid:
         raise ILLError("There is no patron loan attached to the request.")
     return Loan.get_record_by_pid(loan_pid)
def test_loan_item_resolver_for_empty_item_pid(app, testdata):
    """Test item resolving from loan."""
    loan_pid = testdata["loans"][0]["pid"]
    loan = Loan.get_record_by_pid(loan_pid)
    loan = loan.replace_refs()
    assert loan["item"] == dict()
Пример #18
0
def test_search_loans_by_pid(indexed_loans):
    """Test retrieve loan list belonging to an item."""
    loans = list(search_by_pid(item_pid="item_pending_1").scan())
    assert len(loans) == 1
    loan = Loan.get_record_by_pid(loans[0]["pid"])
    assert loan.get("item_pid") == "item_pending_1"
 def _set_loan_end_date(loan_pid, new_end_date):
     """Set loan end date."""
     loan = Loan.get_record_by_pid(loan_pid)
     loan["end_date"] = new_end_date.date().isoformat()
     loan.commit()
     db.session.commit()
def test_search_loans_by_pid(indexed_loans):
    """Test retrieve loan list belonging to an item."""
    loans = list(search_by_pid(item_pid="item_pending_1").scan())
    assert len(loans) == 1
    loan = Loan.get_record_by_pid(loans[0][Loan.pid_field])
    assert loan.get("item_pid") == "item_pending_1"