invenio-app-ils 4.6.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.6.0.dist-info → invenio_app_ils-5.0.0.dist-info}/METADATA +52 -42
  18. {invenio_app_ils-4.6.0.dist-info → invenio_app_ils-5.0.0.dist-info}/RECORD +24 -112
  19. {invenio_app_ils-4.6.0.dist-info → invenio_app_ils-5.0.0.dist-info}/entry_points.txt +3 -0
  20. {invenio_app_ils-4.6.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.6.0.dist-info → invenio_app_ils-5.0.0.dist-info}/WHEEL +0 -0
  114. {invenio_app_ils-4.6.0.dist-info → invenio_app_ils-5.0.0.dist-info}/licenses/AUTHORS.rst +0 -0
  115. {invenio_app_ils-4.6.0.dist-info → invenio_app_ils-5.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,131 +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 document requests."""
9
-
10
- import json
11
-
12
- from flask import url_for
13
-
14
- from tests.helpers import user_login
15
-
16
-
17
- def _compare_list_data(all_expected, data, user_id, is_admin):
18
- """Compare list data with expected values."""
19
- if is_admin:
20
- expected = []
21
- for pids in all_expected.values():
22
- for pid in pids:
23
- expected.append(pid)
24
- else:
25
- expected = all_expected[str(user_id)]
26
-
27
- for hit in data["hits"]["hits"]:
28
- assert hit["metadata"]["pid"] in expected
29
-
30
-
31
- def test_request_list_permissions(client, testdata, json_headers, users):
32
- """Test doc req list permissions."""
33
- url = url_for("invenio_records_rest.dreqid_list")
34
- res = client.get(url, headers=json_headers)
35
- assert res.status_code == 401
36
-
37
- requests_by_patron = {}
38
- for req in testdata["document_requests"]:
39
- if req["patron_pid"] not in requests_by_patron:
40
- requests_by_patron[req["patron_pid"]] = []
41
- requests_by_patron[req["patron_pid"]].append(req["pid"])
42
-
43
- for username in users.keys():
44
- user = user_login(client, username, users)
45
- url = url_for("invenio_records_rest.dreqid_list")
46
- res = client.get(url, headers=json_headers)
47
- assert res.status_code == 200
48
- data = json.loads(res.data.decode("utf-8"))
49
- is_admin = "librarian" in user.email or "admin" in user.email
50
- _compare_list_data(requests_by_patron, data, user.id, is_admin)
51
-
52
-
53
- def test_create_document_request(client, testdata, json_headers, users):
54
- """Test creating document requests."""
55
- tests = [
56
- (
57
- "admin",
58
- 201,
59
- dict(
60
- title="Test title",
61
- request_type="LOAN",
62
- medium="Paper",
63
- patron_pid="1",
64
- ),
65
- ),
66
- (
67
- "librarian",
68
- 400,
69
- dict(
70
- patron_pid="1",
71
- ),
72
- ),
73
- (
74
- "admin",
75
- 201,
76
- dict(
77
- patron_pid="1",
78
- title="Test",
79
- invalid_param="Test",
80
- request_type="LOAN",
81
- medium="Paper",
82
- ),
83
- ),
84
- (
85
- "librarian",
86
- 201,
87
- dict(
88
- title="Test title",
89
- patron_pid="1",
90
- request_type="BUY",
91
- medium="Paper",
92
- ),
93
- ),
94
- (
95
- "patron1",
96
- 201,
97
- dict(
98
- title="Test title",
99
- patron_pid="1",
100
- request_type="BUY",
101
- medium="Paper",
102
- ),
103
- ),
104
- (
105
- "patron2",
106
- 400,
107
- dict(
108
- title="Test title",
109
- patron_pid="1",
110
- request_type="LOAN",
111
- medium="Paper",
112
- ),
113
- ),
114
- (
115
- "patron2",
116
- 201,
117
- dict(
118
- title="Test title",
119
- patron_pid="2",
120
- request_type="LOAN",
121
- medium="Paper",
122
- ),
123
- ),
124
- ]
125
- for username, expected_status, data in tests:
126
- user_login(client, username, users)
127
- url = url_for("invenio_records_rest.dreqid_list")
128
- res = client.post(url, headers=json_headers, data=json.dumps(data))
129
- assert res.status_code == expected_status
130
- if res.status_code == 201:
131
- assert "invalid_param" not in json.loads(res.data)["metadata"]
@@ -1,159 +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 accessibility of document request resource endpoints."""
9
-
10
- from flask import url_for
11
-
12
- from tests.helpers import user_login, validate_response
13
-
14
-
15
- def test_get_document_request_endpoint(client, json_headers, testdata, users):
16
- """Test GET permissions."""
17
-
18
- tests = [
19
- ("patron1", "dreq-1", 200),
20
- ("librarian", "dreq-1", 200),
21
- ("admin", "dreq-1", 200),
22
- ("patron2", "dreq-1", 403),
23
- ("anonymous", "dreq-1", 401),
24
- ("patron2", "dreq-2", 200),
25
- ("librarian", "dreq-2", 200),
26
- ("admin", "dreq-2", 200),
27
- ("patron1", "dreq-2", 403),
28
- ("anonymous", "dreq-2", 401),
29
- ]
30
-
31
- for user, res_id, expected_resp_code in tests:
32
- user_login(client, user, users)
33
- url = url_for("invenio_records_rest.dreqid_item", pid_value=res_id)
34
- validate_response(client, "get", url, json_headers, None, expected_resp_code)
35
-
36
-
37
- def test_document_request_add_document(client, json_headers, testdata, users):
38
- """Test add document to Document Request permissions."""
39
-
40
- tests = [
41
- ("patron1", "dreq-1", 403),
42
- ("librarian", "dreq-1", 202),
43
- ("admin", "dreq-1", 202),
44
- ("anonymous", "dreq-1", 401),
45
- ]
46
-
47
- for user, res_id, expected_resp_code in tests:
48
- user_login(client, user, users)
49
- url = url_for(
50
- "invenio_app_ils_document_requests.dreqid_document",
51
- pid_value=res_id,
52
- )
53
- data = {"document_pid": "docid-1"}
54
- validate_response(client, "post", url, json_headers, data, expected_resp_code)
55
-
56
-
57
- def test_document_request_remove_document(client, json_headers, testdata, users):
58
- """Test remove document from Document Request permissions."""
59
-
60
- tests = [
61
- ("patron1", "dreq-1", 403),
62
- ("librarian", "dreq-1", 202),
63
- ("admin", "dreq-1", 202),
64
- ("anonymous", "dreq-1", 401),
65
- ]
66
-
67
- for user, res_id, expected_resp_code in tests:
68
- user_login(client, user, users)
69
- url = url_for(
70
- "invenio_app_ils_document_requests.dreqid_document",
71
- pid_value=res_id,
72
- )
73
- data = {"document_pid": "docid-1"}
74
- validate_response(client, "delete", url, json_headers, data, expected_resp_code)
75
-
76
-
77
- def test_document_request_add_provider(client, json_headers, testdata, users):
78
- """Test add provider to Document Request permissions."""
79
-
80
- tests = [
81
- ("patron1", "dreq-1", 403),
82
- ("librarian", "dreq-1", 202),
83
- ("admin", "dreq-1", 202),
84
- ("anonymous", "dreq-1", 401),
85
- ]
86
-
87
- for user, res_id, expected_resp_code in tests:
88
- user_login(client, user, users)
89
- url = url_for(
90
- "invenio_app_ils_document_requests.dreqid_provider",
91
- pid_value=res_id,
92
- )
93
- data = {
94
- "physical_item_provider": {
95
- "pid": "acqoid-1",
96
- "pid_type": "acqoid",
97
- }
98
- }
99
- validate_response(client, "post", url, json_headers, data, expected_resp_code)
100
-
101
-
102
- def test_document_request_remove_provider(client, json_headers, testdata, users):
103
- """Test remove provider from Document Request permissions."""
104
-
105
- tests = [
106
- ("patron1", "dreq-1", 403),
107
- ("librarian", "dreq-1", 202),
108
- ("admin", "dreq-1", 202),
109
- ("anonymous", "dreq-1", 401),
110
- ]
111
-
112
- for user, res_id, expected_resp_code in tests:
113
- user_login(client, user, users)
114
- url = url_for(
115
- "invenio_app_ils_document_requests.dreqid_provider",
116
- pid_value=res_id,
117
- )
118
- validate_response(client, "delete", url, json_headers, None, expected_resp_code)
119
-
120
-
121
- def test_document_request_accept(client, json_headers, testdata, users):
122
- """Test Document Request permissions to accept request."""
123
-
124
- tests = [
125
- ("patron1", "dreq-1", 403),
126
- ("librarian", "dreq-5", 202),
127
- ("admin", "dreq-6", 202),
128
- ("anonymous", "dreq-1", 401),
129
- ("admin", "dreq-2", 400),
130
- ]
131
-
132
- for user, res_id, expected_resp_code in tests:
133
- user_login(client, user, users)
134
- url = url_for(
135
- "invenio_app_ils_document_requests.dreqid_accept", pid_value=res_id
136
- )
137
- data = {"state": "ACCEPTED"}
138
- validate_response(client, "post", url, json_headers, data, expected_resp_code)
139
-
140
-
141
- def test_document_request_decline(client, json_headers, testdata, users):
142
- """Test Document Request permissions to decline request."""
143
-
144
- tests = [
145
- ("patron1", "dreq-1", 202),
146
- ("librarian", "dreq-5", 202),
147
- ("admin", "dreq-6", 202),
148
- ("anonymous", "dreq-1", 401),
149
- ("admin", "dreq-2", 400),
150
- ]
151
-
152
- for user, res_id, expected_resp_code in tests:
153
- user_login(client, user, users)
154
- url = url_for(
155
- "invenio_app_ils_document_requests.dreqid_decline",
156
- pid_value=res_id,
157
- )
158
- data = {"decline_reason": "USER_CANCEL"}
159
- validate_response(client, "post", url, json_headers, data, expected_resp_code)
@@ -1,35 +0,0 @@
1
- from invenio_app_ils.document_requests.notifications.api import (
2
- send_document_request_notification,
3
- )
4
-
5
-
6
- def test_notification_document_request_filter(app_with_notifs, mocker, users, testdata):
7
- """Test notification filtering."""
8
-
9
- def filter_document_request_messages(record, action, **kwargs):
10
- """Define notification filter."""
11
- if action == "decline":
12
- return False
13
- return True
14
-
15
- send_mocked = mocker.patch("invenio_app_ils.notifications.backends.mail.send")
16
- send_mocked.__name__ = "send"
17
- send_mocked.__annotations__ = "send"
18
- backends = mocker.patch(
19
- "invenio_app_ils.notifications.api._get_notification_backends",
20
- return_value=[send_mocked],
21
- )
22
- document_request = testdata["document_requests"][0]
23
- with app_with_notifs.app_context():
24
- # remove footer
25
- app_with_notifs.config["ILS_NOTIFICATIONS_TEMPLATES"] = {}
26
- # set filtering on the document requests
27
- app_with_notifs.config["ILS_NOTIFICATIONS_FILTER_DOCUMENT_REQUEST"] = (
28
- filter_document_request_messages
29
- )
30
-
31
- send_document_request_notification(
32
- document_request, action="decline", msg_extra_ctx={}
33
- )
34
-
35
- assert not send_mocked.apply_async.called
tests/api/ill/__init__.py DELETED
@@ -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
- """ILL API Tests."""
@@ -1,74 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2021 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 record CRUD."""
9
-
10
- import pytest
11
-
12
- from invenio_app_ils.errors import DocumentNotFoundError, PatronNotFoundError
13
- from invenio_app_ils.ill.api import BorrowingRequest
14
- from invenio_app_ils.ill.errors import ILLError
15
- from invenio_app_ils.providers.errors import ProviderNotFoundError
16
-
17
-
18
- def test_brw_req_refs(app, testdata):
19
- """Test creation of a borrowing request."""
20
- brw_req = BorrowingRequest.create(
21
- dict(
22
- pid="illlid-99",
23
- document_pid="docid-1",
24
- patron_pid="1",
25
- provider_pid="ill-provid-1",
26
- status="PENDING",
27
- type="PHYSICAL_COPY",
28
- )
29
- )
30
- assert "$schema" in brw_req
31
- assert "provider" in brw_req and "$ref" in brw_req["provider"]
32
- assert "document" in brw_req and "$ref" in brw_req["document"]
33
- assert "patron" in brw_req and "$ref" in brw_req["patron"]
34
-
35
- brw_req = BorrowingRequest.get_record_by_pid("illbid-1")
36
- brw_req = brw_req.replace_refs()
37
- assert "provider" in brw_req and brw_req["provider"]["name"]
38
- assert "document" in brw_req and brw_req["document"]["title"]
39
- assert "patron" in brw_req and brw_req["patron"]["name"]
40
-
41
-
42
- def test_ill_brw_validation(db, testdata):
43
- """Test validation when updating a borrowing request."""
44
- borrowing_request_pid = testdata["ill_brw_reqs"][0]["pid"]
45
-
46
- # change document pid
47
- borrowing_request = BorrowingRequest.get_record_by_pid(borrowing_request_pid)
48
- borrowing_request["document_pid"] = "not_found_doc"
49
- with pytest.raises(DocumentNotFoundError):
50
- borrowing_request.commit()
51
-
52
- # change provider pid
53
- borrowing_request = BorrowingRequest.get_record_by_pid(borrowing_request_pid)
54
- borrowing_request["provider_pid"] = "not_found_lib"
55
- with pytest.raises(ProviderNotFoundError):
56
- borrowing_request.commit()
57
-
58
- # change patron pid
59
- borrowing_request = BorrowingRequest.get_record_by_pid(borrowing_request_pid)
60
- borrowing_request["patron_pid"] = "9999"
61
- with pytest.raises(PatronNotFoundError):
62
- borrowing_request.commit()
63
-
64
- # add cancel reason without status CANCELLED
65
- borrowing_request = BorrowingRequest.get_record_by_pid(borrowing_request_pid)
66
- borrowing_request["cancel_reason"] = "USER_CANCEL"
67
- with pytest.raises(ILLError):
68
- borrowing_request.commit()
69
-
70
- # update status to CANCELLED without cancel_reason
71
- borrowing_request = BorrowingRequest.get_record_by_pid(borrowing_request_pid)
72
- borrowing_request["status"] = "CANCELLED"
73
- with pytest.raises(ILLError):
74
- borrowing_request.commit()
@@ -1,198 +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 ILL borrowing requests actions."""
9
-
10
- import json
11
- from datetime import timedelta
12
-
13
- import arrow
14
- from flask import url_for
15
-
16
- from invenio_app_ils.ill.api import BORROWING_REQUEST_PID_TYPE, BorrowingRequest
17
- from tests.helpers import user_login
18
-
19
- _HTTP_OK = [200, 201, 204]
20
- ITEM_ENDPOINT = "invenio_records_rest.illbid_item"
21
- LIST_ENDPOINT = "invenio_records_rest.illbid_list"
22
-
23
-
24
- def _create_loan_action(pid, data, client, json_headers):
25
- """Send request to create a new loan from the ILL."""
26
- url = url_for("invenio_app_ils_ill.illbid_create_loan", pid_value=pid)
27
- data["transaction_location_pid"] = "locid-1"
28
- return client.post(url, headers=json_headers, data=json.dumps(data))
29
-
30
-
31
- def _assert_create_loan_action_fails(pid, data, client, json_headers):
32
- """Asserts that the create loan action validation fails."""
33
- res = _create_loan_action(pid, data, client, json_headers)
34
- assert res.status_code == 400
35
-
36
-
37
- def test_brwreq_create_loan_only_backoffice(client, testdata, json_headers, users):
38
- """Test that patron have no permission of creating loans from ILLs."""
39
- user_login(client, "patron1", users)
40
- res = _create_loan_action("illbid-2", dict(), client, json_headers)
41
- assert res.status_code == 403
42
-
43
-
44
- def test_brwreq_create_loan_fails_on_wrong_status(
45
- db, client, testdata, json_headers, users
46
- ):
47
- """Test borrowing requests create loan action fails on wrong status."""
48
- user_login(client, "librarian", users)
49
-
50
- def _create_new_brwreq(data=None):
51
- brwreq = data or dict(
52
- document_pid="docid-3",
53
- provider_pid="ill-provid-2",
54
- patron_pid="1",
55
- status="PENDING",
56
- type="PHYSICAL_COPY",
57
- )
58
- url = url_for(LIST_ENDPOINT)
59
- res = client.post(url, headers=json_headers, data=json.dumps(brwreq))
60
- assert res.status_code in _HTTP_OK
61
- brw_req = res.get_json()["metadata"]
62
- return brw_req["pid"]
63
-
64
- def _update_brwreq_with_new_status(pid, status):
65
- rec = BorrowingRequest.get_record_by_pid(pid)
66
- rec["status"] = status
67
- if status == "CANCELLED":
68
- rec["cancel_reason"] = "OTHER"
69
- rec.commit()
70
- db.session.commit()
71
-
72
- def _assert_fail_when_status(pid, status):
73
- _update_brwreq_with_new_status(pid, status)
74
-
75
- now = arrow.utcnow()
76
- future = now + timedelta(days=15)
77
- data = dict(loan_start_date=now.isoformat(), loan_end_date=future.isoformat())
78
- _assert_create_loan_action_fails(pid, data, client, json_headers)
79
-
80
- pid = _create_new_brwreq()
81
-
82
- _assert_fail_when_status(pid, "PENDING")
83
- _assert_fail_when_status(pid, "ON_LOAN")
84
- _assert_fail_when_status(pid, "RETURNED")
85
- _assert_fail_when_status(pid, "CANCELLED")
86
-
87
-
88
- def test_brwreq_create_loan_fails_on_wrong_loan_end_date(
89
- db, client, testdata, json_headers, users
90
- ):
91
- """Test borrowing requests create loan action fails on wrong end date."""
92
- user_login(client, "librarian", users)
93
-
94
- # demo data "illbid-2" has the valid state `REQUESTED`
95
- pid = "illbid-2"
96
- # missing date param
97
- _assert_create_loan_action_fails(pid, dict(), client, json_headers)
98
-
99
- now = arrow.utcnow()
100
-
101
- # wrong format date
102
- future = now + timedelta(days=5)
103
- data = dict(
104
- loan_start_date=now.isoformat(),
105
- loan_end_date=future.date().isoformat(),
106
- )
107
- _assert_create_loan_action_fails(pid, data, client, json_headers)
108
- data = dict(
109
- loan_start_date=now.date().isoformat(),
110
- loan_end_date=future.isoformat(),
111
- )
112
- _assert_create_loan_action_fails(pid, data, client, json_headers)
113
-
114
- # past date
115
- past = now - timedelta(days=15)
116
- data = dict(
117
- loan_start_date=now.date().isoformat(),
118
- loan_end_date=past.date().isoformat(),
119
- )
120
- _assert_create_loan_action_fails(pid, data, client, json_headers)
121
-
122
-
123
- def test_brwreq_create_loan_fails_on_loan_pid_already_attached(
124
- db, client, testdata, json_headers, users
125
- ):
126
- """Test borrowing requests create loan action fails on loan_pid already."""
127
- user_login(client, "librarian", users)
128
-
129
- # demo data "illbid-2" has the valid state `REQUESTED`
130
- pid = "illbid-2"
131
-
132
- rec = BorrowingRequest.get_record_by_pid(pid)
133
- rec.setdefault("patron_loan", {})
134
- rec["patron_loan"]["pid"] = "loanid-3"
135
- rec.commit()
136
- db.session.commit()
137
-
138
- # already with a loan pid for some reasons
139
- now = arrow.utcnow()
140
- future = now + timedelta(days=5)
141
- data = dict(
142
- loan_start_date=now.date().isoformat(),
143
- loan_end_date=future.date().isoformat(),
144
- )
145
- _assert_create_loan_action_fails(pid, data, client, json_headers)
146
-
147
-
148
- def test_brwreq_create_loan_succeeds(db, client, testdata, json_headers, users):
149
- """Test borrowing requests create loan action succeeds."""
150
- user = user_login(client, "librarian", users)
151
-
152
- # demo data "illbid-2" has the valid state `REQUESTED`
153
- pid = "illbid-2"
154
-
155
- now = arrow.utcnow()
156
- start = (now + timedelta(days=3)).date().isoformat()
157
- future = (now + timedelta(days=5)).date().isoformat()
158
- data = dict(loan_start_date=start, loan_end_date=future)
159
- res = _create_loan_action(pid, data, client, json_headers)
160
- assert res.status_code in _HTTP_OK
161
- brw_req = res.get_json()["metadata"]
162
-
163
- assert brw_req["status"] == "ON_LOAN"
164
- assert "patron_loan" in brw_req
165
- patron_loan = brw_req["patron_loan"]
166
- assert "pid" in patron_loan
167
- assert "loan" in patron_loan
168
- loan = patron_loan["loan"]
169
- assert patron_loan["pid"] == loan["pid"]
170
- assert loan["end_date"] == future
171
- loan_pid = loan["pid"]
172
-
173
- # fetch the loan
174
- url = url_for("invenio_records_rest.loanid_item", pid_value=loan_pid)
175
- res = client.get(url, headers=json_headers)
176
- assert res.status_code in _HTTP_OK
177
- loan = res.get_json()["metadata"]
178
-
179
- # make sure the loan is created with the data from the ILL
180
- assert loan["item_pid"] == dict(type=BORROWING_REQUEST_PID_TYPE, value=pid)
181
- assert loan["start_date"] == start
182
- assert loan["end_date"] == future
183
- assert loan["document_pid"] == brw_req["document_pid"]
184
- assert loan["patron_pid"] == brw_req["patron_pid"]
185
- assert loan["transaction_user_pid"] == str(user.id)
186
-
187
- # update notes (a random field)
188
- brw_req["notes"] = "This is a note"
189
- url = url_for(ITEM_ENDPOINT, pid_value=pid)
190
- res = client.put(url, headers=json_headers, data=json.dumps(brw_req))
191
- assert res.status_code in _HTTP_OK
192
- updated_brw_req = res.get_json()["metadata"]
193
-
194
- # make sure `patron_loan` system field is preserved
195
- assert updated_brw_req["notes"] == "This is a note"
196
- assert "patron_loan" in updated_brw_req
197
- assert "pid" in patron_loan
198
- assert "loan" in patron_loan