edu-rdm-integration 3.9.2__py3-none-any.whl → 3.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.
Files changed (279) hide show
  1. edu_rdm_integration/__init__.py +0 -1
  2. edu_rdm_integration/adapters/apps.py +15 -2
  3. edu_rdm_integration/adapters/caches.py +25 -12
  4. edu_rdm_integration/adapters/errors.py +13 -2
  5. edu_rdm_integration/adapters/functions.py +53 -14
  6. edu_rdm_integration/adapters/helpers.py +34 -8
  7. edu_rdm_integration/adapters/managers.py +41 -5
  8. edu_rdm_integration/adapters/presenters.py +26 -2
  9. edu_rdm_integration/adapters/receivers.py +16 -2
  10. edu_rdm_integration/adapters/results.py +50 -4
  11. edu_rdm_integration/adapters/runners.py +79 -20
  12. edu_rdm_integration/adapters/strategies.py +56 -54
  13. edu_rdm_integration/adapters/validators.py +43 -4
  14. edu_rdm_integration/apps.py +3 -23
  15. edu_rdm_integration/collect_and_export_data/__init__.py +1 -1
  16. edu_rdm_integration/collect_and_export_data/apps.py +1 -0
  17. edu_rdm_integration/collect_and_export_data/migrations/0001_initial.py +107 -17
  18. edu_rdm_integration/collect_and_export_data/migrations/0002_auto_20250204_1413.py +4 -2
  19. edu_rdm_integration/{consts.py → core/consts.py} +0 -11
  20. edu_rdm_integration/{enums.py → core/enums.py} +7 -54
  21. edu_rdm_integration/core/helpers.py +331 -0
  22. edu_rdm_integration/core/operations.py +71 -0
  23. edu_rdm_integration/core/redis_cache.py +20 -0
  24. edu_rdm_integration/{collect_and_export_data → core/registry}/actions.py +6 -12
  25. edu_rdm_integration/core/registry/apps.py +11 -0
  26. edu_rdm_integration/{collect_and_export_data → core/registry}/ui.py +1 -1
  27. edu_rdm_integration/{storages.py → core/storages.py} +8 -17
  28. edu_rdm_integration/{utils.py → core/utils.py} +29 -91
  29. edu_rdm_integration/migrations/0001_initial.py +294 -44
  30. edu_rdm_integration/migrations/0002_init_data_uploadstatus.py +1 -3
  31. edu_rdm_integration/migrations/0003_create_index_file_upload_status.py +0 -1
  32. edu_rdm_integration/migrations/0004_uploaderclientlog.py +1 -2
  33. edu_rdm_integration/migrations/0005_auto_20231204_1224.py +16 -4
  34. edu_rdm_integration/migrations/0006_request_status_data.py +60 -58
  35. edu_rdm_integration/migrations/0007_delete_upload_status.py +0 -1
  36. edu_rdm_integration/migrations/0009_auto_20240522_1619.py +1 -5
  37. edu_rdm_integration/migrations/0010_transferredentity_export_enabled.py +0 -1
  38. edu_rdm_integration/migrations/0011_exportingdatasubstageentity.py +16 -3
  39. edu_rdm_integration/migrations/0012_exportingdatasubstageattachment_attachment_size.py +0 -1
  40. edu_rdm_integration/migrations/0013_set_attachment_size.py +8 -12
  41. edu_rdm_integration/migrations/0014_uploaddatacommand.py +33 -6
  42. edu_rdm_integration/migrations/0015_set_exporting_sub_stage_status.py +1 -5
  43. edu_rdm_integration/migrations/0016_transferredentity_queue_level.py +2 -2
  44. edu_rdm_integration/migrations/0017_delete_uploaddatacommand.py +3 -2
  45. edu_rdm_integration/migrations/__init__.py +1 -0
  46. edu_rdm_integration/{registry → pipelines/transfer}/actions.py +13 -26
  47. edu_rdm_integration/pipelines/transfer/app_meta.py +18 -0
  48. edu_rdm_integration/pipelines/transfer/apps.py +19 -0
  49. edu_rdm_integration/pipelines/transfer/enums.py +34 -0
  50. edu_rdm_integration/pipelines/transfer/migrations/0001_initial.py +57 -0
  51. edu_rdm_integration/{base.py → pipelines/transfer/mixins.py} +29 -53
  52. edu_rdm_integration/pipelines/transfer/models.py +48 -0
  53. edu_rdm_integration/{tasks.py → pipelines/transfer/tasks.py} +51 -150
  54. edu_rdm_integration/{registry → pipelines/transfer}/ui.py +4 -10
  55. edu_rdm_integration/rdm_entities/apps.py +11 -0
  56. edu_rdm_integration/{entities.py → rdm_entities/entities.py} +67 -57
  57. edu_rdm_integration/rdm_entities/migrations/0001_initial.py +44 -0
  58. edu_rdm_integration/{enum_register → rdm_entities}/mixins.py +8 -59
  59. edu_rdm_integration/rdm_entities/models.py +63 -0
  60. edu_rdm_integration/rdm_entities/utils.py +33 -0
  61. edu_rdm_integration/rdm_models/apps.py +16 -0
  62. edu_rdm_integration/rdm_models/migrations/0001_initial.py +40 -0
  63. edu_rdm_integration/rdm_models/mixins.py +67 -0
  64. edu_rdm_integration/rdm_models/models.py +73 -0
  65. edu_rdm_integration/rdm_models/utils.py +23 -0
  66. edu_rdm_integration/stages/collect_data/apps.py +11 -0
  67. edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/functions.py-tpl +2 -2
  68. edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/managers.py-tpl +1 -1
  69. edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/runners.py-tpl +1 -1
  70. edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/tests.py-tpl +2 -1
  71. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/caches.py +2 -2
  72. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/functions.py +15 -18
  73. edu_rdm_integration/stages/collect_data/functions/base/helpers.py +20 -0
  74. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/managers.py +20 -27
  75. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/mixins.py +38 -55
  76. edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/runners.py +2 -5
  77. edu_rdm_integration/stages/collect_data/functions/calculated/base/__init__.py +0 -0
  78. edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/caches.py +3 -7
  79. edu_rdm_integration/stages/collect_data/functions/calculated/base/errors.py +7 -0
  80. edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/functions.py +8 -16
  81. edu_rdm_integration/stages/collect_data/functions/calculated/base/helpers.py +24 -0
  82. edu_rdm_integration/stages/collect_data/functions/calculated/base/managers.py +19 -0
  83. edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/presenters.py +1 -3
  84. edu_rdm_integration/stages/collect_data/functions/calculated/base/results.py +12 -0
  85. edu_rdm_integration/stages/collect_data/functions/calculated/base/runners.py +28 -0
  86. edu_rdm_integration/stages/collect_data/functions/calculated/base/validators.py +20 -0
  87. edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/strategies.py +32 -70
  88. edu_rdm_integration/stages/collect_data/functions/non_calculated/__init__.py +0 -0
  89. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/__init__.py +0 -0
  90. edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/caches.py +13 -22
  91. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/errors.py +7 -0
  92. edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/functions.py +8 -16
  93. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/helpers.py +24 -0
  94. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/managers.py +19 -0
  95. edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/presenters.py +1 -3
  96. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/results.py +12 -0
  97. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/runners.py +28 -0
  98. edu_rdm_integration/stages/collect_data/functions/non_calculated/base/validators.py +20 -0
  99. edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/strategies.py +32 -70
  100. edu_rdm_integration/{collect_data → stages/collect_data}/generators.py +9 -14
  101. edu_rdm_integration/stages/collect_data/helpers.py +154 -0
  102. edu_rdm_integration/stages/collect_data/management/__init__.py +0 -0
  103. edu_rdm_integration/stages/collect_data/management/base.py +100 -0
  104. edu_rdm_integration/stages/collect_data/management/commands/__init__.py +0 -0
  105. edu_rdm_integration/{management → stages/collect_data/management}/commands/collect_latest_models_data.py +5 -7
  106. edu_rdm_integration/{management → stages/collect_data/management}/commands/collect_models_data.py +5 -7
  107. edu_rdm_integration/stages/collect_data/migrations/0001_initial.py +187 -0
  108. edu_rdm_integration/stages/collect_data/migrations/0002_edurdmcollectdatacommandprogress.py +105 -0
  109. edu_rdm_integration/stages/collect_data/migrations/__init__.py +0 -0
  110. edu_rdm_integration/stages/collect_data/mixins.py +56 -0
  111. edu_rdm_integration/stages/collect_data/models.py +318 -0
  112. edu_rdm_integration/{collect_data/collect.py → stages/collect_data/operations.py} +30 -43
  113. edu_rdm_integration/stages/collect_data/registry/__init__.py +0 -0
  114. edu_rdm_integration/{collect_data → stages/collect_data/registry}/actions.py +17 -20
  115. edu_rdm_integration/stages/collect_data/registry/apps.py +11 -0
  116. edu_rdm_integration/{collect_data → stages/collect_data/registry}/ui.py +8 -15
  117. edu_rdm_integration/{collect_data → stages/collect_data}/tests.py +2 -2
  118. edu_rdm_integration/stages/export_data/__init__.py +0 -0
  119. edu_rdm_integration/stages/export_data/apps.py +11 -0
  120. edu_rdm_integration/stages/export_data/function_templates/__init__.py +0 -0
  121. edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/functions.py-tpl +2 -2
  122. edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/managers.py-tpl +2 -2
  123. edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/runners.py-tpl +2 -2
  124. edu_rdm_integration/stages/export_data/functions/__init__.py +0 -0
  125. edu_rdm_integration/stages/export_data/functions/base/__init__.py +0 -0
  126. edu_rdm_integration/{export_data → stages/export_data/functions}/base/caches.py +3 -8
  127. edu_rdm_integration/stages/export_data/functions/base/errors.py +7 -0
  128. edu_rdm_integration/{export_data → stages/export_data/functions}/base/functions.py +28 -59
  129. edu_rdm_integration/{export_data → stages/export_data/functions}/base/helpers.py +7 -17
  130. edu_rdm_integration/{export_data → stages/export_data/functions}/base/managers.py +19 -28
  131. edu_rdm_integration/stages/export_data/functions/base/presenters.py +11 -0
  132. edu_rdm_integration/{export_data → stages/export_data/functions}/base/requests.py +13 -40
  133. edu_rdm_integration/stages/export_data/functions/base/results.py +12 -0
  134. edu_rdm_integration/{export_data → stages/export_data/functions}/base/runners.py +9 -21
  135. edu_rdm_integration/stages/export_data/functions/base/validators.py +20 -0
  136. edu_rdm_integration/{export_data → stages/export_data}/generators.py +7 -6
  137. edu_rdm_integration/stages/export_data/helpers.py +203 -0
  138. edu_rdm_integration/stages/export_data/management/__init__.py +0 -0
  139. edu_rdm_integration/stages/export_data/management/base.py +101 -0
  140. edu_rdm_integration/stages/export_data/management/commands/__init__.py +0 -0
  141. edu_rdm_integration/{management → stages/export_data/management}/commands/export_entities_data.py +5 -7
  142. edu_rdm_integration/{management → stages/export_data/management}/commands/export_latest_entities_data.py +5 -7
  143. edu_rdm_integration/stages/export_data/migrations/0001_initial.py +324 -0
  144. edu_rdm_integration/stages/export_data/migrations/__init__.py +0 -0
  145. edu_rdm_integration/stages/export_data/mixins.py +50 -0
  146. edu_rdm_integration/stages/export_data/models.py +362 -0
  147. edu_rdm_integration/{export_data/export.py → stages/export_data/operations.py} +13 -152
  148. edu_rdm_integration/stages/export_data/registry/__init__.py +0 -0
  149. edu_rdm_integration/{export_data → stages/export_data/registry}/actions.py +18 -18
  150. edu_rdm_integration/stages/export_data/registry/apps.py +11 -0
  151. edu_rdm_integration/{export_data → stages/export_data/registry}/ui.py +5 -7
  152. edu_rdm_integration/{export_data → stages/export_data}/strategies.py +30 -68
  153. edu_rdm_integration/stages/service/__init__.py +0 -0
  154. edu_rdm_integration/stages/service/apps.py +19 -0
  155. edu_rdm_integration/stages/service/tasks.py +63 -0
  156. edu_rdm_integration/stages/upload_data/__init__.py +0 -0
  157. edu_rdm_integration/stages/upload_data/apps.py +19 -0
  158. edu_rdm_integration/stages/upload_data/consts.py +10 -0
  159. edu_rdm_integration/{export_data → stages/upload_data}/dataclasses.py +1 -0
  160. edu_rdm_integration/stages/upload_data/enums.py +17 -0
  161. edu_rdm_integration/{export_data/export_manager.py → stages/upload_data/export_managers.py} +73 -68
  162. edu_rdm_integration/stages/upload_data/helpers.py +164 -0
  163. edu_rdm_integration/stages/upload_data/management/__init__.py +0 -0
  164. edu_rdm_integration/stages/upload_data/management/base.py +134 -0
  165. edu_rdm_integration/stages/upload_data/management/commands/__init__.py +0 -0
  166. edu_rdm_integration/{management → stages/upload_data/management}/commands/async_fix_attachment_size.py +32 -54
  167. edu_rdm_integration/{management → stages/upload_data/management}/commands/check_upload_status.py +7 -6
  168. edu_rdm_integration/{management → stages/upload_data/management}/commands/datamart_status.py +3 -3
  169. edu_rdm_integration/{management → stages/upload_data/management}/commands/datamart_upload.py +4 -4
  170. edu_rdm_integration/stages/upload_data/migrations/0001_initial.py +161 -0
  171. edu_rdm_integration/stages/upload_data/migrations/__init__.py +0 -0
  172. edu_rdm_integration/stages/upload_data/models.py +175 -0
  173. edu_rdm_integration/stages/upload_data/operations.py +156 -0
  174. edu_rdm_integration/{export_data/queue.py → stages/upload_data/queues.py} +10 -8
  175. edu_rdm_integration/stages/upload_data/tasks.py +103 -0
  176. edu_rdm_integration/stages/upload_data/uploader_log/__init__.py +0 -0
  177. edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/actions.py +14 -16
  178. edu_rdm_integration/stages/upload_data/uploader_log/apps.py +11 -0
  179. edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/managers.py +15 -30
  180. edu_rdm_integration/stages/upload_data/uploader_log/migrations/0001_initial.py +31 -0
  181. edu_rdm_integration/stages/upload_data/uploader_log/migrations/__init__.py +0 -0
  182. edu_rdm_integration/stages/upload_data/uploader_log/models.py +86 -0
  183. edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/ui.py +8 -6
  184. {edu_rdm_integration-3.9.2.dist-info → edu_rdm_integration-3.10.0.dist-info}/METADATA +238 -238
  185. edu_rdm_integration-3.10.0.dist-info/RECORD +255 -0
  186. edu_rdm_integration/app_meta.py +0 -16
  187. edu_rdm_integration/app_settings.py +0 -77
  188. edu_rdm_integration/collect_and_export_data/models.py +0 -67
  189. edu_rdm_integration/collect_and_export_data/utils.py +0 -224
  190. edu_rdm_integration/collect_data/base/helpers.py +0 -26
  191. edu_rdm_integration/collect_data/calculated/base/errors.py +0 -9
  192. edu_rdm_integration/collect_data/calculated/base/helpers.py +0 -32
  193. edu_rdm_integration/collect_data/calculated/base/managers.py +0 -23
  194. edu_rdm_integration/collect_data/calculated/base/results.py +0 -16
  195. edu_rdm_integration/collect_data/calculated/base/runners.py +0 -36
  196. edu_rdm_integration/collect_data/calculated/base/validators.py +0 -28
  197. edu_rdm_integration/collect_data/helpers.py +0 -92
  198. edu_rdm_integration/collect_data/non_calculated/base/errors.py +0 -9
  199. edu_rdm_integration/collect_data/non_calculated/base/helpers.py +0 -32
  200. edu_rdm_integration/collect_data/non_calculated/base/managers.py +0 -23
  201. edu_rdm_integration/collect_data/non_calculated/base/results.py +0 -16
  202. edu_rdm_integration/collect_data/non_calculated/base/runners.py +0 -36
  203. edu_rdm_integration/collect_data/non_calculated/base/validators.py +0 -28
  204. edu_rdm_integration/enum_register/register.py +0 -79
  205. edu_rdm_integration/export_data/base/errors.py +0 -9
  206. edu_rdm_integration/export_data/base/presenters.py +0 -13
  207. edu_rdm_integration/export_data/base/results.py +0 -16
  208. edu_rdm_integration/export_data/base/validators.py +0 -28
  209. edu_rdm_integration/export_data/helpers.py +0 -92
  210. edu_rdm_integration/helpers.py +0 -412
  211. edu_rdm_integration/management/general.py +0 -327
  212. edu_rdm_integration/models.py +0 -982
  213. edu_rdm_integration/redis_cache.py +0 -51
  214. edu_rdm_integration/uploader_log/apps.py +0 -10
  215. edu_rdm_integration-3.9.2.dist-info/RECORD +0 -198
  216. /edu_rdm_integration/{collect_and_export_data/migrations → core}/__init__.py +0 -0
  217. /edu_rdm_integration/{mapping.py → core/mapping.py} +0 -0
  218. /edu_rdm_integration/{collect_data → core/registry}/__init__.py +0 -0
  219. /edu_rdm_integration/{templates → core/registry/templates}/ui-js/start-task.js +0 -0
  220. /edu_rdm_integration/{signals.py → core/signals.py} +0 -0
  221. /edu_rdm_integration/{typing.py → core/typing.py} +0 -0
  222. /edu_rdm_integration/{collect_data/base → pipelines}/__init__.py +0 -0
  223. /edu_rdm_integration/{collect_data/calculated → pipelines/transfer}/__init__.py +0 -0
  224. /edu_rdm_integration/{collect_data/calculated/base → pipelines/transfer/migrations}/__init__.py +0 -0
  225. /edu_rdm_integration/{templates → pipelines/transfer/templates}/ui-js/transferred-entity-list.js +0 -0
  226. /edu_rdm_integration/{collect_data/non_calculated → rdm_entities}/__init__.py +0 -0
  227. /edu_rdm_integration/{collect_data/non_calculated/base → rdm_entities/migrations}/__init__.py +0 -0
  228. /edu_rdm_integration/{enum_register → rdm_models}/__init__.py +0 -0
  229. /edu_rdm_integration/{export_data → rdm_models/migrations}/__init__.py +0 -0
  230. /edu_rdm_integration/{export_data/base → stages}/__init__.py +0 -0
  231. /edu_rdm_integration/{function_templates → stages/collect_data}/__init__.py +0 -0
  232. /edu_rdm_integration/{collect_data/const.py → stages/collect_data/consts.py} +0 -0
  233. /edu_rdm_integration/{management → stages/collect_data/function_templates}/__init__.py +0 -0
  234. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/__init__.py-tpl +0 -0
  235. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/apps.py-tpl +0 -0
  236. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/caches.py-tpl +0 -0
  237. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/consts.py-tpl +0 -0
  238. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/enums.py-tpl +0 -0
  239. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/errors.py-tpl +0 -0
  240. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/helpers.py-tpl +0 -0
  241. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/presenters.py-tpl +0 -0
  242. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/results.py-tpl +0 -0
  243. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/strings.py-tpl +0 -0
  244. /edu_rdm_integration/{function_templates → stages/collect_data/function_templates}/function_collect_data_template/validators.py-tpl +0 -0
  245. /edu_rdm_integration/{management/commands → stages/collect_data/functions}/__init__.py +0 -0
  246. /edu_rdm_integration/{registry → stages/collect_data/functions/base}/__init__.py +0 -0
  247. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/base/consts.py +0 -0
  248. /edu_rdm_integration/{uploader_log → stages/collect_data/functions/calculated}/__init__.py +0 -0
  249. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/consts.py +0 -0
  250. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/enums.py +0 -0
  251. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/strings.py +0 -0
  252. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/calculated/base/tests.py +0 -0
  253. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/consts.py +0 -0
  254. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/enums.py +0 -0
  255. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/strings.py +0 -0
  256. /edu_rdm_integration/{collect_data → stages/collect_data/functions}/non_calculated/base/tests.py +0 -0
  257. /edu_rdm_integration/{export_data → stages/export_data}/consts.py +0 -0
  258. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/__init__.py-tpl +0 -0
  259. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/apps.py-tpl +0 -0
  260. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/caches.py-tpl +0 -0
  261. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/consts.py-tpl +0 -0
  262. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/enums.py-tpl +0 -0
  263. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/errors.py-tpl +0 -0
  264. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/helpers.py-tpl +0 -0
  265. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/presenters.py-tpl +0 -0
  266. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/results.py-tpl +0 -0
  267. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/strings.py-tpl +0 -0
  268. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/tests.py-tpl +0 -0
  269. /edu_rdm_integration/{function_templates → stages/export_data/function_templates}/function_export_data_template/validators.py-tpl +0 -0
  270. /edu_rdm_integration/{export_data → stages/export_data/functions}/base/consts.py +0 -0
  271. /edu_rdm_integration/{export_data → stages/export_data/functions}/base/enums.py +0 -0
  272. /edu_rdm_integration/{export_data → stages/export_data/functions}/base/strings.py +0 -0
  273. /edu_rdm_integration/{export_data → stages/export_data/functions}/base/tests.py +0 -0
  274. /edu_rdm_integration/{templates → stages/export_data/registry/templates}/ui-js/stage_for_export.js +0 -0
  275. /edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/enums.py +0 -0
  276. /edu_rdm_integration/{uploader_log → stages/upload_data/uploader_log}/templates/ui-js/object-grid-buttons.js +0 -0
  277. {edu_rdm_integration-3.9.2.dist-info → edu_rdm_integration-3.10.0.dist-info}/WHEEL +0 -0
  278. {edu_rdm_integration-3.9.2.dist-info → edu_rdm_integration-3.10.0.dist-info}/licenses/LICENSE +0 -0
  279. {edu_rdm_integration-3.9.2.dist-info → edu_rdm_integration-3.10.0.dist-info}/top_level.txt +0 -0
@@ -21,33 +21,27 @@ from edu_rdm_integration.adapters.helpers import (
21
21
  WebEduFunctionHelper,
22
22
  WebEduRunnerHelper,
23
23
  )
24
- from edu_rdm_integration.consts import (
24
+ from edu_rdm_integration.core.consts import (
25
25
  DATE_FORMAT,
26
26
  EXPORT_DATETIME_FORMAT,
27
27
  HASH_ALGORITHM,
28
28
  )
29
- from edu_rdm_integration.export_data.base.caches import (
29
+ from edu_rdm_integration.stages.export_data.functions.base.caches import (
30
30
  BaseExportDataFunctionCacheStorage,
31
31
  BaseExportDataRunnerCacheStorage,
32
32
  )
33
33
 
34
34
 
35
35
  class BaseExportDataRunnerHelper(WebEduRunnerHelper):
36
- """
37
- Базовый класс помощников ранеров функций выгрузки данных для интеграции с "Региональная витрина данных".
38
- """
36
+ """Базовый класс помощников ранеров функций выгрузки данных для интеграции с "Региональная витрина данных"."""
39
37
 
40
38
  def _prepare_cache_class(self) -> type[BaseExportDataRunnerCacheStorage]:
41
- """
42
- Возвращает класс кеша помощника ранера.
43
- """
39
+ """Возвращает класс кеша помощника ранера."""
44
40
  return BaseExportDataRunnerCacheStorage
45
41
 
46
42
 
47
43
  class BaseExportDataFunctionHelper(WebEduFunctionHelper):
48
- """
49
- Базовый класс помощников функций выгрузки данных для интеграции с "Региональная витрина данных".
50
- """
44
+ """Базовый класс помощников функций выгрузки данных для интеграции с "Региональная витрина данных"."""
51
45
 
52
46
  cryptographer = HashData(hash_algorithm=HASH_ALGORITHM)
53
47
 
@@ -88,9 +82,7 @@ class BaseExportDataFunctionHelper(WebEduFunctionHelper):
88
82
  hashable_fields: set[str],
89
83
  ignore_prefix_fields: set[str],
90
84
  ) -> list[str]:
91
- """
92
- Формирование списка строковых значений полей.
93
- """
85
+ """Формирование списка строковых значений полей."""
94
86
  field_values = []
95
87
  key_fields = primary_key_fields.union(foreign_key_fields)
96
88
  add_prefix_fields = key_fields.difference(ignore_prefix_fields)
@@ -124,7 +116,5 @@ class BaseExportDataFunctionHelper(WebEduFunctionHelper):
124
116
  return field_values
125
117
 
126
118
  def _prepare_cache_class(self) -> type[BaseExportDataFunctionCacheStorage]:
127
- """
128
- Возвращает класс кеша помощника функции.
129
- """
119
+ """Возвращает класс кеша помощника функции."""
130
120
  return BaseExportDataFunctionCacheStorage
@@ -20,26 +20,26 @@ from m3_db_utils.models import (
20
20
  from edu_rdm_integration.adapters.managers import (
21
21
  WebEduRunnerManager,
22
22
  )
23
- from edu_rdm_integration.consts import (
23
+ from edu_rdm_integration.core.consts import (
24
24
  LOGS_DELIMITER,
25
25
  )
26
- from edu_rdm_integration.export_data.base.runners import (
27
- BaseExportDataRunner,
26
+ from edu_rdm_integration.core.storages import (
27
+ RegionalDataMartEntityStorage,
28
28
  )
29
- from edu_rdm_integration.models import (
29
+ from edu_rdm_integration.stages.collect_data.models import (
30
30
  CollectingDataStageStatus,
31
+ )
32
+ from edu_rdm_integration.stages.export_data.functions.base.runners import (
33
+ BaseExportDataRunner,
34
+ )
35
+ from edu_rdm_integration.stages.export_data.models import (
31
36
  ExportingDataStage,
32
37
  ExportingDataStageStatus,
33
38
  )
34
- from edu_rdm_integration.storages import (
35
- RegionalDataMartEntityStorage,
36
- )
37
39
 
38
40
 
39
41
  class BaseExportDataRunnerManager(WebEduRunnerManager, metaclass=ABCMeta):
40
- """
41
- Менеджер ранеров функций выгрузки данных для интеграции с "Региональная витрина данных".
42
- """
42
+ """Менеджер ранеров функций выгрузки данных для интеграции с "Региональная витрина данных"."""
43
43
 
44
44
  forced_run = True
45
45
 
@@ -66,15 +66,11 @@ class BaseExportDataRunnerManager(WebEduRunnerManager, metaclass=ABCMeta):
66
66
 
67
67
  @classmethod
68
68
  def _prepare_runner_class(cls) -> type[BaseExportDataRunner]:
69
- """
70
- Возвращает класс ранера.
71
- """
69
+ """Возвращает класс ранера."""
72
70
  return BaseExportDataRunner
73
71
 
74
72
  def _find_exporting_data_stage(self):
75
- """
76
- Поиск последнего подэтапа выгрузки данных сущности РВД.
77
- """
73
+ """Поиск последнего подэтапа выгрузки данных сущности РВД."""
78
74
  entity_storage = RegionalDataMartEntityStorage()
79
75
  entity_storage.prepare()
80
76
 
@@ -94,9 +90,7 @@ class BaseExportDataRunnerManager(WebEduRunnerManager, metaclass=ABCMeta):
94
90
  return exporting_data_stage
95
91
 
96
92
  def _prepare_period(self, *args, **kwargs) -> tuple[datetime, datetime]:
97
- """
98
- Формирование периода сбора данных моделей РВД.
99
- """
93
+ """Формирование периода сбора данных моделей РВД."""
100
94
  period_started_at = kwargs.get('period_started_at')
101
95
  period_ended_at = kwargs.get('period_ended_at')
102
96
 
@@ -114,8 +108,7 @@ class BaseExportDataRunnerManager(WebEduRunnerManager, metaclass=ABCMeta):
114
108
  return period_started_at, period_ended_at
115
109
 
116
110
  def _prepare_model_ids_map(self) -> dict[ModelEnumValue, Iterator[int]]:
117
- """
118
- Осуществляется поиск записей моделей добавленных или обновленных за указанный период времени.
111
+ """Осуществляется поиск записей моделей добавленных или обновленных за указанный период времени.
119
112
 
120
113
  Т.к. моделей влияющих на сущность может быть множество, то в методе формируется словарь, содержащий в качестве
121
114
  ключа название модели, значение - итератор идентификаторов записей.
@@ -123,8 +116,7 @@ class BaseExportDataRunnerManager(WebEduRunnerManager, metaclass=ABCMeta):
123
116
  return {}
124
117
 
125
118
  def _create_runner(self, *args, **kwargs):
126
- """
127
- Производится расширение для осуществления поиска идентификаторов записей моделей РВД для дальнейшей выгрузки.
119
+ """Производится расширение для осуществления поиска идентификаторов записей моделей РВД для дальнейшей выгрузки.
128
120
 
129
121
  model_ids_map пробрасывается в ранер для дальнейшей обработки записей для формирования чанков.
130
122
  is_force_fill_cache указывается для отказа от заполнения кешей запускаемых объектов при их создании.
@@ -145,15 +137,14 @@ class BaseExportDataRunnerManager(WebEduRunnerManager, metaclass=ABCMeta):
145
137
  logger.info(f'{LOGS_DELIMITER}change status {repr(self._stage)}')
146
138
 
147
139
  def _start_runner(self, *args, **kwargs):
148
- """
149
- Ранер необходимо запустить с отложенным заполнением кешей, чтобы заполнение произошло перед запуском объекта.
140
+ """Ранер необходимо запустить с отложенным заполнением кешей.
141
+
142
+ Это позволит произвести заполнение перед запуском объекта.
150
143
  """
151
144
  super()._start_runner(*args, is_force_fill_cache=False, **kwargs)
152
145
 
153
146
  def _after_start_runner(self, *args, **kwargs):
154
- """
155
- Точка расширения поведения менеджера ранера после запуска ранера.
156
- """
147
+ """Точка расширения поведения менеджера ранера после запуска ранера."""
157
148
  if self._runner.result.has_not_errors:
158
149
  self._stage.status_id = ExportingDataStageStatus.FINISHED.key
159
150
  else:
@@ -0,0 +1,11 @@
1
+ from abc import (
2
+ ABCMeta,
3
+ )
4
+
5
+ from edu_rdm_integration.adapters.presenters import (
6
+ WebEduResultPresenter,
7
+ )
8
+
9
+
10
+ class BaseExportDataResultPresenter(WebEduResultPresenter, metaclass=ABCMeta):
11
+ """Презентер результата работы функций выгрузки данных для интеграции с "Региональная витрина данных"."""
@@ -18,9 +18,7 @@ from uploader_client.interfaces import (
18
18
 
19
19
  @dataclass
20
20
  class RegionalDataMartEntityRequest(OpenAPIRequest):
21
- """
22
- Запрос на отправку данных сущности.
23
- """
21
+ """Запрос на отправку данных сущности."""
24
22
 
25
23
  datamart_name: str
26
24
  table_name: str
@@ -32,52 +30,35 @@ class RegionalDataMartEntityRequest(OpenAPIRequest):
32
30
  data: Any = None
33
31
 
34
32
  def get_method(self):
35
- """
36
- Получение метода запроса.
37
- """
33
+ """Получение метода запроса."""
38
34
  return self.method
39
35
 
40
36
  def get_url(self):
41
- """
42
- Получение сформированного URL.
43
- """
37
+ """Получение сформированного URL."""
44
38
  return f'/v2/datamarts/{self.datamart_name}/tables/{self.table_name}/{self.operation}'
45
39
 
46
40
  def get_headers(self) -> dict:
47
- """
48
- Возвращает заголовки запроса.
49
- """
41
+ """Возвращает заголовки запроса."""
50
42
  return self.headers
51
43
 
52
44
  def get_files(self):
53
- """
54
- Возвращает файлы для отправки.
55
- """
56
- files = [
57
- (file_name, file_.open('rb'))
58
- for file_name, file_ in self.files
59
- ]
45
+ """Возвращает файлы для отправки."""
46
+ files = [(file_name, file_.open('rb')) for file_name, file_ in self.files]
60
47
 
61
48
  return files
62
49
 
63
50
  def get_data(self):
64
- """
65
- Возвращает содержимое запроса.
66
- """
51
+ """Возвращает содержимое запроса."""
67
52
  return self.data
68
53
 
69
54
  def get_timeout(self):
70
- """
71
- Возвращает время ожидания ответа.
72
- """
55
+ """Возвращает время ожидания ответа."""
73
56
  return settings.RDM_UPLOADER_CLIENT_REQUEST_TIMEOUT
74
57
 
75
58
 
76
59
  @dataclass
77
60
  class RegionalDataMartStatusRequest(OpenAPIRequest):
78
- """
79
- Запрос для получения статуса загрузки данных в РВД.
80
- """
61
+ """Запрос для получения статуса загрузки данных в РВД."""
81
62
 
82
63
  request_id: str
83
64
  method: str
@@ -85,25 +66,17 @@ class RegionalDataMartStatusRequest(OpenAPIRequest):
85
66
  parameters: dict = Field(default_factory=dict)
86
67
 
87
68
  def get_method(self):
88
- """
89
- Получение метода запроса.
90
- """
69
+ """Получение метода запроса."""
91
70
  return self.method
92
71
 
93
72
  def get_url(self):
94
- """
95
- Получение сформированного URL.
96
- """
73
+ """Получение сформированного URL."""
97
74
  return f'/v2/requests/{self.request_id}/status'
98
75
 
99
76
  def get_headers(self) -> dict:
100
- """
101
- Возвращает заголовки запроса.
102
- """
77
+ """Возвращает заголовки запроса."""
103
78
  return self.headers
104
79
 
105
80
  def get_timeout(self):
106
- """
107
- Возвращает время ожидания ответа.
108
- """
81
+ """Возвращает время ожидания ответа."""
109
82
  return settings.RDM_UPLOADER_CLIENT_REQUEST_TIMEOUT
@@ -0,0 +1,12 @@
1
+ from edu_rdm_integration.adapters.results import (
2
+ WebEduFunctionResult,
3
+ WebEduRunnerResult,
4
+ )
5
+
6
+
7
+ class BaseExportDataRunnerResult(WebEduRunnerResult):
8
+ """Базовый класс результата работы ранера функций выгрузки данных для интеграции с РВД."""
9
+
10
+
11
+ class BaseExportDataFunctionResult(WebEduFunctionResult):
12
+ """Базовый класс результата функции выгрузки данных для интеграции с РВД."""
@@ -1,44 +1,34 @@
1
1
  from edu_rdm_integration.adapters.runners import (
2
2
  WebEduRunner,
3
3
  )
4
- from edu_rdm_integration.export_data.base.helpers import (
4
+ from edu_rdm_integration.stages.export_data.functions.base.helpers import (
5
5
  BaseExportDataRunnerHelper,
6
6
  )
7
- from edu_rdm_integration.export_data.base.results import (
7
+ from edu_rdm_integration.stages.export_data.functions.base.results import (
8
8
  BaseExportDataRunnerResult,
9
9
  )
10
- from edu_rdm_integration.export_data.base.validators import (
10
+ from edu_rdm_integration.stages.export_data.functions.base.validators import (
11
11
  BaseExportDataRunnerValidator,
12
12
  )
13
13
 
14
14
 
15
15
  class BaseExportDataRunner(WebEduRunner):
16
- """
17
- Базовый класс ранеров функций выгрузки данных для интеграции с "Региональная витрина данных".
18
- """
16
+ """Базовый класс ранеров функций выгрузки данных для интеграции с "Региональная витрина данных"."""
19
17
 
20
18
  def _prepare_helper_class(self) -> type[BaseExportDataRunnerHelper]:
21
- """
22
- Возвращает класс помощника ранера функции.
23
- """
19
+ """Возвращает класс помощника ранера функции."""
24
20
  return BaseExportDataRunnerHelper
25
21
 
26
22
  def _prepare_validator_class(self) -> type[BaseExportDataRunnerValidator]:
27
- """
28
- Возвращает класс валидатора ранера функции.
29
- """
23
+ """Возвращает класс валидатора ранера функции."""
30
24
  return BaseExportDataRunnerValidator
31
25
 
32
26
  def _prepare_result_class(self) -> type[BaseExportDataRunnerResult]:
33
- """
34
- Возвращает класс результата ранера функции.
35
- """
27
+ """Возвращает класс результата ранера функции."""
36
28
  return BaseExportDataRunnerResult
37
29
 
38
30
  def _prepare_model_ids_chunks(self, *args, model_ids_map=None, **kwargs):
39
- """
40
- Формирование чанков идентификаторов записей моделей для дальнейшей работы в рамках функций.
41
- """
31
+ """Формирование чанков идентификаторов записей моделей для дальнейшей работы в рамках функций."""
42
32
  # model_ids_chunks = make_chunks(
43
33
  # iterable=model_ids,
44
34
  # size=settings.RDM_EXPORT_CHUNK_SIZE,
@@ -47,9 +37,7 @@ class BaseExportDataRunner(WebEduRunner):
47
37
  return ()
48
38
 
49
39
  def _get_runnable_objects(self, *args, **kwargs):
50
- """
51
- Возвращает генератор запускаемых объектов.
52
- """
40
+ """Возвращает генератор запускаемых объектов."""
53
41
  model_ids_chunks = self._prepare_model_ids_chunks(*args, **kwargs)
54
42
 
55
43
  for chunk_index, model_ids_chunk in enumerate(model_ids_chunks, start=1):
@@ -0,0 +1,20 @@
1
+ from edu_rdm_integration.adapters.validators import (
2
+ WebEduFunctionValidator,
3
+ WebEduRunnerValidator,
4
+ )
5
+
6
+
7
+ class BaseExportDataRunnerValidator(WebEduRunnerValidator):
8
+ """Базовый класс валидаторов ранеров функций выгрузки данных для интеграции с "Региональная витрина данных"."""
9
+
10
+ def validate(self, runnable):
11
+ """Выполнение валидации."""
12
+ super().validate(runnable=runnable)
13
+
14
+
15
+ class BaseExportDataFunctionValidator(WebEduFunctionValidator):
16
+ """Базовый класс валидаторов функций выгрузки данных для интеграции с "Региональная витрина данных"."""
17
+
18
+ def validate(self, runnable):
19
+ """Выполнение валидации."""
20
+ super().validate(runnable=runnable)
@@ -16,10 +16,11 @@ from m3_db_utils.models import (
16
16
  ModelEnumValue,
17
17
  )
18
18
 
19
- from edu_rdm_integration import (
20
- consts,
19
+ from edu_rdm_integration.core.consts import (
20
+ BATCH_SIZE,
21
+ DATE_FORMAT,
21
22
  )
22
- from edu_rdm_integration.models import (
23
+ from edu_rdm_integration.rdm_entities.models import (
23
24
  RegionalDataMartEntityEnum,
24
25
  )
25
26
 
@@ -32,7 +33,7 @@ class BaseFirstExportEntitiesDataCommandsGenerator:
32
33
  entities: Iterable[str],
33
34
  period_started_at=datetime.combine(date.today(), time.min),
34
35
  period_ended_at=datetime.combine(date.today(), time.min),
35
- batch_size=consts.BATCH_SIZE,
36
+ batch_size=BATCH_SIZE,
36
37
  **kwargs,
37
38
  ):
38
39
  """Инициализация."""
@@ -87,8 +88,8 @@ class BaseFirstExportEntitiesDataCommandsGenerator:
87
88
  for entity in self.entities:
88
89
  ordered_rows_queries_sql = self.ordered_rows_query.format(
89
90
  table_name=entity.main_model_enum.model._meta.db_table,
90
- period_started_at=self.period_started_at.strftime(consts.DATE_FORMAT),
91
- period_ended_at=self.period_ended_at.strftime(consts.DATE_FORMAT),
91
+ period_started_at=self.period_started_at.strftime(DATE_FORMAT),
92
+ period_ended_at=self.period_ended_at.strftime(DATE_FORMAT),
92
93
  )
93
94
 
94
95
  temp_get_logs_periods_sql = self.get_logs_periods_sql.format(
@@ -0,0 +1,203 @@
1
+ import os
2
+ from datetime import (
3
+ date,
4
+ datetime,
5
+ time,
6
+ timedelta,
7
+ )
8
+ from typing import (
9
+ TYPE_CHECKING,
10
+ Iterable,
11
+ Union,
12
+ )
13
+
14
+ from django.conf import (
15
+ settings,
16
+ )
17
+ from django.db.models import (
18
+ CharField,
19
+ OuterRef,
20
+ Subquery,
21
+ Value,
22
+ )
23
+ from django.db.models.functions import (
24
+ Cast,
25
+ Coalesce,
26
+ Least,
27
+ )
28
+ from django.db.transaction import (
29
+ atomic,
30
+ )
31
+
32
+ from educommon import (
33
+ logger,
34
+ )
35
+
36
+ from edu_rdm_integration.apps import (
37
+ EduRDMIntegrationConfig,
38
+ )
39
+
40
+
41
+ if TYPE_CHECKING:
42
+ from typing import (
43
+ NamedTuple,
44
+ )
45
+
46
+ from django.db.models import (
47
+ Model,
48
+ )
49
+
50
+ from edu_rdm_integration.rdm_models.models import (
51
+ BaseEntityModel,
52
+ )
53
+ from edu_rdm_integration.stages.export_data.functions.base.managers import (
54
+ BaseExportDataRunnerManager,
55
+ )
56
+
57
+
58
+ @atomic
59
+ def set_failed_status_suspended_exporting_data_stages() -> dict[str, int]:
60
+ """Установить статус 'Завершено с ошибками' для зависших этапов и подэтапов экспорта.
61
+
62
+ Экспорт считается зависшим в случае если за определенное в параметре RDM_CHECK_SUSPEND_TASK_STAGE_TIMEOUT время,
63
+ отсутствуют изменения в связанных подэтапах. Параметр RDM_CHECK_SUSPEND_TASK_STAGE_TIMEOUT определяется
64
+ в настройках приложения.
65
+ """
66
+ from edu_rdm_integration.stages.export_data.models import (
67
+ ExportingDataStage,
68
+ ExportingDataStageStatus,
69
+ ExportingDataSubStage,
70
+ ExportingDataSubStageStatus,
71
+ )
72
+
73
+ changed_status_result = {
74
+ 'change_stage_count': 0,
75
+ 'change_sub_stage_count': 0,
76
+ }
77
+
78
+ current_datetime = datetime.now()
79
+ suspended_time_at = current_datetime - timedelta(minutes=settings.RDM_CHECK_SUSPEND_TASK_STAGE_TIMEOUT)
80
+
81
+ suspended_stage_ids = set(
82
+ ExportingDataStage.objects.annotate(
83
+ last_sub_stage_started_at=Coalesce(
84
+ Subquery(
85
+ ExportingDataSubStage.objects.filter(stage_id=OuterRef('pk'))
86
+ .values('started_at')
87
+ .order_by('-started_at')[:1]
88
+ ),
89
+ Value(datetime.combine(date.min, time.min)),
90
+ )
91
+ )
92
+ .filter(
93
+ last_sub_stage_started_at__lt=suspended_time_at,
94
+ status__in=(
95
+ ExportingDataStageStatus.CREATED.key,
96
+ ExportingDataStageStatus.IN_PROGRESS.key,
97
+ ),
98
+ )
99
+ .values_list('pk', flat=True)
100
+ )
101
+
102
+ if suspended_stage_ids:
103
+ logger.info(f'find suspended ExportingDataStage: {", ".join(map(str, suspended_stage_ids))}..')
104
+
105
+ change_stage_count = ExportingDataStage.objects.filter(
106
+ pk__in=suspended_stage_ids,
107
+ ).update(
108
+ status=ExportingDataStageStatus.FAILED.key,
109
+ ended_at=current_datetime,
110
+ )
111
+
112
+ change_sub_stage_count = ExportingDataSubStage.objects.filter(
113
+ stage_id__in=suspended_stage_ids,
114
+ ).update(
115
+ status=ExportingDataSubStageStatus.FAILED.key,
116
+ ended_at=current_datetime,
117
+ )
118
+
119
+ changed_status_result.update(
120
+ {
121
+ 'change_stage_count': change_stage_count,
122
+ 'change_sub_stage_count': change_sub_stage_count,
123
+ }
124
+ )
125
+
126
+ return changed_status_result
127
+
128
+
129
+ def get_exporting_managers_max_period_ended_dates(
130
+ exporting_managers: Iterable['BaseExportDataRunnerManager'],
131
+ ) -> dict[str, 'datetime']:
132
+ """Возвращает дату и время последнего успешного этапа экспорта для менеджеров Функций экспорта."""
133
+ from edu_rdm_integration.stages.export_data.models import (
134
+ ExportingDataStage,
135
+ ExportingDataStageStatus,
136
+ )
137
+
138
+ managers_last_period_ended = (
139
+ ExportingDataStage.objects.filter(
140
+ manager_id__in=[manager.uuid for manager in exporting_managers],
141
+ id=Subquery(
142
+ ExportingDataStage.objects.filter(
143
+ manager_id=OuterRef('manager_id'),
144
+ status_id=ExportingDataStageStatus.FINISHED.key,
145
+ )
146
+ .order_by('-id')
147
+ .values('id')[:1]
148
+ ),
149
+ )
150
+ .annotate(
151
+ str_manager_id=Cast('manager_id', output_field=CharField()),
152
+ last_period_ended_at=Least('period_ended_at', 'started_at'),
153
+ )
154
+ .values_list(
155
+ 'str_manager_id',
156
+ 'last_period_ended_at',
157
+ )
158
+ )
159
+
160
+ return {manager_id: last_period_ended_at for manager_id, last_period_ended_at in managers_last_period_ended}
161
+
162
+
163
+ def get_exporting_data_stage_attachment_path(instance, filename):
164
+ """Возвращает путь до файла-вложения в этап выгрузки данных сущности.
165
+
166
+ Args:
167
+ instance: объект ExportingDataStage
168
+ filename: имя загружаемого файла
169
+
170
+ Returns:
171
+ Строковое представление пути
172
+ """
173
+ datetime_now = datetime.now()
174
+
175
+ return os.path.join(
176
+ settings.UPLOADS,
177
+ EduRDMIntegrationConfig.label,
178
+ datetime_now.strftime('%Y/%m/%d'),
179
+ instance.exporting_data_sub_stage.__class__.__name__.lower(),
180
+ str(instance.exporting_data_sub_stage_id),
181
+ str(instance.operation),
182
+ filename,
183
+ )
184
+
185
+
186
+ def set_entity_field_by_model_object(
187
+ entity: 'BaseEntityModel', model_object: Union['Model', 'NamedTuple'], mapping: dict[str, str]
188
+ ) -> None:
189
+ """Обновление значений полей сущности по измененным полям модели.
190
+
191
+ Args:
192
+ entity: Выгружаемая сущность;
193
+ model_object: Объект модели с измененными полями;
194
+ mapping: Словарь маппинга полей модели к полям сущности
195
+ """
196
+ for model_field, entity_field in mapping.items():
197
+ if hasattr(model_object, model_field):
198
+ setattr(entity, entity_field, getattr(model_object, model_field))
199
+
200
+
201
+ def get_isoformat_timezone():
202
+ """Возвращает временную зонну в ISO представлении."""
203
+ return datetime.now().astimezone().isoformat()[-6:]