educommon 3.17.0__tar.gz → 3.19.0__tar.gz
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-3.17.0 → educommon-3.19.0}/CHANGELOG.md +34 -5
- {educommon-3.17.0 → educommon-3.19.0}/PKG-INFO +1 -1
- educommon-3.19.0/src/educommon/audit_log/management/commands/audit_log_migrate_data.py +357 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/management/commands/reinstall_audit_log.py +5 -0
- educommon-3.19.0/src/educommon/audit_log/migrations/0010_alter_auditlog_time.py +24 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/models.py +4 -1
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/sql/install_audit_log.sql +6 -2
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/utils/__init__.py +24 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon.egg-info/PKG-INFO +1 -1
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon.egg-info/SOURCES.txt +2 -0
- {educommon-3.17.0 → educommon-3.19.0}/CONDUCT.md +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/CONTRIBUTING.md +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/MANIFEST.in +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/README.md +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/pyproject.toml +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/setup.cfg +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/README.rst +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/apps.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/static/edu_about/barsgroup.png +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/ui/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/ui/about-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/ui/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/ui/common-tab.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/ui/packages-tab.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/ui/postgresql-extensions-tab.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/ui/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/about/utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/apps.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/consts.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/exceptions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/helpers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/locker.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/migrations/0001_initial.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/migrations/0002_task_type_and_status_data.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/migrations/0003_alter_runningtask_options.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/migrations/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/tasks.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/templates/ui-js/async-task-list-win.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/templates/ui-js/async-task-revoke.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/templates/ui-js/async-task-view-win.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_task/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/apps.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/exceptions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/fixtures/initial_data.json +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/locks.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/migrations/0001_initial.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/migrations/0002_load_initial_data.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/migrations/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/statuses.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/async_tasks/tasks.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/README.rst +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/app_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/apps.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/constants.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/error_log/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/error_log/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/helpers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/management/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/management/commands/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/middleware.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0001_initial.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0002_install_audit_log.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0003_logproxy.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0004_reinstall_audit_log.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0005_postgresql_error.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0006_auto_20200806_1707.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0007_create_selective_tables_function.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0008_table_logged.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/0009_reinstall_audit_log.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/migrations/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/permissions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/proxies.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/routers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/sql/configure_audit_log.sql +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/audit_log/utils/operations.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/app_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/backends/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/backends/base.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/backends/caching.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/backends/simple.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/checker.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/config.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/constants.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/management/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/management/commands/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/management/commands/rbac.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/manager.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/migrations/0001_initial.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/migrations/0002_model_modifier_metaclass_fix.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/migrations/0003_permission_hidden.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/migrations/0004_auto_20171024_1245.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/migrations/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/permissions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/templates/rbac/role-add-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/templates/rbac/role-edit-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/templates/rbac/roles-list-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/templates/rbac/roles-view-list-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/rbac/validators.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/app_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/checkers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/const.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/migrations/0001_initial.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/migrations/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/static/simple_auth/simple_auth.css +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/templates/simple_auth/change_reset_password_page.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/templates/simple_auth/email/reset_password.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/templates/simple_auth/login_page.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/templates/simple_auth/reset_password_page.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/auth/simple_auth/validators.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/app_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/base.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/catalogs.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/apps.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/migrations/0001_initial.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/migrations/0002_add_contingent_model_deleted.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/migrations/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/model_views.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/observer.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/plugin_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/storage.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/contingent_plugin/utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/json_data/icao.json +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/json_data/okogu.json +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/contingent/json_data/oksm.json +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/fields.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/migration/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/migration/operations.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/mixins/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/mixins/date_interval.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/mixins/validation.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/model_view/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/model_view/table-view.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/observer.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/README.md +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/const.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/management/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/management/commands/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/management/commands/apply_partitioning.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/management/commands/clear_table.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/management/commands/split_table.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/partitioning.sql +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/partitioning_set_search_path.sql +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/partitioning/triggers.sql +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/routers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/signals.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/validators/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/db/validators/simple.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/README.rst +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/api.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/app_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/exceptions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/management/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/management/commands/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/management/commands/atcfs_migrate.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/monkey_patching.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/settings.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/storage.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/django/storages/atcfs/templates/atcfs_unavailable.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/extjs/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/extjs/fields/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/extjs/fields/input_params.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/XLSReader.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/api.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/constants.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/loggers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/proxy.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/proxy_import.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/refactoring-notes.txt +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/report.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/test_file.xls +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/importer/validators.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/integration_entities/README.rst +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/integration_entities/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/integration_entities/consts.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/integration_entities/entities.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/integration_entities/enums.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/integration_entities/helpers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/integration_entities/mixins.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ioc/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/logger/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/logger/app_settings.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/logger/apps.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/logger/consts.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/logger/formatters.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/logger/helpers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/logger/loggers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/logger/records.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/delete_check/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/delete_check/cancel-confirm-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/delete_check/listeners.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/delete_check/mixins.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/delete_check/related-objects-window.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/delete_check/signals.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/delete_check/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/listeners/delete_check/utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/extensions/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/m3/transaction_context.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/apps.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/filters.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/templates/base-grid-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/templates/filter-panel.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/templates/grid-panel.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/templates/multiSelectWindow.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/templates/multiselect-page-fix.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/templates/relations-check-mixin-template.html +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/objectpack/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/README.rst +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/app_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/apps.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/base.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/builders/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/builders/excel/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/builders/excel/_base.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/builders/excel/_header.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/builders/excel/constants.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/builders/excel/product.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/builders/excel/with_merged_cells.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/config.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/constants.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/editor/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/editor/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/editor/edit-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/editor/list-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/editor/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/exceptions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0001_initial.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0002_report_filters.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0003_reportfilter_exclude.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0004_reportfilter_fields.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0005_reportcolumn_visible.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0006_reportsorting.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0007_include_available_units.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0008_auto_20170407_1318.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0009_auto_20180405_0642.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/0010_add_aggregate_fields.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/migrations/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/mixins.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/plugin_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/registries.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/constructor/validators.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/reporter.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/report/utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/rest/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/rest/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/rest/context.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/rest/controllers.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/rest/misc.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/rest/mixins.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/secure_media/README.rst +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/secure_media/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/secure_media/app_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/thread_data.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/caching.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/conversion.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/crypto.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/date.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/db/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/db/postgresql.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/fonts/Arial.ttf +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/fonts/Calibri.ttf +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/fonts/Tahoma.ttf +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/fonts/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/licence/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/licence/converters.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/misc.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/object_grid.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/phone_number/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/phone_number/enums.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/phone_number/modelfields.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/phone_number/phone_number.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/phone_number/validators.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/plugins.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/registry.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/seqtools.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/serializer.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/storage.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/system.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/system_app/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/system_app/management/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/system_app/management/commands/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/system_app/management/commands/delete_objects.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/system_app/templatetags/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/system_app/templatetags/educommon.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/xml/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/xml/catalog.json +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/xml/resolver.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/xml/saml-schema-assertion-2.0.xsd +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/xml/saml-schema-protocol-2.0.xsd +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/xml/xenc-schema.xsd +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/utils/xml/xmldsig-core-schema.xsd +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/README.rst +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/actions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/app_meta.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/base.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0001_initial.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0002_auto_20160628_1334.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0003_add_fields_to_smev_logs.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0004_auto_20160727_1600.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0005_auto_20161130_1615.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0006_auto_20170327_1027.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0007_auto_20180607_1040.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0008_auto_20180713_1445.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/0009_auto_20201130_1553.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/migrations/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/models.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/provider.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/report.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/smev/__init__.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/smev/applications.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/smev/exceptions.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/templates/report/smev_logs.xlsx +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/templates/ui-js/smev-logs-list-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/templates/ui-js/smev-logs-report-setting-window.js +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/ui.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon/ws_log/utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon.egg-info/dependency_links.txt +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon.egg-info/requires.txt +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/src/educommon.egg-info/top_level.txt +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_contingent_plugin_utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_dates_splitter.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_delete_check.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_delete_objects.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_django_db_utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_interval_mixins.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_personal_data_fields.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_phone_number.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_report.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_service_db_router.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_utils.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_utils_plugins.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/test_validators.py +0 -0
- {educommon-3.17.0 → educommon-3.19.0}/tests/tests_rbac.py +0 -0
@@ -28,6 +28,35 @@
|
|
28
28
|
### Удалено
|
29
29
|
|
30
30
|
|
31
|
+
# [3.19.0] - 2025-06-10
|
32
|
+
|
33
|
+
После поднятия версии, необходимо пересоздать функции журнала изменений в БД `django-admin reinstall_audit_log`.
|
34
|
+
|
35
|
+
### Добавлено
|
36
|
+
|
37
|
+
- [EDUDEVOPS-89](https://jira.bars.group/browse/EDUDEVOPS-89)
|
38
|
+
PATCH Добавлена функция get_auto_now_fields_by_model для получения словаря с полями, имеющими auto_now=True.
|
39
|
+
|
40
|
+
### Изменено
|
41
|
+
|
42
|
+
- [EDUDEVOPS-89](https://jira.bars.group/browse/EDUDEVOPS-89)
|
43
|
+
MINOR Изменена функция audit.on_modify в install_audit_log.sql.
|
44
|
+
Логирование изменений игнорируется, если при обновлении записи изменились только поля с auto_now=True.
|
45
|
+
|
46
|
+
|
47
|
+
# [3.18.0] - 2025-06-05
|
48
|
+
|
49
|
+
### Добавлено
|
50
|
+
|
51
|
+
- [EDUSCHL-23442](https://jira.bars.group/browse/EDUSCHL-23442)
|
52
|
+
MINOR Добавлена manage-команда переноса логов из локальных приложений в educommon.audit_log
|
53
|
+
|
54
|
+
### Изменено
|
55
|
+
|
56
|
+
- [EDUSCHL-23442](https://jira.bars.group/browse/EDUSCHL-23442)
|
57
|
+
PATCH В поле AuditLog.time auto_now_add заменен на default
|
58
|
+
|
59
|
+
|
31
60
|
# [3.17.0] - 2025-05-28
|
32
61
|
|
33
62
|
Добавлена проверка конфликтующих таблиц которые должны логироваться, но находятся в сервисных приложениях.
|
@@ -83,9 +112,9 @@
|
|
83
112
|
### Изменено
|
84
113
|
|
85
114
|
- [EDUSCHL-23386](https://jira.bars.group/browse/EDUSCHL-23386)
|
86
|
-
MINOR Классы LogProxy, AuditLogPack преобразованы в абстрактные с добавлением абстрактных методов для
|
115
|
+
MINOR Классы LogProxy, AuditLogPack преобразованы в абстрактные с добавлением абстрактных методов для
|
87
116
|
извлечения исходных данных необходимых при: отображении ФИО пользователя в журнале изменений; фильтрации по ФИО;
|
88
|
-
отображении ФИО, организации в окне редактирования записи журнала изменений.
|
117
|
+
отображении ФИО, организации в окне редактирования записи журнала изменений.
|
89
118
|
Подробнее о необходимых настройках в audit_log/README.rst.
|
90
119
|
|
91
120
|
|
@@ -94,7 +123,7 @@
|
|
94
123
|
Небольшой рефакторинг для корректной сборки пакета.
|
95
124
|
|
96
125
|
### Изменено
|
97
|
-
|
126
|
+
|
98
127
|
- MINOR Удалены ненужные файлы, актуализирована сборка пакета.
|
99
128
|
|
100
129
|
|
@@ -117,14 +146,14 @@
|
|
117
146
|
PATCH Заменено устаревшее строковое форматирование `%` на f-строки и `.format()`.
|
118
147
|
PATCH Проведён широкий рефакторинг кода с использованием `ruff`: улучшена читаемость, устранены потенциальные ошибки и упрощена структура модулей.
|
119
148
|
- [EDUKNDG-15346](https://jira.bars.group/browse/EDUKNDG-15346)
|
120
|
-
PATCH Исправлена минимальная дата для валидатора поля RangedDateField и BirthDateField.
|
149
|
+
PATCH Исправлена минимальная дата для валидатора поля RangedDateField и BirthDateField.
|
121
150
|
- [EDUSCHL-23422](https://jira.bars.group/browse/EDUSCHL-23422)
|
122
151
|
PATCH Тип сообщения о предотвращении доступа к БД, по которой не проводистя миграция,
|
123
152
|
с `warning` изменён на `debug`
|
124
153
|
|
125
154
|
### Удалено
|
126
155
|
|
127
|
-
- [EDUDEVOPS-28](https://jira.bars.group/browse/EDUDEVOPS-28)
|
156
|
+
- [EDUDEVOPS-28](https://jira.bars.group/browse/EDUDEVOPS-28)
|
128
157
|
PATCH Удалены остатки поддержки Python2: директивы `__future__`, проверки `sys.version_info`, типы `unicode`, `basestring` и др.
|
129
158
|
|
130
159
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: educommon
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.19.0
|
4
4
|
Summary: Общая кодовая база для проектов БЦ Образование
|
5
5
|
Author-email: BARS Group <education_dev@bars-open.ru>
|
6
6
|
Project-URL: Homepage, https://stash.bars-open.ru/projects/EDUBASE/repos/educommon/browse
|
@@ -0,0 +1,357 @@
|
|
1
|
+
"""
|
2
|
+
Команда переноса данных из локального AuditLog'а в educommon'овский.
|
3
|
+
"""
|
4
|
+
import sys
|
5
|
+
from datetime import (
|
6
|
+
datetime as dt,
|
7
|
+
)
|
8
|
+
from typing import (
|
9
|
+
TYPE_CHECKING,
|
10
|
+
Generator,
|
11
|
+
Optional,
|
12
|
+
Type,
|
13
|
+
)
|
14
|
+
|
15
|
+
from dateutil.relativedelta import (
|
16
|
+
relativedelta,
|
17
|
+
)
|
18
|
+
from django.apps import (
|
19
|
+
apps,
|
20
|
+
)
|
21
|
+
from django.core.management.base import (
|
22
|
+
BaseCommand,
|
23
|
+
OutputWrapper,
|
24
|
+
)
|
25
|
+
from django.db.models import (
|
26
|
+
ManyToManyField,
|
27
|
+
Model,
|
28
|
+
)
|
29
|
+
|
30
|
+
from educommon.audit_log.models import (
|
31
|
+
AuditLog,
|
32
|
+
Table,
|
33
|
+
)
|
34
|
+
from educommon.audit_log.utils import (
|
35
|
+
get_model_by_table,
|
36
|
+
)
|
37
|
+
|
38
|
+
|
39
|
+
if TYPE_CHECKING:
|
40
|
+
from django.db.models.query import (
|
41
|
+
QuerySet,
|
42
|
+
)
|
43
|
+
|
44
|
+
|
45
|
+
PROJECT_LOCAL_AUDIT_LOG_APP = {
|
46
|
+
'eduschl': 'web_edu_audit_log',
|
47
|
+
'edussuz': 'audit_log_ssuz',
|
48
|
+
'edukndg': 'audit_log_kndg'
|
49
|
+
}
|
50
|
+
LOG_OPERATION_MAP = {
|
51
|
+
'N': AuditLog.OPERATION_CREATE,
|
52
|
+
'I': AuditLog.OPERATION_CREATE,
|
53
|
+
'U': AuditLog.OPERATION_UPDATE,
|
54
|
+
'D': AuditLog.OPERATION_DELETE,
|
55
|
+
}
|
56
|
+
LOCAL_AUDIT_LOG_MODEL_NAME = 'Log'
|
57
|
+
DEFAULT_DATE_YEAR_RANGE = 1
|
58
|
+
|
59
|
+
|
60
|
+
class BulkSaver:
|
61
|
+
"""Контекстный менеджер для группового сохранения записей."""
|
62
|
+
|
63
|
+
def __init__(self, bulk_size: int) -> None:
|
64
|
+
self._bulk_size = bulk_size
|
65
|
+
self._bulk_list = []
|
66
|
+
|
67
|
+
def __enter__(self):
|
68
|
+
return self
|
69
|
+
|
70
|
+
def __exit__(self, *exc):
|
71
|
+
self._bulk_save()
|
72
|
+
|
73
|
+
def save(self, audit_log: AuditLog):
|
74
|
+
self._bulk_list.append(audit_log)
|
75
|
+
if len(self._bulk_list) >= self._bulk_size:
|
76
|
+
self._bulk_save()
|
77
|
+
|
78
|
+
def _bulk_save(self):
|
79
|
+
AuditLog.objects.bulk_create(self._bulk_list)
|
80
|
+
self._bulk_list.clear()
|
81
|
+
|
82
|
+
|
83
|
+
class LogMigrator:
|
84
|
+
"""Класс для миграции логов из локального AuditLog'а в educommon'овский."""
|
85
|
+
|
86
|
+
def __init__(self, stdout: OutputWrapper):
|
87
|
+
"""Инициализация."""
|
88
|
+
self._stdout = stdout
|
89
|
+
|
90
|
+
@staticmethod
|
91
|
+
def get_model(model_name: str) -> Optional[Type[Model]]:
|
92
|
+
"""Bозвращает класс модели по имени."""
|
93
|
+
for mod in apps.get_models():
|
94
|
+
if mod.__name__ == model_name and mod.__module__.find('django') == -1:
|
95
|
+
return mod
|
96
|
+
|
97
|
+
return None
|
98
|
+
|
99
|
+
def _get_educommon_table(self, model_name: str, create: bool = False) -> tuple[Optional[Table], str]:
|
100
|
+
"""Возвращает таблицу, отслеживаемую системой аудита."""
|
101
|
+
model_cls = self.get_model(model_name)
|
102
|
+
|
103
|
+
if not model_cls:
|
104
|
+
return None, f'Не найдено Django моделей с именем {model_name}'
|
105
|
+
try:
|
106
|
+
return Table.objects.get(name=model_cls._meta.db_table), ''
|
107
|
+
except Table.DoesNotExist:
|
108
|
+
is_loggable_mixin_use = getattr(model_cls, 'need_to_log', False)
|
109
|
+
|
110
|
+
if not is_loggable_mixin_use:
|
111
|
+
return None, (
|
112
|
+
f'В таблицу {model_name} не добавлен LoggableModelMixin'
|
113
|
+
)
|
114
|
+
|
115
|
+
if create:
|
116
|
+
return Table.objects.create(
|
117
|
+
name=model_cls._meta.db_table,
|
118
|
+
schema='public',
|
119
|
+
logged=True,
|
120
|
+
), ''
|
121
|
+
|
122
|
+
return None, (
|
123
|
+
f'В educommon не найдено таблицы с именем {model_cls._meta.db_table}. '
|
124
|
+
'Таблицу можно создать, указав флаг force_create_educommon_table'
|
125
|
+
)
|
126
|
+
|
127
|
+
@staticmethod
|
128
|
+
def _get_fields_map(table: Table) -> dict[str, str]:
|
129
|
+
"""Возвращает словарь соответствия поля модели и его названия."""
|
130
|
+
return {
|
131
|
+
field.name: field.attname
|
132
|
+
for field in get_model_by_table(table)._meta.get_fields()
|
133
|
+
if field.concrete and not isinstance(field, ManyToManyField)
|
134
|
+
}
|
135
|
+
|
136
|
+
def _get_local_audit_log_query(
|
137
|
+
self,
|
138
|
+
project: str,
|
139
|
+
model_name: str,
|
140
|
+
date_from: dt,
|
141
|
+
date_to: dt
|
142
|
+
) -> tuple[Optional['QuerySet'], str]:
|
143
|
+
"""Возвращает QuerySet с локальными логами."""
|
144
|
+
if not (audit_log_app_name := PROJECT_LOCAL_AUDIT_LOG_APP.get(project)):
|
145
|
+
return None, 'Неизвестное название проекта.'
|
146
|
+
|
147
|
+
audit_log_model = apps.get_model(audit_log_app_name, LOCAL_AUDIT_LOG_MODEL_NAME)
|
148
|
+
|
149
|
+
if not audit_log_model:
|
150
|
+
return None, 'Не найдена локальная модель логов.'
|
151
|
+
|
152
|
+
return audit_log_model.objects.filter(
|
153
|
+
model=model_name,
|
154
|
+
date__lt=date_to,
|
155
|
+
date__gte=date_from,
|
156
|
+
), ''
|
157
|
+
|
158
|
+
@staticmethod
|
159
|
+
def _prepare_local_logs(query: 'QuerySet') -> Generator[tuple, None, None]:
|
160
|
+
"""Подготавливает данные логов для дальнейшего использования."""
|
161
|
+
query = query.values_list(
|
162
|
+
'user_id',
|
163
|
+
'date',
|
164
|
+
'model_id',
|
165
|
+
'object_json',
|
166
|
+
'ip',
|
167
|
+
'operation',
|
168
|
+
).order_by(
|
169
|
+
'date',
|
170
|
+
)
|
171
|
+
for user_id, date_, model_id, object_json, ip, operation in query.iterator():
|
172
|
+
yield user_id, date_, model_id, ip, operation, object_json
|
173
|
+
|
174
|
+
@staticmethod
|
175
|
+
def _prepare_object_dict(fields_map: dict, object_dict: Optional[dict]) -> dict[str, str]:
|
176
|
+
"""Подготавливает данные о объекте для AuditLog.
|
177
|
+
|
178
|
+
В основном требуется только для переименования ForeignKey-полей вида
|
179
|
+
`period` в `period_id`
|
180
|
+
"""
|
181
|
+
if not object_dict:
|
182
|
+
return {}
|
183
|
+
|
184
|
+
filled_field_names = set(fields_map).intersection(object_dict)
|
185
|
+
return {
|
186
|
+
fields_map[field_name]: object_dict[field_name]
|
187
|
+
for field_name in filled_field_names
|
188
|
+
}
|
189
|
+
|
190
|
+
def process(
|
191
|
+
self,
|
192
|
+
model_name: str,
|
193
|
+
project: str,
|
194
|
+
bulk_save_size: int,
|
195
|
+
date_from: Optional[dt] = None,
|
196
|
+
date_to: Optional[dt] = None,
|
197
|
+
force_create_educommon_table: bool = False,
|
198
|
+
):
|
199
|
+
"""Перенос записей из локального AuditLog'а в educommon."""
|
200
|
+
table, error = self._get_educommon_table(model_name, force_create_educommon_table)
|
201
|
+
if error:
|
202
|
+
self._stdout.write(error)
|
203
|
+
return
|
204
|
+
|
205
|
+
fields_map = self._get_fields_map(table)
|
206
|
+
|
207
|
+
first_audit_log_date = self._get_first_audit_log_date(table)
|
208
|
+
date_to = dt.combine((date_to or dt.today()), dt.max.time())
|
209
|
+
|
210
|
+
date_to = min(date_to, first_audit_log_date)
|
211
|
+
date_from = date_from or (date_to - relativedelta(years=DEFAULT_DATE_YEAR_RANGE))
|
212
|
+
|
213
|
+
self._stdout.write(
|
214
|
+
f'Поиск записей в локальном Auditlog с {date_from} по {date_to}... ',
|
215
|
+
ending='',
|
216
|
+
)
|
217
|
+
|
218
|
+
local_audit_log_query, error = self._get_local_audit_log_query(
|
219
|
+
project=project,
|
220
|
+
model_name=model_name,
|
221
|
+
date_from=date_from,
|
222
|
+
date_to=date_to,
|
223
|
+
)
|
224
|
+
if error:
|
225
|
+
self._stdout.write(error)
|
226
|
+
return
|
227
|
+
|
228
|
+
total_count = local_audit_log_query.count()
|
229
|
+
self._stdout.write(f'Найдено {total_count} запись(ей).')
|
230
|
+
|
231
|
+
local_logs = self._prepare_local_logs(local_audit_log_query)
|
232
|
+
self._stdout.write(f'Подготовка к работе... (занимает некоторое время)', ending='\r',)
|
233
|
+
with BulkSaver(bulk_save_size) as bulk:
|
234
|
+
for count, (user_id, date_, object_id, ip, operation, data_dict) in enumerate(local_logs, start=1):
|
235
|
+
object_dict = self._prepare_object_dict(fields_map, data_dict[0].get('fields', {}))
|
236
|
+
|
237
|
+
operation = LOG_OPERATION_MAP[operation]
|
238
|
+
|
239
|
+
if operation == AuditLog.OPERATION_UPDATE:
|
240
|
+
changes = object_dict
|
241
|
+
else:
|
242
|
+
# Если объект быз создан или удалён, то изменений нет.
|
243
|
+
changes = {}
|
244
|
+
|
245
|
+
bulk.save(AuditLog(
|
246
|
+
user_id=user_id,
|
247
|
+
ip=ip,
|
248
|
+
time=date_,
|
249
|
+
table_id=table.id,
|
250
|
+
data=object_dict,
|
251
|
+
changes=changes,
|
252
|
+
object_id=object_id,
|
253
|
+
operation=operation,
|
254
|
+
))
|
255
|
+
|
256
|
+
self._stdout.write(
|
257
|
+
f'Обработано {(count / total_count) * 100:5.2f}% запись(ей)... (Последняя от {date_})',
|
258
|
+
ending='\r',
|
259
|
+
)
|
260
|
+
|
261
|
+
def _get_first_audit_log_date(self, table: str) -> dt:
|
262
|
+
"""Возвращает первую дату/время появления audit_log по переданной таблице.
|
263
|
+
|
264
|
+
В случае отсуствия логов прекращает выполнение команды за отсутствием данных для переноса.
|
265
|
+
"""
|
266
|
+
first_log = AuditLog.objects.filter(
|
267
|
+
table=table,
|
268
|
+
).order_by('time').first()
|
269
|
+
|
270
|
+
if not first_log:
|
271
|
+
self._stdout.write('Не найдены локальные логи переданной модели. Завершение команды.')
|
272
|
+
sys.exit()
|
273
|
+
|
274
|
+
return first_log.time
|
275
|
+
|
276
|
+
|
277
|
+
class Command(BaseCommand):
|
278
|
+
"""Команда переноса данных из локального AuditLog'а в educommon'овский."""
|
279
|
+
|
280
|
+
help = (
|
281
|
+
'Команда для переноса данных из локального AuditLog`а в educommon.audit_log.models.AuditLog.\n'
|
282
|
+
'Пример использования:\n'
|
283
|
+
'audit_log_migrate_data --project eduschl --model_name Mark --date_from 10.10.2024'
|
284
|
+
)
|
285
|
+
|
286
|
+
@staticmethod
|
287
|
+
def _get_date(date_string: str) -> dt:
|
288
|
+
return dt.strptime(date_string, '%d.%m.%Y')
|
289
|
+
|
290
|
+
def add_arguments(self, parser):
|
291
|
+
parser.add_argument(
|
292
|
+
'--model_name',
|
293
|
+
type=str,
|
294
|
+
help='Название модели из локального лога',
|
295
|
+
)
|
296
|
+
parser.add_argument(
|
297
|
+
'--project',
|
298
|
+
type=str,
|
299
|
+
help='Наименование (код) продукта, в котором применяется команда',
|
300
|
+
)
|
301
|
+
parser.add_argument(
|
302
|
+
'--date_from',
|
303
|
+
type=self._get_date,
|
304
|
+
required=False,
|
305
|
+
help=(
|
306
|
+
'Дата, с которой будут переноситься логи в формате ДД.ММ.ГГГГ. '
|
307
|
+
'Значение по умолчанию - на год раньше даты, указанной в --date_to'
|
308
|
+
),
|
309
|
+
)
|
310
|
+
parser.add_argument(
|
311
|
+
'--date_to',
|
312
|
+
type=self._get_date,
|
313
|
+
required=False,
|
314
|
+
help=(
|
315
|
+
'Дата, по которую будут переноситься логи в формате ДД.ММ.ГГГГ.'
|
316
|
+
'Значение по умолчанию - текущая дата.'
|
317
|
+
),
|
318
|
+
)
|
319
|
+
parser.add_argument(
|
320
|
+
'--force_create_educommon_table',
|
321
|
+
action='store_true',
|
322
|
+
default=False,
|
323
|
+
help=(
|
324
|
+
'Создание отслеживаемой таблицы (educommon.audit_log.models.Table), '
|
325
|
+
'если она еще не была создана'
|
326
|
+
),
|
327
|
+
)
|
328
|
+
parser.add_argument(
|
329
|
+
'--bulk_save_size',
|
330
|
+
type=int,
|
331
|
+
default=500,
|
332
|
+
help='По сколько записей за раз будет сохраняться. По умолчанию 500',
|
333
|
+
)
|
334
|
+
|
335
|
+
def handle(
|
336
|
+
self,
|
337
|
+
model_name: str,
|
338
|
+
project: str,
|
339
|
+
date_from: Optional[dt],
|
340
|
+
date_to: Optional[dt],
|
341
|
+
force_create_educommon_table: bool,
|
342
|
+
bulk_save_size: int,
|
343
|
+
*args,
|
344
|
+
**options,
|
345
|
+
):
|
346
|
+
"""Выполнение переноса записей."""
|
347
|
+
self.stdout.write('Начало работы команды.')
|
348
|
+
LogMigrator(self.stdout).process(
|
349
|
+
model_name=model_name,
|
350
|
+
project=project,
|
351
|
+
date_from=date_from,
|
352
|
+
date_to=date_to,
|
353
|
+
force_create_educommon_table=force_create_educommon_table,
|
354
|
+
bulk_save_size=bulk_save_size,
|
355
|
+
)
|
356
|
+
|
357
|
+
self.stdout.write(self.style.SUCCESS('Выполнение команды завершено.'))
|
@@ -10,6 +10,9 @@ from django.core.management.base import (
|
|
10
10
|
from django.db import (
|
11
11
|
connection,
|
12
12
|
)
|
13
|
+
from psycopg2.extras import (
|
14
|
+
Json,
|
15
|
+
)
|
13
16
|
|
14
17
|
from educommon.audit_log.constants import (
|
15
18
|
INSTALL_AUDIT_LOG_SQL_FILE_NAME,
|
@@ -19,6 +22,7 @@ from educommon.audit_log.constants import (
|
|
19
22
|
from educommon.audit_log.utils import (
|
20
23
|
clear_audit_logs,
|
21
24
|
configure,
|
25
|
+
get_auto_now_fields_by_model,
|
22
26
|
get_db_connection_params,
|
23
27
|
)
|
24
28
|
|
@@ -69,6 +73,7 @@ class Command(BaseCommand):
|
|
69
73
|
"""Подготовка SQL-кода."""
|
70
74
|
params = get_db_connection_params()
|
71
75
|
params['lock_id'] = PG_LOCK_ID
|
76
|
+
params['auto_now_fields'] = Json(get_auto_now_fields_by_model())
|
72
77
|
|
73
78
|
self.stdout.write('preparing SQL-code..\n')
|
74
79
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Generated by Django 3.2.24 on 2025-05-16 12:04
|
2
|
+
|
3
|
+
from django.db import (
|
4
|
+
migrations,
|
5
|
+
models,
|
6
|
+
)
|
7
|
+
from django.utils import (
|
8
|
+
timezone,
|
9
|
+
)
|
10
|
+
|
11
|
+
|
12
|
+
class Migration(migrations.Migration):
|
13
|
+
|
14
|
+
dependencies = [
|
15
|
+
('audit_log', '0009_reinstall_audit_log'),
|
16
|
+
]
|
17
|
+
|
18
|
+
operations = [
|
19
|
+
migrations.AlterField(
|
20
|
+
model_name='auditlog',
|
21
|
+
name='time',
|
22
|
+
field=models.DateTimeField(db_index=True, default=timezone.now, verbose_name='Дата, время'),
|
23
|
+
),
|
24
|
+
]
|
@@ -41,6 +41,9 @@ from django.db.backends.signals import (
|
|
41
41
|
from django.dispatch.dispatcher import (
|
42
42
|
receiver,
|
43
43
|
)
|
44
|
+
from django.utils import (
|
45
|
+
timezone,
|
46
|
+
)
|
44
47
|
|
45
48
|
from educommon.audit_log.utils import (
|
46
49
|
get_audit_log_context,
|
@@ -115,7 +118,7 @@ class AuditLog(ReadOnlyMixin, BaseModel):
|
|
115
118
|
verbose_name='Тип пользователя',
|
116
119
|
)
|
117
120
|
ip = models.GenericIPAddressField(null=True, verbose_name='IP адрес')
|
118
|
-
time = models.DateTimeField(
|
121
|
+
time = models.DateTimeField(default=timezone.now, db_index=True, verbose_name='Дата, время')
|
119
122
|
table = models.ForeignKey(
|
120
123
|
Table,
|
121
124
|
verbose_name='Таблица',
|
@@ -188,6 +188,8 @@ DECLARE
|
|
188
188
|
operation_code INTEGER;
|
189
189
|
len INTEGER;
|
190
190
|
text_error TEXT;
|
191
|
+
auto_now_field_names TEXT[];
|
192
|
+
all_changed_have_auto_now BOOLEAN;
|
191
193
|
BEGIN
|
192
194
|
operation_code := 0;
|
193
195
|
user_id := audit.get_param('audit_log.user_id');
|
@@ -202,8 +204,10 @@ BEGIN
|
|
202
204
|
data := hstore(OLD);
|
203
205
|
changes := hstore(NEW) - hstore(OLD);
|
204
206
|
len := array_length(akeys(changes),1);
|
205
|
-
|
206
|
-
|
207
|
+
auto_now_field_names := ARRAY(SELECT jsonb_array_elements_text({auto_now_fields}::jsonb -> TG_TABLE_NAME::TEXT));
|
208
|
+
all_changed_have_auto_now := auto_now_field_names @> akeys(changes);
|
209
|
+
-- Если изменений нет или изменения, только в автообновляемых полях, то не логируем.
|
210
|
+
IF (len IS NOT NULL OR len = 0) AND NOT all_changed_have_auto_now THEN
|
207
211
|
result_value := NEW;
|
208
212
|
operation_code := 2;
|
209
213
|
END IF;
|
@@ -469,3 +469,27 @@ def get_audit_log_context(request):
|
|
469
469
|
result['ip'] = get_ip(request)
|
470
470
|
|
471
471
|
return result
|
472
|
+
|
473
|
+
|
474
|
+
def get_auto_now_fields_by_model() -> dict[str, list[str]]:
|
475
|
+
"""Возвращает словарь с полями, имеющими auto_now=True, для моделей с флагом need_to_log = True.
|
476
|
+
|
477
|
+
Returns:
|
478
|
+
Словарь, где ключ это название таблицы, а значение это список названий полей имеющими auto_now=True.
|
479
|
+
"""
|
480
|
+
auto_now_fields = {}
|
481
|
+
|
482
|
+
for model in apps.get_models():
|
483
|
+
if not getattr(model, 'need_to_log', False):
|
484
|
+
continue
|
485
|
+
|
486
|
+
auto_now_field_names = [
|
487
|
+
field.name
|
488
|
+
for field in model._meta.get_fields()
|
489
|
+
if getattr(field, 'auto_now', False)
|
490
|
+
]
|
491
|
+
|
492
|
+
if auto_now_field_names:
|
493
|
+
auto_now_fields[model._meta.db_table] = auto_now_field_names
|
494
|
+
|
495
|
+
return auto_now_fields
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: educommon
|
3
|
-
Version: 3.
|
3
|
+
Version: 3.19.0
|
4
4
|
Summary: Общая кодовая база для проектов БЦ Образование
|
5
5
|
Author-email: BARS Group <education_dev@bars-open.ru>
|
6
6
|
Project-URL: Homepage, https://stash.bars-open.ru/projects/EDUBASE/repos/educommon/browse
|
@@ -68,6 +68,7 @@ src/educommon/audit_log/error_log/__init__.py
|
|
68
68
|
src/educommon/audit_log/error_log/actions.py
|
69
69
|
src/educommon/audit_log/management/__init__.py
|
70
70
|
src/educommon/audit_log/management/commands/__init__.py
|
71
|
+
src/educommon/audit_log/management/commands/audit_log_migrate_data.py
|
71
72
|
src/educommon/audit_log/management/commands/reinstall_audit_log.py
|
72
73
|
src/educommon/audit_log/migrations/0001_initial.py
|
73
74
|
src/educommon/audit_log/migrations/0002_install_audit_log.py
|
@@ -78,6 +79,7 @@ src/educommon/audit_log/migrations/0006_auto_20200806_1707.py
|
|
78
79
|
src/educommon/audit_log/migrations/0007_create_selective_tables_function.py
|
79
80
|
src/educommon/audit_log/migrations/0008_table_logged.py
|
80
81
|
src/educommon/audit_log/migrations/0009_reinstall_audit_log.py
|
82
|
+
src/educommon/audit_log/migrations/0010_alter_auditlog_time.py
|
81
83
|
src/educommon/audit_log/migrations/__init__.py
|
82
84
|
src/educommon/audit_log/sql/configure_audit_log.sql
|
83
85
|
src/educommon/audit_log/sql/install_audit_log.sql
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|