educommon 3.12.0__py3-none-any.whl → 3.13.2__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.
- educommon/__init__.py +0 -1
- educommon/about/ui/actions.py +16 -30
- educommon/about/ui/ui.py +3 -12
- educommon/about/utils.py +6 -5
- educommon/async_task/__init__.py +0 -1
- educommon/async_task/actions.py +18 -13
- educommon/async_task/apps.py +4 -0
- educommon/async_task/locker.py +2 -5
- educommon/async_task/migrations/0001_initial.py +55 -9
- educommon/async_task/migrations/0002_task_type_and_status_data.py +94 -89
- educommon/async_task/migrations/0003_alter_runningtask_options.py +0 -1
- educommon/async_task/models.py +9 -6
- educommon/async_task/tasks.py +11 -7
- educommon/async_task/ui.py +16 -35
- educommon/async_tasks/__init__.py +0 -1
- educommon/async_tasks/apps.py +4 -0
- educommon/async_tasks/locks.py +11 -21
- educommon/async_tasks/migrations/0001_initial.py +68 -8
- educommon/async_tasks/migrations/0002_load_initial_data.py +0 -1
- educommon/async_tasks/models.py +9 -29
- educommon/async_tasks/tasks.py +25 -54
- educommon/audit_log/__init__.py +1 -0
- educommon/audit_log/actions.py +27 -36
- educommon/audit_log/app_meta.py +7 -4
- educommon/audit_log/apps.py +44 -29
- educommon/audit_log/constants.py +7 -4
- educommon/audit_log/error_log/actions.py +1 -3
- educommon/audit_log/helpers.py +2 -4
- educommon/audit_log/management/commands/reinstall_audit_log.py +11 -7
- educommon/audit_log/migrations/0001_initial.py +91 -16
- educommon/audit_log/migrations/0002_install_audit_log.py +13 -13
- educommon/audit_log/migrations/0003_logproxy.py +1 -3
- educommon/audit_log/migrations/0004_reinstall_audit_log.py +1 -4
- educommon/audit_log/migrations/0005_postgresql_error.py +4 -2
- educommon/audit_log/migrations/0006_auto_20200806_1707.py +3 -4
- educommon/audit_log/migrations/0007_create_selective_tables_function.py +8 -5
- educommon/audit_log/migrations/0008_table_logged.py +0 -1
- educommon/audit_log/migrations/0009_reinstall_audit_log.py +0 -1
- educommon/audit_log/models.py +36 -42
- educommon/audit_log/permissions.py +11 -9
- educommon/audit_log/proxies.py +12 -23
- educommon/audit_log/ui.py +18 -15
- educommon/audit_log/utils/__init__.py +28 -60
- educommon/audit_log/utils/operations.py +16 -2
- educommon/auth/__init__.py +0 -3
- educommon/auth/rbac/__init__.py +2 -4
- educommon/auth/rbac/actions.py +148 -145
- educommon/auth/rbac/app_meta.py +9 -6
- educommon/auth/rbac/backends/base.py +2 -8
- educommon/auth/rbac/backends/caching.py +27 -37
- educommon/auth/rbac/backends/simple.py +1 -4
- educommon/auth/rbac/checker.py +1 -3
- educommon/auth/rbac/management/commands/rbac.py +6 -11
- educommon/auth/rbac/manager.py +18 -47
- educommon/auth/rbac/migrations/0001_initial.py +73 -12
- educommon/auth/rbac/migrations/0002_model_modifier_metaclass_fix.py +7 -6
- educommon/auth/rbac/migrations/0003_permission_hidden.py +1 -5
- educommon/auth/rbac/migrations/0004_auto_20171024_1245.py +26 -19
- educommon/auth/rbac/models.py +63 -68
- educommon/auth/rbac/permissions.py +6 -7
- educommon/auth/rbac/ui.py +83 -84
- educommon/auth/rbac/utils.py +10 -11
- educommon/auth/rbac/validators.py +4 -5
- educommon/auth/simple_auth/__init__.py +1 -5
- educommon/auth/simple_auth/actions.py +79 -92
- educommon/auth/simple_auth/app_meta.py +2 -9
- educommon/auth/simple_auth/checkers.py +3 -3
- educommon/auth/simple_auth/migrations/0001_initial.py +23 -4
- educommon/auth/simple_auth/validators.py +0 -1
- educommon/contingent/actions.py +7 -7
- educommon/contingent/app_meta.py +1 -4
- educommon/contingent/base.py +10 -15
- educommon/contingent/catalogs.py +424 -540
- educommon/contingent/contingent_plugin/actions.py +4 -15
- educommon/contingent/contingent_plugin/apps.py +10 -4
- educommon/contingent/contingent_plugin/migrations/0001_initial.py +5 -6
- educommon/contingent/contingent_plugin/migrations/0002_add_contingent_model_deleted.py +6 -11
- educommon/contingent/contingent_plugin/model_views.py +2 -12
- educommon/contingent/contingent_plugin/models.py +2 -7
- educommon/contingent/contingent_plugin/observer.py +14 -13
- educommon/contingent/contingent_plugin/plugin_meta.py +1 -3
- educommon/contingent/contingent_plugin/storage.py +8 -7
- educommon/contingent/contingent_plugin/utils.py +6 -6
- educommon/django/db/fields.py +72 -86
- educommon/django/db/migration/__init__.py +3 -7
- educommon/django/db/migration/operations.py +29 -51
- educommon/django/db/mixins/__init__.py +16 -10
- educommon/django/db/mixins/date_interval.py +47 -75
- educommon/django/db/mixins/validation.py +26 -26
- educommon/django/db/model_view/__init__.py +18 -22
- educommon/django/db/models.py +9 -8
- educommon/django/db/observer.py +9 -27
- educommon/django/db/partitioning/__init__.py +66 -92
- educommon/django/db/partitioning/management/commands/apply_partitioning.py +3 -13
- educommon/django/db/partitioning/management/commands/clear_table.py +18 -14
- educommon/django/db/partitioning/management/commands/split_table.py +18 -13
- educommon/django/db/routers.py +6 -15
- educommon/django/db/signals.py +149 -2
- educommon/django/db/utils.py +14 -19
- educommon/django/db/validators/__init__.py +1 -0
- educommon/django/db/validators/simple.py +72 -100
- educommon/django/storages/atcfs/api.py +39 -53
- educommon/django/storages/atcfs/app_meta.py +1 -1
- educommon/django/storages/atcfs/management/commands/atcfs_migrate.py +42 -55
- educommon/django/storages/atcfs/models.py +0 -3
- educommon/django/storages/atcfs/monkey_patching.py +18 -12
- educommon/django/storages/atcfs/storage.py +14 -23
- educommon/extjs/fields/input_params.py +15 -45
- educommon/importer/XLSReader.py +143 -241
- educommon/importer/__init__.py +86 -4
- educommon/importer/api.py +53 -84
- educommon/importer/constants.py +4 -14
- educommon/importer/loggers.py +16 -26
- educommon/importer/proxy.py +131 -176
- educommon/importer/proxy_import.py +11 -12
- educommon/importer/report.py +4 -6
- educommon/importer/ui.py +32 -26
- educommon/importer/validators.py +4 -7
- educommon/integration_entities/helpers.py +14 -18
- educommon/ioc/__init__.py +3 -6
- educommon/logger/loggers.py +10 -14
- educommon/m3/__init__.py +20 -38
- educommon/m3/extensions/__init__.py +1 -0
- educommon/m3/extensions/listeners/__init__.py +22 -38
- educommon/m3/extensions/listeners/delete_check/listeners.py +31 -41
- educommon/m3/extensions/listeners/delete_check/mixins.py +20 -25
- educommon/m3/extensions/listeners/delete_check/signals.py +2 -2
- educommon/m3/extensions/listeners/delete_check/ui.py +15 -14
- educommon/m3/extensions/listeners/delete_check/utils.py +9 -11
- educommon/m3/extensions/ui.py +15 -33
- educommon/m3/transaction_context.py +17 -19
- educommon/objectpack/actions.py +70 -88
- educommon/objectpack/apps.py +5 -0
- educommon/objectpack/filters.py +9 -15
- educommon/objectpack/ui.py +59 -77
- educommon/report/__init__.py +9 -5
- educommon/report/actions.py +29 -32
- educommon/report/constructor/__init__.py +5 -8
- educommon/report/constructor/app_meta.py +1 -3
- educommon/report/constructor/apps.py +1 -0
- educommon/report/constructor/base.py +33 -80
- educommon/report/constructor/builders/excel/_base.py +138 -286
- educommon/report/constructor/builders/excel/_header.py +2 -9
- educommon/report/constructor/builders/excel/product.py +13 -34
- educommon/report/constructor/builders/excel/with_merged_cells.py +18 -14
- educommon/report/constructor/config.py +2 -0
- educommon/report/constructor/editor/actions.py +101 -215
- educommon/report/constructor/editor/ui.py +71 -93
- educommon/report/constructor/exceptions.py +6 -12
- educommon/report/constructor/migrations/0001_initial.py +36 -44
- educommon/report/constructor/migrations/0002_report_filters.py +86 -72
- educommon/report/constructor/migrations/0003_reportfilter_exclude.py +5 -5
- educommon/report/constructor/migrations/0004_reportfilter_fields.py +22 -18
- educommon/report/constructor/migrations/0005_reportcolumn_visible.py +5 -4
- educommon/report/constructor/migrations/0006_reportsorting.py +21 -17
- educommon/report/constructor/migrations/0007_include_available_units.py +14 -14
- educommon/report/constructor/migrations/0008_auto_20170407_1318.py +4 -5
- educommon/report/constructor/migrations/0009_auto_20180405_0642.py +1 -4
- educommon/report/constructor/migrations/0010_add_aggregate_fields.py +7 -8
- educommon/report/constructor/mixins.py +14 -15
- educommon/report/constructor/models.py +76 -124
- educommon/report/constructor/utils.py +3 -8
- educommon/report/constructor/validators.py +1 -3
- educommon/report/reporter.py +25 -43
- educommon/report/utils.py +14 -40
- educommon/rest/actions.py +7 -11
- educommon/rest/context.py +6 -16
- educommon/rest/controllers.py +10 -10
- educommon/rest/mixins.py +29 -27
- educommon/secure_media/app_meta.py +9 -9
- educommon/utils/__init__.py +3 -2
- educommon/utils/caching.py +1 -3
- educommon/utils/conversion.py +1 -3
- educommon/utils/crypto.py +1 -2
- educommon/utils/date.py +13 -26
- educommon/utils/db/__init__.py +17 -26
- educommon/utils/db/postgresql.py +1 -4
- educommon/utils/fonts/__init__.py +3 -4
- educommon/utils/licence/__init__.py +5 -16
- educommon/utils/misc.py +9 -18
- educommon/utils/object_grid.py +55 -62
- educommon/utils/phone_number/modelfields.py +1 -3
- educommon/utils/phone_number/phone_number.py +5 -8
- educommon/utils/phone_number/validators.py +8 -23
- educommon/utils/plugins.py +15 -28
- educommon/utils/registry.py +2 -1
- educommon/utils/seqtools.py +1 -3
- educommon/utils/serializer.py +9 -16
- educommon/utils/storage.py +3 -2
- educommon/utils/system.py +1 -3
- educommon/utils/system_app/management/commands/delete_objects.py +17 -34
- educommon/utils/ui.py +87 -84
- educommon/utils/xml/__init__.py +2 -7
- educommon/utils/xml/resolver.py +1 -0
- educommon/ws_log/actions.py +31 -76
- educommon/ws_log/base.py +6 -20
- educommon/ws_log/migrations/0001_initial.py +25 -8
- educommon/ws_log/migrations/0002_auto_20160628_1334.py +0 -1
- educommon/ws_log/migrations/0003_add_fields_to_smev_logs.py +20 -4
- educommon/ws_log/migrations/0004_auto_20160727_1600.py +7 -6
- educommon/ws_log/migrations/0005_auto_20161130_1615.py +14 -4
- educommon/ws_log/migrations/0006_auto_20170327_1027.py +3 -2
- educommon/ws_log/migrations/0007_auto_20180607_1040.py +8 -9
- educommon/ws_log/migrations/0008_auto_20180713_1445.py +23 -10
- educommon/ws_log/migrations/0009_auto_20201130_1553.py +7 -2
- educommon/ws_log/models.py +21 -35
- educommon/ws_log/provider.py +2 -1
- educommon/ws_log/report.py +8 -13
- educommon/ws_log/smev/applications.py +12 -27
- educommon/ws_log/smev/exceptions.py +2 -3
- educommon/ws_log/ui.py +32 -32
- educommon/ws_log/utils.py +1 -3
- educommon-3.13.2.dist-info/METADATA +57 -0
- educommon-3.13.2.dist-info/RECORD +354 -0
- {educommon-3.12.0.dist-info → educommon-3.13.2.dist-info}/WHEEL +1 -1
- educommon/utils/patches.py +0 -27
- educommon/version.conf +0 -11
- educommon-3.12.0.dist-info/METADATA +0 -47
- educommon-3.12.0.dist-info/RECORD +0 -357
- educommon-3.12.0.dist-info/dependency_links.txt +0 -1
- {educommon-3.12.0.dist-info → educommon-3.13.2.dist-info}/top_level.txt +0 -0
educommon/objectpack/filters.py
CHANGED
@@ -33,9 +33,7 @@ class ColumnFilterEngine(BaseFilterEngine):
|
|
33
33
|
def configure_grid(self, grid):
|
34
34
|
"""Метод конфигурации грида."""
|
35
35
|
# расширение плагином
|
36
|
-
if not ExtensionManager().execute(
|
37
|
-
'column_filter_engine.configure_grid', self, grid
|
38
|
-
):
|
36
|
+
if not ExtensionManager().execute('column_filter_engine.configure_grid', self, grid):
|
39
37
|
super().configure_grid(grid)
|
40
38
|
|
41
39
|
|
@@ -50,7 +48,7 @@ class ModifiedChoicesFilter(CustomFilter):
|
|
50
48
|
self._choices = choices
|
51
49
|
kwargs['xtype'] = 'combo'
|
52
50
|
|
53
|
-
super(
|
51
|
+
super().__init__(*args, **kwargs)
|
54
52
|
|
55
53
|
def create_control(self):
|
56
54
|
"""Контрол."""
|
@@ -58,6 +56,7 @@ class ModifiedChoicesFilter(CustomFilter):
|
|
58
56
|
choices = self._choices()
|
59
57
|
else:
|
60
58
|
choices = self._choices
|
59
|
+
|
61
60
|
return make_combo_box(data=list(choices))
|
62
61
|
|
63
62
|
def get_control(self):
|
@@ -69,6 +68,7 @@ class ModifiedChoicesFilter(CustomFilter):
|
|
69
68
|
control.allow_blank = True
|
70
69
|
control.hide_clear_trigger = False
|
71
70
|
control.value = None
|
71
|
+
|
72
72
|
return control
|
73
73
|
|
74
74
|
def get_script(self):
|
@@ -87,9 +87,7 @@ class BoolChoicesFilter(ModifiedChoicesFilter):
|
|
87
87
|
"""Формирование lookup для фильтра."""
|
88
88
|
return Q(**{field_name: v}) if v is not None else Q()
|
89
89
|
|
90
|
-
super(
|
91
|
-
*args, choices=choices, parser='boolean', lookup=lookup, **kwargs
|
92
|
-
)
|
90
|
+
super().__init__(*args, choices=choices, parser='boolean', lookup=lookup, **kwargs)
|
93
91
|
|
94
92
|
|
95
93
|
class DateFilter(ColumnFilterWithDefaultValue):
|
@@ -97,10 +95,7 @@ class DateFilter(ColumnFilterWithDefaultValue):
|
|
97
95
|
|
98
96
|
def create_control(self):
|
99
97
|
"""Создание контрола."""
|
100
|
-
return _create_control_for_field(
|
101
|
-
self.field,
|
102
|
-
**self._field_fabric_params
|
103
|
-
)
|
98
|
+
return _create_control_for_field(self.field, **self._field_fabric_params)
|
104
99
|
|
105
100
|
def get_control(self):
|
106
101
|
"""Настройка контрола."""
|
@@ -126,10 +121,7 @@ class DateFilterByAnnotatedField(DateFilter):
|
|
126
121
|
собираются в кварисете через annotate.
|
127
122
|
"""
|
128
123
|
|
129
|
-
def __init__(
|
130
|
-
self, model, field_name, lookup=None, tooltip=None, default_value=None,
|
131
|
-
**field_fabric_params
|
132
|
-
):
|
124
|
+
def __init__(self, model, field_name, lookup=None, tooltip=None, default_value=None, **field_fabric_params):
|
133
125
|
"""Инициализация параметров."""
|
134
126
|
field_name = field_name.replace('.', '__')
|
135
127
|
self._model = model
|
@@ -143,8 +135,10 @@ class DateFilterByAnnotatedField(DateFilter):
|
|
143
135
|
if not callable(lookup) and '%s' in lookup:
|
144
136
|
lookup = lookup % field_name
|
145
137
|
else:
|
138
|
+
|
146
139
|
def lookup(x):
|
147
140
|
return Q(**{field_name: x})
|
141
|
+
|
148
142
|
self._lookup = lookup
|
149
143
|
|
150
144
|
def create_control(self):
|
educommon/objectpack/ui.py
CHANGED
@@ -32,9 +32,7 @@ from educommon.utils.ui import (
|
|
32
32
|
|
33
33
|
|
34
34
|
class GridPanel(ext.ExtPanel):
|
35
|
-
"""
|
36
|
-
Панель, имеющая grid_url, по которому получает грид и вставляет в себя
|
37
|
-
"""
|
35
|
+
"""Панель, имеющая grid_url, по которому получает грид и вставляет в себя."""
|
38
36
|
|
39
37
|
grid_url = None
|
40
38
|
template = 'grid-panel.js'
|
@@ -43,24 +41,21 @@ class GridPanel(ext.ExtPanel):
|
|
43
41
|
def __init__(self, *args, **kwargs):
|
44
42
|
# в инитах затирается темплейт
|
45
43
|
t = self.template
|
46
|
-
|
44
|
+
|
45
|
+
super().__init__(*args, **kwargs)
|
46
|
+
|
47
47
|
self.template = t
|
48
48
|
|
49
49
|
@staticmethod
|
50
50
|
def _create_grid(pack, columns, grid_cls, group_by=None, **kwargs):
|
51
|
-
"""
|
52
|
-
|
51
|
+
"""Метод возвращает грид.
|
52
|
+
|
53
53
|
:param grid_cls: класс грида
|
54
54
|
:type grid_cls: ExtObjectGrid
|
55
55
|
:param str group_by: темплейт для группирования
|
56
56
|
"""
|
57
57
|
grid = grid_cls(
|
58
|
-
region='north',
|
59
|
-
force_fit=False,
|
60
|
-
auto_scroll=True,
|
61
|
-
auto_width=False,
|
62
|
-
cls='word-wrap-grid',
|
63
|
-
**kwargs
|
58
|
+
region='north', force_fit=False, auto_scroll=True, auto_width=False, cls='word-wrap-grid', **kwargs
|
64
59
|
)
|
65
60
|
grid.flex = 1
|
66
61
|
grid.sm = ext.ExtGridCellSelModel()
|
@@ -72,23 +67,17 @@ class GridPanel(ext.ExtPanel):
|
|
72
67
|
# если грид с группирующими строками
|
73
68
|
if group_by:
|
74
69
|
grid.store = ext_store.ExtGroupingStore(
|
75
|
-
url=grid.get_store().url,
|
76
|
-
total_property='total',
|
77
|
-
root='rows',
|
78
|
-
auto_load=True
|
79
|
-
)
|
80
|
-
grid.store.reader = ext_store.ExtJsonReader(
|
81
|
-
total_property='total',
|
82
|
-
root='rows')
|
83
|
-
grid.view = ExtGridGroupingView(
|
84
|
-
group_text_template=group_by,
|
85
|
-
force_fit=grid.force_fit
|
70
|
+
url=grid.get_store().url, total_property='total', root='rows', auto_load=True
|
86
71
|
)
|
72
|
+
grid.store.reader = ext_store.ExtJsonReader(total_property='total', root='rows')
|
73
|
+
grid.view = ExtGridGroupingView(group_text_template=group_by, force_fit=grid.force_fit)
|
87
74
|
|
88
75
|
def configure_reader(col):
|
89
76
|
grid.store.reader.set_fields(col['data_index'])
|
90
77
|
else:
|
91
|
-
|
78
|
+
|
79
|
+
def configure_reader(col):
|
80
|
+
return None
|
92
81
|
|
93
82
|
def populate(root, columns):
|
94
83
|
for c in columns:
|
@@ -123,7 +112,7 @@ class GridPanel(ext.ExtPanel):
|
|
123
112
|
|
124
113
|
@classmethod
|
125
114
|
def configure_grid(cls, grid, params):
|
126
|
-
"""Конфигурирование
|
115
|
+
"""Конфигурирование грида."""
|
127
116
|
|
128
117
|
pack = params['pack']
|
129
118
|
# обычное поведение
|
@@ -138,6 +127,7 @@ class GridPanel(ext.ExtPanel):
|
|
138
127
|
@classmethod
|
139
128
|
def create_grid(cls, pack, columns, **kwargs):
|
140
129
|
grid = cls._create_grid(pack, columns, cls.grid_class, **kwargs)
|
130
|
+
|
141
131
|
return grid
|
142
132
|
|
143
133
|
def pre_render(self):
|
@@ -146,35 +136,30 @@ class GridPanel(ext.ExtPanel):
|
|
146
136
|
|
147
137
|
def render(self):
|
148
138
|
self.pre_render()
|
149
|
-
|
139
|
+
|
140
|
+
self.cmp_code = super().render()
|
141
|
+
|
150
142
|
return render_component(self)
|
151
143
|
|
152
144
|
|
153
145
|
class FilterPanel(ext.ExtPanel):
|
154
|
-
"""
|
155
|
-
Панель, умеющая fireevent'ить об изменении контрола,
|
156
|
-
входящего в список filters
|
157
|
-
"""
|
146
|
+
"""Панель, умеющая fireevent'ить об изменении контрола, входящего в список filters."""
|
158
147
|
|
159
148
|
def __init__(self, *args, **kwargs):
|
160
149
|
super(FilterPanel, self).__init__(*args, **kwargs)
|
150
|
+
|
161
151
|
self.filters = []
|
162
152
|
|
163
153
|
def configure_redirect(self, control, event):
|
154
|
+
"""Связывает текущую панель с контролом control посредством fireevent'а event."""
|
155
|
+
self._listeners['changed'] = f"""
|
156
|
+
function(params) {{
|
157
|
+
Ext.getCmp('{control.client_id}').fireEvent('{event}', params);
|
158
|
+
}}
|
164
159
|
"""
|
165
|
-
Связывает текущую панель с контролом control
|
166
|
-
посредством fireevent'а event
|
167
|
-
"""
|
168
|
-
self._listeners["changed"] = """
|
169
|
-
function(params) {
|
170
|
-
Ext.getCmp('%s').fireEvent('%s', params)
|
171
|
-
}""" % (control.client_id, event)
|
172
160
|
|
173
161
|
def configure_events(self):
|
174
|
-
"""
|
175
|
-
Дополнение рендера fireevent'ом изменения значения контролов,
|
176
|
-
входящих в список filters панели
|
177
|
-
"""
|
162
|
+
"""Дополнение рендера fireevent'ом изменения значения контролов, входящих в список filters панели."""
|
178
163
|
for control in self.filters:
|
179
164
|
# определяется что за контрол и приделываются разные events
|
180
165
|
if isinstance(control, ComboBoxWithStore):
|
@@ -195,25 +180,28 @@ class FilterPanel(ext.ExtPanel):
|
|
195
180
|
def render(self):
|
196
181
|
self.configure_events()
|
197
182
|
self.pre_render()
|
183
|
+
|
198
184
|
self.cmp_code = super(FilterPanel, self).render()
|
185
|
+
|
199
186
|
# где-то в инитах затирается темплейт, опишем еще раз
|
200
187
|
self.template = 'filter-panel.js'
|
188
|
+
|
201
189
|
return render_component(self)
|
202
190
|
|
203
191
|
|
204
192
|
class BaseGridWindow(BaseWindow):
|
205
|
-
"""
|
206
|
-
|
193
|
+
"""Базовое окно с фильтрующей панелью и панелью с гридом.
|
194
|
+
|
207
195
|
Клиент получает панель с гридом с сервера при изменении
|
208
|
-
полей фильтрации на фильтрующей
|
196
|
+
полей фильтрации на фильтрующей панели.
|
209
197
|
"""
|
198
|
+
|
210
199
|
grid_panel_cls = GridPanel # панель грида
|
211
200
|
|
212
201
|
def _init_grid_panel(self):
|
213
202
|
"""Панель для грида."""
|
214
203
|
self.grid_panel = self.grid_panel_cls(
|
215
|
-
region='center', layout='hbox', flex=1,
|
216
|
-
layout_config={"align": "stretch"}
|
204
|
+
region='center', layout='hbox', flex=1, layout_config={'align': 'stretch'}
|
217
205
|
)
|
218
206
|
|
219
207
|
def _init_filter_panel(self):
|
@@ -229,7 +217,8 @@ class BaseGridWindow(BaseWindow):
|
|
229
217
|
)
|
230
218
|
|
231
219
|
def _init_components(self):
|
232
|
-
super(
|
220
|
+
super()._init_components()
|
221
|
+
|
233
222
|
self._init_grid_panel()
|
234
223
|
self._init_filter_panel()
|
235
224
|
# связываются две панели
|
@@ -238,7 +227,8 @@ class BaseGridWindow(BaseWindow):
|
|
238
227
|
self._mro_exclude_list.append(self.filter_cnt)
|
239
228
|
|
240
229
|
def _do_layout(self):
|
241
|
-
super(
|
230
|
+
super()._do_layout()
|
231
|
+
|
242
232
|
self.layout = 'border'
|
243
233
|
self.maximizable = self.maximized = True
|
244
234
|
self.minimizable = True
|
@@ -247,20 +237,16 @@ class BaseGridWindow(BaseWindow):
|
|
247
237
|
self.grid_panel.layout_config['align'] = 'stretch'
|
248
238
|
|
249
239
|
# добавление фильтрующих полей в фильтрующую панель
|
250
|
-
assert self.filter_cnt.filters, (
|
251
|
-
'Необходимо добавить элементы в список фильтров '
|
252
|
-
'(self.filter_cnt.filters)!')
|
240
|
+
assert self.filter_cnt.filters, 'Необходимо добавить элементы в список фильтров (self.filter_cnt.filters)!'
|
253
241
|
|
254
|
-
self.items.extend([
|
255
|
-
self.filter_cnt, self.grid_panel
|
256
|
-
])
|
242
|
+
self.items.extend([self.filter_cnt, self.grid_panel])
|
257
243
|
|
258
244
|
def set_params(self, params):
|
245
|
+
super().set_params(params)
|
259
246
|
|
260
|
-
super(BaseGridWindow, self).set_params(params)
|
261
247
|
self.template_globals = 'base-grid-window.js'
|
262
248
|
|
263
|
-
self.pack = params[
|
249
|
+
self.pack = params['grid_pack']
|
264
250
|
|
265
251
|
# урл получения грида для панели с гридом
|
266
252
|
self.grid_panel.grid_url = self.pack.get_grid_action_url()
|
@@ -279,17 +265,18 @@ class RelatedErrorWindow(BaseWindow):
|
|
279
265
|
Показывается, если невозможно удаление записи из-за наличия ссылок
|
280
266
|
на удаляемый объект.
|
281
267
|
"""
|
268
|
+
|
282
269
|
def _init_components(self):
|
283
|
-
super(
|
284
|
-
|
270
|
+
super()._init_components()
|
271
|
+
|
272
|
+
self.title = 'Внимание!'
|
285
273
|
self.layout = 'fit'
|
286
|
-
self.panel = ext.ExtPanel(
|
287
|
-
auto_scroll=True
|
288
|
-
)
|
274
|
+
self.panel = ext.ExtPanel(auto_scroll=True)
|
289
275
|
self.items.append(self.panel)
|
290
276
|
|
291
277
|
def set_params(self, params):
|
292
|
-
super(
|
278
|
+
super().set_params(params)
|
279
|
+
|
293
280
|
assert 'html' in params
|
294
281
|
self.panel.html = params['html']
|
295
282
|
|
@@ -303,19 +290,17 @@ class _ListWindowMixin:
|
|
303
290
|
"""
|
304
291
|
|
305
292
|
def __init__(self):
|
306
|
-
super(
|
293
|
+
super().__init__()
|
307
294
|
|
308
|
-
self._mro_exclude_list.extend((
|
309
|
-
self.grid,
|
310
|
-
))
|
295
|
+
self._mro_exclude_list.extend((self.grid,))
|
311
296
|
|
312
297
|
def _init_components(self):
|
313
|
-
super(
|
298
|
+
super()._init_components()
|
314
299
|
|
315
300
|
self._mro_exclude_list.remove(self.grid.top_bar.button_refresh)
|
316
301
|
|
317
302
|
def set_params(self, params):
|
318
|
-
super(
|
303
|
+
super().set_params(params)
|
319
304
|
|
320
305
|
if params.get('read_only'):
|
321
306
|
reconfigure_grid_by_access(self.grid)
|
@@ -334,7 +319,7 @@ class _SelectWindowMixin(_ListWindowMixin):
|
|
334
319
|
"""Класс-примесь для окон выбора объектов."""
|
335
320
|
|
336
321
|
def set_params(self, params):
|
337
|
-
super(
|
322
|
+
super().set_params(params)
|
338
323
|
|
339
324
|
reconfigure_grid_by_access(self.grid, can_view=False)
|
340
325
|
|
@@ -357,14 +342,11 @@ class BaseMultiSelectWindow(_SelectWindowMixin, OPBaseMultiSelectWindow):
|
|
357
342
|
"""
|
358
343
|
|
359
344
|
def set_params(self, params):
|
360
|
-
super(
|
345
|
+
super().set_params(params)
|
346
|
+
|
361
347
|
self.grid.allow_paging = False
|
362
|
-
self.multiselect_page_fix = local_template(
|
363
|
-
|
364
|
-
)
|
365
|
-
self.template_globals = local_template(
|
366
|
-
'templates/multiSelectWindow.js'
|
367
|
-
)
|
348
|
+
self.multiselect_page_fix = local_template('templates/multiselect-page-fix.js')
|
349
|
+
self.template_globals = local_template('templates/multiSelectWindow.js')
|
368
350
|
|
369
351
|
|
370
352
|
class EditWindowMixin:
|
@@ -377,7 +359,7 @@ class EditWindowMixin:
|
|
377
359
|
"""
|
378
360
|
|
379
361
|
def set_params(self, params):
|
380
|
-
super(
|
362
|
+
super().set_params(params)
|
381
363
|
|
382
364
|
if params.get('read_only'):
|
383
365
|
# TODO: Выпилить эту функцию, а ее код перенести сюда
|
educommon/report/__init__.py
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
различных элементов отчётной подсистемы: провайдера данных, построителя отчёта
|
5
5
|
и собственно отчёта.
|
6
6
|
"""
|
7
|
+
|
7
8
|
from abc import (
|
8
9
|
ABCMeta,
|
9
10
|
abstractmethod,
|
@@ -209,7 +210,7 @@ class AbstractReportBuilder(metaclass=ABCMeta):
|
|
209
210
|
|
210
211
|
@abstractmethod
|
211
212
|
def build(self):
|
212
|
-
"""
|
213
|
+
"""Метод, осуществляющий построение отчёта.
|
213
214
|
|
214
215
|
Должен возвращать результат в виде файла или иной структуры данных.
|
215
216
|
"""
|
@@ -241,7 +242,7 @@ class BaseProviderAdapter(Mapping, dict):
|
|
241
242
|
|
242
243
|
'Магические' и некоторые отдельные методы будут игнорироваться.
|
243
244
|
"""
|
244
|
-
return not(attr.startswith('_') or attr in self._attrs_stop_list)
|
245
|
+
return not (attr.startswith('_') or attr in self._attrs_stop_list)
|
245
246
|
|
246
247
|
|
247
248
|
class FlatDataProviderAdapter(BaseProviderAdapter):
|
@@ -265,7 +266,7 @@ class FlatDataProviderAdapter(BaseProviderAdapter):
|
|
265
266
|
"""
|
266
267
|
assert isinstance(splitter, str), type(splitter)
|
267
268
|
|
268
|
-
super(
|
269
|
+
super().__init__(provider)
|
269
270
|
|
270
271
|
self.level_splitter = splitter
|
271
272
|
self._all_keys = self._get_all_keys(self.provider)
|
@@ -274,7 +275,7 @@ class FlatDataProviderAdapter(BaseProviderAdapter):
|
|
274
275
|
"""Все ключи в иерархии провайдеров."""
|
275
276
|
result = []
|
276
277
|
if key_level is None:
|
277
|
-
key_level =
|
278
|
+
key_level = ''
|
278
279
|
else:
|
279
280
|
if key_level:
|
280
281
|
key_level += self.level_splitter + provider.name
|
@@ -333,6 +334,7 @@ class FlatDataProviderAdapter(BaseProviderAdapter):
|
|
333
334
|
|
334
335
|
def __bool__(self):
|
335
336
|
return bool(self._all_keys)
|
337
|
+
|
336
338
|
__nonzero__ = __bool__
|
337
339
|
|
338
340
|
def __iter__(self):
|
@@ -361,7 +363,8 @@ class NestedDataProviderAdapter(BaseProviderAdapter):
|
|
361
363
|
|
362
364
|
:param provider: провайдер данных
|
363
365
|
"""
|
364
|
-
super(
|
366
|
+
super().__init__(provider)
|
367
|
+
|
365
368
|
self._all_keys = self._get_top_keys(self.provider)
|
366
369
|
|
367
370
|
def _get_top_keys(self, provider):
|
@@ -410,6 +413,7 @@ class NestedDataProviderAdapter(BaseProviderAdapter):
|
|
410
413
|
|
411
414
|
def __bool__(self):
|
412
415
|
return bool(self._all_keys)
|
416
|
+
|
413
417
|
__nonzero__ = __bool__
|
414
418
|
|
415
419
|
def __iter__(self):
|
educommon/report/actions.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
"""Генерация отчётов средствами платформы M3."""
|
2
|
+
|
2
3
|
from m3 import (
|
3
4
|
ApplicationLogicException,
|
4
5
|
)
|
@@ -17,7 +18,6 @@ from objectpack.ui import (
|
|
17
18
|
|
18
19
|
|
19
20
|
class BaseReportPack(BasePack):
|
20
|
-
|
21
21
|
"""Базовый класс отчёта.
|
22
22
|
|
23
23
|
Отчёты на любых движках могут быть описаны на основе этого класса.
|
@@ -74,19 +74,19 @@ def download_result(url):
|
|
74
74
|
url = str(url, 'utf-8')
|
75
75
|
return OperationResult(
|
76
76
|
success=True,
|
77
|
-
code="""
|
78
|
-
(function(){
|
77
|
+
code=f"""
|
78
|
+
(function() {{
|
79
79
|
var hiddenIFrameID = 'hiddenDownloader',
|
80
80
|
iframe = document.getElementById(hiddenIFrameID);
|
81
|
-
if (iframe === null) {
|
81
|
+
if (iframe === null) {{
|
82
82
|
iframe = document.createElement('iframe');
|
83
83
|
iframe.id = hiddenIFrameID;
|
84
84
|
iframe.style.display = 'none';
|
85
85
|
document.body.appendChild(iframe);
|
86
|
-
}
|
87
|
-
iframe.src = "
|
88
|
-
})()
|
89
|
-
"""
|
86
|
+
}}
|
87
|
+
iframe.src = "{url}";
|
88
|
+
}})()
|
89
|
+
""",
|
90
90
|
)
|
91
91
|
|
92
92
|
|
@@ -105,12 +105,12 @@ class CommonReportWindowAction(BaseWindowAction):
|
|
105
105
|
|
106
106
|
def set_window_params(self):
|
107
107
|
"""Задание параметров окна."""
|
108
|
-
super(
|
108
|
+
super().set_window_params()
|
109
|
+
|
109
110
|
params = self.win_params.copy()
|
110
111
|
params['title'] = self.parent.title
|
111
112
|
params['form_url'] = self.parent.get_reporting_url()
|
112
|
-
self.win_params = self.parent.set_report_window_params(
|
113
|
-
params, self.request, self.context)
|
113
|
+
self.win_params = self.parent.set_report_window_params(params, self.request, self.context)
|
114
114
|
|
115
115
|
|
116
116
|
class CommonReportAction(BaseAction):
|
@@ -130,12 +130,12 @@ class CommonReportAction(BaseAction):
|
|
130
130
|
builder_params.update(title=pack.title)
|
131
131
|
# генерация отчёта
|
132
132
|
out_file_url = pack.make_report(provider_params, builder_params)
|
133
|
+
|
133
134
|
return download_result(out_file_url.encode('utf-8'))
|
134
135
|
|
135
136
|
|
136
137
|
class CommonReportPack(BasePack):
|
137
|
-
"""
|
138
|
-
Пак, реализующий генерацию отчётов.
|
138
|
+
"""Пак, реализующий генерацию отчётов.
|
139
139
|
|
140
140
|
Использует класс-построитель reporter.
|
141
141
|
"""
|
@@ -159,14 +159,16 @@ class CommonReportPack(BasePack):
|
|
159
159
|
|
160
160
|
def __init__(self):
|
161
161
|
"""Конструктор пака генерации отчётов."""
|
162
|
-
super(
|
162
|
+
super().__init__()
|
163
163
|
|
164
164
|
self.report_window_action = CommonReportWindowAction()
|
165
165
|
self.report_action = CommonReportAction()
|
166
|
-
self.actions.extend(
|
167
|
-
|
168
|
-
|
169
|
-
|
166
|
+
self.actions.extend(
|
167
|
+
[
|
168
|
+
self.report_window_action,
|
169
|
+
self.report_action,
|
170
|
+
]
|
171
|
+
)
|
170
172
|
|
171
173
|
def get_reporting_url(self):
|
172
174
|
"""Отдаёт адрес форме, куда передавать данные для обработки."""
|
@@ -174,7 +176,7 @@ class CommonReportPack(BasePack):
|
|
174
176
|
|
175
177
|
@staticmethod
|
176
178
|
def context2dict(context):
|
177
|
-
"""
|
179
|
+
"""Преобразование контекста в словарь."""
|
178
180
|
result = {}
|
179
181
|
for key, value in context.__dict__.items():
|
180
182
|
try:
|
@@ -187,16 +189,14 @@ class CommonReportPack(BasePack):
|
|
187
189
|
return result
|
188
190
|
|
189
191
|
def check_report_params(self, request, context):
|
190
|
-
"""
|
191
|
-
Проверка передаваемых параметров для формирования отчёта.
|
192
|
+
"""Проверка передаваемых параметров для формирования отчёта.
|
192
193
|
|
193
194
|
:raise: ApplicationLogicException
|
194
195
|
"""
|
195
196
|
pass
|
196
197
|
|
197
198
|
def get_provider_params(self, request, context):
|
198
|
-
"""
|
199
|
-
Преобразование request, context к словарю для создания провайдера.
|
199
|
+
"""Преобразование request, context к словарю для создания провайдера.
|
200
200
|
|
201
201
|
:param request:
|
202
202
|
:param context:
|
@@ -204,8 +204,7 @@ class CommonReportPack(BasePack):
|
|
204
204
|
return {}
|
205
205
|
|
206
206
|
def get_builder_params(self, request, context):
|
207
|
-
"""
|
208
|
-
Преобразование request, context к словарю для создания билдера.
|
207
|
+
"""Преобразование request, context к словарю для создания билдера.
|
209
208
|
|
210
209
|
:param request:
|
211
210
|
:param context:
|
@@ -213,8 +212,7 @@ class CommonReportPack(BasePack):
|
|
213
212
|
return {}
|
214
213
|
|
215
214
|
def init_reporter(self, provider_params, builder_params):
|
216
|
-
"""
|
217
|
-
Инициализация построителя с передачей параметров билдеру и провайдеру.
|
215
|
+
"""Инициализация построителя с передачей параметров билдеру и провайдеру.
|
218
216
|
|
219
217
|
Не требует переопределения.
|
220
218
|
"""
|
@@ -224,20 +222,19 @@ class CommonReportPack(BasePack):
|
|
224
222
|
"""Синхронное построение отчёта. Не требует переопределения."""
|
225
223
|
reporter = self.init_reporter(provider_params, builder_params)
|
226
224
|
url = reporter.make_report()
|
225
|
+
|
227
226
|
return url
|
228
227
|
|
229
228
|
def set_report_window_params(self, params, request, context):
|
230
229
|
"""Дополнение параметров окна отчёта."""
|
231
|
-
if self.reporter_class.extension not in (
|
232
|
-
self.reporter_class._available_extensions
|
233
|
-
):
|
230
|
+
if self.reporter_class.extension not in (self.reporter_class._available_extensions):
|
234
231
|
raise ApplicationLogicException('Расширение указано неверно!')
|
235
232
|
params['extension'] = self.reporter_class.extension
|
233
|
+
|
236
234
|
return params
|
237
235
|
|
238
236
|
def create_report_window(self, request, context):
|
239
|
-
"""
|
240
|
-
Cоздание окна настройки параметров отчёта.
|
237
|
+
"""Cоздание окна настройки параметров отчёта.
|
241
238
|
|
242
239
|
Не требует переопределения.
|
243
240
|
"""
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
Поддерживает конструирование пользователем простых отчетов в формате Excel.
|
4
4
|
"""
|
5
|
+
|
5
6
|
import django
|
6
7
|
from pkg_resources import (
|
7
8
|
get_distribution,
|
@@ -19,16 +20,12 @@ default_app_config = __name__ + '.apps.AppConfig'
|
|
19
20
|
dist = get_distribution('m3-ui').version
|
20
21
|
version = tuple(int(x) for x in dist.split('.'))
|
21
22
|
|
22
|
-
assert (
|
23
|
-
|
24
|
-
|
25
|
-
(2, 2, 11) <= version < (2, 3)
|
26
|
-
), 'Конструктор отчетов не поддерживает версию {} пакета m3-ui'.format(dist)
|
23
|
+
assert (2, 0, 9) <= version < (2, 1) or (2, 1, 9) <= version < (2, 2) or (2, 2, 11) <= version < (2, 3), (
|
24
|
+
'Конструктор отчетов не поддерживает версию {} пакета m3-ui'.format(dist)
|
25
|
+
)
|
27
26
|
# -----------------------------------------------------------------------------
|
28
27
|
# Проверка версии Django
|
29
28
|
|
30
29
|
|
31
|
-
assert django.VERSION >= (1, 8),
|
32
|
-
'Конструктор отчетов работает только в системах на базе Django 1.8+'
|
33
|
-
)
|
30
|
+
assert django.VERSION >= (1, 8), 'Конструктор отчетов работает только в системах на базе Django 1.8+'
|
34
31
|
# -----------------------------------------------------------------------------
|