folio-migration-tools 1.9.10__py3-none-any.whl → 1.10.0__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 +3 -4
- folio_migration_tools/__main__.py +53 -31
- folio_migration_tools/circulation_helper.py +118 -108
- folio_migration_tools/custom_dict.py +2 -2
- folio_migration_tools/custom_exceptions.py +4 -5
- folio_migration_tools/folder_structure.py +17 -7
- folio_migration_tools/helper.py +8 -7
- folio_migration_tools/holdings_helper.py +4 -3
- folio_migration_tools/i18n_cache.py +79 -0
- folio_migration_tools/library_configuration.py +77 -37
- folio_migration_tools/mapper_base.py +45 -31
- folio_migration_tools/mapping_file_transformation/courses_mapper.py +1 -1
- folio_migration_tools/mapping_file_transformation/holdings_mapper.py +7 -3
- folio_migration_tools/mapping_file_transformation/item_mapper.py +13 -26
- folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +1 -2
- folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +13 -11
- folio_migration_tools/mapping_file_transformation/order_mapper.py +6 -5
- folio_migration_tools/mapping_file_transformation/organization_mapper.py +3 -3
- folio_migration_tools/mapping_file_transformation/user_mapper.py +47 -28
- folio_migration_tools/marc_rules_transformation/conditions.py +82 -97
- folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +13 -5
- folio_migration_tools/marc_rules_transformation/hrid_handler.py +3 -2
- folio_migration_tools/marc_rules_transformation/marc_file_processor.py +26 -24
- folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +56 -51
- folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +28 -17
- folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +68 -37
- folio_migration_tools/migration_report.py +18 -7
- folio_migration_tools/migration_tasks/batch_poster.py +285 -354
- folio_migration_tools/migration_tasks/bibs_transformer.py +14 -9
- folio_migration_tools/migration_tasks/courses_migrator.py +2 -3
- folio_migration_tools/migration_tasks/holdings_csv_transformer.py +23 -24
- folio_migration_tools/migration_tasks/holdings_marc_transformer.py +14 -24
- folio_migration_tools/migration_tasks/items_transformer.py +23 -34
- folio_migration_tools/migration_tasks/loans_migrator.py +67 -144
- folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +3 -3
- folio_migration_tools/migration_tasks/migration_task_base.py +47 -60
- folio_migration_tools/migration_tasks/orders_transformer.py +25 -42
- folio_migration_tools/migration_tasks/organization_transformer.py +9 -18
- folio_migration_tools/migration_tasks/requests_migrator.py +21 -24
- folio_migration_tools/migration_tasks/reserves_migrator.py +6 -5
- folio_migration_tools/migration_tasks/user_transformer.py +25 -20
- folio_migration_tools/task_configuration.py +6 -7
- folio_migration_tools/transaction_migration/legacy_loan.py +15 -27
- folio_migration_tools/transaction_migration/legacy_request.py +1 -1
- folio_migration_tools/translations/en.json +0 -7
- {folio_migration_tools-1.9.10.dist-info → folio_migration_tools-1.10.0.dist-info}/METADATA +19 -28
- folio_migration_tools-1.10.0.dist-info/RECORD +63 -0
- folio_migration_tools-1.10.0.dist-info/WHEEL +4 -0
- folio_migration_tools-1.10.0.dist-info/entry_points.txt +3 -0
- folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +0 -241
- folio_migration_tools/migration_tasks/authority_transformer.py +0 -119
- folio_migration_tools/test_infrastructure/__init__.py +0 -0
- folio_migration_tools/test_infrastructure/mocked_classes.py +0 -406
- folio_migration_tools-1.9.10.dist-info/RECORD +0 -67
- folio_migration_tools-1.9.10.dist-info/WHEEL +0 -4
- folio_migration_tools-1.9.10.dist-info/entry_points.txt +0 -3
- folio_migration_tools-1.9.10.dist-info/licenses/LICENSE +0 -21
|
@@ -19,6 +19,7 @@ from art import tprint
|
|
|
19
19
|
from folio_migration_tools.circulation_helper import CirculationHelper
|
|
20
20
|
from folio_migration_tools.custom_exceptions import TransformationRecordFailedError
|
|
21
21
|
from folio_migration_tools.helper import Helper
|
|
22
|
+
from folio_migration_tools.i18n_cache import i18n_t
|
|
22
23
|
from folio_migration_tools.library_configuration import (
|
|
23
24
|
FileDefinition,
|
|
24
25
|
LibraryConfiguration,
|
|
@@ -76,18 +77,14 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
76
77
|
Optional[list[FileDefinition]],
|
|
77
78
|
Field(
|
|
78
79
|
title="Item files",
|
|
79
|
-
description=(
|
|
80
|
-
"List of files containing item data. By default is empty list."
|
|
81
|
-
),
|
|
80
|
+
description=("List of files containing item data. By default is empty list."),
|
|
82
81
|
),
|
|
83
82
|
] = []
|
|
84
83
|
patron_files: Annotated[
|
|
85
84
|
Optional[list[FileDefinition]],
|
|
86
85
|
Field(
|
|
87
86
|
title="Patron files",
|
|
88
|
-
description=(
|
|
89
|
-
"List of files containing patron data. By default is empty list."
|
|
90
|
-
),
|
|
87
|
+
description=("List of files containing patron data. By default is empty list."),
|
|
91
88
|
),
|
|
92
89
|
] = []
|
|
93
90
|
|
|
@@ -124,9 +121,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
124
121
|
my_path = "/configurations/entries?query=(module==ORG%20and%20configName==localeSettings)"
|
|
125
122
|
try:
|
|
126
123
|
self.tenant_timezone_str = json.loads(
|
|
127
|
-
self.folio_client.folio_get_single_object(my_path)["configs"][0][
|
|
128
|
-
"value"
|
|
129
|
-
]
|
|
124
|
+
self.folio_client.folio_get_single_object(my_path)["configs"][0]["value"]
|
|
130
125
|
)["timezone"]
|
|
131
126
|
logging.info("Tenant timezone is: %s", self.tenant_timezone_str)
|
|
132
127
|
except Exception:
|
|
@@ -135,14 +130,10 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
135
130
|
self.tenant_timezone = ZoneInfo(self.tenant_timezone_str)
|
|
136
131
|
self.semi_valid_legacy_loans = []
|
|
137
132
|
for file_def in task_configuration.open_loans_files:
|
|
138
|
-
loans_file_path =
|
|
139
|
-
self.folder_structure.legacy_records_folder / file_def.file_name
|
|
140
|
-
)
|
|
133
|
+
loans_file_path = self.folder_structure.legacy_records_folder / file_def.file_name
|
|
141
134
|
with open(loans_file_path, "r", encoding="utf-8") as loans_file:
|
|
142
|
-
total_rows, empty_rows, reader = (
|
|
143
|
-
|
|
144
|
-
loans_file, loans_file_path
|
|
145
|
-
)
|
|
135
|
+
total_rows, empty_rows, reader = MappingFileMapperBase._get_delimited_file_reader(
|
|
136
|
+
loans_file, loans_file_path
|
|
146
137
|
)
|
|
147
138
|
logging.info("Source data file contains %d rows", total_rows)
|
|
148
139
|
logging.info("Source data file contains %d empty rows", empty_rows)
|
|
@@ -159,8 +150,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
159
150
|
self.semi_valid_legacy_loans.extend(
|
|
160
151
|
self.load_and_validate_legacy_loans(
|
|
161
152
|
reader,
|
|
162
|
-
file_def.service_point_id
|
|
163
|
-
or task_configuration.fallback_service_point_id,
|
|
153
|
+
file_def.service_point_id or task_configuration.fallback_service_point_id,
|
|
164
154
|
)
|
|
165
155
|
)
|
|
166
156
|
|
|
@@ -169,12 +159,8 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
169
159
|
len(self.semi_valid_legacy_loans),
|
|
170
160
|
file_def.file_name,
|
|
171
161
|
)
|
|
172
|
-
logging.info(
|
|
173
|
-
|
|
174
|
-
)
|
|
175
|
-
if any(self.task_configuration.item_files) or any(
|
|
176
|
-
self.task_configuration.patron_files
|
|
177
|
-
):
|
|
162
|
+
logging.info("Loaded and validated %s loans in total", len(self.semi_valid_legacy_loans))
|
|
163
|
+
if any(self.task_configuration.item_files) or any(self.task_configuration.patron_files):
|
|
178
164
|
self.valid_legacy_loans = list(self.check_barcodes())
|
|
179
165
|
logging.info(
|
|
180
166
|
"Loaded and validated %s loans against barcodes",
|
|
@@ -182,8 +168,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
182
168
|
)
|
|
183
169
|
else:
|
|
184
170
|
logging.info(
|
|
185
|
-
"No item or user files supplied. Not validating
|
|
186
|
-
"previously migrated objects"
|
|
171
|
+
"No item or user files supplied. Not validating againstpreviously migrated objects"
|
|
187
172
|
)
|
|
188
173
|
self.valid_legacy_loans = self.semi_valid_legacy_loans
|
|
189
174
|
logging.info("Starting row number is %s", task_configuration.starting_row)
|
|
@@ -191,9 +176,9 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
191
176
|
|
|
192
177
|
def check_smtp_config(self):
|
|
193
178
|
try:
|
|
194
|
-
smtp_config = self.folio_client.folio_get_single_object(
|
|
195
|
-
"
|
|
196
|
-
|
|
179
|
+
smtp_config = self.folio_client.folio_get_single_object("/smtp-configuration")[
|
|
180
|
+
"smtpConfigurations"
|
|
181
|
+
][0]
|
|
197
182
|
smtp_config_disabled = "disabled" in smtp_config["host"].lower()
|
|
198
183
|
except IndexError:
|
|
199
184
|
smtp_config_disabled = True
|
|
@@ -201,9 +186,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
201
186
|
if not smtp_config_disabled:
|
|
202
187
|
logging.warn("SMTP connection not disabled...")
|
|
203
188
|
for i in range(10, 0, -1):
|
|
204
|
-
sys.stdout.write(
|
|
205
|
-
"Pausing for {:02d} seconds. Press Ctrl+C to exit...\r".format(i)
|
|
206
|
-
)
|
|
189
|
+
sys.stdout.write("Pausing for {:02d} seconds. Press Ctrl+C to exit...\r".format(i))
|
|
207
190
|
time.sleep(1)
|
|
208
191
|
else:
|
|
209
192
|
logging.info("SMTP connection is disabled...")
|
|
@@ -223,13 +206,14 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
223
206
|
):
|
|
224
207
|
t0_migration = time.time()
|
|
225
208
|
self.migration_report.add_general_statistics(
|
|
226
|
-
|
|
209
|
+
i18n_t("Processed pre-validated loans")
|
|
227
210
|
)
|
|
228
211
|
try:
|
|
229
212
|
self.checkout_single_loan(legacy_loan)
|
|
230
213
|
except TransformationRecordFailedError as ee:
|
|
231
214
|
logging.error(
|
|
232
|
-
f"Transformation failed in row {num_loans}
|
|
215
|
+
f"Transformation failed in row {num_loans} "
|
|
216
|
+
f"Item barcode: {legacy_loan.item_barcode} "
|
|
233
217
|
f"Patron barcode: {legacy_loan.patron_barcode}"
|
|
234
218
|
)
|
|
235
219
|
ee.log_it()
|
|
@@ -239,9 +223,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
239
223
|
f"Patron barcode: {legacy_loan.patron_barcode} {ee}"
|
|
240
224
|
)
|
|
241
225
|
if num_loans % 25 == 0:
|
|
242
|
-
logging.info(
|
|
243
|
-
f"{timings(self.t0, t0_migration, num_loans)} {num_loans}"
|
|
244
|
-
)
|
|
226
|
+
logging.info(f"{timings(self.t0, t0_migration, num_loans)} {num_loans}")
|
|
245
227
|
|
|
246
228
|
def checkout_single_loan(self, legacy_loan: LegacyLoan):
|
|
247
229
|
"""Checks a legacy loan out. Retries once if it fails.
|
|
@@ -252,21 +234,15 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
252
234
|
res_checkout = self.circulation_helper.check_out_by_barcode(legacy_loan)
|
|
253
235
|
|
|
254
236
|
if res_checkout.was_successful:
|
|
255
|
-
self.migration_report.add("Details",
|
|
256
|
-
self.migration_report.add_general_statistics(
|
|
257
|
-
i18n.t("Successfully checked out")
|
|
258
|
-
)
|
|
237
|
+
self.migration_report.add("Details", i18n_t("Checked out on first try"))
|
|
238
|
+
self.migration_report.add_general_statistics(i18n_t("Successfully checked out"))
|
|
259
239
|
self.set_renewal_count(legacy_loan, res_checkout)
|
|
260
240
|
self.set_new_status(legacy_loan, res_checkout)
|
|
261
241
|
elif res_checkout.should_be_retried:
|
|
262
242
|
res_checkout2 = self.handle_checkout_failure(legacy_loan, res_checkout)
|
|
263
243
|
if res_checkout2.was_successful and res_checkout2.folio_loan:
|
|
264
|
-
self.migration_report.add(
|
|
265
|
-
|
|
266
|
-
)
|
|
267
|
-
self.migration_report.add_general_statistics(
|
|
268
|
-
i18n.t("Successfully checked out")
|
|
269
|
-
)
|
|
244
|
+
self.migration_report.add("Details", i18n_t("Checked out on second try"))
|
|
245
|
+
self.migration_report.add_general_statistics(i18n_t("Successfully checked out"))
|
|
270
246
|
logging.info("Checked out on second try")
|
|
271
247
|
self.set_renewal_count(legacy_loan, res_checkout2)
|
|
272
248
|
self.set_new_status(legacy_loan, res_checkout2)
|
|
@@ -274,42 +250,36 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
274
250
|
if res_checkout2.error_message == "Aged to lost and checked out":
|
|
275
251
|
self.migration_report.add(
|
|
276
252
|
"Details",
|
|
277
|
-
i18n.t("Second failure")
|
|
278
|
-
+ f": {res_checkout2.migration_report_message}",
|
|
253
|
+
i18n.t("Second failure") + f": {res_checkout2.migration_report_message}",
|
|
279
254
|
)
|
|
280
255
|
logging.error(
|
|
281
256
|
f"{res_checkout2.error_message}. Item barcode: {legacy_loan.item_barcode}"
|
|
282
257
|
)
|
|
283
258
|
else:
|
|
284
259
|
self.failed[legacy_loan.item_barcode] = legacy_loan
|
|
285
|
-
self.migration_report.add_general_statistics(
|
|
286
|
-
logging.error(
|
|
287
|
-
"Failed on second try: %s", res_checkout2.error_message
|
|
288
|
-
)
|
|
260
|
+
self.migration_report.add_general_statistics(i18n_t("Failed loans"))
|
|
261
|
+
logging.error("Failed on second try: %s", res_checkout2.error_message)
|
|
289
262
|
self.migration_report.add(
|
|
290
263
|
"Details",
|
|
291
|
-
i18n.t("Second failure")
|
|
292
|
-
+ f": {res_checkout2.migration_report_message}",
|
|
264
|
+
i18n.t("Second failure") + f": {res_checkout2.migration_report_message}",
|
|
293
265
|
)
|
|
294
266
|
raise TransformationRecordFailedError(
|
|
295
267
|
f"Row {legacy_loan.row}",
|
|
296
|
-
|
|
268
|
+
i18n_t("Loans failing during checkout, second try"),
|
|
297
269
|
json.dumps(legacy_loan.to_dict()),
|
|
298
270
|
)
|
|
299
271
|
elif not res_checkout.should_be_retried:
|
|
300
|
-
logging.error(
|
|
301
|
-
|
|
302
|
-
)
|
|
303
|
-
self.migration_report.add_general_statistics(i18n.t("Failed loans"))
|
|
272
|
+
logging.error("Failed first time. No retries: %s", res_checkout.error_message)
|
|
273
|
+
self.migration_report.add_general_statistics(i18n_t("Failed loans"))
|
|
304
274
|
self.migration_report.add(
|
|
305
275
|
"Details",
|
|
306
|
-
|
|
276
|
+
i18n_t("Failed 1st time. No retries")
|
|
307
277
|
+ f": {res_checkout.migration_report_message}",
|
|
308
278
|
)
|
|
309
279
|
self.failed[legacy_loan.item_barcode] = legacy_loan
|
|
310
280
|
raise TransformationRecordFailedError(
|
|
311
281
|
f"Row {legacy_loan.row}",
|
|
312
|
-
|
|
282
|
+
i18n_t("Loans failing during checkout"),
|
|
313
283
|
json.dumps(legacy_loan.to_dict()),
|
|
314
284
|
)
|
|
315
285
|
|
|
@@ -328,14 +298,10 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
328
298
|
elif legacy_loan.next_item_status not in ["Available", "", "Checked out"]:
|
|
329
299
|
self.set_item_status(legacy_loan)
|
|
330
300
|
|
|
331
|
-
def set_renewal_count(
|
|
332
|
-
self, legacy_loan: LegacyLoan, res_checkout: TransactionResult
|
|
333
|
-
):
|
|
301
|
+
def set_renewal_count(self, legacy_loan: LegacyLoan, res_checkout: TransactionResult):
|
|
334
302
|
if legacy_loan.renewal_count > 0:
|
|
335
303
|
self.update_open_loan(res_checkout.folio_loan, legacy_loan)
|
|
336
|
-
self.migration_report.add_general_statistics(
|
|
337
|
-
i18n.t("Updated renewal count for loan")
|
|
338
|
-
)
|
|
304
|
+
self.migration_report.add_general_statistics(i18n_t("Updated renewal count for loan"))
|
|
339
305
|
|
|
340
306
|
def wrap_up(self):
|
|
341
307
|
for k, v in self.failed.items():
|
|
@@ -346,7 +312,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
346
312
|
|
|
347
313
|
with open(self.folder_structure.migration_reports_file, "w+") as report_file:
|
|
348
314
|
self.migration_report.write_migration_report(
|
|
349
|
-
|
|
315
|
+
i18n_t("Loans migration report"), report_file, self.start_datetime
|
|
350
316
|
)
|
|
351
317
|
self.clean_out_empty_logs()
|
|
352
318
|
|
|
@@ -362,9 +328,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
362
328
|
"service_point_id",
|
|
363
329
|
]
|
|
364
330
|
with open(self.folder_structure.failed_recs_path, "w+") as failed_loans_file:
|
|
365
|
-
writer = csv.DictWriter(
|
|
366
|
-
failed_loans_file, fieldnames=csv_columns, dialect="tsv"
|
|
367
|
-
)
|
|
331
|
+
writer = csv.DictWriter(failed_loans_file, fieldnames=csv_columns, dialect="tsv")
|
|
368
332
|
writer.writeheader()
|
|
369
333
|
for _k, failed_loan in self.failed_and_not_dupe.items():
|
|
370
334
|
writer.writerow(failed_loan[0])
|
|
@@ -379,20 +343,16 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
379
343
|
user_barcodes, self.task_configuration.patron_files, self.folder_structure
|
|
380
344
|
)
|
|
381
345
|
for loan in self.semi_valid_legacy_loans:
|
|
382
|
-
has_item_barcode = loan.item_barcode in item_barcodes or not any(
|
|
383
|
-
|
|
384
|
-
)
|
|
385
|
-
has_patron_barcode = loan.patron_barcode in user_barcodes or not any(
|
|
386
|
-
user_barcodes
|
|
387
|
-
)
|
|
346
|
+
has_item_barcode = loan.item_barcode in item_barcodes or not any(item_barcodes)
|
|
347
|
+
has_patron_barcode = loan.patron_barcode in user_barcodes or not any(user_barcodes)
|
|
388
348
|
has_proxy_barcode = True
|
|
389
349
|
if loan.proxy_patron_barcode:
|
|
390
|
-
has_proxy_barcode = (
|
|
391
|
-
|
|
350
|
+
has_proxy_barcode = loan.proxy_patron_barcode in user_barcodes or not any(
|
|
351
|
+
user_barcodes
|
|
392
352
|
)
|
|
393
353
|
if has_item_barcode and has_patron_barcode and has_proxy_barcode:
|
|
394
354
|
self.migration_report.add_general_statistics(
|
|
395
|
-
|
|
355
|
+
i18n_t("Loans verified against migrated user and item")
|
|
396
356
|
)
|
|
397
357
|
yield loan
|
|
398
358
|
else:
|
|
@@ -401,9 +361,9 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
401
361
|
self.migration_report.add_general_statistics(i18n.t("Failed loans"))
|
|
402
362
|
self.migration_report.add(
|
|
403
363
|
"DiscardedLoans",
|
|
404
|
-
|
|
364
|
+
i18n_t("Loans discarded. Had migrated item barcode")
|
|
405
365
|
+ f": {has_item_barcode}. "
|
|
406
|
-
+
|
|
366
|
+
+ i18n_t("Had migrated user barcode")
|
|
407
367
|
+ f": {has_patron_barcode}"
|
|
408
368
|
+ f": {has_proxy_barcode}",
|
|
409
369
|
)
|
|
@@ -424,9 +384,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
424
384
|
json.dumps(loan.to_dict()),
|
|
425
385
|
)
|
|
426
386
|
|
|
427
|
-
def load_and_validate_legacy_loans(
|
|
428
|
-
self, loans_reader, service_point_id: str
|
|
429
|
-
) -> list:
|
|
387
|
+
def load_and_validate_legacy_loans(self, loans_reader, service_point_id: str) -> list:
|
|
430
388
|
results = []
|
|
431
389
|
num_bad = 0
|
|
432
390
|
logging.info("Validating legacy loans in file...")
|
|
@@ -442,33 +400,27 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
442
400
|
if any(legacy_loan.errors):
|
|
443
401
|
num_bad += 1
|
|
444
402
|
self.migration_report.add_general_statistics(
|
|
445
|
-
|
|
403
|
+
i18n_t("Loans failed pre-validation")
|
|
446
404
|
)
|
|
447
|
-
self.migration_report.add_general_statistics(
|
|
405
|
+
self.migration_report.add_general_statistics(i18n_t("Failed loans"))
|
|
448
406
|
for error in legacy_loan.errors:
|
|
449
|
-
self.migration_report.add(
|
|
450
|
-
"DiscardedLoans", f"{error[0]} - {error[1]}"
|
|
451
|
-
)
|
|
407
|
+
self.migration_report.add("DiscardedLoans", f"{error[0]} - {error[1]}")
|
|
452
408
|
# Add this loan to failed loans for later correction and re-run.
|
|
453
|
-
self.failed[
|
|
454
|
-
legacy_loan
|
|
455
|
-
|
|
409
|
+
self.failed[legacy_loan.item_barcode or f"no_barcode_{legacy_loan_count}"] = (
|
|
410
|
+
legacy_loan
|
|
411
|
+
)
|
|
456
412
|
else:
|
|
457
413
|
results.append(legacy_loan)
|
|
458
414
|
except TransformationRecordFailedError as trfe:
|
|
459
415
|
num_bad += 1
|
|
460
|
-
self.migration_report.add_general_statistics(
|
|
461
|
-
i18n.t("Loans failed pre-validation")
|
|
462
|
-
)
|
|
416
|
+
self.migration_report.add_general_statistics(i18n_t("Loans failed pre-validation"))
|
|
463
417
|
self.migration_report.add(
|
|
464
418
|
"DiscardedLoans",
|
|
465
419
|
f"{trfe.message} - see data issues log",
|
|
466
420
|
)
|
|
467
421
|
trfe.log_it()
|
|
468
422
|
self.failed[
|
|
469
|
-
legacy_loan_dict.get(
|
|
470
|
-
"item_barcode", f"no_barcode_{legacy_loan_count}"
|
|
471
|
-
)
|
|
423
|
+
legacy_loan_dict.get("item_barcode", f"no_barcode_{legacy_loan_count}")
|
|
472
424
|
] = legacy_loan_dict
|
|
473
425
|
except ValueError as ve:
|
|
474
426
|
logging.exception(ve)
|
|
@@ -516,9 +468,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
516
468
|
return self.handle_lost_item(legacy_loan, "Aged to lost")
|
|
517
469
|
elif folio_checkout.error_message == "Declared lost":
|
|
518
470
|
return self.handle_lost_item(legacy_loan, "Declared lost")
|
|
519
|
-
elif folio_checkout.error_message.startswith(
|
|
520
|
-
"Cannot check out to inactive user"
|
|
521
|
-
):
|
|
471
|
+
elif folio_checkout.error_message.startswith("Cannot check out to inactive user"):
|
|
522
472
|
return self.checkout_to_inactive_user(legacy_loan)
|
|
523
473
|
elif (
|
|
524
474
|
"has the item status Claimed returned and cannot be checked out"
|
|
@@ -550,9 +500,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
550
500
|
f"Duplicate loans (or failed twice) Item barcode: "
|
|
551
501
|
f"{legacy_loan.item_barcode} Patron barcode: {legacy_loan.patron_barcode}"
|
|
552
502
|
)
|
|
553
|
-
self.migration_report.add(
|
|
554
|
-
"Details", i18n.t("Duplicate loans (or failed twice)")
|
|
555
|
-
)
|
|
503
|
+
self.migration_report.add("Details", i18n.t("Duplicate loans (or failed twice)"))
|
|
556
504
|
del self.failed[legacy_loan.item_barcode]
|
|
557
505
|
return TransactionResult(False, False, "", "", "")
|
|
558
506
|
|
|
@@ -563,9 +511,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
563
511
|
user["expirationDate"] = datetime.isoformat(datetime.now() + timedelta(days=1))
|
|
564
512
|
self.activate_user(user)
|
|
565
513
|
logging.debug("Successfully Activated user")
|
|
566
|
-
res = self.circulation_helper.check_out_by_barcode(
|
|
567
|
-
legacy_loan
|
|
568
|
-
) # checkout_and_update
|
|
514
|
+
res = self.circulation_helper.check_out_by_barcode(legacy_loan) # checkout_and_update
|
|
569
515
|
if res.should_be_retried:
|
|
570
516
|
res = self.handle_checkout_failure(legacy_loan, res)
|
|
571
517
|
self.migration_report.add("Details", res.migration_report_message)
|
|
@@ -670,9 +616,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
670
616
|
loan_to_put["dueDate"] = due_date.isoformat()
|
|
671
617
|
loan_to_put["loanDate"] = out_date.isoformat()
|
|
672
618
|
loan_to_put["renewalCount"] = renewal_count
|
|
673
|
-
url =
|
|
674
|
-
f"{self.folio_client.gateway_url}/circulation/loans/{loan_to_put['id']}"
|
|
675
|
-
)
|
|
619
|
+
url = f"{self.folio_client.gateway_url}/circulation/loans/{loan_to_put['id']}"
|
|
676
620
|
req = self.http_client.put(
|
|
677
621
|
url,
|
|
678
622
|
headers=self.folio_client.okapi_headers,
|
|
@@ -693,8 +637,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
693
637
|
else:
|
|
694
638
|
self.migration_report.add(
|
|
695
639
|
"Details",
|
|
696
|
-
i18n.t("Update open loan error http status")
|
|
697
|
-
+ f": {req.status_code}",
|
|
640
|
+
i18n.t("Update open loan error http status") + f": {req.status_code}",
|
|
698
641
|
)
|
|
699
642
|
req.raise_for_status()
|
|
700
643
|
logging.debug("Updating open loan was successful")
|
|
@@ -724,41 +667,27 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
724
667
|
"servicePointId": str(self.task_configuration.fallback_service_point_id),
|
|
725
668
|
}
|
|
726
669
|
logging.debug(f"Declare lost data: {json.dumps(data, indent=4)}")
|
|
727
|
-
if self.folio_put_post(
|
|
728
|
-
|
|
729
|
-
):
|
|
730
|
-
self.migration_report.add(
|
|
731
|
-
"Details", i18n.t("Successfully declared loan as lost")
|
|
732
|
-
)
|
|
670
|
+
if self.folio_put_post(declare_lost_url, data, "POST", i18n.t("Declare item as lost")):
|
|
671
|
+
self.migration_report.add("Details", i18n.t("Successfully declared loan as lost"))
|
|
733
672
|
else:
|
|
734
673
|
logging.error(f"Unsuccessfully declared loan {folio_loan} as lost")
|
|
735
|
-
self.migration_report.add(
|
|
736
|
-
"Details", i18n.t("Unsuccessfully declared loan as lost")
|
|
737
|
-
)
|
|
674
|
+
self.migration_report.add("Details", i18n.t("Unsuccessfully declared loan as lost"))
|
|
738
675
|
|
|
739
676
|
def claim_returned(self, folio_loan):
|
|
740
|
-
claim_returned_url =
|
|
741
|
-
f"/circulation/loans/{folio_loan['id']}/claim-item-returned"
|
|
742
|
-
)
|
|
677
|
+
claim_returned_url = f"/circulation/loans/{folio_loan['id']}/claim-item-returned"
|
|
743
678
|
logging.debug(f"Claim returned url:{claim_returned_url}")
|
|
744
679
|
due_date = du_parser.isoparse(folio_loan["dueDate"])
|
|
745
680
|
data = {
|
|
746
|
-
"itemClaimedReturnedDateTime": datetime.isoformat(
|
|
747
|
-
due_date + timedelta(days=1)
|
|
748
|
-
),
|
|
681
|
+
"itemClaimedReturnedDateTime": datetime.isoformat(due_date + timedelta(days=1)),
|
|
749
682
|
"comment": "Created at migration. Date is due date + 1 day",
|
|
750
683
|
}
|
|
751
684
|
logging.debug(f"Claim returned data:\t{json.dumps(data)}")
|
|
752
|
-
if self.folio_put_post(
|
|
753
|
-
claim_returned_url, data, "POST", i18n.t("Claim item returned")
|
|
754
|
-
):
|
|
685
|
+
if self.folio_put_post(claim_returned_url, data, "POST", i18n.t("Claim item returned")):
|
|
755
686
|
self.migration_report.add(
|
|
756
687
|
"Details", i18n.t("Successfully declared loan as Claimed returned")
|
|
757
688
|
)
|
|
758
689
|
else:
|
|
759
|
-
logging.error(
|
|
760
|
-
f"Unsuccessfully declared loan {folio_loan} as Claimed returned"
|
|
761
|
-
)
|
|
690
|
+
logging.error(f"Unsuccessfully declared loan {folio_loan} as Claimed returned")
|
|
762
691
|
self.migration_report.add(
|
|
763
692
|
"Details",
|
|
764
693
|
i18n.t(
|
|
@@ -770,13 +699,9 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
770
699
|
def set_item_status(self, legacy_loan: LegacyLoan):
|
|
771
700
|
try:
|
|
772
701
|
# Get Item by barcode, update status.
|
|
773
|
-
item_path = (
|
|
774
|
-
f'item-storage/items?query=(barcode=="{legacy_loan.item_barcode}")'
|
|
775
|
-
)
|
|
702
|
+
item_path = f'item-storage/items?query=(barcode=="{legacy_loan.item_barcode}")'
|
|
776
703
|
item_url = f"{self.folio_client.gateway_url}/{item_path}"
|
|
777
|
-
resp = self.http_client.get(
|
|
778
|
-
item_url, headers=self.folio_client.okapi_headers
|
|
779
|
-
)
|
|
704
|
+
resp = self.http_client.get(item_url, headers=self.folio_client.okapi_headers)
|
|
780
705
|
resp.raise_for_status()
|
|
781
706
|
data = resp.json()
|
|
782
707
|
folio_item = data["items"][0]
|
|
@@ -897,9 +822,7 @@ class LoansMigrator(MigrationTaskBase):
|
|
|
897
822
|
try:
|
|
898
823
|
api_path = f"{folio_loan['id']}/change-due-date"
|
|
899
824
|
api_url = f"{self.folio_client.gateway_url}/circulation/loans/{api_path}"
|
|
900
|
-
body = {
|
|
901
|
-
"dueDate": du_parser.isoparse(str(legacy_loan.due_date)).isoformat()
|
|
902
|
-
}
|
|
825
|
+
body = {"dueDate": du_parser.isoparse(str(legacy_loan.due_date)).isoformat()}
|
|
903
826
|
req = self.http_client.post(
|
|
904
827
|
api_url, headers=self.folio_client.okapi_headers, json=body
|
|
905
828
|
)
|
|
@@ -6,7 +6,6 @@ import time
|
|
|
6
6
|
import traceback
|
|
7
7
|
from typing import List, Optional
|
|
8
8
|
|
|
9
|
-
import i18n
|
|
10
9
|
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
11
10
|
|
|
12
11
|
from folio_migration_tools.custom_exceptions import (
|
|
@@ -15,6 +14,7 @@ from folio_migration_tools.custom_exceptions import (
|
|
|
15
14
|
TransformationRecordFailedError,
|
|
16
15
|
)
|
|
17
16
|
from folio_migration_tools.helper import Helper
|
|
17
|
+
from folio_migration_tools.i18n_cache import i18n_t
|
|
18
18
|
from folio_migration_tools.library_configuration import (
|
|
19
19
|
FileDefinition,
|
|
20
20
|
LibraryConfiguration,
|
|
@@ -118,7 +118,7 @@ class ManualFeeFinesTransformer(MigrationTaskBase):
|
|
|
118
118
|
full_path = self.folder_structure.legacy_records_folder / file_def.file_name
|
|
119
119
|
with open(full_path, encoding="utf-8-sig") as records_file:
|
|
120
120
|
self.mapper.migration_report.add_general_statistics(
|
|
121
|
-
|
|
121
|
+
i18n_t("Number of files processed")
|
|
122
122
|
)
|
|
123
123
|
start = time.time()
|
|
124
124
|
|
|
@@ -172,7 +172,7 @@ class ManualFeeFinesTransformer(MigrationTaskBase):
|
|
|
172
172
|
self.folder_structure.migration_reports_file,
|
|
173
173
|
)
|
|
174
174
|
self.mapper.migration_report.write_migration_report(
|
|
175
|
-
|
|
175
|
+
i18n_t("Manual fee/fine transformation report"),
|
|
176
176
|
migration_report_file,
|
|
177
177
|
self.start_datetime,
|
|
178
178
|
)
|