folio-migration-tools 1.9.0rc12__py3-none-any.whl → 1.9.0rc13__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/library_configuration.py +21 -1
- folio_migration_tools/mapper_base.py +78 -4
- folio_migration_tools/mapping_file_transformation/courses_mapper.py +2 -1
- folio_migration_tools/mapping_file_transformation/holdings_mapper.py +8 -4
- folio_migration_tools/mapping_file_transformation/item_mapper.py +4 -11
- folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +1 -0
- folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +3 -19
- folio_migration_tools/mapping_file_transformation/notes_mapper.py +2 -0
- folio_migration_tools/mapping_file_transformation/order_mapper.py +4 -1
- folio_migration_tools/mapping_file_transformation/organization_mapper.py +3 -0
- folio_migration_tools/mapping_file_transformation/user_mapper.py +3 -1
- folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +1 -0
- folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +83 -4
- folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +5 -0
- folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +10 -4
- folio_migration_tools/migration_tasks/bibs_transformer.py +13 -3
- folio_migration_tools/migration_tasks/holdings_csv_transformer.py +42 -21
- folio_migration_tools/migration_tasks/holdings_marc_transformer.py +22 -12
- folio_migration_tools/migration_tasks/items_transformer.py +4 -3
- folio_migration_tools/migration_tasks/migration_task_base.py +22 -1
- folio_migration_tools/migration_tasks/orders_transformer.py +2 -0
- folio_migration_tools/migration_tasks/user_transformer.py +1 -0
- folio_migration_tools/translations/en.json +12 -3
- {folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.dist-info}/METADATA +1 -1
- {folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.dist-info}/RECORD +28 -28
- {folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.dist-info}/LICENSE +0 -0
- {folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.dist-info}/WHEEL +0 -0
- {folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.dist-info}/entry_points.txt +0 -0
|
@@ -32,7 +32,27 @@ class FileDefinition(BaseModel):
|
|
|
32
32
|
] = ""
|
|
33
33
|
discovery_suppressed: Annotated[bool, Field(title="Discovery suppressed")] = False
|
|
34
34
|
staff_suppressed: Annotated[bool, Field(title="Staff suppressed")] = False
|
|
35
|
-
service_point_id: Annotated[
|
|
35
|
+
service_point_id: Annotated[
|
|
36
|
+
str,
|
|
37
|
+
Field(
|
|
38
|
+
title="Service point ID",
|
|
39
|
+
description=(
|
|
40
|
+
"Service point to be used for "
|
|
41
|
+
"transactions created from this file (Loans-only)."
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
] = ""
|
|
45
|
+
statistical_code: Annotated[
|
|
46
|
+
str,
|
|
47
|
+
Field(
|
|
48
|
+
title="Statistical code",
|
|
49
|
+
description=(
|
|
50
|
+
"Statistical code (code) to be used inventory records created from "
|
|
51
|
+
"this file (Instances, Holdings, Items). Specify multiple codes using "
|
|
52
|
+
"multi_field_delimiter."
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
] = ""
|
|
36
56
|
create_source_records: Annotated[
|
|
37
57
|
bool,
|
|
38
58
|
Field(
|
|
@@ -6,12 +6,13 @@ import sys
|
|
|
6
6
|
import uuid
|
|
7
7
|
from datetime import datetime, timezone
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Dict, List
|
|
9
|
+
from typing import Dict, List, Optional, Tuple, Union
|
|
10
10
|
|
|
11
11
|
import i18n
|
|
12
12
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
13
13
|
from folio_uuid.folio_uuid import FolioUUID
|
|
14
14
|
from folioclient import FolioClient
|
|
15
|
+
from pymarc import Record
|
|
15
16
|
|
|
16
17
|
from folio_migration_tools.custom_exceptions import (
|
|
17
18
|
TransformationFieldMappingError,
|
|
@@ -19,7 +20,8 @@ from folio_migration_tools.custom_exceptions import (
|
|
|
19
20
|
TransformationRecordFailedError,
|
|
20
21
|
)
|
|
21
22
|
from folio_migration_tools.extradata_writer import ExtradataWriter
|
|
22
|
-
from folio_migration_tools.
|
|
23
|
+
from folio_migration_tools.helper import Helper
|
|
24
|
+
from folio_migration_tools.library_configuration import FileDefinition, LibraryConfiguration
|
|
23
25
|
from folio_migration_tools.mapping_file_transformation.ref_data_mapping import (
|
|
24
26
|
RefDataMapping,
|
|
25
27
|
)
|
|
@@ -34,8 +36,9 @@ class MapperBase:
|
|
|
34
36
|
def __init__(
|
|
35
37
|
self,
|
|
36
38
|
library_configuration: LibraryConfiguration,
|
|
39
|
+
task_configuration: AbstractTaskConfiguration,
|
|
37
40
|
folio_client: FolioClient,
|
|
38
|
-
parent_id_map:
|
|
41
|
+
parent_id_map: Dict[str, Tuple] = {},
|
|
39
42
|
):
|
|
40
43
|
logging.info("MapperBase initiating")
|
|
41
44
|
self.parent_id_map: dict[str, tuple] = parent_id_map
|
|
@@ -43,7 +46,7 @@ class MapperBase:
|
|
|
43
46
|
self.start_datetime = datetime.now(timezone.utc)
|
|
44
47
|
self.folio_client: FolioClient = folio_client
|
|
45
48
|
self.library_configuration: LibraryConfiguration = library_configuration
|
|
46
|
-
self.task_configuration: AbstractTaskConfiguration
|
|
49
|
+
self.task_configuration: AbstractTaskConfiguration = task_configuration
|
|
47
50
|
self.mapped_folio_fields: dict = {}
|
|
48
51
|
self.migration_report: MigrationReport = MigrationReport()
|
|
49
52
|
self.num_criticalerrors = 0
|
|
@@ -440,6 +443,74 @@ class MapperBase:
|
|
|
440
443
|
)
|
|
441
444
|
)
|
|
442
445
|
|
|
446
|
+
def map_statistical_codes(self, folio_record: dict, file_def: FileDefinition, legacy_record: Optional[Union[dict, Record]] = None):
|
|
447
|
+
"""Map statistical codes to the folio record.
|
|
448
|
+
|
|
449
|
+
This method checks if the file definition contains statistical codes and
|
|
450
|
+
if so, it splits the codes by the multi-field delimiter and adds them to
|
|
451
|
+
the folio record's 'statisticalCodeIds' field. If the field does not exist,
|
|
452
|
+
it initializes it as an empty list before appending the codes.
|
|
453
|
+
|
|
454
|
+
Args:
|
|
455
|
+
folio_record (dict): The FOLIO record to which the statistical codes will be added.
|
|
456
|
+
file_def (FileDefinition): The file definition containing the statistical codes.
|
|
457
|
+
legacy_record (Optional[Union[dict, Record]]): The legacy record from which the statistical codes are derived.
|
|
458
|
+
"""
|
|
459
|
+
if file_def.statistical_code:
|
|
460
|
+
code_strings = file_def.statistical_code.split(
|
|
461
|
+
self.library_configuration.multi_field_delimiter
|
|
462
|
+
)
|
|
463
|
+
folio_record["statisticalCodeIds"] = folio_record.get("statisticalCodeIds", []) + code_strings
|
|
464
|
+
|
|
465
|
+
def setup_statistical_codes_map(self, statistical_codes_map):
|
|
466
|
+
if statistical_codes_map:
|
|
467
|
+
self.statistical_codes_mapping = RefDataMapping(
|
|
468
|
+
self.folio_client,
|
|
469
|
+
"/statistical-codes",
|
|
470
|
+
"statisticalCodes",
|
|
471
|
+
statistical_codes_map,
|
|
472
|
+
"code",
|
|
473
|
+
"StatisticalCodeMapping",
|
|
474
|
+
)
|
|
475
|
+
logging.info(f"Statistical codes mapping set up {self.statistical_codes_mapping.mapped_legacy_keys}")
|
|
476
|
+
else:
|
|
477
|
+
self.statistical_codes_mapping = None
|
|
478
|
+
logging.info("Statistical codes map is not set up")
|
|
479
|
+
|
|
480
|
+
def get_statistical_code(self, legacy_item: dict, folio_prop_name: str, index_or_id):
|
|
481
|
+
if self.statistical_codes_mapping:
|
|
482
|
+
return self.get_mapped_ref_data_value(
|
|
483
|
+
self.statistical_codes_mapping,
|
|
484
|
+
legacy_item,
|
|
485
|
+
index_or_id,
|
|
486
|
+
folio_prop_name,
|
|
487
|
+
True,
|
|
488
|
+
)
|
|
489
|
+
self.migration_report.add(
|
|
490
|
+
"StatisticalCodeMapping",
|
|
491
|
+
i18n.t("Mapping not set up"),
|
|
492
|
+
)
|
|
493
|
+
return ""
|
|
494
|
+
|
|
495
|
+
def map_statistical_code_ids(
|
|
496
|
+
self, legacy_ids, folio_record: dict
|
|
497
|
+
):
|
|
498
|
+
if stat_codes := {x: None for x in folio_record.pop("statisticalCodeIds", [])}:
|
|
499
|
+
folio_code_ids = set()
|
|
500
|
+
for stat_code in stat_codes:
|
|
501
|
+
if stat_code_id := self.get_statistical_code({"legacy_stat_code": stat_code}, "statisticalCodeId", legacy_ids):
|
|
502
|
+
folio_code_ids.add(stat_code_id)
|
|
503
|
+
else:
|
|
504
|
+
Helper.log_data_issue(
|
|
505
|
+
legacy_ids,
|
|
506
|
+
i18n.t(
|
|
507
|
+
"Statistical code '%{code}' not found in FOLIO",
|
|
508
|
+
code=stat_code,
|
|
509
|
+
),
|
|
510
|
+
stat_code,
|
|
511
|
+
)
|
|
512
|
+
folio_record["statisticalCodeIds"] = list(folio_code_ids)
|
|
513
|
+
|
|
443
514
|
@property
|
|
444
515
|
def base_string_for_folio_uuid(self):
|
|
445
516
|
if self.library_configuration.use_gateway_url_for_uuids and not self.library_configuration.is_ecs:
|
|
@@ -462,6 +533,9 @@ class MapperBase:
|
|
|
462
533
|
)
|
|
463
534
|
return location_map
|
|
464
535
|
|
|
536
|
+
@staticmethod
|
|
537
|
+
def get_object_type() -> FOLIONamespaces:
|
|
538
|
+
raise NotImplementedError("This method should be overridden in subclasses")
|
|
465
539
|
|
|
466
540
|
def flatten(my_dict: dict, path=""):
|
|
467
541
|
for k, v in iter(my_dict.items()):
|
|
@@ -31,13 +31,13 @@ class CoursesMapper(MappingFileMapperBase):
|
|
|
31
31
|
self.user_cache: dict = {}
|
|
32
32
|
self.notes_mapper: NotesMapper = NotesMapper(
|
|
33
33
|
library_configuration,
|
|
34
|
+
None,
|
|
34
35
|
self.folio_client,
|
|
35
36
|
course_map,
|
|
36
37
|
FOLIONamespaces.note,
|
|
37
38
|
True,
|
|
38
39
|
)
|
|
39
40
|
self.composite_course_schema = self.get_composite_course_schema()
|
|
40
|
-
self.task_configuration = task_configuration
|
|
41
41
|
super().__init__(
|
|
42
42
|
folio_client,
|
|
43
43
|
self.composite_course_schema,
|
|
@@ -45,6 +45,7 @@ class CoursesMapper(MappingFileMapperBase):
|
|
|
45
45
|
None,
|
|
46
46
|
FOLIONamespaces.course,
|
|
47
47
|
library_configuration,
|
|
48
|
+
task_configuration
|
|
48
49
|
)
|
|
49
50
|
self.course_map = course_map
|
|
50
51
|
if terms_map:
|
|
@@ -15,7 +15,7 @@ from folio_migration_tools.mapping_file_transformation.mapping_file_mapper_base
|
|
|
15
15
|
from folio_migration_tools.mapping_file_transformation.ref_data_mapping import (
|
|
16
16
|
RefDataMapping,
|
|
17
17
|
)
|
|
18
|
-
|
|
18
|
+
from folio_migration_tools.task_configuration import AbstractTaskConfiguration
|
|
19
19
|
|
|
20
20
|
class HoldingsMapper(MappingFileMapperBase):
|
|
21
21
|
def __init__(
|
|
@@ -26,6 +26,7 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
26
26
|
call_number_type_map,
|
|
27
27
|
instance_id_map,
|
|
28
28
|
library_configuration: LibraryConfiguration,
|
|
29
|
+
task_config: AbstractTaskConfiguration,
|
|
29
30
|
statistical_codes_map=None,
|
|
30
31
|
):
|
|
31
32
|
holdings_schema = folio_client.get_holdings_schema()
|
|
@@ -37,6 +38,7 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
37
38
|
statistical_codes_map,
|
|
38
39
|
FOLIONamespaces.holdings,
|
|
39
40
|
library_configuration,
|
|
41
|
+
task_config
|
|
40
42
|
)
|
|
41
43
|
self.holdings_map = holdings_map
|
|
42
44
|
|
|
@@ -58,8 +60,10 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
58
60
|
"CallNumberTypeMapping",
|
|
59
61
|
)
|
|
60
62
|
|
|
61
|
-
def perform_additional_mappings(self, folio_rec, file_def):
|
|
63
|
+
def perform_additional_mappings(self, legacy_ids, folio_rec, file_def):
|
|
62
64
|
self.handle_suppression(folio_rec, file_def)
|
|
65
|
+
self.map_statistical_codes(folio_rec, file_def)
|
|
66
|
+
self.map_statistical_code_ids(legacy_ids, folio_rec)
|
|
63
67
|
|
|
64
68
|
def handle_suppression(self, folio_record, file_def: FileDefinition):
|
|
65
69
|
folio_record["discoverySuppress"] = file_def.discovery_suppressed
|
|
@@ -73,8 +77,8 @@ class HoldingsMapper(MappingFileMapperBase):
|
|
|
73
77
|
return self.get_location_id(legacy_item, index_or_id, folio_prop_name)
|
|
74
78
|
elif folio_prop_name == "callNumberTypeId":
|
|
75
79
|
return self.get_call_number_type_id(legacy_item, folio_prop_name, index_or_id)
|
|
76
|
-
elif folio_prop_name.startswith("statisticalCodeIds"):
|
|
77
|
-
|
|
80
|
+
# elif folio_prop_name.startswith("statisticalCodeIds"):
|
|
81
|
+
# return self.get_statistical_code(legacy_item, folio_prop_name, index_or_id)
|
|
78
82
|
|
|
79
83
|
mapped_value = super().get_prop(
|
|
80
84
|
legacy_item, folio_prop_name, index_or_id, schema_default_value
|
|
@@ -52,8 +52,8 @@ class ItemMapper(MappingFileMapperBase):
|
|
|
52
52
|
statistical_codes_map,
|
|
53
53
|
FOLIONamespaces.items,
|
|
54
54
|
library_configuration,
|
|
55
|
+
task_configuration,
|
|
55
56
|
)
|
|
56
|
-
self.task_configuration = task_configuration
|
|
57
57
|
self.item_schema = self.folio_client.get_item_schema()
|
|
58
58
|
self.items_map = items_map
|
|
59
59
|
self.holdings_id_map = holdings_id_map
|
|
@@ -117,8 +117,10 @@ class ItemMapper(MappingFileMapperBase):
|
|
|
117
117
|
"LocationMapping",
|
|
118
118
|
)
|
|
119
119
|
|
|
120
|
-
def perform_additional_mappings(self, folio_rec, file_def):
|
|
120
|
+
def perform_additional_mappings(self, legacy_ids, folio_rec, file_def):
|
|
121
121
|
self.handle_suppression(folio_rec, file_def)
|
|
122
|
+
self.map_statistical_codes(folio_rec, file_def)
|
|
123
|
+
self.map_statistical_code_ids(legacy_ids, folio_rec)
|
|
122
124
|
|
|
123
125
|
def handle_suppression(self, folio_record, file_def: FileDefinition):
|
|
124
126
|
folio_record["discoverySuppress"] = file_def.discovery_suppressed
|
|
@@ -219,15 +221,6 @@ class ItemMapper(MappingFileMapperBase):
|
|
|
219
221
|
return self.get_mapped_ref_data_value(
|
|
220
222
|
self.loan_type_mapping, legacy_item, folio_prop_name, index_or_id
|
|
221
223
|
)
|
|
222
|
-
elif folio_prop_name.startswith("statisticalCodeIds"):
|
|
223
|
-
statistical_code_id = self.get_statistical_code(
|
|
224
|
-
legacy_item, folio_prop_name, index_or_id
|
|
225
|
-
)
|
|
226
|
-
self.migration_report.add(
|
|
227
|
-
"StatisticalCodeMapping",
|
|
228
|
-
f"{folio_prop_name} -> {statistical_code_id}",
|
|
229
|
-
)
|
|
230
|
-
return statistical_code_id
|
|
231
224
|
|
|
232
225
|
mapped_value = super().get_prop(
|
|
233
226
|
legacy_item, folio_prop_name, index_or_id, schema_default_value
|
|
@@ -20,10 +20,8 @@ from folio_migration_tools.custom_exceptions import (
|
|
|
20
20
|
)
|
|
21
21
|
from folio_migration_tools.library_configuration import LibraryConfiguration
|
|
22
22
|
from folio_migration_tools.mapper_base import MapperBase
|
|
23
|
-
from folio_migration_tools.mapping_file_transformation.ref_data_mapping import (
|
|
24
|
-
RefDataMapping,
|
|
25
|
-
)
|
|
26
23
|
from folio_migration_tools.migration_report import MigrationReport
|
|
24
|
+
from folio_migration_tools.task_configuration import AbstractTaskConfiguration
|
|
27
25
|
|
|
28
26
|
empty_vals = ["Not mapped", None, ""]
|
|
29
27
|
|
|
@@ -37,9 +35,10 @@ class MappingFileMapperBase(MapperBase):
|
|
|
37
35
|
statistical_codes_map,
|
|
38
36
|
uuid_namespace: UUID,
|
|
39
37
|
library_configuration: LibraryConfiguration,
|
|
38
|
+
task_config: AbstractTaskConfiguration,
|
|
40
39
|
ignore_legacy_identifier=False,
|
|
41
40
|
):
|
|
42
|
-
super().__init__(library_configuration, folio_client)
|
|
41
|
+
super().__init__(library_configuration, task_config, folio_client)
|
|
43
42
|
self.uuid_namespace = uuid_namespace
|
|
44
43
|
self.ignore_legacy_identifier = ignore_legacy_identifier
|
|
45
44
|
self.schema = schema
|
|
@@ -101,21 +100,6 @@ class MappingFileMapperBase(MapperBase):
|
|
|
101
100
|
)
|
|
102
101
|
csv.register_dialect("tsv", delimiter="\t")
|
|
103
102
|
|
|
104
|
-
def setup_statistical_codes_map(self, statistical_codes_map):
|
|
105
|
-
if statistical_codes_map:
|
|
106
|
-
self.statistical_codes_mapping = RefDataMapping(
|
|
107
|
-
self.folio_client,
|
|
108
|
-
"/statistical-codes",
|
|
109
|
-
"statisticalCodes",
|
|
110
|
-
statistical_codes_map,
|
|
111
|
-
"code",
|
|
112
|
-
"StatisticalCodeMapping",
|
|
113
|
-
)
|
|
114
|
-
logging.info("Statistical codes mapping set up")
|
|
115
|
-
else:
|
|
116
|
-
self.statistical_codes_mapping = None
|
|
117
|
-
logging.info("Statistical codes map is not set up")
|
|
118
|
-
|
|
119
103
|
def setup_field_map(self, ignore_legacy_identifier):
|
|
120
104
|
field_map = {} # Map of folio_fields and source fields as an array
|
|
121
105
|
for k in self.record_map["data"]:
|
|
@@ -14,6 +14,7 @@ class NotesMapper(MappingFileMapperBase):
|
|
|
14
14
|
def __init__(
|
|
15
15
|
self,
|
|
16
16
|
library_configuration: LibraryConfiguration,
|
|
17
|
+
task_configuration,
|
|
17
18
|
folio_client: FolioClient,
|
|
18
19
|
record_map: dict,
|
|
19
20
|
object_type: FOLIONamespaces,
|
|
@@ -28,6 +29,7 @@ class NotesMapper(MappingFileMapperBase):
|
|
|
28
29
|
None,
|
|
29
30
|
object_type,
|
|
30
31
|
library_configuration,
|
|
32
|
+
task_configuration,
|
|
31
33
|
ignore_legacy_identifier,
|
|
32
34
|
)
|
|
33
35
|
|
|
@@ -30,6 +30,7 @@ class CompositeOrderMapper(MappingFileMapperBase):
|
|
|
30
30
|
self,
|
|
31
31
|
folio_client: FolioClient,
|
|
32
32
|
library_configuration: LibraryConfiguration,
|
|
33
|
+
task_configuration,
|
|
33
34
|
composite_order_map: dict,
|
|
34
35
|
organizations_id_map: dict,
|
|
35
36
|
instance_id_map: dict,
|
|
@@ -53,6 +54,7 @@ class CompositeOrderMapper(MappingFileMapperBase):
|
|
|
53
54
|
None,
|
|
54
55
|
FOLIONamespaces.orders,
|
|
55
56
|
library_configuration,
|
|
57
|
+
task_configuration,
|
|
56
58
|
)
|
|
57
59
|
logging.info("Loading Instance ID map...")
|
|
58
60
|
self.instance_id_map = instance_id_map
|
|
@@ -80,6 +82,7 @@ class CompositeOrderMapper(MappingFileMapperBase):
|
|
|
80
82
|
self.folio_client: FolioClient = folio_client
|
|
81
83
|
self.notes_mapper: NotesMapper = NotesMapper(
|
|
82
84
|
library_configuration,
|
|
85
|
+
None,
|
|
83
86
|
self.folio_client,
|
|
84
87
|
composite_order_map,
|
|
85
88
|
FOLIONamespaces.note,
|
|
@@ -366,7 +369,7 @@ class CompositeOrderMapper(MappingFileMapperBase):
|
|
|
366
369
|
|
|
367
370
|
def perform_additional_mapping(self, index_or_id, composite_order):
|
|
368
371
|
self.validate_po_number(index_or_id, composite_order.get("poNumber"))
|
|
369
|
-
|
|
372
|
+
|
|
370
373
|
# Get organization UUID from FOLIO
|
|
371
374
|
composite_order["vendor"] = self.get_folio_organization_uuid(
|
|
372
375
|
index_or_id, composite_order.get("vendor")
|
|
@@ -23,6 +23,7 @@ class OrganizationMapper(MappingFileMapperBase):
|
|
|
23
23
|
self,
|
|
24
24
|
folio_client: FolioClient,
|
|
25
25
|
library_configuration: LibraryConfiguration,
|
|
26
|
+
task_config,
|
|
26
27
|
organization_map: dict,
|
|
27
28
|
organization_types_map,
|
|
28
29
|
address_categories_map,
|
|
@@ -43,6 +44,7 @@ class OrganizationMapper(MappingFileMapperBase):
|
|
|
43
44
|
None,
|
|
44
45
|
FOLIONamespaces.organizations,
|
|
45
46
|
library_configuration,
|
|
47
|
+
task_config,
|
|
46
48
|
)
|
|
47
49
|
self.organization_schema = organization_schema
|
|
48
50
|
# Set up reference data maps
|
|
@@ -56,6 +58,7 @@ class OrganizationMapper(MappingFileMapperBase):
|
|
|
56
58
|
self.folio_client: FolioClient = folio_client
|
|
57
59
|
self.notes_mapper: NotesMapper = NotesMapper(
|
|
58
60
|
library_configuration,
|
|
61
|
+
None,
|
|
59
62
|
self.folio_client,
|
|
60
63
|
organization_map,
|
|
61
64
|
FOLIONamespaces.note,
|
|
@@ -47,10 +47,12 @@ class UserMapper(MappingFileMapperBase):
|
|
|
47
47
|
None,
|
|
48
48
|
FOLIONamespaces.users,
|
|
49
49
|
library_config,
|
|
50
|
+
task_config
|
|
50
51
|
)
|
|
51
|
-
self.task_config =
|
|
52
|
+
self.task_config = self.task_configuration
|
|
52
53
|
self.notes_mapper: NotesMapper = NotesMapper(
|
|
53
54
|
self.library_configuration,
|
|
55
|
+
None,
|
|
54
56
|
self.folio_client,
|
|
55
57
|
self.record_map,
|
|
56
58
|
FOLIONamespaces.users,
|
|
@@ -62,6 +62,7 @@ class AuthorityMapper(RulesMapperBase):
|
|
|
62
62
|
folio_client,
|
|
63
63
|
library_configuration,
|
|
64
64
|
task_configuration,
|
|
65
|
+
None,
|
|
65
66
|
self.get_authority_json_schema(folio_client, library_configuration),
|
|
66
67
|
Conditions(folio_client, self, "auth", library_configuration.folio_release),
|
|
67
68
|
)
|
|
@@ -6,14 +6,14 @@ import urllib.parse
|
|
|
6
6
|
import uuid
|
|
7
7
|
from abc import abstractmethod
|
|
8
8
|
from textwrap import wrap
|
|
9
|
-
from typing import List, Tuple
|
|
9
|
+
from typing import Dict, List, Tuple
|
|
10
10
|
|
|
11
11
|
import i18n
|
|
12
12
|
import pymarc
|
|
13
13
|
from dateutil.parser import parse
|
|
14
14
|
from folio_uuid.folio_uuid import FOLIONamespaces, FolioUUID
|
|
15
15
|
from folioclient import FolioClient
|
|
16
|
-
from pymarc import Field, Record, Subfield
|
|
16
|
+
from pymarc import Field, Optional, Record, Subfield
|
|
17
17
|
|
|
18
18
|
from folio_migration_tools.custom_exceptions import (
|
|
19
19
|
TransformationFieldMappingError,
|
|
@@ -35,18 +35,18 @@ class RulesMapperBase(MapperBase):
|
|
|
35
35
|
folio_client: FolioClient,
|
|
36
36
|
library_configuration: LibraryConfiguration,
|
|
37
37
|
task_configuration,
|
|
38
|
+
statistical_codes_map: Optional[Dict],
|
|
38
39
|
schema: dict,
|
|
39
40
|
conditions=None,
|
|
40
41
|
parent_id_map: dict[str, tuple] = None,
|
|
41
42
|
):
|
|
42
|
-
super().__init__(library_configuration, folio_client, parent_id_map)
|
|
43
|
+
super().__init__(library_configuration, task_configuration, folio_client, parent_id_map)
|
|
43
44
|
self.parsed_records = 0
|
|
44
45
|
self.id_map: dict[str, tuple] = {}
|
|
45
46
|
self.start = time.time()
|
|
46
47
|
self.last_batch_time = time.time()
|
|
47
48
|
self.folio_client: FolioClient = folio_client
|
|
48
49
|
self.schema: dict = schema
|
|
49
|
-
self.task_configuration = task_configuration
|
|
50
50
|
self.conditions = conditions
|
|
51
51
|
self.item_json_schema = ""
|
|
52
52
|
self.mappings: dict = {}
|
|
@@ -61,6 +61,8 @@ class RulesMapperBase(MapperBase):
|
|
|
61
61
|
self.migration_report,
|
|
62
62
|
self.task_configuration.deactivate035_from001,
|
|
63
63
|
)
|
|
64
|
+
|
|
65
|
+
self.setup_statistical_codes_map(statistical_codes_map)
|
|
64
66
|
logging.info("Current user id is %s", self.folio_client.current_user)
|
|
65
67
|
|
|
66
68
|
def print_progress(self):
|
|
@@ -813,6 +815,83 @@ class RulesMapperBase(MapperBase):
|
|
|
813
815
|
)
|
|
814
816
|
data_import_marc_file.write(marc_record.as_marc())
|
|
815
817
|
|
|
818
|
+
|
|
819
|
+
def map_statistical_codes(
|
|
820
|
+
self,
|
|
821
|
+
folio_record: dict,
|
|
822
|
+
file_def: FileDefinition,
|
|
823
|
+
marc_record: Record,
|
|
824
|
+
):
|
|
825
|
+
"""Map statistical codes to FOLIO instance
|
|
826
|
+
|
|
827
|
+
This method first calls the base class method to map statistical codes
|
|
828
|
+
from the file_def. Then, it checks to see if there are any MARC field
|
|
829
|
+
mappings defined in the task configuration. If so, it creates a list
|
|
830
|
+
of lists where the first element is the MARC field tag, and the remaining
|
|
831
|
+
elements are the subfields to be used for mapping. It then iterates
|
|
832
|
+
through the MARC fields, retrieves the values based on the subfields.
|
|
833
|
+
Finally, it adds the mapped codes to the folio_record's statisticalCodeIds.
|
|
834
|
+
|
|
835
|
+
Args:
|
|
836
|
+
legacy_ids (List[str]): The legacy IDs of the folio record
|
|
837
|
+
folio_record (dict): The Dictionary representation of the FOLIO record
|
|
838
|
+
marc_record (Record): The pymarc Record object
|
|
839
|
+
file_def (FileDefinition): The file definition object from which marc_record was read
|
|
840
|
+
"""
|
|
841
|
+
super().map_statistical_codes(folio_record, file_def)
|
|
842
|
+
if self.task_configuration.statistical_code_mapping_fields:
|
|
843
|
+
stat_code_marc_fields = []
|
|
844
|
+
for mapping in self.task_configuration.statistical_code_mapping_fields:
|
|
845
|
+
stat_code_marc_fields.append(mapping.split("$"))
|
|
846
|
+
for field_map in stat_code_marc_fields:
|
|
847
|
+
mapped_codes = self.map_stat_codes_from_marc_field(field_map, marc_record, self.library_configuration.multi_field_delimiter)
|
|
848
|
+
folio_record['statisticalCodeIds'] = folio_record.get("statisticalCodeIds", []) + mapped_codes
|
|
849
|
+
|
|
850
|
+
@staticmethod
|
|
851
|
+
def map_stat_codes_from_marc_field(field_map: List[str], marc_record: Record, multi_field_delimiter: str="<delimiter>") -> List[str]:
|
|
852
|
+
"""Map statistical codes from MARC field to FOLIO instance.
|
|
853
|
+
|
|
854
|
+
This function extracts statistical codes from a MARC field based on the provided field map.
|
|
855
|
+
It supports multiple subfields and uses a delimiter to handle concatenated values.
|
|
856
|
+
|
|
857
|
+
Args:
|
|
858
|
+
field_map (List[str]): A list where the first element is the MARC field tag, and the remaining elements are subfields to extract values from.
|
|
859
|
+
marc_record (Record): The MARC record to process.
|
|
860
|
+
multi_field_delimiter (str): A delimiter used to concatenate multiple subfield values that should be individual mapped values.
|
|
861
|
+
|
|
862
|
+
Returns:
|
|
863
|
+
str: A string of statistical codes extracted from the MARC field, formatted as "<field>_<subfield>:<value>".
|
|
864
|
+
"""
|
|
865
|
+
field_values = []
|
|
866
|
+
if len(field_map) == 2:
|
|
867
|
+
subfields = []
|
|
868
|
+
for mf in marc_record.get_fields(field_map[0]):
|
|
869
|
+
subfields.extend(
|
|
870
|
+
multi_field_delimiter.join(
|
|
871
|
+
mf.get_subfields(field_map[1])
|
|
872
|
+
).split(multi_field_delimiter)
|
|
873
|
+
)
|
|
874
|
+
field_values.extend(
|
|
875
|
+
[
|
|
876
|
+
f"{field_map[0]}_{field_map[1]}:{x}" for
|
|
877
|
+
x in subfields
|
|
878
|
+
]
|
|
879
|
+
)
|
|
880
|
+
elif len(field_map) > 2:
|
|
881
|
+
for mf in marc_record.get_fields(field_map[0]):
|
|
882
|
+
for sf in field_map[1:]:
|
|
883
|
+
field_values.extend(
|
|
884
|
+
[
|
|
885
|
+
f"{field_map[0]}_{sf}:{x}" for x in multi_field_delimiter.join(
|
|
886
|
+
mf.get_subfields(sf)
|
|
887
|
+
).split(multi_field_delimiter)
|
|
888
|
+
]
|
|
889
|
+
)
|
|
890
|
+
elif field_map:
|
|
891
|
+
for mf in marc_record.get_fields(field_map[0]):
|
|
892
|
+
field_values.append(f"{field_map[0]}:{mf.value()}")
|
|
893
|
+
return field_values
|
|
894
|
+
|
|
816
895
|
def save_source_record(
|
|
817
896
|
self,
|
|
818
897
|
srs_records_file,
|
|
@@ -44,11 +44,13 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
44
44
|
folio_client: FolioClient,
|
|
45
45
|
library_configuration: LibraryConfiguration,
|
|
46
46
|
task_configuration: MarcTaskConfigurationBase,
|
|
47
|
+
statistical_codes_map: Dict[str, str] = None,
|
|
47
48
|
):
|
|
48
49
|
super().__init__(
|
|
49
50
|
folio_client,
|
|
50
51
|
library_configuration,
|
|
51
52
|
task_configuration,
|
|
53
|
+
statistical_codes_map,
|
|
52
54
|
self.get_instance_schema(folio_client),
|
|
53
55
|
Conditions(folio_client, self, "bibs", library_configuration.folio_release),
|
|
54
56
|
)
|
|
@@ -205,6 +207,9 @@ class BibsRulesMapper(RulesMapperBase):
|
|
|
205
207
|
folio_instance["modeOfIssuanceId"] = self.get_mode_of_issuance_id(marc_record, legacy_ids)
|
|
206
208
|
self.handle_languages(folio_instance, marc_record, legacy_ids)
|
|
207
209
|
self.handle_suppression(folio_instance, file_def)
|
|
210
|
+
# Map statistical codes from MARC and FileDefinition, then map the IDs
|
|
211
|
+
self.map_statistical_codes(folio_instance, file_def, marc_record)
|
|
212
|
+
self.map_statistical_code_ids(legacy_ids, folio_instance)
|
|
208
213
|
self.handle_holdings(marc_record)
|
|
209
214
|
if prec_titles := folio_instance.get("precedingTitles", []):
|
|
210
215
|
self.migration_report.add("PrecedingSuccedingTitles", f"{len(prec_titles)}")
|
|
@@ -7,6 +7,7 @@ import i18n
|
|
|
7
7
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
8
8
|
from folio_uuid.folio_uuid import FolioUUID
|
|
9
9
|
from folioclient import FolioClient
|
|
10
|
+
from pymarc import Optional
|
|
10
11
|
from pymarc.field import Field
|
|
11
12
|
from pymarc.record import Record
|
|
12
13
|
|
|
@@ -40,20 +41,21 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
40
41
|
library_configuration: LibraryConfiguration,
|
|
41
42
|
parent_id_map: dict,
|
|
42
43
|
boundwith_relationship_map_rows: List[Dict],
|
|
44
|
+
statistical_codes_map: Optional[Dict] = None,
|
|
43
45
|
):
|
|
44
|
-
self.task_configuration = task_configuration
|
|
45
46
|
self.conditions = Conditions(
|
|
46
47
|
folio_client,
|
|
47
48
|
self,
|
|
48
49
|
"holdings",
|
|
49
50
|
library_configuration.folio_release,
|
|
50
|
-
|
|
51
|
+
task_configuration.default_call_number_type_name,
|
|
51
52
|
)
|
|
52
53
|
self.folio = folio_client
|
|
53
54
|
super().__init__(
|
|
54
55
|
folio_client,
|
|
55
56
|
library_configuration,
|
|
56
57
|
task_configuration,
|
|
58
|
+
statistical_codes_map,
|
|
57
59
|
self.fetch_holdings_schema(folio_client),
|
|
58
60
|
self.conditions,
|
|
59
61
|
parent_id_map,
|
|
@@ -297,6 +299,10 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
297
299
|
"",
|
|
298
300
|
)
|
|
299
301
|
self.handle_suppression(folio_holding, file_def, True)
|
|
302
|
+
# First, map statistical codes from MARC fields and FileDefinitions to FOLIO statistical codes.
|
|
303
|
+
# Then, convert the mapped statistical codes to their corresponding code IDs.
|
|
304
|
+
self.map_statistical_codes(folio_holding, file_def, marc_record)
|
|
305
|
+
self.map_statistical_code_ids(legacy_ids, folio_holding)
|
|
300
306
|
self.set_source_id(self.create_source_records, folio_holding, self.holdingssources, file_def)
|
|
301
307
|
|
|
302
308
|
def pick_first_location_if_many(self, folio_holding: Dict, legacy_ids: List[str]):
|
|
@@ -582,7 +588,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
582
588
|
"", "Column BIB_ID missing from Boundwith relationship map", ""
|
|
583
589
|
)
|
|
584
590
|
|
|
585
|
-
def setup_boundwith_relationship_map(self,
|
|
591
|
+
def setup_boundwith_relationship_map(self, boundwith_relationship_map_list: List[Dict]):
|
|
586
592
|
"""
|
|
587
593
|
Creates a map of MFHD_ID to BIB_ID for boundwith relationships.
|
|
588
594
|
|
|
@@ -597,7 +603,7 @@ class RulesMapperHoldings(RulesMapperBase):
|
|
|
597
603
|
TransformationRecordFailedError: If BIB_ID is not in the instance id map.
|
|
598
604
|
"""
|
|
599
605
|
new_map = {}
|
|
600
|
-
for idx, entry in enumerate(
|
|
606
|
+
for idx, entry in enumerate(boundwith_relationship_map_list):
|
|
601
607
|
self.verity_boundwith_map_entry(entry)
|
|
602
608
|
mfhd_uuid = str(
|
|
603
609
|
FolioUUID(
|
|
@@ -7,8 +7,6 @@ from pydantic import Field
|
|
|
7
7
|
|
|
8
8
|
from folio_migration_tools.helper import Helper
|
|
9
9
|
from folio_migration_tools.library_configuration import (
|
|
10
|
-
FileDefinition,
|
|
11
|
-
HridHandling,
|
|
12
10
|
IlsFlavour,
|
|
13
11
|
LibraryConfiguration,
|
|
14
12
|
)
|
|
@@ -116,11 +114,23 @@ class BibsTransformer(MigrationTaskBase):
|
|
|
116
114
|
use_logging: bool = True,
|
|
117
115
|
):
|
|
118
116
|
super().__init__(library_config, task_config, folio_client, use_logging)
|
|
117
|
+
self.task_config = task_config
|
|
118
|
+
self.task_configuration = self.task_config
|
|
119
|
+
if self.task_config.statistical_codes_map_file_name:
|
|
120
|
+
statcode_mapping = self.load_ref_data_mapping_file(
|
|
121
|
+
"statisticalCodeIds",
|
|
122
|
+
self.folder_structure.mapping_files_folder
|
|
123
|
+
/ self.task_config.statistical_codes_map_file_name,
|
|
124
|
+
[],
|
|
125
|
+
False,
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
statcode_mapping = None
|
|
119
129
|
self.processor: MarcFileProcessor
|
|
120
130
|
self.check_source_files(
|
|
121
131
|
self.folder_structure.legacy_records_folder, self.task_configuration.files
|
|
122
132
|
)
|
|
123
|
-
self.mapper = BibsRulesMapper(self.folio_client, library_config, self.task_configuration)
|
|
133
|
+
self.mapper = BibsRulesMapper(self.folio_client, library_config, self.task_configuration, statcode_mapping)
|
|
124
134
|
self.bib_ids: set = set()
|
|
125
135
|
if (
|
|
126
136
|
self.task_configuration.reset_hrid_settings
|
|
@@ -160,6 +160,16 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
160
160
|
),
|
|
161
161
|
),
|
|
162
162
|
] = True
|
|
163
|
+
statistical_codes_map_file_name: Annotated[
|
|
164
|
+
Optional[str],
|
|
165
|
+
Field(
|
|
166
|
+
title="Statistical code map file name",
|
|
167
|
+
description=(
|
|
168
|
+
"Path to the file containing the mapping of statistical codes. "
|
|
169
|
+
"The file should be in TSV format with legacy_stat_code and folio_code columns."
|
|
170
|
+
),
|
|
171
|
+
),
|
|
172
|
+
] = ""
|
|
163
173
|
|
|
164
174
|
@staticmethod
|
|
165
175
|
def get_object_type() -> FOLIONamespaces:
|
|
@@ -174,16 +184,27 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
174
184
|
):
|
|
175
185
|
super().__init__(library_config, task_config, folio_client, use_logging)
|
|
176
186
|
self.fallback_holdings_type = None
|
|
187
|
+
self.folio_keys, self.holdings_field_map = self.load_mapped_fields()
|
|
188
|
+
if any(k for k in self.folio_keys if k.startswith("statisticalCodeIds")):
|
|
189
|
+
statcode_mapping = self.load_ref_data_mapping_file(
|
|
190
|
+
"statisticalCodeIds",
|
|
191
|
+
self.folder_structure.mapping_files_folder
|
|
192
|
+
/ self.task_configuration.statistical_codes_map_file_name,
|
|
193
|
+
self.folio_keys,
|
|
194
|
+
False,
|
|
195
|
+
)
|
|
196
|
+
else:
|
|
197
|
+
statcode_mapping = None
|
|
177
198
|
try:
|
|
178
|
-
self.task_config = task_config
|
|
179
199
|
self.bound_with_keys = set()
|
|
180
200
|
self.mapper = HoldingsMapper(
|
|
181
201
|
self.folio_client,
|
|
182
|
-
self.
|
|
202
|
+
self.holdings_field_map,
|
|
183
203
|
self.load_location_map(),
|
|
184
204
|
self.load_call_number_type_map(),
|
|
185
205
|
self.load_instance_id_map(True),
|
|
186
206
|
library_config,
|
|
207
|
+
statcode_mapping,
|
|
187
208
|
)
|
|
188
209
|
self.holdings = {}
|
|
189
210
|
self.total_records = 0
|
|
@@ -196,19 +217,19 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
196
217
|
logging.info("%s\tholdings types in tenant", len(self.holdings_types))
|
|
197
218
|
self.validate_merge_criterias()
|
|
198
219
|
self.check_source_files(
|
|
199
|
-
self.folder_structure.data_folder / "items", self.
|
|
220
|
+
self.folder_structure.data_folder / "items", self.task_configuration.files
|
|
200
221
|
)
|
|
201
222
|
self.fallback_holdings_type = next(
|
|
202
223
|
h
|
|
203
224
|
for h in self.holdings_types
|
|
204
|
-
if h["id"] == self.
|
|
225
|
+
if h["id"] == self.task_configuration.fallback_holdings_type_id
|
|
205
226
|
)
|
|
206
227
|
if not self.fallback_holdings_type:
|
|
207
228
|
raise TransformationProcessError(
|
|
208
229
|
"",
|
|
209
230
|
(
|
|
210
231
|
"Holdings type with ID "
|
|
211
|
-
f"{self.
|
|
232
|
+
f"{self.task_configuration.fallback_holdings_type_id} "
|
|
212
233
|
"not found in FOLIO."
|
|
213
234
|
),
|
|
214
235
|
)
|
|
@@ -216,15 +237,15 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
216
237
|
"%s will be used as default holdings type",
|
|
217
238
|
self.fallback_holdings_type["name"],
|
|
218
239
|
)
|
|
219
|
-
if any(self.
|
|
220
|
-
for file_name in self.
|
|
240
|
+
if any(self.task_configuration.previously_generated_holdings_files):
|
|
241
|
+
for file_name in self.task_configuration.previously_generated_holdings_files:
|
|
221
242
|
logging.info("Processing %s", file_name)
|
|
222
243
|
self.holdings.update(
|
|
223
244
|
HoldingsHelper.load_previously_generated_holdings(
|
|
224
245
|
self.folder_structure.results_folder / file_name,
|
|
225
|
-
self.
|
|
246
|
+
self.task_configuration.holdings_merge_criteria,
|
|
226
247
|
self.mapper.migration_report,
|
|
227
|
-
self.
|
|
248
|
+
self.task_configuration.holdings_type_uuid_for_boundwiths,
|
|
228
249
|
)
|
|
229
250
|
)
|
|
230
251
|
|
|
@@ -260,7 +281,7 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
260
281
|
def load_call_number_type_map(self):
|
|
261
282
|
with open(
|
|
262
283
|
self.folder_structure.mapping_files_folder
|
|
263
|
-
/ self.
|
|
284
|
+
/ self.task_configuration.call_number_type_map_file_name,
|
|
264
285
|
"r",
|
|
265
286
|
) as callnumber_type_map_f:
|
|
266
287
|
return self.load_ref_data_map_from_file(
|
|
@@ -269,7 +290,7 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
269
290
|
|
|
270
291
|
def load_location_map(self):
|
|
271
292
|
with open(
|
|
272
|
-
self.folder_structure.mapping_files_folder / self.
|
|
293
|
+
self.folder_structure.mapping_files_folder / self.task_configuration.location_map_file_name
|
|
273
294
|
) as location_map_f:
|
|
274
295
|
return self.load_ref_data_map_from_file(
|
|
275
296
|
location_map_f, "Found %s rows in location map"
|
|
@@ -283,7 +304,7 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
283
304
|
|
|
284
305
|
def load_mapped_fields(self):
|
|
285
306
|
with open(
|
|
286
|
-
self.folder_structure.mapping_files_folder / self.
|
|
307
|
+
self.folder_structure.mapping_files_folder / self.task_configuration.holdings_map_file_name
|
|
287
308
|
) as holdings_mapper_f:
|
|
288
309
|
holdings_map = json.load(holdings_mapper_f)
|
|
289
310
|
logging.info("%s fields in holdings mapping file map", len(holdings_map["data"]))
|
|
@@ -294,11 +315,11 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
294
315
|
"%s mapped fields in holdings mapping file map",
|
|
295
316
|
len(list(mapped_fields)),
|
|
296
317
|
)
|
|
297
|
-
return holdings_map
|
|
318
|
+
return mapped_fields, holdings_map
|
|
298
319
|
|
|
299
320
|
def do_work(self):
|
|
300
321
|
logging.info("Starting....")
|
|
301
|
-
for file_def in self.
|
|
322
|
+
for file_def in self.task_configuration.files:
|
|
302
323
|
logging.info("Processing %s", file_def.file_name)
|
|
303
324
|
try:
|
|
304
325
|
self.process_single_file(file_def)
|
|
@@ -311,7 +332,7 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
311
332
|
print(f"\n{error_str}\nHalting")
|
|
312
333
|
sys.exit(1)
|
|
313
334
|
logging.info(
|
|
314
|
-
f"processed {self.total_records:,} records in {len(self.
|
|
335
|
+
f"processed {self.total_records:,} records in {len(self.task_configuration.files)} files"
|
|
315
336
|
)
|
|
316
337
|
|
|
317
338
|
def wrap_up(self):
|
|
@@ -357,8 +378,8 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
357
378
|
holdings_schema = self.folio_client.get_holdings_schema()
|
|
358
379
|
properties = holdings_schema["properties"].keys()
|
|
359
380
|
logging.info(properties)
|
|
360
|
-
logging.info(self.
|
|
361
|
-
res = [mc for mc in self.
|
|
381
|
+
logging.info(self.task_configuration.holdings_merge_criteria)
|
|
382
|
+
res = [mc for mc in self.task_configuration.holdings_merge_criteria if mc not in properties]
|
|
362
383
|
if any(res):
|
|
363
384
|
logging.critical(
|
|
364
385
|
(
|
|
@@ -426,7 +447,7 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
426
447
|
raise TransformationRecordFailedError(legacy_id, "No instance id in parsed record", "")
|
|
427
448
|
|
|
428
449
|
for folio_holding in holdings_from_row:
|
|
429
|
-
self.mapper.perform_additional_mappings(folio_holding, file_def)
|
|
450
|
+
self.mapper.perform_additional_mappings(legacy_id, folio_holding, file_def)
|
|
430
451
|
self.merge_holding_in(folio_holding, all_instance_ids, legacy_id)
|
|
431
452
|
self.mapper.report_folio_mapping(folio_holding, self.mapper.schema)
|
|
432
453
|
|
|
@@ -436,7 +457,7 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
436
457
|
self.mapper.create_bound_with_holdings(
|
|
437
458
|
folio_holding,
|
|
438
459
|
folio_holding["instanceId"],
|
|
439
|
-
self.
|
|
460
|
+
self.task_configuration.holdings_type_uuid_for_boundwiths,
|
|
440
461
|
)
|
|
441
462
|
)
|
|
442
463
|
|
|
@@ -480,9 +501,9 @@ class HoldingsCsvTransformer(MigrationTaskBase):
|
|
|
480
501
|
# Regular holding. Merge according to criteria
|
|
481
502
|
new_holding_key = HoldingsHelper.to_key(
|
|
482
503
|
incoming_holding,
|
|
483
|
-
self.
|
|
504
|
+
self.task_configuration.holdings_merge_criteria,
|
|
484
505
|
self.mapper.migration_report,
|
|
485
|
-
self.
|
|
506
|
+
self.task_configuration.holdings_type_uuid_for_boundwiths,
|
|
486
507
|
)
|
|
487
508
|
if self.holdings.get(new_holding_key, None):
|
|
488
509
|
self.mapper.migration_report.add_general_statistics(
|
|
@@ -216,7 +216,16 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
216
216
|
):
|
|
217
217
|
csv.register_dialect("tsv", delimiter="\t")
|
|
218
218
|
super().__init__(library_config, task_config, folio_client, use_logging)
|
|
219
|
-
self.
|
|
219
|
+
if self.task_configuration.statistical_codes_map_file_name:
|
|
220
|
+
statcode_mapping = self.load_ref_data_mapping_file(
|
|
221
|
+
"statisticalCodeIds",
|
|
222
|
+
self.folder_structure.mapping_files_folder
|
|
223
|
+
/ self.task_configuration.statistical_codes_map_file_name,
|
|
224
|
+
[],
|
|
225
|
+
False,
|
|
226
|
+
)
|
|
227
|
+
else:
|
|
228
|
+
statcode_mapping = None
|
|
220
229
|
self.holdings_types = list(
|
|
221
230
|
self.folio_client.folio_get_all("/holdings-types", "holdingsTypes")
|
|
222
231
|
)
|
|
@@ -224,7 +233,7 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
224
233
|
(
|
|
225
234
|
h
|
|
226
235
|
for h in self.holdings_types
|
|
227
|
-
if h["id"] == self.
|
|
236
|
+
if h["id"] == self.task_configuration.fallback_holdings_type_id
|
|
228
237
|
),
|
|
229
238
|
{"name": ""},
|
|
230
239
|
)
|
|
@@ -232,7 +241,7 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
232
241
|
raise TransformationProcessError(
|
|
233
242
|
"",
|
|
234
243
|
(
|
|
235
|
-
f"Holdings type with ID {self.
|
|
244
|
+
f"Holdings type with ID {self.task_configuration.fallback_holdings_type_id}"
|
|
236
245
|
" not found in FOLIO."
|
|
237
246
|
),
|
|
238
247
|
)
|
|
@@ -243,11 +252,11 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
243
252
|
|
|
244
253
|
# Load Boundwith relationship map
|
|
245
254
|
self.boundwith_relationship_map_rows = []
|
|
246
|
-
if self.
|
|
255
|
+
if self.task_configuration.boundwith_relationship_file_path:
|
|
247
256
|
try:
|
|
248
257
|
with open(
|
|
249
258
|
self.folder_structure.legacy_records_folder
|
|
250
|
-
/ self.
|
|
259
|
+
/ self.task_configuration.boundwith_relationship_file_path
|
|
251
260
|
) as boundwith_relationship_file:
|
|
252
261
|
self.boundwith_relationship_map_rows = list(
|
|
253
262
|
csv.DictReader(boundwith_relationship_file, dialect="tsv")
|
|
@@ -260,28 +269,29 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
260
269
|
raise TransformationProcessError(
|
|
261
270
|
"",
|
|
262
271
|
i18n.t("Provided boundwith relationship file not found"),
|
|
263
|
-
self.
|
|
272
|
+
self.task_configuration.boundwith_relationship_file_path,
|
|
264
273
|
)
|
|
265
274
|
|
|
266
275
|
location_map_path = (
|
|
267
276
|
self.folder_structure.mapping_files_folder
|
|
268
|
-
/ self.
|
|
277
|
+
/ self.task_configuration.location_map_file_name
|
|
269
278
|
)
|
|
270
279
|
with open(location_map_path) as location_map_file:
|
|
271
280
|
self.location_map = list(csv.DictReader(location_map_file, dialect="tsv"))
|
|
272
281
|
logging.info("Locations in map: %s", len(self.location_map))
|
|
273
282
|
|
|
274
283
|
self.check_source_files(
|
|
275
|
-
self.folder_structure.legacy_records_folder, self.
|
|
284
|
+
self.folder_structure.legacy_records_folder, self.task_configuration.files
|
|
276
285
|
)
|
|
277
286
|
self.instance_id_map = self.load_instance_id_map(True)
|
|
278
287
|
self.mapper = RulesMapperHoldings(
|
|
279
288
|
self.folio_client,
|
|
280
289
|
self.location_map,
|
|
281
|
-
self.
|
|
290
|
+
self.task_configuration,
|
|
282
291
|
self.library_configuration,
|
|
283
292
|
self.instance_id_map,
|
|
284
293
|
self.boundwith_relationship_map_rows,
|
|
294
|
+
statcode_mapping
|
|
285
295
|
)
|
|
286
296
|
self.add_supplemental_mfhd_mappings()
|
|
287
297
|
if (
|
|
@@ -293,12 +303,12 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
293
303
|
logging.info("Init done")
|
|
294
304
|
|
|
295
305
|
def add_supplemental_mfhd_mappings(self):
|
|
296
|
-
if self.
|
|
306
|
+
if self.task_configuration.supplemental_mfhd_mapping_rules_file:
|
|
297
307
|
try:
|
|
298
308
|
with open(
|
|
299
309
|
(
|
|
300
310
|
self.folder_structure.mapping_files_folder
|
|
301
|
-
/ self.
|
|
311
|
+
/ self.task_configuration.supplemental_mfhd_mapping_rules_file
|
|
302
312
|
),
|
|
303
313
|
"r",
|
|
304
314
|
) as new_rules_file:
|
|
@@ -313,7 +323,7 @@ class HoldingsMarcTransformer(MigrationTaskBase):
|
|
|
313
323
|
raise TransformationProcessError(
|
|
314
324
|
"",
|
|
315
325
|
"Provided supplemental MFHD mapping rules file not found",
|
|
316
|
-
self.
|
|
326
|
+
self.task_configuration.supplemental_mfhd_mapping_rules_file,
|
|
317
327
|
)
|
|
318
328
|
else:
|
|
319
329
|
new_rules = {}
|
|
@@ -124,10 +124,10 @@ class ItemsTransformer(MigrationTaskBase):
|
|
|
124
124
|
statistical_codes_map_file_name: Annotated[
|
|
125
125
|
Optional[str],
|
|
126
126
|
Field(
|
|
127
|
-
title="Statistical
|
|
127
|
+
title="Statistical code map file name",
|
|
128
128
|
description=(
|
|
129
|
-
"
|
|
130
|
-
"
|
|
129
|
+
"Path to the file containing the mapping of statistical codes. "
|
|
130
|
+
"The file should be in TSV format with legacy_stat_code and folio_code columns."
|
|
131
131
|
),
|
|
132
132
|
),
|
|
133
133
|
] = ""
|
|
@@ -205,6 +205,7 @@ class ItemsTransformer(MigrationTaskBase):
|
|
|
205
205
|
csv.register_dialect("tsv", delimiter="\t")
|
|
206
206
|
super().__init__(library_config, task_config, folio_client, use_logging)
|
|
207
207
|
self.task_config = task_config
|
|
208
|
+
self.task_configuration = self.task_config
|
|
208
209
|
self.check_source_files(
|
|
209
210
|
self.folder_structure.legacy_records_folder, self.task_config.files
|
|
210
211
|
)
|
|
@@ -455,7 +455,7 @@ class MigrationTaskBase:
|
|
|
455
455
|
logging.info("No mapping setup for %s", folio_property_name)
|
|
456
456
|
logging.info("%s will have default mapping if any ", folio_property_name)
|
|
457
457
|
logging.info(
|
|
458
|
-
"Add a file named %s and add the field to the
|
|
458
|
+
"Add a file named %s and add the field to the field mapping json file.",
|
|
459
459
|
map_file_path,
|
|
460
460
|
)
|
|
461
461
|
return None
|
|
@@ -522,6 +522,27 @@ class MarcTaskConfigurationBase(task_configuration.AbstractTaskConfiguration):
|
|
|
522
522
|
),
|
|
523
523
|
),
|
|
524
524
|
] = False
|
|
525
|
+
statistical_codes_map_file_name: Annotated[
|
|
526
|
+
Optional[str],
|
|
527
|
+
Field(
|
|
528
|
+
title="Statistical code map file name",
|
|
529
|
+
description=(
|
|
530
|
+
"Path to the file containing the mapping of statistical codes. "
|
|
531
|
+
"The file should be in TSV format with legacy_stat_code and folio_code columns."
|
|
532
|
+
),
|
|
533
|
+
),
|
|
534
|
+
] = ""
|
|
535
|
+
statistical_code_mapping_fields: Annotated[
|
|
536
|
+
List[str],
|
|
537
|
+
Field(
|
|
538
|
+
title="Statistical code mapping fields",
|
|
539
|
+
description=(
|
|
540
|
+
"List of fields + subfields to be used for mapping statistical codes. "
|
|
541
|
+
"Subfields should be delimited by a \"$\" (eg. 907$a). Single repeating subfields "
|
|
542
|
+
"will be treated as unique values. Multiple subfields will be concatenated together with a space."
|
|
543
|
+
),
|
|
544
|
+
),
|
|
545
|
+
] = []
|
|
525
546
|
|
|
526
547
|
class ExcludeLevelFilter(logging.Filter):
|
|
527
548
|
def __init__(self, level):
|
|
@@ -157,6 +157,7 @@ class OrdersTransformer(MigrationTaskBase):
|
|
|
157
157
|
super().__init__(library_config, task_config, folio_client, use_logging)
|
|
158
158
|
self.object_type_name = self.get_object_type().name
|
|
159
159
|
self.task_config = task_config
|
|
160
|
+
self.task_configuration = self.task_config
|
|
160
161
|
self.files = self.list_source_files()
|
|
161
162
|
self.total_records = 0
|
|
162
163
|
self.current_folio_record: dict = {}
|
|
@@ -175,6 +176,7 @@ class OrdersTransformer(MigrationTaskBase):
|
|
|
175
176
|
self.mapper = CompositeOrderMapper(
|
|
176
177
|
self.folio_client,
|
|
177
178
|
self.library_configuration,
|
|
179
|
+
self.task_configuration,
|
|
178
180
|
self.orders_map,
|
|
179
181
|
self.load_id_map(self.folder_structure.organizations_id_map_path, True),
|
|
180
182
|
self.load_instance_id_map(True),
|
|
@@ -119,6 +119,7 @@ class UserTransformer(MigrationTaskBase):
|
|
|
119
119
|
):
|
|
120
120
|
super().__init__(library_config, task_config, folio_client, use_logging)
|
|
121
121
|
self.task_config = task_config
|
|
122
|
+
self.task_configuration = self.task_config
|
|
122
123
|
self.total_records = 0
|
|
123
124
|
|
|
124
125
|
self.user_map = self.setup_records_map(
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"%{value} added to %{entry}": "%{value} added to %{entry}",
|
|
13
13
|
"%{value} mapped to %{mapped_value}": "%{value} mapped to %{mapped_value}",
|
|
14
14
|
"%{value} not found in map.": "%{value} not found in map.",
|
|
15
|
+
"0 is staff-only, all other values are public": "0 is staff-only, all other values are public",
|
|
15
16
|
"008 is too short": "008 is too short",
|
|
16
17
|
"008 length invalid. '%{rest}' was stripped out": "008 length invalid. '%{rest}' was stripped out",
|
|
17
18
|
"035 generation from 001 turned off": "035 generation from 001 turned off",
|
|
@@ -57,6 +58,7 @@
|
|
|
57
58
|
"Data issue. Consider fixing the record. ": "Data issue. Consider fixing the record. ",
|
|
58
59
|
"Declare item as lost": "Declare item as lost",
|
|
59
60
|
"Discarded reserves": "Discarded reserves",
|
|
61
|
+
"Due date is before out date, or date information is missing from both": "Due date is before out date, or date information is missing from both",
|
|
60
62
|
"Duplicate 001. Creating HRID instead.\n Previous 001 will be stored in a new 035 field": "Duplicate 001. Creating HRID instead.\n Previous 001 will be stored in a new 035 field",
|
|
61
63
|
"Duplicate MARC record identifiers ": "Duplicate MARC record identifiers ",
|
|
62
64
|
"Duplicate barcodes": "Duplicate barcodes",
|
|
@@ -106,6 +108,7 @@
|
|
|
106
108
|
"Mapped from Indicator 1": "Mapped from Indicator 1",
|
|
107
109
|
"Mapping failed for %{tag} \"%{subfield}\" (%{normalized_subfield})": "Mapping failed for %{tag} \"%{subfield}\" (%{normalized_subfield})",
|
|
108
110
|
"Mapping failed for %{tag} \"%{subfield}\" (Normalized: %{normalized_subfield})": "Mapping failed for %{tag} \"%{subfield}\" (Normalized: %{normalized_subfield})",
|
|
111
|
+
"Mapping not set up": "Mapping not set up",
|
|
109
112
|
"Mapping not set up for target field": "Mapping not set up for target field",
|
|
110
113
|
"Mapping not setup": "Mapping not setup",
|
|
111
114
|
"Measure": "Measure",
|
|
@@ -128,7 +131,9 @@
|
|
|
128
131
|
"Number of organizations created": "Number of organizations created",
|
|
129
132
|
"Number of records written to disk": "Number of records written to disk",
|
|
130
133
|
"Number of reoccuring identical %{type}": "Number of reoccuring identical %{type}",
|
|
134
|
+
"Number of reoccurring identical %{type}": "Number of reoccurring identical %{type}",
|
|
131
135
|
"Ogranization transformation report": "Ogranization transformation report",
|
|
136
|
+
"Organization transformation report": "Organization transformation report",
|
|
132
137
|
"Organizations linked using organizations_id_map": "Organizations linked using organizations_id_map",
|
|
133
138
|
"Organizations not in ID map, linked using FOLIO lookup": "Organizations not in ID map, linked using FOLIO lookup",
|
|
134
139
|
"Original value": "Original value",
|
|
@@ -143,8 +148,10 @@
|
|
|
143
148
|
"Previously transformed holdings record loaded": "Previously transformed holdings record loaded",
|
|
144
149
|
"Processed pre-validated loans": "Processed pre-validated loans",
|
|
145
150
|
"Processed reserves": "Processed reserves",
|
|
151
|
+
"Provided boundwith relationship file not found": "Provided boundwith relationship file not found",
|
|
146
152
|
"Pruchase Orders and Purchase Order Lines Transformation Report": "Pruchase Orders and Purchase Order Lines Transformation Report",
|
|
147
153
|
"RECORD FAILED Organization identifier not in ID map/FOLIO": "RECORD FAILED Organization identifier not in ID map/FOLIO",
|
|
154
|
+
"RECORD FAILED: PO number has invalid character(s)": "RECORD FAILED: PO number has invalid character(s)",
|
|
148
155
|
"Records failed": "Records failed",
|
|
149
156
|
"Records failed because of failed holdings": "Records failed because of failed holdings",
|
|
150
157
|
"Records failed due to an error. See data issues log for details": "Records failed due to an error. See data issues log for details",
|
|
@@ -178,9 +185,13 @@
|
|
|
178
185
|
"Set leader 10 (Indicator count) from %{field} to 2": "Set leader 10 (Indicator count) from %{field} to 2",
|
|
179
186
|
"Set leader 11 (Subfield code count) from %{record} to 2": "Set leader 11 (Subfield code count) from %{record} to 2",
|
|
180
187
|
"Set leader 20-23 from %{field} to 4500": "Set leader 20-23 from %{field} to 4500",
|
|
188
|
+
"Set up statistical code id mapping...": "Set up statistical code id mapping...",
|
|
181
189
|
"Source digits": "Source digits",
|
|
182
190
|
"Source of heading or term": "Source of heading or term",
|
|
183
191
|
"Staff suppressed": "Staff suppressed",
|
|
192
|
+
"Statistical code": "Statistical code",
|
|
193
|
+
"Statistical code '%{code}' not found in FOLIO": "Statistical code '%{code}' not found in FOLIO",
|
|
194
|
+
"Statistical codes not supported for this object type": "Statistical codes not supported for this object type",
|
|
184
195
|
"Stored courselistings": "Stored courselistings",
|
|
185
196
|
"Stored courses": "Stored courses",
|
|
186
197
|
"Stored instructors": "Stored instructors",
|
|
@@ -441,7 +452,5 @@
|
|
|
441
452
|
"legacy id from %{fro}": "legacy id from %{fro}",
|
|
442
453
|
"naturalId mapped from %{fro}": "naturalId mapped from %{fro}",
|
|
443
454
|
"no matching identifier_types in %{names}": "no matching identifier_types in %{names}",
|
|
444
|
-
"subfield present in %{linked_value_tag} but not in %{pattern_field}": "subfield present in %{linked_value_tag} but not in %{pattern_field}"
|
|
445
|
-
"Provided boundwith relationship file not found": "Provided boundwith relationship file not found",
|
|
446
|
-
"Due date is before out date, or date information is missing from both": "Due date is before out date, or date information is missing from both"
|
|
455
|
+
"subfield present in %{linked_value_tag} but not in %{pattern_field}": "subfield present in %{linked_value_tag} but not in %{pattern_field}"
|
|
447
456
|
}
|
{folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.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.0rc13
|
|
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
|
{folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.dist-info}/RECORD
RENAMED
|
@@ -10,19 +10,19 @@ folio_migration_tools/folder_structure.py,sha256=bZlmKGtxdytWcqjnM2lE4Vpx4nHyYRk
|
|
|
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=LzICsZQdOkXwIqdDfh59x0-Cx77Lb18qVnWroNqekS8,7046
|
|
14
|
+
folio_migration_tools/mapper_base.py,sha256=IYER8Dq-4qLq3qiAvUpnzc33usUbfZtNKzyZJD6DNds,23567
|
|
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=
|
|
17
|
-
folio_migration_tools/mapping_file_transformation/holdings_mapper.py,sha256=
|
|
18
|
-
folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=
|
|
19
|
-
folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py,sha256=
|
|
20
|
-
folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py,sha256=
|
|
21
|
-
folio_migration_tools/mapping_file_transformation/notes_mapper.py,sha256=
|
|
22
|
-
folio_migration_tools/mapping_file_transformation/order_mapper.py,sha256
|
|
23
|
-
folio_migration_tools/mapping_file_transformation/organization_mapper.py,sha256=
|
|
16
|
+
folio_migration_tools/mapping_file_transformation/courses_mapper.py,sha256=yX8yCCw6B54r7JUn5IPhMYKBgImiagUzfwBxNVRf5MQ,8091
|
|
17
|
+
folio_migration_tools/mapping_file_transformation/holdings_mapper.py,sha256=DY4cpSWaJWJo-8ESpO4PSf_raTIRAVSt9N0-aV1ShGc,7504
|
|
18
|
+
folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=wYEnSsV7U7YE2Df2sld_qJsbPtV9YoEV42iAbatjN8U,10402
|
|
19
|
+
folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py,sha256=2-W2Z8hwAhWT77zfDWuwWqm20j4w1mfzeAXWiyssQ8I,13434
|
|
20
|
+
folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py,sha256=EHeeC-Yr4Cy9OhoTcteJAtMiG_yJu8pq1NqikkVCmMc,37274
|
|
21
|
+
folio_migration_tools/mapping_file_transformation/notes_mapper.py,sha256=vCmZmjrjyYtXeFCyVqvWfnP8y1jGGu15RXzXIHh12xY,3530
|
|
22
|
+
folio_migration_tools/mapping_file_transformation/order_mapper.py,sha256=-JEBEeOntNPE9-NYhWAJ1hpQI03ZzMv-_mkyLzSa9x4,17750
|
|
23
|
+
folio_migration_tools/mapping_file_transformation/organization_mapper.py,sha256=u1Lb6tApn-nVLqbbJV38BuipKL3OK8Y2uQ4ogoyGQaI,14639
|
|
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=GnePkCK2k8VSd_wAUNlLwTLLB-WwpxZLBC-kDXtONBU,7867
|
|
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=Rvdub7RdtR1BWnZij_Ejgp7cG9Kz58i_tXwXJbhaMtU,12101
|
|
@@ -30,27 +30,27 @@ folio_migration_tools/marc_rules_transformation/hrid_handler.py,sha256=SgnSYeNR0
|
|
|
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=M-PHduzMYmZnrMwOSlwnWQ5bT-566gVRFSMo-JgS2d4,12346
|
|
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=PGt2w8h2pj8_8sGjQe3L-odFDlquURtKnoNFRWQB3GI,9621
|
|
34
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_base.py,sha256=6vVvrNoViZZ1g2piKtOPMlqYspej-2eei8HIwM-K_Lg,45309
|
|
35
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py,sha256=H7RrU1KfFlTj6M0l7HXD3vOtxKHY4FD5xrXmGjCjcRc,30324
|
|
36
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=dOqje_UVxTQDgi2CMNjjzZRKOHU99bR0ik6sYuAzibo,26939
|
|
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=BcbNz2z5bGcbXmNvjnLd3IVHb0RSuagiVPvm77GUzwU,36402
|
|
41
|
-
folio_migration_tools/migration_tasks/bibs_transformer.py,sha256=
|
|
41
|
+
folio_migration_tools/migration_tasks/bibs_transformer.py,sha256=46d44pcDAodFXDYbrTCMRASISbDciXmA0CXYfhP2IaE,6298
|
|
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=
|
|
43
|
+
folio_migration_tools/migration_tasks/holdings_csv_transformer.py,sha256=g3r4J1Y18vU18BjUmye7oSANR_TLTrP95la41flqj5M,22736
|
|
44
|
+
folio_migration_tools/migration_tasks/holdings_marc_transformer.py,sha256=DVYdSNUPmdTv6GfLJdyT806dZV6UQHH_T8gkqtPgXaU,14143
|
|
45
|
+
folio_migration_tools/migration_tasks/items_transformer.py,sha256=uBcVv-t_4N9j1pNyJPt-wFkKbNQLTe4_NFvOXMUcBjA,19212
|
|
46
46
|
folio_migration_tools/migration_tasks/loans_migrator.py,sha256=CPsin9XLzHwNrpKHPMHAvgRvpoH8QvAfYZYr1FSxAN4,34520
|
|
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=Q-57h6rmt74bC9LidA9ZoagEcwVd_ytq8IUWelVOm2E,22521
|
|
49
|
+
folio_migration_tools/migration_tasks/orders_transformer.py,sha256=6SnzU_rUTu2B5hQykI2nRA7vI1rg-uxuF9Ncupe0AEY,14302
|
|
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=4sSPer6_6yMwiiY1VYJmYZske_Ah1XG4KAM3NDadPhg,9952
|
|
53
|
-
folio_migration_tools/migration_tasks/user_transformer.py,sha256=
|
|
53
|
+
folio_migration_tools/migration_tasks/user_transformer.py,sha256=aylrMC9n47fdStgsNfW4ZbJh2E4FDSPypsaNv52ynKc,12330
|
|
54
54
|
folio_migration_tools/task_configuration.py,sha256=2GXVog0-_cFybqsU2WFcxnTNGDhvDzqb7gYyIimdPAk,1131
|
|
55
55
|
folio_migration_tools/test_infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
56
|
folio_migration_tools/test_infrastructure/mocked_classes.py,sha256=lpohRMqKnGmsoyspUQFXuyrGXRoIQZu2Dq7Q5WLQJw8,14877
|
|
@@ -59,9 +59,9 @@ folio_migration_tools/transaction_migration/legacy_loan.py,sha256=zablUc_xKI2ah1
|
|
|
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=qzw0okg4axAE_ezXopP9gFsQ_e60o0zh7zqRzFBSWHY,1806
|
|
61
61
|
folio_migration_tools/transaction_migration/transaction_result.py,sha256=cTdCN0BnlI9_ZJB2Z3Fdkl9gpymIi-9mGZsRFlQcmDk,656
|
|
62
|
-
folio_migration_tools/translations/en.json,sha256=
|
|
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.
|
|
62
|
+
folio_migration_tools/translations/en.json,sha256=FeoaN3INfim4_-l3DSamHo2hn1SUJr5DsgDgsV4XUek,39693
|
|
63
|
+
folio_migration_tools-1.9.0rc13.dist-info/LICENSE,sha256=PhIEkitVi3ejgq56tt6sWoJIG_zmv82cjjd_aYPPGdI,1072
|
|
64
|
+
folio_migration_tools-1.9.0rc13.dist-info/METADATA,sha256=Oo3lLbvSLtsgtpkihR2fKc_IJmXR4LXcDUSDLNGjOzU,7448
|
|
65
|
+
folio_migration_tools-1.9.0rc13.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
66
|
+
folio_migration_tools-1.9.0rc13.dist-info/entry_points.txt,sha256=Hbe-HjqMcU8FwVshVIkeWyZd9XwgT1CCMNf06EpHQu8,77
|
|
67
|
+
folio_migration_tools-1.9.0rc13.dist-info/RECORD,,
|
{folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.dist-info}/LICENSE
RENAMED
|
File without changes
|
{folio_migration_tools-1.9.0rc12.dist-info → folio_migration_tools-1.9.0rc13.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|