folio-migration-tools 1.2.1__py3-none-any.whl → 1.9.10__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/__init__.py +11 -0
- folio_migration_tools/__main__.py +169 -85
- folio_migration_tools/circulation_helper.py +96 -59
- folio_migration_tools/config_file_load.py +66 -0
- folio_migration_tools/custom_dict.py +6 -4
- folio_migration_tools/custom_exceptions.py +21 -19
- folio_migration_tools/extradata_writer.py +46 -0
- folio_migration_tools/folder_structure.py +63 -66
- folio_migration_tools/helper.py +29 -21
- folio_migration_tools/holdings_helper.py +57 -34
- folio_migration_tools/i18n_config.py +9 -0
- folio_migration_tools/library_configuration.py +173 -13
- folio_migration_tools/mapper_base.py +317 -106
- folio_migration_tools/mapping_file_transformation/courses_mapper.py +203 -0
- folio_migration_tools/mapping_file_transformation/holdings_mapper.py +83 -69
- folio_migration_tools/mapping_file_transformation/item_mapper.py +98 -94
- folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +352 -0
- folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +702 -223
- folio_migration_tools/mapping_file_transformation/notes_mapper.py +90 -0
- folio_migration_tools/mapping_file_transformation/order_mapper.py +492 -0
- folio_migration_tools/mapping_file_transformation/organization_mapper.py +389 -0
- folio_migration_tools/mapping_file_transformation/ref_data_mapping.py +38 -27
- folio_migration_tools/mapping_file_transformation/user_mapper.py +149 -361
- folio_migration_tools/marc_rules_transformation/conditions.py +650 -246
- folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +292 -130
- folio_migration_tools/marc_rules_transformation/hrid_handler.py +244 -0
- folio_migration_tools/marc_rules_transformation/loc_language_codes.xml +20846 -0
- folio_migration_tools/marc_rules_transformation/marc_file_processor.py +300 -0
- folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py +136 -0
- folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +241 -0
- folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +681 -201
- folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +395 -429
- folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +531 -100
- folio_migration_tools/migration_report.py +85 -38
- folio_migration_tools/migration_tasks/__init__.py +1 -3
- folio_migration_tools/migration_tasks/authority_transformer.py +119 -0
- folio_migration_tools/migration_tasks/batch_poster.py +911 -198
- folio_migration_tools/migration_tasks/bibs_transformer.py +121 -116
- folio_migration_tools/migration_tasks/courses_migrator.py +192 -0
- folio_migration_tools/migration_tasks/holdings_csv_transformer.py +252 -247
- folio_migration_tools/migration_tasks/holdings_marc_transformer.py +321 -115
- folio_migration_tools/migration_tasks/items_transformer.py +264 -84
- folio_migration_tools/migration_tasks/loans_migrator.py +506 -195
- folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +187 -0
- folio_migration_tools/migration_tasks/migration_task_base.py +364 -74
- folio_migration_tools/migration_tasks/orders_transformer.py +373 -0
- folio_migration_tools/migration_tasks/organization_transformer.py +451 -0
- folio_migration_tools/migration_tasks/requests_migrator.py +130 -62
- folio_migration_tools/migration_tasks/reserves_migrator.py +253 -0
- folio_migration_tools/migration_tasks/user_transformer.py +180 -139
- folio_migration_tools/task_configuration.py +46 -0
- folio_migration_tools/test_infrastructure/__init__.py +0 -0
- folio_migration_tools/test_infrastructure/mocked_classes.py +406 -0
- folio_migration_tools/transaction_migration/legacy_loan.py +148 -34
- folio_migration_tools/transaction_migration/legacy_request.py +65 -25
- folio_migration_tools/transaction_migration/legacy_reserve.py +47 -0
- folio_migration_tools/transaction_migration/transaction_result.py +12 -1
- folio_migration_tools/translations/en.json +476 -0
- folio_migration_tools-1.9.10.dist-info/METADATA +169 -0
- folio_migration_tools-1.9.10.dist-info/RECORD +67 -0
- {folio_migration_tools-1.2.1.dist-info → folio_migration_tools-1.9.10.dist-info}/WHEEL +1 -2
- folio_migration_tools-1.9.10.dist-info/entry_points.txt +3 -0
- folio_migration_tools/generate_schemas.py +0 -46
- folio_migration_tools/mapping_file_transformation/mapping_file_mapping_base_impl.py +0 -44
- folio_migration_tools/mapping_file_transformation/user_mapper_base.py +0 -212
- folio_migration_tools/marc_rules_transformation/bibs_processor.py +0 -163
- folio_migration_tools/marc_rules_transformation/holdings_processor.py +0 -284
- folio_migration_tools/report_blurbs.py +0 -219
- folio_migration_tools/transaction_migration/legacy_fee_fine.py +0 -36
- folio_migration_tools-1.2.1.dist-info/METADATA +0 -134
- folio_migration_tools-1.2.1.dist-info/RECORD +0 -50
- folio_migration_tools-1.2.1.dist-info/top_level.txt +0 -1
- {folio_migration_tools-1.2.1.dist-info → folio_migration_tools-1.9.10.dist-info/licenses}/LICENSE +0 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import i18n
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
4
|
+
|
|
5
|
+
from folio_uuid.folio_uuid import FOLIONamespaces
|
|
6
|
+
from folio_uuid.folio_uuid import FolioUUID
|
|
7
|
+
from folioclient import FolioClient
|
|
8
|
+
|
|
9
|
+
from folio_migration_tools.custom_exceptions import TransformationRecordFailedError
|
|
10
|
+
from folio_migration_tools.library_configuration import LibraryConfiguration
|
|
11
|
+
from folio_migration_tools.mapping_file_transformation.mapping_file_mapper_base import (
|
|
12
|
+
MappingFileMapperBase,
|
|
13
|
+
)
|
|
14
|
+
from folio_migration_tools.mapping_file_transformation.notes_mapper import NotesMapper
|
|
15
|
+
from folio_migration_tools.mapping_file_transformation.ref_data_mapping import (
|
|
16
|
+
RefDataMapping,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CoursesMapper(MappingFileMapperBase):
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
folio_client: FolioClient,
|
|
24
|
+
course_map,
|
|
25
|
+
terms_map,
|
|
26
|
+
departments_map,
|
|
27
|
+
library_configuration: LibraryConfiguration,
|
|
28
|
+
task_configuration,
|
|
29
|
+
):
|
|
30
|
+
self.folio_client: FolioClient = folio_client
|
|
31
|
+
self.user_cache: dict = {}
|
|
32
|
+
self.notes_mapper: NotesMapper = NotesMapper(
|
|
33
|
+
library_configuration,
|
|
34
|
+
None,
|
|
35
|
+
self.folio_client,
|
|
36
|
+
course_map,
|
|
37
|
+
FOLIONamespaces.note,
|
|
38
|
+
True,
|
|
39
|
+
)
|
|
40
|
+
self.composite_course_schema = self.get_composite_course_schema()
|
|
41
|
+
super().__init__(
|
|
42
|
+
folio_client,
|
|
43
|
+
self.composite_course_schema,
|
|
44
|
+
course_map,
|
|
45
|
+
None,
|
|
46
|
+
FOLIONamespaces.course,
|
|
47
|
+
library_configuration,
|
|
48
|
+
task_configuration
|
|
49
|
+
)
|
|
50
|
+
self.course_map = course_map
|
|
51
|
+
if terms_map:
|
|
52
|
+
self.terms_map = RefDataMapping(
|
|
53
|
+
self.folio_client,
|
|
54
|
+
"/coursereserves/terms",
|
|
55
|
+
"terms",
|
|
56
|
+
terms_map,
|
|
57
|
+
"name",
|
|
58
|
+
"TermsMapping",
|
|
59
|
+
)
|
|
60
|
+
else:
|
|
61
|
+
self.terms_map = None
|
|
62
|
+
|
|
63
|
+
if departments_map:
|
|
64
|
+
self.departments_map = RefDataMapping(
|
|
65
|
+
self.folio_client,
|
|
66
|
+
"/coursereserves/departments",
|
|
67
|
+
"departments",
|
|
68
|
+
departments_map,
|
|
69
|
+
"name",
|
|
70
|
+
"DepartmentsMapping",
|
|
71
|
+
)
|
|
72
|
+
else:
|
|
73
|
+
self.departments_map = None
|
|
74
|
+
|
|
75
|
+
def store_objects(self, composite_course):
|
|
76
|
+
try:
|
|
77
|
+
self.extradata_writer.write("courselisting", composite_course[0]["courselisting"])
|
|
78
|
+
self.migration_report.add_general_statistics(i18n.t("Stored courselistings"))
|
|
79
|
+
self.extradata_writer.write("course", composite_course[0]["course"])
|
|
80
|
+
self.migration_report.add_general_statistics(i18n.t("Stored courses"))
|
|
81
|
+
if "instructors" in composite_course[0] and any(composite_course[0]["instructors"]):
|
|
82
|
+
for instructor in composite_course[0]["instructors"]:
|
|
83
|
+
self.extradata_writer.write("instructor", instructor)
|
|
84
|
+
self.migration_report.add_general_statistics(i18n.t("Stored instructors"))
|
|
85
|
+
|
|
86
|
+
except Exception as ee:
|
|
87
|
+
raise TransformationRecordFailedError(
|
|
88
|
+
composite_course[1], "Failed when storing", ee
|
|
89
|
+
) from ee
|
|
90
|
+
|
|
91
|
+
def perform_additional_mappings(self, composite_course):
|
|
92
|
+
try:
|
|
93
|
+
# Assign deterministic ids to every object
|
|
94
|
+
composite_course[0]["course"]["id"] = self.get_uuid(
|
|
95
|
+
composite_course, FOLIONamespaces.course
|
|
96
|
+
)
|
|
97
|
+
composite_course[0]["courselisting"]["id"] = self.get_uuid(
|
|
98
|
+
composite_course, FOLIONamespaces.course_listing
|
|
99
|
+
)
|
|
100
|
+
if "instructors" in composite_course[0] and any(composite_course[0]["instructors"]):
|
|
101
|
+
for idx, instructor in enumerate(composite_course[0]["instructors"]):
|
|
102
|
+
instructor["id"] = self.get_uuid(
|
|
103
|
+
composite_course, FOLIONamespaces.instructor, idx
|
|
104
|
+
)
|
|
105
|
+
# Link instructor to course listing
|
|
106
|
+
instructor["courseListingId"] = composite_course[0]["courselisting"]["id"]
|
|
107
|
+
if self.task_configuration.look_up_instructor:
|
|
108
|
+
self.populate_instructor_from_users(instructor)
|
|
109
|
+
else:
|
|
110
|
+
self.migration_report.add_general_statistics(i18n.t("Missing Instructors"))
|
|
111
|
+
|
|
112
|
+
# Link course to courselisting
|
|
113
|
+
composite_course[0]["course"]["courseListingId"] = composite_course[0][
|
|
114
|
+
"courselisting"
|
|
115
|
+
]["id"]
|
|
116
|
+
|
|
117
|
+
except Exception as ee:
|
|
118
|
+
raise TransformationRecordFailedError(
|
|
119
|
+
composite_course[1], "Failed when creating and linking ids", ee
|
|
120
|
+
) from ee
|
|
121
|
+
|
|
122
|
+
def get_uuid(self, composite_course, object_type: FOLIONamespaces, idx: int = 0):
|
|
123
|
+
return str(
|
|
124
|
+
FolioUUID(
|
|
125
|
+
self.base_string_for_folio_uuid,
|
|
126
|
+
object_type,
|
|
127
|
+
composite_course[1] if idx == 0 else f"{composite_course[1]}_{idx}",
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def populate_instructor_from_users(self, instructor: dict):
|
|
132
|
+
if instructor["userId"] not in self.user_cache:
|
|
133
|
+
path = "/users"
|
|
134
|
+
query = f'?query=(externalSystemId=="{instructor["userId"]}")'
|
|
135
|
+
if user := next(self.folio_client.folio_get_all(path, "users", query), None):
|
|
136
|
+
self.user_cache[instructor["userId"]] = user
|
|
137
|
+
if user := self.user_cache.get(instructor["userId"], {}):
|
|
138
|
+
instructor["userId"] = user.get("id", "")
|
|
139
|
+
instructor["barcode"] = user.get("barcode", "")
|
|
140
|
+
instructor["patronGroup"] = user.get("patronGroup", "")
|
|
141
|
+
else:
|
|
142
|
+
del instructor["userId"]
|
|
143
|
+
|
|
144
|
+
def get_prop(self, legacy_item, folio_prop_name, index_or_id, schema_default_value):
|
|
145
|
+
if folio_prop_name == "courselisting.termId":
|
|
146
|
+
return self.get_mapped_ref_data_value(
|
|
147
|
+
self.terms_map,
|
|
148
|
+
legacy_item,
|
|
149
|
+
folio_prop_name,
|
|
150
|
+
index_or_id,
|
|
151
|
+
False,
|
|
152
|
+
)
|
|
153
|
+
elif folio_prop_name == "course.departmentId":
|
|
154
|
+
return self.get_mapped_ref_data_value(
|
|
155
|
+
self.departments_map,
|
|
156
|
+
legacy_item,
|
|
157
|
+
folio_prop_name,
|
|
158
|
+
index_or_id,
|
|
159
|
+
False,
|
|
160
|
+
)
|
|
161
|
+
elif mapped_value := super().get_prop(
|
|
162
|
+
legacy_item, folio_prop_name, index_or_id, schema_default_value
|
|
163
|
+
):
|
|
164
|
+
return mapped_value
|
|
165
|
+
else:
|
|
166
|
+
self.migration_report.add("UnmappedProperties", f"{folio_prop_name}")
|
|
167
|
+
return ""
|
|
168
|
+
|
|
169
|
+
def get_composite_course_schema(self) -> Dict[str, Any]:
|
|
170
|
+
if self:
|
|
171
|
+
return {
|
|
172
|
+
"properties": {
|
|
173
|
+
"course": self.folio_client.get_from_github(
|
|
174
|
+
"folio-org", "mod-courses", "/ramls/course.json"
|
|
175
|
+
),
|
|
176
|
+
"courselisting": self.folio_client.get_from_github(
|
|
177
|
+
"folio-org", "mod-courses", "/ramls/courselisting.json"
|
|
178
|
+
),
|
|
179
|
+
"instructors": {
|
|
180
|
+
"type": "array",
|
|
181
|
+
"items": self.folio_client.get_from_github(
|
|
182
|
+
"folio-org", "mod-courses", "/ramls/instructor.json"
|
|
183
|
+
),
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
else:
|
|
188
|
+
return {
|
|
189
|
+
"properties": {
|
|
190
|
+
"course": FolioClient.get_latest_from_github(
|
|
191
|
+
"folio-org", "mod-courses", "/ramls/course.json"
|
|
192
|
+
),
|
|
193
|
+
"courselisting": FolioClient.get_latest_from_github(
|
|
194
|
+
"folio-org", "mod-courses", "/ramls/courselisting.json"
|
|
195
|
+
),
|
|
196
|
+
"instructors": {
|
|
197
|
+
"type": "array",
|
|
198
|
+
"items": FolioClient.get_latest_from_github(
|
|
199
|
+
"folio-org", "mod-courses", "/ramls/instructor.json"
|
|
200
|
+
),
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import ast
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
import i18n
|
|
4
6
|
from folio_uuid.folio_uuid import FOLIONamespaces
|
|
5
|
-
from
|
|
6
|
-
|
|
7
|
+
from folioclient import FolioClient
|
|
8
|
+
|
|
9
|
+
from folio_migration_tools.custom_exceptions import TransformationProcessError, TransformationRecordFailedError
|
|
10
|
+
from folio_migration_tools.library_configuration import (
|
|
11
|
+
FileDefinition,
|
|
12
|
+
LibraryConfiguration,
|
|
13
|
+
)
|
|
7
14
|
from folio_migration_tools.mapping_file_transformation.mapping_file_mapper_base import (
|
|
8
15
|
MappingFileMapperBase,
|
|
9
16
|
)
|
|
10
17
|
from folio_migration_tools.mapping_file_transformation.ref_data_mapping import (
|
|
11
18
|
RefDataMapping,
|
|
12
19
|
)
|
|
13
|
-
from folio_migration_tools.
|
|
14
|
-
|
|
20
|
+
from folio_migration_tools.task_configuration import AbstractTaskConfiguration
|
|
15
21
|
|
|
16
22
|
class HoldingsMapper(MappingFileMapperBase):
|
|
17
23
|
def __init__(
|
|
@@ -22,6 +28,7 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
22
28
|
call_number_type_map,
|
|
23
29
|
instance_id_map,
|
|
24
30
|
library_configuration: LibraryConfiguration,
|
|
31
|
+
task_config: AbstractTaskConfiguration,
|
|
25
32
|
statistical_codes_map=None,
|
|
26
33
|
):
|
|
27
34
|
holdings_schema = folio_client.get_holdings_schema()
|
|
@@ -33,6 +40,7 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
33
40
|
statistical_codes_map,
|
|
34
41
|
FOLIONamespaces.holdings,
|
|
35
42
|
library_configuration,
|
|
43
|
+
task_config
|
|
36
44
|
)
|
|
37
45
|
self.holdings_map = holdings_map
|
|
38
46
|
|
|
@@ -42,7 +50,7 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
42
50
|
"locations",
|
|
43
51
|
location_map,
|
|
44
52
|
"code",
|
|
45
|
-
|
|
53
|
+
"LocationMapping",
|
|
46
54
|
)
|
|
47
55
|
if call_number_type_map:
|
|
48
56
|
self.call_number_mapping = RefDataMapping(
|
|
@@ -51,71 +59,77 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
51
59
|
"callNumberTypes",
|
|
52
60
|
call_number_type_map,
|
|
53
61
|
"name",
|
|
54
|
-
|
|
62
|
+
"CallNumberTypeMapping",
|
|
55
63
|
)
|
|
64
|
+
self.holdings_sources = self.get_holdings_sources()
|
|
56
65
|
|
|
57
|
-
def
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
def get_holdings_sources(self):
|
|
67
|
+
res = {}
|
|
68
|
+
holdings_sources = list(
|
|
69
|
+
self.folio_client.folio_get_all("/holdings-sources", "holdingsRecordsSources")
|
|
70
|
+
)
|
|
71
|
+
logging.info("Fetched %s holdingsRecordsSources from tenant", len(holdings_sources))
|
|
72
|
+
res = {n["name"].upper(): n["id"] for n in holdings_sources}
|
|
73
|
+
if "FOLIO" not in res:
|
|
74
|
+
raise TransformationProcessError("", "No holdings source with name FOLIO in tenant")
|
|
75
|
+
if "MARC" not in res:
|
|
76
|
+
raise TransformationProcessError("", "No holdings source with name MARC in tenant")
|
|
77
|
+
logging.info(json.dumps(res, indent=4))
|
|
78
|
+
return res
|
|
64
79
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Blurbs.DefaultValuesAdded, f"{value} added to {folio_prop_name}"
|
|
70
|
-
)
|
|
71
|
-
return value
|
|
80
|
+
def perform_additional_mappings(self, legacy_ids, folio_rec, file_def):
|
|
81
|
+
self.handle_suppression(folio_rec, file_def)
|
|
82
|
+
self.map_statistical_codes(folio_rec, file_def)
|
|
83
|
+
self.map_statistical_code_ids(legacy_ids, folio_rec)
|
|
72
84
|
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
def handle_suppression(self, folio_record, file_def: FileDefinition):
|
|
86
|
+
folio_record["discoverySuppress"] = file_def.discovery_suppressed
|
|
87
|
+
self.migration_report.add(
|
|
88
|
+
"Suppression",
|
|
89
|
+
i18n.t("Suppressed from discovery") + f' = {folio_record["discoverySuppress"]}',
|
|
75
90
|
)
|
|
76
|
-
legacy_value = " ".join(legacy_values).strip()
|
|
77
91
|
|
|
92
|
+
def get_prop(self, legacy_item, folio_prop_name, index_or_id, schema_default_value):
|
|
78
93
|
if folio_prop_name == "permanentLocationId":
|
|
79
94
|
return self.get_location_id(legacy_item, index_or_id, folio_prop_name)
|
|
80
|
-
elif folio_prop_name == "temporaryLocationId":
|
|
81
|
-
return self.get_location_id(legacy_item, index_or_id, folio_prop_name, True)
|
|
82
|
-
elif folio_prop_name == "callNumber":
|
|
83
|
-
if legacy_value.startswith("[") and len(legacy_value.split(",")) > 1:
|
|
84
|
-
self.migration_report.add_general_statistics(
|
|
85
|
-
"Bound-with items callnumber identified"
|
|
86
|
-
)
|
|
87
|
-
self.migration_report.add(
|
|
88
|
-
Blurbs.BoundWithMappings,
|
|
89
|
-
(
|
|
90
|
-
f"Number of bib-level callnumbers in record: "
|
|
91
|
-
f"{len(legacy_value.split(','))}"
|
|
92
|
-
),
|
|
93
|
-
)
|
|
94
|
-
return legacy_value.removeprefix("[").removesuffix("]")
|
|
95
95
|
elif folio_prop_name == "callNumberTypeId":
|
|
96
|
-
return self.get_call_number_type_id(
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
96
|
+
return self.get_call_number_type_id(legacy_item, folio_prop_name, index_or_id)
|
|
97
|
+
# elif folio_prop_name.startswith("statisticalCodeIds"):
|
|
98
|
+
# return self.get_statistical_code(legacy_item, folio_prop_name, index_or_id)
|
|
99
|
+
|
|
100
|
+
mapped_value = super().get_prop(
|
|
101
|
+
legacy_item, folio_prop_name, index_or_id, schema_default_value
|
|
102
|
+
)
|
|
103
|
+
if folio_prop_name == "callNumber":
|
|
104
|
+
return self.get_call_number(mapped_value)
|
|
103
105
|
elif folio_prop_name == "instanceId":
|
|
104
|
-
return self.get_instance_ids(
|
|
105
|
-
elif
|
|
106
|
-
|
|
107
|
-
self.migration_report.add(
|
|
108
|
-
Blurbs.Details, f"{legacy_item_keys} were concatenated"
|
|
109
|
-
)
|
|
110
|
-
return legacy_value
|
|
106
|
+
return self.get_instance_ids(mapped_value, index_or_id)
|
|
107
|
+
elif mapped_value:
|
|
108
|
+
return mapped_value
|
|
111
109
|
else:
|
|
112
|
-
|
|
110
|
+
self.migration_report.add("UnmappedProperties", f"{folio_prop_name}")
|
|
113
111
|
return ""
|
|
114
112
|
|
|
113
|
+
def get_call_number(self, legacy_value):
|
|
114
|
+
if legacy_value.startswith("[") and len(legacy_value.split(",")) > 1:
|
|
115
|
+
self.migration_report.add_general_statistics(
|
|
116
|
+
i18n.t("Bound-with items callnumber identified")
|
|
117
|
+
)
|
|
118
|
+
self.migration_report.add(
|
|
119
|
+
"BoundWithMappings",
|
|
120
|
+
(f"Number of bib-level callnumbers in record: {len(legacy_value.split(','))}"),
|
|
121
|
+
)
|
|
122
|
+
if legacy_value.startswith("[") and len(legacy_value.split(",")) == 1:
|
|
123
|
+
try:
|
|
124
|
+
legacy_value = ast.literal_eval(str(legacy_value))[0]
|
|
125
|
+
except (SyntaxError, ValueError):
|
|
126
|
+
return legacy_value
|
|
127
|
+
return legacy_value
|
|
128
|
+
|
|
115
129
|
def get_location_id(
|
|
116
130
|
self, legacy_item: dict, id_or_index, folio_prop_name, prevent_default=False
|
|
117
131
|
):
|
|
118
|
-
return self.
|
|
132
|
+
return self.get_mapped_ref_data_value(
|
|
119
133
|
self.location_mapping,
|
|
120
134
|
legacy_item,
|
|
121
135
|
id_or_index,
|
|
@@ -125,10 +139,10 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
125
139
|
|
|
126
140
|
def get_call_number_type_id(self, legacy_item, folio_prop_name: str, id_or_index):
|
|
127
141
|
if self.call_number_mapping:
|
|
128
|
-
return self.
|
|
142
|
+
return self.get_mapped_ref_data_value(
|
|
129
143
|
self.call_number_mapping, legacy_item, id_or_index, folio_prop_name
|
|
130
144
|
)
|
|
131
|
-
self.migration_report.add(
|
|
145
|
+
self.migration_report.add("CallNumberTypeMapping", i18n.t("No Call Number Type Mapping"))
|
|
132
146
|
return ""
|
|
133
147
|
|
|
134
148
|
def get_instance_ids(self, legacy_value: str, index_or_id: str):
|
|
@@ -136,8 +150,8 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
136
150
|
return_ids = []
|
|
137
151
|
legacy_bib_ids = self.get_legacy_bib_ids(legacy_value, index_or_id)
|
|
138
152
|
self.migration_report.add(
|
|
139
|
-
|
|
140
|
-
|
|
153
|
+
"BoundWithMappings",
|
|
154
|
+
i18n.t("Number of bib records referenced in item") + f": {len(legacy_bib_ids)}",
|
|
141
155
|
)
|
|
142
156
|
for legacy_instance_id in legacy_bib_ids:
|
|
143
157
|
new_legacy_value = (
|
|
@@ -150,18 +164,18 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
150
164
|
and legacy_instance_id not in self.instance_id_map
|
|
151
165
|
):
|
|
152
166
|
self.migration_report.add_general_statistics(
|
|
153
|
-
"Records not matched to Instances"
|
|
167
|
+
i18n.t("Records not matched to Instances")
|
|
154
168
|
)
|
|
155
169
|
s = "Bib id not in instance id map."
|
|
156
170
|
raise TransformationRecordFailedError(index_or_id, s, new_legacy_value)
|
|
157
171
|
else:
|
|
158
172
|
self.migration_report.add_general_statistics(
|
|
159
|
-
"Records matched to Instances"
|
|
173
|
+
i18n.t("Records matched to Instances")
|
|
174
|
+
)
|
|
175
|
+
entry = self.instance_id_map.get(new_legacy_value, "") or self.instance_id_map.get(
|
|
176
|
+
legacy_instance_id
|
|
160
177
|
)
|
|
161
|
-
|
|
162
|
-
new_legacy_value, ""
|
|
163
|
-
) or self.instance_id_map.get(legacy_instance_id)
|
|
164
|
-
return_ids.append(entry["folio_id"])
|
|
178
|
+
return_ids.append(entry[1])
|
|
165
179
|
if any(return_ids):
|
|
166
180
|
return return_ids
|
|
167
181
|
else:
|
|
@@ -177,11 +191,11 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
177
191
|
new_value_len = len(new_legacy_values)
|
|
178
192
|
if new_value_len > 1:
|
|
179
193
|
self.migration_report.add_general_statistics(
|
|
180
|
-
"Bound-with items identified by bib id"
|
|
194
|
+
i18n.t("Bound-with items identified by bib id")
|
|
181
195
|
)
|
|
182
196
|
self.migration_report.add(
|
|
183
|
-
|
|
184
|
-
"Bib ids referenced in bound-with items",
|
|
197
|
+
"GeneralStatistics",
|
|
198
|
+
i18n.t("Bib ids referenced in bound-with items"),
|
|
185
199
|
new_value_len,
|
|
186
200
|
)
|
|
187
201
|
return new_legacy_values
|
|
@@ -190,4 +204,4 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
190
204
|
index_or_id,
|
|
191
205
|
f"Instance ID could not get parsed to array of strings {error}",
|
|
192
206
|
legacy_value,
|
|
193
|
-
)
|
|
207
|
+
) from error
|