folio-migration-tools 1.2.1__py3-none-any.whl → 1.9.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. folio_migration_tools/__init__.py +11 -0
  2. folio_migration_tools/__main__.py +169 -85
  3. folio_migration_tools/circulation_helper.py +96 -59
  4. folio_migration_tools/config_file_load.py +66 -0
  5. folio_migration_tools/custom_dict.py +6 -4
  6. folio_migration_tools/custom_exceptions.py +21 -19
  7. folio_migration_tools/extradata_writer.py +46 -0
  8. folio_migration_tools/folder_structure.py +63 -66
  9. folio_migration_tools/helper.py +29 -21
  10. folio_migration_tools/holdings_helper.py +57 -34
  11. folio_migration_tools/i18n_config.py +9 -0
  12. folio_migration_tools/library_configuration.py +173 -13
  13. folio_migration_tools/mapper_base.py +317 -106
  14. folio_migration_tools/mapping_file_transformation/courses_mapper.py +203 -0
  15. folio_migration_tools/mapping_file_transformation/holdings_mapper.py +83 -69
  16. folio_migration_tools/mapping_file_transformation/item_mapper.py +98 -94
  17. folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +352 -0
  18. folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +702 -223
  19. folio_migration_tools/mapping_file_transformation/notes_mapper.py +90 -0
  20. folio_migration_tools/mapping_file_transformation/order_mapper.py +492 -0
  21. folio_migration_tools/mapping_file_transformation/organization_mapper.py +389 -0
  22. folio_migration_tools/mapping_file_transformation/ref_data_mapping.py +38 -27
  23. folio_migration_tools/mapping_file_transformation/user_mapper.py +149 -361
  24. folio_migration_tools/marc_rules_transformation/conditions.py +650 -246
  25. folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +292 -130
  26. folio_migration_tools/marc_rules_transformation/hrid_handler.py +244 -0
  27. folio_migration_tools/marc_rules_transformation/loc_language_codes.xml +20846 -0
  28. folio_migration_tools/marc_rules_transformation/marc_file_processor.py +300 -0
  29. folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py +136 -0
  30. folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +241 -0
  31. folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +681 -201
  32. folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +395 -429
  33. folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +531 -100
  34. folio_migration_tools/migration_report.py +85 -38
  35. folio_migration_tools/migration_tasks/__init__.py +1 -3
  36. folio_migration_tools/migration_tasks/authority_transformer.py +119 -0
  37. folio_migration_tools/migration_tasks/batch_poster.py +911 -198
  38. folio_migration_tools/migration_tasks/bibs_transformer.py +121 -116
  39. folio_migration_tools/migration_tasks/courses_migrator.py +192 -0
  40. folio_migration_tools/migration_tasks/holdings_csv_transformer.py +252 -247
  41. folio_migration_tools/migration_tasks/holdings_marc_transformer.py +321 -115
  42. folio_migration_tools/migration_tasks/items_transformer.py +264 -84
  43. folio_migration_tools/migration_tasks/loans_migrator.py +506 -195
  44. folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +187 -0
  45. folio_migration_tools/migration_tasks/migration_task_base.py +364 -74
  46. folio_migration_tools/migration_tasks/orders_transformer.py +373 -0
  47. folio_migration_tools/migration_tasks/organization_transformer.py +451 -0
  48. folio_migration_tools/migration_tasks/requests_migrator.py +130 -62
  49. folio_migration_tools/migration_tasks/reserves_migrator.py +253 -0
  50. folio_migration_tools/migration_tasks/user_transformer.py +180 -139
  51. folio_migration_tools/task_configuration.py +46 -0
  52. folio_migration_tools/test_infrastructure/__init__.py +0 -0
  53. folio_migration_tools/test_infrastructure/mocked_classes.py +406 -0
  54. folio_migration_tools/transaction_migration/legacy_loan.py +148 -34
  55. folio_migration_tools/transaction_migration/legacy_request.py +65 -25
  56. folio_migration_tools/transaction_migration/legacy_reserve.py +47 -0
  57. folio_migration_tools/transaction_migration/transaction_result.py +12 -1
  58. folio_migration_tools/translations/en.json +476 -0
  59. folio_migration_tools-1.9.10.dist-info/METADATA +169 -0
  60. folio_migration_tools-1.9.10.dist-info/RECORD +67 -0
  61. {folio_migration_tools-1.2.1.dist-info → folio_migration_tools-1.9.10.dist-info}/WHEEL +1 -2
  62. folio_migration_tools-1.9.10.dist-info/entry_points.txt +3 -0
  63. folio_migration_tools/generate_schemas.py +0 -46
  64. folio_migration_tools/mapping_file_transformation/mapping_file_mapping_base_impl.py +0 -44
  65. folio_migration_tools/mapping_file_transformation/user_mapper_base.py +0 -212
  66. folio_migration_tools/marc_rules_transformation/bibs_processor.py +0 -163
  67. folio_migration_tools/marc_rules_transformation/holdings_processor.py +0 -284
  68. folio_migration_tools/report_blurbs.py +0 -219
  69. folio_migration_tools/transaction_migration/legacy_fee_fine.py +0 -36
  70. folio_migration_tools-1.2.1.dist-info/METADATA +0 -134
  71. folio_migration_tools-1.2.1.dist-info/RECORD +0 -50
  72. folio_migration_tools-1.2.1.dist-info/top_level.txt +0 -1
  73. {folio_migration_tools-1.2.1.dist-info → folio_migration_tools-1.9.10.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,169 @@
1
+ Metadata-Version: 2.4
2
+ Name: folio_migration_tools
3
+ Version: 1.9.10
4
+ Summary: A tool allowing you to migrate data from legacy ILS:s (Library systems) into FOLIO LSP
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Keywords: FOLIO,ILS,LSP,Library Systems,MARC21,Library data
8
+ Author: Theodor Tolstoy
9
+ Author-email: github.teddes@tolstoy.se
10
+ Requires-Python: >=3.10,<4.0
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Provides-Extra: docs
18
+ Requires-Dist: argparse-prompt (>=0.0.5,<0.0.6)
19
+ Requires-Dist: art (>=6.5,<7.0)
20
+ Requires-Dist: deepdiff (>=6.2.3,<7.0.0)
21
+ Requires-Dist: defusedxml (>=0.7.1,<0.8.0)
22
+ Requires-Dist: folio-data-import (>=0.4.1)
23
+ Requires-Dist: folio-uuid (>=1.0.0,<2.0.0)
24
+ Requires-Dist: folioclient (>=0.70.1,<0.71.0)
25
+ Requires-Dist: pyaml (>=21.10.1,<22.0.0)
26
+ Requires-Dist: pydantic (>=1.10.2,<2.0.0)
27
+ Requires-Dist: pyhumps (>=3.7.3,<4.0.0)
28
+ Requires-Dist: pymarc (>=5.2.3,<6.0.0)
29
+ Requires-Dist: python-dateutil (>=2.8.2,<3.0.0)
30
+ Requires-Dist: python-i18n (>=0.3.9,<0.4.0)
31
+ Project-URL: Documentation, https://folio-migration-tools.readthedocs.io/en/latest/
32
+ Project-URL: Homepage, https://github.com/folio-fse/folio_migration_tools
33
+ Project-URL: Repository, https://github.com/FOLIO-FSE/folio_migration_tools
34
+ Description-Content-Type: text/markdown
35
+
36
+ # FOLIO Migration Tools
37
+ ![example workflow](https://github.com/FOLIO-FSE/MARC21-To-FOLIO/actions/workflows/python-app.yml/badge.svg)[![codecov](https://codecov.io/gh/FOLIO-FSE/folio_migration_tools/branch/main/graph/badge.svg?token=ZQL5ILWWGT)](https://codecov.io/gh/FOLIO-FSE/folio_migration_tools) [![readthedocs](https://readthedocs.org/projects/docs/badge/?version=latest)](https://folio-migration-tools.readthedocs.io/)
38
+
39
+ A toolkit that enables you to migrate data over from a legacy ILS system into [FOLIO LSP](https://www.folio.org/)
40
+
41
+ # What is it good for?
42
+ FOLIO Migration tools enables you to migrate libraries with the most common ILS:s over to FOLIO without data losses or any major data transformation tasks.
43
+ The tools transforms and loads the data providing you and the library with good actionable logs and data cleaning task lists together with the migrated data.
44
+
45
+ ## What data does it cover?
46
+ FOLIO Migration Tools currently covers the following data sets:
47
+ * Catalog (Inventory and SRS in FOLIO terminology)
48
+ * Circulation transactions (Open loans and requests)
49
+ * Users/Patrons (In FOLIO, these share the same app/database)
50
+ * Courses and Reserves (Course reserves)
51
+ * Organizations (Vendor records)
52
+ * Orders (limited support)
53
+
54
+ ### What additional functionality is on the roadmap?
55
+ This is the loose roadmap, in order of most likely implementations first
56
+ * ERM-related objects
57
+ * Financial records
58
+
59
+ ### Can I use the tools for ongoing imports and integrations?
60
+ The tools are primarliy maintained for performing initial data migrations. We recommend that you use native FOLIO functionality for ongoing loads where possible.
61
+ In theory, these tools can be used for ongoing patron loads from systems like Banner, Workday, or PeopleSoft. But we recommend you to weigh your options carefully before going down this path.
62
+
63
+ # Contributing
64
+ Want to contribute? Read the [CONTRIBUTING.MD](https://github.com/FOLIO-FSE/folio_migration_tools/blob/main/CONTRIBUTING.md)
65
+
66
+ # Found an issue?
67
+ Report it on the [Github Issue tracker](https://github.com/FOLIO-FSE/folio_migration_tools/issues)
68
+
69
+ The scripts requires a FOLIO tenant with reference data properly set up. The script will throw messages telling what reference data is missing.
70
+ # Installing
71
+ Make sure you are running Python 3.9 or above.
72
+ ## 1. Using pip and venv
73
+ ### 2.1. Create and activate a [virtual environment](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment)
74
+ ```
75
+ python -m venv ./.venv # Creates a virtual env in the current folder
76
+ source .venv/bin/activate # Activates the venv
77
+ ```
78
+ ### 2. Install using pip:
79
+ ```
80
+ python -m pip install folio_migration_tools
81
+ ```
82
+ ### 3. Test the installation by showing the help pages
83
+ ```
84
+ python -m folio_migration_tools -h
85
+ ```
86
+
87
+ ## 2. Using pipenv
88
+ ### 1. Run
89
+ ```
90
+ pipenv install folio-migration-tools
91
+ ```
92
+ ### 2. Test the installation by showing the help pages
93
+ ```
94
+ pipenv run python3 -m folio_migration_tools -h
95
+ ```
96
+
97
+ # FOLIO migration process
98
+ This repo plays the main part in a process using a collection of tools. The process itself is documented in more detail, including example configuration files, at [this template repository](https://github.com/FOLIO-FSE/migration_repo_template)
99
+ In order to perform migrations according to this process, you need the following:
100
+ * An Installation of [FOLIO Migration Tools](https://pypi.org/project/folio-migration-tools/). Installation instructions above.
101
+ * A clone, or a separate repo created from [migration_repo_template](https://github.com/FOLIO-FSE/migration_repo_template)
102
+ * Access to the [Data mapping file creator](https://data-mapping-file-creator.folio.ebsco.com/data_mapping_creation) web tool
103
+ * A FOLIO tenant running the latest or the second latest version of FOLIO
104
+
105
+ # Internationalization
106
+
107
+ This repo uses [Python-i18n](https://github.com/danhper/python-i18n) to translate reports between languages, and to handle large strings for templates.
108
+
109
+ **Any English string which will end up in a report** should be wrapped in the function `i18n.t` from `i18n`:
110
+
111
+ ## Keys/Usage
112
+
113
+ ```js
114
+ i18n.t("Reports")+":"
115
+ ```
116
+
117
+ Templating is achieved with `%{[key]}` blocks, and keyword arguments in the internationaliation:
118
+
119
+ ```js
120
+ i18n.t("Code '%{code}' not found in FOLIO",code=folio_code)
121
+ ```
122
+
123
+ Long strings can use a placeholder key:
124
+
125
+ ```js
126
+ i18n.t("blurbs.Introduction.description")
127
+ ```
128
+
129
+ With the full string in ```translations/en.json```:
130
+
131
+ ```json
132
+ "blurbs.Introduction.description": "<br/>Data errors preventing records from being migrated
133
+ ```
134
+
135
+ ## Translations Files
136
+
137
+ Translation files live in the `translations` directory, with `en.json` as the default.
138
+
139
+ Extract template files with the `extract_translations` script:
140
+
141
+ ```bash
142
+ python scripts/extract_translations.py
143
+ ```
144
+
145
+ ## Internationalizations
146
+
147
+ Other langauges translations live in `translations/[locale].json`.
148
+ For example, Spanish would be `es.json`.
149
+
150
+ The keys must match the English keys, but the Values should be translated.
151
+
152
+ You can update a language file's keys with:
153
+
154
+ ```bash
155
+ python scripts/update_language.py --target-lang [locale]
156
+ ```
157
+
158
+ Translate all new strings, which begin with `TRANSLATE`, then commit.
159
+
160
+ ## Tips
161
+
162
+ * Internationalize entire phrases or paragraphs, not just the constitutent words. Syntax and grammar vary significantly between languages.
163
+ * Name template variables as generically as possible in the circumstance, and check translations for reusable translations.
164
+ * In a block with sentences separately followed by values, such as a table, you only need to translate the sentences.
165
+
166
+ # Running the scripts
167
+ For information on syntax, what files are needed and produced by the toolkit, refer to the documentation and example files in the [template repository](https://github.com/FOLIO-FSE/migration_repo_template). We are building out the docs section in this repository as well:[Documentation](https://folio-migration-tools.readthedocs.io/en/latest/)
168
+ ¨
169
+
@@ -0,0 +1,67 @@
1
+ folio_migration_tools/__init__.py,sha256=DXvzUKFSpSZjflFWaNm0L8yhFk0u7RVIvQMskwMmKFc,238
2
+ folio_migration_tools/__main__.py,sha256=kfo4iKf3GJD7deh4RvIizKnC4zvIgCpNo-Bs7HBM34s,8453
3
+ folio_migration_tools/circulation_helper.py,sha256=iib2p0WGzOcAnwaJppDYiONc-1Jdna66dPAtBmAIuCE,14538
4
+ folio_migration_tools/colors.py,sha256=GP0wdI_GZ2WD5SjrbPN-S3u8vvN_u6rGQIBBcWv_0ZM,227
5
+ folio_migration_tools/config_file_load.py,sha256=zHHa6NDkN6EJiQE4DgjrFQPVKsd70POsfbGkB8308jg,2822
6
+ folio_migration_tools/custom_dict.py,sha256=-FUnhKp90Dg8EHlY6twx-PYQxBUWEO7FgxL2b7pf-xk,678
7
+ folio_migration_tools/custom_exceptions.py,sha256=1zgOKy3NBUVGG6i9YxK6w2Hntlea8MHmm7mdnjBtzvQ,2687
8
+ folio_migration_tools/extradata_writer.py,sha256=fuchNcMc6BYb9IyfAcvXg7X4J2TfX6YiROfT2hr0JMw,1678
9
+ folio_migration_tools/folder_structure.py,sha256=bZlmKGtxdytWcqjnM2lE4Vpx4nHyYRk7CNL1tZhLtXY,6917
10
+ folio_migration_tools/helper.py,sha256=iWQhdcuzbGzVpEAiHQczO4hdhIH_iciLEp1SCGDynMI,2983
11
+ folio_migration_tools/holdings_helper.py,sha256=yJpz6aJrKRBiJ1MtT5bs2vXAc88uJuGh2_KDuCySOKc,7559
12
+ folio_migration_tools/i18n_config.py,sha256=3AH_2b9zTsxE4XTe4isM_zYtPJSlK0ix6eBmV7kAYUM,228
13
+ folio_migration_tools/library_configuration.py,sha256=LzICsZQdOkXwIqdDfh59x0-Cx77Lb18qVnWroNqekS8,7046
14
+ folio_migration_tools/mapper_base.py,sha256=IYER8Dq-4qLq3qiAvUpnzc33usUbfZtNKzyZJD6DNds,23567
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=yX8yCCw6B54r7JUn5IPhMYKBgImiagUzfwBxNVRf5MQ,8091
17
+ folio_migration_tools/mapping_file_transformation/holdings_mapper.py,sha256=qT8LMWZytSaOyUC9OzfJeekVIkLkNim4OzfoGlAh75g,8290
18
+ folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=ZmPc64X_l3hq8qc0WDhZ020TdjvucZoQciIVIpPzwiA,10472
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=LqxpULlickaQhIv92iBA7SwSXy1PN7l-9swLHQdnx6g,38408
21
+ folio_migration_tools/mapping_file_transformation/notes_mapper.py,sha256=vCmZmjrjyYtXeFCyVqvWfnP8y1jGGu15RXzXIHh12xY,3530
22
+ folio_migration_tools/mapping_file_transformation/order_mapper.py,sha256=hYnVkm28hE8GtOXQJDHBO0yt2Kp34bR71Qwye83WgFI,18226
23
+ folio_migration_tools/mapping_file_transformation/organization_mapper.py,sha256=u1Lb6tApn-nVLqbbJV38BuipKL3OK8Y2uQ4ogoyGQaI,14639
24
+ folio_migration_tools/mapping_file_transformation/ref_data_mapping.py,sha256=rROcBiL5TE7bWsJ95A6shurPZ1e4In6PTwR5BN9amzU,8991
25
+ folio_migration_tools/mapping_file_transformation/user_mapper.py,sha256=LJTj2F2dRKqyI37Ww0gY1AHLLT3dqyuKkY_RS_3-rg0,8543
26
+ folio_migration_tools/marc_rules_transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ folio_migration_tools/marc_rules_transformation/conditions.py,sha256=F78a70HXcDLnOXDs_vSTdgf4opMWHzXzOjvpWlOh4PM,47719
28
+ folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py,sha256=gM0ETZVVih35cSSpOBXA8wrBFhq2oeYaGsD89tnSNJs,13433
29
+ folio_migration_tools/marc_rules_transformation/hrid_handler.py,sha256=SgnSYeNR0z_qarkizBMWZZWr8tOPZJ4fvlZjlM3nJOU,9999
30
+ folio_migration_tools/marc_rules_transformation/loc_language_codes.xml,sha256=ztn2_yKws6qySL4oSsZh7sOjxq5bCC1PhAnXJdtgmJ0,382912
31
+ folio_migration_tools/marc_rules_transformation/marc_file_processor.py,sha256=QhVbJSlsWkGQgUo7ZVmQvlwpEN20Tyon_kzrZOWECoE,12549
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=PGt2w8h2pj8_8sGjQe3L-odFDlquURtKnoNFRWQB3GI,9621
34
+ folio_migration_tools/marc_rules_transformation/rules_mapper_base.py,sha256=loNZ9gEYaAwjkP2_wLlXGedjWvSdHoGF_oJN9g6gI3s,45928
35
+ folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py,sha256=RD46EzS0NQArn5LCGbrxDm9vbbW9PO_6iNUQwJBAbSg,30364
36
+ folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=ZgyDxmNE7LwW8Cd55wRIEE-u6iyMKCRRXdq2ZRjm2nc,28779
37
+ folio_migration_tools/migration_report.py,sha256=BkRspM1hwTBnWeqsHamf7yVEofzLj560Q-9G--O00hw,4258
38
+ folio_migration_tools/migration_tasks/__init__.py,sha256=ZkbY_yGyB84Ke8OMlYUzyyBj4cxxNrhMTwQlu_GbdDs,211
39
+ folio_migration_tools/migration_tasks/authority_transformer.py,sha256=AoXg9s-GLO3yEEDCrQV7hc4YVXxwxsdxDdpj1zhHydE,4251
40
+ folio_migration_tools/migration_tasks/batch_poster.py,sha256=Oc04VXIs-D8HzvKDtFR3evGVuPZmw35iWyUyOnpP-RE,50410
41
+ folio_migration_tools/migration_tasks/bibs_transformer.py,sha256=46d44pcDAodFXDYbrTCMRASISbDciXmA0CXYfhP2IaE,6298
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=-lMsQCkxVj2kFa0awf0_wsD5do1hbRhUqIu4p0UiRNk,21955
44
+ folio_migration_tools/migration_tasks/holdings_marc_transformer.py,sha256=c_ruhOgidyJdSnnRwWUs3wwFMiLqbVMPOhhCaYuH_TI,14343
45
+ folio_migration_tools/migration_tasks/items_transformer.py,sha256=oTbFX2saF7-ZCb1mO3baLvODnBSEbbN5F_GtSth3iG4,19755
46
+ folio_migration_tools/migration_tasks/loans_migrator.py,sha256=PF8DNpGKsppSDr7wX96Ao13UTFu6dl9cz2URLqSsOzE,40052
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=weQGuqmJz_OFvUUmV3tf19va7Hzc01OAOELbsn9ORR0,22664
49
+ folio_migration_tools/migration_tasks/orders_transformer.py,sha256=3Fk3WgSYtCboIsRgHpt0Zd5-es8vT7FWoqDHkupUXLk,14318
50
+ folio_migration_tools/migration_tasks/organization_transformer.py,sha256=Kuxkh1sKyUVBqm5qAK1Jrq-4xcyNz2JPZvvFRqfwI8s,16922
51
+ folio_migration_tools/migration_tasks/requests_migrator.py,sha256=QP9OBezC3FfcKpI78oMmydxcPaUIYAgHyKevyLwC-WQ,14841
52
+ folio_migration_tools/migration_tasks/reserves_migrator.py,sha256=4sSPer6_6yMwiiY1VYJmYZske_Ah1XG4KAM3NDadPhg,9952
53
+ folio_migration_tools/migration_tasks/user_transformer.py,sha256=aylrMC9n47fdStgsNfW4ZbJh2E4FDSPypsaNv52ynKc,12330
54
+ folio_migration_tools/task_configuration.py,sha256=73OWc8TX--fwPRptv3eQVEVv0-XmNaZcb3m__1HENSA,1161
55
+ folio_migration_tools/test_infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
+ folio_migration_tools/test_infrastructure/mocked_classes.py,sha256=BurU3NGU_Q8as_BGmW98q9O6bujZDkOfFmvKKdVw9t8,15056
57
+ folio_migration_tools/transaction_migration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
+ folio_migration_tools/transaction_migration/legacy_loan.py,sha256=sLw2fCBao1VWZykOx-BWpMndLHjJNj-HJZFYqbpVV5A,7561
59
+ folio_migration_tools/transaction_migration/legacy_request.py,sha256=1ulyFzPQw_InOjyPzkWpGnNptgXdQ18nmri0J8Nlpkc,6124
60
+ folio_migration_tools/transaction_migration/legacy_reserve.py,sha256=qzw0okg4axAE_ezXopP9gFsQ_e60o0zh7zqRzFBSWHY,1806
61
+ folio_migration_tools/transaction_migration/transaction_result.py,sha256=cTdCN0BnlI9_ZJB2Z3Fdkl9gpymIi-9mGZsRFlQcmDk,656
62
+ folio_migration_tools/translations/en.json,sha256=4Ac66PR5Y78ll4_grhBm2IdTMsoZUv0q3IJvX8SQiJI,41778
63
+ folio_migration_tools-1.9.10.dist-info/METADATA,sha256=otbWpB6CpG0dn3fTGpgP9U1PMj7aMc5LpCQ-REYC3Oo,7472
64
+ folio_migration_tools-1.9.10.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
65
+ folio_migration_tools-1.9.10.dist-info/entry_points.txt,sha256=Hbe-HjqMcU8FwVshVIkeWyZd9XwgT1CCMNf06EpHQu8,77
66
+ folio_migration_tools-1.9.10.dist-info/licenses/LICENSE,sha256=PhIEkitVi3ejgq56tt6sWoJIG_zmv82cjjd_aYPPGdI,1072
67
+ folio_migration_tools-1.9.10.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.37.1)
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ folio-migration-tools=folio_migration_tools.__main__:main
3
+
@@ -1,46 +0,0 @@
1
- import os
2
-
3
- from argparse_prompt import PromptParser
4
-
5
- from folio_migration_tools.library_configuration import LibraryConfiguration
6
- from folio_migration_tools.migration_tasks import *
7
- from folio_migration_tools.migration_tasks import migration_task_base
8
-
9
-
10
- def parse_args():
11
- """Parse CLI Arguments"""
12
- parser = PromptParser()
13
- parser.add_argument("results_path", help="Path to store schemas")
14
- return parser.parse_args()
15
-
16
-
17
- def main():
18
- args = parse_args()
19
- with open(
20
- os.path.join(args.results_path, "LibraryConfigurationSchema.json"), "w"
21
- ) as outfile:
22
- outfile.write(LibraryConfiguration.schema_json(indent=4))
23
-
24
- for t in inheritors(migration_task_base.MigrationTaskBase):
25
- with open(
26
- os.path.join(args.results_path, f"{t.__name__}Schema.json"), "w"
27
- ) as outfile:
28
- outfile.write(t.TaskConfiguration.schema_json(indent=4))
29
- print("done generating schemas.")
30
- sys.exit(0)
31
-
32
-
33
- def inheritors(base_class):
34
- subclasses = set()
35
- work = [base_class]
36
- while work:
37
- parent = work.pop()
38
- for child in parent.__subclasses__():
39
- if child not in subclasses:
40
- subclasses.add(child)
41
- work.append(child)
42
- return subclasses
43
-
44
-
45
- if __name__ == "__main__":
46
- main()
@@ -1,44 +0,0 @@
1
- from folio_migration_tools.library_configuration import LibraryConfiguration
2
- from folioclient import FolioClient
3
- from folio_uuid.folio_namespaces import FOLIONamespaces
4
- from folio_migration_tools.mapping_file_transformation.mapping_file_mapper_base import (
5
- MappingFileMapperBase,
6
- )
7
- from folio_migration_tools.report_blurbs import Blurbs
8
-
9
-
10
- class MappingFileMappingBaseImpl(MappingFileMapperBase):
11
- def __init__(
12
- self,
13
- library_configuration: LibraryConfiguration,
14
- folio_client: FolioClient,
15
- schema: dict,
16
- record_map: dict,
17
- object_type: FOLIONamespaces,
18
- ignore_legacy_identifier: bool = False,
19
- ):
20
-
21
- super().__init__(
22
- folio_client,
23
- schema,
24
- record_map,
25
- None,
26
- object_type,
27
- library_configuration,
28
- ignore_legacy_identifier,
29
- )
30
-
31
- def get_prop(self, legacy_item, folio_prop_name, index_or_id):
32
- legacy_item_keys = self.mapped_from_legacy_data.get(folio_prop_name, [])
33
-
34
- if len(legacy_item_keys) == 1 and folio_prop_name in self.mapped_from_values:
35
- return self.mapped_from_values.get(folio_prop_name, "")
36
-
37
- legacy_values = MappingFileMapperBase.get_legacy_vals(
38
- legacy_item, legacy_item_keys
39
- )
40
- if len(legacy_item_keys) > 1:
41
- self.migration_report.add(
42
- Blurbs.Details, f"{legacy_item_keys} were concatenated"
43
- )
44
- return " ".join(legacy_values).strip()
@@ -1,212 +0,0 @@
1
- import collections.abc
2
- from abc import abstractmethod
3
- from typing import Dict
4
-
5
- from folio_uuid import FOLIONamespaces, FolioUUID
6
- from folioclient import FolioClient
7
- from folio_migration_tools.custom_exceptions import TransformationProcessError
8
- from folio_migration_tools.library_configuration import LibraryConfiguration
9
- from folio_migration_tools.mapper_base import MapperBase
10
- from folio_migration_tools.migration_report import MigrationReport
11
-
12
-
13
- class UserMapperBase(MapperBase):
14
- def __init__(
15
- self, folio_client: FolioClient, library_configuration: LibraryConfiguration
16
- ):
17
- super().__init__(library_configuration, folio_client)
18
- self.legacy_id_map: Dict[str, str] = {}
19
-
20
- self.migration_report = MigrationReport()
21
- self.folio_client = folio_client
22
- self.mapped_folio_fields = {}
23
- self.ref_data_dicts = {}
24
- self.mapped_legacy_fields = {}
25
-
26
- def print_mapping_report(self, total_records):
27
- print("\n## Mapped FOLIO fields")
28
- d_sorted = {
29
- k: self.mapped_folio_fields[k] for k in sorted(self.mapped_folio_fields)
30
- }
31
- print("FOLIO Field | % | Has value")
32
- print("--- | --- | --- :")
33
- for k, v in d_sorted.items():
34
- mp = v / total_records
35
- mapped_per = "{:.0%}".format(max(mp, 0))
36
- print(f"{k} | {mapped_per} | {v} ")
37
- print("\n## Mapped Legacy fields")
38
- d_sorted = {
39
- k: self.mapped_legacy_fields[k] for k in sorted(self.mapped_legacy_fields)
40
- }
41
- print("Legacy Field | % | Has Value")
42
- print("--- | --- | --- :")
43
- for k, v in d_sorted.items():
44
- mp = v / total_records
45
- mapped_per = "{:.0%}".format(max(mp, 0))
46
- print(f"{k} | {mapped_per} | {v}")
47
-
48
- def report_legacy_mapping(self, legacy_object):
49
- for field_name, value in legacy_object.items():
50
- v = 1 if value else 0
51
- if field_name not in self.mapped_legacy_fields:
52
- self.mapped_legacy_fields[field_name] = [1, v]
53
- else:
54
- self.mapped_legacy_fields[field_name][0] += 1
55
- self.mapped_legacy_fields[field_name][1] += v
56
-
57
- def report_folio_mapping(self, folio_object):
58
- flat_object = flatten(folio_object)
59
- for field_name, value in flat_object.items():
60
- v = 1 if value else 0
61
- if field_name not in self.mapped_folio_fields:
62
- self.mapped_folio_fields[field_name] = [1, v]
63
- else:
64
- self.mapped_folio_fields[field_name][0] += 1
65
- self.mapped_folio_fields[field_name][1] += v
66
-
67
- def instantiate_user(self, legacy_id):
68
- if not legacy_id:
69
- raise TransformationProcessError(
70
- "",
71
- (
72
- "Legacy id not present. Have you set "
73
- "the legacyIdentifier in the mapping file?"
74
- ),
75
- )
76
- user_id = str(
77
- FolioUUID(self.folio_client.okapi_url, FOLIONamespaces.users, legacy_id)
78
- )
79
- return {
80
- "metadata": self.folio_client.get_metadata_construct(),
81
- "id": user_id,
82
- "type": "object",
83
- "personal": {},
84
- "customFields": {},
85
- }
86
-
87
- def validate(self, folio_user):
88
- failures = []
89
- self.migration_report.add(
90
- "Number of addresses per user",
91
- len(folio_user["personal"].get("addresses", [])),
92
- )
93
- req_fields = ["username", "email", "active"]
94
- for req in req_fields:
95
- if req not in folio_user:
96
- failures.append(req)
97
- self.migration_report.add(
98
- "Failed records that needs to get fixed",
99
- f"Required field {req} is missing from {folio_user['username']}",
100
- )
101
- if not folio_user["personal"].get("lastName", ""):
102
- failures.append("lastName")
103
- self.migration_report.add(
104
- "Failed records that needs to get fixed",
105
- f"Required field personal.lastName is missing from {folio_user['username']}",
106
- )
107
- if failures:
108
- self.migration_report.add("User validation", "Total failed users")
109
- for failure in failures:
110
- self.migration_report.add("User validation", f"{failure}")
111
- raise ValueError(
112
- f"Record {folio_user['username']} failed validation {failures}"
113
- )
114
-
115
- def write_migration_report(self):
116
- for a in self.migration_report:
117
- print("")
118
- print(f"## {a} - {len(self.migration_report[a])} things")
119
- print("Measure | Count")
120
- print("--- | ---:")
121
- b = self.migration_report[a]
122
- sortedlist = [(k, b[k]) for k in sorted(b, key=as_str)]
123
- for b in sortedlist:
124
- print(f"{b[0]} | {b[1]}")
125
-
126
- def save_migration_report_to_disk(self, file_path, total_records):
127
- with open(file_path, "w+") as report_file:
128
- for a in self.migration_report:
129
- report_file.write("\n")
130
- report_file.write(f"## {a} - {len(self.migration_report[a])} things\n")
131
- report_file.write("Measure | Count\n")
132
- report_file.write("--- | ---:\n")
133
- b = self.migration_report[a]
134
- sortedlist = [(k, b[k]) for k in sorted(b, key=as_str)]
135
- for b in sortedlist:
136
- report_file.write(f"{b[0]} | {b[1]}\n")
137
- report_file.write("\n## Mapped FOLIO fields\n")
138
- d_sorted = {
139
- k: self.mapped_folio_fields[k] for k in sorted(self.mapped_folio_fields)
140
- }
141
- report_file.write("FOLIO Field | % | Has Value\n")
142
- report_file.write("--- | --- | --- | ---:\n")
143
- for k, v in d_sorted.items():
144
- mp = v / total_records
145
- mapped_per = "{:.0%}".format(max(mp, 0))
146
- report_file.write(f"{k} | {mapped_per} | {v} \n")
147
- report_file.write("\n## Mapped Legacy fields\n")
148
- d_sorted = {
149
- k: self.mapped_legacy_fields[k]
150
- for k in sorted(self.mapped_legacy_fields)
151
- }
152
- report_file.write("Legacy Field | % | Has Value\n")
153
- report_file.write("--- | --- | --- | ---:\n")
154
- for k, v in d_sorted.items():
155
- mp = v / total_records
156
- mapped_per = "{:.0%}".format(max(mp, 0))
157
- report_file.write(f"{k} | {mapped_per} | {v}\n")
158
-
159
- @staticmethod
160
- def print_dict_to_md_table(my_dict, h1="", h2=""):
161
- d_sorted = {k: my_dict[k] for k in sorted(my_dict)}
162
- print(f"{h1} | {h2}")
163
- print("--- | ---:")
164
- for k, v in d_sorted.items():
165
- print(f"{k} | {v}")
166
-
167
- def get_ref_data_tuple_by_code(self, ref_data, ref_name, code):
168
- return self.get_ref_data_tuple(ref_data, ref_name, code, "code")
169
-
170
- def get_ref_data_tuple_by_name(self, ref_data, ref_name, name):
171
- return self.get_ref_data_tuple(ref_data, ref_name, name, "name")
172
-
173
- def get_ref_data_tuple(self, ref_data, ref_name, key_value, key_type):
174
- dict_key = f"{ref_name}{key_type}"
175
- ref_object = self.ref_data_dicts.get(dict_key, {}).get(
176
- key_value.lower().strip(), ()
177
- )
178
- # logging.info(f"{key_value} - {ref_object} - {dict_key}")
179
- if ref_object:
180
- return ref_object
181
- else:
182
- d = {}
183
- for r in ref_data:
184
- d[r[key_type].lower()] = (r["id"], r["name"])
185
- self.ref_data_dicts[dict_key] = d
186
- return self.ref_data_dicts.get(dict_key, {}).get(key_value.lower().strip(), ())
187
-
188
- @abstractmethod
189
- def do_map(self, legacy_user, object_map):
190
- raise NotImplementedError
191
-
192
- @abstractmethod
193
- def get_users(self, source_file, file_format: str):
194
- raise NotImplementedError
195
-
196
-
197
- def flatten(d, parent_key="", sep="."):
198
- items = []
199
- for k, v in d.items():
200
- new_key = parent_key + sep + k if parent_key else k
201
- if isinstance(v, collections.abc.MutableMapping):
202
- items.extend(flatten(v, new_key, sep=sep).items())
203
- else:
204
- items.append((new_key, v))
205
- return dict(items)
206
-
207
-
208
- def as_str(s):
209
- try:
210
- return str(s), ""
211
- except ValueError:
212
- return "", s