folio-migration-tools 1.9.0rc8__tar.gz → 1.9.0rc10__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.0rc8 → folio_migration_tools-1.9.0rc10}/PKG-INFO +1 -1
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/pyproject.toml +1 -1
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapper_base.py +1 -1
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/marc_file_processor.py +21 -23
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +3 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +39 -37
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +17 -20
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/bibs_transformer.py +3 -58
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/holdings_marc_transformer.py +2 -23
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/migration_task_base.py +65 -1
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/task_configuration.py +18 -1
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/LICENSE +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/README.md +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/__init__.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/__main__.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/circulation_helper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/colors.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/config_file_load.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/custom_dict.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/custom_exceptions.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/extradata_writer.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/folder_structure.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/helper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/holdings_helper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/i18n_config.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/library_configuration.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/__init__.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/courses_mapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/holdings_mapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/item_mapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/notes_mapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/order_mapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/organization_mapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/ref_data_mapping.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/mapping_file_transformation/user_mapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/__init__.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/conditions.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/hrid_handler.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/loc_language_codes.xml +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_report.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/__init__.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/authority_transformer.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/batch_poster.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/courses_migrator.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/holdings_csv_transformer.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/items_transformer.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/loans_migrator.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/orders_transformer.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/organization_transformer.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/requests_migrator.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/reserves_migrator.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/migration_tasks/user_transformer.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/test_infrastructure/__init__.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/test_infrastructure/mocked_classes.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/transaction_migration/__init__.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/transaction_migration/legacy_loan.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/transaction_migration/legacy_request.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/transaction_migration/legacy_reserve.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/transaction_migration/transaction_result.py +0 -0
- {folio_migration_tools-1.9.0rc8 → folio_migration_tools-1.9.0rc10}/src/folio_migration_tools/translations/en.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "folio_migration_tools"
|
|
3
|
-
version = "1.9.
|
|
3
|
+
version = "1.9.0rc10"
|
|
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"},
|
|
@@ -272,7 +272,7 @@ class MapperBase:
|
|
|
272
272
|
[
|
|
273
273
|
object_type == FOLIONamespaces.instances,
|
|
274
274
|
(not getattr(self.task_configuration, "data_import_marc", False)),
|
|
275
|
-
getattr(self
|
|
275
|
+
getattr(self, "create_source_records", True),
|
|
276
276
|
]
|
|
277
277
|
):
|
|
278
278
|
return (legacy_id, folio_record["id"], folio_record["hrid"])
|
|
@@ -3,7 +3,7 @@ import os
|
|
|
3
3
|
import sys
|
|
4
4
|
import time
|
|
5
5
|
import traceback
|
|
6
|
-
from typing import List
|
|
6
|
+
from typing import BinaryIO, Dict, List, Set, TextIO
|
|
7
7
|
|
|
8
8
|
import i18n
|
|
9
9
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
@@ -24,24 +24,26 @@ from folio_migration_tools.migration_report import MigrationReport
|
|
|
24
24
|
|
|
25
25
|
class MarcFileProcessor:
|
|
26
26
|
def __init__(
|
|
27
|
-
self, mapper: RulesMapperBase, folder_structure: FolderStructure, created_objects_file
|
|
27
|
+
self, mapper: RulesMapperBase, folder_structure: FolderStructure, created_objects_file: TextIO
|
|
28
28
|
):
|
|
29
29
|
self.object_type: FOLIONamespaces = folder_structure.object_type
|
|
30
30
|
self.folder_structure: FolderStructure = folder_structure
|
|
31
31
|
self.mapper: RulesMapperBase = mapper
|
|
32
|
-
self.created_objects_file = created_objects_file
|
|
33
|
-
if mapper.
|
|
34
|
-
|
|
32
|
+
self.created_objects_file: TextIO = created_objects_file
|
|
33
|
+
if mapper.create_source_records and any(
|
|
34
|
+
x.create_source_records for x in mapper.task_configuration.files
|
|
35
|
+
):
|
|
36
|
+
self.srs_records_file: TextIO = open(self.folder_structure.srs_records_path, "w+")
|
|
35
37
|
if getattr(mapper.task_configuration, "data_import_marc", False):
|
|
36
|
-
self.data_import_marc_file = open(self.folder_structure.data_import_marc_path, "wb+")
|
|
37
|
-
self.unique_001s:
|
|
38
|
+
self.data_import_marc_file: BinaryIO = open(self.folder_structure.data_import_marc_path, "wb+")
|
|
39
|
+
self.unique_001s: Set[str] = set()
|
|
38
40
|
self.failed_records_count: int = 0
|
|
39
41
|
self.records_count: int = 0
|
|
40
42
|
self.start: float = time.time()
|
|
41
|
-
self.legacy_ids:
|
|
43
|
+
self.legacy_ids: Set[str] = set()
|
|
42
44
|
if (
|
|
43
45
|
self.object_type == FOLIONamespaces.holdings
|
|
44
|
-
and self.mapper.
|
|
46
|
+
and self.mapper.create_source_records
|
|
45
47
|
):
|
|
46
48
|
logging.info("Loading Parent HRID map for SRS creation")
|
|
47
49
|
self.parent_hrids = {entity[1]: entity[2] for entity in mapper.parent_id_map.values()}
|
|
@@ -78,7 +80,7 @@ class MarcFileProcessor:
|
|
|
78
80
|
|
|
79
81
|
if (
|
|
80
82
|
file_def.create_source_records
|
|
81
|
-
and self.mapper.
|
|
83
|
+
and self.mapper.create_source_records
|
|
82
84
|
):
|
|
83
85
|
self.save_srs_record(
|
|
84
86
|
marc_record,
|
|
@@ -132,7 +134,7 @@ class MarcFileProcessor:
|
|
|
132
134
|
def save_marc_record(
|
|
133
135
|
self,
|
|
134
136
|
marc_record: Record,
|
|
135
|
-
folio_rec:
|
|
137
|
+
folio_rec: Dict,
|
|
136
138
|
object_type: FOLIONamespaces
|
|
137
139
|
):
|
|
138
140
|
self.mapper.save_data_import_marc_record(
|
|
@@ -146,14 +148,10 @@ class MarcFileProcessor:
|
|
|
146
148
|
self,
|
|
147
149
|
marc_record: Record,
|
|
148
150
|
file_def: FileDefinition,
|
|
149
|
-
folio_rec,
|
|
151
|
+
folio_rec: Dict,
|
|
150
152
|
legacy_ids: List[str],
|
|
151
153
|
object_type: FOLIONamespaces,
|
|
152
154
|
):
|
|
153
|
-
if not all(
|
|
154
|
-
[file_def.create_source_records, self.mapper.task_configuration.create_source_records]
|
|
155
|
-
):
|
|
156
|
-
return
|
|
157
155
|
if object_type in [FOLIONamespaces.holdings]:
|
|
158
156
|
if "008" in marc_record and len(marc_record["008"].data) > 32:
|
|
159
157
|
remain, rest = (
|
|
@@ -188,7 +186,7 @@ class MarcFileProcessor:
|
|
|
188
186
|
)
|
|
189
187
|
self.mapper.migration_report.add_general_statistics(i18n.t("SRS records written to disk"))
|
|
190
188
|
|
|
191
|
-
def add_mapped_location_code_to_record(self, marc_record, folio_rec):
|
|
189
|
+
def add_mapped_location_code_to_record(self, marc_record: Record, folio_rec: Dict):
|
|
192
190
|
location_code = next(
|
|
193
191
|
(
|
|
194
192
|
location["code"]
|
|
@@ -225,9 +223,9 @@ class MarcFileProcessor:
|
|
|
225
223
|
|
|
226
224
|
@staticmethod
|
|
227
225
|
def get_valid_folio_record_ids(
|
|
228
|
-
legacy_ids, folio_record_identifiers, migration_report: MigrationReport
|
|
229
|
-
):
|
|
230
|
-
new_ids = set()
|
|
226
|
+
legacy_ids: List[str], folio_record_identifiers: Set[str], migration_report: MigrationReport
|
|
227
|
+
) -> List[str]:
|
|
228
|
+
new_ids: Set[str] = set()
|
|
231
229
|
for legacy_id in legacy_ids:
|
|
232
230
|
if legacy_id not in folio_record_identifiers:
|
|
233
231
|
new_ids.add(legacy_id)
|
|
@@ -266,12 +264,12 @@ class MarcFileProcessor:
|
|
|
266
264
|
self.mapper.mapped_folio_fields,
|
|
267
265
|
self.mapper.mapped_legacy_fields,
|
|
268
266
|
)
|
|
269
|
-
if self
|
|
267
|
+
if hasattr(self, "srs_records_file"):
|
|
270
268
|
self.srs_records_file.seek(0)
|
|
271
269
|
if not self.srs_records_file.seek(0):
|
|
272
270
|
os.remove(self.srs_records_file.name)
|
|
273
271
|
self.srs_records_file.close()
|
|
274
|
-
if
|
|
272
|
+
if hasattr(self, "data_import_marc_file"):
|
|
275
273
|
self.data_import_marc_file.seek(0)
|
|
276
274
|
if not self.data_import_marc_file.read(1):
|
|
277
275
|
os.remove(self.data_import_marc_file.name)
|
|
@@ -281,7 +279,7 @@ class MarcFileProcessor:
|
|
|
281
279
|
logging.info("Transformation report written to %s", report_file.name)
|
|
282
280
|
logging.info("Processor is done.")
|
|
283
281
|
|
|
284
|
-
def add_legacy_ids_to_map(self, folio_rec, filtered_legacy_ids):
|
|
282
|
+
def add_legacy_ids_to_map(self, folio_rec: Dict, filtered_legacy_ids: List[str]):
|
|
285
283
|
for legacy_id in filtered_legacy_ids:
|
|
286
284
|
self.legacy_ids.add(legacy_id)
|
|
287
285
|
if legacy_id not in self.mapper.id_map:
|
|
@@ -51,6 +51,9 @@ class RulesMapperBase(MapperBase):
|
|
|
51
51
|
self.item_json_schema = ""
|
|
52
52
|
self.mappings: dict = {}
|
|
53
53
|
self.schema_properties = None
|
|
54
|
+
self.create_source_records = all(
|
|
55
|
+
[self.task_configuration.create_source_records, (not getattr(self.task_configuration, "data_import_marc", False))]
|
|
56
|
+
)
|
|
54
57
|
if hasattr(self.task_configuration, "hrid_handling"):
|
|
55
58
|
self.hrid_handler = HRIDHandler(
|
|
56
59
|
folio_client,
|
|
@@ -7,7 +7,7 @@ import time
|
|
|
7
7
|
import typing
|
|
8
8
|
import uuid
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import Generator, List
|
|
10
|
+
from typing import Dict, Generator, List
|
|
11
11
|
|
|
12
12
|
import i18n
|
|
13
13
|
import pymarc
|
|
@@ -16,6 +16,7 @@ from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
|
16
16
|
from folio_uuid.folio_uuid import FolioUUID
|
|
17
17
|
from folioclient import FolioClient
|
|
18
18
|
from pymarc.record import Leader, Record
|
|
19
|
+
from pymarc.field import Field
|
|
19
20
|
|
|
20
21
|
from folio_migration_tools.custom_exceptions import (
|
|
21
22
|
TransformationProcessError,
|
|
@@ -32,6 +33,7 @@ from folio_migration_tools.marc_rules_transformation.conditions import Condition
|
|
|
32
33
|
from folio_migration_tools.marc_rules_transformation.rules_mapper_base import (
|
|
33
34
|
RulesMapperBase,
|
|
34
35
|
)
|
|
36
|
+
from folio_migration_tools.migration_tasks.migration_task_base import MarcTaskConfigurationBase
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
class BibsRulesMapper(RulesMapperBase):
|
|
@@ -40,9 +42,9 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
40
42
|
|
|
41
43
|
def __init__(
|
|
42
44
|
self,
|
|
43
|
-
folio_client,
|
|
45
|
+
folio_client: FolioClient,
|
|
44
46
|
library_configuration: LibraryConfiguration,
|
|
45
|
-
task_configuration,
|
|
47
|
+
task_configuration: MarcTaskConfigurationBase,
|
|
46
48
|
):
|
|
47
49
|
super().__init__(
|
|
48
50
|
folio_client,
|
|
@@ -59,15 +61,12 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
59
61
|
self.instance_relationships: dict = {}
|
|
60
62
|
self.instance_relationship_types: dict = {}
|
|
61
63
|
self.other_mode_of_issuance_id = get_unspecified_mode_of_issuance(self.folio_client)
|
|
62
|
-
self.create_source_records = all(
|
|
63
|
-
[self.task_configuration.create_source_records, (not getattr(self.task_configuration, "data_import_marc", False))]
|
|
64
|
-
)
|
|
65
64
|
self.data_import_marc = self.task_configuration.data_import_marc
|
|
66
65
|
if self.data_import_marc:
|
|
67
66
|
self.hrid_handler.deactivate035_from001 = True
|
|
68
67
|
self.start = time.time()
|
|
69
68
|
|
|
70
|
-
def perform_initial_preparation(self, marc_record:
|
|
69
|
+
def perform_initial_preparation(self, file_def: FileDefinition, marc_record: Record, legacy_ids: List[str]):
|
|
71
70
|
folio_instance = {}
|
|
72
71
|
folio_instance["id"] = str(
|
|
73
72
|
FolioUUID(
|
|
@@ -76,7 +75,10 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
76
75
|
str(legacy_ids[-1]),
|
|
77
76
|
)
|
|
78
77
|
)
|
|
79
|
-
if
|
|
78
|
+
if (
|
|
79
|
+
all([self.create_source_records, file_def.create_source_records])
|
|
80
|
+
or self.hrid_handler.handling == HridHandling.preserve001
|
|
81
|
+
):
|
|
80
82
|
self.hrid_handler.handle_hrid(
|
|
81
83
|
FOLIONamespaces.instances,
|
|
82
84
|
folio_instance,
|
|
@@ -90,7 +92,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
90
92
|
|
|
91
93
|
return folio_instance
|
|
92
94
|
|
|
93
|
-
def handle_leader_05(self, marc_record, legacy_ids):
|
|
95
|
+
def handle_leader_05(self, marc_record: Record, legacy_ids: List[str]):
|
|
94
96
|
leader_05 = marc_record.leader[5] or "Empty"
|
|
95
97
|
self.migration_report.add("RecordStatus", i18n.t("Original value") + f": {leader_05}")
|
|
96
98
|
if leader_05 not in ["a", "c", "d", "n", "p"]:
|
|
@@ -102,14 +104,14 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
102
104
|
Helper.log_data_issue(legacy_ids, "d in leader. Is this correct?", marc_record.leader)
|
|
103
105
|
|
|
104
106
|
def parse_record(
|
|
105
|
-
self, marc_record:
|
|
107
|
+
self, marc_record: Record, file_def: FileDefinition, legacy_ids: List[str]
|
|
106
108
|
) -> list[dict]:
|
|
107
109
|
"""Parses a bib recod into a FOLIO Inventory instance object
|
|
108
110
|
Community mapping suggestion: https://bit.ly/2S7Gyp3
|
|
109
111
|
This is the main function
|
|
110
112
|
|
|
111
113
|
Args:
|
|
112
|
-
marc_record (
|
|
114
|
+
marc_record (Record): _description_
|
|
113
115
|
file_def (FileDefinition): _description_
|
|
114
116
|
legacy_ids (List[str]): List of legacy ids in record
|
|
115
117
|
|
|
@@ -119,7 +121,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
119
121
|
self.print_progress()
|
|
120
122
|
ignored_subsequent_fields: set = set()
|
|
121
123
|
bad_tags = set(self.task_configuration.tags_to_delete) # "907"
|
|
122
|
-
folio_instance = self.perform_initial_preparation(marc_record, legacy_ids)
|
|
124
|
+
folio_instance = self.perform_initial_preparation(file_def, marc_record, legacy_ids)
|
|
123
125
|
if self.data_import_marc:
|
|
124
126
|
self.simple_bib_map(folio_instance, marc_record, ignored_subsequent_fields, legacy_ids)
|
|
125
127
|
else:
|
|
@@ -178,7 +180,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
178
180
|
legacy_ids (List[str]): _description_
|
|
179
181
|
file_def (FileDefinition): _description_
|
|
180
182
|
"""
|
|
181
|
-
if file_def.create_source_records and self.
|
|
183
|
+
if file_def.create_source_records and self.create_source_records:
|
|
182
184
|
folio_instance["source"] = "MARC"
|
|
183
185
|
else:
|
|
184
186
|
folio_instance["source"] = "FOLIO"
|
|
@@ -198,7 +200,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
198
200
|
del folio_instance["succeedingTitles"]
|
|
199
201
|
self.migration_report.add("PrecedingSuccedingTitles", f"{len(succ_titles)}")
|
|
200
202
|
|
|
201
|
-
def handle_languages(self, folio_instance, marc_record, legacy_ids):
|
|
203
|
+
def handle_languages(self, folio_instance: Dict, marc_record: Record, legacy_ids: List[str]):
|
|
202
204
|
if "languages" in folio_instance:
|
|
203
205
|
orig_languages = {lang: None for lang in folio_instance["languages"]}
|
|
204
206
|
orig_languages.update(
|
|
@@ -255,7 +257,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
255
257
|
if self.task_configuration.update_hrid_settings:
|
|
256
258
|
self.hrid_handler.store_hrid_settings()
|
|
257
259
|
|
|
258
|
-
def get_instance_type_id(self, marc_record,
|
|
260
|
+
def get_instance_type_id(self, marc_record: Record, legacy_ids: List[str]) -> str:
|
|
259
261
|
return_id = ""
|
|
260
262
|
|
|
261
263
|
def get_folio_id_by_name(f336a: str):
|
|
@@ -283,7 +285,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
283
285
|
+ f" ({f336a})",
|
|
284
286
|
)
|
|
285
287
|
Helper.log_data_issue(
|
|
286
|
-
|
|
288
|
+
legacy_ids,
|
|
287
289
|
"instance type name (336$a) -Unsuccessful matching",
|
|
288
290
|
f336a,
|
|
289
291
|
)
|
|
@@ -316,7 +318,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
316
318
|
),
|
|
317
319
|
)
|
|
318
320
|
Helper.log_data_issue(
|
|
319
|
-
|
|
321
|
+
legacy_ids,
|
|
320
322
|
i18n.t("instance type code (%{code}) not found in FOLIO", code="336$b"),
|
|
321
323
|
f336_b,
|
|
322
324
|
)
|
|
@@ -337,7 +339,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
337
339
|
return_id = t[0]
|
|
338
340
|
return return_id
|
|
339
341
|
|
|
340
|
-
def get_instance_format_id_by_code(self,
|
|
342
|
+
def get_instance_format_id_by_code(self, legacy_ids: List[str], code: str):
|
|
341
343
|
try:
|
|
342
344
|
match = next(f for f in self.folio_client.instance_formats if f["code"] == code)
|
|
343
345
|
self.migration_report.add(
|
|
@@ -347,14 +349,14 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
347
349
|
return match["id"]
|
|
348
350
|
except Exception:
|
|
349
351
|
# TODO: Distinguish between generated codes and proper 338bs
|
|
350
|
-
Helper.log_data_issue(
|
|
352
|
+
Helper.log_data_issue(legacy_ids, "Instance format Code not found in FOLIO", code)
|
|
351
353
|
self.migration_report.add(
|
|
352
354
|
"InstanceFormat",
|
|
353
355
|
i18n.t("Code '%{code}' not found in FOLIO", code=code),
|
|
354
356
|
)
|
|
355
357
|
return ""
|
|
356
358
|
|
|
357
|
-
def get_instance_format_id_by_name(self, f337a: str, f338a: str,
|
|
359
|
+
def get_instance_format_id_by_name(self, f337a: str, f338a: str, legacy_ids: List[str]):
|
|
358
360
|
f337a = f337a.lower().strip()
|
|
359
361
|
f338a = f338a.lower().strip()
|
|
360
362
|
match_template = f"{f337a} -- {f338a}"
|
|
@@ -376,7 +378,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
376
378
|
return match["id"]
|
|
377
379
|
except Exception:
|
|
378
380
|
Helper.log_data_issue(
|
|
379
|
-
|
|
381
|
+
legacy_ids,
|
|
380
382
|
"Unsuccessful matching on 337$a and 338$a",
|
|
381
383
|
match_template,
|
|
382
384
|
)
|
|
@@ -391,7 +393,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
391
393
|
)
|
|
392
394
|
return ""
|
|
393
395
|
|
|
394
|
-
def f338_source_is_rda_carrier(self, field:
|
|
396
|
+
def f338_source_is_rda_carrier(self, field: Field):
|
|
395
397
|
if "2" not in field:
|
|
396
398
|
self.migration_report.add(
|
|
397
399
|
"InstanceFormat",
|
|
@@ -407,7 +409,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
407
409
|
return False
|
|
408
410
|
|
|
409
411
|
def get_instance_format_ids_from_a(
|
|
410
|
-
self, field_index, f_338:
|
|
412
|
+
self, field_index: int, f_338: Field, all_337s: List[Field], legacy_id: List[str]
|
|
411
413
|
):
|
|
412
414
|
self.migration_report.add(
|
|
413
415
|
"InstanceFormat",
|
|
@@ -421,7 +423,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
421
423
|
):
|
|
422
424
|
yield fmt_id
|
|
423
425
|
|
|
424
|
-
def get_instance_format_ids(self, marc_record, legacy_id):
|
|
426
|
+
def get_instance_format_ids(self, marc_record: Record, legacy_id: List[str]):
|
|
425
427
|
all_337s = marc_record.get_fields("337")
|
|
426
428
|
all_338s = marc_record.get_fields("338")
|
|
427
429
|
for fidx, f_338 in enumerate(all_338s):
|
|
@@ -466,7 +468,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
466
468
|
legacy_id, combined_code
|
|
467
469
|
)
|
|
468
470
|
|
|
469
|
-
def get_mode_of_issuance_id(self, marc_record: Record,
|
|
471
|
+
def get_mode_of_issuance_id(self, marc_record: Record, legacy_ids: List[str]) -> str:
|
|
470
472
|
level = marc_record.leader[7]
|
|
471
473
|
try:
|
|
472
474
|
name = "unspecified"
|
|
@@ -496,7 +498,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
496
498
|
return ret
|
|
497
499
|
except IndexError:
|
|
498
500
|
self.migration_report.add(
|
|
499
|
-
"PossibleCleaningTasks", i18n.t("No Leader[7] in") + f" {
|
|
501
|
+
"PossibleCleaningTasks", i18n.t("No Leader[7] in") + f" {legacy_ids}"
|
|
500
502
|
)
|
|
501
503
|
|
|
502
504
|
return self.other_mode_of_issuance_id
|
|
@@ -512,7 +514,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
512
514
|
return "".join(marc_record["008"].data[35:38])
|
|
513
515
|
return ""
|
|
514
516
|
|
|
515
|
-
def get_languages_041(self, marc_record, legacy_id):
|
|
517
|
+
def get_languages_041(self, marc_record: Record, legacy_id: List[str]) -> Dict[str, None]:
|
|
516
518
|
languages = dict()
|
|
517
519
|
lang_fields = marc_record.get_fields("041")
|
|
518
520
|
if not any(lang_fields):
|
|
@@ -543,21 +545,21 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
543
545
|
}
|
|
544
546
|
return languages
|
|
545
547
|
|
|
546
|
-
def get_languages(self, marc_record: Record, legacy_id: str) -> List[str]:
|
|
548
|
+
def get_languages(self, marc_record: Record, legacy_id: List[str]) -> List[str]:
|
|
547
549
|
"""Get languages and tranforms them to correct codes
|
|
548
550
|
|
|
549
551
|
Args:
|
|
550
|
-
marc_record (Record):
|
|
551
|
-
legacy_id (str):
|
|
552
|
+
marc_record (Record): A pymarc Record object
|
|
553
|
+
legacy_id (List[str]): A list of legacy ids from the legacy record
|
|
552
554
|
|
|
553
555
|
Returns:
|
|
554
|
-
List[str]:
|
|
556
|
+
List[str]: List of language codes
|
|
555
557
|
"""
|
|
556
558
|
languages = self.get_languages_041(marc_record, legacy_id)
|
|
557
559
|
languages[self.get_languages_008(marc_record)] = None
|
|
558
|
-
for lang in languages
|
|
560
|
+
for lang in languages:
|
|
559
561
|
self.migration_report.add("LanguagesInRecords", lang)
|
|
560
|
-
return list(languages
|
|
562
|
+
return list(languages)
|
|
561
563
|
|
|
562
564
|
def fetch_language_codes(self) -> Generator[str, None, None]:
|
|
563
565
|
"""Loads the list of standardized language codes from LoC
|
|
@@ -575,7 +577,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
575
577
|
yield code.text
|
|
576
578
|
|
|
577
579
|
def filter_langs(
|
|
578
|
-
self, language_values: List[str], marc_record: Record, index_or_legacy_id
|
|
580
|
+
self, language_values: List[str], marc_record: Record, index_or_legacy_id: List[str]
|
|
579
581
|
) -> typing.Generator:
|
|
580
582
|
forbidden_values = ["###", "zxx", "n/a", "N/A", "|||"]
|
|
581
583
|
for language_value in language_values:
|
|
@@ -629,7 +631,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
629
631
|
else:
|
|
630
632
|
raise TransformationProcessError("", f"ILS {ils_flavour} not configured")
|
|
631
633
|
|
|
632
|
-
def get_aleph_bib_id(self, marc_record: Record):
|
|
634
|
+
def get_aleph_bib_id(self, marc_record: Record) -> List[str]:
|
|
633
635
|
res = {f["b"].strip(): None for f in marc_record.get_fields("998") if "b" in f}
|
|
634
636
|
if any(res):
|
|
635
637
|
self.migration_report.add_general_statistics(
|
|
@@ -651,7 +653,7 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
651
653
|
) from e
|
|
652
654
|
|
|
653
655
|
|
|
654
|
-
def get_unspecified_mode_of_issuance(folio_client: FolioClient):
|
|
656
|
+
def get_unspecified_mode_of_issuance(folio_client: FolioClient) -> str:
|
|
655
657
|
m_o_is = list(folio_client.modes_of_issuance)
|
|
656
658
|
if not any(m_o_is):
|
|
657
659
|
logging.critical("No Modes of issuance set up in tenant. Quitting...")
|
|
@@ -684,7 +686,7 @@ def get_custom_bib_id(marc_record: Record, field_string: str):
|
|
|
684
686
|
)
|
|
685
687
|
|
|
686
688
|
|
|
687
|
-
def get_iii_bib_id(marc_record: Record):
|
|
689
|
+
def get_iii_bib_id(marc_record: Record) -> List[str]:
|
|
688
690
|
try:
|
|
689
691
|
return [marc_record["907"]["a"]]
|
|
690
692
|
except Exception as e:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
|
-
from typing import List
|
|
4
|
+
from typing import Dict, List, Set
|
|
5
5
|
|
|
6
6
|
import i18n
|
|
7
7
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
@@ -235,10 +235,10 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
235
235
|
|
|
236
236
|
def process_marc_field(
|
|
237
237
|
self,
|
|
238
|
-
folio_holding:
|
|
238
|
+
folio_holding: Dict,
|
|
239
239
|
marc_field: Field,
|
|
240
|
-
ignored_subsequent_fields,
|
|
241
|
-
index_or_legacy_ids,
|
|
240
|
+
ignored_subsequent_fields: Set,
|
|
241
|
+
index_or_legacy_ids: List[str],
|
|
242
242
|
):
|
|
243
243
|
"""This overwrites the implementation for Auth and instances
|
|
244
244
|
|
|
@@ -261,7 +261,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
261
261
|
ignored_subsequent_fields.add(marc_field.tag)
|
|
262
262
|
|
|
263
263
|
def perform_additional_mapping(
|
|
264
|
-
self, marc_record: Record, folio_holding, legacy_ids: List[str], file_def: FileDefinition
|
|
264
|
+
self, marc_record: Record, folio_holding: Dict, legacy_ids: List[str], file_def: FileDefinition
|
|
265
265
|
):
|
|
266
266
|
"""_summary_
|
|
267
267
|
|
|
@@ -279,11 +279,8 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
279
279
|
self.pick_first_location_if_many(folio_holding, legacy_ids)
|
|
280
280
|
self.parse_coded_holdings_statements(marc_record, folio_holding, legacy_ids)
|
|
281
281
|
HoldingsHelper.handle_notes(folio_holding)
|
|
282
|
-
create_source_records = all(
|
|
283
|
-
[file_def.create_source_records, self.task_configuration.create_source_records]
|
|
284
|
-
)
|
|
285
282
|
if (
|
|
286
|
-
create_source_records
|
|
283
|
+
all([file_def.create_source_records, self.create_source_records])
|
|
287
284
|
or self.task_configuration.hrid_handling == HridHandling.preserve001
|
|
288
285
|
):
|
|
289
286
|
self.hrid_handler.handle_hrid(
|
|
@@ -298,9 +295,9 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
298
295
|
"",
|
|
299
296
|
)
|
|
300
297
|
self.handle_suppression(folio_holding, file_def, True)
|
|
301
|
-
self.set_source_id(self.
|
|
298
|
+
self.set_source_id(self.create_source_records, folio_holding, self.holdingssources, file_def)
|
|
302
299
|
|
|
303
|
-
def pick_first_location_if_many(self, folio_holding, legacy_ids: List[str]):
|
|
300
|
+
def pick_first_location_if_many(self, folio_holding: Dict, legacy_ids: List[str]):
|
|
304
301
|
if " " in folio_holding.get("permanentLocationId", ""):
|
|
305
302
|
Helper.log_data_issue(
|
|
306
303
|
legacy_ids,
|
|
@@ -312,14 +309,14 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
312
309
|
]
|
|
313
310
|
|
|
314
311
|
@staticmethod
|
|
315
|
-
def set_source_id(
|
|
316
|
-
if file_def.create_source_records and
|
|
312
|
+
def set_source_id(create_source_records: bool, folio_rec: Dict, holdingssources: Dict, file_def: FileDefinition):
|
|
313
|
+
if file_def.create_source_records and create_source_records:
|
|
317
314
|
folio_rec["sourceId"] = holdingssources.get("MARC")
|
|
318
315
|
else:
|
|
319
316
|
folio_rec["sourceId"] = holdingssources.get("FOLIO")
|
|
320
317
|
|
|
321
318
|
def parse_coded_holdings_statements(
|
|
322
|
-
self, marc_record: Record, folio_holding, legacy_ids: List[str]
|
|
319
|
+
self, marc_record: Record, folio_holding: Dict, legacy_ids: List[str]
|
|
323
320
|
):
|
|
324
321
|
# TODO: Should one be able to switch these things off?
|
|
325
322
|
a = {
|
|
@@ -351,7 +348,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
351
348
|
x.create_source_records for x in self.task_configuration.files
|
|
352
349
|
]
|
|
353
350
|
if all(source_file_create_source_records):
|
|
354
|
-
create_source_records = self.
|
|
351
|
+
create_source_records = self.create_source_records
|
|
355
352
|
else:
|
|
356
353
|
logging.info(
|
|
357
354
|
"If all source files have create_source_records set to false, "
|
|
@@ -369,7 +366,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
369
366
|
logging.info("Fetching HoldingsRecord schema...")
|
|
370
367
|
return folio_client.get_holdings_schema()
|
|
371
368
|
|
|
372
|
-
def set_holdings_type(self, marc_record: Record, folio_holding, legacy_ids: List[str]):
|
|
369
|
+
def set_holdings_type(self, marc_record: Record, folio_holding: Dict, legacy_ids: List[str]):
|
|
373
370
|
# Holdings type mapping
|
|
374
371
|
ldr06 = marc_record.leader[6]
|
|
375
372
|
# TODO: map this better
|
|
@@ -425,7 +422,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
425
422
|
ldr06,
|
|
426
423
|
)
|
|
427
424
|
|
|
428
|
-
def set_default_call_number_type_if_empty(self, folio_holding):
|
|
425
|
+
def set_default_call_number_type_if_empty(self, folio_holding: Dict):
|
|
429
426
|
if not folio_holding.get("callNumberTypeId", ""):
|
|
430
427
|
folio_holding["callNumberTypeId"] = self.conditions.default_call_number_type["id"]
|
|
431
428
|
|
|
@@ -462,7 +459,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
462
459
|
)
|
|
463
460
|
return results
|
|
464
461
|
|
|
465
|
-
def verity_boundwith_map_entry(self, entry):
|
|
462
|
+
def verity_boundwith_map_entry(self, entry: Dict):
|
|
466
463
|
if "MFHD_ID" not in entry or not entry.get("MFHD_ID", ""):
|
|
467
464
|
raise TransformationProcessError(
|
|
468
465
|
"", "Column MFHD_ID missing from Boundwith relationship map", ""
|
|
@@ -472,7 +469,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
472
469
|
"", "Column BIB_ID missing from Boundwith relationship map", ""
|
|
473
470
|
)
|
|
474
471
|
|
|
475
|
-
def setup_boundwith_relationship_map(self, boundwith_relationship_map):
|
|
472
|
+
def setup_boundwith_relationship_map(self, boundwith_relationship_map: List[Dict]):
|
|
476
473
|
"""
|
|
477
474
|
Creates a map of MFHD_ID to BIB_ID for boundwith relationships.
|
|
478
475
|
|
|
@@ -503,7 +500,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
503
500
|
self.handle_transformation_record_failed_error(idx, trfe)
|
|
504
501
|
return new_map
|
|
505
502
|
|
|
506
|
-
def get_bw_instance_id_map_tuple(self, entry):
|
|
503
|
+
def get_bw_instance_id_map_tuple(self, entry: Dict):
|
|
507
504
|
try:
|
|
508
505
|
return self.parent_id_map[entry["BIB_ID"]]
|
|
509
506
|
except KeyError:
|
|
@@ -18,35 +18,11 @@ from folio_migration_tools.marc_rules_transformation.marc_file_processor import
|
|
|
18
18
|
from folio_migration_tools.marc_rules_transformation.rules_mapper_bibs import (
|
|
19
19
|
BibsRulesMapper,
|
|
20
20
|
)
|
|
21
|
-
from folio_migration_tools.migration_tasks.migration_task_base import MigrationTaskBase
|
|
22
|
-
from folio_migration_tools.task_configuration import AbstractTaskConfiguration
|
|
21
|
+
from folio_migration_tools.migration_tasks.migration_task_base import MarcTaskConfigurationBase, MigrationTaskBase
|
|
23
22
|
|
|
24
23
|
|
|
25
24
|
class BibsTransformer(MigrationTaskBase):
|
|
26
|
-
class TaskConfiguration(
|
|
27
|
-
name: Annotated[
|
|
28
|
-
str,
|
|
29
|
-
Field(
|
|
30
|
-
description=(
|
|
31
|
-
"Name of this migration task. The name is being used to call the specific "
|
|
32
|
-
"task, and to distinguish tasks of similar types"
|
|
33
|
-
)
|
|
34
|
-
),
|
|
35
|
-
]
|
|
36
|
-
migration_task_type: Annotated[
|
|
37
|
-
str,
|
|
38
|
-
Field(
|
|
39
|
-
title="Migration task type",
|
|
40
|
-
description=("The type of migration task you want to perform."),
|
|
41
|
-
),
|
|
42
|
-
]
|
|
43
|
-
files: Annotated[
|
|
44
|
-
List[FileDefinition],
|
|
45
|
-
Field(
|
|
46
|
-
title="Source files",
|
|
47
|
-
description=("List of MARC21 files with bibliographic records."),
|
|
48
|
-
),
|
|
49
|
-
]
|
|
25
|
+
class TaskConfiguration(MarcTaskConfigurationBase):
|
|
50
26
|
ils_flavour: Annotated[
|
|
51
27
|
IlsFlavour,
|
|
52
28
|
Field(
|
|
@@ -87,16 +63,6 @@ class BibsTransformer(MigrationTaskBase):
|
|
|
87
63
|
),
|
|
88
64
|
),
|
|
89
65
|
] = []
|
|
90
|
-
create_source_records: Annotated[
|
|
91
|
-
bool,
|
|
92
|
-
Field(
|
|
93
|
-
title="Create source records",
|
|
94
|
-
description=(
|
|
95
|
-
"Controls wheter or not to retain the MARC records in "
|
|
96
|
-
"Source Record Storage."
|
|
97
|
-
),
|
|
98
|
-
),
|
|
99
|
-
] = True
|
|
100
66
|
data_import_marc: Annotated[
|
|
101
67
|
bool,
|
|
102
68
|
Field(
|
|
@@ -107,7 +73,7 @@ class BibsTransformer(MigrationTaskBase):
|
|
|
107
73
|
"of FOLIO instance records (and optional SRS records) will be generated."
|
|
108
74
|
),
|
|
109
75
|
)
|
|
110
|
-
] =
|
|
76
|
+
] = True
|
|
111
77
|
parse_cataloged_date: Annotated[
|
|
112
78
|
bool,
|
|
113
79
|
Field(
|
|
@@ -118,17 +84,6 @@ class BibsTransformer(MigrationTaskBase):
|
|
|
118
84
|
),
|
|
119
85
|
),
|
|
120
86
|
] = False
|
|
121
|
-
hrid_handling: Annotated[
|
|
122
|
-
HridHandling,
|
|
123
|
-
Field(
|
|
124
|
-
title="HRID Handling",
|
|
125
|
-
description=(
|
|
126
|
-
"Setting to default will make FOLIO generate HRIDs and move the existing "
|
|
127
|
-
"001:s into a 035, concatenated with the 003. Choosing preserve001 means "
|
|
128
|
-
"the 001:s will remain in place, and that they will also become the HRIDs"
|
|
129
|
-
),
|
|
130
|
-
),
|
|
131
|
-
] = HridHandling.default
|
|
132
87
|
reset_hrid_settings: Annotated[
|
|
133
88
|
bool,
|
|
134
89
|
Field(
|
|
@@ -146,16 +101,6 @@ class BibsTransformer(MigrationTaskBase):
|
|
|
146
101
|
description="At the end of the run, update FOLIO with the HRID settings",
|
|
147
102
|
),
|
|
148
103
|
] = True
|
|
149
|
-
deactivate035_from001: Annotated[
|
|
150
|
-
bool,
|
|
151
|
-
Field(
|
|
152
|
-
title="Create 035 from 001 and 003",
|
|
153
|
-
description=(
|
|
154
|
-
"This deactivates the FOLIO default functionality of moving the previous 001 "
|
|
155
|
-
"into a 035, prefixed with the value from 003"
|
|
156
|
-
),
|
|
157
|
-
),
|
|
158
|
-
] = False
|
|
159
104
|
|
|
160
105
|
@staticmethod
|
|
161
106
|
def get_object_type() -> FOLIONamespaces:
|
|
@@ -19,12 +19,11 @@ from folio_migration_tools.library_configuration import (
|
|
|
19
19
|
from folio_migration_tools.marc_rules_transformation.rules_mapper_holdings import (
|
|
20
20
|
RulesMapperHoldings,
|
|
21
21
|
)
|
|
22
|
-
from folio_migration_tools.migration_tasks.migration_task_base import MigrationTaskBase
|
|
23
|
-
from folio_migration_tools.task_configuration import AbstractTaskConfiguration
|
|
22
|
+
from folio_migration_tools.migration_tasks.migration_task_base import MarcTaskConfigurationBase, MigrationTaskBase
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
class HoldingsMarcTransformer(MigrationTaskBase):
|
|
27
|
-
class TaskConfiguration(
|
|
26
|
+
class TaskConfiguration(MarcTaskConfigurationBase):
|
|
28
27
|
name: Annotated[
|
|
29
28
|
str,
|
|
30
29
|
Field(
|
|
@@ -59,16 +58,6 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
59
58
|
),
|
|
60
59
|
),
|
|
61
60
|
] = HridHandling.default
|
|
62
|
-
deactivate035_from001: Annotated[
|
|
63
|
-
bool,
|
|
64
|
-
Field(
|
|
65
|
-
title="Create 035 from 001 and 003",
|
|
66
|
-
description=(
|
|
67
|
-
"This deactivates the FOLIO default functionality of moving the previous 001 "
|
|
68
|
-
"into a 035, prefixed with the value from 003"
|
|
69
|
-
),
|
|
70
|
-
),
|
|
71
|
-
] = False
|
|
72
61
|
holdings_type_uuid_for_boundwiths: Annotated[
|
|
73
62
|
str,
|
|
74
63
|
Field(
|
|
@@ -89,16 +78,6 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
89
78
|
),
|
|
90
79
|
),
|
|
91
80
|
] = ""
|
|
92
|
-
create_source_records: Annotated[
|
|
93
|
-
bool,
|
|
94
|
-
Field(
|
|
95
|
-
title="Create source records",
|
|
96
|
-
description=(
|
|
97
|
-
"Controls wheter or not to retain the MARC records in "
|
|
98
|
-
"Source Record Storage."
|
|
99
|
-
),
|
|
100
|
-
),
|
|
101
|
-
] = True
|
|
102
81
|
update_hrid_settings: Annotated[
|
|
103
82
|
bool,
|
|
104
83
|
Field(
|
|
@@ -9,11 +9,12 @@ from abc import abstractmethod
|
|
|
9
9
|
from datetime import datetime, timezone
|
|
10
10
|
from genericpath import isfile
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Optional
|
|
12
|
+
from typing import Annotated, List, Optional
|
|
13
13
|
|
|
14
14
|
import folioclient
|
|
15
15
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
16
16
|
from folioclient import FolioClient
|
|
17
|
+
from pydantic import Field
|
|
17
18
|
|
|
18
19
|
from folio_migration_tools import library_configuration, task_configuration
|
|
19
20
|
from folio_migration_tools.custom_exceptions import (
|
|
@@ -163,6 +164,7 @@ class MigrationTaskBase:
|
|
|
163
164
|
the central tenant instance ids. This is a bit of a hack, but it works for now.
|
|
164
165
|
"""
|
|
165
166
|
map_files = []
|
|
167
|
+
instance_id_map = {}
|
|
166
168
|
if self.library_configuration.is_ecs and self.central_folder_structure:
|
|
167
169
|
logging.info(
|
|
168
170
|
"Loading ECS central tenant instance id map from %s", self.central_folder_structure.instance_id_map_path
|
|
@@ -459,6 +461,68 @@ class MigrationTaskBase:
|
|
|
459
461
|
return None
|
|
460
462
|
|
|
461
463
|
|
|
464
|
+
class MarcTaskConfigurationBase(task_configuration.AbstractTaskConfiguration):
|
|
465
|
+
"""
|
|
466
|
+
Base class for MARC task configurations.
|
|
467
|
+
|
|
468
|
+
Attributes:
|
|
469
|
+
files (List[library_configuration.FileDefinition]):
|
|
470
|
+
List of MARC21 files to be processed.
|
|
471
|
+
|
|
472
|
+
create_source_records (bool):
|
|
473
|
+
Controls whether or not to retain the MARC records in Source Record Storage.
|
|
474
|
+
Default is False, meaning MARC records will not be retained.
|
|
475
|
+
|
|
476
|
+
hrid_handling (library_configuration.HridHandling):
|
|
477
|
+
Determines how HRIDs are handled.
|
|
478
|
+
- 'default': FOLIO generates HRIDs and moves existing 001 fields into a 035 field, concatenated with the 003 field.
|
|
479
|
+
- 'preserve001': Keeps the 001 fields in place and uses them as HRIDs.
|
|
480
|
+
Default is 'default'.
|
|
481
|
+
|
|
482
|
+
deactivate035_from001 (bool):
|
|
483
|
+
Disables the default FOLIO functionality of moving the previous 001 field into a 035 field, prefixed with the value from 003.
|
|
484
|
+
Default is False, meaning the functionality remains active.
|
|
485
|
+
"""
|
|
486
|
+
|
|
487
|
+
files: Annotated[
|
|
488
|
+
List[library_configuration.FileDefinition],
|
|
489
|
+
Field(
|
|
490
|
+
title="Source files",
|
|
491
|
+
description=("List of MARC21 files with bibliographic records."),
|
|
492
|
+
),
|
|
493
|
+
]
|
|
494
|
+
create_source_records: Annotated[
|
|
495
|
+
bool,
|
|
496
|
+
Field(
|
|
497
|
+
title="Create source records",
|
|
498
|
+
description=(
|
|
499
|
+
"Controls whether or not to retain the MARC records in "
|
|
500
|
+
"Source Record Storage."
|
|
501
|
+
),
|
|
502
|
+
),
|
|
503
|
+
] = False
|
|
504
|
+
hrid_handling: Annotated[
|
|
505
|
+
library_configuration.HridHandling,
|
|
506
|
+
Field(
|
|
507
|
+
title="HRID Handling",
|
|
508
|
+
description=(
|
|
509
|
+
"Setting to default will make FOLIO generate HRIDs and move the existing "
|
|
510
|
+
"001:s into a 035, concatenated with the 003. Choosing preserve001 means "
|
|
511
|
+
"the 001:s will remain in place, and that they will also become the HRIDs"
|
|
512
|
+
),
|
|
513
|
+
),
|
|
514
|
+
] = library_configuration.HridHandling.default
|
|
515
|
+
deactivate035_from001: Annotated[
|
|
516
|
+
bool,
|
|
517
|
+
Field(
|
|
518
|
+
title="Create 035 from 001 and 003",
|
|
519
|
+
description=(
|
|
520
|
+
"This deactivates the FOLIO default functionality of moving the previous 001 "
|
|
521
|
+
"into a 035, prefixed with the value from 003"
|
|
522
|
+
),
|
|
523
|
+
),
|
|
524
|
+
] = False
|
|
525
|
+
|
|
462
526
|
class ExcludeLevelFilter(logging.Filter):
|
|
463
527
|
def __init__(self, level):
|
|
464
528
|
super().__init__()
|
|
@@ -10,7 +10,24 @@ def to_camel(string):
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class AbstractTaskConfiguration(BaseModel):
|
|
13
|
-
|
|
13
|
+
"""Abstract class for task configuration."""
|
|
14
|
+
|
|
15
|
+
name: Annotated[
|
|
16
|
+
str,
|
|
17
|
+
Field(
|
|
18
|
+
description=(
|
|
19
|
+
"Name of this migration task. The name is being used to call the specific "
|
|
20
|
+
"task, and to distinguish tasks of similar types"
|
|
21
|
+
)
|
|
22
|
+
),
|
|
23
|
+
]
|
|
24
|
+
migration_task_type: Annotated[
|
|
25
|
+
str,
|
|
26
|
+
Field(
|
|
27
|
+
title="Migration task type",
|
|
28
|
+
description=("The type of migration task you want to perform."),
|
|
29
|
+
),
|
|
30
|
+
]
|
|
14
31
|
ecs_tenant_id: Annotated[
|
|
15
32
|
str,
|
|
16
33
|
Field(
|
|
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
|
|
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
|