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.
Files changed (331) hide show
  1. invenio_app_ils/__init__.py +2 -2
  2. invenio_app_ils/acquisition/api.py +3 -1
  3. invenio_app_ils/acquisition/config.py +10 -21
  4. invenio_app_ils/acquisition/jsonresolvers/order_order_lines.py +1 -0
  5. invenio_app_ils/acquisition/mappings/os-v1/acq_orders/order-v1.0.0.json +364 -0
  6. invenio_app_ils/acquisition/mappings/os-v2/__init__.py +0 -0
  7. invenio_app_ils/acquisition/mappings/os-v2/acq_orders/order-v1.0.0.json +364 -0
  8. invenio_app_ils/acquisition/mappings/v7/acq_orders/order-v1.0.0.json +14 -0
  9. invenio_app_ils/acquisition/search.py +5 -15
  10. invenio_app_ils/assets/semantic-ui/less/theme.config +103 -0
  11. invenio_app_ils/assets/semantic-ui/templates/.gitkeep +0 -0
  12. invenio_app_ils/circulation/api.py +153 -67
  13. invenio_app_ils/circulation/config.py +29 -25
  14. invenio_app_ils/circulation/indexer.py +14 -19
  15. invenio_app_ils/circulation/loaders/__init__.py +2 -0
  16. invenio_app_ils/circulation/loaders/schemas/json/loan_checkout.py +2 -3
  17. invenio_app_ils/circulation/loaders/schemas/json/loan_request.py +82 -16
  18. invenio_app_ils/circulation/loaders/schemas/json/loan_self_checkout.py +19 -0
  19. invenio_app_ils/circulation/notifications/api.py +23 -19
  20. invenio_app_ils/circulation/notifications/messages.py +6 -6
  21. invenio_app_ils/circulation/notifications/tasks.py +1 -2
  22. invenio_app_ils/circulation/receivers.py +2 -5
  23. invenio_app_ils/circulation/search.py +23 -22
  24. invenio_app_ils/circulation/serializers/__init__.py +2 -2
  25. invenio_app_ils/circulation/serializers/csv.py +1 -3
  26. invenio_app_ils/circulation/serializers/custom_fields.py +5 -9
  27. invenio_app_ils/circulation/serializers/json.py +2 -6
  28. invenio_app_ils/circulation/serializers/response.py +12 -12
  29. invenio_app_ils/circulation/stats/views.py +5 -15
  30. invenio_app_ils/circulation/tasks.py +2 -6
  31. invenio_app_ils/circulation/templates/invenio_app_ils_circulation/notifications/self_checkout.html +19 -0
  32. invenio_app_ils/circulation/templates/invenio_app_ils_circulation/notifications/update_dates.html +19 -0
  33. invenio_app_ils/circulation/utils.py +23 -17
  34. invenio_app_ils/circulation/views.py +103 -39
  35. invenio_app_ils/cli.py +220 -260
  36. invenio_app_ils/closures/api.py +72 -7
  37. invenio_app_ils/closures/serializers/__init__.py +16 -0
  38. invenio_app_ils/closures/serializers/response.py +35 -0
  39. invenio_app_ils/closures/serializers/schema.py +28 -0
  40. invenio_app_ils/closures/tasks.py +4 -11
  41. invenio_app_ils/closures/views.py +66 -0
  42. invenio_app_ils/config.py +207 -150
  43. invenio_app_ils/document_requests/api.py +6 -21
  44. invenio_app_ils/document_requests/loaders/__init__.py +4 -12
  45. invenio_app_ils/document_requests/mappings/{v6 → os-v1}/__init__.py +2 -2
  46. invenio_app_ils/document_requests/mappings/os-v1/document_requests/document_request-v1.0.0.json +196 -0
  47. invenio_app_ils/document_requests/mappings/os-v2/__init__.py +8 -0
  48. invenio_app_ils/document_requests/mappings/os-v2/document_requests/document_request-v1.0.0.json +196 -0
  49. invenio_app_ils/document_requests/notifications/api.py +2 -7
  50. invenio_app_ils/document_requests/notifications/messages.py +3 -7
  51. invenio_app_ils/document_requests/search.py +2 -6
  52. invenio_app_ils/document_requests/views.py +4 -10
  53. invenio_app_ils/documents/api.py +19 -25
  54. invenio_app_ils/documents/indexer.py +13 -20
  55. invenio_app_ils/documents/jsonresolvers/document_circulation.py +11 -33
  56. invenio_app_ils/documents/jsonresolvers/document_eitem.py +1 -0
  57. invenio_app_ils/documents/jsonresolvers/document_item.py +8 -9
  58. invenio_app_ils/documents/jsonresolvers/document_stock.py +7 -7
  59. invenio_app_ils/documents/loaders/jsonschemas/document.py +3 -14
  60. invenio_app_ils/documents/mappings/{v6 → os-v1}/__init__.py +1 -1
  61. invenio_app_ils/documents/mappings/os-v1/documents/document-v1.0.0.json +932 -0
  62. invenio_app_ils/documents/mappings/os-v1/documents/document-v2.0.0.json +1066 -0
  63. invenio_app_ils/documents/mappings/os-v2/__init__.py +8 -0
  64. invenio_app_ils/documents/mappings/os-v2/documents/document-v1.0.0.json +932 -0
  65. invenio_app_ils/documents/mappings/os-v2/documents/document-v2.0.0.json +1066 -0
  66. invenio_app_ils/documents/mappings/v7/documents/document-v1.0.0.json +102 -11
  67. invenio_app_ils/documents/mappings/v7/documents/document-v2.0.0.json +1066 -0
  68. invenio_app_ils/documents/schemas/documents/document-v2.0.0.json +732 -0
  69. invenio_app_ils/eitems/api.py +41 -7
  70. invenio_app_ils/eitems/loaders/jsonschemas/eitems.py +6 -6
  71. invenio_app_ils/eitems/mappings/{v6 → os-v1}/__init__.py +1 -1
  72. invenio_app_ils/eitems/mappings/os-v1/eitems/eitem-v1.0.0.json +139 -0
  73. invenio_app_ils/eitems/mappings/os-v1/eitems/eitem-v2.0.0.json +142 -0
  74. invenio_app_ils/eitems/mappings/os-v1/eitems/eitem-v3.0.0.json +179 -0
  75. invenio_app_ils/{series/mappings/v6 → eitems/mappings/os-v2}/__init__.py +1 -1
  76. invenio_app_ils/eitems/mappings/os-v2/eitems/eitem-v1.0.0.json +139 -0
  77. invenio_app_ils/eitems/mappings/os-v2/eitems/eitem-v2.0.0.json +142 -0
  78. invenio_app_ils/eitems/mappings/os-v2/eitems/eitem-v3.0.0.json +179 -0
  79. invenio_app_ils/eitems/mappings/v7/eitems/eitem-v1.0.0.json +12 -2
  80. invenio_app_ils/eitems/mappings/v7/eitems/eitem-v2.0.0.json +142 -0
  81. invenio_app_ils/eitems/mappings/v7/eitems/eitem-v3.0.0.json +179 -0
  82. invenio_app_ils/eitems/schemas/eitems/eitem-v2.0.0.json +120 -0
  83. invenio_app_ils/eitems/schemas/eitems/eitem-v3.0.0.json +120 -0
  84. invenio_app_ils/eitems/search.py +3 -9
  85. invenio_app_ils/errors.py +119 -6
  86. invenio_app_ils/ext.py +15 -18
  87. invenio_app_ils/facets.py +13 -15
  88. invenio_app_ils/files/receivers.py +1 -1
  89. invenio_app_ils/files/views.py +1 -2
  90. invenio_app_ils/ill/api.py +1 -2
  91. invenio_app_ils/ill/config.py +10 -16
  92. invenio_app_ils/ill/jsonresolvers/borrowing_request_document.py +2 -3
  93. invenio_app_ils/ill/jsonresolvers/borrowing_request_patron.py +1 -3
  94. invenio_app_ils/ill/jsonresolvers/borrowing_request_provider.py +1 -3
  95. invenio_app_ils/ill/loaders/__init__.py +3 -9
  96. invenio_app_ils/ill/loaders/jsonschemas/patron_loan_actions.py +1 -8
  97. invenio_app_ils/ill/loaders/jsonschemas/patron_loan_extension_actions.py +3 -8
  98. invenio_app_ils/ill/mappings/{v6 → os-v1}/__init__.py +1 -1
  99. invenio_app_ils/ill/mappings/os-v1/ill_borrowing_requests/borrowing_request-v1.0.0.json +254 -0
  100. invenio_app_ils/{acquisition/mappings/v6 → ill/mappings/os-v2}/__init__.py +1 -1
  101. invenio_app_ils/ill/mappings/os-v2/ill_borrowing_requests/borrowing_request-v1.0.0.json +254 -0
  102. invenio_app_ils/ill/mappings/v7/ill_borrowing_requests/borrowing_request-v1.0.0.json +14 -0
  103. invenio_app_ils/ill/notifications/api.py +1 -4
  104. invenio_app_ils/ill/search.py +3 -9
  105. invenio_app_ils/ill/serializers/__init__.py +1 -3
  106. invenio_app_ils/ill/views.py +2 -4
  107. invenio_app_ils/internal_locations/api.py +1 -4
  108. invenio_app_ils/internal_locations/mappings/{v6 → os-v1}/__init__.py +1 -1
  109. invenio_app_ils/internal_locations/mappings/os-v1/internal_locations/internal_location-v1.0.0.json +108 -0
  110. invenio_app_ils/internal_locations/mappings/os-v2/__init__.py +8 -0
  111. invenio_app_ils/internal_locations/mappings/os-v2/internal_locations/internal_location-v1.0.0.json +108 -0
  112. invenio_app_ils/internal_locations/search.py +1 -3
  113. invenio_app_ils/items/api.py +18 -15
  114. invenio_app_ils/items/indexer.py +1 -3
  115. invenio_app_ils/items/jsonresolvers/item_document.py +1 -1
  116. invenio_app_ils/items/jsonresolvers/item_internal_location.py +2 -6
  117. invenio_app_ils/items/loaders/jsonschemas/items.py +2 -0
  118. {tests/api/circulation → invenio_app_ils/items/mappings/os-v1}/__init__.py +1 -1
  119. invenio_app_ils/items/mappings/os-v1/items/item-v1.0.0.json +285 -0
  120. invenio_app_ils/items/mappings/os-v1/items/item-v2.0.0.json +326 -0
  121. {tests/api/ill → invenio_app_ils/items/mappings/os-v2}/__init__.py +1 -1
  122. invenio_app_ils/items/mappings/os-v2/items/item-v1.0.0.json +285 -0
  123. invenio_app_ils/items/mappings/os-v2/items/item-v2.0.0.json +326 -0
  124. invenio_app_ils/items/mappings/v7/items/item-v1.0.0.json +11 -0
  125. invenio_app_ils/items/mappings/v7/items/item-v2.0.0.json +326 -0
  126. invenio_app_ils/items/schemas/items/item-v1.0.0.json +22 -0
  127. invenio_app_ils/items/schemas/items/item-v2.0.0.json +172 -0
  128. invenio_app_ils/items/search.py +18 -11
  129. invenio_app_ils/items/serializers/item.py +7 -6
  130. invenio_app_ils/literature/api.py +1 -3
  131. invenio_app_ils/literature/search.py +3 -5
  132. invenio_app_ils/literature/serializers/csv.py +1 -3
  133. invenio_app_ils/literature/serializers/json.py +1 -3
  134. invenio_app_ils/locations/api.py +2 -4
  135. invenio_app_ils/locations/indexer.py +3 -9
  136. invenio_app_ils/locations/loaders/__init__.py +1 -3
  137. invenio_app_ils/locations/loaders/jsonschemas/location.py +4 -11
  138. invenio_app_ils/locations/mappings/{v6 → os-v1}/__init__.py +1 -1
  139. invenio_app_ils/locations/mappings/os-v1/locations/location-v1.0.0.json +90 -0
  140. invenio_app_ils/locations/mappings/os-v2/__init__.py +8 -0
  141. invenio_app_ils/locations/mappings/os-v2/locations/location-v1.0.0.json +90 -0
  142. invenio_app_ils/notifications/messages.py +4 -3
  143. invenio_app_ils/notifications/tasks.py +1 -3
  144. invenio_app_ils/notifications/views.py +2 -2
  145. invenio_app_ils/patrons/anonymization.py +53 -32
  146. invenio_app_ils/patrons/api.py +3 -5
  147. invenio_app_ils/patrons/cli.py +1 -2
  148. invenio_app_ils/patrons/indexer.py +4 -13
  149. invenio_app_ils/patrons/mappings/os-v1/__init__.py +8 -0
  150. invenio_app_ils/patrons/mappings/os-v1/patrons/patron-v1.0.0.json +42 -0
  151. invenio_app_ils/patrons/mappings/os-v2/__init__.py +8 -0
  152. invenio_app_ils/patrons/mappings/os-v2/patrons/patron-v1.0.0.json +42 -0
  153. invenio_app_ils/patrons/views.py +4 -14
  154. invenio_app_ils/permissions.py +93 -35
  155. invenio_app_ils/providers/api.py +2 -6
  156. invenio_app_ils/providers/config.py +11 -19
  157. invenio_app_ils/providers/indexer.py +2 -6
  158. invenio_app_ils/providers/mappings/{v6 → os-v1}/__init__.py +1 -1
  159. invenio_app_ils/providers/mappings/os-v1/providers/provider-v1.0.0.json +57 -0
  160. invenio_app_ils/providers/mappings/os-v2/__init__.py +8 -0
  161. invenio_app_ils/providers/mappings/os-v2/providers/provider-v1.0.0.json +57 -0
  162. invenio_app_ils/providers/mappings/v7/__init__.py +1 -1
  163. invenio_app_ils/providers/proxies.py +1 -3
  164. invenio_app_ils/records/api.py +3 -9
  165. invenio_app_ils/records/loaders/schemas/changed_by.py +1 -3
  166. invenio_app_ils/records/loaders/schemas/identifiers.py +23 -0
  167. invenio_app_ils/records/metadata_extensions.py +1 -4
  168. invenio_app_ils/records/permissions.py +8 -2
  169. invenio_app_ils/records/serializers/__init__.py +1 -4
  170. invenio_app_ils/records/views.py +4 -7
  171. invenio_app_ils/records_relations/api.py +11 -34
  172. invenio_app_ils/records_relations/indexer.py +1 -3
  173. invenio_app_ils/records_relations/retriever.py +14 -9
  174. invenio_app_ils/records_relations/views.py +16 -50
  175. invenio_app_ils/relations/api.py +17 -16
  176. invenio_app_ils/search_permissions.py +24 -24
  177. invenio_app_ils/series/api.py +10 -12
  178. invenio_app_ils/series/loaders/jsonschemas/series.py +3 -2
  179. invenio_app_ils/{items/mappings/v6 → series/mappings/os-v1}/__init__.py +1 -1
  180. invenio_app_ils/series/mappings/os-v1/series/series-v1.0.0.json +324 -0
  181. invenio_app_ils/series/mappings/os-v1/series/series-v2.0.0.json +396 -0
  182. {tests/api/acquisition → invenio_app_ils/series/mappings/os-v2}/__init__.py +1 -1
  183. invenio_app_ils/series/mappings/os-v2/series/series-v1.0.0.json +324 -0
  184. invenio_app_ils/series/mappings/os-v2/series/series-v2.0.0.json +396 -0
  185. invenio_app_ils/series/mappings/v7/series/series-v1.0.0.json +35 -3
  186. invenio_app_ils/series/mappings/v7/series/series-v2.0.0.json +396 -0
  187. invenio_app_ils/series/schemas/series/series-v2.0.0.json +354 -0
  188. invenio_app_ils/stats/aggregations/aggr_file_download/os-v1/aggr-file-download-v1.json +60 -0
  189. invenio_app_ils/stats/aggregations/aggr_file_download/os-v2/__init__.py +9 -0
  190. invenio_app_ils/stats/aggregations/aggr_file_download/os-v2/aggr-file-download-v1.json +60 -0
  191. invenio_app_ils/stats/event_builders.py +73 -0
  192. invenio_app_ils/stats/file_download/os-v1/file-download-v1.json +72 -0
  193. invenio_app_ils/stats/file_download/os-v2/__init__.py +9 -0
  194. invenio_app_ils/stats/file_download/os-v2/file-download-v1.json +72 -0
  195. invenio_app_ils/stats/processors.py +30 -0
  196. invenio_app_ils/stats/templates/aggregations/__init__.py +8 -0
  197. invenio_app_ils/stats/templates/aggregations/ils_record_changes/__init__.py +8 -0
  198. invenio_app_ils/stats/templates/aggregations/ils_record_changes/os-v2/__init__.py +8 -0
  199. invenio_app_ils/stats/templates/aggregations/ils_record_changes/os-v2/aggr-ils-record-changes-v1.json +41 -0
  200. {tests → invenio_app_ils/stats/templates/events}/__init__.py +2 -2
  201. invenio_app_ils/stats/templates/events/ils_record_changes/__init__.py +8 -0
  202. invenio_app_ils/stats/templates/events/ils_record_changes/os-v2/__init__.py +8 -0
  203. invenio_app_ils/stats/templates/events/ils_record_changes/os-v2/ils-record-changes-v1.json +41 -0
  204. invenio_app_ils/templates/logged_out.html +12 -0
  205. invenio_app_ils/views.py +18 -4
  206. invenio_app_ils/vocabularies/api.py +1 -1
  207. invenio_app_ils/vocabularies/cli.py +6 -18
  208. invenio_app_ils/vocabularies/data/acq_order_line_payment_modes.json +5 -0
  209. invenio_app_ils/vocabularies/data/identifier_schemes.json +5 -0
  210. invenio_app_ils/vocabularies/indexer.py +1 -4
  211. invenio_app_ils/vocabularies/jsonresolvers/licenses.py +2 -11
  212. invenio_app_ils/vocabularies/mappings/os-v1/__init__.py +8 -0
  213. invenio_app_ils/vocabularies/mappings/os-v1/vocabularies/vocabulary-v1.0.0.json +23 -0
  214. invenio_app_ils/vocabularies/mappings/os-v2/__init__.py +8 -0
  215. invenio_app_ils/vocabularies/mappings/os-v2/vocabularies/vocabulary-v1.0.0.json +23 -0
  216. invenio_app_ils/vocabularies/sources/base.py +1 -3
  217. invenio_app_ils/webpack.py +27 -0
  218. invenio_app_ils-6.1.0.dist-info/METADATA +627 -0
  219. {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info}/RECORD +227 -249
  220. {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info}/WHEEL +1 -1
  221. {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info}/entry_points.txt +9 -5
  222. {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info}/top_level.txt +0 -1
  223. invenio_app_ils/acquisition/mappings/v6/acq_orders/order-v1.0.0.json +0 -352
  224. invenio_app_ils/document_requests/mappings/v6/document_requests/document_request-v1.0.0.json +0 -199
  225. invenio_app_ils/documents/mappings/v6/documents/document-v1.0.0.json +0 -843
  226. invenio_app_ils/eitems/mappings/v6/eitems/eitem-v1.0.0.json +0 -131
  227. invenio_app_ils/ill/mappings/v6/ill_borrowing_requests/borrowing_request-v1.0.0.json +0 -242
  228. invenio_app_ils/internal_locations/mappings/v6/internal_locations/internal_location-v1.0.0.json +0 -110
  229. invenio_app_ils/items/mappings/v6/items/item-v1.0.0.json +0 -276
  230. invenio_app_ils/locations/mappings/v6/locations/location-v1.0.0.json +0 -92
  231. invenio_app_ils/notifications/admin.py +0 -57
  232. invenio_app_ils/patrons/mappings/v6/__init__.py +0 -8
  233. invenio_app_ils/patrons/mappings/v6/patrons/patron-v1.0.0.json +0 -44
  234. invenio_app_ils/providers/mappings/v6/providers/provider-v1.0.0.json +0 -59
  235. invenio_app_ils/series/mappings/v6/series/series-v1.0.0.json +0 -298
  236. invenio_app_ils/stats/aggregations/aggr_file_download/v6/aggr-file-download-v1.json +0 -59
  237. invenio_app_ils/stats/file_download/v6/file-download-v1.json +0 -74
  238. invenio_app_ils/version.py +0 -14
  239. invenio_app_ils/vocabularies/mappings/v6/__init__.py +0 -8
  240. invenio_app_ils/vocabularies/mappings/v6/vocabularies/vocabulary-v1.0.0.json +0 -25
  241. invenio_app_ils-1.0.0a54.dist-info/METADATA +0 -95
  242. tests/api/__init__.py +0 -8
  243. tests/api/acquisition/test_acq_orders_crud.py +0 -102
  244. tests/api/acquisition/test_acq_orders_permissions.py +0 -104
  245. tests/api/acquisition/test_acq_providers_permissions.py +0 -83
  246. tests/api/circulation/test_expired_loans.py +0 -88
  247. tests/api/circulation/test_loan_checkout.py +0 -216
  248. tests/api/circulation/test_loan_default_durations.py +0 -57
  249. tests/api/circulation/test_loan_document_resolver.py +0 -18
  250. tests/api/circulation/test_loan_extend.py +0 -132
  251. tests/api/circulation/test_loan_item_permissions.py +0 -139
  252. tests/api/circulation/test_loan_item_resolver.py +0 -26
  253. tests/api/circulation/test_loan_list_permissions.py +0 -104
  254. tests/api/circulation/test_loan_patron_resolver.py +0 -38
  255. tests/api/circulation/test_loan_request.py +0 -234
  256. tests/api/circulation/test_loan_update.py +0 -150
  257. tests/api/circulation/test_notifications.py +0 -229
  258. tests/api/conftest.py +0 -236
  259. tests/api/document_requests/__init__.py +0 -8
  260. tests/api/document_requests/test_document_requests.py +0 -131
  261. tests/api/document_requests/test_document_requests_permissions.py +0 -177
  262. tests/api/document_requests/test_notifications_filter.py +0 -36
  263. tests/api/ill/test_ill_brw_crud.py +0 -84
  264. tests/api/ill/test_ill_brw_reqs_patron_loan_create_action.py +0 -207
  265. tests/api/ill/test_ill_brw_reqs_patron_loan_extension_actions.py +0 -298
  266. tests/api/ill/test_ill_brw_reqs_permissions.py +0 -169
  267. tests/api/ill/test_ill_providers_permissions.py +0 -82
  268. tests/api/ils/__init__.py +0 -8
  269. tests/api/ils/documents/__init__.py +0 -8
  270. tests/api/ils/documents/test_document_crud.py +0 -57
  271. tests/api/ils/documents/test_document_permissions.py +0 -106
  272. tests/api/ils/documents/test_document_resolvers.py +0 -35
  273. tests/api/ils/eitems/__init__.py +0 -8
  274. tests/api/ils/eitems/test_eitems_crud.py +0 -41
  275. tests/api/ils/eitems/test_eitems_permissions.py +0 -84
  276. tests/api/ils/eitems/test_files.py +0 -172
  277. tests/api/ils/items/__init__.py +0 -8
  278. tests/api/ils/items/test_apis.py +0 -43
  279. tests/api/ils/items/test_items_crud.py +0 -60
  280. tests/api/ils/items/test_items_permissions.py +0 -107
  281. tests/api/ils/items/test_items_update.py +0 -47
  282. tests/api/ils/records_relations/__init__.py +0 -8
  283. tests/api/ils/records_relations/helpers.py +0 -115
  284. tests/api/ils/records_relations/test_records_relations_parentchild.py +0 -560
  285. tests/api/ils/records_relations/test_records_relations_sequence.py +0 -302
  286. tests/api/ils/records_relations/test_records_relations_siblings.py +0 -678
  287. tests/api/ils/series/__init__.py +0 -8
  288. tests/api/ils/series/test_series_permissions.py +0 -95
  289. tests/api/ils/test_anonymization.py +0 -189
  290. tests/api/ils/test_apis.py +0 -76
  291. tests/api/ils/test_closures.py +0 -324
  292. tests/api/ils/test_errors.py +0 -126
  293. tests/api/ils/test_facets.py +0 -84
  294. tests/api/ils/test_internal_locations.py +0 -96
  295. tests/api/ils/test_loaders.py +0 -55
  296. tests/api/ils/test_metadata_extensions.py +0 -205
  297. tests/api/ils/test_notifications.py +0 -183
  298. tests/api/ils/test_notifications_mails.py +0 -39
  299. tests/api/ils/test_notifications_permissions.py +0 -55
  300. tests/api/ils/test_patrons.py +0 -106
  301. tests/api/ils/test_record_delete.py +0 -46
  302. tests/api/ils/test_record_permissions.py +0 -135
  303. tests/api/ils/test_resolvers.py +0 -207
  304. tests/api/ils/test_stats.py +0 -160
  305. tests/api/ils/test_tasks.py +0 -211
  306. tests/api/ils/test_vocabularies.py +0 -35
  307. tests/conftest.py +0 -123
  308. tests/data/acq_orders.json +0 -89
  309. tests/data/acq_providers.json +0 -12
  310. tests/data/document_requests.json +0 -77
  311. tests/data/documents.json +0 -237
  312. tests/data/eitems.json +0 -66
  313. tests/data/ill_borrowing_requests.json +0 -77
  314. tests/data/ill_providers.json +0 -12
  315. tests/data/internal_locations.json +0 -22
  316. tests/data/items.json +0 -271
  317. tests/data/loans.json +0 -133
  318. tests/data/loans_most_loaned.json +0 -128
  319. tests/data/locations.json +0 -20
  320. tests/data/series.json +0 -33
  321. tests/helpers.py +0 -104
  322. tests/templates/notifications/title_body.html +0 -8
  323. tests/templates/notifications/title_body_html.html +0 -13
  324. tests/templates/notifications/title_body_html_ctx.html +0 -13
  325. tests/templates/notifications/title_only.html +0 -3
  326. tests/test_version.py +0 -17
  327. /tests/templates/notifications/blank.html → /invenio_app_ils/acquisition/mappings/os-v1/__init__.py +0 -0
  328. /invenio_app_ils/stats/aggregations/aggr_file_download/{v6 → os-v1}/__init__.py +0 -0
  329. /invenio_app_ils/stats/file_download/{v6 → os-v1}/__init__.py +0 -0
  330. {invenio_app_ils-1.0.0a54.dist-info → invenio_app_ils-6.1.0.dist-info/licenses}/AUTHORS.rst +0 -0
  331. {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
 
@@ -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 backoffice_permission
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 backoffice_permission().can():
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
 
@@ -17,7 +17,12 @@ from sqlalchemy import and_, or_
17
17
  from invenio_app_ils.errors import RecordRelationsError
18
18
 
19
19
  ILS_RELATION_TYPE = namedtuple(
20
- "IlsRelationType", RelationType._fields + ("relation_class",)
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 backoffice_permission
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 backoffice_permission().allows(g.identity):
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 query_parser(search, qstr=None):
67
- """Default parser that uses the Q() from elasticsearch_dsl."""
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
- return Q("query_string", query=qstr, **extra_params)
78
- return Q()
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 = query_parser(search, qstr=query_string)
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 backoffice_permission().allows(
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)
@@ -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-v1.0.0.json"
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
- self.pid)
85
- related_serial_volumes = pcr_serial.get_children_of(
86
- self.pid)
87
- for child_pid in related_serial_volumes + \
88
- related_multipart_volumes:
89
- related_refs.add("{pid_value}:{pid_type}".format(
90
- pid_value=child_pid.pid_value, pid_type=child_pid.pid_type))
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(