Skip to content

Commit

Permalink
Circulation: Renewal due date from current_date
Browse files Browse the repository at this point in the history
* NEW Blocks renewal if renewal due date less than checkout due date
* FIX Fixes rero#231.

Signed-off-by: Aly Badr <aly.badr@rero.ch>
  • Loading branch information
Aly Badr committed Apr 8, 2019
1 parent a89cf80 commit 1af9d16
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 25 deletions.
15 changes: 9 additions & 6 deletions rero_ils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from __future__ import absolute_import, print_function

from datetime import timedelta
from functools import partial

from invenio_circulation.pidstore.pids import CIRCULATION_LOAN_FETCHER, \
CIRCULATION_LOAN_MINTER, CIRCULATION_LOAN_PID_TYPE
Expand All @@ -51,9 +52,8 @@
from rero_ils.modules.loans.api import Loan

from .modules.items.api import Item, ItemsIndexer
from .modules.loans.utils import can_be_requested, \
get_default_extension_duration, get_default_extension_max_count, \
get_default_loan_duration, is_item_available_for_checkout, \
from .modules.loans.utils import can_be_requested, get_default_loan_duration, \
get_extension_params, is_item_available_for_checkout, \
loan_satisfy_circ_policies
from .modules.patrons.api import Patron
from .permissions import librarian_delete_permission_factory, \
Expand Down Expand Up @@ -975,9 +975,12 @@ def _(x):
item_available=is_item_available_for_checkout
),
extension=dict(
from_end_date=True,
duration_default=get_default_extension_duration,
max_count=get_default_extension_max_count
from_end_date=partial(
get_extension_params, parameter_name='from_end_date'),
duration_default=partial(
get_extension_params, parameter_name='duration_default'),
max_count=partial(
get_extension_params, parameter_name='max_count'),
),
request=dict(
can_be_requested=can_be_requested
Expand Down
2 changes: 1 addition & 1 deletion rero_ils/modules/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
"""Admin views and actions."""

from flask_admin import BaseView, expose
from flask_babelex import gettext as _
from invenio_admin.permissions import \
admin_permission_factory as default_admin_permission_factory

from ..permissions import can_edit
from flask_babelex import gettext as _


class ILSManager(BaseView):
Expand Down
43 changes: 26 additions & 17 deletions rero_ils/modules/loans/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

from datetime import datetime, timedelta

import ciso8601
from dateutil.parser import parse

from ..circ_policies.api import CircPolicy
from ..items.api import Item
from ..libraries.api import Library
Expand Down Expand Up @@ -66,27 +69,33 @@ def get_default_loan_duration(loan):
return new_duration.days


def get_default_extension_duration(loan):
"""Return extension duration in number of days."""
def get_extension_params(loan=None, parameter_name=None):
"""Return extension parameters."""
policy = get_circ_policy(loan)
# TODO: case when start_date is not sysdate.
start_date = datetime.now()
library_pid = Item.get_record_by_pid(loan.item_pid).library_pid
library = Library.get_record_by_pid(library_pid)
# invenio-circulation due_date.
due_date = start_date + timedelta(days=policy.get('renewal_duration'))
# rero_ils due_date, considering library opening_hours and exception_dates.
# next_open: -1 to check first the due date not the days.
open_after_due_date = library.next_open(date=due_date - timedelta(days=1))
new_duration = open_after_due_date - start_date
end_date = ciso8601.parse_datetime_as_naive(loan.get('end_date'))
params = {
'max_count': policy.get('number_renewals'),
'from_end_date': False,
'duration_default': policy.get('renewal_duration')
}
current_date = datetime.now()

return new_duration.days
library = Library.get_record_by_pid(
Item.get_record_by_pid(loan.item_pid).library_pid)

calculated_due_date = current_date + timedelta(
days=policy.get('renewal_duration'))

def get_default_extension_max_count(loan):
"""Return extensions max count."""
policy = get_circ_policy(loan)
return policy.get('number_renewals')
first_open_date = library.next_open(
date=calculated_due_date - timedelta(days=1))

if first_open_date < end_date:
params['max_count'] = 0

new_duration = first_open_date - current_date
params['duration_default'] = new_duration.days

return params.get(parameter_name)


def loan_satisfy_circ_policies(loan):
Expand Down
84 changes: 83 additions & 1 deletion tests/api/test_items_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@

from rero_ils.modules.circ_policies.api import CircPoliciesSearch
from rero_ils.modules.items.api import Item, ItemStatus
from rero_ils.modules.loans.api import LoanAction
from rero_ils.modules.loans.api import Loan, LoanAction
from rero_ils.modules.loans.utils import get_extension_params


def test_items_permissions(client, item_on_loan, user_patron_no_email,
Expand Down Expand Up @@ -1209,3 +1210,84 @@ def test_item_possible_actions(client, item_on_shelf,
reindex=True
)
assert circ_policy['allow_checkout']


def test_items_extend_rejected(client, user_librarian_no_email,
user_patron_no_email,
location, item_type,
item_on_shelf, json_header,
circ_policy_short):
"""."""
login_user_via_session(client, user_librarian_no_email.user)
item = item_on_shelf
item_pid = item.pid
patron_pid = user_patron_no_email.pid

# checkout
res = client.post(
url_for('api_item.checkout'),
data=json.dumps(
dict(
item_pid=item_pid,
patron_pid=patron_pid
)
),
content_type='application/json',
)
assert res.status_code == 200
data = get_json(res)
actions = data.get('action_applied')
loan_pid = actions[LoanAction.CHECKOUT].get('loan_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')
assert max_count > 0

assert circ_policy_short['number_renewals']
assert circ_policy_short['renewal_duration'] > 1
circ_policy_short['renewal_duration'] = 1

circ_policy_short.update(
data=circ_policy_short,
dbcommit=True,
reindex=True)
flush_index(CircPoliciesSearch.Meta.index)

max_count = get_extension_params(loan=loan, parameter_name='max_count')
assert max_count == 0

# extend loan rejected
res = client.post(
url_for('api_item.extend_loan'),
data=json.dumps(
dict(
item_pid=item_pid,
loan_pid=loan_pid
)
),
content_type='application/json',
)

assert res.status_code == 403

circ_policy_short['number_renewals'] = 1

circ_policy_short.update(
data=circ_policy_short,
dbcommit=True,
reindex=True)
flush_index(CircPoliciesSearch.Meta.index)

# checkin
res = client.post(
url_for('api_item.checkin'),
data=json.dumps(
dict(
item_pid=item_pid,
loan_pid=loan_pid
)
),
content_type='application/json',
)
assert res.status_code == 200

0 comments on commit 1af9d16

Please sign in to comment.