invenio-app-ils 4.0.0rc1__py2.py3-none-any.whl → 4.2.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 (29) hide show
  1. invenio_app_ils/__init__.py +2 -2
  2. invenio_app_ils/circulation/config.py +1 -1
  3. invenio_app_ils/circulation/loaders/schemas/json/loan_request.py +2 -1
  4. invenio_app_ils/documents/jsonresolvers/document_stock.py +1 -1
  5. invenio_app_ils/documents/loaders/jsonschemas/document.py +1 -1
  6. invenio_app_ils/documents/mappings/os-v1/documents/document-v2.0.0.json +127 -39
  7. invenio_app_ils/documents/mappings/os-v2/documents/document-v2.0.0.json +127 -39
  8. invenio_app_ils/documents/mappings/v7/documents/document-v2.0.0.json +127 -39
  9. invenio_app_ils/eitems/loaders/jsonschemas/eitems.py +1 -1
  10. invenio_app_ils/items/api.py +13 -1
  11. invenio_app_ils/items/loaders/jsonschemas/items.py +1 -1
  12. invenio_app_ils/items/serializers/item.py +4 -4
  13. invenio_app_ils/permissions.py +43 -35
  14. invenio_app_ils/records/views.py +1 -1
  15. invenio_app_ils/records_relations/api.py +1 -0
  16. invenio_app_ils/relations/api.py +6 -1
  17. invenio_app_ils/series/loaders/jsonschemas/series.py +1 -1
  18. invenio_app_ils/series/mappings/os-v1/series/series-v2.0.0.json +46 -11
  19. invenio_app_ils/series/mappings/os-v2/series/series-v2.0.0.json +46 -11
  20. invenio_app_ils/series/mappings/v7/series/series-v2.0.0.json +46 -11
  21. {invenio_app_ils-4.0.0rc1.dist-info → invenio_app_ils-4.2.0.dist-info}/METADATA +69 -58
  22. {invenio_app_ils-4.0.0rc1.dist-info → invenio_app_ils-4.2.0.dist-info}/RECORD +28 -29
  23. {invenio_app_ils-4.0.0rc1.dist-info → invenio_app_ils-4.2.0.dist-info}/WHEEL +1 -1
  24. tests/api/ils/items/test_items_crud.py +46 -4
  25. tests/api/ils/items/test_items_update.py +0 -40
  26. {invenio_app_ils-4.0.0rc1.dist-info → invenio_app_ils-4.2.0.dist-info}/AUTHORS.rst +0 -0
  27. {invenio_app_ils-4.0.0rc1.dist-info → invenio_app_ils-4.2.0.dist-info}/LICENSE +0 -0
  28. {invenio_app_ils-4.0.0rc1.dist-info → invenio_app_ils-4.2.0.dist-info}/entry_points.txt +0 -0
  29. {invenio_app_ils-4.0.0rc1.dist-info → invenio_app_ils-4.2.0.dist-info}/top_level.txt +0 -0
@@ -160,15 +160,27 @@ class Item(IlsRecord):
160
160
  )
161
161
  }
162
162
 
163
+ @classmethod
164
+ def enforce_constraints(cls, data, **kwargs):
165
+ """Enforce constraints.
166
+
167
+ :param data (dict): dict that can be mutated to enforce constraints.
168
+ """
169
+ # barcode is a required field and it should be always uppercase
170
+ data["barcode"] = data["barcode"].upper()
171
+
163
172
  @classmethod
164
173
  def create(cls, data, id_=None, **kwargs):
165
174
  """Create Item record."""
166
175
  cls.build_resolver_fields(data)
167
- return super().create(data, id_=id_, **kwargs)
176
+ cls.enforce_constraints(data, **kwargs)
177
+ created = super().create(data, id_=id_, **kwargs)
178
+ return created
168
179
 
169
180
  def update(self, *args, **kwargs):
170
181
  """Update Item record."""
171
182
  super().update(*args, **kwargs)
183
+ self.enforce_constraints(self)
172
184
  self.build_resolver_fields(self)
173
185
 
174
186
  def delete(self, **kwargs):
@@ -15,8 +15,8 @@ from invenio_app_ils.records.loaders.schemas.changed_by import (
15
15
  ChangedBySchema,
16
16
  set_changed_by,
17
17
  )
18
- from invenio_app_ils.records.loaders.schemas.price import PriceSchema
19
18
  from invenio_app_ils.records.loaders.schemas.identifiers import IdentifierSchema
19
+ from invenio_app_ils.records.loaders.schemas.price import PriceSchema
20
20
 
21
21
 
22
22
  class ISBNSchema(Schema):
@@ -49,7 +49,7 @@ class ItemCSVSerializer(CSVSerializer):
49
49
  pid, record, links_factory=links_factory, **kwargs
50
50
  )
51
51
  filter_circulation(item)
52
- field_cover_metadata(item.get('metadata', {}).get("document", {}))
52
+ field_cover_metadata(item.get("metadata", {}).get("document", {}))
53
53
  return item
54
54
 
55
55
  def transform_search_hit(self, pid, record_hit, links_factory=None, **kwargs):
@@ -58,7 +58,7 @@ class ItemCSVSerializer(CSVSerializer):
58
58
  pid, record_hit, links_factory=links_factory, **kwargs
59
59
  )
60
60
  filter_circulation(hit)
61
- field_cover_metadata(hit.get('metadata', {}).get("document", {}))
61
+ field_cover_metadata(hit.get("metadata", {}).get("document", {}))
62
62
  return hit
63
63
 
64
64
 
@@ -71,7 +71,7 @@ class ItemJSONSerializer(JSONSerializer):
71
71
  pid, record, links_factory=links_factory, **kwargs
72
72
  )
73
73
  filter_circulation(item)
74
- field_cover_metadata(item.get('metadata', {}).get("document", {}))
74
+ field_cover_metadata(item.get("metadata", {}).get("document", {}))
75
75
  return item
76
76
 
77
77
  def transform_search_hit(self, pid, record_hit, links_factory=None, **kwargs):
@@ -80,5 +80,5 @@ class ItemJSONSerializer(JSONSerializer):
80
80
  pid, record_hit, links_factory=links_factory, **kwargs
81
81
  )
82
82
  filter_circulation(hit)
83
- field_cover_metadata(hit.get('metadata', {}).get("document", {}))
83
+ field_cover_metadata(hit.get("metadata", {}).get("document", {}))
84
84
  return hit
@@ -134,25 +134,27 @@ def patron_owner_permission(record):
134
134
  def loan_checkout_permission(*args, **kwargs):
135
135
  """Return permission to allow admins and librarians to checkout and patrons to self-checkout if enabled."""
136
136
  if not has_request_context():
137
- # If from CLI, don't allow self-checkout
137
+ # CLI or Celery task
138
138
  return backoffice_permission()
139
+
139
140
  if current_user.is_anonymous:
140
141
  abort(401)
141
142
 
142
143
  is_admin_or_librarian = backoffice_permission().allows(g.identity)
143
144
  if is_admin_or_librarian:
144
145
  return backoffice_permission()
146
+
147
+ # ensure that only the loan's patron can do operations on this loan
145
148
  if len(args):
146
149
  loan = args[0]
147
150
  else:
148
- loan = kwargs.get("record", {})
149
- is_patron_current_user = current_user.id == int(loan.get("patron_pid"))
150
- if (
151
- current_app.config.get("ILS_SELF_CHECKOUT_ENABLED", False)
152
- and is_patron_current_user
153
- ):
151
+ loan = kwargs["record"]
152
+ is_patron_current_user = current_user.id == int(loan["patron_pid"])
153
+
154
+ if current_app.config["ILS_SELF_CHECKOUT_ENABLED"] and is_patron_current_user:
154
155
  return authenticated_user_permission()
155
- raise LoanCheckoutByPatronForbidden(int(loan.get("patron_pid")), current_user.id)
156
+
157
+ raise LoanCheckoutByPatronForbidden(int(loan["patron_pid"]), current_user.id)
156
158
 
157
159
 
158
160
  class PatronOwnerPermission(Permission):
@@ -163,36 +165,42 @@ class PatronOwnerPermission(Permission):
163
165
  super().__init__(UserNeed(int(record["patron_pid"])), backoffice_access_action)
164
166
 
165
167
 
168
+ _is_authenticated_user = [
169
+ "circulation-loan-request",
170
+ "patron-loans",
171
+ "bulk-loan-extension",
172
+ ]
173
+ _is_backoffice_permission = [
174
+ "circulation-loan-force-checkout",
175
+ "circulation-overdue-loan-notification",
176
+ "circulation-loan-update-dates",
177
+ "relations-create",
178
+ "relations-delete",
179
+ "stats-most-loaned",
180
+ "document-request-actions",
181
+ "bucket-create",
182
+ "ill-brwreq-patron-loan-create",
183
+ "ill-brwreq-patron-loan-extension-accept",
184
+ "ill-brwreq-patron-loan-extension-decline",
185
+ "send-notification-to-patron",
186
+ ]
187
+ _is_patron_owner_permission = [
188
+ "document-request-decline",
189
+ "ill-brwreq-patron-loan-extension-request",
190
+ ]
191
+
192
+
166
193
  def views_permissions_factory(action):
167
194
  """Return ILS views permissions factory."""
168
- is_authenticated_user = [
169
- "circulation-loan-request",
170
- "patron-loans",
171
- "bulk-loan-extension",
172
- ]
173
- is_backoffice_permission = [
174
- "circulation-loan-checkout",
175
- "circulation-loan-force-checkout",
176
- "circulation-overdue-loan-notification",
177
- "circulation-loan-update-dates",
178
- "relations-create",
179
- "relations-delete",
180
- "stats-most-loaned",
181
- "document-request-actions",
182
- "bucket-create",
183
- "ill-brwreq-patron-loan-create",
184
- "ill-brwreq-patron-loan-extension-accept",
185
- "ill-brwreq-patron-loan-extension-decline",
186
- "send-notification-to-patron",
187
- ]
188
- is_patron_owner_permission = [
189
- "document-request-decline",
190
- "ill-brwreq-patron-loan-extension-request",
191
- ]
192
- if action in is_authenticated_user:
195
+ if action in _is_authenticated_user:
193
196
  return authenticated_user_permission()
194
- elif action in is_backoffice_permission:
197
+ elif action in _is_backoffice_permission:
195
198
  return backoffice_permission()
196
- elif action in is_patron_owner_permission:
199
+ elif action in _is_patron_owner_permission:
197
200
  return PatronOwnerPermission
201
+ elif action == "circulation-loan-checkout":
202
+ if current_app.config["ILS_SELF_CHECKOUT_ENABLED"]:
203
+ return authenticated_user_permission()
204
+ else:
205
+ return backoffice_permission()
198
206
  return deny_all()
@@ -20,7 +20,7 @@ from invenio_app_ils.errors import StatsError
20
20
  from invenio_app_ils.permissions import backoffice_permission
21
21
  from invenio_app_ils.records.permissions import RecordPermission
22
22
  from invenio_app_ils.series.api import SERIES_PID_TYPE
23
- from invenio_app_ils.signals import record_viewed, file_downloaded
23
+ from invenio_app_ils.signals import file_downloaded, record_viewed
24
24
 
25
25
 
26
26
  def create_document_stats_blueprint(app):
@@ -425,6 +425,7 @@ class IlsRecordWithRelations(IlsRecord):
425
425
  def relations(self):
426
426
  """Get record relations."""
427
427
  from .retriever import get_relations
428
+
428
429
  return get_relations(self)
429
430
 
430
431
  def clear(self):
@@ -17,7 +17,12 @@ from sqlalchemy import and_, or_
17
17
  from invenio_app_ils.errors import RecordRelationsError
18
18
 
19
19
  ILS_RELATION_TYPE = namedtuple(
20
- "IlsRelationType", RelationType._fields + ("relation_class", "sort_by",)
20
+ "IlsRelationType",
21
+ RelationType._fields
22
+ + (
23
+ "relation_class",
24
+ "sort_by",
25
+ ),
21
26
  )
22
27
 
23
28
  LANGUAGE_RELATION = ILS_RELATION_TYPE(
@@ -21,10 +21,10 @@ from invenio_app_ils.records.loaders.schemas.changed_by import (
21
21
  ChangedBySchema,
22
22
  set_changed_by,
23
23
  )
24
+ from invenio_app_ils.records.loaders.schemas.identifiers import IdentifierSchema
24
25
  from invenio_app_ils.records.loaders.schemas.preserve_cover_metadata import (
25
26
  preserve_cover_metadata,
26
27
  )
27
- from invenio_app_ils.records.loaders.schemas.identifiers import IdentifierSchema
28
28
  from invenio_app_ils.series.api import Series
29
29
 
30
30
 
@@ -61,7 +61,9 @@
61
61
  "type": "date"
62
62
  },
63
63
  "abstract": {
64
- "type": "text"
64
+ "type": "text",
65
+ "analyzer": "custom_analyzer",
66
+ "search_analyzer": "custom_analyzer"
65
67
  },
66
68
  "access_urls": {
67
69
  "type": "object",
@@ -93,7 +95,9 @@
93
95
  "type": "keyword"
94
96
  },
95
97
  "value": {
96
- "type": "text"
98
+ "type": "text",
99
+ "analyzer": "custom_analyzer",
100
+ "search_analyzer": "custom_analyzer"
97
101
  }
98
102
  }
99
103
  },
@@ -103,7 +107,9 @@
103
107
  "type": "keyword"
104
108
  }
105
109
  },
106
- "type": "text"
110
+ "type": "text",
111
+ "analyzer": "custom_analyzer",
112
+ "search_analyzer": "custom_analyzer"
107
113
  },
108
114
  "cover_metadata": {
109
115
  "properties": {},
@@ -121,13 +127,22 @@
121
127
  "type": "object"
122
128
  },
123
129
  "document_type": {
124
- "type": "keyword"
130
+ "type": "keyword",
131
+ "fields": {
132
+ "text": {
133
+ "type": "text",
134
+ "analyzer": "custom_analyzer",
135
+ "search_analyzer": "custom_analyzer"
136
+ }
137
+ }
125
138
  },
126
139
  "edition": {
127
140
  "type": "keyword",
128
141
  "fields": {
129
142
  "text": {
130
- "type": "text"
143
+ "type": "text",
144
+ "analyzer": "custom_analyzer",
145
+ "search_analyzer": "custom_analyzer"
131
146
  }
132
147
  }
133
148
  },
@@ -183,7 +198,9 @@
183
198
  "type": "keyword",
184
199
  "fields": {
185
200
  "text": {
186
- "type": "text"
201
+ "type": "text",
202
+ "analyzer": "custom_analyzer",
203
+ "search_analyzer": "custom_analyzer"
187
204
  }
188
205
  }
189
206
  }
@@ -218,7 +235,7 @@
218
235
  "keywords": {
219
236
  "properties": {
220
237
  "source": { "type": "text" },
221
- "value": { "type": "text" }
238
+ "value": { "type": "text", "analyzer": "custom_analyzer", "search_analyzer": "custom_analyzer" }
222
239
  },
223
240
  "type": "object"
224
241
  },
@@ -235,7 +252,14 @@
235
252
  "type": "keyword"
236
253
  },
237
254
  "publication_year": {
238
- "type": "keyword"
255
+ "type": "keyword",
256
+ "fields": {
257
+ "text": {
258
+ "type": "text",
259
+ "analyzer": "custom_analyzer",
260
+ "search_analyzer": "custom_analyzer"
261
+ }
262
+ }
239
263
  },
240
264
  "publisher": {
241
265
  "fields": {
@@ -243,7 +267,9 @@
243
267
  "type": "keyword"
244
268
  }
245
269
  },
246
- "type": "text"
270
+ "type": "text",
271
+ "analyzer": "custom_analyzer",
272
+ "search_analyzer": "custom_analyzer"
247
273
  },
248
274
  "relation_types": {
249
275
  "type": "keyword"
@@ -337,7 +363,14 @@
337
363
  "type": "text"
338
364
  },
339
365
  "value": {
340
- "type": "keyword"
366
+ "type": "keyword",
367
+ "fields": {
368
+ "text": {
369
+ "type": "text",
370
+ "analyzer": "custom_analyzer",
371
+ "search_analyzer": "custom_analyzer"
372
+ }
373
+ }
341
374
  },
342
375
  "meta": {
343
376
  "type": "text"
@@ -348,7 +381,9 @@
348
381
  "physical_volumes": {
349
382
  "properties": {
350
383
  "description": {
351
- "type": "text"
384
+ "type": "text",
385
+ "analyzer": "custom_analyzer",
386
+ "search_analyzer": "custom_analyzer"
352
387
  },
353
388
  "location": {
354
389
  "type": "text"
@@ -61,7 +61,9 @@
61
61
  "type": "date"
62
62
  },
63
63
  "abstract": {
64
- "type": "text"
64
+ "type": "text",
65
+ "analyzer": "custom_analyzer",
66
+ "search_analyzer": "custom_analyzer"
65
67
  },
66
68
  "access_urls": {
67
69
  "type": "object",
@@ -93,7 +95,9 @@
93
95
  "type": "keyword"
94
96
  },
95
97
  "value": {
96
- "type": "text"
98
+ "type": "text",
99
+ "analyzer": "custom_analyzer",
100
+ "search_analyzer": "custom_analyzer"
97
101
  }
98
102
  }
99
103
  },
@@ -103,7 +107,9 @@
103
107
  "type": "keyword"
104
108
  }
105
109
  },
106
- "type": "text"
110
+ "type": "text",
111
+ "analyzer": "custom_analyzer",
112
+ "search_analyzer": "custom_analyzer"
107
113
  },
108
114
  "cover_metadata": {
109
115
  "properties": {},
@@ -121,13 +127,22 @@
121
127
  "type": "object"
122
128
  },
123
129
  "document_type": {
124
- "type": "keyword"
130
+ "type": "keyword",
131
+ "fields": {
132
+ "text": {
133
+ "type": "text",
134
+ "analyzer": "custom_analyzer",
135
+ "search_analyzer": "custom_analyzer"
136
+ }
137
+ }
125
138
  },
126
139
  "edition": {
127
140
  "type": "keyword",
128
141
  "fields": {
129
142
  "text": {
130
- "type": "text"
143
+ "type": "text",
144
+ "analyzer": "custom_analyzer",
145
+ "search_analyzer": "custom_analyzer"
131
146
  }
132
147
  }
133
148
  },
@@ -183,7 +198,9 @@
183
198
  "type": "keyword",
184
199
  "fields": {
185
200
  "text": {
186
- "type": "text"
201
+ "type": "text",
202
+ "analyzer": "custom_analyzer",
203
+ "search_analyzer": "custom_analyzer"
187
204
  }
188
205
  }
189
206
  }
@@ -218,7 +235,7 @@
218
235
  "keywords": {
219
236
  "properties": {
220
237
  "source": { "type": "text" },
221
- "value": { "type": "text" }
238
+ "value": { "type": "text", "analyzer": "custom_analyzer", "search_analyzer": "custom_analyzer" }
222
239
  },
223
240
  "type": "object"
224
241
  },
@@ -235,7 +252,14 @@
235
252
  "type": "keyword"
236
253
  },
237
254
  "publication_year": {
238
- "type": "keyword"
255
+ "type": "keyword",
256
+ "fields": {
257
+ "text": {
258
+ "type": "text",
259
+ "analyzer": "custom_analyzer",
260
+ "search_analyzer": "custom_analyzer"
261
+ }
262
+ }
239
263
  },
240
264
  "publisher": {
241
265
  "fields": {
@@ -243,7 +267,9 @@
243
267
  "type": "keyword"
244
268
  }
245
269
  },
246
- "type": "text"
270
+ "type": "text",
271
+ "analyzer": "custom_analyzer",
272
+ "search_analyzer": "custom_analyzer"
247
273
  },
248
274
  "relation_types": {
249
275
  "type": "keyword"
@@ -337,7 +363,14 @@
337
363
  "type": "text"
338
364
  },
339
365
  "value": {
340
- "type": "keyword"
366
+ "type": "keyword",
367
+ "fields": {
368
+ "text": {
369
+ "type": "text",
370
+ "analyzer": "custom_analyzer",
371
+ "search_analyzer": "custom_analyzer"
372
+ }
373
+ }
341
374
  },
342
375
  "meta": {
343
376
  "type": "text"
@@ -348,7 +381,9 @@
348
381
  "physical_volumes": {
349
382
  "properties": {
350
383
  "description": {
351
- "type": "text"
384
+ "type": "text",
385
+ "analyzer": "custom_analyzer",
386
+ "search_analyzer": "custom_analyzer"
352
387
  },
353
388
  "location": {
354
389
  "type": "text"
@@ -61,7 +61,9 @@
61
61
  "type": "date"
62
62
  },
63
63
  "abstract": {
64
- "type": "text"
64
+ "type": "text",
65
+ "analyzer": "custom_analyzer",
66
+ "search_analyzer": "custom_analyzer"
65
67
  },
66
68
  "access_urls": {
67
69
  "type": "object",
@@ -93,7 +95,9 @@
93
95
  "type": "keyword"
94
96
  },
95
97
  "value": {
96
- "type": "text"
98
+ "type": "text",
99
+ "analyzer": "custom_analyzer",
100
+ "search_analyzer": "custom_analyzer"
97
101
  }
98
102
  }
99
103
  },
@@ -103,7 +107,9 @@
103
107
  "type": "keyword"
104
108
  }
105
109
  },
106
- "type": "text"
110
+ "type": "text",
111
+ "analyzer": "custom_analyzer",
112
+ "search_analyzer": "custom_analyzer"
107
113
  },
108
114
  "cover_metadata": {
109
115
  "properties": {},
@@ -121,13 +127,22 @@
121
127
  "type": "object"
122
128
  },
123
129
  "document_type": {
124
- "type": "keyword"
130
+ "type": "keyword",
131
+ "fields": {
132
+ "text": {
133
+ "type": "text",
134
+ "analyzer": "custom_analyzer",
135
+ "search_analyzer": "custom_analyzer"
136
+ }
137
+ }
125
138
  },
126
139
  "edition": {
127
140
  "type": "keyword",
128
141
  "fields": {
129
142
  "text": {
130
- "type": "text"
143
+ "type": "text",
144
+ "analyzer": "custom_analyzer",
145
+ "search_analyzer": "custom_analyzer"
131
146
  }
132
147
  }
133
148
  },
@@ -183,7 +198,9 @@
183
198
  "type": "keyword",
184
199
  "fields": {
185
200
  "text": {
186
- "type": "text"
201
+ "type": "text",
202
+ "analyzer": "custom_analyzer",
203
+ "search_analyzer": "custom_analyzer"
187
204
  }
188
205
  }
189
206
  }
@@ -218,7 +235,7 @@
218
235
  "keywords": {
219
236
  "properties": {
220
237
  "source": { "type": "text" },
221
- "value": { "type": "text" }
238
+ "value": { "type": "text", "analyzer": "custom_analyzer", "search_analyzer": "custom_analyzer" }
222
239
  },
223
240
  "type": "object"
224
241
  },
@@ -235,7 +252,14 @@
235
252
  "type": "keyword"
236
253
  },
237
254
  "publication_year": {
238
- "type": "keyword"
255
+ "type": "keyword",
256
+ "fields": {
257
+ "text": {
258
+ "type": "text",
259
+ "analyzer": "custom_analyzer",
260
+ "search_analyzer": "custom_analyzer"
261
+ }
262
+ }
239
263
  },
240
264
  "publisher": {
241
265
  "fields": {
@@ -243,7 +267,9 @@
243
267
  "type": "keyword"
244
268
  }
245
269
  },
246
- "type": "text"
270
+ "type": "text",
271
+ "analyzer": "custom_analyzer",
272
+ "search_analyzer": "custom_analyzer"
247
273
  },
248
274
  "relation_types": {
249
275
  "type": "keyword"
@@ -337,7 +363,14 @@
337
363
  "type": "text"
338
364
  },
339
365
  "value": {
340
- "type": "keyword"
366
+ "type": "keyword",
367
+ "fields": {
368
+ "text": {
369
+ "type": "text",
370
+ "analyzer": "custom_analyzer",
371
+ "search_analyzer": "custom_analyzer"
372
+ }
373
+ }
341
374
  },
342
375
  "meta": {
343
376
  "type": "text"
@@ -348,7 +381,9 @@
348
381
  "physical_volumes": {
349
382
  "properties": {
350
383
  "description": {
351
- "type": "text"
384
+ "type": "text",
385
+ "analyzer": "custom_analyzer",
386
+ "search_analyzer": "custom_analyzer"
352
387
  },
353
388
  "location": {
354
389
  "type": "text"