folio-migration-tools 1.9.0rc3__tar.gz → 1.9.0rc4__tar.gz

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 (66) hide show
  1. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/PKG-INFO +1 -1
  2. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/pyproject.toml +5 -1
  3. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/order_mapper.py +8 -4
  4. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +3 -2
  5. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/batch_poster.py +86 -8
  6. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/courses_migrator.py +54 -8
  7. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/holdings_csv_transformer.py +102 -14
  8. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/items_transformer.py +133 -20
  9. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/loans_migrator.py +61 -9
  10. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/migration_task_base.py +104 -11
  11. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/orders_transformer.py +107 -14
  12. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/organization_transformer.py +79 -14
  13. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/requests_migrator.py +56 -7
  14. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/reserves_migrator.py +26 -4
  15. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/user_transformer.py +88 -18
  16. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/transaction_migration/legacy_loan.py +13 -1
  17. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/transaction_migration/legacy_reserve.py +3 -5
  18. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/LICENSE +0 -0
  19. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/README.md +0 -0
  20. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/__init__.py +0 -0
  21. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/__main__.py +0 -0
  22. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/circulation_helper.py +0 -0
  23. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/colors.py +0 -0
  24. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/config_file_load.py +0 -0
  25. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/custom_dict.py +0 -0
  26. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/custom_exceptions.py +0 -0
  27. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/extradata_writer.py +0 -0
  28. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/folder_structure.py +0 -0
  29. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/helper.py +0 -0
  30. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/holdings_helper.py +0 -0
  31. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/i18n_config.py +0 -0
  32. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/library_configuration.py +0 -0
  33. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapper_base.py +0 -0
  34. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/__init__.py +0 -0
  35. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/courses_mapper.py +0 -0
  36. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/holdings_mapper.py +0 -0
  37. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/item_mapper.py +0 -0
  38. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +0 -0
  39. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +0 -0
  40. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/notes_mapper.py +0 -0
  41. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/organization_mapper.py +0 -0
  42. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/ref_data_mapping.py +0 -0
  43. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/mapping_file_transformation/user_mapper.py +0 -0
  44. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/__init__.py +0 -0
  45. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/conditions.py +0 -0
  46. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +0 -0
  47. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/hrid_handler.py +0 -0
  48. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/loc_language_codes.xml +0 -0
  49. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/marc_file_processor.py +0 -0
  50. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py +0 -0
  51. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +0 -0
  52. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +0 -0
  53. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +0 -0
  54. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_report.py +0 -0
  55. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/__init__.py +0 -0
  56. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/authority_transformer.py +0 -0
  57. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/bibs_transformer.py +0 -0
  58. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/holdings_marc_transformer.py +0 -0
  59. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +0 -0
  60. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/task_configuration.py +0 -0
  61. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/test_infrastructure/__init__.py +0 -0
  62. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/test_infrastructure/mocked_classes.py +0 -0
  63. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/transaction_migration/__init__.py +0 -0
  64. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/transaction_migration/legacy_request.py +0 -0
  65. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/transaction_migration/transaction_result.py +0 -0
  66. {folio_migration_tools-1.9.0rc3 → folio_migration_tools-1.9.0rc4}/src/folio_migration_tools/translations/en.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: folio_migration_tools
3
- Version: 1.9.0rc3
3
+ Version: 1.9.0rc4
4
4
  Summary: A tool allowing you to migrate data from legacy ILS:s (Library systems) into FOLIO LSP
5
5
  License: MIT
6
6
  Keywords: FOLIO,ILS,LSP,Library Systems,MARC21,Library data
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "folio_migration_tools"
3
- version = "1.9.0rc3"
3
+ version = "1.9.0rc4"
4
4
  description = "A tool allowing you to migrate data from legacy ILS:s (Library systems) into FOLIO LSP"
5
5
  authors = [
6
6
  {name = "Theodor Tolstoy", email = "github.teddes@tolstoy.se"},
@@ -77,6 +77,10 @@ pandas = "^1.5.3"
77
77
  types-requests = "^2.28.11.17"
78
78
  types-python-dateutil = "^2.8.19.11"
79
79
  ipykernel = "^6.29.5"
80
+ pytest-asyncio = "^0.23.0"
80
81
 
81
82
  [tool.poetry.extras]
82
83
  docs = ["m2r", "sphinx", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "toml"]
84
+
85
+ [tool.poetry.requires-plugins]
86
+ poetry-plugin-export = ">=1.8"
@@ -25,7 +25,6 @@ from folio_migration_tools.mapping_file_transformation.ref_data_mapping import (
25
25
 
26
26
 
27
27
  class CompositeOrderMapper(MappingFileMapperBase):
28
- VALID_PO_NUMBER_CHARACTERS = r"[A-Za-z0-9]"
29
28
 
30
29
  def __init__(
31
30
  self,
@@ -270,9 +269,9 @@ class CompositeOrderMapper(MappingFileMapperBase):
270
269
  and "$ref" in object_schema
271
270
  and object_schema["type"] == "object"
272
271
  ):
273
- submodule_path["properties"] = CompositeOrderMapper.inject_schema_by_ref(
272
+ object_schema["properties"] = CompositeOrderMapper.inject_schema_by_ref(
274
273
  submodule_path, github_headers, object_schema
275
- ).get("properties")
274
+ ).get("properties", {})#TODO: Investigate new CustomFields schema and figure out how to actually handle it
276
275
 
277
276
  for property_name_level1, property_level1 in object_schema.get(
278
277
  "properties", {}
@@ -385,7 +384,7 @@ class CompositeOrderMapper(MappingFileMapperBase):
385
384
  index_or_id: str,
386
385
  po_number: str,
387
386
  ):
388
- if re.sub(self.VALID_PO_NUMBER_CHARACTERS, "", po_number):
387
+ if not self.is_valid_po_number(po_number):
389
388
  self.migration_report.add(
390
389
  "PurchaseOrderVendorLinking",
391
390
  i18n.t("RECORD FAILED: PO number has invalid character(s)"),
@@ -396,6 +395,11 @@ class CompositeOrderMapper(MappingFileMapperBase):
396
395
  po_number,
397
396
  )
398
397
 
398
+ @staticmethod
399
+ def is_valid_po_number(po_number: str) -> bool:
400
+ valid_po_number_characters = r"[A-Za-z0-9]"
401
+ return re.sub(valid_po_number_characters, "", po_number) == ""
402
+
399
403
  def get_matching_record_from_folio(
400
404
  self,
401
405
  index_or_id,
@@ -69,7 +69,6 @@ class RulesMapperHoldings(RulesMapperBase):
69
69
  logging.info("Fetching mapping rules from the tenant")
70
70
  rules_endpoint = "/mapping-rules/marc-holdings"
71
71
  self.mappings = self.folio_client.folio_get_single_object(rules_endpoint)
72
- self.fix_853_bug_in_rules()
73
72
 
74
73
  def fix_853_bug_in_rules(self):
75
74
  f852_mappings = self.mappings["852"]
@@ -90,9 +89,10 @@ class RulesMapperHoldings(RulesMapperBase):
90
89
  )
91
90
  self.mappings["852"] = new_852_mapping
92
91
 
93
- def integrate_supplemental_mfhd_mappings(self, new_rules):
92
+ def integrate_supplemental_mfhd_mappings(self, new_rules={}):
94
93
  try:
95
94
  self.mappings.update(new_rules)
95
+ self.fix_853_bug_in_rules()
96
96
  except Exception as e:
97
97
  raise TransformationProcessError(
98
98
  "",
@@ -102,6 +102,7 @@ class RulesMapperHoldings(RulesMapperBase):
102
102
 
103
103
  def prep_852_notes(self, marc_record: Record):
104
104
  for field in marc_record.get_fields("852"):
105
+ field.subfields.sort(key=lambda x: x[0])
105
106
  new_952 = Field(
106
107
  tag="952",
107
108
  indicators=["f", "f"],
@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  import copy
2
3
  import json
3
4
  import logging
@@ -248,22 +249,84 @@ class BatchPoster(MigrationTaskBase):
248
249
  if self.task_configuration.object_type == "SRS":
249
250
  self.commit_snapshot()
250
251
 
252
+ @staticmethod
253
+ def set_consortium_source(json_rec):
254
+ if json_rec['source'] == 'MARC':
255
+ json_rec['source'] = 'CONSORTIUM-MARC'
256
+ elif json_rec['source'] == 'FOLIO':
257
+ json_rec['source'] = 'CONSORTIUM-FOLIO'
258
+
259
+ def set_version(self, batch, query_api, object_type) -> None:
260
+ """
261
+ Synchronous wrapper for set_version_async
262
+ """
263
+ loop = asyncio.get_event_loop()
264
+ if loop.is_running():
265
+ loop.run_until_complete(self.set_version_async(batch, query_api, object_type))
266
+ else:
267
+ asyncio.run(self.set_version_async(batch, query_api, object_type))
268
+
269
+ async def set_version_async(self, batch, query_api, object_type) -> None:
270
+ """
271
+ Fetches the current version of the records in the batch, if the record exists in FOLIO
272
+
273
+ Args:
274
+ batch (list): List of records to fetch versions for
275
+ query_api (str): The query API endpoint to use
276
+ object_type (str): The key in the API response that contains the records
277
+
278
+ Returns:
279
+ None
280
+ """
281
+ fetch_batch_size = 90
282
+ fetch_tasks = []
283
+ updates = {}
284
+ async with httpx.AsyncClient(base_url=self.folio_client.okapi_url) as client:
285
+ for i in range(0, len(batch), fetch_batch_size):
286
+ batch_slice = batch[i:i + fetch_batch_size]
287
+ fetch_tasks.append(
288
+ client.get(
289
+ query_api,
290
+ params={
291
+ "query": f"id==({' OR '.join([record['id'] for record in batch_slice if 'id' in record])})",
292
+ "limit": fetch_batch_size
293
+ },
294
+ headers=self.folio_client.okapi_headers
295
+ )
296
+ )
297
+ responses = await asyncio.gather(*fetch_tasks)
298
+
299
+ for response in responses:
300
+ if response.status_code == 200:
301
+ response_json = await response.json()
302
+ for record in response_json[object_type]:
303
+ updates[record["id"]] = {
304
+ "_version": record["_version"],
305
+ }
306
+ if "status" in record:
307
+ updates[record["id"]]["status"] = record["status"]
308
+ else:
309
+ logging.error(
310
+ "Failed to fetch current records. HTTP %s\t%s",
311
+ response.status_code,
312
+ response.text,
313
+ )
314
+ for record in batch:
315
+ if record["id"] in updates:
316
+ record.update(updates[record["id"]])
317
+
251
318
  def post_record_batch(self, batch, failed_recs_file, row):
252
319
  json_rec = json.loads(row.split("\t")[-1])
253
- if (
254
- self.task_configuration.object_type in ["Instances", "Holdings", "Items"]
255
- and not self.task_configuration.use_safe_inventory_endpoints
256
- ):
257
- self.migration_report.add_general_statistics(
258
- i18n.t("Set _version to -1 to enable upsert")
259
- )
260
- json_rec["_version"] = -1
320
+ if self.task_configuration.object_type == "ShadowInstances":
321
+ self.set_consortium_source(json_rec)
261
322
  if self.task_configuration.object_type == "SRS":
262
323
  json_rec["snapshotId"] = self.snapshot_id
263
324
  if self.processed == 1:
264
325
  logging.info(json.dumps(json_rec, indent=True))
265
326
  batch.append(json_rec)
266
327
  if len(batch) == int(self.batch_size):
328
+ if self.query_params.get("upsert", False) and self.api_info.get("query_endpoint", ""):
329
+ self.set_version(batch, self.api_info['query_endpoint'], self.api_info['object_name'])
267
330
  self.post_batch(batch, failed_recs_file, self.processed)
268
331
  batch = []
269
332
  return batch
@@ -648,6 +711,7 @@ def get_api_info(object_type: str, use_safe: bool = True):
648
711
  if use_safe
649
712
  else "/item-storage/batch/synchronous-unsafe"
650
713
  ),
714
+ "query_endpoint": "/item-storage/items",
651
715
  "is_batch": True,
652
716
  "total_records": False,
653
717
  "addSnapshotId": False,
@@ -660,12 +724,26 @@ def get_api_info(object_type: str, use_safe: bool = True):
660
724
  if use_safe
661
725
  else "/holdings-storage/batch/synchronous-unsafe"
662
726
  ),
727
+ "query_endpoint": "/holdings-storage/holdings",
663
728
  "is_batch": True,
664
729
  "total_records": False,
665
730
  "addSnapshotId": False,
666
731
  "supports_upsert": True,
667
732
  },
668
733
  "Instances": {
734
+ "object_name": "instances",
735
+ "api_endpoint": (
736
+ "/instance-storage/batch/synchronous"
737
+ if use_safe
738
+ else "/instance-storage/batch/synchronous-unsafe"
739
+ ),
740
+ "query_endpoint": "/instance-storage/instances",
741
+ "is_batch": True,
742
+ "total_records": False,
743
+ "addSnapshotId": False,
744
+ "supports_upsert": True,
745
+ },
746
+ "ShadowInstances": {
669
747
  "object_name": "instances",
670
748
  "api_endpoint": (
671
749
  "/instance-storage/batch/synchronous"
@@ -4,7 +4,8 @@ import logging
4
4
  import sys
5
5
  import time
6
6
  import traceback
7
- from typing import Optional
7
+ from typing import Optional, Annotated
8
+ from pydantic import Field
8
9
 
9
10
  import i18n
10
11
  from folio_uuid.folio_namespaces import FOLIONamespaces
@@ -29,13 +30,58 @@ from folio_migration_tools.task_configuration import AbstractTaskConfiguration
29
30
 
30
31
  class CoursesMigrator(MigrationTaskBase):
31
32
  class TaskConfiguration(AbstractTaskConfiguration):
32
- name: str
33
- composite_course_map_path: str
34
- migration_task_type: str
35
- courses_file: FileDefinition
36
- terms_map_path: str
37
- departments_map_path: str
38
- look_up_instructor: Optional[bool] = False
33
+ name: Annotated[
34
+ str,
35
+ Field(
36
+ title="Task name",
37
+ description="The name of the task",
38
+ ),
39
+ ]
40
+ composite_course_map_path: Annotated[
41
+ str,
42
+ Field(
43
+ title="Composite course map path",
44
+ description="Path to the composite course map file",
45
+ ),
46
+ ]
47
+ migration_task_type: Annotated[
48
+ str,
49
+ Field(
50
+ title="Migration task type",
51
+ description="Type of migration task",
52
+ ),
53
+ ]
54
+ courses_file: Annotated[
55
+ FileDefinition,
56
+ Field(
57
+ title="Courses file",
58
+ description="File containing course data",
59
+ ),
60
+ ]
61
+ terms_map_path: Annotated[
62
+ str,
63
+ Field(
64
+ title="Terms map path",
65
+ description="Path to the terms map file",
66
+ ),
67
+ ]
68
+ departments_map_path: Annotated[
69
+ str,
70
+ Field(
71
+ title="Departments map path",
72
+ description="Path to the departments map file",
73
+ ),
74
+ ]
75
+ look_up_instructor: Annotated[
76
+ Optional[bool],
77
+ Field(
78
+ title="Look up instructor",
79
+ description=(
80
+ "Flag to indicate whether to look up instructors. "
81
+ "By default is False."
82
+ ),
83
+ ),
84
+ ] = False
39
85
 
40
86
  @staticmethod
41
87
  def get_object_type() -> FOLIONamespaces:
@@ -39,37 +39,125 @@ csv.register_dialect("tsv", delimiter="\t")
39
39
 
40
40
  class HoldingsCsvTransformer(MigrationTaskBase):
41
41
  class TaskConfiguration(AbstractTaskConfiguration):
42
- name: str
43
- migration_task_type: str
44
- hrid_handling: HridHandling
45
- files: List[FileDefinition]
46
- holdings_map_file_name: str
47
- location_map_file_name: str
48
- default_call_number_type_name: str
49
- previously_generated_holdings_files: Optional[list[str]] = []
50
- fallback_holdings_type_id: str
42
+ name: Annotated[
43
+ str,
44
+ Field(
45
+ title="Task name",
46
+ description="Name of the task",
47
+ ),
48
+ ]
49
+ migration_task_type: Annotated[
50
+ str,
51
+ Field(
52
+ title="Migration task type",
53
+ description="Type of migration task",
54
+ ),
55
+ ]
56
+ hrid_handling: Annotated[
57
+ HridHandling,
58
+ Field(
59
+ title="HRID handling",
60
+ description=(
61
+ "Determining how the HRID generation "
62
+ "should be handled."
63
+ ),
64
+ ),
65
+ ]
66
+ files: Annotated[
67
+ List[FileDefinition],
68
+ Field(
69
+ title="Files",
70
+ description="List of files",
71
+ ),
72
+ ]
73
+ holdings_map_file_name: Annotated[
74
+ str,
75
+ Field(
76
+ title="Holdings map file name",
77
+ description="File name for holdings map",
78
+ ),
79
+ ]
80
+ location_map_file_name: Annotated[
81
+ str,
82
+ Field(
83
+ title="Location map file name",
84
+ description="File name for location map",
85
+ ),
86
+ ]
87
+ default_call_number_type_name: Annotated[
88
+ str,
89
+ Field(
90
+ title="Default call number type name",
91
+ description="Default name for call number type",
92
+ ),
93
+ ]
94
+ previously_generated_holdings_files: Annotated[
95
+ Optional[list[str]],
96
+ Field(
97
+ title="Previously generated holdings files",
98
+ description=(
99
+ "List of previously generated holdings files. "
100
+ "By default is empty list."
101
+ ),
102
+ ),
103
+ ] = []
104
+ fallback_holdings_type_id: Annotated[
105
+ str,
106
+ Field(
107
+ title="Fallback holdings type ID",
108
+ description="ID for fallback holdings type",
109
+ ),
110
+ ]
51
111
  holdings_type_uuid_for_boundwiths: Annotated[
52
112
  str,
53
113
  Field(
54
114
  title="Holdings Type for Boundwith Holdings",
55
115
  description=(
56
116
  "UUID for a Holdings type (set in Settings->Inventory) "
57
- "for Bound-with Holdings)"
117
+ "for Bound-with Holdings. Default is empty string."
58
118
  ),
59
119
  ),
60
120
  ] = ""
61
- call_number_type_map_file_name: Optional[str]
62
- holdings_merge_criteria: Optional[list[str]] = [
121
+ call_number_type_map_file_name: Annotated[
122
+ Optional[str],
123
+ Field(
124
+ title="Call number type map file name",
125
+ description="File name for call number type map",
126
+ ),
127
+ ]
128
+ holdings_merge_criteria: Annotated[
129
+ Optional[list[str]],
130
+ Field(
131
+ title="Holdings merge criteria",
132
+ description=(
133
+ "List of holdings merge criteria. "
134
+ "Default value is "
135
+ "['instanceId', 'permanentLocationId', 'callNumber']."
136
+ ),
137
+ ),
138
+ ] = [
63
139
  "instanceId",
64
140
  "permanentLocationId",
65
141
  "callNumber",
66
142
  ]
67
- reset_hrid_settings: Optional[bool] = False
143
+ reset_hrid_settings: Annotated[
144
+ Optional[bool],
145
+ Field(
146
+ title="Reset HRID settings",
147
+ description=(
148
+ "At the end of the run reset "
149
+ "FOLIO with the HRID settings. Default is FALSE."
150
+ ),
151
+ ),
152
+ ] = False
68
153
  update_hrid_settings: Annotated[
69
154
  bool,
70
155
  Field(
71
156
  title="Update HRID settings",
72
- description="At the end of the run, update FOLIO with the HRID settings",
157
+ description=(
158
+ "At the end of the run update "
159
+ "FOLIO with the HRID settings. Default is TRUE."
160
+ ),
73
161
  ),
74
162
  ] = True
75
163
 
@@ -1,4 +1,3 @@
1
- '''Main "script."'''
2
1
  import csv
3
2
  import ctypes
4
3
  import json
@@ -36,26 +35,136 @@ csv.field_size_limit(int(ctypes.c_ulong(-1).value // 2))
36
35
 
37
36
  class ItemsTransformer(MigrationTaskBase):
38
37
  class TaskConfiguration(AbstractTaskConfiguration):
39
- name: str
40
- migration_task_type: str
41
- hrid_handling: HridHandling
42
- files: List[FileDefinition]
43
- items_mapping_file_name: str
44
- location_map_file_name: str
45
- default_call_number_type_name: str
46
- temp_location_map_file_name: Optional[str] = ""
47
- material_types_map_file_name: str
48
- loan_types_map_file_name: str
49
- temp_loan_types_map_file_name: Optional[str] = ""
50
- statistical_codes_map_file_name: Optional[str] = ""
51
- item_statuses_map_file_name: str
52
- call_number_type_map_file_name: str
53
- reset_hrid_settings: Optional[bool] = False
38
+ name: Annotated[
39
+ str,
40
+ Field(
41
+ title="Task name",
42
+ description="Name of the task.",
43
+ ),
44
+ ]
45
+ migration_task_type: Annotated[
46
+ str,
47
+ Field(
48
+ title="Migration task type",
49
+ description="Type of migration task.",
50
+ ),
51
+ ]
52
+ hrid_handling: Annotated[
53
+ HridHandling,
54
+ Field(
55
+ title="HRID handling",
56
+ description=(
57
+ "Determining how the HRID generation "
58
+ "should be handled."
59
+ ),
60
+ ),
61
+ ]
62
+ files: Annotated[
63
+ List[FileDefinition],
64
+ Field(
65
+ title="Files",
66
+ description="List of files.",
67
+ ),
68
+ ]
69
+ items_mapping_file_name: Annotated[
70
+ str,
71
+ Field(
72
+ title="Items mapping file name",
73
+ description="File name for items mapping.",
74
+ ),
75
+ ]
76
+ location_map_file_name: Annotated[
77
+ str,
78
+ Field(
79
+ title="Location map file name",
80
+ description="File name for location map.",
81
+ ),
82
+ ]
83
+ default_call_number_type_name: Annotated[
84
+ str,
85
+ Field(
86
+ title="Default call number type name",
87
+ description="Default name for call number type.",
88
+ ),
89
+ ]
90
+ temp_location_map_file_name: Annotated[
91
+ Optional[str],
92
+ Field(
93
+ title="Temporary location map file name",
94
+ description=(
95
+ "Temporary file name for location map. "
96
+ "Empty string by default."
97
+ ),
98
+ ),
99
+ ] = ""
100
+ material_types_map_file_name: Annotated[
101
+ str,
102
+ Field(
103
+ title="Material types map file name",
104
+ description="File name for material types map.",
105
+ ),
106
+ ]
107
+ loan_types_map_file_name: Annotated[
108
+ str,
109
+ Field(
110
+ title="Loan types map file name",
111
+ description="File name for loan types map.",
112
+ ),
113
+ ]
114
+ temp_loan_types_map_file_name: Annotated[
115
+ Optional[str],
116
+ Field(
117
+ title="Temporary loan types map file name",
118
+ description=(
119
+ "File name for temporary loan types map. "
120
+ "Empty string by default."
121
+ ),
122
+ ),
123
+ ] = ""
124
+ statistical_codes_map_file_name: Annotated[
125
+ Optional[str],
126
+ Field(
127
+ title="Statistical codes map file name",
128
+ description=(
129
+ "File name for statistical codes map. "
130
+ "Empty string by default."
131
+ ),
132
+ ),
133
+ ] = ""
134
+ item_statuses_map_file_name: Annotated[
135
+ str,
136
+ Field(
137
+ title="Item statuses map file name",
138
+ description="File name for item statuses map.",
139
+ ),
140
+ ]
141
+ call_number_type_map_file_name: Annotated[
142
+ str,
143
+ Field(
144
+ title="Call number type map file name",
145
+ description="File name for call number type map.",
146
+ ),
147
+ ]
148
+ reset_hrid_settings: Annotated[
149
+ Optional[bool],
150
+ Field(
151
+ title="Reset HRID settings",
152
+ description=(
153
+ "At the end of the run "
154
+ "reset FOLIO with the HRID settings. "
155
+ "By default is False."
156
+ ),
157
+ ),
158
+ ] = False
54
159
  update_hrid_settings: Annotated[
55
160
  bool,
56
161
  Field(
57
162
  title="Update HRID settings",
58
- description="At the end of the run, update FOLIO with the HRID settings",
163
+ description=(
164
+ "At the end of the run "
165
+ "update FOLIO with the HRID settings. "
166
+ "By default is True."
167
+ ),
59
168
  ),
60
169
  ] = True
61
170
  boundwith_relationship_file_path: Annotated[
@@ -63,8 +172,10 @@ class ItemsTransformer(MigrationTaskBase):
63
172
  Field(
64
173
  title="Boundwith relationship file path",
65
174
  description=(
66
- "Path to a file outlining Boundwith relationships, in the style of Voyager."
67
- " A TSV file with MFHD_ID and BIB_ID headers and values"
175
+ "Path to a file outlining Boundwith relationships, "
176
+ "in the style of Voyager. "
177
+ "A TSV file with MFHD_ID and BIB_ID headers and values. "
178
+ "By default is empty string."
68
179
  ),
69
180
  ),
70
181
  ] = ""
@@ -73,7 +184,9 @@ class ItemsTransformer(MigrationTaskBase):
73
184
  Field(
74
185
  title="Prevent permanent location map default",
75
186
  description=(
76
- "Prevent the default mapping of permanent location to the default location."
187
+ "Prevent the default mapping of permanent location "
188
+ "to the default location. "
189
+ "By default is False."
77
190
  ),
78
191
  ),
79
192
  ] = False