def test_update_item(db, testdata):
    """Test update item status."""
    def get_active_loan_pid_and_item_pid():
        for t in testdata["items"]:
            if t["status"] == "CAN_CIRCULATE":
                item_pid = dict(type=ITEM_PID_TYPE, value=t["pid"])
                active_loan = (
                    get_active_loan_by_item_pid(item_pid).execute().hits)
                total = (active_loan.total
                         if lt_es7 else active_loan.total.value)
                if total > 0:
                    return t["pid"], active_loan[0]["pid"]

    # change document pid while is on loan
    item_pid, loan_pid = get_active_loan_pid_and_item_pid()
    item = Item.get_record_by_pid(item_pid)
    item["document_pid"] = "docid-1"
    with pytest.raises(ItemHasPastLoansError):
        item.commit()

    # change document to one that does not exist
    item = Item.get_record_by_pid("itemid-1")
    item["document_pid"] = "not_found_doc"
    with pytest.raises(DocumentNotFoundError):
        item.commit()
def test_checkout_conditions_librarian(client, json_headers, users, testdata):
    """Test checkout conditions user."""
    librarian = users["librarian"]
    user_login(client, "librarian", users)
    url = url_for("invenio_app_ils_circulation.loan_checkout")

    params = deepcopy(NEW_LOAN)
    params["item_pid"] = dict(type="pitmid", value="itemid-61")
    params["transaction_user_pid"] = str(librarian.id)
    res = client.post(url, headers=json_headers, data=json.dumps(params))
    assert res.status_code == 202

    params = deepcopy(NEW_LOAN)
    params["item_pid"] = dict(type="pitmid", value="itemid-MISSING")
    params["transaction_user_pid"] = str(librarian.id)
    res = client.post(url, headers=json_headers, data=json.dumps(params))
    # missing
    assert res.status_code == 400

    params = deepcopy(NEW_LOAN)
    params["force"] = True
    params["item_pid"] = dict(type="pitmid", value="itemid-MISSING")
    params["transaction_user_pid"] = str(librarian.id)
    res = client.post(url, headers=json_headers, data=json.dumps(params))
    # missing but force
    assert res.status_code == 202
    item = Item.get_record_by_pid(params["item_pid"]["value"])
    assert item["status"] == "CAN_CIRCULATE"
Example #3
0
def _set_item_to_can_circulate(item_pid):
    """Change the item status to CAN_CIRCULATE."""
    item = Item.get_record_by_pid(item_pid["value"])
    if item["status"] != "CAN_CIRCULATE":
        item["status"] = "CAN_CIRCULATE"
        item.commit()
        db.session.commit()
        current_app_ils.item_indexer.index(item)
def test_loan_extension_end_date(app, client, json_headers, users, testdata,
                                 loan_params):
    """Test loan end date after extension."""
    params = deepcopy(loan_params)
    del params["transaction_date"]
    record = _checkout_loan_pid1(client, json_headers, users, params)
    extend_url = record["links"]["actions"]["extend"]
    loan = record["metadata"]

    item = Item.get_record_by_pid(loan["item_pid"]["value"])
    item_loan_duration = circulation_default_loan_duration_for_item(item)

    user_login(client, "patron1", users)

    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_extension_end_date_loan_not_overdue(loan_pid):
        """Test that new end date is added to the current end date."""
        now = arrow.utcnow()
        new_end_date = now + timedelta(days=10)  # loan is not overdue
        _set_loan_end_date(loan_pid, new_end_date)

        expected_end_date = new_end_date + item_loan_duration

        res = client.post(extend_url,
                          headers=json_headers,
                          data=json.dumps(params))
        assert res.status_code == 202
        new_loan = res.get_json()["metadata"]
        assert new_loan["end_date"] == expected_end_date.date().isoformat()

    def test_extension_end_date_loan_overdue(loan_pid):
        """Test that new end date is added to today."""
        now = arrow.utcnow()

        new_end_date = now - timedelta(days=2)  # loan is overdue since 2 days
        _set_loan_end_date(loan_pid, new_end_date)

        expected_end_date = now + item_loan_duration
        res = client.post(extend_url,
                          headers=json_headers,
                          data=json.dumps(params))
        assert res.status_code == 202
        new_loan = res.get_json()["metadata"]
        # loan new end date should start from now
        assert new_loan["end_date"] == expected_end_date.date().isoformat()

    test_extension_end_date_loan_not_overdue(loan["pid"])
    test_extension_end_date_loan_overdue(loan["pid"])
Example #5
0
def test_item_refs(app, testdata):
    """Test creation of an item."""
    item = Item.create(
        dict(
            pid="itemid-99",
            document_pid="docid-1",
            internal_location_pid="ilocid-4",
            created_by=dict(type="script", value="demo"),
            barcode="348048",
            status="CAN_CIRCULATE",
            circulation_restriction="NO_RESTRICTION",
            medium="PAPER",
        ))
    assert "$schema" in item
    assert "document" in item and "$ref" in item["document"]
    assert "internal_location" in item and "$ref" in item["internal_location"]

    item = Item.get_record_by_pid("itemid-1")
    item = item.replace_refs()
    assert "document" in item and item["document"]["title"]
    assert "internal_location" in item and item["internal_location"]["name"]
Example #6
0
def test_item_validation(db, testdata):
    """Test validation when updating an item."""
    item_pid = testdata["items"][0]["pid"]
    orginal_item = Item.get_record_by_pid(item_pid)

    # change document pid
    item = deepcopy(orginal_item)
    item["document_pid"] = "not_found_doc"
    with pytest.raises(DocumentNotFoundError):
        item.commit()

    # change internal location pid
    item = deepcopy(orginal_item)
    item["internal_location_pid"] = "not_found_pid"
    with pytest.raises(InternalLocationNotFoundError):
        item.commit()
Example #7
0
def get_item_by_barcode(barcode):
    """Retrieve item object by barcode."""
    search = ItemSearch().query(
        "bool",
        filter=[
            Q("term", barcode=barcode),
        ],
    )
    result = search.execute()
    hits_total = result.hits.total.value
    if not result.hits or hits_total < 1:
        click.secho("no item found with barcode {}".format(barcode), fg="red")
        raise ItemMigrationError(
            "no item found with barcode {}".format(barcode))
    elif hits_total > 1:
        raise ItemMigrationError(
            "found more than one item with barcode {}".format(barcode))
    else:
        return Item.get_record_by_pid(result.hits[0].pid)
    def test_on_item_update():
        """Test item resolvers."""
        indexer = _get_mock()

        # item on loan
        pid = "itemid-56"
        item = Item.get_record_by_pid(pid)
        ItemIndexer().index(item)

        referenced = _assert_origin(indexer, ITEM_PID_TYPE, pid)

        # should re-index loans
        n_loans = 2  # from test data, including pending
        _assert_contains(referenced, CIRCULATION_LOAN_PID_TYPE)

        # should re-index document
        n_documents = 1  # from test data
        _assert_contains(referenced, DOCUMENT_PID_TYPE)

        assert len(referenced) == n_loans + n_documents
Example #9
0
def testdata(app, db, es_clear, system_user):
    """Create, index and return test data."""
    indexer = RecordIndexer()

    locations = load_json_from_datadir("locations.json")
    for location in locations:
        record = Location.create(location)
        mint_record_pid(LOCATION_PID_TYPE, "pid", record)
        record.commit()
        db.session.commit()
        indexer.index(record)

    internal_locations = load_json_from_datadir("internal_locations.json")
    for internal_location in internal_locations:
        record = InternalLocation.create(internal_location)
        mint_record_pid(
            INTERNAL_LOCATION_PID_TYPE, "pid", record
        )
        record.commit()
        db.session.commit()
        indexer.index(record)

    documents = load_json_from_datadir("documents.json")
    for doc in documents:
        record = Document.create(doc)
        mint_record_pid(DOCUMENT_PID_TYPE, "pid", record)
        record.commit()
        db.session.commit()
        indexer.index(record)

    items = load_json_from_datadir("items.json")
    for item in items:
        record = Item.create(item)
        mint_record_pid(ITEM_PID_TYPE, "pid", record)
        record.commit()
        db.session.commit()
        indexer.index(record)

    loans = load_json_from_datadir("loans.json")
    for loan in loans:
        record = Loan.create(loan)
        mint_record_pid(CIRCULATION_LOAN_PID_TYPE, "pid", record)
        record.commit()
        db.session.commit()
        indexer.index(record)

    series = load_json_from_datadir("series.json")
    for serie in series:
        record = Series.create(serie)
        mint_record_pid(SERIES_PID_TYPE, "pid", record)
        record.commit()
        db.session.commit()
        indexer.index(record)

    # flush all indices after indexing, otherwise ES won't be ready for tests
    current_search.flush_and_refresh(index='*')
    return {
        "documents": documents,
        "items": items,
        "loans": loans,
        "locations": locations,
        "series": series,
    }