folio-migration-tools 1.9.2__tar.gz → 1.9.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/PKG-INFO +2 -1
  2. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/pyproject.toml +17 -9
  3. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/user_mapper.py +39 -31
  4. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/conditions.py +239 -30
  5. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +99 -65
  6. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/marc_file_processor.py +6 -1
  7. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +2 -2
  8. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +7 -1
  9. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/batch_poster.py +201 -51
  10. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/holdings_marc_transformer.py +22 -11
  11. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/items_transformer.py +25 -10
  12. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/loans_migrator.py +238 -77
  13. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/organization_transformer.py +1 -0
  14. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/task_configuration.py +3 -1
  15. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/test_infrastructure/mocked_classes.py +5 -0
  16. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/transaction_migration/legacy_loan.py +30 -10
  17. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/translations/en.json +19 -1
  18. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/LICENSE +0 -0
  19. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/README.md +0 -0
  20. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/__init__.py +0 -0
  21. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/__main__.py +0 -0
  22. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/circulation_helper.py +0 -0
  23. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/colors.py +0 -0
  24. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/config_file_load.py +0 -0
  25. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/custom_dict.py +0 -0
  26. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/custom_exceptions.py +0 -0
  27. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/extradata_writer.py +0 -0
  28. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/folder_structure.py +0 -0
  29. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/helper.py +0 -0
  30. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/holdings_helper.py +0 -0
  31. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/i18n_config.py +0 -0
  32. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/library_configuration.py +0 -0
  33. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapper_base.py +0 -0
  34. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/__init__.py +0 -0
  35. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/courses_mapper.py +0 -0
  36. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/holdings_mapper.py +0 -0
  37. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/item_mapper.py +0 -0
  38. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +0 -0
  39. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +0 -0
  40. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/notes_mapper.py +0 -0
  41. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/order_mapper.py +0 -0
  42. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/organization_mapper.py +0 -0
  43. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/mapping_file_transformation/ref_data_mapping.py +0 -0
  44. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/__init__.py +0 -0
  45. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/hrid_handler.py +0 -0
  46. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/loc_language_codes.xml +0 -0
  47. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py +0 -0
  48. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +0 -0
  49. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +0 -0
  50. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_report.py +0 -0
  51. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/__init__.py +0 -0
  52. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/authority_transformer.py +0 -0
  53. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/bibs_transformer.py +0 -0
  54. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/courses_migrator.py +0 -0
  55. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/holdings_csv_transformer.py +0 -0
  56. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +0 -0
  57. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/migration_task_base.py +0 -0
  58. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/orders_transformer.py +0 -0
  59. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/requests_migrator.py +0 -0
  60. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/reserves_migrator.py +0 -0
  61. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/migration_tasks/user_transformer.py +0 -0
  62. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/test_infrastructure/__init__.py +0 -0
  63. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/transaction_migration/__init__.py +0 -0
  64. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/transaction_migration/legacy_request.py +0 -0
  65. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/transaction_migration/legacy_reserve.py +0 -0
  66. {folio_migration_tools-1.9.2 → folio_migration_tools-1.9.4}/src/folio_migration_tools/transaction_migration/transaction_result.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: folio_migration_tools
3
- Version: 1.9.2
3
+ Version: 1.9.4
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
@@ -19,6 +19,7 @@ Requires-Dist: argparse-prompt (>=0.0.5,<0.0.6)
19
19
  Requires-Dist: art (>=6.5,<7.0)
20
20
  Requires-Dist: deepdiff (>=6.2.3,<7.0.0)
21
21
  Requires-Dist: defusedxml (>=0.7.1,<0.8.0)
22
+ Requires-Dist: folio-data-import (>=0.3.2,<0.4.0)
22
23
  Requires-Dist: folio-uuid (>=0.2.8,<0.3.0)
23
24
  Requires-Dist: folioclient (>=0.70.1,<0.71.0)
24
25
  Requires-Dist: pyaml (>=21.10.1,<22.0.0)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "folio_migration_tools"
3
- version = "1.9.2"
3
+ version = "1.9.4"
4
4
  description = "A tool allowing you to migrate data from legacy ILS:s (Library systems) into FOLIO LSP"
5
5
  authors = [
6
6
  {name = "Theodor Tolstoy", email = "github.teddes@tolstoy.se"},
@@ -56,6 +56,7 @@ deepdiff = "^6.2.3"
56
56
  pyaml = "^21.10.1"
57
57
  python-i18n = "^0.3.9"
58
58
  art = "^6.5"
59
+ folio-data-import = "^0.3.2"
59
60
 
60
61
  [tool.poetry.group.dev.dependencies]
61
62
  pytest = "^7.1.3"
@@ -63,24 +64,31 @@ lxml = ">4.9"
63
64
  coverage = {extras = ["toml"], version = "^6.5.0"}
64
65
  pytest-cov = "^4.0.0"
65
66
  black = "^22.10.0"
66
- flake8 = "^5.0.4"
67
+ flake8 = "^7.3.0"
67
68
  mypy = "^0.982"
68
- flake8-black = "^0.3.3"
69
- flake8-bugbear = "^22.9.23"
69
+ flake8-black = "^0.3.6"
70
+ flake8-bugbear = "^24.12.12"
70
71
  flake8-bandit = "^4.1.1"
71
- flake8-isort = "^5.0.0"
72
+ flake8-isort = "^6.1.2"
72
73
  flake8-docstrings = "^1.6.0"
73
74
  darglint = "^1.8.1"
74
- sphinx = "^5.3.0"
75
- sphinx-autodoc-typehints = "^1.19.4"
76
- myst-parser = "^0.18.1"
77
75
  types-requests = "^2.28.11.17"
78
76
  types-python-dateutil = "^2.8.19.11"
79
77
  ipykernel = "^6.29.5"
80
78
  pytest-asyncio = "^0.23.0"
79
+ sphinx-autobuild = "^2024.10.3"
80
+
81
+ [tool.poetry.group.docs.dependencies]
82
+ m2r = "^0.2.1"
83
+ myst-parser = "<4.0.0"
84
+ sphinx = ">=6.0.0, <8.0.0"
85
+ sphinx-autodoc-typehints = "^1.17.0"
86
+ sphinx-rtd-theme = "^1.0.0"
87
+ toml = "^0.10.2"
88
+ sphinx-book-theme = "^1.1.4"
81
89
 
82
90
  [tool.poetry.extras]
83
- docs = ["m2r", "sphinx", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "toml"]
91
+ docs = ["m2r", "sphinx", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "toml",]
84
92
 
85
93
  [tool.poetry.requires-plugins]
86
94
  poetry-plugin-export = ">=1.8"
@@ -59,8 +59,8 @@ class UserMapper(MappingFileMapperBase):
59
59
  True,
60
60
  )
61
61
  self.notes_mapper.migration_report = self.migration_report
62
- self.setup_departments_mapping(departments_mapping)
63
- self.setup_groups_mapping(groups_map)
62
+ self.departments_mapping = self.setup_departments_mapping(departments_mapping)
63
+ self.groups_mapping = self.setup_groups_mapping(groups_map)
64
64
 
65
65
  for m in self.record_map["data"]:
66
66
  if m["folio_field"].startswith("customFields"):
@@ -120,7 +120,8 @@ class UserMapper(MappingFileMapperBase):
120
120
 
121
121
  return clean_folio_object
122
122
 
123
- def get_users(self, source_file, file_format: str):
123
+ @staticmethod
124
+ def get_users(source_file, file_format: str):
124
125
  csv.register_dialect("tsv", delimiter="\t")
125
126
  if file_format == "tsv":
126
127
  reader = csv.DictReader(source_file, dialect="tsv")
@@ -156,12 +157,25 @@ class UserMapper(MappingFileMapperBase):
156
157
  "No Departments mapping set up. Set up a departments mapping file "
157
158
  " or remove the mapping of the Departments field",
158
159
  )
159
- return self.get_mapped_name(
160
- self.departments_mapping,
161
- legacy_user,
162
- index_or_id,
163
- True,
164
- )
160
+ if len(self.departments_mapping.mapped_legacy_keys) == 1 and self.library_configuration.multi_field_delimiter in legacy_user.get(self.departments_mapping.mapped_legacy_keys[0], ""):
161
+ split_departments = legacy_user.get(self.departments_mapping.mapped_legacy_keys[0], "").split(
162
+ self.library_configuration.multi_field_delimiter
163
+ )
164
+ return self.library_configuration.multi_field_delimiter.join([
165
+ self.get_mapped_name(
166
+ self.departments_mapping,
167
+ {self.departments_mapping.mapped_legacy_keys[0]: dept},
168
+ index_or_id,
169
+ True,
170
+ ) for dept in split_departments
171
+ ])
172
+ else:
173
+ return self.get_mapped_name(
174
+ self.departments_mapping,
175
+ legacy_user,
176
+ index_or_id,
177
+ True,
178
+ )
165
179
  elif folio_prop_name in ["expirationDate", "enrollmentDate", "personal.dateOfBirth"]:
166
180
  return self.get_parsed_date(mapped_value, folio_prop_name)
167
181
  return mapped_value
@@ -184,27 +198,21 @@ class UserMapper(MappingFileMapperBase):
184
198
  return ""
185
199
 
186
200
  def setup_groups_mapping(self, groups_map):
187
- if groups_map:
188
- self.groups_mapping = RefDataMapping(
189
- self.folio_client,
190
- "/groups",
191
- "usergroups",
192
- groups_map,
193
- "group",
194
- "UserGroupMapping",
195
- )
196
- else:
197
- self.groups_mapping = None
201
+ return RefDataMapping(
202
+ self.folio_client,
203
+ "/groups",
204
+ "usergroups",
205
+ groups_map,
206
+ "group",
207
+ "UserGroupMapping",
208
+ ) if groups_map else None
198
209
 
199
210
  def setup_departments_mapping(self, departments_mapping):
200
- if departments_mapping:
201
- self.departments_mapping = RefDataMapping(
202
- self.folio_client,
203
- "/departments",
204
- "departments",
205
- departments_mapping,
206
- "name",
207
- "DepartmentsMapping",
208
- )
209
- else:
210
- self.departments_mapping = None
211
+ return RefDataMapping(
212
+ self.folio_client,
213
+ "/departments",
214
+ "departments",
215
+ departments_mapping,
216
+ "name",
217
+ "DepartmentsMapping",
218
+ ) if departments_mapping else None
@@ -90,6 +90,7 @@ class Conditions:
90
90
  logging.info("%s\tholding_note_types", len(self.folio.holding_note_types)) # type: ignore
91
91
  logging.info("%s\tcall_number_types", len(self.folio.call_number_types)) # type: ignore
92
92
  self.setup_and_validate_holdings_types()
93
+ self.ill_policies = self.folio.folio_get_all("/ill-policies", "illPolicies")
93
94
  # Raise for empty settings
94
95
  if not self.folio.holding_note_types:
95
96
  raise TransformationProcessError("", "No holding_note_types in FOLIO")
@@ -466,36 +467,6 @@ class Conditions:
466
467
  def condition_char_select(self, legacy_id, value, parameter, marc_field: field.Field):
467
468
  return value[parameter["from"] : parameter["to"]]
468
469
 
469
- def condition_set_receipt_status(self, legacy_id, value, parameter, marc_field: field.Field):
470
- if len(value) < 7:
471
- self.mapper.migration_report.add(
472
- "ReceiptStatusMapping", i18n.t("008 is too short") + f": {value}"
473
- )
474
- return ""
475
- try:
476
- status_map = {
477
- "0": "Unknown",
478
- "1": "Other receipt or acquisition status",
479
- "2": "Received and complete or ceased",
480
- "3": "On order",
481
- "4": "Currently received",
482
- "5": "Not currently received",
483
- "6": "External access",
484
- }
485
- mapped_value = status_map[value[6]]
486
- self.mapper.migration_report.add(
487
- "ReceiptStatusMapping",
488
- i18n.t(
489
- "%{value} mapped to %{mapped_value}", value=value[6], mapped_value=mapped_value
490
- ),
491
- )
492
-
493
- return
494
- except Exception:
495
- self.mapper.migration_report.add(
496
- "ReceiptStatusMapping", i18n.t("%{value} not found in map.", value=value)
497
- )
498
- return "Unknown"
499
470
 
500
471
  def condition_set_identifier_type_id_by_name(
501
472
  self, legacy_id, value, parameter, marc_field: field.Field
@@ -915,3 +886,241 @@ class Conditions:
915
886
  legacy_id,
916
887
  f"Subject source not found for {value} {marc_field}",
917
888
  )
889
+
890
+ def condition_set_receipt_status(
891
+ self, legacy_id, value, parameter, marc_field: field.Field
892
+ ):
893
+ """
894
+ This method maps the receipt status based on the 008 field.
895
+ This condition is not available in FOLIO's MARC mapping engine and
896
+ will require use of a supplemental mapping rules file in the
897
+ HoldingsMarcTransformer task definition.
898
+ """
899
+ if len(value) < 7:
900
+ self.mapper.migration_report.add(
901
+ "ReceiptStatusMapping", i18n.t("008 is too short") + f": {value}"
902
+ )
903
+ return ""
904
+
905
+ status_map = {
906
+ "0": "Unknown",
907
+ "1": "Other receipt or acquisition status",
908
+ "2": "Received and complete or ceased",
909
+ "3": "On order",
910
+ "4": "Currently received",
911
+ "5": "Not currently received",
912
+ "6": "External access",
913
+ }
914
+
915
+ try:
916
+ mapped_value = status_map[value[6]]
917
+ self.mapper.migration_report.add(
918
+ "ReceiptStatusMapping",
919
+ i18n.t(
920
+ "%{value} mapped to %{mapped_value}",
921
+ value=value[6],
922
+ mapped_value=mapped_value,
923
+ ),
924
+ )
925
+ return mapped_value
926
+ except Exception:
927
+ self.mapper.migration_report.add(
928
+ "ReceiptStatusMapping", i18n.t("%{value} not found in map.", value=value[6])
929
+ )
930
+ return ""
931
+
932
+ def condition_set_acquisition_method(
933
+ self, legacy_id, value, parameter, marc_field: field.Field
934
+ ):
935
+ """
936
+ This method maps the acquisition method based on the 008 field.
937
+ This condition is not available in FOLIO's MARC mapping engine and
938
+ will require use of a supplemental mapping rules file in the
939
+ HoldingsMarcTransformer task definition.
940
+ """
941
+ if len(value) < 8:
942
+ self.mapper.migration_report.add(
943
+ "ReceiptStatusMapping", i18n.t("008 is too short") + f": {value}"
944
+ )
945
+ return ""
946
+
947
+ try:
948
+ acq_methods = {
949
+ "c": "Cooperative or consortial purchase",
950
+ "d": "Deposit",
951
+ "e": "Exchange",
952
+ "f": "Free",
953
+ "g": "Gift",
954
+ "l": "Legal deposit",
955
+ "m": "Membership",
956
+ "n": "Non-library purchase",
957
+ "p": "Purchase",
958
+ "q": "Lease",
959
+ "u": "Unknown",
960
+ "z": "Other method of acquisition",
961
+ }
962
+ mapped_value = acq_methods[value[7]]
963
+ self.mapper.migration_report.add(
964
+ "MethodOfAcquisitionMapping",
965
+ i18n.t(
966
+ "%{value} mapped to %{mapped_value}", value=value[7], mapped_value=mapped_value
967
+ ),
968
+ )
969
+ return mapped_value
970
+ except Exception:
971
+ self.mapper.migration_report.add(
972
+ "MethodOfAcquisitionMapping", i18n.t("%{value} not found in map.", value=value[8])
973
+ )
974
+ return ""
975
+
976
+ def condition_set_retention_policy(
977
+ self, legacy_id, value, parameter, marc_field: field.Field
978
+ ):
979
+ """
980
+ This method maps the retention policy based on the 008 field.
981
+ This condition is not available in FOLIO's MARC mapping engine and
982
+ will require use of a supplemental mapping rules file in the
983
+ HoldingsMarcTransformer task definition.
984
+ """
985
+ if len(value) < 13:
986
+ self.mapper.migration_report.add(
987
+ "RetentionPolicyMapping", i18n.t("008 is too short") + f": {value}"
988
+ )
989
+ return ""
990
+ value = value.replace("|", " ").replace("#", " ") # Replace pipe with space for mapping consistency
991
+ try:
992
+ retention_policies = {
993
+ "0": "Unknown",
994
+ "1": "Other general retention policy",
995
+ "2": "Retained except as replaced by updates",
996
+ "3": "Sample issue retained",
997
+ "4": "Retained until replaced by microform",
998
+ "5": "Retained until replaced by cumulation, replacement volume, or revision",
999
+ "6": "Retained for a limited period",
1000
+ "7": "Not retained",
1001
+ "8": "Permanently retained",
1002
+ }
1003
+ mapped_value = retention_policies[value[12]]
1004
+ self.mapper.migration_report.add(
1005
+ "RetentionPolicyMapping",
1006
+ i18n.t(
1007
+ "%{value} mapped to %{mapped_value}",
1008
+ value=value[12],
1009
+ mapped_value=mapped_value,
1010
+ ),
1011
+ )
1012
+ if value[12] == "6":
1013
+ policy_types = {
1014
+ "l": "Latest",
1015
+ "p": "Previous",
1016
+ }
1017
+ unit_types = {
1018
+ "m": "Day",
1019
+ "w": "Month",
1020
+ "y": "Year",
1021
+ "e": "Edition",
1022
+ "i": "Issue",
1023
+ "s": "Supplement"
1024
+ }
1025
+ try:
1026
+ specific_retention_policy = ""
1027
+ if value[13].strip() or value[15].strip():
1028
+ if value[14].strip() and int(value[14]) > 1:
1029
+ specific_retention_policy = f"{policy_types.get(value[13], '')} {value[14]} {unit_types.get(value[15], '')}s retained".strip()
1030
+ else:
1031
+ specific_retention_policy = f"{policy_types.get(value[13], '')} {unit_types.get(value[15], '')} retained".strip()
1032
+ if specific_retention_policy:
1033
+ self.mapper.migration_report.add(
1034
+ "RetentionPolicyMapping",
1035
+ i18n.t(
1036
+ "Retention policy 6 indicates a limited period. Specific retention period will be mapped from 008/13-15",
1037
+ )
1038
+ )
1039
+ return specific_retention_policy
1040
+ else:
1041
+ raise ValueError(
1042
+ "Specific retention policy is empty or invalid in 008/13-15"
1043
+ )
1044
+ except ValueError:
1045
+ self.mapper.migration_report.add(
1046
+ "RetentionPolicyMapping",
1047
+ i18n.t("Invalid specific retention policy in 008/13-15: %{value}", value=value[13:16]),
1048
+ )
1049
+ return mapped_value
1050
+ except Exception:
1051
+ self.mapper.migration_report.add(
1052
+ "RetentionPolicyMapping", i18n.t("%{value} not found in map.", value=value[12])
1053
+ )
1054
+ return ""
1055
+
1056
+ def condition_set_ill_policy(
1057
+ self, legacy_id, value, parameter, marc_field: field.Field
1058
+ ):
1059
+ """
1060
+ This method maps the ILL policy based on the 008 field.
1061
+ This condition is not available in FOLIO's MARC mapping engine and
1062
+ will require use of a supplemental mapping rules file in the
1063
+ HoldingsMarcTransformer task definition."""
1064
+ if len(value) < 21:
1065
+ self.mapper.migration_report.add(
1066
+ "ILLPolicyMapping", i18n.t("008 is too short") + f": {value}"
1067
+ )
1068
+ return ""
1069
+ try:
1070
+ ill_policies = {
1071
+ "a": "Will lend",
1072
+ "b": "Will not lend",
1073
+ "c": "Will lend hard copy only",
1074
+ "l": "Limited lending policy",
1075
+ "u": "Unknown",
1076
+ }
1077
+ mapped_value = ill_policies[value[20]]
1078
+ self.mapper.migration_report.add(
1079
+ "ILLPolicyMapping",
1080
+ i18n.t("%{value} mapped to %{mapped_value}", value=value[20], mapped_value=mapped_value),
1081
+ )
1082
+ ill_policy_id = self.get_ref_data_tuple_by_name(
1083
+ self.ill_policies, "ill_policies", mapped_value
1084
+ )
1085
+ return ill_policy_id[0] if ill_policy_id else ""
1086
+ except Exception:
1087
+ self.mapper.migration_report.add(
1088
+ "ILLPolicyMapping", i18n.t("%{value} not found in map.", value=value[20])
1089
+ )
1090
+ return ""
1091
+
1092
+ def condition_set_digitization_policy(
1093
+ self, legacy_id, value, parameter, marc_field: field.Field
1094
+ ):
1095
+ """
1096
+ This method maps the digitization policy based on the 008 field.
1097
+ This condition is not available in FOLIO's MARC mapping engine and
1098
+ will require use of a supplemental mapping rules file in the
1099
+ HoldingsMarcTransformer task definition.
1100
+ """
1101
+ if len(value) < 22:
1102
+ self.mapper.migration_report.add(
1103
+ "DigitizationPolicyMapping", i18n.t("008 is too short") + f": {value}"
1104
+ )
1105
+ return ""
1106
+ try:
1107
+ digitization_policies = {
1108
+ "a": "Will reproduce",
1109
+ "b": "Will not reproduce",
1110
+ "u": "Unknown",
1111
+ }
1112
+ mapped_value = digitization_policies[value[21]]
1113
+ self.mapper.migration_report.add(
1114
+ "DigitizationPolicyMapping",
1115
+ i18n.t(
1116
+ "%{value} mapped to %{mapped_value}",
1117
+ value=value[21],
1118
+ mapped_value=mapped_value,
1119
+ ),
1120
+ )
1121
+ return mapped_value
1122
+ except Exception:
1123
+ self.mapper.migration_report.add(
1124
+ "DigitizationPolicyMapping", i18n.t("%{value} not found in map.", value=value[21])
1125
+ )
1126
+ return ""