edu-rdm-integration 0.4.3__py3-none-any.whl → 0.4.5__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.
- edu_rdm_integration/collect_data/base/caches.py +26 -0
- edu_rdm_integration/collect_data/base/mixins.py +78 -0
- edu_rdm_integration/collect_data/calculated/base/caches.py +9 -8
- edu_rdm_integration/collect_data/non_calculated/base/caches.py +16 -3
- edu_rdm_integration/export_data/export.py +2 -1
- {edu_rdm_integration-0.4.3.dist-info → edu_rdm_integration-0.4.5.dist-info}/METADATA +26 -1
- {edu_rdm_integration-0.4.3.dist-info → edu_rdm_integration-0.4.5.dist-info}/RECORD +11 -10
- {edu_rdm_integration-0.4.3.dist-info → edu_rdm_integration-0.4.5.dist-info}/LICENSE +0 -0
- {edu_rdm_integration-0.4.3.dist-info → edu_rdm_integration-0.4.5.dist-info}/WHEEL +0 -0
- {edu_rdm_integration-0.4.3.dist-info → edu_rdm_integration-0.4.5.dist-info}/namespace_packages.txt +0 -0
- {edu_rdm_integration-0.4.3.dist-info → edu_rdm_integration-0.4.5.dist-info}/top_level.txt +0 -0
@@ -2,12 +2,16 @@ from typing import (
|
|
2
2
|
Any,
|
3
3
|
Dict,
|
4
4
|
Optional,
|
5
|
+
NamedTuple,
|
5
6
|
)
|
6
7
|
|
7
8
|
from edu_rdm_integration.adapters.caches import (
|
8
9
|
WebEduEntityCache,
|
9
10
|
)
|
10
11
|
|
12
|
+
from educommon.integration_entities.enums import (
|
13
|
+
EntityLogOperation,
|
14
|
+
)
|
11
15
|
|
12
16
|
class WebEduEntityCacheExtended(WebEduEntityCache):
|
13
17
|
"""
|
@@ -43,3 +47,25 @@ class WebEduEntityCacheExtended(WebEduEntityCache):
|
|
43
47
|
self._entities = self._entities.only(*self._only_fields)
|
44
48
|
|
45
49
|
self._entities = self._entities.distinct()
|
50
|
+
|
51
|
+
|
52
|
+
class LogChange(NamedTuple):
|
53
|
+
"""Операция и значения измененных полей из лога."""
|
54
|
+
|
55
|
+
operation: EntityLogOperation
|
56
|
+
fields: Dict[str, Any]
|
57
|
+
|
58
|
+
@property
|
59
|
+
def is_create(self) -> bool:
|
60
|
+
"""Лог создания."""
|
61
|
+
return self.operation == EntityLogOperation.CREATE
|
62
|
+
|
63
|
+
@property
|
64
|
+
def is_update(self) -> bool:
|
65
|
+
"""Лог изменения."""
|
66
|
+
return self.operation == EntityLogOperation.UPDATE
|
67
|
+
|
68
|
+
@property
|
69
|
+
def is_delete(self) -> bool:
|
70
|
+
"""Лог удаления."""
|
71
|
+
return self.operation == EntityLogOperation.DELETE
|
@@ -0,0 +1,78 @@
|
|
1
|
+
from edu_rdm_integration.collect_data.base.caches import (
|
2
|
+
LogChange,
|
3
|
+
)
|
4
|
+
from edu_rdm_integration.mapping import (
|
5
|
+
MODEL_FIELDS_LOG_FILTER,
|
6
|
+
)
|
7
|
+
|
8
|
+
from educommon.audit_log.utils import (
|
9
|
+
get_model_by_table,
|
10
|
+
)
|
11
|
+
from educommon.integration_entities.consts import (
|
12
|
+
LOG_OPERATION_MAP,
|
13
|
+
)
|
14
|
+
from educommon.integration_entities.enums import (
|
15
|
+
EntityLogOperation,
|
16
|
+
)
|
17
|
+
|
18
|
+
|
19
|
+
class ReformatLogsMixin:
|
20
|
+
"""Миксин для преобразования логов к удобному для работы виду в кешах помощников функций."""
|
21
|
+
|
22
|
+
def _reformat_logs(self):
|
23
|
+
"""
|
24
|
+
Производится преобразование логов к удобному для работы виду.
|
25
|
+
|
26
|
+
Предполагается вложенные словари. На первом уровне ключом будет название
|
27
|
+
модели, на втором идентификатор записи.
|
28
|
+
"""
|
29
|
+
for log in self.raw_logs:
|
30
|
+
model = get_model_by_table(log.table)._meta.label
|
31
|
+
|
32
|
+
if getattr(self, '_log_only_models', None) and (model not in self._log_only_models):
|
33
|
+
# Пропускаем, если модель не входит в список отслеживаемых
|
34
|
+
continue
|
35
|
+
|
36
|
+
operation = LOG_OPERATION_MAP[log.operation]
|
37
|
+
|
38
|
+
if operation in EntityLogOperation.values:
|
39
|
+
fields = log.data
|
40
|
+
else:
|
41
|
+
fields = {}
|
42
|
+
|
43
|
+
log_change = LogChange(
|
44
|
+
operation=operation,
|
45
|
+
fields=fields,
|
46
|
+
)
|
47
|
+
|
48
|
+
if not self._filter_log(model, log_change):
|
49
|
+
# Если модель не отслеживается, то запись лога не сохраняем
|
50
|
+
continue
|
51
|
+
|
52
|
+
if log_change.operation == EntityLogOperation.DELETE:
|
53
|
+
self.logs[model][log.object_id] = [log_change, ]
|
54
|
+
else:
|
55
|
+
self.logs[model][log.object_id].append(log_change)
|
56
|
+
|
57
|
+
@staticmethod
|
58
|
+
def _filter_log(model: str, log_change: LogChange) -> bool:
|
59
|
+
"""
|
60
|
+
Производится проверка изменений на отслеживаемые поля.
|
61
|
+
"""
|
62
|
+
is_filtered = False
|
63
|
+
|
64
|
+
if model in MODEL_FIELDS_LOG_FILTER[log_change.operation]:
|
65
|
+
filter_fields = MODEL_FIELDS_LOG_FILTER[log_change.operation][model]
|
66
|
+
if filter_fields:
|
67
|
+
# Если заданы конкретные поля, которые должны отслеживать
|
68
|
+
for field in log_change.fields:
|
69
|
+
if field in filter_fields:
|
70
|
+
# Достаточно, чтобы хотя бы одно поле попало под фильтр
|
71
|
+
is_filtered = True
|
72
|
+
break
|
73
|
+
else:
|
74
|
+
# Модель отслеживается, но перечень фильтруемых полей не задан,
|
75
|
+
# значит фильтруем все поля модели
|
76
|
+
is_filtered = True
|
77
|
+
|
78
|
+
return is_filtered
|
@@ -28,6 +28,13 @@ from edu_rdm_integration.adapters.caches import (
|
|
28
28
|
from edu_rdm_integration.collect_data.calculated.base.consts import (
|
29
29
|
LOOKUP_SEP,
|
30
30
|
)
|
31
|
+
from educommon.utils.conversion import (
|
32
|
+
int_or_none,
|
33
|
+
)
|
34
|
+
|
35
|
+
from edu_rdm_integration.collect_data.base.mixins import (
|
36
|
+
ReformatLogsMixin,
|
37
|
+
)
|
31
38
|
|
32
39
|
|
33
40
|
class BaseCollectingCalculatedExportedDataRunnerCacheStorage(WebEduRunnerCacheStorage):
|
@@ -36,7 +43,7 @@ class BaseCollectingCalculatedExportedDataRunnerCacheStorage(WebEduRunnerCacheSt
|
|
36
43
|
"""
|
37
44
|
|
38
45
|
|
39
|
-
class BaseCollectingCalculatedExportedDataFunctionCacheStorage(WebEduFunctionCacheStorage):
|
46
|
+
class BaseCollectingCalculatedExportedDataFunctionCacheStorage(ReformatLogsMixin, WebEduFunctionCacheStorage):
|
40
47
|
"""
|
41
48
|
Базовый кеш помощников функций сбора расчетных данных для интеграции с "Региональная витрина данных".
|
42
49
|
"""
|
@@ -60,13 +67,7 @@ class BaseCollectingCalculatedExportedDataFunctionCacheStorage(WebEduFunctionCac
|
|
60
67
|
# }
|
61
68
|
self.logs = defaultdict(lambda: defaultdict(list))
|
62
69
|
|
63
|
-
|
64
|
-
"""
|
65
|
-
Производится преобразование логов к удобному для работы виду.
|
66
|
-
|
67
|
-
Предполагается вложенные словари. На первом уровне ключом будет название
|
68
|
-
модели, на втором идентификатор записи.
|
69
|
-
"""
|
70
|
+
self._prepare_logs()
|
70
71
|
|
71
72
|
def _prepare_logs(self):
|
72
73
|
"""
|
@@ -67,7 +67,7 @@ class BaseCollectingExportedDataFunctionCacheStorage(WebEduFunctionCacheStorage)
|
|
67
67
|
Базовый кеш помощников функций сбора данных для интеграции с "Региональная витрина данных".
|
68
68
|
"""
|
69
69
|
|
70
|
-
def __init__(self, raw_logs, *args, **kwargs):
|
70
|
+
def __init__(self, raw_logs, is_merge_logs=False, *args, **kwargs):
|
71
71
|
super().__init__(*args, **kwargs)
|
72
72
|
|
73
73
|
# Необработанные логи как есть.
|
@@ -75,7 +75,7 @@ class BaseCollectingExportedDataFunctionCacheStorage(WebEduFunctionCacheStorage)
|
|
75
75
|
|
76
76
|
# TODO Перенести в базовый класс (https://jira.bars.group/browse/EDUSCHL-19991)
|
77
77
|
# Необходимость объединения логов относящихся к одному объекту
|
78
|
-
self.is_merge_logs =
|
78
|
+
self.is_merge_logs = is_merge_logs
|
79
79
|
|
80
80
|
# Подготовленные логи в виде:
|
81
81
|
# {
|
@@ -149,7 +149,20 @@ class BaseCollectingExportedDataFunctionCacheStorage(WebEduFunctionCacheStorage)
|
|
149
149
|
if log_change.operation == EntityLogOperation.DELETE:
|
150
150
|
self.logs[model][log.object_id] = [log_change, ]
|
151
151
|
else:
|
152
|
-
self.
|
152
|
+
if self.is_merge_logs:
|
153
|
+
self._merge_logs(self.logs[model][log.object_id], log_change)
|
154
|
+
else:
|
155
|
+
self.logs[model][log.object_id].append(log_change)
|
156
|
+
|
157
|
+
@staticmethod
|
158
|
+
def _merge_logs(log_changes: List[LogChange], log_change: LogChange):
|
159
|
+
"""
|
160
|
+
Производит объединение (накопление) изменений полей в рамках одного объекта.
|
161
|
+
"""
|
162
|
+
if log_changes:
|
163
|
+
log_changes[0].fields.update(log_change.fields)
|
164
|
+
else:
|
165
|
+
log_changes.append(log_change)
|
153
166
|
|
154
167
|
def _prepare_logs(self):
|
155
168
|
"""
|
@@ -5,6 +5,7 @@ from datetime import (
|
|
5
5
|
date,
|
6
6
|
datetime,
|
7
7
|
time,
|
8
|
+
timedelta,
|
8
9
|
)
|
9
10
|
from typing import (
|
10
11
|
Dict,
|
@@ -295,7 +296,7 @@ class BaseExportLatestEntitiesData(BaseExportEntitiesData):
|
|
295
296
|
kwargs['period_ended_at'] = timezone.now()
|
296
297
|
|
297
298
|
if kwargs['period_started_at'] > kwargs['period_ended_at']:
|
298
|
-
kwargs['period_started_at'] = kwargs['period_ended_at'] -
|
299
|
+
kwargs['period_started_at'] = kwargs['period_ended_at'] - timedelta(
|
299
300
|
seconds=settings.RDM_TRANSFER_TASK_TIMEDELTA
|
300
301
|
)
|
301
302
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: edu-rdm-integration
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.5
|
4
4
|
Summary: Интеграция с Региональной витриной данных
|
5
5
|
Home-page:
|
6
6
|
Download-URL:
|
@@ -215,6 +215,31 @@ ENABLE_REQUEST_EMULATION = True
|
|
215
215
|
|
216
216
|
### Исправлено
|
217
217
|
|
218
|
+
## [0.4.5] - 2023-08-09
|
219
|
+
|
220
|
+
Объединение обрабатываемых логов относящихся к одному объекту
|
221
|
+
|
222
|
+
### Добавлено
|
223
|
+
|
224
|
+
- [EDUSCHL-19991](https://jira.bars.group/browse/EDUSCHL-19991)
|
225
|
+
PATCH Новый миксин ```ReformatLogsMixin``` , новое поле is_merge_logs и новый метод _merge_logs у класса ```BaseCollectingExportedDataFunctionCacheStorage```
|
226
|
+
|
227
|
+
### Изменено
|
228
|
+
|
229
|
+
### Исправлено
|
230
|
+
|
231
|
+
## [0.4.4] - 2023-08-12
|
232
|
+
|
233
|
+
Исправлен баг с timedelta
|
234
|
+
|
235
|
+
### Добавлено
|
236
|
+
|
237
|
+
### Изменено
|
238
|
+
|
239
|
+
### Исправлено
|
240
|
+
- [EDUSCHL-20200](https://jira.bars.group/browse/EDUSCHL-20200)
|
241
|
+
PATCH Исправлен баг с timedelta.
|
242
|
+
|
218
243
|
|
219
244
|
## [0.4.3] - 2023-08-12
|
220
245
|
|
@@ -30,14 +30,15 @@ edu_rdm_integration/collect_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRk
|
|
30
30
|
edu_rdm_integration/collect_data/collect.py,sha256=4aeIb44l6u-RYcIDGU1c840GZ0nNFAb6l5e0gGdFuhQ,14739
|
31
31
|
edu_rdm_integration/collect_data/generators.py,sha256=GJpOWDp1jeQQPI4Zx4w0BxaAaGu6S3ow63UMEfvcFl0,8974
|
32
32
|
edu_rdm_integration/collect_data/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
|
-
edu_rdm_integration/collect_data/base/caches.py,sha256=
|
33
|
+
edu_rdm_integration/collect_data/base/caches.py,sha256=vOfYoWfFdYbhnOwmeEdOB_ErieQrMlORXqojVCiGKrA,2029
|
34
34
|
edu_rdm_integration/collect_data/base/functions.py,sha256=0vAOx4lrEbBOxFbeCl_wB7imfYq1EgqwTvmqUbrXgT4,2403
|
35
35
|
edu_rdm_integration/collect_data/base/managers.py,sha256=UkiFhyD3Gn3drErXc0NjQkSyPan10BkQp-yx-2vc_AM,6067
|
36
|
+
edu_rdm_integration/collect_data/base/mixins.py,sha256=vgWCsSgjtUjvu-fMBByEq6xbIocjzjmdNzhMs5DRKVI,3180
|
36
37
|
edu_rdm_integration/collect_data/base/runners.py,sha256=mqrdVUMud7ss-0Iufj3DHEdy7BDHgbkZ7ZEGJfUaslc,2835
|
37
38
|
edu_rdm_integration/collect_data/calculated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
39
|
edu_rdm_integration/collect_data/calculated/strategies.py,sha256=S-a6DA8E0CTMOxLg9Xk_7c3ZbN-ngmaNnKycoJnCLTs,7621
|
39
40
|
edu_rdm_integration/collect_data/calculated/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
40
|
-
edu_rdm_integration/collect_data/calculated/base/caches.py,sha256=
|
41
|
+
edu_rdm_integration/collect_data/calculated/base/caches.py,sha256=O4VrWmOs6Wpooo9wkZliPM-YyaYwSsG1XXPBR_LFGpk,7564
|
41
42
|
edu_rdm_integration/collect_data/calculated/base/consts.py,sha256=DsgPOF_2iCzZTPity27oDDkpS6Axdhd5C94uSkIwA1g,84
|
42
43
|
edu_rdm_integration/collect_data/calculated/base/enums.py,sha256=BSmwrkzYwEQhz9NbZCJsldY532PqgZJzxzsVk6ue0bM,93
|
43
44
|
edu_rdm_integration/collect_data/calculated/base/errors.py,sha256=bDVjmB43pZJ2C8sNnqF177qMB4l_XskDpVTFqTmxjj8,326
|
@@ -53,7 +54,7 @@ edu_rdm_integration/collect_data/calculated/base/validators.py,sha256=xIaSIE9oKb
|
|
53
54
|
edu_rdm_integration/collect_data/non_calculated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
54
55
|
edu_rdm_integration/collect_data/non_calculated/strategies.py,sha256=5mC1g1ynjvGX2wRBJ2MPHo8DfaxbEiBd4H_k65IQvT8,7423
|
55
56
|
edu_rdm_integration/collect_data/non_calculated/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
56
|
-
edu_rdm_integration/collect_data/non_calculated/base/caches.py,sha256=
|
57
|
+
edu_rdm_integration/collect_data/non_calculated/base/caches.py,sha256=qRC92vy-oUcyokAF279CcZgWTl_x-PxsGAK-5Rb31-g,6821
|
57
58
|
edu_rdm_integration/collect_data/non_calculated/base/consts.py,sha256=pds1t4eHzovm7Yz2o5je3UHqRE8gqfT2sL-IwpoBN_o,66
|
58
59
|
edu_rdm_integration/collect_data/non_calculated/base/enums.py,sha256=BSmwrkzYwEQhz9NbZCJsldY532PqgZJzxzsVk6ue0bM,93
|
59
60
|
edu_rdm_integration/collect_data/non_calculated/base/errors.py,sha256=dGawEQ2ItTxlFt9ynhYhpqx40Qmrlg2rOskH0DsNVnQ,297
|
@@ -68,7 +69,7 @@ edu_rdm_integration/collect_data/non_calculated/base/tests.py,sha256=MoRY-a75Ow-
|
|
68
69
|
edu_rdm_integration/collect_data/non_calculated/base/validators.py,sha256=0YvnfrfK1iFcZVSB-M-Xv82tIjYxEU_BwLofAEuGVW4,973
|
69
70
|
edu_rdm_integration/export_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
70
71
|
edu_rdm_integration/export_data/consts.py,sha256=Z6Uho8oViMc0t1tyQFZfrPFBwPx6KnhUf_iZ0qgob8o,16
|
71
|
-
edu_rdm_integration/export_data/export.py,sha256=
|
72
|
+
edu_rdm_integration/export_data/export.py,sha256=YGO2Uw_TpHW_Hl3Lp-IBfIdwWEjmJ8RvlR5i_Vve2Yc,12399
|
72
73
|
edu_rdm_integration/export_data/generators.py,sha256=huonSRK5arfBzU09BnLAHC7AsSFYU0sCz5utCtejdJk,3950
|
73
74
|
edu_rdm_integration/export_data/strategies.py,sha256=NcI2VsDfAmm9k-Nul6LZkSxruCmo7B-XH7wzgW6-vfE,6718
|
74
75
|
edu_rdm_integration/export_data/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -94,9 +95,9 @@ edu_rdm_integration/management/commands/export_entities_data.py,sha256=Mas1zwsH-
|
|
94
95
|
edu_rdm_integration/migrations/0001_initial.py,sha256=toNuYoHZePe5wJ6AKEW9oPOdt2OefmxDEDDJGYQIrFk,18719
|
95
96
|
edu_rdm_integration/migrations/0002_init_data_uploadstatus.py,sha256=kht966YNuDbC3qTGrcWswJPsVuAtNO59Ck15G2eS2bU,944
|
96
97
|
edu_rdm_integration/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
97
|
-
edu_rdm_integration-0.4.
|
98
|
-
edu_rdm_integration-0.4.
|
99
|
-
edu_rdm_integration-0.4.
|
100
|
-
edu_rdm_integration-0.4.
|
101
|
-
edu_rdm_integration-0.4.
|
102
|
-
edu_rdm_integration-0.4.
|
98
|
+
edu_rdm_integration-0.4.5.dist-info/LICENSE,sha256=uw43Gjjj-1vXWCItfSrNDpbejnOwZMrNerUh8oWbq8Q,3458
|
99
|
+
edu_rdm_integration-0.4.5.dist-info/METADATA,sha256=PuPYKD0jJOwTcWTw33-_Yy44YL_tX0Jzr2J5fJ5JI-Y,22468
|
100
|
+
edu_rdm_integration-0.4.5.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
101
|
+
edu_rdm_integration-0.4.5.dist-info/namespace_packages.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
102
|
+
edu_rdm_integration-0.4.5.dist-info/top_level.txt,sha256=nRJV0O14UtNE-jGIYG03sohgFnZClvf57H5m6VBXe9Y,20
|
103
|
+
edu_rdm_integration-0.4.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{edu_rdm_integration-0.4.3.dist-info → edu_rdm_integration-0.4.5.dist-info}/namespace_packages.txt
RENAMED
File without changes
|
File without changes
|