Skip to content

Commit

Permalink
circulation : fix issue two loans instead of one
Browse files Browse the repository at this point in the history
* Closes rero#484
* Moves prior_checkout_actions() function from api_views.py to api.py

Co-Authored-by: Benoit Erken <[email protected]>
  • Loading branch information
Benoit Erken and benerken committed Sep 19, 2019
1 parent 2bc5120 commit 82b90b9
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 25 deletions.
27 changes: 25 additions & 2 deletions rero_ils/modules/items/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ def dumps_for_circulation(self):
for loan in self.get_requests():
data.setdefault('pending_loans',
[]).append(loan.dumps_for_circulation())

return data

@classmethod
Expand Down Expand Up @@ -772,11 +771,35 @@ def checkin(self, current_loan, **kwargs):
item, validate_action = self.validate_request(**request)
return self, actions

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

@add_loans_parameters_and_flush_indexes
def checkout(self, current_loan, **kwargs):
"""Checkout item to the user."""
new_data = self.prior_checkout_actions(kwargs)
loan = Loan.get_record_by_pid(new_data.get('pid'))
current_loan = loan or Loan.create(new_data,
dbcommit=True,
reindex=True)

loan = current_circulation.circulation.trigger(
current_loan, **dict(kwargs, trigger='checkout')
current_loan, **dict(new_data, trigger='checkout')
)
return self, {
LoanAction.CHECKOUT: loan
Expand Down
22 changes: 1 addition & 21 deletions rero_ils/modules/items/api_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,6 @@ def librarian_request(item, data):
return item.request(**data)


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


@api_blueprint.route('/checkout', methods=['POST'])
@check_authentication
@jsonify_action
Expand All @@ -143,8 +124,7 @@ def checkout(item, data):
required_parameters: patron_pid, item_pid
"""
new_data = prior_checkout_actions(item, data)
return item.checkout(**new_data)
return item.checkout(**data)


@api_blueprint.route("/checkin", methods=['POST'])
Expand Down
3 changes: 1 addition & 2 deletions tests/api/test_items_rest_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,8 @@ class locale:
data = get_json(res)
loan_pid = data.get('action_applied')[LoanAction.CHECKIN].get('pid')

from rero_ils.modules.items.api_views import prior_checkout_actions
data = {'pid': loan_pid}
return_data = prior_checkout_actions(item_lib_martigny, data)
return_data = item_lib_martigny.prior_checkout_actions(data)
assert return_data == {}


Expand Down
90 changes: 90 additions & 0 deletions tests/api/test_loans_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
import pytz
from flask import url_for
from invenio_accounts.testutils import login_user_via_session
from invenio_circulation.api import get_loan_for_item
from invenio_circulation.search.api import LoansSearch
from utils import flush_index, get_json

from rero_ils.modules.items.api import Item
from rero_ils.modules.loans.api import Loan, LoanAction, get_due_soon_loans, \
get_last_transaction_loc_for_item, get_loans_by_patron_pid, \
get_overdue_loans
Expand Down Expand Up @@ -258,3 +260,91 @@ def test_overdue_loans(client, librarian_martigny_no_email,
content_type='application/json',
)
assert res.status_code == 200


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')

0 comments on commit 82b90b9

Please sign in to comment.