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
|
@@ -21,6 +21,8 @@ from marshmallow import (
|
|
|
21
21
|
validates_schema,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
+
from invenio_app_ils.proxies import current_app_ils
|
|
25
|
+
|
|
24
26
|
from .base import LoanBaseSchemaV1
|
|
25
27
|
|
|
26
28
|
|
|
@@ -31,14 +33,54 @@ def request_start_date_default():
|
|
|
31
33
|
|
|
32
34
|
def request_expire_date_default():
|
|
33
35
|
"""Set default value for request_expire_date field."""
|
|
34
|
-
duration_days = current_app.config[
|
|
35
|
-
"ILS_CIRCULATION_LOAN_REQUEST_DURATION_DAYS"
|
|
36
|
-
]
|
|
36
|
+
duration_days = current_app.config["ILS_CIRCULATION_LOAN_REQUEST_DURATION_DAYS"]
|
|
37
37
|
duration = timedelta(days=duration_days)
|
|
38
38
|
now = arrow.get().utcnow()
|
|
39
39
|
return (now + duration).date().isoformat()
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
def get_offset_duration(request_start_date, location_pid, working_days_to_offset):
|
|
43
|
+
location = current_app_ils.location_record_cls.get_record_by_pid(location_pid)
|
|
44
|
+
|
|
45
|
+
weekdays = location["opening_weekdays"]
|
|
46
|
+
exceptions = location["opening_exceptions"]
|
|
47
|
+
disabled = set()
|
|
48
|
+
|
|
49
|
+
date = request_start_date
|
|
50
|
+
max_date = request_start_date + timedelta(
|
|
51
|
+
days=current_app.config["ILS_CIRCULATION_LOAN_REQUEST_DURATION_DAYS"]
|
|
52
|
+
)
|
|
53
|
+
# Calculate all disabled days that need to be skipped
|
|
54
|
+
# Used in calculating non-closure days to offset in post-load checks
|
|
55
|
+
while date <= max_date:
|
|
56
|
+
date_iso = date.date().isoformat()
|
|
57
|
+
is_open = weekdays[date.weekday()]["is_open"]
|
|
58
|
+
|
|
59
|
+
for exception in exceptions:
|
|
60
|
+
start_date = arrow.get(exception["start_date"])
|
|
61
|
+
end_date = arrow.get(exception["end_date"])
|
|
62
|
+
|
|
63
|
+
if start_date <= arrow.get(date.date()) <= end_date:
|
|
64
|
+
is_open = exception["is_open"]
|
|
65
|
+
|
|
66
|
+
if not is_open:
|
|
67
|
+
disabled.add(date_iso)
|
|
68
|
+
|
|
69
|
+
date += timedelta(days=1)
|
|
70
|
+
|
|
71
|
+
total_offset_days = 0
|
|
72
|
+
date = request_start_date
|
|
73
|
+
while working_days_to_offset > 0:
|
|
74
|
+
date_iso = date.date().isoformat()
|
|
75
|
+
if date_iso not in disabled:
|
|
76
|
+
disabled.add(date_iso)
|
|
77
|
+
working_days_to_offset -= 1
|
|
78
|
+
date += timedelta(days=1)
|
|
79
|
+
total_offset_days += 1
|
|
80
|
+
|
|
81
|
+
return timedelta(days=total_offset_days)
|
|
82
|
+
|
|
83
|
+
|
|
42
84
|
class LoanRequestDeliverySchemaV1(Schema):
|
|
43
85
|
"""Loan common delivery Schema."""
|
|
44
86
|
|
|
@@ -65,12 +107,12 @@ class LoanRequestSchemaV1(LoanBaseSchemaV1):
|
|
|
65
107
|
"""Loan request schema."""
|
|
66
108
|
|
|
67
109
|
delivery = fields.Nested(LoanRequestDeliverySchemaV1)
|
|
68
|
-
request_expire_date = DateString(
|
|
69
|
-
request_start_date = DateString(
|
|
110
|
+
request_expire_date = DateString(load_default=request_expire_date_default)
|
|
111
|
+
request_start_date = DateString(load_default=request_start_date_default)
|
|
70
112
|
|
|
71
113
|
@validates_schema()
|
|
72
114
|
def validates_schema(self, data, **kwargs):
|
|
73
|
-
"""Validate schema
|
|
115
|
+
"""Validate schema fields."""
|
|
74
116
|
delivery = data.get("delivery")
|
|
75
117
|
# if delivery methods is configured, it has to be a mandatory field
|
|
76
118
|
if (
|
|
@@ -79,29 +121,44 @@ class LoanRequestSchemaV1(LoanBaseSchemaV1):
|
|
|
79
121
|
):
|
|
80
122
|
raise ValidationError("Delivery is required.", "delivery")
|
|
81
123
|
|
|
124
|
+
if current_app.config["ILS_CIRCULATION_LOAN_REQUEST_OFFSET"] < 0:
|
|
125
|
+
raise ValidationError(
|
|
126
|
+
{
|
|
127
|
+
"ILS_CIRCULATION_LOAN_REQUEST_OFFSET": [
|
|
128
|
+
"The minimum days after which a loan can start cannot be negative."
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
)
|
|
132
|
+
|
|
82
133
|
@post_load()
|
|
83
134
|
def postload_checks(self, data, **kwargs):
|
|
84
135
|
"""Validate dates values."""
|
|
85
136
|
start = arrow.get(data["request_start_date"]).date()
|
|
86
137
|
end = arrow.get(data["request_expire_date"]).date()
|
|
87
|
-
duration_days = current_app.config[
|
|
88
|
-
"ILS_CIRCULATION_LOAN_REQUEST_DURATION_DAYS"
|
|
89
|
-
]
|
|
138
|
+
duration_days = current_app.config["ILS_CIRCULATION_LOAN_REQUEST_DURATION_DAYS"]
|
|
90
139
|
duration = timedelta(days=duration_days)
|
|
91
140
|
|
|
141
|
+
loan_request_offset = current_app.config["ILS_CIRCULATION_LOAN_REQUEST_OFFSET"]
|
|
142
|
+
offset_with_closures = get_offset_duration(
|
|
143
|
+
arrow.get(data["request_start_date"]),
|
|
144
|
+
data["transaction_location_pid"],
|
|
145
|
+
loan_request_offset,
|
|
146
|
+
)
|
|
147
|
+
|
|
92
148
|
if end < start:
|
|
93
149
|
raise ValidationError(
|
|
94
150
|
{
|
|
95
|
-
"request_start_date":
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"
|
|
151
|
+
"request_start_date": (
|
|
152
|
+
"The request start date cannot be after the end date."
|
|
153
|
+
),
|
|
154
|
+
"request_end_date": (
|
|
155
|
+
"The request end date cannot be before the start date."
|
|
156
|
+
),
|
|
99
157
|
}
|
|
100
158
|
)
|
|
101
159
|
elif end - start > duration:
|
|
102
|
-
message = (
|
|
103
|
-
|
|
104
|
-
+ "cannot be longer than {} days.".format(duration_days)
|
|
160
|
+
message = "The request duration cannot be longer than {} days.".format(
|
|
161
|
+
duration_days
|
|
105
162
|
)
|
|
106
163
|
raise ValidationError(
|
|
107
164
|
{
|
|
@@ -109,4 +166,13 @@ class LoanRequestSchemaV1(LoanBaseSchemaV1):
|
|
|
109
166
|
"request_expire_date": [message],
|
|
110
167
|
}
|
|
111
168
|
)
|
|
169
|
+
elif end - start < offset_with_closures:
|
|
170
|
+
message = "The requested start date must be at least {} non-closure days from today.".format(
|
|
171
|
+
loan_request_offset
|
|
172
|
+
)
|
|
173
|
+
raise ValidationError(
|
|
174
|
+
{
|
|
175
|
+
"request_start_date": [message],
|
|
176
|
+
}
|
|
177
|
+
)
|
|
112
178
|
return data
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2019 CERN.
|
|
4
|
+
#
|
|
5
|
+
# invenio-app-ils is free software; you can redistribute it and/or modify
|
|
6
|
+
# it under the terms of the MIT License; see LICENSE file for more details.
|
|
7
|
+
|
|
8
|
+
"""Invenio App ILS circulation Loan Checkout loader JSON schema."""
|
|
9
|
+
|
|
10
|
+
from invenio_circulation.records.loaders.schemas.json import LoanItemPIDSchemaV1
|
|
11
|
+
from marshmallow import fields
|
|
12
|
+
|
|
13
|
+
from .base import LoanBaseSchemaV1
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LoanSelfCheckoutSchemaV1(LoanBaseSchemaV1):
|
|
17
|
+
"""Loan self-checkout schema."""
|
|
18
|
+
|
|
19
|
+
item_pid = fields.Nested(LoanItemPIDSchemaV1, required=True)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
#
|
|
3
|
-
# Copyright (C) 2021 CERN.
|
|
3
|
+
# Copyright (C) 2021-2025 CERN.
|
|
4
4
|
#
|
|
5
5
|
# invenio-app-ils is free software; you can redistribute it and/or modify it
|
|
6
6
|
# under the terms of the MIT License; see LICENSE file for more details.
|
|
@@ -10,10 +10,7 @@
|
|
|
10
10
|
from flask import current_app
|
|
11
11
|
from invenio_records_rest.utils import obj_or_import_string
|
|
12
12
|
|
|
13
|
-
from invenio_app_ils.notifications.api import
|
|
14
|
-
build_common_msg_ctx,
|
|
15
|
-
send_notification,
|
|
16
|
-
)
|
|
13
|
+
from invenio_app_ils.notifications.api import build_common_msg_ctx, send_notification
|
|
17
14
|
from invenio_app_ils.patrons.api import Patron
|
|
18
15
|
|
|
19
16
|
|
|
@@ -36,9 +33,7 @@ def send_loan_notification(loan, action, msg_extra_ctx=None, **kwargs):
|
|
|
36
33
|
msg_ctx.update(build_common_msg_ctx(loan))
|
|
37
34
|
msg_ctx.update(_build_circulation_msg_ctx())
|
|
38
35
|
|
|
39
|
-
func_or_path = current_app.config[
|
|
40
|
-
"ILS_CIRCULATION_NOTIFICATIONS_MSG_BUILDER"
|
|
41
|
-
]
|
|
36
|
+
func_or_path = current_app.config["ILS_CIRCULATION_NOTIFICATIONS_MSG_BUILDER"]
|
|
42
37
|
builder = obj_or_import_string(func_or_path)
|
|
43
38
|
msg = builder(loan, action, msg_ctx, **kwargs)
|
|
44
39
|
|
|
@@ -69,12 +64,22 @@ def send_expiring_loan_reminder_notification(loan, expiring_in_days):
|
|
|
69
64
|
)
|
|
70
65
|
|
|
71
66
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
def send_dates_updated_notification(loan):
|
|
68
|
+
"""Send reminder notification."""
|
|
69
|
+
send_loan_notification(
|
|
70
|
+
action="update_dates",
|
|
71
|
+
loan=loan,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def send_bulk_extend_notification(
|
|
76
|
+
extended_loans,
|
|
77
|
+
not_extended_loans,
|
|
78
|
+
patron_pid,
|
|
79
|
+
action="bulk_extend",
|
|
80
|
+
msg_extra_ctx=None,
|
|
81
|
+
**kwargs
|
|
82
|
+
):
|
|
78
83
|
"""Send notification to patron about bulk extend action."""
|
|
79
84
|
_filter = current_app.config["ILS_CIRCULATION_NOTIFICATIONS_FILTER"]
|
|
80
85
|
if _filter and _filter({}, action, **kwargs) is False:
|
|
@@ -92,13 +97,12 @@ def send_bulk_extend_notification(extended_loans,
|
|
|
92
97
|
context.update(build_common_msg_ctx(loan))
|
|
93
98
|
not_extended_loans_ctx.append(context)
|
|
94
99
|
|
|
95
|
-
msg_ctx.update(
|
|
96
|
-
|
|
100
|
+
msg_ctx.update(
|
|
101
|
+
extended_loans=extended_loans_ctx, not_extended_loans_ctx=not_extended_loans_ctx
|
|
102
|
+
)
|
|
97
103
|
msg_ctx.update(_build_circulation_msg_ctx())
|
|
98
104
|
|
|
99
|
-
func_or_path = current_app.config[
|
|
100
|
-
"ILS_CIRCULATION_NOTIFICATIONS_MSG_BUILDER"
|
|
101
|
-
]
|
|
105
|
+
func_or_path = current_app.config["ILS_CIRCULATION_NOTIFICATIONS_MSG_BUILDER"]
|
|
102
106
|
builder = obj_or_import_string(func_or_path)
|
|
103
107
|
msg = builder({}, action, msg_ctx, **kwargs)
|
|
104
108
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
#
|
|
3
|
-
# Copyright (C) 2021 CERN.
|
|
3
|
+
# Copyright (C) 2021-2025 CERN.
|
|
4
4
|
#
|
|
5
5
|
# invenio-app-ils is free software; you can redistribute it and/or modify it
|
|
6
6
|
# under the terms of the MIT License; see LICENSE file for more details.
|
|
@@ -25,12 +25,14 @@ class NotificationLoanMsg(NotificationMsg):
|
|
|
25
25
|
request="request.html",
|
|
26
26
|
request_no_items="request_no_items.html",
|
|
27
27
|
checkout="checkout.html",
|
|
28
|
+
self_checkout="self_checkout.html",
|
|
28
29
|
checkin="checkin.html",
|
|
29
30
|
extend="extend.html",
|
|
30
31
|
cancel="cancel.html",
|
|
32
|
+
update_dates="update_dates.html",
|
|
31
33
|
overdue_reminder="overdue_reminder.html",
|
|
32
34
|
expiring_reminder="will_expire_in_reminder.html",
|
|
33
|
-
bulk_extend="bulk_extend.html"
|
|
35
|
+
bulk_extend="bulk_extend.html",
|
|
34
36
|
)
|
|
35
37
|
|
|
36
38
|
def __init__(self, loan, action, msg_ctx, **kwargs):
|
|
@@ -67,9 +69,7 @@ class NotificationLoanMsg(NotificationMsg):
|
|
|
67
69
|
"""Get the template filename based on the loan action."""
|
|
68
70
|
new_state = self.loan["state"]
|
|
69
71
|
document_pid = self.loan.get("document_pid")
|
|
70
|
-
is_request =
|
|
71
|
-
new_state in current_app.config["CIRCULATION_STATES_LOAN_REQUEST"]
|
|
72
|
-
)
|
|
72
|
+
is_request = new_state in current_app.config["CIRCULATION_STATES_LOAN_REQUEST"]
|
|
73
73
|
if (
|
|
74
74
|
is_request
|
|
75
75
|
and document_pid
|
|
@@ -112,6 +112,6 @@ class NotificationBulkExtendLoanMsg(NotificationLoanMsg):
|
|
|
112
112
|
|
|
113
113
|
def notification_loan_msg_builder(loan, action, msg_ctx, **kwargs):
|
|
114
114
|
"""Factory builder to create a notification msg."""
|
|
115
|
-
if action ==
|
|
115
|
+
if action == "bulk_extend":
|
|
116
116
|
return NotificationBulkExtendLoanMsg(action, msg_ctx, **kwargs)
|
|
117
117
|
return NotificationLoanMsg(loan, action, msg_ctx, **kwargs)
|
|
@@ -27,8 +27,7 @@ celery_logger = get_task_logger(__name__)
|
|
|
27
27
|
@shared_task
|
|
28
28
|
def send_overdue_loans_notification_reminder():
|
|
29
29
|
"""Send notification message for loans that are overdue every X days."""
|
|
30
|
-
days = current_app.config[
|
|
31
|
-
"ILS_CIRCULATION_NOTIFICATION_OVERDUE_REMINDER_INTERVAL"]
|
|
30
|
+
days = current_app.config["ILS_CIRCULATION_NOTIFICATION_OVERDUE_REMINDER_INTERVAL"]
|
|
32
31
|
for hit in get_all_overdue_loans().scan():
|
|
33
32
|
loan = hit.to_dict()
|
|
34
33
|
days_ago = circulation_overdue_loan_days(loan)
|
|
@@ -10,9 +10,7 @@
|
|
|
10
10
|
from invenio_circulation.proxies import current_circulation
|
|
11
11
|
from invenio_circulation.signals import loan_replace_item, loan_state_changed
|
|
12
12
|
|
|
13
|
-
from invenio_app_ils.circulation.notifications.api import
|
|
14
|
-
send_loan_notification,
|
|
15
|
-
)
|
|
13
|
+
from invenio_app_ils.circulation.notifications.api import send_loan_notification
|
|
16
14
|
from invenio_app_ils.circulation.utils import resolve_item_from_loan
|
|
17
15
|
from invenio_app_ils.ill.api import BORROWING_REQUEST_PID_TYPE
|
|
18
16
|
from invenio_app_ils.ill.proxies import current_ils_ill
|
|
@@ -53,8 +51,7 @@ def index_after_loan_replace_item(_, old_item_pid, new_item_pid):
|
|
|
53
51
|
indexer.index(rec)
|
|
54
52
|
|
|
55
53
|
|
|
56
|
-
def send_notification_after_loan_change(_, initial_loan, loan, trigger,
|
|
57
|
-
**kwargs):
|
|
54
|
+
def send_notification_after_loan_change(_, initial_loan, loan, trigger, **kwargs):
|
|
58
55
|
"""Send email notification when the loan changes."""
|
|
59
56
|
send_notification = kwargs.get("send_notification", True)
|
|
60
57
|
if send_notification:
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
|
|
10
10
|
from datetime import datetime, timedelta
|
|
11
11
|
|
|
12
|
-
from elasticsearch_dsl import A, Q
|
|
13
12
|
from flask import current_app
|
|
14
13
|
from invenio_circulation.proxies import current_circulation
|
|
15
14
|
from invenio_circulation.search.api import search_by_pid
|
|
15
|
+
from invenio_search.engine import dsl
|
|
16
16
|
|
|
17
17
|
from invenio_app_ils.items.api import ITEM_PID_TYPE
|
|
18
18
|
|
|
@@ -21,9 +21,7 @@ def get_loan_next_available_date(document_pid):
|
|
|
21
21
|
"""Return active loans on document sorted by the earliest end date."""
|
|
22
22
|
return search_by_pid(
|
|
23
23
|
document_pid=document_pid,
|
|
24
|
-
filter_states=current_app.config.get(
|
|
25
|
-
"CIRCULATION_STATES_LOAN_ACTIVE", []
|
|
26
|
-
),
|
|
24
|
+
filter_states=current_app.config.get("CIRCULATION_STATES_LOAN_ACTIVE", []),
|
|
27
25
|
sort_by_field="end_date",
|
|
28
26
|
)
|
|
29
27
|
|
|
@@ -32,9 +30,7 @@ def get_active_loan_by_item_pid(item_pid):
|
|
|
32
30
|
"""Return any active loans for the given item."""
|
|
33
31
|
return search_by_pid(
|
|
34
32
|
item_pid=item_pid,
|
|
35
|
-
filter_states=current_app.config.get(
|
|
36
|
-
"CIRCULATION_STATES_LOAN_ACTIVE", []
|
|
37
|
-
),
|
|
33
|
+
filter_states=current_app.config.get("CIRCULATION_STATES_LOAN_ACTIVE", []),
|
|
38
34
|
)
|
|
39
35
|
|
|
40
36
|
|
|
@@ -69,12 +65,19 @@ def get_all_range_expiring_loans_by_patron_pid(expiring_in_days, patron_pid):
|
|
|
69
65
|
)
|
|
70
66
|
|
|
71
67
|
|
|
72
|
-
def
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
def get_all_expiring_or_overdue_loans_by_patron_pid(patron_pid):
|
|
69
|
+
"""Return ILS loans expiring or overdue for given patron."""
|
|
70
|
+
days = current_app.config["ILS_CIRCULATION_LOAN_WILL_EXPIRE_DAYS"]
|
|
71
|
+
future = (datetime.today() + timedelta(days=days)).date()
|
|
72
|
+
states = current_app.config["CIRCULATION_STATES_LOAN_ACTIVE"]
|
|
73
|
+
search_cls = current_circulation.loan_search_cls
|
|
74
|
+
return (
|
|
75
|
+
search_cls()
|
|
76
|
+
.filter("term", patron_pid=patron_pid)
|
|
77
77
|
.filter("term", item_pid__type=ITEM_PID_TYPE)
|
|
78
|
+
.filter("range", end_date=dict(lte="{}||/d".format(future)))
|
|
79
|
+
.filter("terms", state=states)
|
|
80
|
+
)
|
|
78
81
|
|
|
79
82
|
|
|
80
83
|
def get_all_expired_loans():
|
|
@@ -103,9 +106,9 @@ def get_all_overdue_loans():
|
|
|
103
106
|
def get_overdue_loans_by_doc_pid(document_pid):
|
|
104
107
|
"""Return any overdue loans for the given document."""
|
|
105
108
|
states = current_app.config["CIRCULATION_STATES_LOAN_ACTIVE"]
|
|
106
|
-
return search_by_pid(
|
|
107
|
-
|
|
108
|
-
)
|
|
109
|
+
return search_by_pid(document_pid=document_pid, filter_states=states).filter(
|
|
110
|
+
"range", end_date=dict(lt="now/d")
|
|
111
|
+
)
|
|
109
112
|
|
|
110
113
|
|
|
111
114
|
def get_most_loaned_documents(from_date, to_date, bucket_size):
|
|
@@ -124,13 +127,13 @@ def get_most_loaned_documents(from_date, to_date, bucket_size):
|
|
|
124
127
|
search = search_cls().query(
|
|
125
128
|
"bool",
|
|
126
129
|
must=[
|
|
127
|
-
Q("terms", state=states),
|
|
128
|
-
Q("range", start_date=dict(gte=from_date, lte=to_date)),
|
|
130
|
+
dsl.Q("terms", state=states),
|
|
131
|
+
dsl.Q("range", start_date=dict(gte=from_date, lte=to_date)),
|
|
129
132
|
],
|
|
130
133
|
)
|
|
131
134
|
|
|
132
135
|
# Aggregation with sub-aggregation to calculate the extension count sum
|
|
133
|
-
aggs = A("terms", field="document_pid", size=bucket_size)
|
|
136
|
+
aggs = dsl.A("terms", field="document_pid", size=bucket_size)
|
|
134
137
|
aggs = aggs.metric("extensions", "sum", field="extension_count")
|
|
135
138
|
search.aggs.bucket("most_loaned_documents", aggs)
|
|
136
139
|
|
|
@@ -151,7 +154,7 @@ def get_loans_aggregated_by_states(document_pid, states, patron_pid=None):
|
|
|
151
154
|
if patron_pid:
|
|
152
155
|
search = search.filter("term", patron_pid=patron_pid)
|
|
153
156
|
# Aggregation
|
|
154
|
-
aggs = A("terms", field="state")
|
|
157
|
+
aggs = dsl.A("terms", field="state")
|
|
155
158
|
search.aggs.bucket("states", aggs)
|
|
156
159
|
|
|
157
160
|
return search
|
|
@@ -166,9 +169,7 @@ def get_loans_by_patron_pid(patron_pid):
|
|
|
166
169
|
def get_active_loans_by_patron_pid(patron_pid):
|
|
167
170
|
"""Returns a search for all the active loans of a given patron."""
|
|
168
171
|
active_states = current_app.config["CIRCULATION_STATES_LOAN_ACTIVE"]
|
|
169
|
-
search = get_loans_by_patron_pid(patron_pid).filter(
|
|
170
|
-
"terms", state=active_states
|
|
171
|
-
)
|
|
172
|
+
search = get_loans_by_patron_pid(patron_pid).filter("terms", state=active_states)
|
|
172
173
|
return search
|
|
173
174
|
|
|
174
175
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
# under the terms of the MIT License; see LICENSE file for more details.
|
|
7
7
|
|
|
8
8
|
"""Loan serializers."""
|
|
9
|
+
|
|
9
10
|
from invenio_records_rest.serializers.response import search_responsify
|
|
10
11
|
|
|
11
12
|
from invenio_app_ils.records.schemas.json import ILSRecordSchemaJSONV1
|
|
@@ -23,5 +24,4 @@ json_v1 = LoanJSONSerializer(ILSRecordSchemaJSONV1, replace_refs=True)
|
|
|
23
24
|
json_v1_response = record_responsify_no_etag(json_v1, "application/json")
|
|
24
25
|
json_v1_search = search_responsify(json_v1, "application/json")
|
|
25
26
|
|
|
26
|
-
bulk_extend_v1_response = bulk_loan_extend_responsify(json_v1,
|
|
27
|
-
'application/json')
|
|
27
|
+
bulk_extend_v1_response = bulk_loan_extend_responsify(json_v1, "application/json")
|
|
@@ -31,9 +31,7 @@ class LoanCSVSerializer(CSVSerializer):
|
|
|
31
31
|
field_transaction_user(loan["metadata"])
|
|
32
32
|
return loan
|
|
33
33
|
|
|
34
|
-
def transform_search_hit(
|
|
35
|
-
self, pid, record_hit, links_factory=None, **kwargs
|
|
36
|
-
):
|
|
34
|
+
def transform_search_hit(self, pid, record_hit, links_factory=None, **kwargs):
|
|
37
35
|
"""Transform search result hit into an intermediate representation."""
|
|
38
36
|
hit = super().transform_search_hit(
|
|
39
37
|
pid, record_hit, links_factory=links_factory, **kwargs
|
|
@@ -11,6 +11,7 @@ from flask import current_app
|
|
|
11
11
|
from invenio_pidstore.errors import PIDDeletedError, PIDDoesNotExistError
|
|
12
12
|
|
|
13
13
|
from invenio_app_ils.circulation.utils import circulation_overdue_loan_days
|
|
14
|
+
from invenio_app_ils.errors import PatronNotFoundError
|
|
14
15
|
from invenio_app_ils.proxies import current_app_ils
|
|
15
16
|
from invenio_app_ils.records.jsonresolvers.api import pick
|
|
16
17
|
|
|
@@ -19,8 +20,7 @@ def field_is_overdue(metadata):
|
|
|
19
20
|
"""Calculate if the loan is overdue."""
|
|
20
21
|
metadata["is_overdue"] = False
|
|
21
22
|
is_loan_active = (
|
|
22
|
-
metadata["state"]
|
|
23
|
-
in current_app.config["CIRCULATION_STATES_LOAN_ACTIVE"]
|
|
23
|
+
metadata["state"] in current_app.config["CIRCULATION_STATES_LOAN_ACTIVE"]
|
|
24
24
|
)
|
|
25
25
|
if is_loan_active and "end_date" in metadata:
|
|
26
26
|
metadata["is_overdue"] = circulation_overdue_loan_days(metadata) > 0
|
|
@@ -50,13 +50,9 @@ def field_transaction_location(metadata):
|
|
|
50
50
|
return
|
|
51
51
|
Location = current_app_ils.location_record_cls
|
|
52
52
|
try:
|
|
53
|
-
transaction_location = Location.get_record_by_pid(
|
|
54
|
-
transaction_location_pid
|
|
55
|
-
)
|
|
53
|
+
transaction_location = Location.get_record_by_pid(transaction_location_pid)
|
|
56
54
|
except PIDDeletedError:
|
|
57
|
-
metadata["transaction_location"] = {
|
|
58
|
-
"name": "This location was deleted."
|
|
59
|
-
}
|
|
55
|
+
metadata["transaction_location"] = {"name": "This location was deleted."}
|
|
60
56
|
return
|
|
61
57
|
except PIDDoesNotExistError:
|
|
62
58
|
metadata["transaction_location"] = {"name": "Location PID invalid."}
|
|
@@ -72,6 +68,6 @@ def field_transaction_user(metadata):
|
|
|
72
68
|
Patron = current_app_ils.patron_cls
|
|
73
69
|
try:
|
|
74
70
|
transaction_user = Patron.get_patron(transaction_user_pid)
|
|
75
|
-
except PIDDeletedError:
|
|
71
|
+
except (PIDDeletedError, PatronNotFoundError):
|
|
76
72
|
return
|
|
77
73
|
metadata["transaction_user"] = pick(transaction_user, "name")
|
|
@@ -9,9 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
from invenio_records_rest.serializers.json import JSONSerializer
|
|
11
11
|
|
|
12
|
-
from invenio_app_ils.literature.serializers.custom_fields import
|
|
13
|
-
field_cover_metadata,
|
|
14
|
-
)
|
|
12
|
+
from invenio_app_ils.literature.serializers.custom_fields import field_cover_metadata
|
|
15
13
|
|
|
16
14
|
from .custom_fields import (
|
|
17
15
|
field_is_overdue,
|
|
@@ -36,9 +34,7 @@ class LoanJSONSerializer(JSONSerializer):
|
|
|
36
34
|
field_cover_metadata(loan["metadata"].get("document", {}))
|
|
37
35
|
return loan
|
|
38
36
|
|
|
39
|
-
def transform_search_hit(
|
|
40
|
-
self, pid, record_hit, links_factory=None, **kwargs
|
|
41
|
-
):
|
|
37
|
+
def transform_search_hit(self, pid, record_hit, links_factory=None, **kwargs):
|
|
42
38
|
"""Transform search result hit into an intermediate representation."""
|
|
43
39
|
hit = super().transform_search_hit(
|
|
44
40
|
pid, record_hit, links_factory=links_factory, **kwargs
|
|
@@ -6,34 +6,34 @@
|
|
|
6
6
|
# under the terms of the MIT License; see LICENSE file for more details.
|
|
7
7
|
|
|
8
8
|
"""Response serializers for circulation module."""
|
|
9
|
+
|
|
9
10
|
import json
|
|
10
11
|
|
|
11
12
|
from flask import current_app
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
def bulk_loan_extend_responsify(serializer,
|
|
15
|
-
mimetype):
|
|
15
|
+
def bulk_loan_extend_responsify(serializer, mimetype):
|
|
16
16
|
"""Bulk loan extend serializer.
|
|
17
17
|
|
|
18
18
|
:param schema_class: Serializer instance.
|
|
19
19
|
:param mimetype: MIME type of response.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
def view(extended_loans, not_extended_loans,
|
|
23
|
-
code=200, headers=None, **kwargs):
|
|
22
|
+
def view(extended_loans, not_extended_loans, code=200, headers=None, **kwargs):
|
|
24
23
|
"""Generate the response object."""
|
|
25
|
-
response_data = {"extended_loans": [],
|
|
26
|
-
"not_extended_loans": []}
|
|
24
|
+
response_data = {"extended_loans": [], "not_extended_loans": []}
|
|
27
25
|
for loan in extended_loans:
|
|
28
|
-
response_data["extended_loans"]
|
|
29
|
-
|
|
26
|
+
response_data["extended_loans"].append(
|
|
27
|
+
serializer.serialize(loan["pid"], loan)
|
|
28
|
+
)
|
|
30
29
|
for loan in not_extended_loans:
|
|
31
|
-
response_data["not_extended_loans"]
|
|
32
|
-
|
|
30
|
+
response_data["not_extended_loans"].append(
|
|
31
|
+
serializer.serialize(loan["pid"], loan)
|
|
32
|
+
)
|
|
33
33
|
|
|
34
34
|
response = current_app.response_class(
|
|
35
|
-
json.dumps(response_data),
|
|
36
|
-
|
|
35
|
+
json.dumps(response_data), mimetype=mimetype
|
|
36
|
+
)
|
|
37
37
|
response.status_code = code
|
|
38
38
|
|
|
39
39
|
if headers is not None:
|
|
@@ -16,10 +16,7 @@ from invenio_rest import ContentNegotiatedMethodView
|
|
|
16
16
|
|
|
17
17
|
from invenio_app_ils.circulation.stats.api import fetch_most_loaned_documents
|
|
18
18
|
from invenio_app_ils.config import RECORDS_REST_MAX_RESULT_WINDOW
|
|
19
|
-
from invenio_app_ils.documents.api import
|
|
20
|
-
DOCUMENT_PID_FETCHER,
|
|
21
|
-
DOCUMENT_PID_TYPE,
|
|
22
|
-
)
|
|
19
|
+
from invenio_app_ils.documents.api import DOCUMENT_PID_FETCHER, DOCUMENT_PID_TYPE
|
|
23
20
|
from invenio_app_ils.errors import InvalidParameterError
|
|
24
21
|
from invenio_app_ils.permissions import need_permissions
|
|
25
22
|
|
|
@@ -29,13 +26,10 @@ def create_most_loaned_documents_view(blueprint, app):
|
|
|
29
26
|
endpoints = app.config.get("RECORDS_REST_ENDPOINTS", [])
|
|
30
27
|
document_endpoint = endpoints.get(DOCUMENT_PID_TYPE, {})
|
|
31
28
|
default_media_type = document_endpoint.get("default_media_type", "")
|
|
32
|
-
search_serializers_aliases = document_endpoint.get(
|
|
33
|
-
"search_serializers_aliases", ""
|
|
34
|
-
)
|
|
29
|
+
search_serializers_aliases = document_endpoint.get("search_serializers_aliases", "")
|
|
35
30
|
search_serializers = document_endpoint.get("search_serializers")
|
|
36
31
|
serializers = {
|
|
37
|
-
mime: obj_or_import_string(func)
|
|
38
|
-
for mime, func in search_serializers.items()
|
|
32
|
+
mime: obj_or_import_string(func) for mime, func in search_serializers.items()
|
|
39
33
|
}
|
|
40
34
|
|
|
41
35
|
view_class = MostLoanedDocumentsResource
|
|
@@ -54,9 +48,7 @@ def create_most_loaned_documents_view(blueprint, app):
|
|
|
54
48
|
|
|
55
49
|
def create_circulation_stats_blueprint(app):
|
|
56
50
|
"""Add statistics views to the blueprint."""
|
|
57
|
-
blueprint = Blueprint(
|
|
58
|
-
"invenio_app_ils_circulation_stats", __name__, url_prefix=""
|
|
59
|
-
)
|
|
51
|
+
blueprint = Blueprint("invenio_app_ils_circulation_stats", __name__, url_prefix="")
|
|
60
52
|
|
|
61
53
|
create_most_loaned_documents_view(blueprint, app)
|
|
62
54
|
|
|
@@ -134,9 +126,7 @@ class MostLoanedDocumentsResource(ContentNegotiatedMethodView):
|
|
|
134
126
|
"""
|
|
135
127
|
size = self._validate_bucket_size()
|
|
136
128
|
from_date, to_date = self._validate_start_date_range()
|
|
137
|
-
most_loaned_documents = fetch_most_loaned_documents(
|
|
138
|
-
from_date, to_date, size
|
|
139
|
-
)
|
|
129
|
+
most_loaned_documents = fetch_most_loaned_documents(from_date, to_date, size)
|
|
140
130
|
return self.make_response(
|
|
141
131
|
pid_fetcher=current_pidstore.fetchers[DOCUMENT_PID_FETCHER],
|
|
142
132
|
search_result=most_loaned_documents,
|
|
@@ -29,9 +29,7 @@ def cancel_expired_loan_requests():
|
|
|
29
29
|
|
|
30
30
|
for hit in get_all_expired_loans().scan():
|
|
31
31
|
loan = Loan.get_record_by_pid(hit.pid)
|
|
32
|
-
duration_days = current_app.config[
|
|
33
|
-
"ILS_CIRCULATION_LOAN_REQUEST_DURATION_DAYS"
|
|
34
|
-
]
|
|
32
|
+
duration_days = current_app.config["ILS_CIRCULATION_LOAN_REQUEST_DURATION_DAYS"]
|
|
35
33
|
params = deepcopy(loan)
|
|
36
34
|
params.update(
|
|
37
35
|
dict(
|
|
@@ -40,9 +38,7 @@ def cancel_expired_loan_requests():
|
|
|
40
38
|
transaction_user_pid=system_agent_id,
|
|
41
39
|
)
|
|
42
40
|
)
|
|
43
|
-
current_circulation.circulation.trigger(
|
|
44
|
-
loan, **dict(params, trigger="cancel")
|
|
45
|
-
)
|
|
41
|
+
current_circulation.circulation.trigger(loan, **dict(params, trigger="cancel"))
|
|
46
42
|
|
|
47
43
|
loan.commit()
|
|
48
44
|
db.session.commit()
|
invenio_app_ils/circulation/templates/invenio_app_ils_circulation/notifications/self_checkout.html
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{% block title %}
|
|
2
|
+
InvenioILS: loan started for "{{ document.title|safe }}"
|
|
3
|
+
{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block body_plain %}
|
|
6
|
+
Dear {{ patron.name }},
|
|
7
|
+
|
|
8
|
+
your self-checkout loan for "{{ document.full_title }}" <{{ spa_routes.HOST }}{{ spa_routes.PATHS['literature']|format(pid=document.pid) }}> has started.
|
|
9
|
+
|
|
10
|
+
The due date is {{ loan.end_date }}.
|
|
11
|
+
{% endblock %}
|
|
12
|
+
|
|
13
|
+
{% block body_html %}
|
|
14
|
+
Dear {{ patron.name }}, <br/><br/>
|
|
15
|
+
|
|
16
|
+
your self-checkout loan for <a href="{{ spa_routes.HOST }}{{ spa_routes.PATHS['literature']|format(pid=document.pid) }}">"{{ document.full_title }}"</a> has <b>started</b>. <br/><br/>
|
|
17
|
+
|
|
18
|
+
<b>The due date is {{ loan.end_date }}</b>.<br/>
|
|
19
|
+
{% endblock %}
|