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.
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/PKG-INFO +3 -2
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/pyproject.toml +20 -8
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/__main__.py +13 -5
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/library_configuration.py +1 -6
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapper_base.py +1 -1
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/item_mapper.py +1 -1
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/order_mapper.py +20 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/conditions.py +28 -2
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/batch_poster.py +29 -14
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/items_transformer.py +9 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/loans_migrator.py +8 -29
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/LICENSE +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/README.md +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/__init__.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/circulation_helper.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/colors.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/config_file_load.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/custom_dict.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/custom_exceptions.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/extradata_writer.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/folder_structure.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/helper.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/holdings_helper.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/i18n_config.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/__init__.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/courses_mapper.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/holdings_mapper.py +0 -0
- {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
- {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
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/notes_mapper.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/organization_mapper.py +0 -0
- {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
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/mapping_file_transformation/user_mapper.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/__init__.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/marc_rules_transformation/hrid_handler.py +0 -0
- {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
- {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
- {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
- {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
- {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
- {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
- {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
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_report.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/__init__.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/authority_transformer.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/bibs_transformer.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/courses_migrator.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/holdings_csv_transformer.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/holdings_marc_transformer.py +0 -0
- {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
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/migration_task_base.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/orders_transformer.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/organization_transformer.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/requests_migrator.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/reserves_migrator.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/migration_tasks/user_transformer.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/task_configuration.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/test_infrastructure/__init__.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/test_infrastructure/mocked_classes.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/__init__.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/legacy_loan.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/legacy_request.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/legacy_reserve.py +0 -0
- {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/transaction_migration/transaction_result.py +0 -0
- {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.
|
|
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:
|
|
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
|
-
[
|
|
1
|
+
[project]
|
|
2
2
|
name = "folio_migration_tools"
|
|
3
|
-
version = "1.9.
|
|
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 = [
|
|
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 = ["
|
|
25
|
-
build-backend = "
|
|
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
|
-
|
|
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
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
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("
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
self.
|
|
143
|
-
|
|
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
|
-
|
|
176
|
-
|
|
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
|
-
|
|
197
|
-
|
|
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
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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...")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/colors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0rc1}/src/folio_migration_tools/helper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|