def test_loan_replace_item_wo_params(
    app, json_headers, params, indexed_loans
):
    """Test that no Loan is returned for the given Item if only pendings."""
    item_pid = "item_on_loan_2"
    loan = get_loan_for_item(item_pid)
    payload = {}
    res, data = _post(app, json_headers, loan, payload)
    assert res.status_code == 400
def test_loan_replace_item(app, json_headers, params, indexed_loans):
    """Test that no Loan is returned for the given Item if only pendings."""
    item_pid = "item_on_loan_2"
    loan = get_loan_for_item(item_pid)
    payload = {"item_pid": "new_item_pid"}
    res, data = _post(app, json_headers, loan, payload)
    assert res.status == "202 ACCEPTED"
    assert data["metadata"]["item_pid"] == payload["item_pid"]
    # the ref won't change as it is pointing back to loan (it will
    # resolve by loan endpoint)
    assert data["metadata"]["item"]["ref"] == loan["loan_pid"]
Example #3
0
 def get_item_end_date(self, format='short_date'):
     """Get item due date for a given item."""
     loan = get_loan_for_item(self.pid)
     if loan:
         end_date = loan['end_date']
         due_date = format_date_filter(
             end_date,
             format=format,
             locale=current_i18n.locale.language,
         )
         return due_date
     return None
Example #4
0
def item(item_barcode):
    """HTTP GET request for requested loans for a library."""
    item = Item.get_item_by_barcode(item_barcode)
    if not item:
        abort(404)
    loan = get_loan_for_item(item.pid)
    if loan:
        loan = Loan.get_record_by_pid(loan['loan_pid']).dumps_for_circulation()
    return jsonify(
        {'metadata': {
            'item': item.dumps_for_circulation(),
            'loan': loan
        }})
def test_multiple_active_loans(app, db, indexed_loans):
    """Test that raises if there are multiple active Loans for given Item."""
    multiple_loans_pid = "item_multiple_pending_on_loan_7"

    test_loan_data = {
        "item_pid": "item_multiple_pending_on_loan_7",
        "patron_pid": "2",
        "state": "ITEM_ON_LOAN",
        "transaction_date": "2018-06-26",
        "transaction_location_pid": "loc_pid",
        "transaction_user_pid": "user_pid",
        "start_date": "2018-07-24",
        "end_date": "2018-08-23"
    }

    pid, loan = create_loan(test_loan_data)
    db.session.commit()
    RecordIndexer().index(loan)
    current_search.flush_and_refresh(index="loans")

    with pytest.raises(MultipleLoansOnItemError):
        get_loan_for_item(multiple_loans_pid)
Example #6
0
 def loan_for_item_resolver(item_pid):
     """Return the loan for the given item."""
     loan = get_loan_for_item(item_pid) or {}
     return {
         "loan_pid": loan.get("pid"),
         "patron_pid": loan.get("patron_pid"),
         "document_pid": loan.get("document_pid"),
         "item_pid": loan.get("item_pid"),
         "state": loan.get("state"),
         "start_date": loan.get("start_date"),
         "end_date": loan.get("end_date"),
         "request_expire_date": loan.get("request_expire_date"),
         "extension_count": loan.get("extension_count"),
     }
Example #7
0
 def prior_checkout_actions(self, action_params):
     """Actions executed prior to a checkout."""
     if action_params.get('pid'):
         loan = Loan.get_record_by_pid(action_params.get('pid'))
         if (loan.get('state') == 'ITEM_IN_TRANSIT_FOR_PICKUP' and
                 loan.get('patron_pid') == action_params.get('patron_pid')):
             self.receive(**action_params)
         if loan.get('state') == 'ITEM_IN_TRANSIT_TO_HOUSE':
             self.cancel_loan(pid=loan.get('pid'))
             del action_params['pid']
     else:
         loan = get_loan_for_item(self.pid)
         if (loan and loan.get('state') != 'ITEM_AT_DESK'):
             self.cancel_loan(pid=loan.get('pid'))
     return action_params
Example #8
0
def prior_checkout_actions(item, data):
    """Actions executed prior to a checkout."""
    if data.get('pid'):
        loan = Loan.get_record_by_pid(data.get('pid'))
        if (loan.get('state') == 'ITEM_IN_TRANSIT_FOR_PICKUP'
                and loan.get('patron_pid') == data.get('patron_pid')):
            item.receive(**data)
        if loan.get('state') == 'ITEM_IN_TRANSIT_TO_HOUSE':
            item.cancel_loan(pid=loan.get('pid'))
            del data['pid']
    else:
        loan = get_loan_for_item(item.pid)
        if loan:
            item.cancel_loan(pid=loan.get('pid'))
    return data
Example #9
0
def create_loan(barcode, transaction_type, loanable_items):
    """Create loans transactions."""
    item = next(loanable_items)
    patron = Patron.get_patron_by_barcode(barcode=barcode)
    start_date, end_date = get_loan_dates(transaction_type, item, patron)
    transaction_date = datetime.now(timezone.utc).isoformat()
    user_pid, user_location = get_random_librarian_and_transaction_location(
        patron)
    item.checkout(
        patron_pid=patron.pid,
        transaction_user_pid=user_pid,
        transaction_location_pid=user_location,
        transaction_date=transaction_date,
        document_pid=item.replace_refs()['document']['pid'],
        item_pid=item.pid,
    )
    if transaction_type == 'extended':
        loan = get_loan_for_item(item.pid)
        loan_pid = loan.get('pid')
        user_pid, user_location = \
            get_random_librarian_and_transaction_location(patron)
        item.extend_loan(
            pid=loan_pid,
            patron_pid=patron.pid,
            transaction_location_pid=user_location,
            transaction_user_pid=user_pid,
            transaction_date=transaction_date,
            document_pid=item.replace_refs()['document']['pid'],
            item_pid=item.pid,
        )
    if transaction_type == 'requested_by_others':
        requested_patron = get_random_patron(barcode)
        user_pid, user_location = \
            get_random_librarian_and_transaction_location(patron)
        circ_policy = CircPolicy.provide_circ_policy(
            item.library_pid, requested_patron.patron_type_pid,
            item.item_type_pid)
        if circ_policy.get('allow_requests'):
            item.request(
                patron_pid=requested_patron.pid,
                transaction_location_pid=user_location,
                transaction_user_pid=user_pid,
                transaction_date=transaction_date,
                pickup_location_pid=get_random_pickup_location(
                    requested_patron.pid),
                document_pid=item.replace_refs()['document']['pid'],
            )
    return item['barcode']
Example #10
0
    def get_item_end_date(self):
        """Get item due date a given item."""
        loan = get_loan_for_item(self.pid)
        if loan:
            end_date = loan['end_date']
            # due_date = datetime.strptime(end_date, '%Y-%m-%d')
            from ...filter import format_date_filter
            from invenio_i18n.ext import current_i18n

            due_date = format_date_filter(
                end_date,
                format='short_date',
                locale=current_i18n.locale.language,
            )
            return due_date
        return None
Example #11
0
 def loan_for_item_resolver(item_pid):
     """Return the loan for the given item."""
     loan = get_loan_for_item(item_pid)
     if not loan:
         return {}
     else:
         return {
             "loan_pid": loan.get("pid"),
             "patron_pid": loan.get("patron_pid"),
             "document_pid": loan.get("document_pid"),
             "item_pid": loan.get("item_pid"),
             "state": loan.get("state"),
             "start_date": loan.get("start_date"),
             "end_date": loan.get("end_date"),
             "extension_count": loan.get("extension_count"),
         }
 def loan_for_item_resolver(item_pid):
     """Return the loan for the given item."""
     loan = get_loan_for_item(dict(value=item_pid, type=ITEM_PID_TYPE))
     if not loan:
         return {}
     else:
         return {
             "loan_pid": loan["pid"],
             "patron_pid": loan["patron_pid"],
             "patron": loan["patron"],
             "document_pid": loan["document_pid"],
             "item_pid": loan.get("item_pid"),
             "state": loan["state"],
             "start_date": loan["start_date"],
             "end_date": loan["end_date"],
             "extension_count": loan.get("extension_count", 0),
             "is_overdue": loan.get("is_overdue", False),
         }
Example #13
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_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)
        circ_policy = CircPolicy.provide_circ_policy(
            item.library_pid,
            patron.patron_type_pid,
            item.item_type_pid
        )
        new_actions = []
        # If circulation policy doesn't allow checkout operation no need to
        # perform special check describe below.
        if circ_policy.get('allow_checkout', False):
            for action in item_dumps.get('actions', []):
                if action == 'checkout':
                    if item.number_of_requests() > 0:
                        patron_barcode = patron.get('patron', {})\
                            .get('barcode')
                        if item.patron_request_rank(patron_barcode) == 1:
                            new_actions.append(action)
                    else:
                        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
        }
    })
Example #14
0
 def actions(self):
     """Get all available actions."""
     transitions = current_app.config.get('CIRCULATION_LOAN_TRANSITIONS')
     loan = get_loan_for_item(self.pid)
     actions = set()
     if loan:
         for transition in transitions.get(loan.get('state')):
             action = transition.get('trigger')
             data = self.action_filter(action, loan)
             if data.get('action_validated'):
                 actions.add(action)
             if data.get('new_action'):
                 actions.add(data.get('new_action'))
     # default actions
     if not loan:
         for transition in transitions.get('CREATED'):
             action = transition.get('trigger')
             actions.add(action)
     # remove unsupported action
     for action in ['cancel', 'request']:
         try:
             actions.remove(action)
             # not yet supported
             # actions.add('cancel_loan')
         except KeyError:
             pass
     # rename
     try:
         actions.remove('extend')
         actions.add('extend_loan')
     except KeyError:
         pass
     # if self['status'] == ItemStatus.MISSING:
     #     actions.add('return_missing')
     # else:
     #     actions.add('lose')
     return actions
Example #15
0
def get_patron_from_checkout_item_pid(item_pid):
    """Get patron from a checkout item pid."""
    from invenio_circulation.api import get_loan_for_item
    patron_pid = get_loan_for_item(item_pid)['patron_pid']
    return Patron.get_record_by_pid(patron_pid)
Example #16
0
def get_checkout_loan_for_item(item_pid):
    """Get patron from a checkout item pid."""
    from invenio_circulation.api import get_loan_for_item
    return get_loan_for_item(item_pid)
def test_api_circulation_item_not_found(app, indexed_loans):
    """Test API GET call to check circulation item not found."""
    loan = get_loan_for_item("")
    assert loan is None
def test_api_circulation_item_on_loan(app, indexed_loans):
    """Test that Loan is returned for the given Item if one active."""
    multiple_loans_pid = "item_multiple_pending_on_loan_7"
    loan = get_loan_for_item(multiple_loans_pid)
    assert loan['state'] == 'ITEM_ON_LOAN'
    assert loan['item_pid'] == multiple_loans_pid
def test_api_circulation_item_loan_pending(app, indexed_loans):
    """Test that no Loan is returned for the given Item if only pendings."""
    pending_item_pid = {"type": "itemid", "value": "item_pending_1"}
    loan = get_loan_for_item(pending_item_pid)
    assert loan is None
def test_api_circulation_item_no_loan(app, indexed_loans):
    """Test that no Loan is returned for the given Item if no loans."""
    not_loaned_item_pid = {"type": "itemid", "value": "item_not_loaned"}
    loan = get_loan_for_item(not_loaned_item_pid)
    assert loan is None
Example #21
0
 def _loan_for_item_resolver(pid_value):
     """Return the loan for the given item."""
     loan = get_loan_for_item(pid_value) or {}
     if loan.get("item"):
         del loan["item"]
     return loan
def test_api_circulation_item_not_found(app, indexed_loans):
    """Test API GET call to check circulation item not found."""
    loan = get_loan_for_item("")
    assert loan is None
Example #23
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')
def test_checkout_item_transit(client, item2_lib_martigny,
                               librarian_martigny_no_email,
                               librarian_saxon_no_email,
                               patron_martigny_no_email, loc_public_saxon,
                               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)

    res = client.post(
        url_for('api_item.librarian_request'),
        data=json.dumps(
            dict(item_pid=item2_lib_martigny.pid,
                 pickup_location_pid=loc_public_saxon.pid,
                 patron_pid=patron_martigny_no_email.pid)),
        content_type='application/json',
    )
    assert res.status_code == 200
    data = get_json(res)
    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.get('state') == 'PENDING'

    # validate request
    res = client.post(
        url_for('api_item.validate_request'),
        data=json.dumps(dict(item_pid=item2_lib_martigny.pid, pid=loan_pid)),
        content_type='application/json',
    )
    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.get('state') == 'ITEM_IN_TRANSIT_FOR_PICKUP'

    login_user_via_session(client, librarian_saxon_no_email.user)
    # receive
    res = client.post(
        url_for('api_item.receive'),
        data=json.dumps(dict(item_pid=item2_lib_martigny.pid, pid=loan_pid)),
        content_type='application/json',
    )
    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)
    assert loan_before_checkout.get('state') == 'ITEM_AT_DESK'
    # checkout
    res = client.post(
        url_for('api_item.checkout'),
        data=json.dumps(
            dict(item_pid=item2_lib_martigny.pid,
                 patron_pid=patron_martigny_no_email.pid)),
        content_type='application/json',
    )
    assert res.status_code == 200
    item = Item.get_record_by_pid(item2_lib_martigny.pid)
    loan_after_checkout = get_loan_for_item(item.pid)
    assert loan_after_checkout.get('state') == 'ITEM_ON_LOAN'
    assert loan_before_checkout.get('pid') == loan_after_checkout.get('pid')
Example #25
0
def create_loan(barcode,
                transaction_type,
                loanable_items,
                verbose=False,
                debug=False):
    """Create loans transactions."""
    try:
        item = next(loanable_items)
        patron = Patron.get_patron_by_barcode(barcode=barcode)
        transaction_date = datetime.now(timezone.utc).isoformat()
        user_pid, user_location = \
            get_random_librarian_and_transaction_location(patron)
        item.checkout(
            patron_pid=patron.pid,
            transaction_user_pid=user_pid,
            transaction_location_pid=user_location,
            transaction_date=transaction_date,
            document_pid=item.replace_refs()['document']['pid'],
            item_pid=item.pid,
        )
        loan = get_loan_for_item(item_pid_to_object(item.pid))
        loan_pid = loan.get('pid')
        loan = Loan.get_record_by_pid(loan_pid)
        if transaction_type == 'overdue_active':
            end_date = datetime.now(timezone.utc) - timedelta(days=2)
            loan['end_date'] = end_date.isoformat()
            loan.update(loan, dbcommit=True, reindex=True)
            loan.create_notification(notification_type='due_soon')

            end_date = datetime.now(timezone.utc) - timedelta(days=70)
            loan['end_date'] = end_date.isoformat()
            loan.update(loan, dbcommit=True, reindex=True)
            loan.create_notification(notification_type='overdue')

        elif transaction_type == 'overdue_paid':
            end_date = datetime.now(timezone.utc) - timedelta(days=2)
            loan['end_date'] = end_date.isoformat()
            loan.update(loan, dbcommit=True, reindex=True)
            loan.create_notification(notification_type='due_soon')

            end_date = datetime.now(timezone.utc) - timedelta(days=70)
            loan['end_date'] = end_date.isoformat()
            loan.update(loan, dbcommit=True, reindex=True)
            notif = loan.create_notification(notification_type='overdue')
            patron_transaction = [
                record for record in notif.patron_transactions
            ][0]
            user = get_random_librarian(patron).replace_refs()
            payment = create_payment_record(
                patron_transaction, user_pid,
                random.choice(user['libraries'])['pid'])
            PatronTransactionEvent.create(payment,
                                          dbcommit=True,
                                          reindex=True,
                                          update_parent=True)
        elif transaction_type == 'extended':
            user_pid, user_location = \
                get_random_librarian_and_transaction_location(patron)
            item.extend_loan(
                pid=loan_pid,
                patron_pid=patron.pid,
                transaction_location_pid=user_location,
                transaction_user_pid=user_pid,
                transaction_date=transaction_date,
                document_pid=item.replace_refs()['document']['pid'],
                item_pid=item.pid,
            )
        elif transaction_type == 'requested_by_others':
            requested_patron = get_random_patron(barcode)
            user_pid, user_location = \
                get_random_librarian_and_transaction_location(patron)
            circ_policy = CircPolicy.provide_circ_policy(
                item.library_pid, requested_patron.patron_type_pid,
                item.item_type_pid)
            if circ_policy.get('allow_requests'):
                item.request(
                    patron_pid=requested_patron.pid,
                    transaction_location_pid=user_location,
                    transaction_user_pid=user_pid,
                    transaction_date=transaction_date,
                    pickup_location_pid=get_random_pickup_location(
                        requested_patron.pid, item),
                    document_pid=item.replace_refs()['document']['pid'],
                )
                loan.create_notification(notification_type='recall')
        return item['barcode']
    except Exception as err:
        if verbose:
            click.secho('\tException loan {transaction_type}: {err}'.format(
                transaction_type=transaction_type, err=err),
                        fg='red')
        if debug:
            traceback.print_exc()
        return None
Example #26
0
def create_loan(barcode,
                transaction_type,
                loanable_items,
                verbose=False,
                debug=False):
    """Create loans transactions."""
    notification_pids = []
    try:
        item = next(loanable_items)
        patron = Patron.get_patron_by_barcode(barcode=barcode)
        transaction_date = datetime.now(timezone.utc).isoformat()
        user_pid, user_location = \
            get_random_librarian_and_transaction_location(patron)
        item.checkout(
            patron_pid=patron.pid,
            transaction_user_pid=user_pid,
            transaction_location_pid=user_location,
            transaction_date=transaction_date,
            document_pid=extracted_data_from_ref(item.get('document')),
            item_pid=item.pid,
        )
        loan = get_loan_for_item(item_pid_to_object(item.pid))
        loan_pid = loan.get('pid')
        loan = Loan.get_record_by_pid(loan_pid)
        if transaction_type == 'overdue_active':
            end_date = datetime.now(timezone.utc) - timedelta(days=2)
            loan['end_date'] = end_date.isoformat()
            loan.update(loan, dbcommit=True, reindex=True)
            notifications = loan.create_notification(
                _type=NotificationType.DUE_SOON)
            for notif in notifications:
                notification_pids.append(notif['pid'])

            end_date = datetime.now(timezone.utc) - timedelta(days=70)
            loan['end_date'] = end_date.isoformat()
            loan.update(loan, dbcommit=True, reindex=True)
            notifications = loan.create_notification(
                _type=NotificationType.OVERDUE)
            for notif in notifications:
                notification_pids.append(notif['pid'])

        elif transaction_type == 'overdue_paid':
            end_date = datetime.now(timezone.utc) - timedelta(days=2)
            loan['end_date'] = end_date.isoformat()
            loan.update(loan, dbcommit=True, reindex=True)
            notifications = loan.create_notification(
                _type=NotificationType.DUE_SOON)
            for notif in notifications:
                notification_pids.append(notif['pid'])

            end_date = datetime.now(timezone.utc) - timedelta(days=70)
            loan['end_date'] = end_date.isoformat()
            loan.update(loan, dbcommit=True, reindex=True)
            notifications = loan.create_notification(
                _type=NotificationType.OVERDUE)
            for notif in notifications:
                notification_pids.append(notif['pid'])
            patron_transaction = next(notif.patron_transactions)
            user = get_random_librarian(patron).replace_refs()
            payment = create_payment_record(
                patron_transaction, user_pid,
                random.choice(user['libraries'])['pid'])
            PatronTransactionEvent.create(payment,
                                          dbcommit=True,
                                          reindex=True,
                                          update_parent=True)
        elif transaction_type == 'extended':
            user_pid, user_location = \
                get_random_librarian_and_transaction_location(patron)
            item.extend_loan(
                pid=loan_pid,
                patron_pid=patron.pid,
                transaction_location_pid=user_location,
                transaction_user_pid=user_pid,
                transaction_date=transaction_date,
                document_pid=extracted_data_from_ref(item.get('document')),
                item_pid=item.pid,
            )
        elif transaction_type == 'requested_by_others':
            requested_patron = get_random_patron(barcode)
            user_pid, user_location = \
                get_random_librarian_and_transaction_location(patron)
            circ_policy = CircPolicy.provide_circ_policy(
                item.organisation_pid, item.library_pid,
                requested_patron.patron_type_pid,
                item.item_type_circulation_category_pid)
            if circ_policy.get('allow_requests'):
                item.request(
                    patron_pid=requested_patron.pid,
                    transaction_location_pid=user_location,
                    transaction_user_pid=user_pid,
                    transaction_date=transaction_date,
                    pickup_location_pid=get_random_pickup_location(
                        requested_patron.pid, item),
                    document_pid=extracted_data_from_ref(item.get('document')),
                )
                notifications = loan.create_notification(
                    _type=NotificationType.RECALL)
                for notif in notifications:
                    notification_pids.append(notif['pid'])
        Dispatcher.dispatch_notifications(notification_pids, verbose=verbose)
        return item['barcode']
    except Exception as err:
        if verbose:
            click.secho(f'\tException loan {transaction_type}:{err}', fg='red')
        if debug:
            traceback.print_exc()
        return None, []
def test_api_circulation_item_no_loan(app, indexed_loans):
    """Test that no Loan is returned for the given Item if no loans."""
    not_loaned_item_pid = "item_not_loaned"
    loan = get_loan_for_item(not_loaned_item_pid)
    assert loan is None
Example #28
0
 def get_extension_count(self):
     """Get item renewal count."""
     loan = get_loan_for_item(self.pid)
     if loan:
         return loan.get('extension_count', 0)
     return 0
def test_api_circulation_item_loan_pending(app, indexed_loans):
    """Test that no Loan is returned for the given Item if only pendings."""
    pending_item_pid = "item_pending_1"
    loan = get_loan_for_item(pending_item_pid)
    assert loan is None