invenio-app-ils 4.5.0__py2.py3-none-any.whl → 5.0.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. invenio_app_ils/__init__.py +1 -1
  2. invenio_app_ils/assets/semantic-ui/less/theme.config +103 -0
  3. invenio_app_ils/circulation/api.py +9 -5
  4. invenio_app_ils/circulation/config.py +1 -0
  5. invenio_app_ils/circulation/loaders/schemas/json/loan_checkout.py +1 -1
  6. invenio_app_ils/circulation/loaders/schemas/json/loan_request.py +2 -2
  7. invenio_app_ils/circulation/notifications/api.py +9 -1
  8. invenio_app_ils/circulation/notifications/messages.py +2 -1
  9. invenio_app_ils/circulation/templates/invenio_app_ils_circulation/notifications/update_dates.html +19 -0
  10. invenio_app_ils/cli.py +92 -64
  11. invenio_app_ils/config.py +10 -2
  12. invenio_app_ils/documents/loaders/jsonschemas/document.py +1 -1
  13. invenio_app_ils/eitems/loaders/jsonschemas/eitems.py +2 -2
  14. invenio_app_ils/patrons/anonymization.py +0 -4
  15. invenio_app_ils/series/loaders/jsonschemas/series.py +1 -1
  16. invenio_app_ils/webpack.py +27 -0
  17. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/METADATA +56 -43
  18. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/RECORD +24 -112
  19. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/entry_points.txt +3 -0
  20. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/top_level.txt +0 -1
  21. invenio_app_ils/notifications/admin.py +0 -57
  22. tests/__init__.py +0 -8
  23. tests/api/__init__.py +0 -8
  24. tests/api/acquisition/__init__.py +0 -8
  25. tests/api/acquisition/test_acq_orders_crud.py +0 -99
  26. tests/api/acquisition/test_acq_orders_permissions.py +0 -104
  27. tests/api/acquisition/test_acq_providers_permissions.py +0 -83
  28. tests/api/circulation/__init__.py +0 -8
  29. tests/api/circulation/test_expired_loans.py +0 -88
  30. tests/api/circulation/test_loan_bulk_extend.py +0 -169
  31. tests/api/circulation/test_loan_checkout.py +0 -422
  32. tests/api/circulation/test_loan_default_durations.py +0 -43
  33. tests/api/circulation/test_loan_document_resolver.py +0 -18
  34. tests/api/circulation/test_loan_extend.py +0 -122
  35. tests/api/circulation/test_loan_item_permissions.py +0 -135
  36. tests/api/circulation/test_loan_item_resolver.py +0 -26
  37. tests/api/circulation/test_loan_list_permissions.py +0 -98
  38. tests/api/circulation/test_loan_patron_resolver.py +0 -38
  39. tests/api/circulation/test_loan_request.py +0 -338
  40. tests/api/circulation/test_loan_update.py +0 -150
  41. tests/api/circulation/test_notifications.py +0 -221
  42. tests/api/conftest.py +0 -227
  43. tests/api/document_requests/__init__.py +0 -8
  44. tests/api/document_requests/test_document_requests.py +0 -131
  45. tests/api/document_requests/test_document_requests_permissions.py +0 -159
  46. tests/api/document_requests/test_notifications_filter.py +0 -35
  47. tests/api/ill/__init__.py +0 -8
  48. tests/api/ill/test_ill_brw_crud.py +0 -74
  49. tests/api/ill/test_ill_brw_reqs_patron_loan_create_action.py +0 -198
  50. tests/api/ill/test_ill_brw_reqs_patron_loan_extension_actions.py +0 -280
  51. tests/api/ill/test_ill_brw_reqs_permissions.py +0 -163
  52. tests/api/ill/test_ill_providers_permissions.py +0 -82
  53. tests/api/ils/__init__.py +0 -8
  54. tests/api/ils/documents/__init__.py +0 -8
  55. tests/api/ils/documents/test_document_crud.py +0 -57
  56. tests/api/ils/documents/test_document_permissions.py +0 -100
  57. tests/api/ils/documents/test_document_resolvers.py +0 -35
  58. tests/api/ils/eitems/__init__.py +0 -8
  59. tests/api/ils/eitems/test_eitems_crud.py +0 -42
  60. tests/api/ils/eitems/test_eitems_permissions.py +0 -85
  61. tests/api/ils/eitems/test_files.py +0 -162
  62. tests/api/ils/items/__init__.py +0 -8
  63. tests/api/ils/items/test_apis.py +0 -43
  64. tests/api/ils/items/test_items_crud.py +0 -99
  65. tests/api/ils/items/test_items_permissions.py +0 -107
  66. tests/api/ils/records_relations/__init__.py +0 -8
  67. tests/api/ils/records_relations/helpers.py +0 -115
  68. tests/api/ils/records_relations/test_records_relations_parentchild.py +0 -560
  69. tests/api/ils/records_relations/test_records_relations_sequence.py +0 -294
  70. tests/api/ils/records_relations/test_records_relations_siblings.py +0 -751
  71. tests/api/ils/series/__init__.py +0 -8
  72. tests/api/ils/series/test_series_permissions.py +0 -95
  73. tests/api/ils/test_anonymization.py +0 -181
  74. tests/api/ils/test_apis.py +0 -76
  75. tests/api/ils/test_closures.py +0 -353
  76. tests/api/ils/test_errors.py +0 -125
  77. tests/api/ils/test_facets.py +0 -88
  78. tests/api/ils/test_internal_locations.py +0 -96
  79. tests/api/ils/test_loaders.py +0 -51
  80. tests/api/ils/test_metadata_extensions.py +0 -206
  81. tests/api/ils/test_notifications.py +0 -173
  82. tests/api/ils/test_notifications_mails.py +0 -37
  83. tests/api/ils/test_notifications_permissions.py +0 -55
  84. tests/api/ils/test_patrons.py +0 -102
  85. tests/api/ils/test_record_delete.py +0 -42
  86. tests/api/ils/test_record_permissions.py +0 -132
  87. tests/api/ils/test_resolvers.py +0 -205
  88. tests/api/ils/test_stats.py +0 -142
  89. tests/api/ils/test_tasks.py +0 -209
  90. tests/api/ils/test_vocabularies.py +0 -35
  91. tests/conftest.py +0 -221
  92. tests/data/acq_orders.json +0 -110
  93. tests/data/acq_providers.json +0 -12
  94. tests/data/document_requests.json +0 -77
  95. tests/data/documents.json +0 -238
  96. tests/data/eitems.json +0 -71
  97. tests/data/ill_borrowing_requests.json +0 -77
  98. tests/data/ill_providers.json +0 -12
  99. tests/data/internal_locations.json +0 -22
  100. tests/data/items.json +0 -304
  101. tests/data/loans.json +0 -133
  102. tests/data/loans_most_loaned.json +0 -128
  103. tests/data/locations.json +0 -26
  104. tests/data/series.json +0 -33
  105. tests/helpers.py +0 -107
  106. tests/templates/notifications/title_body.html +0 -8
  107. tests/templates/notifications/title_body_html.html +0 -13
  108. tests/templates/notifications/title_body_html_ctx.html +0 -13
  109. tests/templates/notifications/title_only.html +0 -3
  110. tests/test_post_logout_redirect.py +0 -23
  111. tests/test_version.py +0 -17
  112. /tests/templates/notifications/blank.html → /invenio_app_ils/assets/semantic-ui/templates/.gitkeep +0 -0
  113. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/WHEEL +0 -0
  114. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/licenses/AUTHORS.rst +0 -0
  115. {invenio_app_ils-4.5.0.dist-info → invenio_app_ils-5.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,104 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2020 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test acquisition orders."""
9
-
10
- import json
11
-
12
- from flask import url_for
13
-
14
- from tests.helpers import user_login
15
-
16
- _HTTP_OK = [200, 201, 204]
17
- ORDER_PID = "acqoid-1"
18
- ITEM_ENDPOINT = "invenio_records_rest.acqoid_item"
19
- LIST_ENDPOINT = "invenio_records_rest.acqoid_list"
20
-
21
-
22
- def test_acq_orders_permissions(client, testdata, json_headers, users):
23
- """Test orders endpoints permissions."""
24
- dummy_acquisition_order = dict(
25
- status="PENDING",
26
- order_date="2020-02-25",
27
- provider_pid="acq-provid-1",
28
- order_lines=[
29
- dict(
30
- copies_ordered=3,
31
- document_pid="docid-1",
32
- medium="paper",
33
- recipient="library",
34
- )
35
- ],
36
- )
37
-
38
- def _test_list(expected_status):
39
- """Test get list."""
40
- url = url_for(LIST_ENDPOINT)
41
- res = client.get(url, headers=json_headers)
42
- assert res.status_code in expected_status
43
-
44
- def _test_create(expected_status, data, user):
45
- """Test record creation."""
46
- url = url_for(LIST_ENDPOINT)
47
- res = client.post(url, headers=json_headers, data=json.dumps(data))
48
- assert res.status_code in expected_status
49
-
50
- if res.status_code < 400:
51
- ord = res.get_json()["metadata"]
52
- assert ord["status"] == "PENDING"
53
- expected_created_by = dict(type="user_id", value=str(user.id))
54
- assert ord["created_by"] == expected_created_by
55
- assert not ord.get("updated_by")
56
- return ord["pid"]
57
-
58
- def _test_update(expected_status, data, pid, user):
59
- """Test record update."""
60
- pid_value = pid or ORDER_PID
61
- url = url_for(ITEM_ENDPOINT, pid_value=pid_value)
62
- res = client.put(url, headers=json_headers, data=json.dumps(data))
63
- assert res.status_code in expected_status
64
- if res.status_code < 400:
65
- expected_changed_by = dict(type="user_id", value=str(user.id))
66
- ord = res.get_json()["metadata"]
67
- assert ord["created_by"] == expected_changed_by
68
- assert ord["updated_by"] == expected_changed_by
69
-
70
- def _test_read(expected_status, pid):
71
- """Test record read."""
72
- pid_value = pid or ORDER_PID
73
- url = url_for(ITEM_ENDPOINT, pid_value=pid_value)
74
- res = client.get(url, headers=json_headers)
75
- assert res.status_code in expected_status
76
-
77
- def _test_delete(expected_status, pid):
78
- """Test record delete."""
79
- url = url_for(ITEM_ENDPOINT, pid_value=pid)
80
- res = client.delete(url, headers=json_headers)
81
- assert res.status_code in expected_status
82
-
83
- tests = [
84
- ("admin", _HTTP_OK, dummy_acquisition_order),
85
- ("librarian", _HTTP_OK, dummy_acquisition_order),
86
- ("patron1", [403], dummy_acquisition_order),
87
- ("anonymous", [401], dummy_acquisition_order),
88
- ]
89
- for username, expected_status, data in tests:
90
- user = user_login(client, username, users)
91
- _test_list(expected_status)
92
- pid = _test_create(expected_status, data, user)
93
- _test_update(expected_status, data, pid, user)
94
- _test_read(expected_status, pid)
95
-
96
- tests = [
97
- ("patron1", [403]),
98
- ("anonymous", [401]),
99
- ("librarian", [403]),
100
- ("admin", [204]),
101
- ]
102
- for username, expected_status in tests:
103
- user_login(client, username, users)
104
- _test_delete(expected_status, ORDER_PID)
@@ -1,83 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2020 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test acquisition provider."""
9
-
10
- import json
11
-
12
- from flask import url_for
13
-
14
- from tests.helpers import user_login
15
-
16
- _HTTP_OK = [200, 201, 204]
17
- PROVIDER_PID = "acq-provid-1"
18
- PROVIDER_NAME = "A provider"
19
- PROVIDER_TYPE = "VENDOR"
20
- ITEM_ENDPOINT = "invenio_records_rest.provid_item"
21
- LIST_ENDPOINT = "invenio_records_rest.provid_list"
22
-
23
-
24
- def test_acq_providers_permissions(client, testdata, json_headers, users):
25
- """Test providers endpoints permissions."""
26
- dummy_acquisition_provider = dict(name=PROVIDER_NAME, type=PROVIDER_TYPE)
27
- tests = [
28
- ("admin", _HTTP_OK, dummy_acquisition_provider),
29
- ("librarian", _HTTP_OK, dummy_acquisition_provider),
30
- ("patron1", [403], dummy_acquisition_provider),
31
- ("anonymous", [401], dummy_acquisition_provider),
32
- ]
33
-
34
- def _test_list(expected_status):
35
- """Test get list."""
36
- url = url_for(LIST_ENDPOINT)
37
- res = client.get(url, headers=json_headers)
38
- assert res.status_code in expected_status
39
-
40
- def _test_create(expected_status, data):
41
- """Test record creation."""
42
- url = url_for(LIST_ENDPOINT)
43
- print("DICT", json.dumps(data))
44
- res = client.post(url, headers=json_headers, data=json.dumps(data))
45
- assert res.status_code in expected_status
46
-
47
- if res.status_code < 400:
48
- record = res.get_json()["metadata"]
49
- assert record["name"] == PROVIDER_NAME
50
- assert record["type"] == PROVIDER_TYPE
51
- return record["pid"]
52
-
53
- def _test_update(expected_status, data, pid):
54
- """Test record update."""
55
- pid_value = pid or PROVIDER_PID
56
- url = url_for(ITEM_ENDPOINT, pid_value=pid_value)
57
- res = client.put(url, headers=json_headers, data=json.dumps(data))
58
- assert res.status_code in expected_status
59
- if res.status_code < 400:
60
- record = res.get_json()["metadata"]
61
- assert record["name"] == PROVIDER_NAME
62
-
63
- def _test_read(expected_status, pid):
64
- """Test record read."""
65
- pid_value = pid or PROVIDER_PID
66
- url = url_for(ITEM_ENDPOINT, pid_value=pid_value)
67
- res = client.get(url, headers=json_headers)
68
- assert res.status_code in expected_status
69
-
70
- def _test_delete(expected_status, pid):
71
- """Test record delete."""
72
- pid_value = pid or PROVIDER_PID
73
- url = url_for(ITEM_ENDPOINT, pid_value=pid_value)
74
- res = client.delete(url, headers=json_headers)
75
- assert res.status_code in expected_status
76
-
77
- for username, expected_status, data in tests:
78
- user_login(client, username, users)
79
- _test_list(expected_status)
80
- pid = _test_create(expected_status, data)
81
- _test_update(expected_status, data, pid)
82
- _test_read(expected_status, pid)
83
- _test_delete(expected_status, pid)
@@ -1,8 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2020 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Circulation API Tests."""
@@ -1,88 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2020 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test transitions on expiring loans."""
9
-
10
- from datetime import timedelta
11
-
12
- import arrow
13
- from flask import url_for
14
- from invenio_indexer.api import RecordIndexer
15
- from invenio_search import current_search
16
-
17
- from invenio_app_ils.circulation.tasks import cancel_expired_loan_requests
18
- from invenio_app_ils.patrons.api import SystemAgent
19
- from tests.helpers import user_login
20
-
21
-
22
- def test_cancel_expired_loans(client, json_headers, db, users, testdata):
23
- """Test cancellation of loan requests after expiration date."""
24
-
25
- user_login(client, "admin", users)
26
-
27
- def prepare_data():
28
- """Prepare data."""
29
- loans = testdata["loans"]
30
-
31
- recs = []
32
- now = arrow.utcnow()
33
-
34
- def new_expiration_date(loan, date):
35
- loan["request_expire_date"] = date.date().isoformat()
36
- loan["state"] = "PENDING"
37
- loan.commit()
38
- recs.append(loan)
39
-
40
- # expired loans
41
- date = now - timedelta(days=1)
42
- new_expiration_date(loans[0], date)
43
- new_expiration_date(loans[1], date)
44
- date = now - timedelta(days=2)
45
- new_expiration_date(loans[2], date)
46
- expired_pids = [loans[0]["pid"], loans[1]["pid"], loans[2]["pid"]]
47
-
48
- # not expired loans
49
- not_expired_pids = []
50
- remaining_not_expired = loans[3:]
51
- n_days = 0 # today
52
- for loan in remaining_not_expired:
53
- date = now + timedelta(days=n_days)
54
- new_expiration_date(loan, date)
55
- not_expired_pids.append(loan["pid"])
56
- n_days += 1
57
- db.session.commit()
58
-
59
- indexer = RecordIndexer()
60
- for rec in recs:
61
- indexer.index(rec)
62
-
63
- current_search.flush_and_refresh(index="*")
64
- return expired_pids, not_expired_pids
65
-
66
- expired_pids, not_expired_pids = prepare_data()
67
-
68
- # trigger cancel expired loan requests
69
- cancel_expired_loan_requests.apply_async()
70
-
71
- for pid_value in expired_pids:
72
- res = client.get(
73
- url_for("invenio_records_rest.loanid_item", pid_value=pid_value),
74
- headers=json_headers,
75
- )
76
- loan = res.get_json()["metadata"]
77
- assert loan["state"] == "CANCELLED"
78
- assert "cancel_reason" in loan
79
- assert loan["transaction_user_pid"] == str(SystemAgent.id)
80
-
81
- for pid_value in not_expired_pids:
82
- res = client.get(
83
- url_for("invenio_records_rest.loanid_item", pid_value=pid_value),
84
- headers=json_headers,
85
- )
86
- loan = res.get_json()["metadata"]
87
- assert loan["state"] == "PENDING"
88
- assert "cancel_reason" not in loan
@@ -1,169 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2019-2020 CERN.
4
- #
5
- # invenio-app-ils is free software; you can redistribute it and/or modify it
6
- # under the terms of the MIT License; see LICENSE file for more details.
7
-
8
- """Test bulk loan extension."""
9
-
10
- from datetime import timedelta
11
-
12
- import arrow
13
- from flask import current_app
14
- from invenio_circulation.api import Loan
15
- from invenio_circulation.pidstore.pids import CIRCULATION_LOAN_PID_TYPE
16
- from invenio_circulation.proxies import current_circulation
17
- from invenio_search import current_search
18
-
19
- from invenio_app_ils.circulation.api import bulk_extend_loans
20
- from invenio_app_ils.items.api import ITEM_PID_TYPE, Item
21
- from invenio_app_ils.proxies import current_app_ils
22
- from tests.api.conftest import _create_records
23
- from tests.helpers import user_login
24
-
25
- pid_start_value = 200
26
- amount_of_ongoing_loans = 3
27
- amount_of_overdue_loans = 3
28
- pid_end_value = pid_start_value + amount_of_ongoing_loans + amount_of_overdue_loans
29
-
30
-
31
- def create_loans(start=pid_start_value, end=pid_end_value):
32
- ongoing_loans = []
33
- overdue_loans = []
34
-
35
- day_range_loan_extendable = current_app.config[
36
- "ILS_CIRCULATION_LOAN_WILL_EXPIRE_DAYS"
37
- ]
38
-
39
- now = arrow.utcnow()
40
-
41
- start_date_expiring = now.isoformat()
42
- start_date_overdue = (now - timedelta(days=5)).isoformat()
43
-
44
- end_date_expiring = (
45
- now + timedelta(days=day_range_loan_extendable - 1)
46
- ).isoformat()
47
- end_date_overdue = (now - timedelta(days=2)).isoformat()
48
-
49
- def loan_generator(pid_value, overdue_loan=False):
50
- end_date = end_date_overdue if overdue_loan else end_date_expiring
51
- start_date = start_date_overdue if overdue_loan else start_date_expiring
52
-
53
- loan = {
54
- "document_pid": "docid-1",
55
- "end_date": end_date,
56
- "item_pid": {"type": "pitmid", "value": f"itemid-{pid_value}"},
57
- "patron_pid": "1",
58
- "pickup_location_pid": "locid-1",
59
- "pid": f"loanid-{pid_value}",
60
- "start_date": start_date,
61
- "state": "ITEM_ON_LOAN",
62
- "transaction_location_pid": "locid-1",
63
- "transaction_user_pid": "1",
64
- "patron": {"email": "patron1@test.ch"},
65
- }
66
-
67
- return loan
68
-
69
- for number in range(start, end):
70
- if len(ongoing_loans) < amount_of_ongoing_loans:
71
- ongoing_loans.append(loan_generator(number))
72
- elif len(overdue_loans) < amount_of_overdue_loans:
73
- overdue_loans.append(loan_generator(number, True))
74
-
75
- return ongoing_loans + overdue_loans
76
-
77
-
78
- def create_items(start=pid_start_value, end=pid_end_value):
79
- items = []
80
-
81
- def items_generator(pid_value):
82
- item = {
83
- "pid": f"itemid-{pid_value}",
84
- "created_by": {"type": "script", "value": "demo"},
85
- "barcode": f"123456{pid_value}89-1",
86
- "document_pid": "docid-1",
87
- "internal_location_pid": "ilocid-1",
88
- "circulation_restriction": "NO_RESTRICTION",
89
- "medium": "NOT_SPECIFIED",
90
- "status": "CAN_CIRCULATE",
91
- "document": {},
92
- }
93
- return item
94
-
95
- for number in range(start, end):
96
- items.append(items_generator(number))
97
-
98
- return items
99
-
100
-
101
- def _prepare_data(db, repeated_run_number=0):
102
- total_loans = amount_of_ongoing_loans + amount_of_overdue_loans
103
- added_value = repeated_run_number * total_loans + repeated_run_number
104
-
105
- new_pid_start_value = pid_start_value + added_value
106
- new_pid_end_value = pid_end_value + added_value
107
-
108
- loans = create_loans(new_pid_start_value, new_pid_end_value)
109
- items = create_items(new_pid_start_value, new_pid_end_value)
110
-
111
- bulk_index_items = _create_records(db, items, Item, ITEM_PID_TYPE)
112
- bulk_index_loans = _create_records(db, loans, Loan, CIRCULATION_LOAN_PID_TYPE)
113
-
114
- for item in bulk_index_items:
115
- current_app_ils.item_indexer.index(item)
116
-
117
- for loan in bulk_index_loans:
118
- current_circulation.loan_indexer().index(loan)
119
-
120
- current_search.flush_and_refresh(index="*")
121
-
122
- return {"loans": bulk_index_loans, "items": bulk_index_items}
123
-
124
-
125
- def test_loan_extend_permissions(
126
- client, json_headers, users, testdata, loan_params, db
127
- ):
128
- def _run_asserts(extended_loans, loans, patron_pid="1"):
129
- assert len(extended_loans) >= len(loans)
130
-
131
- for extended_loan in extended_loans:
132
- for loan in loans:
133
- if loan["pid"] == extended_loan["pid"]:
134
- assert extended_loan["state"] == "ITEM_ON_LOAN"
135
- assert extended_loan["patron_pid"] == str(patron_pid)
136
- assert extended_loan["end_date"] > loan["end_date"]
137
-
138
- def test_patron1_can_extend_own_loans():
139
- patron_1_ongoing_loans = _prepare_data(db)["loans"]
140
-
141
- user_login(client, "patron1", users)
142
-
143
- extended_loans, _ = bulk_extend_loans(patron_pid=1)
144
-
145
- _run_asserts(extended_loans, patron_1_ongoing_loans)
146
-
147
- def test_library_can_extend_any_loan():
148
- patron_1_ongoing_loans = _prepare_data(db, repeated_run_number=1)["loans"]
149
-
150
- user_login(client, "librarian", users)
151
-
152
- extended_loans, _ = bulk_extend_loans(patron_pid=1)
153
-
154
- _run_asserts(extended_loans, patron_1_ongoing_loans)
155
-
156
- def test_patron2_cannot_extend_patron1_loans():
157
- _prepare_data(db, repeated_run_number=2)
158
-
159
- user_login(client, "patron2", users)
160
-
161
- patron1_pid = "1"
162
-
163
- extended_loans, _ = bulk_extend_loans(patron1_pid)
164
-
165
- assert len(extended_loans) == 0
166
-
167
- test_patron1_can_extend_own_loans()
168
- test_library_can_extend_any_loan()
169
- test_patron2_cannot_extend_patron1_loans()