folio-migration-tools 1.9.0rc7__py3-none-any.whl → 1.9.0rc8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- folio_migration_tools/__main__.py +17 -5
- folio_migration_tools/folder_structure.py +5 -0
- folio_migration_tools/library_configuration.py +41 -3
- folio_migration_tools/mapper_base.py +11 -38
- folio_migration_tools/mapping_file_transformation/courses_mapper.py +1 -1
- folio_migration_tools/mapping_file_transformation/item_mapper.py +0 -4
- folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +1 -1
- folio_migration_tools/mapping_file_transformation/user_mapper.py +1 -1
- folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +1 -1
- folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +11 -6
- folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +1 -1
- folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +52 -1
- folio_migration_tools/migration_tasks/holdings_csv_transformer.py +1 -13
- folio_migration_tools/migration_tasks/holdings_marc_transformer.py +12 -3
- folio_migration_tools/migration_tasks/items_transformer.py +22 -17
- folio_migration_tools/migration_tasks/loans_migrator.py +2 -9
- folio_migration_tools/migration_tasks/migration_task_base.py +50 -6
- folio_migration_tools/migration_tasks/orders_transformer.py +1 -1
- folio_migration_tools/migration_tasks/user_transformer.py +2 -10
- folio_migration_tools/test_infrastructure/mocked_classes.py +63 -0
- {folio_migration_tools-1.9.0rc7.dist-info → folio_migration_tools-1.9.0rc8.dist-info}/METADATA +2 -1
- {folio_migration_tools-1.9.0rc7.dist-info → folio_migration_tools-1.9.0rc8.dist-info}/RECORD +25 -25
- {folio_migration_tools-1.9.0rc7.dist-info → folio_migration_tools-1.9.0rc8.dist-info}/LICENSE +0 -0
- {folio_migration_tools-1.9.0rc7.dist-info → folio_migration_tools-1.9.0rc8.dist-info}/WHEEL +0 -0
- {folio_migration_tools-1.9.0rc7.dist-info → folio_migration_tools-1.9.0rc8.dist-info}/entry_points.txt +0 -0
|
@@ -62,6 +62,22 @@ def parse_args(args):
|
|
|
62
62
|
)
|
|
63
63
|
return parser.parse_args(args)
|
|
64
64
|
|
|
65
|
+
def prep_library_config(args):
|
|
66
|
+
config_file_humped = merge_load(args.configuration_path)
|
|
67
|
+
config_file_humped["libraryInformation"]["okapiPassword"] = args.okapi_password
|
|
68
|
+
config_file_humped["libraryInformation"]["baseFolder"] = args.base_folder_path
|
|
69
|
+
config_file = humps.decamelize(config_file_humped)
|
|
70
|
+
library_config = LibraryConfiguration(**config_file["library_information"])
|
|
71
|
+
if library_config.ecs_tenant_id:
|
|
72
|
+
library_config.is_ecs = True
|
|
73
|
+
if library_config.ecs_tenant_id and not library_config.ecs_central_iteration_identifier:
|
|
74
|
+
print(
|
|
75
|
+
"ECS tenant ID is set, but no central iteration identifier is provided. "
|
|
76
|
+
"Please provide the central iteration identifier in the configuration file."
|
|
77
|
+
)
|
|
78
|
+
sys.exit("ECS Central Iteration Identifier Not Found")
|
|
79
|
+
return config_file, library_config
|
|
80
|
+
|
|
65
81
|
|
|
66
82
|
def main():
|
|
67
83
|
try:
|
|
@@ -79,11 +95,7 @@ def main():
|
|
|
79
95
|
except i18n.I18nFileLoadError:
|
|
80
96
|
i18n.load_config(Path(__file__).parent / "i18n_config.py")
|
|
81
97
|
i18n.set("locale", args.report_language)
|
|
82
|
-
|
|
83
|
-
config_file_humped["libraryInformation"]["okapiPassword"] = args.okapi_password
|
|
84
|
-
config_file_humped["libraryInformation"]["baseFolder"] = args.base_folder_path
|
|
85
|
-
config_file = humps.decamelize(config_file_humped)
|
|
86
|
-
library_config = LibraryConfiguration(**config_file["library_information"])
|
|
98
|
+
config_file, library_config = prep_library_config(args)
|
|
87
99
|
try:
|
|
88
100
|
migration_task_config = next(
|
|
89
101
|
t for t in config_file["migration_tasks"] if t["name"] == args.task_name
|
|
@@ -120,6 +120,9 @@ class FolderStructure:
|
|
|
120
120
|
self.id_map_path = (
|
|
121
121
|
self.results_folder / f"{str(self.object_type.name).lower()}_id_map.json"
|
|
122
122
|
)
|
|
123
|
+
self.boundwith_relationships_map_path = (
|
|
124
|
+
self.results_folder / "boundwith_relationships_map.json"
|
|
125
|
+
)
|
|
123
126
|
# Mapping files
|
|
124
127
|
self.material_type_map_path = self.mapping_files_folder / "material_types.tsv"
|
|
125
128
|
self.loan_type_map_path = self.mapping_files_folder / "loan_types.tsv"
|
|
@@ -139,6 +142,8 @@ class FolderStructure:
|
|
|
139
142
|
def verify_git_ignore(gitignore: Path):
|
|
140
143
|
with open(gitignore, "r+") as f:
|
|
141
144
|
contents = f.read()
|
|
145
|
+
if "reports/" not in contents:
|
|
146
|
+
f.write("reports/\n")
|
|
142
147
|
if "results/" not in contents:
|
|
143
148
|
f.write("results/\n")
|
|
144
149
|
if "archive/" not in contents:
|
|
@@ -90,13 +90,20 @@ class LibraryConfiguration(BaseModel):
|
|
|
90
90
|
)
|
|
91
91
|
multi_field_delimiter: Optional[str] = "<delimiter>"
|
|
92
92
|
failed_records_threshold: Annotated[
|
|
93
|
-
int,
|
|
93
|
+
int,
|
|
94
|
+
Field(description=("Number of failed records until the process shuts down")),
|
|
94
95
|
] = 5000
|
|
95
96
|
failed_percentage_threshold: Annotated[
|
|
96
|
-
int,
|
|
97
|
+
int,
|
|
98
|
+
Field(
|
|
99
|
+
description=("Percentage of failed records until the process shuts down")
|
|
100
|
+
),
|
|
97
101
|
] = 20
|
|
98
102
|
generic_exception_threshold: Annotated[
|
|
99
|
-
int,
|
|
103
|
+
int,
|
|
104
|
+
Field(
|
|
105
|
+
description=("Number of generic exceptions until the process shuts down")
|
|
106
|
+
),
|
|
100
107
|
] = 50
|
|
101
108
|
library_name: str
|
|
102
109
|
log_level_debug: bool
|
|
@@ -111,3 +118,34 @@ class LibraryConfiguration(BaseModel):
|
|
|
111
118
|
add_time_stamp_to_file_names: Annotated[
|
|
112
119
|
bool, Field(title="Add time stamp to file names")
|
|
113
120
|
] = False
|
|
121
|
+
use_gateway_url_for_uuids: Annotated[
|
|
122
|
+
bool,
|
|
123
|
+
Field(
|
|
124
|
+
title="Use gateway URL for UUIDs",
|
|
125
|
+
description=(
|
|
126
|
+
"If set to true, folio_uuid will use the gateway URL when generating deterministic UUIDs for FOLIO records. "
|
|
127
|
+
"If set to false (default), the UUIDs will be generated using the tenant_id (or ecs_tenant_id)."
|
|
128
|
+
),
|
|
129
|
+
),
|
|
130
|
+
] = False
|
|
131
|
+
is_ecs: Annotated[
|
|
132
|
+
bool,
|
|
133
|
+
Field(
|
|
134
|
+
title="Library is running ECS FOLIO",
|
|
135
|
+
description=(
|
|
136
|
+
"If set to true, the migration is running in an ECS environment. "
|
|
137
|
+
"If set to false (default), the migration is running in a non-ECS environment. "
|
|
138
|
+
"If ecs_tenant_id is set, this will be set to true, regardless of the value here."
|
|
139
|
+
),
|
|
140
|
+
),
|
|
141
|
+
] = False
|
|
142
|
+
ecs_central_iteration_identifier: Annotated[
|
|
143
|
+
str,
|
|
144
|
+
Field(
|
|
145
|
+
title="ECS central iteration identifier",
|
|
146
|
+
description=(
|
|
147
|
+
"The iteration_identifier value from the central tenant configuration that corresponds "
|
|
148
|
+
"to this configuration's iteration_identifier. Used to access the central instances_id_map."
|
|
149
|
+
),
|
|
150
|
+
),
|
|
151
|
+
] = ""
|
|
@@ -293,42 +293,6 @@ class MapperBase:
|
|
|
293
293
|
)
|
|
294
294
|
sys.exit(1)
|
|
295
295
|
|
|
296
|
-
def setup_boundwith_relationship_map(self, boundwith_relationship_map):
|
|
297
|
-
new_map = {}
|
|
298
|
-
for entry in boundwith_relationship_map:
|
|
299
|
-
if "MFHD_ID" not in entry or not entry.get("MFHD_ID", ""):
|
|
300
|
-
raise TransformationProcessError(
|
|
301
|
-
"", "Column MFHD_ID missing from Boundwith relationship map", ""
|
|
302
|
-
)
|
|
303
|
-
if "BIB_ID" not in entry or not entry.get("BIB_ID", ""):
|
|
304
|
-
raise TransformationProcessError(
|
|
305
|
-
"", "Column BIB_ID missing from Boundwith relationship map", ""
|
|
306
|
-
)
|
|
307
|
-
instance_uuid = str(
|
|
308
|
-
FolioUUID(
|
|
309
|
-
str(self.folio_client.okapi_url),
|
|
310
|
-
FOLIONamespaces.instances,
|
|
311
|
-
entry["BIB_ID"],
|
|
312
|
-
)
|
|
313
|
-
)
|
|
314
|
-
mfhd_uuid = str(
|
|
315
|
-
FolioUUID(
|
|
316
|
-
str(self.folio_client.okapi_url),
|
|
317
|
-
FOLIONamespaces.holdings,
|
|
318
|
-
entry["MFHD_ID"],
|
|
319
|
-
)
|
|
320
|
-
)
|
|
321
|
-
if entry["BIB_ID"] in self.parent_id_map:
|
|
322
|
-
new_map[mfhd_uuid] = new_map.get(mfhd_uuid, []) + [instance_uuid]
|
|
323
|
-
else:
|
|
324
|
-
raise TransformationRecordFailedError(
|
|
325
|
-
entry["MFHD_ID"],
|
|
326
|
-
"Boundwith relationship map contains a BIB_ID id not in the instance id map. No boundwith holdings created.",
|
|
327
|
-
entry["BIB_ID"],
|
|
328
|
-
)
|
|
329
|
-
|
|
330
|
-
return new_map
|
|
331
|
-
|
|
332
296
|
def save_id_map_file(self, path, legacy_map: dict):
|
|
333
297
|
with open(path, "w") as legacy_map_file:
|
|
334
298
|
for id_string in legacy_map.values():
|
|
@@ -417,7 +381,7 @@ class MapperBase:
|
|
|
417
381
|
"holdingsRecordId": bound_with_holding_uuid,
|
|
418
382
|
"itemId": str(
|
|
419
383
|
FolioUUID(
|
|
420
|
-
self.
|
|
384
|
+
self.base_string_for_folio_uuid,
|
|
421
385
|
FOLIONamespaces.items,
|
|
422
386
|
legacy_item_id,
|
|
423
387
|
)
|
|
@@ -470,12 +434,21 @@ class MapperBase:
|
|
|
470
434
|
def generate_boundwith_holding_uuid(self, holding_uuid, instance_uuid):
|
|
471
435
|
return str(
|
|
472
436
|
FolioUUID(
|
|
473
|
-
self.
|
|
437
|
+
self.base_string_for_folio_uuid,
|
|
474
438
|
FOLIONamespaces.holdings,
|
|
475
439
|
f"{holding_uuid}-{instance_uuid}",
|
|
476
440
|
)
|
|
477
441
|
)
|
|
478
442
|
|
|
443
|
+
@property
|
|
444
|
+
def base_string_for_folio_uuid(self):
|
|
445
|
+
if self.library_configuration.use_gateway_url_for_uuids and not self.library_configuration.is_ecs:
|
|
446
|
+
return str(self.folio_client.okapi_url)
|
|
447
|
+
elif self.library_configuration.ecs_tenant_id:
|
|
448
|
+
return str(self.library_configuration.ecs_tenant_id)
|
|
449
|
+
else:
|
|
450
|
+
return str(self.library_configuration.tenant_id)
|
|
451
|
+
|
|
479
452
|
@staticmethod
|
|
480
453
|
def validate_location_map(location_map: List[Dict], locations: List[Dict]) -> List[Dict]:
|
|
481
454
|
mapped_codes = [x['folio_code'] for x in location_map]
|
|
@@ -121,7 +121,7 @@ class CoursesMapper(MappingFileMapperBase):
|
|
|
121
121
|
def get_uuid(self, composite_course, object_type: FOLIONamespaces, idx: int = 0):
|
|
122
122
|
return str(
|
|
123
123
|
FolioUUID(
|
|
124
|
-
self.
|
|
124
|
+
self.base_string_for_folio_uuid,
|
|
125
125
|
object_type,
|
|
126
126
|
composite_course[1] if idx == 0 else f"{composite_course[1]}_{idx}",
|
|
127
127
|
)
|
|
@@ -42,7 +42,6 @@ class ItemMapper(MappingFileMapperBase):
|
|
|
42
42
|
temporary_loan_type_mapping,
|
|
43
43
|
temporary_location_mapping,
|
|
44
44
|
library_configuration: LibraryConfiguration,
|
|
45
|
-
boundwith_relationship_map,
|
|
46
45
|
task_configuration: AbstractTaskConfiguration,
|
|
47
46
|
):
|
|
48
47
|
item_schema = folio_client.get_item_schema()
|
|
@@ -99,9 +98,6 @@ class ItemMapper(MappingFileMapperBase):
|
|
|
99
98
|
"name",
|
|
100
99
|
"PermanentLoanTypeMapping",
|
|
101
100
|
)
|
|
102
|
-
self.boundwith_relationship_map = self.setup_boundwith_relationship_map(
|
|
103
|
-
boundwith_relationship_map
|
|
104
|
-
)
|
|
105
101
|
|
|
106
102
|
self.material_type_mapping = RefDataMapping(
|
|
107
103
|
self.folio_client,
|
|
@@ -158,7 +158,7 @@ class UserMapper(MappingFileMapperBase):
|
|
|
158
158
|
self.departments_mapping,
|
|
159
159
|
legacy_user,
|
|
160
160
|
index_or_id,
|
|
161
|
-
|
|
161
|
+
True,
|
|
162
162
|
)
|
|
163
163
|
elif folio_prop_name in ["expirationDate", "enrollmentDate", "personal.dateOfBirth"]:
|
|
164
164
|
return self.get_parsed_date(mapped_value, folio_prop_name)
|
|
@@ -810,8 +810,8 @@ class RulesMapperBase(MapperBase):
|
|
|
810
810
|
)
|
|
811
811
|
data_import_marc_file.write(marc_record.as_marc())
|
|
812
812
|
|
|
813
|
-
@staticmethod
|
|
814
813
|
def save_source_record(
|
|
814
|
+
self,
|
|
815
815
|
srs_records_file,
|
|
816
816
|
record_type: FOLIONamespaces,
|
|
817
817
|
folio_client: FolioClient,
|
|
@@ -831,7 +831,7 @@ class RulesMapperBase(MapperBase):
|
|
|
831
831
|
legacy_ids (List[str]): _description_
|
|
832
832
|
suppress (bool): _description_
|
|
833
833
|
"""
|
|
834
|
-
srs_id =
|
|
834
|
+
srs_id = self.create_srs_id(record_type, legacy_ids[-1])
|
|
835
835
|
|
|
836
836
|
marc_record.add_ordered_field(
|
|
837
837
|
Field(
|
|
@@ -850,7 +850,7 @@ class RulesMapperBase(MapperBase):
|
|
|
850
850
|
logging.exception(
|
|
851
851
|
"Something is wrong with the marc record's leader: %s, %s", marc_record.leader, ee
|
|
852
852
|
)
|
|
853
|
-
srs_record_string =
|
|
853
|
+
srs_record_string = self.get_srs_string(
|
|
854
854
|
marc_record,
|
|
855
855
|
folio_record,
|
|
856
856
|
srs_id,
|
|
@@ -859,8 +859,7 @@ class RulesMapperBase(MapperBase):
|
|
|
859
859
|
)
|
|
860
860
|
srs_records_file.write(f"{srs_record_string}\n")
|
|
861
861
|
|
|
862
|
-
|
|
863
|
-
def create_srs_id(record_type, okapi_url: str, legacy_id: str):
|
|
862
|
+
def create_srs_id(self, record_type, legacy_id: str):
|
|
864
863
|
srs_types = {
|
|
865
864
|
FOLIONamespaces.holdings: FOLIONamespaces.srs_records_holdingsrecord,
|
|
866
865
|
FOLIONamespaces.instances: FOLIONamespaces.srs_records_bib,
|
|
@@ -868,7 +867,13 @@ class RulesMapperBase(MapperBase):
|
|
|
868
867
|
FOLIONamespaces.edifact: FOLIONamespaces.srs_records_edifact,
|
|
869
868
|
}
|
|
870
869
|
|
|
871
|
-
return str(
|
|
870
|
+
return str(
|
|
871
|
+
FolioUUID(
|
|
872
|
+
self.base_string_for_folio_uuid,
|
|
873
|
+
srs_types.get(record_type),
|
|
874
|
+
legacy_id
|
|
875
|
+
)
|
|
876
|
+
)
|
|
872
877
|
|
|
873
878
|
@staticmethod
|
|
874
879
|
def get_bib_id_from_907y(marc_record: Record, index_or_legacy_id):
|
|
@@ -211,7 +211,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
211
211
|
folio_holding: dict = {}
|
|
212
212
|
folio_holding["id"] = str(
|
|
213
213
|
FolioUUID(
|
|
214
|
-
|
|
214
|
+
self.base_string_for_folio_uuid,
|
|
215
215
|
FOLIONamespaces.holdings,
|
|
216
216
|
str(legacy_ids[0]),
|
|
217
217
|
)
|
|
@@ -461,3 +461,54 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
461
461
|
idx, f"No legacy id found in record from {marc_path}", ""
|
|
462
462
|
)
|
|
463
463
|
return results
|
|
464
|
+
|
|
465
|
+
def verity_boundwith_map_entry(self, entry):
|
|
466
|
+
if "MFHD_ID" not in entry or not entry.get("MFHD_ID", ""):
|
|
467
|
+
raise TransformationProcessError(
|
|
468
|
+
"", "Column MFHD_ID missing from Boundwith relationship map", ""
|
|
469
|
+
)
|
|
470
|
+
if "BIB_ID" not in entry or not entry.get("BIB_ID", ""):
|
|
471
|
+
raise TransformationProcessError(
|
|
472
|
+
"", "Column BIB_ID missing from Boundwith relationship map", ""
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
def setup_boundwith_relationship_map(self, boundwith_relationship_map):
|
|
476
|
+
"""
|
|
477
|
+
Creates a map of MFHD_ID to BIB_ID for boundwith relationships.
|
|
478
|
+
|
|
479
|
+
Arguments:
|
|
480
|
+
boundwith_relationship_map: A list of dictionaries containing the MFHD_ID and BIB_ID.
|
|
481
|
+
|
|
482
|
+
Returns:
|
|
483
|
+
A dictionary mapping MFHD_ID to a list of BIB_IDs.
|
|
484
|
+
|
|
485
|
+
Raises:
|
|
486
|
+
TransformationProcessError: If MFHD_ID or BIB_ID is missing from the entry or if the instance_uuid is not in the parent_id_map.
|
|
487
|
+
TransformationRecordFailedError: If BIB_ID is not in the instance id map.
|
|
488
|
+
"""
|
|
489
|
+
new_map = {}
|
|
490
|
+
for idx, entry in enumerate(boundwith_relationship_map):
|
|
491
|
+
self.verity_boundwith_map_entry(entry)
|
|
492
|
+
mfhd_uuid = str(
|
|
493
|
+
FolioUUID(
|
|
494
|
+
self.base_string_for_folio_uuid,
|
|
495
|
+
FOLIONamespaces.holdings,
|
|
496
|
+
entry["MFHD_ID"],
|
|
497
|
+
)
|
|
498
|
+
)
|
|
499
|
+
try:
|
|
500
|
+
parent_id_tuple = self.get_bw_instance_id_map_tuple(entry)
|
|
501
|
+
new_map[mfhd_uuid] = new_map.get(mfhd_uuid, []) + [parent_id_tuple[1]]
|
|
502
|
+
except TransformationRecordFailedError as trfe:
|
|
503
|
+
self.handle_transformation_record_failed_error(idx, trfe)
|
|
504
|
+
return new_map
|
|
505
|
+
|
|
506
|
+
def get_bw_instance_id_map_tuple(self, entry):
|
|
507
|
+
try:
|
|
508
|
+
return self.parent_id_map[entry["BIB_ID"]]
|
|
509
|
+
except KeyError:
|
|
510
|
+
raise TransformationRecordFailedError(
|
|
511
|
+
entry["MFHD_ID"],
|
|
512
|
+
"Boundwith relationship map contains a BIB_ID id not in the instance id map. No boundwith holdings created for this BIB_ID.",
|
|
513
|
+
entry["BIB_ID"],
|
|
514
|
+
)
|
|
@@ -182,7 +182,7 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
182
182
|
self.load_mapped_fields(),
|
|
183
183
|
self.load_location_map(),
|
|
184
184
|
self.load_call_number_type_map(),
|
|
185
|
-
self.
|
|
185
|
+
self.load_instance_id_map(True),
|
|
186
186
|
library_config,
|
|
187
187
|
)
|
|
188
188
|
self.holdings = {}
|
|
@@ -296,18 +296,6 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
296
296
|
)
|
|
297
297
|
return holdings_map
|
|
298
298
|
|
|
299
|
-
def load_instance_id_map(self):
|
|
300
|
-
res = {}
|
|
301
|
-
with open(self.folder_structure.instance_id_map_path, "r") as instance_id_map_file:
|
|
302
|
-
for index, json_string in enumerate(instance_id_map_file):
|
|
303
|
-
# Format:{"legacy_id", "folio_id","instanceLevelCallNumber"}
|
|
304
|
-
if index % 500000 == 0:
|
|
305
|
-
print(f"{index} instance ids loaded to map", end="\r")
|
|
306
|
-
map_object = json.loads(json_string)
|
|
307
|
-
res[map_object["legacy_id"]] = map_object
|
|
308
|
-
logging.info("Loaded %s migrated instance IDs", (index + 1))
|
|
309
|
-
return res
|
|
310
|
-
|
|
311
299
|
def do_work(self):
|
|
312
300
|
logging.info("Starting....")
|
|
313
301
|
for file_def in self.task_config.files:
|
|
@@ -229,9 +229,7 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
229
229
|
self.check_source_files(
|
|
230
230
|
self.folder_structure.legacy_records_folder, self.task_config.files
|
|
231
231
|
)
|
|
232
|
-
self.instance_id_map = self.
|
|
233
|
-
self.folder_structure.instance_id_map_path, True
|
|
234
|
-
)
|
|
232
|
+
self.instance_id_map = self.load_instance_id_map(True)
|
|
235
233
|
self.mapper = RulesMapperHoldings(
|
|
236
234
|
self.folio_client,
|
|
237
235
|
self.location_map,
|
|
@@ -283,6 +281,17 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
283
281
|
logging.info("Done. Transformer Wrapping up...")
|
|
284
282
|
self.extradata_writer.flush()
|
|
285
283
|
self.processor.wrap_up()
|
|
284
|
+
if self.mapper.boundwith_relationship_map:
|
|
285
|
+
with open(
|
|
286
|
+
self.folder_structure.boundwith_relationships_map_path, "w+"
|
|
287
|
+
) as boundwith_relationship_file:
|
|
288
|
+
logging.info(
|
|
289
|
+
"Writing boundwiths relationship map to %s",
|
|
290
|
+
boundwith_relationship_file.name,
|
|
291
|
+
)
|
|
292
|
+
for key, val in self.mapper.boundwith_relationship_map.items():
|
|
293
|
+
boundwith_relationship_file.write(json.dumps((key, val)) + "\n")
|
|
294
|
+
|
|
286
295
|
with open(self.folder_structure.migration_reports_file, "w+") as report_file:
|
|
287
296
|
self.mapper.migration_report.write_migration_report(
|
|
288
297
|
i18n.t("Bibliographic records transformation report"),
|
|
@@ -233,7 +233,8 @@ class ItemsTransformer(MigrationTaskBase):
|
|
|
233
233
|
).is_file():
|
|
234
234
|
temporary_loan_type_mapping = self.load_ref_data_mapping_file(
|
|
235
235
|
"temporaryLoanTypeId",
|
|
236
|
-
self.folder_structure.
|
|
236
|
+
self.folder_structure.mapping_files_folder
|
|
237
|
+
/ self.task_config.temp_loan_types_map_file_name,
|
|
237
238
|
self.folio_keys,
|
|
238
239
|
)
|
|
239
240
|
else:
|
|
@@ -243,20 +244,9 @@ class ItemsTransformer(MigrationTaskBase):
|
|
|
243
244
|
)
|
|
244
245
|
temporary_loan_type_mapping = None
|
|
245
246
|
# Load Boundwith relationship map
|
|
246
|
-
self.boundwith_relationship_map =
|
|
247
|
+
self.boundwith_relationship_map = {}
|
|
247
248
|
if self.task_config.boundwith_relationship_file_path:
|
|
248
|
-
|
|
249
|
-
self.folder_structure.data_folder
|
|
250
|
-
/ FOLIONamespaces.holdings.name
|
|
251
|
-
/ self.task_config.boundwith_relationship_file_path
|
|
252
|
-
) as boundwith_relationship_file:
|
|
253
|
-
self.boundwith_relationship_map = list(
|
|
254
|
-
csv.DictReader(boundwith_relationship_file, dialect="tsv")
|
|
255
|
-
)
|
|
256
|
-
logging.info(
|
|
257
|
-
"Rows in Bound with relationship map: %s", len(self.boundwith_relationship_map)
|
|
258
|
-
)
|
|
259
|
-
|
|
249
|
+
self.load_boundwith_relationships()
|
|
260
250
|
if (
|
|
261
251
|
self.folder_structure.mapping_files_folder
|
|
262
252
|
/ self.task_config.temp_location_map_file_name
|
|
@@ -312,7 +302,6 @@ class ItemsTransformer(MigrationTaskBase):
|
|
|
312
302
|
temporary_loan_type_mapping,
|
|
313
303
|
temporary_location_mapping,
|
|
314
304
|
self.library_configuration,
|
|
315
|
-
self.boundwith_relationship_map,
|
|
316
305
|
self.task_configuration
|
|
317
306
|
)
|
|
318
307
|
if (
|
|
@@ -367,9 +356,9 @@ class ItemsTransformer(MigrationTaskBase):
|
|
|
367
356
|
self.mapper.perform_additional_mappings(folio_rec, file_def)
|
|
368
357
|
self.handle_circiulation_notes(folio_rec, self.folio_client.current_user)
|
|
369
358
|
self.handle_notes(folio_rec)
|
|
370
|
-
if folio_rec["holdingsRecordId"] in self.
|
|
359
|
+
if folio_rec["holdingsRecordId"] in self.boundwith_relationship_map:
|
|
371
360
|
for idx_, instance_id in enumerate(
|
|
372
|
-
self.
|
|
361
|
+
self.boundwith_relationship_map.get(
|
|
373
362
|
folio_rec["holdingsRecordId"]
|
|
374
363
|
)
|
|
375
364
|
):
|
|
@@ -456,6 +445,22 @@ class ItemsTransformer(MigrationTaskBase):
|
|
|
456
445
|
else:
|
|
457
446
|
del folio_rec["circulationNotes"]
|
|
458
447
|
|
|
448
|
+
def load_boundwith_relationships(self):
|
|
449
|
+
try:
|
|
450
|
+
with open(
|
|
451
|
+
self.folder_structure.boundwith_relationships_map_path
|
|
452
|
+
) as boundwith_relationship_file:
|
|
453
|
+
self.boundwith_relationship_map = dict(
|
|
454
|
+
json.loads(x) for x in boundwith_relationship_file
|
|
455
|
+
)
|
|
456
|
+
logging.info(
|
|
457
|
+
"Rows in Bound with relationship map: %s", len(self.boundwith_relationship_map)
|
|
458
|
+
)
|
|
459
|
+
except FileNotFoundError:
|
|
460
|
+
raise TransformationProcessError(
|
|
461
|
+
"", "Boundwith relationship file specified, but relationships file from holdings transformation not found. ", self.folder_structure.boundwith_relationships_map_path
|
|
462
|
+
)
|
|
463
|
+
|
|
459
464
|
def wrap_up(self):
|
|
460
465
|
logging.info("Done. Transformer wrapping up...")
|
|
461
466
|
self.extradata_writer.flush()
|
|
@@ -14,12 +14,12 @@ from pydantic import Field
|
|
|
14
14
|
import i18n
|
|
15
15
|
from dateutil import parser as du_parser
|
|
16
16
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
17
|
+
from art import tprint
|
|
17
18
|
|
|
18
19
|
from folio_migration_tools.circulation_helper import CirculationHelper
|
|
19
20
|
from folio_migration_tools.helper import Helper
|
|
20
21
|
from folio_migration_tools.library_configuration import (
|
|
21
22
|
FileDefinition,
|
|
22
|
-
FolioRelease,
|
|
23
23
|
LibraryConfiguration,
|
|
24
24
|
)
|
|
25
25
|
from folio_migration_tools.mapping_file_transformation.mapping_file_mapper_base import (
|
|
@@ -781,11 +781,4 @@ def timings(t0, t0func, num_objects):
|
|
|
781
781
|
|
|
782
782
|
|
|
783
783
|
def print_smtp_warning():
|
|
784
|
-
|
|
785
|
-
_____ __ __ _____ ______ ___
|
|
786
|
-
/ ____| | \/ | |_ _| | __ | |__ \\
|
|
787
|
-
| (___ | \ / | | | | |__|_| ) |
|
|
788
|
-
\___ \ | |\/| | | | | | / /
|
|
789
|
-
|_____/ |_| |_| |_| |_| (_)
|
|
790
|
-
""" # noqa: E501, W605
|
|
791
|
-
print(s)
|
|
784
|
+
tprint("\nSMTP?\n", space=2)
|
|
@@ -9,6 +9,7 @@ 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
13
|
|
|
13
14
|
import folioclient
|
|
14
15
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
@@ -54,6 +55,15 @@ class MigrationTaskBase:
|
|
|
54
55
|
{"x-okapi-tenant": self.ecs_tenant_id} if self.ecs_tenant_id else {}
|
|
55
56
|
)
|
|
56
57
|
self.folio_client.okapi_headers.update(self.ecs_tenant_header)
|
|
58
|
+
self.central_folder_structure: Optional[FolderStructure] = None
|
|
59
|
+
if library_configuration.is_ecs and library_configuration.ecs_central_iteration_identifier:
|
|
60
|
+
self.central_folder_structure = FolderStructure(
|
|
61
|
+
library_configuration.base_folder,
|
|
62
|
+
FOLIONamespaces.instances,
|
|
63
|
+
task_configuration.name,
|
|
64
|
+
library_configuration.ecs_central_iteration_identifier,
|
|
65
|
+
library_configuration.add_time_stamp_to_file_names,
|
|
66
|
+
)
|
|
57
67
|
self.folder_structure: FolderStructure = FolderStructure(
|
|
58
68
|
library_configuration.base_folder,
|
|
59
69
|
self.get_object_type(),
|
|
@@ -66,6 +76,8 @@ class MigrationTaskBase:
|
|
|
66
76
|
self.object_type = self.get_object_type()
|
|
67
77
|
try:
|
|
68
78
|
self.folder_structure.setup_migration_file_structure()
|
|
79
|
+
if self.central_folder_structure:
|
|
80
|
+
self.central_folder_structure.setup_migration_file_structure()
|
|
69
81
|
# Initiate Worker
|
|
70
82
|
except FileNotFoundError as fne:
|
|
71
83
|
logging.error(fne)
|
|
@@ -143,15 +155,47 @@ class MigrationTaskBase:
|
|
|
143
155
|
for filename in files:
|
|
144
156
|
logging.info("\t%s", filename)
|
|
145
157
|
|
|
158
|
+
def load_instance_id_map(self, raise_if_empty=True) -> dict:
|
|
159
|
+
"""
|
|
160
|
+
This method handles loading instance id maps for holdings and other transformations that require it.
|
|
161
|
+
This is in the base class because multiple tasks need it. It exists because instances in an ECS environment
|
|
162
|
+
are transformed for the central and data tenants separately, but the data tenants need to know about
|
|
163
|
+
the central tenant instance ids. This is a bit of a hack, but it works for now.
|
|
164
|
+
"""
|
|
165
|
+
map_files = []
|
|
166
|
+
if self.library_configuration.is_ecs and self.central_folder_structure:
|
|
167
|
+
logging.info(
|
|
168
|
+
"Loading ECS central tenant instance id map from %s", self.central_folder_structure.instance_id_map_path
|
|
169
|
+
)
|
|
170
|
+
instance_id_map = self.load_id_map(
|
|
171
|
+
self.central_folder_structure.instance_id_map_path,
|
|
172
|
+
raise_if_empty=False,
|
|
173
|
+
)
|
|
174
|
+
map_files.append(str(self.central_folder_structure.instance_id_map_path))
|
|
175
|
+
logging.info(
|
|
176
|
+
"Loading member tenant isntance id map from %s",
|
|
177
|
+
self.folder_structure.instance_id_map_path
|
|
178
|
+
)
|
|
179
|
+
instance_id_map = self.load_id_map(
|
|
180
|
+
self.folder_structure.instance_id_map_path,
|
|
181
|
+
raise_if_empty=False,
|
|
182
|
+
existing_id_map=instance_id_map,
|
|
183
|
+
)
|
|
184
|
+
map_files.append(str(self.folder_structure.instance_id_map_path))
|
|
185
|
+
if not any(instance_id_map) and raise_if_empty:
|
|
186
|
+
map_file_paths = ", ".join(map_files)
|
|
187
|
+
raise TransformationProcessError("", "Instance id map is empty", map_file_paths)
|
|
188
|
+
return instance_id_map
|
|
189
|
+
|
|
146
190
|
@staticmethod
|
|
147
|
-
def load_id_map(map_path, raise_if_empty=False):
|
|
191
|
+
def load_id_map(map_path, raise_if_empty=False, existing_id_map={}):
|
|
148
192
|
if not isfile(map_path):
|
|
149
|
-
logging.
|
|
193
|
+
logging.warning(
|
|
150
194
|
"No legacy id map found at %s. Will build one from scratch", map_path
|
|
151
195
|
)
|
|
152
196
|
return {}
|
|
153
|
-
id_map =
|
|
154
|
-
loaded_rows =
|
|
197
|
+
id_map = existing_id_map
|
|
198
|
+
loaded_rows = len(id_map)
|
|
155
199
|
with open(map_path) as id_map_file:
|
|
156
200
|
for index, json_string in enumerate(id_map_file, start=1):
|
|
157
201
|
loaded_rows = index
|
|
@@ -159,12 +203,12 @@ class MigrationTaskBase:
|
|
|
159
203
|
map_tuple = json.loads(json_string)
|
|
160
204
|
if loaded_rows % 500000 == 0:
|
|
161
205
|
print(
|
|
162
|
-
f"{loaded_rows + 1} ids loaded to map. Last Id: {map_tuple[0]}",
|
|
206
|
+
f"{loaded_rows + 1} ids loaded to map. Last Id: {map_tuple[0]} ",
|
|
163
207
|
end="\r",
|
|
164
208
|
)
|
|
165
209
|
|
|
166
210
|
id_map[map_tuple[0]] = map_tuple
|
|
167
|
-
logging.info("Loaded %s migrated IDs", loaded_rows)
|
|
211
|
+
logging.info("Loaded %s migrated IDs from %s", loaded_rows, id_map_file.name)
|
|
168
212
|
if not any(id_map) and raise_if_empty:
|
|
169
213
|
raise TransformationProcessError("", "Legacy id map is empty", map_path)
|
|
170
214
|
return id_map
|
|
@@ -177,7 +177,7 @@ class OrdersTransformer(MigrationTaskBase):
|
|
|
177
177
|
self.library_configuration,
|
|
178
178
|
self.orders_map,
|
|
179
179
|
self.load_id_map(self.folder_structure.organizations_id_map_path, True),
|
|
180
|
-
self.
|
|
180
|
+
self.load_instance_id_map(True),
|
|
181
181
|
self.load_ref_data_mapping_file(
|
|
182
182
|
"acquisitionMethod",
|
|
183
183
|
self.folder_structure.mapping_files_folder
|
|
@@ -6,6 +6,7 @@ from pydantic import Field
|
|
|
6
6
|
|
|
7
7
|
import i18n
|
|
8
8
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
9
|
+
from art import tprint
|
|
9
10
|
|
|
10
11
|
from folio_migration_tools.custom_exceptions import (
|
|
11
12
|
TransformationProcessError,
|
|
@@ -282,16 +283,7 @@ class UserTransformer(MigrationTaskBase):
|
|
|
282
283
|
|
|
283
284
|
|
|
284
285
|
def print_email_warning():
|
|
285
|
-
|
|
286
|
-
" ______ __ __ _____ _ _____ ___ \n" # noqa: E501, W605
|
|
287
|
-
" | ____| | \\/ | /\\ |_ _| | | / ____| |__ \\ \n" # noqa: E501, W605
|
|
288
|
-
" | |__ | \\ / | / \\ | | | | | (___ ) |\n" # noqa: E501, W605
|
|
289
|
-
" | __| | |\\/| | / /\\ \\ | | | | \\___ \\ / / \n" # noqa: E501, W605
|
|
290
|
-
" |______| |_| |_| /_/ \\_\\ |_____| |______| |_____/ (_) \n" # noqa: E501, W605
|
|
291
|
-
" \n" # noqa: E501, W605
|
|
292
|
-
" \n"
|
|
293
|
-
)
|
|
294
|
-
print(s)
|
|
286
|
+
tprint("\nEMAILS?\n", space=2)
|
|
295
287
|
|
|
296
288
|
|
|
297
289
|
def remove_empty_addresses(folio_user):
|
|
@@ -12,6 +12,10 @@ from folio_migration_tools.mapping_file_transformation.holdings_mapper import (
|
|
|
12
12
|
HoldingsMapper,
|
|
13
13
|
)
|
|
14
14
|
from folio_migration_tools.migration_report import MigrationReport
|
|
15
|
+
from folio_migration_tools.library_configuration import (
|
|
16
|
+
LibraryConfiguration,
|
|
17
|
+
FolioRelease,
|
|
18
|
+
)
|
|
15
19
|
|
|
16
20
|
|
|
17
21
|
def mocked_holdings_mapper() -> Mock:
|
|
@@ -242,3 +246,62 @@ def folio_get_single_object_mocked(*args, **kwargs):
|
|
|
242
246
|
|
|
243
247
|
def folio_get_from_github(owner, repo, file_path):
|
|
244
248
|
return FolioClient.get_latest_from_github(owner, repo, file_path, "")
|
|
249
|
+
|
|
250
|
+
OKAPI_URL = "http://localhost:9130"
|
|
251
|
+
LIBRARY_NAME = "Test Library"
|
|
252
|
+
|
|
253
|
+
def get_mocked_library_config():
|
|
254
|
+
return LibraryConfiguration(
|
|
255
|
+
okapi_url=OKAPI_URL,
|
|
256
|
+
tenant_id="test_tenant",
|
|
257
|
+
okapi_username="test_user",
|
|
258
|
+
okapi_password="test_password",
|
|
259
|
+
base_folder=Path("."),
|
|
260
|
+
library_name=LIBRARY_NAME,
|
|
261
|
+
log_level_debug=False,
|
|
262
|
+
folio_release=FolioRelease.sunflower,
|
|
263
|
+
iteration_identifier="test_iteration"
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
def get_mocked_ecs_central_libarary_config():
|
|
267
|
+
return LibraryConfiguration(
|
|
268
|
+
okapi_url=OKAPI_URL,
|
|
269
|
+
tenant_id="test_tenant",
|
|
270
|
+
okapi_username="test_user",
|
|
271
|
+
okapi_password="test_password",
|
|
272
|
+
base_folder=Path("."),
|
|
273
|
+
library_name=LIBRARY_NAME,
|
|
274
|
+
log_level_debug=False,
|
|
275
|
+
folio_release=FolioRelease.sunflower,
|
|
276
|
+
iteration_identifier="central_iteration",
|
|
277
|
+
is_ecs=True,
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def get_mocked_ecs_member_libarary_config():
|
|
281
|
+
return LibraryConfiguration(
|
|
282
|
+
okapi_url=OKAPI_URL,
|
|
283
|
+
tenant_id="test_tenant",
|
|
284
|
+
ecs_tenant_id="test_ecs_tenant",
|
|
285
|
+
okapi_username="test_user",
|
|
286
|
+
okapi_password="test_password",
|
|
287
|
+
base_folder=Path("."),
|
|
288
|
+
library_name=LIBRARY_NAME,
|
|
289
|
+
log_level_debug=False,
|
|
290
|
+
folio_release=FolioRelease.sunflower,
|
|
291
|
+
iteration_identifier="member_iteration",
|
|
292
|
+
ecs_central_iteration_identifier="central_iteration",
|
|
293
|
+
is_ecs=True,
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
def get_mocked_folder_structure():
|
|
297
|
+
mock_fs = MagicMock()
|
|
298
|
+
mock_fs.mapping_files = Path("mapping_files")
|
|
299
|
+
mock_fs.results_folder = Path("results")
|
|
300
|
+
mock_fs.legacy_records_folder = Path("source_files")
|
|
301
|
+
mock_fs.logs_folder = Path("logs")
|
|
302
|
+
mock_fs.migration_reports_file = Path("/dev/null")
|
|
303
|
+
mock_fs.transformation_extra_data_path = Path("transformation_extra_data")
|
|
304
|
+
mock_fs.transformation_log_path = Path("/dev/null")
|
|
305
|
+
mock_fs.data_issue_file_path = Path("/dev/null")
|
|
306
|
+
mock_fs.failed_marc_recs_file = Path("failed_marc_recs.txt")
|
|
307
|
+
return mock_fs
|
{folio_migration_tools-1.9.0rc7.dist-info → folio_migration_tools-1.9.0rc8.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: folio_migration_tools
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.0rc8
|
|
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
|
|
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
17
17
|
Provides-Extra: docs
|
|
18
18
|
Requires-Dist: argparse-prompt (>=0.0.5,<0.0.6)
|
|
19
|
+
Requires-Dist: art (>=6.5,<7.0)
|
|
19
20
|
Requires-Dist: deepdiff (>=6.2.3,<7.0.0)
|
|
20
21
|
Requires-Dist: defusedxml (>=0.7.1,<0.8.0)
|
|
21
22
|
Requires-Dist: folio-uuid (>=0.2.8,<0.3.0)
|
{folio_migration_tools-1.9.0rc7.dist-info → folio_migration_tools-1.9.0rc8.dist-info}/RECORD
RENAMED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
folio_migration_tools/__init__.py,sha256=DXvzUKFSpSZjflFWaNm0L8yhFk0u7RVIvQMskwMmKFc,238
|
|
2
|
-
folio_migration_tools/__main__.py,sha256=
|
|
2
|
+
folio_migration_tools/__main__.py,sha256=_0el5EyJhG8lPj--gM5zMfVJgTt9RhrJo7rmuOY20sM,7883
|
|
3
3
|
folio_migration_tools/circulation_helper.py,sha256=2kAkLM6caPiep0ZtBkMICbRDh53KdfdH21oEX1eMRDI,14193
|
|
4
4
|
folio_migration_tools/colors.py,sha256=GP0wdI_GZ2WD5SjrbPN-S3u8vvN_u6rGQIBBcWv_0ZM,227
|
|
5
5
|
folio_migration_tools/config_file_load.py,sha256=zHHa6NDkN6EJiQE4DgjrFQPVKsd70POsfbGkB8308jg,2822
|
|
6
6
|
folio_migration_tools/custom_dict.py,sha256=-FUnhKp90Dg8EHlY6twx-PYQxBUWEO7FgxL2b7pf-xk,678
|
|
7
7
|
folio_migration_tools/custom_exceptions.py,sha256=1zgOKy3NBUVGG6i9YxK6w2Hntlea8MHmm7mdnjBtzvQ,2687
|
|
8
8
|
folio_migration_tools/extradata_writer.py,sha256=fuchNcMc6BYb9IyfAcvXg7X4J2TfX6YiROfT2hr0JMw,1678
|
|
9
|
-
folio_migration_tools/folder_structure.py,sha256=
|
|
9
|
+
folio_migration_tools/folder_structure.py,sha256=bZlmKGtxdytWcqjnM2lE4Vpx4nHyYRk7CNL1tZhLtXY,6917
|
|
10
10
|
folio_migration_tools/helper.py,sha256=KkOkNAGO_fuYqxdLrsbLzCJLQHUrFZG1NzD4RmpQ-KM,2804
|
|
11
11
|
folio_migration_tools/holdings_helper.py,sha256=yJpz6aJrKRBiJ1MtT5bs2vXAc88uJuGh2_KDuCySOKc,7559
|
|
12
12
|
folio_migration_tools/i18n_config.py,sha256=3AH_2b9zTsxE4XTe4isM_zYtPJSlK0ix6eBmV7kAYUM,228
|
|
13
|
-
folio_migration_tools/library_configuration.py,sha256=
|
|
14
|
-
folio_migration_tools/mapper_base.py,sha256=
|
|
13
|
+
folio_migration_tools/library_configuration.py,sha256=UhHNiz9SI2nEnm6XME2ESD33LNwqdRzIgCU9kjYPHQQ,4863
|
|
14
|
+
folio_migration_tools/mapper_base.py,sha256=WnUA2KBJrvAWRuq7KsTPi9YXD76pXfX7lyI5pExEwLI,20139
|
|
15
15
|
folio_migration_tools/mapping_file_transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
|
-
folio_migration_tools/mapping_file_transformation/courses_mapper.py,sha256=
|
|
16
|
+
folio_migration_tools/mapping_file_transformation/courses_mapper.py,sha256=RuNkdG9XumpgPO3Zvcx_JYzZ598Xle_AMNf18zLR2UM,8095
|
|
17
17
|
folio_migration_tools/mapping_file_transformation/holdings_mapper.py,sha256=nJS-xx1LszvbYfw0qdTUHX9xXHlxS7wP5mYmixFMh8A,7221
|
|
18
|
-
folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=
|
|
18
|
+
folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=YYZFgNoDVuSO_mRuaDNZ6-6bYbEtYFtfbIZ1MFPBAgc,10687
|
|
19
19
|
folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py,sha256=nCkqbxaDHKxMuqQHh_afxQp48YrVD-SeCZ0L1iGvnkk,13402
|
|
20
|
-
folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py,sha256=
|
|
20
|
+
folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py,sha256=bLL6tTqqv2MOjZlowjL8lngYP09F_iwfFikEpjB4nmI,37816
|
|
21
21
|
folio_migration_tools/mapping_file_transformation/notes_mapper.py,sha256=auLQZqa4rSJo_MIV4Lc5-LG8RcBpp2bnKH243qNYq_0,3470
|
|
22
22
|
folio_migration_tools/mapping_file_transformation/order_mapper.py,sha256=k-kIuf2ceXrPWe3oVnfhuQlE7eglcx6PDLVJtddkeiM,17680
|
|
23
23
|
folio_migration_tools/mapping_file_transformation/organization_mapper.py,sha256=0zjw0-C-qTYH9GC6FDBElucWCZWdoOiTHOY7q9_4NQg,14571
|
|
24
24
|
folio_migration_tools/mapping_file_transformation/ref_data_mapping.py,sha256=qFsn_LwKZeKFdOudfEQnNA3DEHOdNQVKzTPdZAlDPX0,8864
|
|
25
|
-
folio_migration_tools/mapping_file_transformation/user_mapper.py,sha256=
|
|
25
|
+
folio_migration_tools/mapping_file_transformation/user_mapper.py,sha256=Q8418BdXdCuEDxfoXqLCjWy1lUxhQNLRwSE5Gi1lqoA,7805
|
|
26
26
|
folio_migration_tools/marc_rules_transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
27
|
folio_migration_tools/marc_rules_transformation/conditions.py,sha256=ttTZISieqveu3YpvpnawHh3In1_DNQMTziI5yasfmWU,39142
|
|
28
28
|
folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py,sha256=lTb5QWEAgwyFHy5vdSK6oDl1Q5v2GnzuV04xWV3p4rc,12401
|
|
@@ -30,38 +30,38 @@ folio_migration_tools/marc_rules_transformation/hrid_handler.py,sha256=Ihdv0_1q7
|
|
|
30
30
|
folio_migration_tools/marc_rules_transformation/loc_language_codes.xml,sha256=ztn2_yKws6qySL4oSsZh7sOjxq5bCC1PhAnXJdtgmJ0,382912
|
|
31
31
|
folio_migration_tools/marc_rules_transformation/marc_file_processor.py,sha256=WkOQRDi7f4PZ5qmVH3Q-1_zdGEKYSvOGC6jixDwDp98,12349
|
|
32
32
|
folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py,sha256=9ATjYMRAjy0QcXtmNZaHVhHLJ5hE1WUgOcF6KMJjbgo,5309
|
|
33
|
-
folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py,sha256=
|
|
34
|
-
folio_migration_tools/marc_rules_transformation/rules_mapper_base.py,sha256
|
|
35
|
-
folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py,sha256=
|
|
36
|
-
folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=
|
|
33
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py,sha256=e-wwJs8s8qEgIp8NvQgjx9lEyv7uvt08Fp6fPsy1GK8,9603
|
|
34
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_base.py,sha256=C2jTzdXGkGjE3EWHxUh8jJeqE9tVk0qwRWVxFPZUj-Y,41223
|
|
35
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py,sha256=ZZHsuxlrHRcxkWPeiTjze0SahkNW_rhY3vkOQKnm1cU,28923
|
|
36
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=wTZ2x8VIvCuLuNJLsbUAMCVjbMN7SS1teq0G6LAcOhU,21240
|
|
37
37
|
folio_migration_tools/migration_report.py,sha256=BkRspM1hwTBnWeqsHamf7yVEofzLj560Q-9G--O00hw,4258
|
|
38
38
|
folio_migration_tools/migration_tasks/__init__.py,sha256=ZkbY_yGyB84Ke8OMlYUzyyBj4cxxNrhMTwQlu_GbdDs,211
|
|
39
39
|
folio_migration_tools/migration_tasks/authority_transformer.py,sha256=AoXg9s-GLO3yEEDCrQV7hc4YVXxwxsdxDdpj1zhHydE,4251
|
|
40
40
|
folio_migration_tools/migration_tasks/batch_poster.py,sha256=wI4lCXU5BQDbKErF6pQxT6srq_Wf_nfFAJc4f1sRCoo,36388
|
|
41
41
|
folio_migration_tools/migration_tasks/bibs_transformer.py,sha256=XzlPo-0uuugJA4SM80xOlOj5nDK6OMDXFnAYg80hOBc,7791
|
|
42
42
|
folio_migration_tools/migration_tasks/courses_migrator.py,sha256=CzXnsu-KGP7B4zcINJzLYUqz47D16NuFfzu_DPqRlTQ,7061
|
|
43
|
-
folio_migration_tools/migration_tasks/holdings_csv_transformer.py,sha256=
|
|
44
|
-
folio_migration_tools/migration_tasks/holdings_marc_transformer.py,sha256=
|
|
45
|
-
folio_migration_tools/migration_tasks/items_transformer.py,sha256=
|
|
46
|
-
folio_migration_tools/migration_tasks/loans_migrator.py,sha256=
|
|
43
|
+
folio_migration_tools/migration_tasks/holdings_csv_transformer.py,sha256=NtysoayEIqQ8c_GNcRi6LXDYR-7OLmqFCfciMwzsyT4,21668
|
|
44
|
+
folio_migration_tools/migration_tasks/holdings_marc_transformer.py,sha256=gL2LoXgavVQDpIH-t2vF2za04W8IjBul7MiVifuzvD8,11637
|
|
45
|
+
folio_migration_tools/migration_tasks/items_transformer.py,sha256=qk0sLPBxE5MtPnpLzO_gEhVVe1BqHHnpn2Zaz_vo1RY,19083
|
|
46
|
+
folio_migration_tools/migration_tasks/loans_migrator.py,sha256=JE1e0i2HFzhYl05SqEkg79p9KzwSq_hPboVT9mJhgmk,34510
|
|
47
47
|
folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py,sha256=CnmlTge7nChUJ10EiUkriQtJlVxWqglgfhjgneh2_yM,7247
|
|
48
|
-
folio_migration_tools/migration_tasks/migration_task_base.py,sha256=
|
|
49
|
-
folio_migration_tools/migration_tasks/orders_transformer.py,sha256=
|
|
48
|
+
folio_migration_tools/migration_tasks/migration_task_base.py,sha256=WEKsO8fBsbtA5jkXe_tn1tP9QaVtSzP1_AJR5m41bII,19148
|
|
49
|
+
folio_migration_tools/migration_tasks/orders_transformer.py,sha256=ry3oUUVQTFKCDUbGF5Zjo5ppa6AseKQwpF-wb1sb5UY,14214
|
|
50
50
|
folio_migration_tools/migration_tasks/organization_transformer.py,sha256=vcCjhN1sS55c_a0LXi1Yw1eq3zpDn5E4BGbm2zDQ_Z4,16885
|
|
51
51
|
folio_migration_tools/migration_tasks/requests_migrator.py,sha256=QP9OBezC3FfcKpI78oMmydxcPaUIYAgHyKevyLwC-WQ,14841
|
|
52
52
|
folio_migration_tools/migration_tasks/reserves_migrator.py,sha256=SA3b7FQWHMHb7bEO8ZqOlblQ9m65zWUMH71uRk-zOKw,9950
|
|
53
|
-
folio_migration_tools/migration_tasks/user_transformer.py,sha256=
|
|
53
|
+
folio_migration_tools/migration_tasks/user_transformer.py,sha256=cNBT-wn_xx1OQXiB-vMLZmvyzkg1X562AJXUcYfThaE,12279
|
|
54
54
|
folio_migration_tools/task_configuration.py,sha256=C5-OQtZLH7b4lVeyj5v8OXsqKNN4tzfp9F3b4vhthN4,632
|
|
55
55
|
folio_migration_tools/test_infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
|
-
folio_migration_tools/test_infrastructure/mocked_classes.py,sha256=
|
|
56
|
+
folio_migration_tools/test_infrastructure/mocked_classes.py,sha256=trK1ZvxTdebc8qHtFtLtc-6SLlNdGDtX2z4zhP8GMcI,11278
|
|
57
57
|
folio_migration_tools/transaction_migration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
58
|
folio_migration_tools/transaction_migration/legacy_loan.py,sha256=3PDyC1wbJzF0CcNWelvZ0tC8hjl3p5hbLVJHrz78ORM,6006
|
|
59
59
|
folio_migration_tools/transaction_migration/legacy_request.py,sha256=1ulyFzPQw_InOjyPzkWpGnNptgXdQ18nmri0J8Nlpkc,6124
|
|
60
60
|
folio_migration_tools/transaction_migration/legacy_reserve.py,sha256=d0qbh2fWpwlVSYRL6wZyZG20__NAYNxh7sPSsB-LAes,1804
|
|
61
61
|
folio_migration_tools/transaction_migration/transaction_result.py,sha256=cTdCN0BnlI9_ZJB2Z3Fdkl9gpymIi-9mGZsRFlQcmDk,656
|
|
62
62
|
folio_migration_tools/translations/en.json,sha256=HOVpkb_T-SN_x0NpDp8gyvV1hMLCui3SsG7ByyIv0OU,38669
|
|
63
|
-
folio_migration_tools-1.9.
|
|
64
|
-
folio_migration_tools-1.9.
|
|
65
|
-
folio_migration_tools-1.9.
|
|
66
|
-
folio_migration_tools-1.9.
|
|
67
|
-
folio_migration_tools-1.9.
|
|
63
|
+
folio_migration_tools-1.9.0rc8.dist-info/LICENSE,sha256=PhIEkitVi3ejgq56tt6sWoJIG_zmv82cjjd_aYPPGdI,1072
|
|
64
|
+
folio_migration_tools-1.9.0rc8.dist-info/METADATA,sha256=BelPrPeeo24CEE-5O1AmPhHODf5NOMUAmQWe1TXZf3U,7447
|
|
65
|
+
folio_migration_tools-1.9.0rc8.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
66
|
+
folio_migration_tools-1.9.0rc8.dist-info/entry_points.txt,sha256=Hbe-HjqMcU8FwVshVIkeWyZd9XwgT1CCMNf06EpHQu8,77
|
|
67
|
+
folio_migration_tools-1.9.0rc8.dist-info/RECORD,,
|
{folio_migration_tools-1.9.0rc7.dist-info → folio_migration_tools-1.9.0rc8.dist-info}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|