invenio-app-ils 1.0.0a54__py2.py3-none-any.whl → 6.1.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.
- invenio_app_ils/__init__.py +2 -2
- invenio_app_ils/acquisition/api.py +3 -1
- invenio_app_ils/acquisition/config.py +10 -21
- invenio_app_ils/acquisition/jsonresolvers/order_order_lines.py +1 -0
- invenio_app_ils/acquisition/mappings/os-v1/acq_orders/order-v1.0.0.json +364 -0
- invenio_app_ils/acquisition/mappings/os-v2/__init__.py +0 -0
- invenio_app_ils/acquisition/mappings/os-v2/acq_orders/order-v1.0.0.json +364 -0
- invenio_app_ils/acquisition/mappings/v7/acq_orders/order-v1.0.0.json +14 -0
- invenio_app_ils/acquisition/search.py +5 -15
- invenio_app_ils/assets/semantic-ui/less/theme.config +103 -0
- invenio_app_ils/assets/semantic-ui/templates/.gitkeep +0 -0
- invenio_app_ils/circulation/api.py +153 -67
- invenio_app_ils/circulation/config.py +29 -25
- invenio_app_ils/circulation/indexer.py +14 -19
- invenio_app_ils/circulation/loaders/__init__.py +2 -0
- invenio_app_ils/circulation/loaders/schemas/json/loan_checkout.py +2 -3
- invenio_app_ils/circulation/loaders/schemas/json/loan_request.py +82 -16
- invenio_app_ils/circulation/loaders/schemas/json/loan_self_checkout.py +19 -0
- invenio_app_ils/circulation/notifications/api.py +23 -19
- invenio_app_ils/circulation/notifications/messages.py +6 -6
- invenio_app_ils/circulation/notifications/tasks.py +1 -2
- invenio_app_ils/circulation/receivers.py +2 -5
- invenio_app_ils/circulation/search.py +23 -22
- invenio_app_ils/circulation/serializers/__init__.py +2 -2
- invenio_app_ils/circulation/serializers/csv.py +1 -3
- invenio_app_ils/circulation/serializers/custom_fields.py +5 -9
- invenio_app_ils/circulation/serializers/json.py +2 -6
- invenio_app_ils/circulation/serializers/response.py +12 -12
- invenio_app_ils/circulation/stats/views.py +5 -15
- invenio_app_ils/circulation/tasks.py +2 -6
- invenio_app_ils/circulation/templates/invenio_app_ils_circulation/notifications/self_checkout.html +19 -0
- invenio_app_ils/circulation/templates/invenio_app_ils_circulation/notifications/update_dates.html +19 -0
- invenio_app_ils/circulation/utils.py +23 -17
- invenio_app_ils/circulation/views.py +103 -39
- invenio_app_ils/cli.py +220 -260
- invenio_app_ils/closures/api.py +72 -7
- invenio_app_ils/closures/serializers/__init__.py +16 -0
- invenio_app_ils/closures/serializers/response.py +35 -0
- invenio_app_ils/closures/serializers/schema.py +28 -0
- invenio_app_ils/closures/tasks.py +4 -11
- invenio_app_ils/closures/views.py +66 -0
- invenio_app_ils/config.py +207 -150
- invenio_app_ils/document_requests/api.py +6 -21
- invenio_app_ils/document_requests/loaders/__init__.py +4 -12
- invenio_app_ils/document_requests/mappings/{v6 → os-v1}/__init__.py +2 -2
- invenio_app_ils/document_requests/mappings/os-v1/document_requests/document_request-v1.0.0.json +196 -0
- invenio_app_ils/document_requests/mappings/os-v2/__init__.py +8 -0
- invenio_app_ils/document_requests/mappings/os-v2/document_requests/document_request-v1.0.0.json +196 -0
- invenio_app_ils/document_requests/notifications/api.py +2 -7
- invenio_app_ils/document_requests/notifications/messages.py +3 -7
- invenio_app_ils/document_requests/search.py +2 -6
- invenio_app_ils/document_requests/views.py +4 -10
- invenio_app_ils/documents/api.py +19 -25
- invenio_app_ils/documents/indexer.py +13 -20
- invenio_app_ils/documents/jsonresolvers/document_circulation.py +11 -33
- invenio_app_ils/documents/jsonresolvers/document_eitem.py +1 -0
- invenio_app_ils/documents/jsonresolvers/document_item.py +8 -9
- invenio_app_ils/documents/jsonresolvers/document_stock.py +7 -7
- invenio_app_ils/documents/loaders/jsonschemas/document.py +3 -14
- invenio_app_ils/documents/mappings/{v6 → os-v1}/__init__.py +1 -1
- invenio_app_ils/documents/mappings/os-v1/documents/document-v1.0.0.json +932 -0
- invenio_app_ils/documents/mappings/os-v1/documents/document-v2.0.0.json +1066 -0
- invenio_app_ils/documents/mappings/os-v2/__init__.py +8 -0
- invenio_app_ils/documents/mappings/os-v2/documents/document-v1.0.0.json +932 -0
- invenio_app_ils/documents/mappings/os-v2/documents/document-v2.0.0.json +1066 -0
- invenio_app_ils/documents/mappings/v7/documents/document-v1.0.0.json +102 -11
- invenio_app_ils/documents/mappings/v7/documents/document-v2.0.0.json +1066 -0
- invenio_app_ils/documents/schemas/documents/document-v2.0.0.json +732 -0
- invenio_app_ils/eitems/api.py +41 -7
- invenio_app_ils/eitems/loaders/jsonschemas/eitems.py +6 -6
- invenio_app_ils/eitems/mappings/{v6 → os-v1}/__init__.py +1 -1
- invenio_app_ils/eitems/mappings/os-v1/eitems/eitem-v1.0.0.json +139 -0
- invenio_app_ils/eitems/mappings/os-v1/eitems/eitem-v2.0.0.json +142 -0
- invenio_app_ils/eitems/mappings/os-v1/eitems/eitem-v3.0.0.json +179 -0
- invenio_app_ils/{series/mappings/v6 → eitems/mappings/os-v2}/__init__.py +1 -1
- invenio_app_ils/eitems/mappings/os-v2/eitems/eitem-v1.0.0.json +139 -0
- invenio_app_ils/eitems/mappings/os-v2/eitems/eitem-v2.0.0.json +142 -0
- invenio_app_ils/eitems/mappings/os-v2/eitems/eitem-v3.0.0.json +179 -0
- invenio_app_ils/eitems/mappings/v7/eitems/eitem-v1.0.0.json +12 -2
- invenio_app_ils/eitems/mappings/v7/eitems/eitem-v2.0.0.json +142 -0
- invenio_app_ils/eitems/mappings/v7/eitems/eitem-v3.0.0.json +179 -0
- invenio_app_ils/eitems/schemas/eitems/eitem-v2.0.0.json +120 -0
- invenio_app_ils/eitems/schemas/eitems/eitem-v3.0.0.json +120 -0
- invenio_app_ils/eitems/search.py +3 -9
- invenio_app_ils/errors.py +119 -6
- invenio_app_ils/ext.py +15 -18
- invenio_app_ils/facets.py +13 -15
- invenio_app_ils/files/receivers.py +1 -1
- invenio_app_ils/files/views.py +1 -2
- invenio_app_ils/ill/api.py +1 -2
- invenio_app_ils/ill/config.py +10 -16
- invenio_app_ils/ill/jsonresolvers/borrowing_request_document.py +2 -3
- invenio_app_ils/ill/jsonresolvers/borrowing_request_patron.py +1 -3
- invenio_app_ils/ill/jsonresolvers/borrowing_request_provider.py +1 -3
- invenio_app_ils/ill/loaders/__init__.py +3 -9
- invenio_app_ils/ill/loaders/jsonschemas/patron_loan_actions.py +1 -8
- invenio_app_ils/ill/loaders/jsonschemas/patron_loan_extension_actions.py +3 -8
- invenio_app_ils/ill/mappings/{v6 → os-v1}/__init__.py +1 -1
- invenio_app_ils/ill/mappings/os-v1/ill_borrowing_requests/borrowing_request-v1.0.0.json +254 -0
- invenio_app_ils/{acquisition/mappings/v6 → ill/mappings/os-v2}/__init__.py +1 -1
- invenio_app_ils/ill/mappings/os-v2/ill_borrowing_requests/borrowing_request-v1.0.0.json +254 -0
- invenio_app_ils/ill/mappings/v7/ill_borrowing_requests/borrowing_request-v1.0.0.json +14 -0
- invenio_app_ils/ill/notifications/api.py +1 -4
- invenio_app_ils/ill/search.py +3 -9
- invenio_app_ils/ill/serializers/__init__.py +1 -3
- invenio_app_ils/ill/views.py +2 -4
- invenio_app_ils/internal_locations/api.py +1 -4
- invenio_app_ils/internal_locations/mappings/{v6 → os-v1}/__init__.py +1 -1
- invenio_app_ils/internal_locations/mappings/os-v1/internal_locations/internal_location-v1.0.0.json +108 -0
- invenio_app_ils/internal_locations/mappings/os-v2/__init__.py +8 -0
- invenio_app_ils/internal_locations/mappings/os-v2/internal_locations/internal_location-v1.0.0.json +108 -0
- invenio_app_ils/internal_locations/search.py +1 -3
- invenio_app_ils/items/api.py +18 -15
- invenio_app_ils/items/indexer.py +1 -3
- invenio_app_ils/items/jsonresolvers/item_document.py +1 -1
- invenio_app_ils/items/jsonresolvers/item_internal_location.py +2 -6
- invenio_app_ils/items/loaders/jsonschemas/items.py +2 -0
- {tests/api/circulation → invenio_app_ils/items/mappings/os-v1}/__init__.py +1 -1
- invenio_app_ils/items/mappings/os-v1/items/item-v1.0.0.json +285 -0
- invenio_app_ils/items/mappings/os-v1/items/item-v2.0.0.json +326 -0
- {tests/api/ill → invenio_app_ils/items/mappings/os-v2}/__init__.py +1 -1
- invenio_app_ils/items/mappings/os-v2/items/item-v1.0.0.json +285 -0
- invenio_app_ils/items/mappings/os-v2/items/item-v2.0.0.json +326 -0
- invenio_app_ils/items/mappings/v7/items/item-v1.0.0.json +11 -0
- invenio_app_ils/items/mappings/v7/items/item-v2.0.0.json +326 -0
- invenio_app_ils/items/schemas/items/item-v1.0.0.json +22 -0
- invenio_app_ils/items/schemas/items/item-v2.0.0.json +172 -0
- invenio_app_ils/items/search.py +18 -11
- invenio_app_ils/items/serializers/item.py +7 -6
- invenio_app_ils/literature/api.py +1 -3
- invenio_app_ils/literature/search.py +3 -5
- invenio_app_ils/literature/serializers/csv.py +1 -3
- invenio_app_ils/literature/serializers/json.py +1 -3
- invenio_app_ils/locations/api.py +2 -4
- invenio_app_ils/locations/indexer.py +3 -9
- invenio_app_ils/locations/loaders/__init__.py +1 -3
- invenio_app_ils/locations/loaders/jsonschemas/location.py +4 -11
- invenio_app_ils/locations/mappings/{v6 → os-v1}/__init__.py +1 -1
- invenio_app_ils/locations/mappings/os-v1/locations/location-v1.0.0.json +90 -0
- invenio_app_ils/locations/mappings/os-v2/__init__.py +8 -0
- invenio_app_ils/locations/mappings/os-v2/locations/location-v1.0.0.json +90 -0
- invenio_app_ils/notifications/messages.py +4 -3
- invenio_app_ils/notifications/tasks.py +1 -3
- invenio_app_ils/notifications/views.py +2 -2
- invenio_app_ils/patrons/anonymization.py +53 -32
- invenio_app_ils/patrons/api.py +3 -5
- invenio_app_ils/patrons/cli.py +1 -2
- invenio_app_ils/patrons/indexer.py +4 -13
- invenio_app_ils/patrons/mappings/os-v1/__init__.py +8 -0
- invenio_app_ils/patrons/mappings/os-v1/patrons/patron-v1.0.0.json +42 -0
- invenio_app_ils/patrons/mappings/os-v2/__init__.py +8 -0
- invenio_app_ils/patrons/mappings/os-v2/patrons/patron-v1.0.0.json +42 -0
- invenio_app_ils/patrons/views.py +4 -14
- invenio_app_ils/permissions.py +93 -35
- invenio_app_ils/providers/api.py +2 -6
- invenio_app_ils/providers/config.py +11 -19
- invenio_app_ils/providers/indexer.py +2 -6
- invenio_app_ils/providers/mappings/{v6 → os-v1}/__init__.py +1 -1
- invenio_app_ils/providers/mappings/os-v1/providers/provider-v1.0.0.json +57 -0
- invenio_app_ils/providers/mappings/os-v2/__init__.py +8 -0
- invenio_app_ils/providers/mappings/os-v2/providers/provider-v1.0.0.json +57 -0
- invenio_app_ils/providers/mappings/v7/__init__.py +1 -1
- invenio_app_ils/providers/proxies.py +1 -3
- invenio_app_ils/records/api.py +3 -9
- invenio_app_ils/records/loaders/schemas/changed_by.py +1 -3
- invenio_app_ils/records/loaders/schemas/identifiers.py +23 -0
- invenio_app_ils/records/metadata_extensions.py +1 -4
- invenio_app_ils/records/permissions.py +8 -2
- invenio_app_ils/records/serializers/__init__.py +1 -4
- invenio_app_ils/records/views.py +4 -7
- invenio_app_ils/records_relations/api.py +11 -34
- invenio_app_ils/records_relations/indexer.py +1 -3
- invenio_app_ils/records_relations/retriever.py +14 -9
- invenio_app_ils/records_relations/views.py +16 -50
- invenio_app_ils/relations/api.py +17 -16
- invenio_app_ils/search_permissions.py +24 -24
- invenio_app_ils/series/api.py +10 -12
- invenio_app_ils/series/loaders/jsonschemas/series.py +3 -2
- invenio_app_ils/{items/mappings/v6 → series/mappings/os-v1}/__init__.py +1 -1
- invenio_app_ils/series/mappings/os-v1/series/series-v1.0.0.json +324 -0
- invenio_app_ils/series/mappings/os-v1/series/series-v2.0.0.json +396 -0
- {tests/api/acquisition → invenio_app_ils/series/mappings/os-v2}/__init__.py +1 -1
- invenio_app_ils/series/mappings/os-v2/series/series-v1.0.0.json +324 -0
- invenio_app_ils/series/mappings/os-v2/series/series-v2.0.0.json +396 -0
- invenio_app_ils/series/mappings/v7/series/series-v1.0.0.json +35 -3
- invenio_app_ils/series/mappings/v7/series/series-v2.0.0.json +396 -0
- invenio_app_ils/series/schemas/series/series-v2.0.0.json +354 -0
- invenio_app_ils/stats/aggregations/aggr_file_download/os-v1/aggr-file-download-v1.json +60 -0
- invenio_app_ils/stats/aggregations/aggr_file_download/os-v2/__init__.py +9 -0
- invenio_app_ils/stats/aggregations/aggr_file_download/os-v2/aggr-file-download-v1.json +60 -0
- invenio_app_ils/stats/event_builders.py +73 -0
- invenio_app_ils/stats/file_download/os-v1/file-download-v1.json +72 -0
- invenio_app_ils/stats/file_download/os-v2/__init__.py +9 -0
- invenio_app_ils/stats/file_download/os-v2/file-download-v1.json +72 -0
- invenio_app_ils/stats/processors.py +30 -0
- invenio_app_ils/stats/templates/aggregations/__init__.py +8 -0
- invenio_app_ils/stats/templates/aggregations/ils_record_changes/__init__.py +8 -0
- invenio_app_ils/stats/templates/aggregations/ils_record_changes/os-v2/__init__.py +8 -0
- invenio_app_ils/stats/templates/aggregations/ils_record_changes/os-v2/aggr-ils-record-changes-v1.json +41 -0
- {tests → invenio_app_ils/stats/templates/events}/__init__.py +2 -2
- invenio_app_ils/stats/templates/events/ils_record_changes/__init__.py +8 -0
- invenio_app_ils/stats/templates/events/ils_record_changes/os-v2/__init__.py +8 -0
- invenio_app_ils/stats/templates/events/ils_record_changes/os-v2/ils-record-changes-v1.json +41 -0
- invenio_app_ils/templates/logged_out.html +12 -0
- invenio_app_ils/views.py +18 -4
- invenio_app_ils/vocabularies/api.py +1 -1
- invenio_app_ils/vocabularies/cli.py +6 -18
- invenio_app_ils/vocabularies/data/acq_order_line_payment_modes.json +5 -0
- invenio_app_ils/vocabularies/data/identifier_schemes.json +5 -0
- invenio_app_ils/vocabularies/indexer.py +1 -4
- invenio_app_ils/vocabularies/jsonresolvers/licenses.py +2 -11
- invenio_app_ils/vocabularies/mappings/os-v1/__init__.py +8 -0
- invenio_app_ils/vocabularies/mappings/os-v1/vocabularies/vocabulary-v1.0.0.json +23 -0
- invenio_app_ils/vocabularies/mappings/os-v2/__init__.py +8 -0
- invenio_app_ils/vocabularies/mappings/os-v2/vocabularies/vocabulary-v1.0.0.json +23 -0
- invenio_app_ils/vocabularies/sources/base.py +1 -3
- invenio_app_ils/webpack.py +27 -0
- invenio_app_ils-6.1.0.dist-info/METADATA +627 -0
- {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info}/RECORD +227 -249
- {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info}/WHEEL +1 -1
- {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info}/entry_points.txt +9 -5
- {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info}/top_level.txt +0 -1
- invenio_app_ils/acquisition/mappings/v6/acq_orders/order-v1.0.0.json +0 -352
- invenio_app_ils/document_requests/mappings/v6/document_requests/document_request-v1.0.0.json +0 -199
- invenio_app_ils/documents/mappings/v6/documents/document-v1.0.0.json +0 -843
- invenio_app_ils/eitems/mappings/v6/eitems/eitem-v1.0.0.json +0 -131
- invenio_app_ils/ill/mappings/v6/ill_borrowing_requests/borrowing_request-v1.0.0.json +0 -242
- invenio_app_ils/internal_locations/mappings/v6/internal_locations/internal_location-v1.0.0.json +0 -110
- invenio_app_ils/items/mappings/v6/items/item-v1.0.0.json +0 -276
- invenio_app_ils/locations/mappings/v6/locations/location-v1.0.0.json +0 -92
- invenio_app_ils/notifications/admin.py +0 -57
- invenio_app_ils/patrons/mappings/v6/__init__.py +0 -8
- invenio_app_ils/patrons/mappings/v6/patrons/patron-v1.0.0.json +0 -44
- invenio_app_ils/providers/mappings/v6/providers/provider-v1.0.0.json +0 -59
- invenio_app_ils/series/mappings/v6/series/series-v1.0.0.json +0 -298
- invenio_app_ils/stats/aggregations/aggr_file_download/v6/aggr-file-download-v1.json +0 -59
- invenio_app_ils/stats/file_download/v6/file-download-v1.json +0 -74
- invenio_app_ils/version.py +0 -14
- invenio_app_ils/vocabularies/mappings/v6/__init__.py +0 -8
- invenio_app_ils/vocabularies/mappings/v6/vocabularies/vocabulary-v1.0.0.json +0 -25
- invenio_app_ils-1.0.0a54.dist-info/METADATA +0 -95
- tests/api/__init__.py +0 -8
- tests/api/acquisition/test_acq_orders_crud.py +0 -102
- tests/api/acquisition/test_acq_orders_permissions.py +0 -104
- tests/api/acquisition/test_acq_providers_permissions.py +0 -83
- tests/api/circulation/test_expired_loans.py +0 -88
- tests/api/circulation/test_loan_checkout.py +0 -216
- tests/api/circulation/test_loan_default_durations.py +0 -57
- tests/api/circulation/test_loan_document_resolver.py +0 -18
- tests/api/circulation/test_loan_extend.py +0 -132
- tests/api/circulation/test_loan_item_permissions.py +0 -139
- tests/api/circulation/test_loan_item_resolver.py +0 -26
- tests/api/circulation/test_loan_list_permissions.py +0 -104
- tests/api/circulation/test_loan_patron_resolver.py +0 -38
- tests/api/circulation/test_loan_request.py +0 -234
- tests/api/circulation/test_loan_update.py +0 -150
- tests/api/circulation/test_notifications.py +0 -229
- tests/api/conftest.py +0 -236
- tests/api/document_requests/__init__.py +0 -8
- tests/api/document_requests/test_document_requests.py +0 -131
- tests/api/document_requests/test_document_requests_permissions.py +0 -177
- tests/api/document_requests/test_notifications_filter.py +0 -36
- tests/api/ill/test_ill_brw_crud.py +0 -84
- tests/api/ill/test_ill_brw_reqs_patron_loan_create_action.py +0 -207
- tests/api/ill/test_ill_brw_reqs_patron_loan_extension_actions.py +0 -298
- tests/api/ill/test_ill_brw_reqs_permissions.py +0 -169
- tests/api/ill/test_ill_providers_permissions.py +0 -82
- tests/api/ils/__init__.py +0 -8
- tests/api/ils/documents/__init__.py +0 -8
- tests/api/ils/documents/test_document_crud.py +0 -57
- tests/api/ils/documents/test_document_permissions.py +0 -106
- tests/api/ils/documents/test_document_resolvers.py +0 -35
- tests/api/ils/eitems/__init__.py +0 -8
- tests/api/ils/eitems/test_eitems_crud.py +0 -41
- tests/api/ils/eitems/test_eitems_permissions.py +0 -84
- tests/api/ils/eitems/test_files.py +0 -172
- tests/api/ils/items/__init__.py +0 -8
- tests/api/ils/items/test_apis.py +0 -43
- tests/api/ils/items/test_items_crud.py +0 -60
- tests/api/ils/items/test_items_permissions.py +0 -107
- tests/api/ils/items/test_items_update.py +0 -47
- tests/api/ils/records_relations/__init__.py +0 -8
- tests/api/ils/records_relations/helpers.py +0 -115
- tests/api/ils/records_relations/test_records_relations_parentchild.py +0 -560
- tests/api/ils/records_relations/test_records_relations_sequence.py +0 -302
- tests/api/ils/records_relations/test_records_relations_siblings.py +0 -678
- tests/api/ils/series/__init__.py +0 -8
- tests/api/ils/series/test_series_permissions.py +0 -95
- tests/api/ils/test_anonymization.py +0 -189
- tests/api/ils/test_apis.py +0 -76
- tests/api/ils/test_closures.py +0 -324
- tests/api/ils/test_errors.py +0 -126
- tests/api/ils/test_facets.py +0 -84
- tests/api/ils/test_internal_locations.py +0 -96
- tests/api/ils/test_loaders.py +0 -55
- tests/api/ils/test_metadata_extensions.py +0 -205
- tests/api/ils/test_notifications.py +0 -183
- tests/api/ils/test_notifications_mails.py +0 -39
- tests/api/ils/test_notifications_permissions.py +0 -55
- tests/api/ils/test_patrons.py +0 -106
- tests/api/ils/test_record_delete.py +0 -46
- tests/api/ils/test_record_permissions.py +0 -135
- tests/api/ils/test_resolvers.py +0 -207
- tests/api/ils/test_stats.py +0 -160
- tests/api/ils/test_tasks.py +0 -211
- tests/api/ils/test_vocabularies.py +0 -35
- tests/conftest.py +0 -123
- tests/data/acq_orders.json +0 -89
- tests/data/acq_providers.json +0 -12
- tests/data/document_requests.json +0 -77
- tests/data/documents.json +0 -237
- tests/data/eitems.json +0 -66
- tests/data/ill_borrowing_requests.json +0 -77
- tests/data/ill_providers.json +0 -12
- tests/data/internal_locations.json +0 -22
- tests/data/items.json +0 -271
- tests/data/loans.json +0 -133
- tests/data/loans_most_loaned.json +0 -128
- tests/data/locations.json +0 -20
- tests/data/series.json +0 -33
- tests/helpers.py +0 -104
- tests/templates/notifications/title_body.html +0 -8
- tests/templates/notifications/title_body_html.html +0 -13
- tests/templates/notifications/title_body_html_ctx.html +0 -13
- tests/templates/notifications/title_only.html +0 -3
- tests/test_version.py +0 -17
- /tests/templates/notifications/blank.html → /invenio_app_ils/acquisition/mappings/os-v1/__init__.py +0 -0
- /invenio_app_ils/stats/aggregations/aggr_file_download/{v6 → os-v1}/__init__.py +0 -0
- /invenio_app_ils/stats/file_download/{v6 → os-v1}/__init__.py +0 -0
- {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info/licenses}/AUTHORS.rst +0 -0
- {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info/licenses}/LICENSE +0 -0
|
@@ -10,10 +10,7 @@
|
|
|
10
10
|
from flask import current_app
|
|
11
11
|
from invenio_records_rest.serializers.csv import CSVSerializer
|
|
12
12
|
from invenio_records_rest.serializers.json import JSONSerializer
|
|
13
|
-
from invenio_records_rest.serializers.response import
|
|
14
|
-
add_link_header,
|
|
15
|
-
search_responsify,
|
|
16
|
-
)
|
|
13
|
+
from invenio_records_rest.serializers.response import add_link_header, search_responsify
|
|
17
14
|
|
|
18
15
|
from invenio_app_ils.records.schemas.json import ILSRecordSchemaJSONV1
|
|
19
16
|
|
invenio_app_ils/records/views.py
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
from flask import Blueprint, abort, current_app, request
|
|
11
11
|
from flask_login import current_user
|
|
12
12
|
from invenio_files_rest.models import ObjectVersion
|
|
13
|
-
from invenio_files_rest.signals import file_downloaded
|
|
14
13
|
from invenio_records_rest.utils import obj_or_import_string
|
|
15
14
|
from invenio_records_rest.views import pass_record
|
|
16
15
|
from invenio_rest import ContentNegotiatedMethodView
|
|
@@ -18,10 +17,10 @@ from invenio_rest import ContentNegotiatedMethodView
|
|
|
18
17
|
from invenio_app_ils.documents.api import DOCUMENT_PID_TYPE
|
|
19
18
|
from invenio_app_ils.eitems.api import EITEM_PID_TYPE
|
|
20
19
|
from invenio_app_ils.errors import StatsError
|
|
21
|
-
from invenio_app_ils.permissions import
|
|
20
|
+
from invenio_app_ils.permissions import backoffice_read_permission
|
|
22
21
|
from invenio_app_ils.records.permissions import RecordPermission
|
|
23
22
|
from invenio_app_ils.series.api import SERIES_PID_TYPE
|
|
24
|
-
from invenio_app_ils.signals import record_viewed
|
|
23
|
+
from invenio_app_ils.signals import file_downloaded, record_viewed
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
def create_document_stats_blueprint(app):
|
|
@@ -34,8 +33,7 @@ def create_document_stats_blueprint(app):
|
|
|
34
33
|
default_media_type = options.get("default_media_type", "")
|
|
35
34
|
rec_serializers = options.get("record_serializers", {})
|
|
36
35
|
serializers = {
|
|
37
|
-
mime: obj_or_import_string(func)
|
|
38
|
-
for mime, func in rec_serializers.items()
|
|
36
|
+
mime: obj_or_import_string(func) for mime, func in rec_serializers.items()
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
stats_view = DocumentStatsResource.as_view(
|
|
@@ -64,11 +62,10 @@ class DocumentStatsResource(ContentNegotiatedMethodView):
|
|
|
64
62
|
def post(self, pid, record, **kwargs):
|
|
65
63
|
"""Send a signal to count record view for the record stats."""
|
|
66
64
|
factory = RecordPermission(record, "read")
|
|
67
|
-
if not factory.is_public() and not
|
|
65
|
+
if not factory.is_public() and not backoffice_read_permission().can():
|
|
68
66
|
if not current_user.is_authenticated:
|
|
69
67
|
abort(401)
|
|
70
68
|
abort(403)
|
|
71
|
-
|
|
72
69
|
data = request.get_json()
|
|
73
70
|
event_name = data.get("event")
|
|
74
71
|
if event_name == "record-view":
|
|
@@ -9,10 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
from copy import deepcopy
|
|
11
11
|
|
|
12
|
-
from invenio_app_ils.errors import
|
|
13
|
-
RecordHasReferencesError,
|
|
14
|
-
RecordRelationsError,
|
|
15
|
-
)
|
|
12
|
+
from invenio_app_ils.errors import RecordHasReferencesError, RecordRelationsError
|
|
16
13
|
from invenio_app_ils.records.api import IlsRecord
|
|
17
14
|
from invenio_app_ils.relations.api import (
|
|
18
15
|
MULTIPART_MONOGRAPH_RELATION,
|
|
@@ -44,9 +41,7 @@ class RecordRelationsExtraMetadata(object):
|
|
|
44
41
|
return r
|
|
45
42
|
|
|
46
43
|
@classmethod
|
|
47
|
-
def get_extra_metadata_from(
|
|
48
|
-
cls, record, relation_name, pid_value, pid_type
|
|
49
|
-
):
|
|
44
|
+
def get_extra_metadata_from(cls, record, relation_name, pid_value, pid_type):
|
|
50
45
|
"""Return the extra metadata dict for the given PID and type."""
|
|
51
46
|
metadata = record.get(cls.field_name(), {}).get(relation_name, [])
|
|
52
47
|
for m in metadata:
|
|
@@ -83,9 +78,7 @@ class RecordRelationsExtraMetadata(object):
|
|
|
83
78
|
record.commit()
|
|
84
79
|
|
|
85
80
|
@classmethod
|
|
86
|
-
def remove_extra_metadata_from(
|
|
87
|
-
cls, record, relation_name, pid_value, pid_type
|
|
88
|
-
):
|
|
81
|
+
def remove_extra_metadata_from(cls, record, relation_name, pid_value, pid_type):
|
|
89
82
|
"""Remove any presence of the given PID in extra metadata."""
|
|
90
83
|
field = cls.field_name()
|
|
91
84
|
if field in record and relation_name in record[field]:
|
|
@@ -171,9 +164,7 @@ class RecordRelationsParentChild(RecordRelations):
|
|
|
171
164
|
)
|
|
172
165
|
|
|
173
166
|
# when child is Document, parent is any type of Series
|
|
174
|
-
is_series_doc = isinstance(child, Document) and isinstance(
|
|
175
|
-
parent, Series
|
|
176
|
-
)
|
|
167
|
+
is_series_doc = isinstance(child, Document) and isinstance(parent, Series)
|
|
177
168
|
# when child is Multipart Monograph, parent is only Serials
|
|
178
169
|
is_serial_mm = (
|
|
179
170
|
isinstance(child, Series)
|
|
@@ -215,9 +206,7 @@ class RecordRelationsParentChild(RecordRelations):
|
|
|
215
206
|
|
|
216
207
|
if relation_allows_metadata and has_allowed_metadata:
|
|
217
208
|
# filter and keep only allowed metadata
|
|
218
|
-
allowed = {
|
|
219
|
-
k: v for k, v in kwargs.items() if k in self.allowed_metadata
|
|
220
|
-
}
|
|
209
|
+
allowed = {k: v for k, v in kwargs.items() if k in self.allowed_metadata}
|
|
221
210
|
# store relation metadata in the child record
|
|
222
211
|
RecordRelationsExtraMetadata.add_extra_metadata_to(
|
|
223
212
|
child,
|
|
@@ -261,9 +250,7 @@ class RecordRelationsSiblings(RecordRelations):
|
|
|
261
250
|
from invenio_app_ils.series.api import Series
|
|
262
251
|
|
|
263
252
|
# records must be of the same type
|
|
264
|
-
same_document = isinstance(first, Document) and isinstance(
|
|
265
|
-
second, Document
|
|
266
|
-
)
|
|
253
|
+
same_document = isinstance(first, Document) and isinstance(second, Document)
|
|
267
254
|
same_series = (
|
|
268
255
|
isinstance(first, Series)
|
|
269
256
|
and isinstance(second, Series)
|
|
@@ -312,9 +299,7 @@ class RecordRelationsSiblings(RecordRelations):
|
|
|
312
299
|
)
|
|
313
300
|
)
|
|
314
301
|
|
|
315
|
-
if not (
|
|
316
|
-
valid_edition_fields or valid_language_fields or valid_other_fields
|
|
317
|
-
):
|
|
302
|
+
if not (valid_edition_fields or valid_language_fields or valid_other_fields):
|
|
318
303
|
raise RecordRelationsError(
|
|
319
304
|
"Cannot create relation `{}` "
|
|
320
305
|
"between PID `{}` and PID `{}`,"
|
|
@@ -357,9 +342,7 @@ class RecordRelationsSiblings(RecordRelations):
|
|
|
357
342
|
|
|
358
343
|
if has_allowed_metadata:
|
|
359
344
|
# filter and keep only allowed metadata
|
|
360
|
-
allowed = {
|
|
361
|
-
k: v for k, v in kwargs.items() if k in self.allowed_metadata
|
|
362
|
-
}
|
|
345
|
+
allowed = {k: v for k, v in kwargs.items() if k in self.allowed_metadata}
|
|
363
346
|
# store relation metadata in the first record
|
|
364
347
|
RecordRelationsExtraMetadata.add_extra_metadata_to(
|
|
365
348
|
first,
|
|
@@ -394,9 +377,7 @@ class RecordRelationsSequence(RecordRelations):
|
|
|
394
377
|
"""Constructor."""
|
|
395
378
|
self.relation_types = SEQUENCE_RELATION_TYPES
|
|
396
379
|
|
|
397
|
-
def _validate_relation_between_records(
|
|
398
|
-
self, previous_rec, next_rec, relation_name
|
|
399
|
-
):
|
|
380
|
+
def _validate_relation_between_records(self, previous_rec, next_rec, relation_name):
|
|
400
381
|
"""Validate relation between type of records."""
|
|
401
382
|
from invenio_app_ils.series.api import Series
|
|
402
383
|
|
|
@@ -428,17 +409,13 @@ class RecordRelationsSequence(RecordRelations):
|
|
|
428
409
|
)
|
|
429
410
|
|
|
430
411
|
sequence_relation = SequenceRelation(relation_type)
|
|
431
|
-
sequence_relation.add(
|
|
432
|
-
previous_pid=previous_rec.pid, next_pid=next_rec.pid
|
|
433
|
-
)
|
|
412
|
+
sequence_relation.add(previous_pid=previous_rec.pid, next_pid=next_rec.pid)
|
|
434
413
|
|
|
435
414
|
def remove(self, previous_rec, next_rec, relation_type):
|
|
436
415
|
"""Remove sequence relation between previous and next records."""
|
|
437
416
|
self._validate_relation_type(relation_type)
|
|
438
417
|
sequence_relation = SequenceRelation(relation_type)
|
|
439
|
-
sequence_relation.remove(
|
|
440
|
-
previous_pid=previous_rec.pid, next_pid=next_rec.pid
|
|
441
|
-
)
|
|
418
|
+
sequence_relation.remove(previous_pid=previous_rec.pid, next_pid=next_rec.pid)
|
|
442
419
|
|
|
443
420
|
|
|
444
421
|
class IlsRecordWithRelations(IlsRecord):
|
|
@@ -43,9 +43,7 @@ class RecordRelationIndexer(RecordIndexer):
|
|
|
43
43
|
indexed = dict(pid_type=record._pid_type, record=record)
|
|
44
44
|
|
|
45
45
|
def add_referenced(pid_value, pid_type):
|
|
46
|
-
same_record =
|
|
47
|
-
pid_value == record["pid"] and pid_type == record._pid_type
|
|
48
|
-
)
|
|
46
|
+
same_record = pid_value == record["pid"] and pid_type == record._pid_type
|
|
49
47
|
pid = (pid_value, pid_type)
|
|
50
48
|
if not same_record and pid not in referenced:
|
|
51
49
|
referenced.add(pid)
|
|
@@ -23,9 +23,7 @@ from .api import RecordRelationsExtraMetadata as RelationsExtraMetadata
|
|
|
23
23
|
class RelationObjectBuilderMixin(object):
|
|
24
24
|
"""Relations object builder."""
|
|
25
25
|
|
|
26
|
-
def build_relations_object(
|
|
27
|
-
self, pid_value, pid_type, relation_name, **kwargs
|
|
28
|
-
):
|
|
26
|
+
def build_relations_object(self, pid_value, pid_type, relation_name, **kwargs):
|
|
29
27
|
"""Build and return each object of `relations` field."""
|
|
30
28
|
r = {
|
|
31
29
|
"pid_value": pid_value,
|
|
@@ -92,9 +90,7 @@ class ParentChildRetriever(RelationObjectBuilderMixin):
|
|
|
92
90
|
name = relation_type.name
|
|
93
91
|
|
|
94
92
|
for parent_pid in pcr.get_parents_of(self.child_record.pid):
|
|
95
|
-
r = self._build_relation_obj(
|
|
96
|
-
self.child_record, parent_pid, name
|
|
97
|
-
)
|
|
93
|
+
r = self._build_relation_obj(self.child_record, parent_pid, name)
|
|
98
94
|
relations.setdefault(name, [])
|
|
99
95
|
relations[name].append(r)
|
|
100
96
|
return relations
|
|
@@ -154,9 +150,7 @@ class SiblingsRetriever(RelationObjectBuilderMixin):
|
|
|
154
150
|
|
|
155
151
|
sibling = IlsRecord.get_record_by_pid(pid_value, pid_type=pid_type)
|
|
156
152
|
|
|
157
|
-
metadata = self._get_extra_metadata(
|
|
158
|
-
self.record, sibling, relation_type
|
|
159
|
-
)
|
|
153
|
+
metadata = self._get_extra_metadata(self.record, sibling, relation_type)
|
|
160
154
|
# copy the extra metadata into the relation, if any
|
|
161
155
|
r.update(metadata)
|
|
162
156
|
|
|
@@ -176,6 +170,17 @@ class SiblingsRetriever(RelationObjectBuilderMixin):
|
|
|
176
170
|
r = self._build_relation_obj(sibling_pid, name)
|
|
177
171
|
relations.setdefault(name, [])
|
|
178
172
|
relations[name].append(r)
|
|
173
|
+
|
|
174
|
+
# Pre-requisite: fields being sorted should be of the same type.
|
|
175
|
+
# Sort by the keys available in the data in order
|
|
176
|
+
if relation_type.sort_by:
|
|
177
|
+
relations.get(name, []).sort(
|
|
178
|
+
key=lambda rec: [
|
|
179
|
+
rec.get("record_metadata", {}).get(key)
|
|
180
|
+
for key in relation_type.sort_by
|
|
181
|
+
]
|
|
182
|
+
)
|
|
183
|
+
|
|
179
184
|
return relations
|
|
180
185
|
|
|
181
186
|
|
|
@@ -43,8 +43,7 @@ def create_relations_blueprint(app):
|
|
|
43
43
|
default_media_type = options.get("default_media_type", "")
|
|
44
44
|
rec_serializers = options.get("record_serializers", {})
|
|
45
45
|
serializers = {
|
|
46
|
-
mime: obj_or_import_string(func)
|
|
47
|
-
for mime, func in rec_serializers.items()
|
|
46
|
+
mime: obj_or_import_string(func) for mime, func in rec_serializers.items()
|
|
48
47
|
}
|
|
49
48
|
record_relations = view_class.as_view(
|
|
50
49
|
view_class.view_name.format(pid_type),
|
|
@@ -86,9 +85,7 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
86
85
|
child_pid_value = payload.pop("child_pid_value")
|
|
87
86
|
child_pid_type = payload.pop("child_pid_type")
|
|
88
87
|
except KeyError as key:
|
|
89
|
-
raise RecordRelationsError(
|
|
90
|
-
"The `{}` is a required field".format(key)
|
|
91
|
-
)
|
|
88
|
+
raise RecordRelationsError("The `{}` is a required field".format(key))
|
|
92
89
|
|
|
93
90
|
return (
|
|
94
91
|
parent_pid_value,
|
|
@@ -167,9 +164,7 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
167
164
|
pid_value = payload.pop("pid_value")
|
|
168
165
|
pid_type = payload.pop("pid_type")
|
|
169
166
|
except KeyError as key:
|
|
170
|
-
raise RecordRelationsError(
|
|
171
|
-
"The `{}` is a required field".format(key)
|
|
172
|
-
)
|
|
167
|
+
raise RecordRelationsError("The `{}` is a required field".format(key))
|
|
173
168
|
|
|
174
169
|
return pid_value, pid_type, payload
|
|
175
170
|
|
|
@@ -193,19 +188,14 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
193
188
|
|
|
194
189
|
if pid_value == record["pid"] and pid_type == record._pid_type:
|
|
195
190
|
raise RecordRelationsError(
|
|
196
|
-
"Cannot create a relation for PID `{}` with itself".format(
|
|
197
|
-
pid_value
|
|
198
|
-
)
|
|
191
|
+
"Cannot create a relation for PID `{}` with itself".format(pid_value)
|
|
199
192
|
)
|
|
200
193
|
|
|
201
194
|
second = IlsRecord.get_record_by_pid(pid_value, pid_type=pid_type)
|
|
202
195
|
|
|
203
196
|
rr = RecordRelationsSiblings()
|
|
204
197
|
modified_record = rr.add(
|
|
205
|
-
first=record,
|
|
206
|
-
second=second,
|
|
207
|
-
relation_type=relation_type,
|
|
208
|
-
**metadata
|
|
198
|
+
first=record, second=second, relation_type=relation_type, **metadata
|
|
209
199
|
)
|
|
210
200
|
return modified_record, record, second
|
|
211
201
|
|
|
@@ -220,9 +210,7 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
220
210
|
relation_type: "<relation name>"
|
|
221
211
|
}
|
|
222
212
|
"""
|
|
223
|
-
pid_value, pid_type, _ = self._validate_siblings_creation_payload(
|
|
224
|
-
payload
|
|
225
|
-
)
|
|
213
|
+
pid_value, pid_type, _ = self._validate_siblings_creation_payload(payload)
|
|
226
214
|
|
|
227
215
|
second = IlsRecord.get_record_by_pid(pid_value, pid_type=pid_type)
|
|
228
216
|
|
|
@@ -240,14 +228,9 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
240
228
|
previous_pid_value = payload.pop("previous_pid_value")
|
|
241
229
|
previous_pid_type = payload.pop("previous_pid_type")
|
|
242
230
|
except KeyError as key:
|
|
243
|
-
raise RecordRelationsError(
|
|
244
|
-
"The `{}` is a required field".format(key)
|
|
245
|
-
)
|
|
231
|
+
raise RecordRelationsError("The `{}` is a required field".format(key))
|
|
246
232
|
|
|
247
|
-
if
|
|
248
|
-
record["pid"] != next_pid_value
|
|
249
|
-
and record["pid"] != previous_pid_value
|
|
250
|
-
):
|
|
233
|
+
if record["pid"] != next_pid_value and record["pid"] != previous_pid_value:
|
|
251
234
|
raise RecordRelationsError(
|
|
252
235
|
"Cannot create a relation for other record than one with PID "
|
|
253
236
|
"`{}`".format(record["pid"])
|
|
@@ -256,9 +239,7 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
256
239
|
if next_pid_value == previous_pid_value:
|
|
257
240
|
raise RecordRelationsError(
|
|
258
241
|
"Cannot create a sequence with the same next PID `{}`"
|
|
259
|
-
"and previous PID `{}`".format(
|
|
260
|
-
next_pid_value, previous_pid_value
|
|
261
|
-
)
|
|
242
|
+
"and previous PID `{}`".format(next_pid_value, previous_pid_value)
|
|
262
243
|
)
|
|
263
244
|
|
|
264
245
|
return (
|
|
@@ -290,9 +271,7 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
290
271
|
metadata,
|
|
291
272
|
) = self._validate_sequence_creation_payload(record, payload)
|
|
292
273
|
|
|
293
|
-
next_rec = IlsRecord.get_record_by_pid(
|
|
294
|
-
next_pid_value, pid_type=next_pid_type
|
|
295
|
-
)
|
|
274
|
+
next_rec = IlsRecord.get_record_by_pid(next_pid_value, pid_type=next_pid_type)
|
|
296
275
|
|
|
297
276
|
previous_rec = IlsRecord.get_record_by_pid(
|
|
298
277
|
previous_pid_value, pid_type=previous_pid_type
|
|
@@ -327,9 +306,7 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
327
306
|
metadata,
|
|
328
307
|
) = self._validate_sequence_creation_payload(record, payload)
|
|
329
308
|
|
|
330
|
-
next_rec = IlsRecord.get_record_by_pid(
|
|
331
|
-
next_pid_value, pid_type=next_pid_type
|
|
332
|
-
)
|
|
309
|
+
next_rec = IlsRecord.get_record_by_pid(next_pid_value, pid_type=next_pid_type)
|
|
333
310
|
|
|
334
311
|
previous_rec = IlsRecord.get_record_by_pid(
|
|
335
312
|
prev_pid_value, pid_type=prev_pid_type
|
|
@@ -364,14 +341,10 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
364
341
|
record, rt, payload
|
|
365
342
|
)
|
|
366
343
|
elif rt in SEQUENCE_RELATION_TYPES:
|
|
367
|
-
first, second = self._create_sequence_relation(
|
|
368
|
-
record, rt, payload
|
|
369
|
-
)
|
|
344
|
+
first, second = self._create_sequence_relation(record, rt, payload)
|
|
370
345
|
modified = second
|
|
371
346
|
else:
|
|
372
|
-
raise RecordRelationsError(
|
|
373
|
-
"Invalid relation type `{}`".format(rt.name)
|
|
374
|
-
)
|
|
347
|
+
raise RecordRelationsError("Invalid relation type `{}`".format(rt.name))
|
|
375
348
|
|
|
376
349
|
db.session.commit()
|
|
377
350
|
|
|
@@ -426,14 +399,10 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
426
399
|
record, rt, payload
|
|
427
400
|
)
|
|
428
401
|
elif rt in SEQUENCE_RELATION_TYPES:
|
|
429
|
-
first, second = self._delete_sequence_relation(
|
|
430
|
-
record, rt, payload
|
|
431
|
-
)
|
|
402
|
+
first, second = self._delete_sequence_relation(record, rt, payload)
|
|
432
403
|
modified = first
|
|
433
404
|
else:
|
|
434
|
-
raise RecordRelationsError(
|
|
435
|
-
"Invalid relation type `{}`".format(rt.name)
|
|
436
|
-
)
|
|
405
|
+
raise RecordRelationsError("Invalid relation type `{}`".format(rt.name))
|
|
437
406
|
|
|
438
407
|
db.session.commit()
|
|
439
408
|
|
|
@@ -441,10 +410,7 @@ class RecordRelationsResource(ContentNegotiatedMethodView):
|
|
|
441
410
|
records_to_index.append(second)
|
|
442
411
|
|
|
443
412
|
# if the record is the modified, return the modified version
|
|
444
|
-
if
|
|
445
|
-
modified.pid == record.pid
|
|
446
|
-
and modified._pid_type == record._pid_type
|
|
447
|
-
):
|
|
413
|
+
if modified.pid == record.pid and modified._pid_type == record._pid_type:
|
|
448
414
|
return modified
|
|
449
415
|
return record
|
|
450
416
|
|
invenio_app_ils/relations/api.py
CHANGED
|
@@ -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",
|
|
20
|
+
"IlsRelationType",
|
|
21
|
+
RelationType._fields
|
|
22
|
+
+ (
|
|
23
|
+
"relation_class",
|
|
24
|
+
"sort_by",
|
|
25
|
+
),
|
|
21
26
|
)
|
|
22
27
|
|
|
23
28
|
LANGUAGE_RELATION = ILS_RELATION_TYPE(
|
|
@@ -27,6 +32,7 @@ LANGUAGE_RELATION = ILS_RELATION_TYPE(
|
|
|
27
32
|
"invenio_app_ils.relations.nodes:PIDNodeRelated",
|
|
28
33
|
"invenio_pidrelations.serializers.schemas.RelationSchema",
|
|
29
34
|
"invenio_app_ils.relations.api.SiblingsRelation",
|
|
35
|
+
None,
|
|
30
36
|
)
|
|
31
37
|
EDITION_RELATION = ILS_RELATION_TYPE(
|
|
32
38
|
1,
|
|
@@ -35,6 +41,7 @@ EDITION_RELATION = ILS_RELATION_TYPE(
|
|
|
35
41
|
"invenio_app_ils.relations.nodes:PIDNodeRelated",
|
|
36
42
|
"invenio_pidrelations.serializers.schemas.RelationSchema",
|
|
37
43
|
"invenio_app_ils.relations.api.SiblingsRelation",
|
|
44
|
+
["edition"],
|
|
38
45
|
)
|
|
39
46
|
OTHER_RELATION = ILS_RELATION_TYPE(
|
|
40
47
|
2,
|
|
@@ -43,6 +50,7 @@ OTHER_RELATION = ILS_RELATION_TYPE(
|
|
|
43
50
|
"invenio_app_ils.relations.nodes:PIDNodeRelated",
|
|
44
51
|
"invenio_pidrelations.serializers.schemas.RelationSchema",
|
|
45
52
|
"invenio_app_ils.relations.api.SiblingsRelation",
|
|
53
|
+
None,
|
|
46
54
|
)
|
|
47
55
|
MULTIPART_MONOGRAPH_RELATION = ILS_RELATION_TYPE(
|
|
48
56
|
3,
|
|
@@ -51,6 +59,7 @@ MULTIPART_MONOGRAPH_RELATION = ILS_RELATION_TYPE(
|
|
|
51
59
|
"invenio_app_ils.relations.nodes:PIDNodeRelated",
|
|
52
60
|
"invenio_pidrelations.serializers.schemas.RelationSchema",
|
|
53
61
|
"invenio_app_ils.relations.api.ParentChildRelation",
|
|
62
|
+
None,
|
|
54
63
|
)
|
|
55
64
|
SERIAL_RELATION = ILS_RELATION_TYPE(
|
|
56
65
|
4,
|
|
@@ -59,6 +68,7 @@ SERIAL_RELATION = ILS_RELATION_TYPE(
|
|
|
59
68
|
"invenio_app_ils.relations.nodes:PIDNodeRelated",
|
|
60
69
|
"invenio_pidrelations.serializers.schemas.RelationSchema",
|
|
61
70
|
"invenio_app_ils.relations.api.ParentChildRelation",
|
|
71
|
+
None,
|
|
62
72
|
)
|
|
63
73
|
SEQUENCE_RELATION = ILS_RELATION_TYPE(
|
|
64
74
|
5,
|
|
@@ -67,6 +77,7 @@ SEQUENCE_RELATION = ILS_RELATION_TYPE(
|
|
|
67
77
|
"invenio_app_ils.relations.nodes:PIDNodeRelated",
|
|
68
78
|
"invenio_pidrelations.serializers.schemas.RelationSchema",
|
|
69
79
|
"invenio_app_ils.relations.api.SequenceRelation",
|
|
80
|
+
None,
|
|
70
81
|
)
|
|
71
82
|
|
|
72
83
|
|
|
@@ -77,9 +88,7 @@ SIBLINGS_RELATION_TYPES = [LANGUAGE_RELATION, EDITION_RELATION, OTHER_RELATION]
|
|
|
77
88
|
SEQUENCE_RELATION_TYPES = [SEQUENCE_RELATION]
|
|
78
89
|
|
|
79
90
|
ILS_PIDRELATIONS_TYPES = (
|
|
80
|
-
PARENT_CHILD_RELATION_TYPES
|
|
81
|
-
+ SIBLINGS_RELATION_TYPES
|
|
82
|
-
+ SEQUENCE_RELATION_TYPES
|
|
91
|
+
PARENT_CHILD_RELATION_TYPES + SIBLINGS_RELATION_TYPES + SEQUENCE_RELATION_TYPES
|
|
83
92
|
)
|
|
84
93
|
|
|
85
94
|
|
|
@@ -185,9 +194,7 @@ class ParentChildRelation(Relation):
|
|
|
185
194
|
)
|
|
186
195
|
|
|
187
196
|
with db.session.begin_nested():
|
|
188
|
-
return PIDRelation.create(
|
|
189
|
-
parent_pid, child_pid, self.relation_type.id
|
|
190
|
-
)
|
|
197
|
+
return PIDRelation.create(parent_pid, child_pid, self.relation_type.id)
|
|
191
198
|
|
|
192
199
|
def remove(self, parent_pid, child_pid):
|
|
193
200
|
"""Delete the relation for the given PIDs."""
|
|
@@ -299,9 +306,7 @@ class SiblingsRelation(Relation):
|
|
|
299
306
|
pids_to_relate.add(first_pid)
|
|
300
307
|
pids_to_relate.add(second_pid)
|
|
301
308
|
|
|
302
|
-
self._recreate_relations_with_random_parent(
|
|
303
|
-
all_relations, pids_to_relate
|
|
304
|
-
)
|
|
309
|
+
self._recreate_relations_with_random_parent(all_relations, pids_to_relate)
|
|
305
310
|
|
|
306
311
|
def remove(self, pid):
|
|
307
312
|
"""Remove the only possible relation of this given PID.
|
|
@@ -357,9 +362,7 @@ class SiblingsRelation(Relation):
|
|
|
357
362
|
)
|
|
358
363
|
)
|
|
359
364
|
|
|
360
|
-
self._recreate_relations_with_random_parent(
|
|
361
|
-
all_relations, pids_to_relate
|
|
362
|
-
)
|
|
365
|
+
self._recreate_relations_with_random_parent(all_relations, pids_to_relate)
|
|
363
366
|
|
|
364
367
|
|
|
365
368
|
class SequenceRelation(Relation):
|
|
@@ -386,9 +389,7 @@ class SequenceRelation(Relation):
|
|
|
386
389
|
)
|
|
387
390
|
|
|
388
391
|
with db.session.begin_nested():
|
|
389
|
-
return PIDRelation.create(
|
|
390
|
-
previous_pid, next_pid, self.relation_type.id
|
|
391
|
-
)
|
|
392
|
+
return PIDRelation.create(previous_pid, next_pid, self.relation_type.id)
|
|
392
393
|
|
|
393
394
|
def remove(self, previous_pid, next_pid):
|
|
394
395
|
"""Delete the relation for the given PIDs."""
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
import re
|
|
11
11
|
|
|
12
|
-
from elasticsearch_dsl import Q
|
|
13
12
|
from flask import current_app, g, has_request_context, request
|
|
13
|
+
from invenio_search.engine import dsl
|
|
14
14
|
|
|
15
15
|
from invenio_app_ils.errors import SearchQueryError, UnauthorizedSearchError
|
|
16
|
-
from invenio_app_ils.permissions import
|
|
16
|
+
from invenio_app_ils.permissions import backoffice_read_permission
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def _get_user_provides():
|
|
@@ -30,12 +30,12 @@ def _get_user_provides():
|
|
|
30
30
|
|
|
31
31
|
def search_filter_record_permissions():
|
|
32
32
|
"""Filter list of results by `_access` and `restricted` fields."""
|
|
33
|
-
if not has_request_context() or
|
|
34
|
-
return Q()
|
|
33
|
+
if not has_request_context() or backoffice_read_permission().allows(g.identity):
|
|
34
|
+
return dsl.Q()
|
|
35
35
|
|
|
36
36
|
# A record is public if `restricted` field False or missing
|
|
37
|
-
restricted_field_missing = ~Q("exists", field="restricted")
|
|
38
|
-
is_restricted = restricted_field_missing | Q("term", restricted=False)
|
|
37
|
+
restricted_field_missing = ~dsl.Q("exists", field="restricted")
|
|
38
|
+
is_restricted = restricted_field_missing | dsl.Q("term", restricted=False)
|
|
39
39
|
|
|
40
40
|
combined_filter = is_restricted
|
|
41
41
|
|
|
@@ -43,28 +43,28 @@ def search_filter_record_permissions():
|
|
|
43
43
|
# if `_access`, check `_access.read` against the user. It takes
|
|
44
44
|
# precedence over `restricted`.
|
|
45
45
|
# if not `_access`, check if open access as before.
|
|
46
|
-
_access_field_exists = Q("exists", field="_access.read")
|
|
46
|
+
_access_field_exists = dsl.Q("exists", field="_access.read")
|
|
47
47
|
provides = _get_user_provides()
|
|
48
|
-
user_can_read = _access_field_exists & Q(
|
|
48
|
+
user_can_read = _access_field_exists & dsl.Q(
|
|
49
49
|
"terms", **{"_access.read": provides}
|
|
50
50
|
)
|
|
51
|
-
combined_filter = user_can_read | (
|
|
52
|
-
~_access_field_exists & ~is_restricted
|
|
53
|
-
)
|
|
51
|
+
combined_filter = user_can_read | (~_access_field_exists & ~is_restricted)
|
|
54
52
|
|
|
55
|
-
return Q("bool", filter=[combined_filter])
|
|
53
|
+
return dsl.Q("bool", filter=[combined_filter])
|
|
56
54
|
|
|
57
55
|
|
|
58
|
-
def ils_search_factory(self, search, validator=None):
|
|
59
|
-
"""Search factory with Query String validator.
|
|
56
|
+
def ils_search_factory(self, search, query_parser=None, validator=None):
|
|
57
|
+
"""Search factory with Query String parser and validator.
|
|
60
58
|
|
|
61
59
|
:param self: REST view.
|
|
62
60
|
:param search: Elastic search DSL search instance.
|
|
61
|
+
:param query_parser: Custom Query parser DSL.
|
|
62
|
+
:param validator: Custom Validator for query string.
|
|
63
63
|
:returns: Tuple with search instance and URL arguments.
|
|
64
64
|
"""
|
|
65
65
|
|
|
66
|
-
def
|
|
67
|
-
"""Default parser that uses the Q() from
|
|
66
|
+
def _query_parser(search, qstr=None, query_params_modifier=None):
|
|
67
|
+
"""Default parser that uses the Q() from invenio_search.engine.dsl."""
|
|
68
68
|
if qstr:
|
|
69
69
|
boosted = getattr(search, "boosted_fields", [])
|
|
70
70
|
extra_params = {}
|
|
@@ -74,8 +74,10 @@ def ils_search_factory(self, search, validator=None):
|
|
|
74
74
|
# parsing exception on data fields, see known issues
|
|
75
75
|
# https://www.elastic.co/guide/en/elasticsearch/reference/current/release-notes-7.1.1.html # noqa
|
|
76
76
|
extra_params["lenient"] = True
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
if query_params_modifier:
|
|
78
|
+
query_params_modifier(extra_params)
|
|
79
|
+
return dsl.Q("query_string", query=qstr, **extra_params)
|
|
80
|
+
return dsl.Q()
|
|
79
81
|
|
|
80
82
|
from invenio_records_rest.facets import default_facets_factory
|
|
81
83
|
from invenio_records_rest.sorter import default_sorter_factory
|
|
@@ -84,7 +86,7 @@ def ils_search_factory(self, search, validator=None):
|
|
|
84
86
|
|
|
85
87
|
if validator:
|
|
86
88
|
search, query_string = validator(search, query_string)
|
|
87
|
-
query =
|
|
89
|
+
query = _query_parser(search, qstr=query_string, query_params_modifier=query_parser)
|
|
88
90
|
|
|
89
91
|
try:
|
|
90
92
|
search = search.query(query)
|
|
@@ -118,13 +120,11 @@ def _filter_by_patron(patron_id, search, query_string=None):
|
|
|
118
120
|
def _filter_by_current_patron(search, query_string=None):
|
|
119
121
|
"""Filter search results by patron_pid."""
|
|
120
122
|
# if the logged in user is not librarian or admin, validate the query
|
|
121
|
-
if has_request_context() and not
|
|
122
|
-
g.identity
|
|
123
|
-
):
|
|
123
|
+
if has_request_context() and not backoffice_read_permission().allows(g.identity):
|
|
124
124
|
return _filter_by_patron(g.identity.id, search, query_string)
|
|
125
125
|
return search, query_string
|
|
126
126
|
|
|
127
127
|
|
|
128
|
-
def search_factory_filter_by_patron(self, search):
|
|
128
|
+
def search_factory_filter_by_patron(self, search, query_parser=None):
|
|
129
129
|
"""Prepare query string to filter records by current logged in user."""
|
|
130
|
-
return ils_search_factory(self, search, _filter_by_current_patron)
|
|
130
|
+
return ils_search_factory(self, search, query_parser, _filter_by_current_patron)
|
invenio_app_ils/series/api.py
CHANGED
|
@@ -42,10 +42,8 @@ class Series(IlsRecordWithRelations):
|
|
|
42
42
|
SERIES_TYPES = ["SERIAL", "PERIODICAL"]
|
|
43
43
|
|
|
44
44
|
_pid_type = SERIES_PID_TYPE
|
|
45
|
-
_schema = "series/series-
|
|
46
|
-
_relations_path =
|
|
47
|
-
"{scheme}://{host}/api/resolver/series/{series_pid}/relations"
|
|
48
|
-
)
|
|
45
|
+
_schema = "series/series-v2.0.0.json"
|
|
46
|
+
_relations_path = "{scheme}://{host}/api/resolver/series/{series_pid}/relations"
|
|
49
47
|
|
|
50
48
|
MODE_OF_ISSUANCE = [
|
|
51
49
|
"MULTIPART_MONOGRAPH",
|
|
@@ -80,14 +78,14 @@ class Series(IlsRecordWithRelations):
|
|
|
80
78
|
related_refs = set()
|
|
81
79
|
pcr_multipart = ParentChildRelation(MULTIPART_MONOGRAPH_RELATION)
|
|
82
80
|
pcr_serial = ParentChildRelation(SERIAL_RELATION)
|
|
83
|
-
related_multipart_volumes = pcr_multipart.get_children_of(
|
|
84
|
-
|
|
85
|
-
related_serial_volumes
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
related_multipart_volumes = pcr_multipart.get_children_of(self.pid)
|
|
82
|
+
related_serial_volumes = pcr_serial.get_children_of(self.pid)
|
|
83
|
+
for child_pid in related_serial_volumes + related_multipart_volumes:
|
|
84
|
+
related_refs.add(
|
|
85
|
+
"{pid_value}:{pid_type}".format(
|
|
86
|
+
pid_value=child_pid.pid_value, pid_type=child_pid.pid_type
|
|
87
|
+
)
|
|
88
|
+
)
|
|
91
89
|
|
|
92
90
|
if related_refs:
|
|
93
91
|
raise RecordHasReferencesError(
|