Skip to content

Commit

Permalink
global: test coverage and docs for patrons
Browse files Browse the repository at this point in the history
* BETTER increase test coverage and add docs for patrons.

Signed-off-by: Aly Badr <[email protected]>
  • Loading branch information
Aly Badr committed May 14, 2019
1 parent e0bb39d commit 4569f33
Show file tree
Hide file tree
Showing 16 changed files with 201 additions and 55 deletions.
10 changes: 5 additions & 5 deletions rero_ils/modules/patrons/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class Patron(IlsRecord):
@classmethod
def create(cls, data, id_=None, delete_pid=True,
dbcommit=False, reindex=False, **kwargs):
"""."""
"""Patron record creation."""
record = super(Patron, cls).create(
data, id_, delete_pid, dbcommit, reindex, **kwargs)
record._update_roles()
Expand All @@ -101,7 +101,7 @@ def update(self, data, dbcommit=False, reindex=False):

@cached_property
def user(self):
"""."""
"""Invenio user of a patron."""
email = self.get('email')
user = _datastore.find_user(email=email)
if not user:
Expand All @@ -116,7 +116,7 @@ def user(self):
return user

def _update_roles(self):
"""."""
"""Update user roles."""
db_roles = self.user.roles
for role in self.available_roles:
in_db = role in db_roles
Expand All @@ -127,7 +127,7 @@ def _update_roles(self):
self.remove_role(role)

def _remove_roles(self):
"""."""
"""Remove roles."""
db_roles = self.user.roles
for role in self.available_roles:
if role in db_roles:
Expand Down Expand Up @@ -162,7 +162,7 @@ def get_pid_by_email(cls, email):

@classmethod
def get_librarian_pickup_location_pid(cls):
"""."""
"""Returns pickup locations for a librarian."""
if 'librarian' in current_patron['roles']:
library = Library.get_record_by_pid(
current_patron.replace_refs()['library']['pid']
Expand Down
2 changes: 1 addition & 1 deletion rero_ils/modules/patrons/jsonschemas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.

"""JSON schemas for rero-ils."""
"""JSON schemas for patrons."""
41 changes: 20 additions & 21 deletions rero_ils/modules/patrons/listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,23 @@ def func_item_at_desk(sender, *args, **kwargs):
"""Function for signal item_at_desk."""
item = kwargs['item']

# Get patron for holding.
holdings = item.get('_circulation', {}).get('holdings', [])
if holdings:
patron_barcode = holdings[0].get('patron_barcode')
patron = Patron.get_patron_by_barcode(patron_barcode)

if patron:
# Send at desk mail
subject = _('Document at desk')
email = patron.get('email')
recipients = [email]
template = 'patron_request_at_desk'
send_mail(
subject=subject,
recipients=recipients,
template=template,
language='eng',
document=Document.get_document_by_itemid(item.id),
# holding=item.dumps().get('_circulation').get('holdings')[0],
holding='get loans with state ITEM_AT_DESK, To be implemented',
)
requests = item.number_of_requests()
if requests:
for request in item.get_requests():
if request.get('state') == 'ITEM_AT_DESK':
patron = Patron.get_record_by_pid(request.get('patron_pid'))
if patron:
# Send at desk mail
subject = _('Document at desk')
document_pid = request.get('document_pid')
email = patron.get('email')
recipients = [email]
template = 'patron_request_at_desk'
send_mail(
subject=subject,
recipients=recipients,
template=template,
language='eng',
document=Document.get_record_by_pid(document_pid),
holding=request
)
2 changes: 1 addition & 1 deletion rero_ils/modules/patrons/mappings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.

"""Elasticsearch mappings."""
"""Elasticsearch mappings for patrons."""
2 changes: 1 addition & 1 deletion rero_ils/modules/patrons/mappings/v6/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.

"""Elasticsearch mappings."""
"""Elasticsearch mappings for patrons."""
2 changes: 1 addition & 1 deletion rero_ils/modules/patrons/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.

"""Utilities functions for rero-ils."""
"""Utilities functions for patrons."""


from flask_login import current_user
Expand Down
16 changes: 1 addition & 15 deletions rero_ils/modules/patrons/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@

from __future__ import absolute_import, print_function

from functools import wraps

from flask import Blueprint, current_app, jsonify, render_template, request
from flask_babelex import gettext as _
from flask_login import current_user, login_required
Expand All @@ -42,7 +40,6 @@
from ..libraries.api import Library
from ..loans.api import get_loans_by_patron_pid
from ..locations.api import Location
from ...permissions import login_and_librarian

api_blueprint = Blueprint(
'api_patrons',
Expand All @@ -53,16 +50,6 @@
)


def check_permission(fn):
"""."""
@wraps(fn)
def decorated_view(*args, **kwargs):
"""."""
login_and_librarian()
return fn(*args, **kwargs)
return decorated_view


blueprint = Blueprint(
'patrons',
__name__,
Expand Down Expand Up @@ -121,7 +108,6 @@ def profile():
if patron is None:
raise NotFound()
loans = get_loans_by_patron_pid(patron.pid)

checkouts = []
requests = []
if loans:
Expand Down Expand Up @@ -159,7 +145,7 @@ def get_patron_from_barcode(value):

@blueprint.app_template_filter('get_patron_from_checkout_item_pid')
def get_patron_from_checkout_item_pid(item_pid):
"""Get patron from a checkout item pid."""
"""Get patron from a checked out 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)
Expand Down
4 changes: 4 additions & 0 deletions tests/api/test_items_rest_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ def test_checkout_no_loan_given(client, librarian_martigny_no_email,
data = get_json(res)
loan_pid = data.get('action_applied')[LoanAction.CHECKOUT].get('loan_pid')

from rero_ils.modules.patrons.views import \
get_patron_from_checkout_item_pid
assert get_patron_from_checkout_item_pid(item.pid) == patron

res = client.post(
url_for('api_item.checkin'),
data=json.dumps(
Expand Down
4 changes: 2 additions & 2 deletions tests/api/test_loans_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from invenio_accounts.testutils import login_user_via_session


def test_loans_permissions(client, loan_pedning, json_header):
def test_loans_permissions(client, loan_pending, json_header):
"""Test record retrieval."""
item_url = url_for('invenio_records_rest.loanid_item', pid_value='1')
post_url = url_for('invenio_records_rest.loanid_list')
Expand All @@ -56,7 +56,7 @@ def test_loans_permissions(client, loan_pedning, json_header):
assert res.status_code == 401


def test_loans_logged_permissions(client, loan_pedning,
def test_loans_logged_permissions(client, loan_pending,
librarian_martigny_no_email,
json_header):
"""Test record retrieval."""
Expand Down
5 changes: 5 additions & 0 deletions tests/api/test_patrons_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@

import mock
from flask import url_for
from invenio_accounts.testutils import login_user_via_session
from utils import VerifyRecordPermissionPatch, get_json, to_relative_url

from rero_ils.modules.items.api import ItemStatus
from rero_ils.modules.loans.api import Loan, LoanAction
from rero_ils.modules.patrons.utils import user_has_patron


def test_patrons_permissions(client, librarian_martigny_no_email,
json_header):
Expand Down
152 changes: 152 additions & 0 deletions tests/api/test_patrons_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#
# This file is part of RERO ILS.
# Copyright (C) 2017 RERO.
#
# RERO ILS is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# RERO ILS is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with RERO ILS; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
#
# In applying this license, RERO does not
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.

"""Tests Views for patrons."""

import json

import mock
import pytest
from flask import url_for
from invenio_accounts.testutils import login_user_via_session
from utils import VerifyRecordPermissionPatch, get_json, to_relative_url

from rero_ils.modules.items.api import ItemStatus
from rero_ils.modules.loans.api import Loan, LoanAction
from rero_ils.modules.patrons.cli import import_users
from rero_ils.modules.patrons.listener import func_item_at_desk, \
listener_item_at_desk
from rero_ils.modules.patrons.utils import user_has_patron


def test_patron_can_delete(client, librarian_martigny_no_email,
patron_martigny_no_email, loc_public_martigny,
item_lib_martigny, json_header,
circulation_policies):
"""Test patron can delete."""
login_user_via_session(client, librarian_martigny_no_email.user)
item = item_lib_martigny
patron = patron_martigny_no_email
location = loc_public_martigny
# request
res = client.post(
url_for('api_item.librarian_request'),
data=json.dumps(
dict(
item_pid=item.pid,
pickup_location_pid=location.pid,
patron_pid=patron.pid
)
),
content_type='application/json',
)
assert res.status_code == 200
data = get_json(res)
loan_pid = data.get('action_applied')[LoanAction.REQUEST].get('loan_pid')

links = patron_martigny_no_email.get_links_to_me()
assert 'loans' in links

assert not patron_martigny_no_email.can_delete

reasons = patron_martigny_no_email.reasons_not_to_delete()
assert 'links' in reasons

item.cancel_loan(loan_pid=loan_pid)
assert item.status == ItemStatus.ON_SHELF


def test_patron_utils(client, librarian_martigny_no_email,
patron_martigny_no_email, loc_public_martigny,
item_lib_martigny, json_header,
circulation_policies, librarian_martigny):
"""Test patron utils."""
login_user_via_session(client, librarian_martigny_no_email.user)
item = item_lib_martigny
patron = patron_martigny_no_email
location = loc_public_martigny

from rero_ils.modules.patrons.views import get_location_name_from_pid
assert get_location_name_from_pid(loc_public_martigny.pid) == \
location.get('name')

from rero_ils.modules.patrons.views import get_patron_from_pid
assert get_patron_from_pid(patron.pid) == patron

from rero_ils.modules.patrons.views import get_checkout_loan_for_item
assert not get_checkout_loan_for_item(item.pid)

from rero_ils.modules.patrons.views import get_patron_from_barcode
assert get_patron_from_barcode(patron.get('barcode')) == patron


def test_librarian_pickup_locations(client, librarian_martigny_no_email,
lib_martigny, loc_public_martigny,
patron_martigny_no_email,
patron_martigny):
"""Test get librarian pickup locations."""
login_user_via_session(client, librarian_martigny_no_email.user)

with mock.patch(
'rero_ils.modules.patrons.api.current_patron',
librarian_martigny_no_email
):
assert user_has_patron
pick = librarian_martigny_no_email.get_librarian_pickup_location_pid()
assert pick == loc_public_martigny.pid

with mock.patch(
'rero_ils.modules.patrons.api.current_patron',
patron_martigny
):
assert user_has_patron
pick = librarian_martigny_no_email.get_librarian_pickup_location_pid()
assert not pick
record = patron_martigny
del record['roles']
assert user_has_patron


def test_patron_listener(client, librarian_martigny_no_email,
item_lib_fully,
lib_fully, loc_public_martigny,
patron_martigny_no_email,
patron_martigny,
loan_pending):
"""Test patron listener."""
login_user_via_session(client, librarian_martigny_no_email.user)
requests = item_lib_fully.number_of_requests()
assert requests == 1
for request in item_lib_fully.get_requests():
item_lib_fully.validate_request(**request)
item_lib_fully.receive(**loan_pending)

with mock.patch(
'rero_ils.modules.ext.current_admin',
{}
):
sender = {}
data = {'item': item_lib_fully}
with mock.patch('rero_ils.utils.send_mail'):
with pytest.raises(AttributeError):
assert listener_item_at_desk(sender, **data)
1 change: 1 addition & 0 deletions tests/data/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,7 @@
"patron_pid": "ptrn1",
"start_date": "2019-01-09T08:18:22.576291+00:00",
"end_date": "2019-02-08T08:18:22.576291+00:00",
"pickup_location_pid": "loc1",
"transaction_date": "2019-01-09T08:18:22.576291+00:00",
"transaction_location_pid": "loc1",
"transaction_user_pid": "ptrn1"
Expand Down
2 changes: 1 addition & 1 deletion tests/fixtures/circulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def loan_data_tmp(data):


@pytest.fixture(scope="module")
def loan_pedning(
def loan_pending(
app,
item_lib_fully,
loc_public_martigny,
Expand Down
Loading

0 comments on commit 4569f33

Please sign in to comment.