folio-migration-tools 1.9.0a6__tar.gz → 1.9.0rc1__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.0a6 → folio_migration_tools-1.9.0rc1}/PKG-INFO +3 -2
  2. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/pyproject.toml +20 -8
  3. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/__main__.py +13 -5
  4. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/library_configuration.py +1 -6
  5. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapper_base.py +1 -1
  6. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/item_mapper.py +1 -1
  7. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/order_mapper.py +20 -0
  8. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/conditions.py +28 -2
  9. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/batch_poster.py +29 -14
  10. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/items_transformer.py +9 -0
  11. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/loans_migrator.py +8 -29
  12. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/LICENSE +0 -0
  13. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/README.md +0 -0
  14. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/__init__.py +0 -0
  15. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/circulation_helper.py +0 -0
  16. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/colors.py +0 -0
  17. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/config_file_load.py +0 -0
  18. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/custom_dict.py +0 -0
  19. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/custom_exceptions.py +0 -0
  20. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/extradata_writer.py +0 -0
  21. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/folder_structure.py +0 -0
  22. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/helper.py +0 -0
  23. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/holdings_helper.py +0 -0
  24. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/i18n_config.py +0 -0
  25. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/__init__.py +0 -0
  26. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/courses_mapper.py +0 -0
  27. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/holdings_mapper.py +0 -0
  28. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +0 -0
  29. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +0 -0
  30. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/notes_mapper.py +0 -0
  31. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/organization_mapper.py +0 -0
  32. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/ref_data_mapping.py +0 -0
  33. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/user_mapper.py +0 -0
  34. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/__init__.py +0 -0
  35. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +0 -0
  36. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/hrid_handler.py +0 -0
  37. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/loc_language_codes.xml +0 -0
  38. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/marc_file_processor.py +0 -0
  39. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py +0 -0
  40. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +0 -0
  41. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +0 -0
  42. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +0 -0
  43. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +0 -0
  44. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_report.py +0 -0
  45. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/__init__.py +0 -0
  46. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/authority_transformer.py +0 -0
  47. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/bibs_transformer.py +0 -0
  48. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/courses_migrator.py +0 -0
  49. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/holdings_csv_transformer.py +0 -0
  50. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/holdings_marc_transformer.py +0 -0
  51. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +0 -0
  52. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/migration_task_base.py +0 -0
  53. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/orders_transformer.py +0 -0
  54. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/organization_transformer.py +0 -0
  55. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/requests_migrator.py +0 -0
  56. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/reserves_migrator.py +0 -0
  57. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/user_transformer.py +0 -0
  58. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/task_configuration.py +0 -0
  59. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/test_infrastructure/__init__.py +0 -0
  60. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/test_infrastructure/mocked_classes.py +0 -0
  61. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/__init__.py +0 -0
  62. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/legacy_loan.py +0 -0
  63. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/legacy_request.py +0 -0
  64. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/legacy_reserve.py +0 -0
  65. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/transaction_result.py +0 -0
  66. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/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.0a6
3
+ Version: 1.9.0rc1
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
@@ -26,7 +26,8 @@ Requires-Dist: pyhumps (>=3.7.3,<4.0.0)
26
26
  Requires-Dist: pymarc (>=5.2.3,<6.0.0)
27
27
  Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
28
28
  Requires-Dist: python-i18n (>=0.3.9,<0.4.0)
29
- Project-URL: Homepage, https://github.com/FOLIO-FSE/folio_migration_tools
29
+ Project-URL: Documentation, https://folio-migration-tools.readthedocs.io/en/latest/
30
+ Project-URL: Homepage, https://github.com/folio-fse/folio_migration_tools
30
31
  Project-URL: Repository, https://github.com/FOLIO-FSE/folio_migration_tools
31
32
  Description-Content-Type: text/markdown
32
33
 
@@ -1,14 +1,26 @@
1
- [tool.poetry]
1
+ [project]
2
2
  name = "folio_migration_tools"
3
- version = "1.9.0a6"
3
+ version = "1.9.0rc1"
4
4
  description = "A tool allowing you to migrate data from legacy ILS:s (Library systems) into FOLIO LSP"
5
- authors = ["Theodor Tolstoy <github.teddes@tolstoy.se>", "Lisa Sjögren", "Brooks Travis", "Jeremy Nelson", "Clinton Bradford"]
5
+ authors = [
6
+ {name = "Theodor Tolstoy", email = "github.teddes@tolstoy.se"},
7
+ {name = "Lisa Sjögren"},
8
+ {name = "Brooks Travis", email = "brooks.travis@gmail.com"},
9
+ {name = "Jeremy Nelson"},
10
+ {name = "Clinton Bradford"}
11
+ ]
6
12
  license = "MIT"
7
13
  readme = "README.md"
8
- homepage = "https://github.com/FOLIO-FSE/folio_migration_tools"
9
- repository = "https://github.com/FOLIO-FSE/folio_migration_tools"
10
14
  keywords = ["FOLIO", "ILS", "LSP", "Library Systems", "MARC21", "Library data"]
11
15
 
16
+ [project.urls]
17
+ documentation = "https://folio-migration-tools.readthedocs.io/en/latest/"
18
+ homepage = "https://github.com/folio-fse/folio_migration_tools"
19
+ repository = "https://github.com/FOLIO-FSE/folio_migration_tools"
20
+
21
+ [project.scripts]
22
+ folio-migration-tools = "folio_migration_tools.__main__:main"
23
+
12
24
  [tool.coverage.report]
13
25
  show_missing = false
14
26
  fail_under = 10
@@ -21,13 +33,12 @@ branch = true
21
33
  source = ["folio_migration_tools"]
22
34
 
23
35
  [build-system]
24
- requires = ["setuptools>=42"]
25
- build-backend = "setuptools.build_meta"
36
+ requires = ["poetry-core>=1.0.0"]
37
+ build-backend = "poetry.core.masonry.api"
26
38
 
27
39
  [tool.black]
28
40
  line-length = 99
29
41
 
30
-
31
42
  [tool.isort]
32
43
  profile = "black"
33
44
 
@@ -65,6 +76,7 @@ myst-parser = "^0.18.1"
65
76
  pandas = "^1.5.3"
66
77
  types-requests = "^2.28.11.17"
67
78
  types-python-dateutil = "^2.8.19.11"
79
+ ipykernel = "^6.29.5"
68
80
 
69
81
  [tool.poetry.extras]
70
82
  docs = ["m2r", "sphinx", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "toml"]
@@ -124,7 +124,8 @@ def main():
124
124
  except TransformationProcessError as tpe:
125
125
  logging.critical(tpe.message)
126
126
  print(f"\n{tpe.message}: {tpe.data_value}")
127
- sys.exit("Transformation Failure")
127
+ print("Task failure. Halting.")
128
+ sys.exit(1)
128
129
  logging.info("Work done. Shutting down")
129
130
  sys.exit(0)
130
131
  except json.decoder.JSONDecodeError as json_error:
@@ -148,10 +149,17 @@ def main():
148
149
  print("Halting")
149
150
  sys.exit("JSON Not Matching Spec")
150
151
  except httpx.HTTPError as connection_error:
151
- print(
152
- f"\nConnection Error when connecting to {connection_error.request.url}. "
153
- "Are you connectet to the Internet/VPN? Do you need to update DNS settings?"
154
- )
152
+ if hasattr(connection_error, "response"):
153
+ print(
154
+ f"\nHTTP Error when connecting to {connection_error.request.url}. "
155
+ f"Status code: {connection_error.response.status_code}. "
156
+ f"\nResponse: {connection_error.response.text}"
157
+ )
158
+ else:
159
+ print(
160
+ f"\nConnection Error when connecting to {connection_error.request.url}. "
161
+ "Are you connected to the Internet/VPN? Do you need to update DNS settings?"
162
+ )
155
163
  sys.exit("HTTP Not Connecting")
156
164
  except FileNotFoundError as fnf_error:
157
165
  print(f"\n{fnf_error.strerror}: {fnf_error.filename}")
@@ -62,14 +62,9 @@ class IlsFlavour(str, Enum):
62
62
 
63
63
 
64
64
  class FolioRelease(str, Enum):
65
- lotus = "lotus"
66
- morning_glory = "morning-glory"
67
- nolana = "nolana"
68
- orchid = "orchid"
69
- poppy = "poppy"
70
- quesnelia = "quesnelia"
71
65
  ramsons = "ramsons"
72
66
  sunflower = "sunflower"
67
+ trillium = "trillium"
73
68
 
74
69
 
75
70
  class LibraryConfiguration(BaseModel):
@@ -444,7 +444,7 @@ class MapperBase:
444
444
  except IndexError:
445
445
  if call_numbers:
446
446
  bound_with_holding["callNumber"] = call_numbers[0]
447
- except SyntaxError:
447
+ except (SyntaxError, ValueError):
448
448
  bound_with_holding["callNumber"] = call_number
449
449
  else:
450
450
  bound_with_holding["callNumber"] = call_number
@@ -165,7 +165,7 @@ class ItemMapper(MappingFileMapperBase):
165
165
  legacy_item,
166
166
  folio_prop_name,
167
167
  index_or_id,
168
- False,
168
+ self.task_configuration.prevent_permanent_location_map_default,
169
169
  )
170
170
  elif folio_prop_name == "temporaryLocationId":
171
171
  if not self.temp_location_mapping:
@@ -25,6 +25,8 @@ 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
  def __init__(
29
31
  self,
30
32
  folio_client: FolioClient,
@@ -364,6 +366,8 @@ class CompositeOrderMapper(MappingFileMapperBase):
364
366
  return {}
365
367
 
366
368
  def perform_additional_mapping(self, index_or_id, composite_order):
369
+ self.validate_po_number(index_or_id, composite_order.get("poNumber"))
370
+
367
371
  # Get organization UUID from FOLIO
368
372
  composite_order["vendor"] = self.get_folio_organization_uuid(
369
373
  index_or_id, composite_order.get("vendor")
@@ -376,6 +380,22 @@ class CompositeOrderMapper(MappingFileMapperBase):
376
380
 
377
381
  return composite_order
378
382
 
383
+ def validate_po_number(
384
+ self,
385
+ index_or_id: str,
386
+ po_number: str,
387
+ ):
388
+ if re.sub(self.VALID_PO_NUMBER_CHARACTERS, "", po_number):
389
+ self.migration_report.add(
390
+ "PurchaseOrderVendorLinking",
391
+ i18n.t("RECORD FAILED: PO number has invalid character(s)"),
392
+ )
393
+ raise TransformationRecordFailedError(
394
+ index_or_id,
395
+ "Purchase Order number has invalid character(s)",
396
+ po_number,
397
+ )
398
+
379
399
  def get_matching_record_from_folio(
380
400
  self,
381
401
  index_or_id,
@@ -846,7 +846,7 @@ class Conditions:
846
846
  self.mapper.migration_report.add(
847
847
  "StaffOnlyViaIndicator",
848
848
  f"{marc_field.tag} indicator1: {ind1} ("
849
- + i18n.t("1 is public, all other values are Staff only")
849
+ + i18n.t("0 is staff-only, all other values are public")
850
850
  + ")",
851
851
  )
852
852
  if ind1 == "0":
@@ -864,4 +864,30 @@ class Conditions:
864
864
  raise TransformationProcessError(
865
865
  legacy_id,
866
866
  f"Subject type not found for {parameter['name']} {marc_field}",
867
- )
867
+ )
868
+
869
+ def condition_set_subject_source_id(self, legacy_id, value, parameter, marc_field: field.Field):
870
+ try:
871
+ t = self.get_ref_data_tuple_by_name(
872
+ self.folio.folio_get_all("/subject-sources", "subjectSources"), "subject_sources", parameter["name"]
873
+ )
874
+ self.mapper.migration_report.add("MappedSubjectSources", t[1])
875
+ return t[0]
876
+ except Exception:
877
+ raise TransformationProcessError(
878
+ legacy_id,
879
+ f"Subject source not found for {parameter['name']} {marc_field}",
880
+ )
881
+
882
+ def condition_set_subject_source_id_by_code(self, legacy_id, value, parameter, marc_field: field.Field):
883
+ try:
884
+ t = self.get_ref_data_tuple_by_code(
885
+ self.folio.folio_get_all("/subject-sources", "subjectSources"), "subject_sources", value
886
+ )
887
+ self.mapper.migration_report.add("MappedSubjectSources", t[1])
888
+ return t[0]
889
+ except Exception:
890
+ raise TransformationProcessError(
891
+ legacy_id,
892
+ f"Subject source not found for {value} {marc_field}",
893
+ )
@@ -136,12 +136,12 @@ class BatchPoster(MigrationTaskBase):
136
136
  def do_work(self):
137
137
  with self.folio_client.get_folio_http_client() as httpx_client:
138
138
  self.http_client = httpx_client
139
- try:
140
- batch = []
141
- if self.task_configuration.object_type == "SRS":
142
- self.create_snapshot()
143
- with open(self.folder_structure.failed_recs_path, "w") as failed_recs_file:
144
- for file_def in self.task_configuration.files:
139
+ with open(self.folder_structure.failed_recs_path, "w", encoding='utf-8') as failed_recs_file:
140
+ try:
141
+ batch = []
142
+ if self.task_configuration.object_type == "SRS":
143
+ self.create_snapshot()
144
+ for idx, file_def in enumerate(self.task_configuration.files):
145
145
  path = self.folder_structure.results_folder / file_def.file_name
146
146
  with open(path) as rows:
147
147
  logging.info("Running %s", path)
@@ -172,9 +172,8 @@ class BatchPoster(MigrationTaskBase):
172
172
  self.processed,
173
173
  failed_recs_file,
174
174
  )
175
- logging.critical("Halting %s", tpe)
176
- print(f"\n\t{tpe.message}")
177
- sys.exit(1)
175
+ batch = []
176
+ raise
178
177
  except TransformationRecordFailedError as exception:
179
178
  self.handle_generic_exception(
180
179
  exception,
@@ -184,7 +183,21 @@ class BatchPoster(MigrationTaskBase):
184
183
  failed_recs_file,
185
184
  )
186
185
  batch = []
187
-
186
+ except (FileNotFoundError, PermissionError) as ose:
187
+ logging.error("Error reading file: %s", ose)
188
+
189
+ except Exception as ee:
190
+ if "idx" in locals() and self.task_configuration.files[idx:]:
191
+ for file in self.task_configuration.files[idx:]:
192
+ try:
193
+ with open(file, "r") as failed_file:
194
+ failed_file.seek(self.processed)
195
+ failed_recs_file.write(failed_file.read())
196
+ self.processed = 0
197
+ except (FileNotFoundError, PermissionError) as ose:
198
+ logging.error("Error reading file: %s", ose)
199
+ raise ee
200
+ finally:
188
201
  if self.task_configuration.object_type != "Extradata" and any(batch):
189
202
  try:
190
203
  self.post_batch(batch, failed_recs_file, self.processed)
@@ -193,10 +206,8 @@ class BatchPoster(MigrationTaskBase):
193
206
  exception, last_row, batch, self.processed, failed_recs_file
194
207
  )
195
208
  logging.info("Done posting %s records. ", (self.processed))
196
- except Exception as ee:
197
- if self.task_configuration.object_type == "SRS":
198
- self.commit_snapshot()
199
- raise ee
209
+ if self.task_configuration.object_type == "SRS":
210
+ self.commit_snapshot()
200
211
 
201
212
  def post_record_batch(self, batch, failed_recs_file, row):
202
213
  json_rec = json.loads(row.split("\t")[-1])
@@ -339,6 +350,10 @@ class BatchPoster(MigrationTaskBase):
339
350
 
340
351
  def post_batch(self, batch, failed_recs_file, num_records, recursion_depth=0):
341
352
  response = self.do_post(batch)
353
+ if response.status_code == 401:
354
+ logging.error("Authorization failed (%s). Fetching new auth token...", response.text)
355
+ self.folio_client.login()
356
+ response = self.do_post(batch)
342
357
  if response.status_code == 201:
343
358
  logging.info(
344
359
  (
@@ -68,6 +68,15 @@ class ItemsTransformer(MigrationTaskBase):
68
68
  ),
69
69
  ),
70
70
  ] = ""
71
+ prevent_permanent_location_map_default: Annotated[
72
+ bool,
73
+ Field(
74
+ title="Prevent permanent location map default",
75
+ description=(
76
+ "Prevent the default mapping of permanent location to the default location."
77
+ ),
78
+ ),
79
+ ] = False
71
80
 
72
81
  @staticmethod
73
82
  def get_object_type() -> FOLIONamespaces:
@@ -8,11 +8,11 @@ import traceback
8
8
  from datetime import datetime, timedelta
9
9
  from typing import Optional
10
10
  from urllib.error import HTTPError
11
+ from zoneinfo import ZoneInfo
11
12
 
12
13
  import i18n
13
14
  from dateutil import parser as du_parser
14
15
  from folio_uuid.folio_namespaces import FOLIONamespaces
15
- from zoneinfo import ZoneInfo
16
16
 
17
17
  from folio_migration_tools.circulation_helper import CirculationHelper
18
18
  from folio_migration_tools.helper import Helper
@@ -131,34 +131,13 @@ class LoansMigrator(MigrationTaskBase):
131
131
  logging.info("Init completed")
132
132
 
133
133
  def check_smtp_config(self):
134
- if self.library_configuration.folio_release.lower() == FolioRelease.morning_glory:
135
- logging.warn("DEPRECATED: Morning Glory support will be removed in a future release!")
136
- okapi_config_base_path = "/configurations/entries"
137
- okapi_config_query = "(module=={}%20and%20configName=={}%20and%20code=={})"
138
- okapi_config_limit = 1000
139
- okapi_config_module = "SMTP_SERVER"
140
- okapi_config_name = "smtp"
141
- okapi_config_code = "EMAIL_SMTP_HOST_DISABLED"
142
- smtp_config_path = (
143
- okapi_config_base_path
144
- + "?"
145
- + str(okapi_config_limit)
146
- + "&query="
147
- + okapi_config_query.format(
148
- okapi_config_module, okapi_config_name, okapi_config_code
149
- )
150
- )
151
- smtp_config_disabled = self.folio_client.folio_get_single_object(smtp_config_path)[
152
- "configs"
153
- ]
154
- else:
155
- try:
156
- smtp_config = self.folio_client.folio_get_single_object("/smtp-configuration")[
157
- "smtpConfigurations"
158
- ][0]
159
- smtp_config_disabled = "disabled" in smtp_config["host"].lower()
160
- except IndexError:
161
- smtp_config_disabled = True
134
+ try:
135
+ smtp_config = self.folio_client.folio_get_single_object("/smtp-configuration")[
136
+ "smtpConfigurations"
137
+ ][0]
138
+ smtp_config_disabled = "disabled" in smtp_config["host"].lower()
139
+ except IndexError:
140
+ smtp_config_disabled = True
162
141
  print_smtp_warning()
163
142
  if not smtp_config_disabled:
164
143
  logging.warn("SMTP connection not disabled...")