Веб-приложение для мониторинга земель на основе картографических данных. Приложение предоставляет интерактивную карту с возможностью просмотра различных слоев данных о земельных ресурсах, систему заявок на услуги и документооборот.
/test для просмотра списка сервисов ArcGIS с измерением времени загрузки/ocsk-services для получения списка ОЦСК сервисов из JSON файлаgiprozem.user_plots (координаты в формате GeoJSON, JSONB)/export/zu-excel для экспорта результатов поиска участковБэкенд разделён на модули с четким разделением ответственности:
app.py — точка входа Flask, использует create_app()app/__init__.py — фабрика create_app(): конфигурация, Babel, регистрация блюпринтовapp/logging_setup.py — настройка логирования с ротацией файловapp/extensions.py — объявления экстеншенов (babel)app/i18n.py — выбор локали пользователяapp/blueprints/public.py — публичные маршруты: GET /app/blueprints/proxy.py — проксирование запросов: GET /Proxy/Wms, GET /Proxy/Wfs, GET /Proxy/Map/*app/blueprints/account.py — аутентификация: POST /Account/Login, GET /Account/Logoutapp/blueprints/api.py — REST API: настройки, заявки, документы, справочники, пользователиapp/services/certificates.py — работа с сертификатами ЭЦПapp/repositories/database_manager.py — слой доступа к данным, управление БД
giprozem.user_plots, индексы логов)Реализована современная модульная система для JavaScript:
static/js/app.js — точка входа ES-модуля, инициализация всех UI-модулейstatic/js/notifications.js — модуль уведомленийstatic/js/map.js — картографический функционал (Leaflet + ESRI Leaflet, ArcGIS Server интеграция)static/js/modules/ — функциональные модули:
auth.js — авторизация и управление сессиямиdocuments.js — загрузка и управление документамиgeojson.js — работа с GeoJSON даннымиlanguage.js — смена языка интерфейсаmenu.js — обработчики менюmodals.js — жизненный цикл модальных оконorders.js — создание заявок на услугиpersonal.js — личный кабинет и управление пользователямиrequests.js — управление заявками и фильтрацияrequest-details.js — просмотр детальной информации о заявкахsearch.js — поиск земельных участков по кадастровому номеруservices.js — загрузка справочниковsettings.js — настройки пользователяvalidators.js — валидация формtype="module"windowapp.jsgit clone <repository-url>
cd LandMonitoring
python3 -m venv venv
source venv/bin/activate # На Windows: venv\Scripts\activate
pip install -r requirements.txt
Примечание: Если возникают проблемы с установкой psycopg2-binary, установите системные зависимости:
# Ubuntu/Debian
sudo apt-get install python3-dev libpq-dev
# macOS
brew install postgresql
# CentOS/RHEL
sudo yum install python3-devel postgresql-devel
Важно: Убедитесь, что PostgreSQL запущен и доступен:
# Проверка статуса PostgreSQL
sudo systemctl status postgresql
# Запуск PostgreSQL (если не запущен)
sudo systemctl start postgresql
-- Создайте схему giprozem
CREATE SCHEMA IF NOT EXISTS giprozem;
-- Таблица настроек пользователей
CREATE TABLE IF NOT EXISTS giprozem.user_settings (
iin VARCHAR(12) PRIMARY KEY,
phone VARCHAR(20),
email VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица истории авторизаций
CREATE TABLE IF NOT EXISTS giprozem.auth_history (
id SERIAL PRIMARY KEY,
iin VARCHAR(12) NOT NULL,
fio VARCHAR(200),
login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
logout_time TIMESTAMP,
ip_address INET,
user_agent TEXT,
success BOOLEAN DEFAULT TRUE,
error_message TEXT
);
-- Таблица ролей (справочник)
CREATE TABLE IF NOT EXISTS giprozem.roles (
role_code VARCHAR(10) PRIMARY KEY,
name_ru VARCHAR(100) NOT NULL,
name_kk VARCHAR(100) NOT NULL
);
-- Наполнение ролей (без дубликатов)
INSERT INTO giprozem.roles (role_code, name_ru, name_kk) VALUES
('00','Пользователь','Пайдаланушы'),
('01','Исполнитель','Орындаушы'),
('02','Канцелярия','Кеңсе'),
('03','Руководитель','Басшы'),
('99','Администратор','Әкімші')
ON CONFLICT (role_code) DO NOTHING;
-- Таблица ролей пользователей (многие-ко-многим)
CREATE TABLE IF NOT EXISTS giprozem.user_roles (
iin VARCHAR(12) NOT NULL,
role_code VARCHAR(10) NOT NULL
);
-- Таблица услуг
CREATE TABLE IF NOT EXISTS giprozem.services (
id SERIAL PRIMARY KEY,
code VARCHAR(10) UNIQUE NOT NULL,
name_ru VARCHAR(200) NOT NULL,
name_kk VARCHAR(200) NOT NULL,
description_ru TEXT,
description_kk TEXT,
price DECIMAL(10,2) DEFAULT 0.00,
duration_days INTEGER DEFAULT 30,
is_active BOOLEAN DEFAULT TRUE
);
-- Таблица статусов заявок
CREATE TABLE IF NOT EXISTS giprozem.request_statuses (
id SERIAL PRIMARY KEY,
code VARCHAR(10) UNIQUE NOT NULL,
name_ru VARCHAR(100) NOT NULL,
name_kk VARCHAR(100) NOT NULL,
color VARCHAR(20) DEFAULT '#007bff'
);
-- Таблица заявок
CREATE TABLE IF NOT EXISTS giprozem.requests (
id SERIAL PRIMARY KEY,
request_number VARCHAR(30) UNIQUE NOT NULL,
user_iin VARCHAR(12) NOT NULL,
service_id INTEGER REFERENCES giprozem.services(id),
status_id INTEGER REFERENCES giprozem.request_statuses(id),
title VARCHAR(200) NOT NULL,
description TEXT,
address TEXT,
coordinates JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP
);
-- Таблица документов (хранение бинарных данных файла)
CREATE TABLE IF NOT EXISTS giprozem.documents (
id SERIAL PRIMARY KEY,
request_id INTEGER REFERENCES giprozem.requests(id) ON DELETE CASCADE,
filename VARCHAR(255) NOT NULL,
original_filename VARCHAR(255) NOT NULL,
file_data BYTEA NOT NULL,
file_size BIGINT NOT NULL,
mime_type VARCHAR(100),
description VARCHAR(500),
uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uploaded_by VARCHAR(12) NOT NULL
);
-- Таблица последовательности номеров заявок
CREATE TABLE IF NOT EXISTS giprozem.request_number_sequence (
service_code VARCHAR(10) NOT NULL,
date_part VARCHAR(6) NOT NULL,
last_sequence INTEGER NOT NULL DEFAULT 0,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица участков пользователя (вкладка "Мои участки и отводы")
CREATE TABLE IF NOT EXISTS giprozem.user_plots (
id SERIAL PRIMARY KEY,
user_iin VARCHAR(12) NOT NULL,
name TEXT NOT NULL,
location TEXT,
cadastral_number VARCHAR(20),
egkn_id VARCHAR(20),
coordinates JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Журнал действий пользователей
CREATE TABLE IF NOT EXISTS giprozem.user_activity_logs (
id SERIAL PRIMARY KEY,
user_iin VARCHAR(12) NOT NULL,
action_type VARCHAR(50) NOT NULL,
action_description TEXT,
resource_type VARCHAR(50),
resource_id VARCHAR(100),
ip_address INET,
user_agent TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
additional_data JSONB
);
-- Индексы для оптимизации
CREATE INDEX IF NOT EXISTS idx_auth_history_iin ON giprozem.auth_history(iin);
CREATE INDEX IF NOT EXISTS idx_auth_history_login_time ON giprozem.auth_history(login_time);
CREATE INDEX IF NOT EXISTS idx_requests_user_iin ON giprozem.requests(user_iin);
CREATE INDEX IF NOT EXISTS idx_requests_status_id ON giprozem.requests(status_id);
CREATE INDEX IF NOT EXISTS idx_documents_request_id ON giprozem.documents(request_id);
CREATE UNIQUE INDEX IF NOT EXISTS ux_user_roles_iin_role ON giprozem.user_roles (iin, role_code);
CREATE UNIQUE INDEX IF NOT EXISTS ux_reqnum_seq_service_date ON giprozem.request_number_sequence (service_code, date_part);
CREATE INDEX IF NOT EXISTS idx_user_plots_user_iin ON giprozem.user_plots (user_iin);
CREATE INDEX IF NOT EXISTS idx_user_activity_logs_user_iin ON giprozem.user_activity_logs (user_iin);
CREATE INDEX IF NOT EXISTS idx_user_activity_logs_created_at ON giprozem.user_activity_logs (created_at);
CREATE INDEX IF NOT EXISTS idx_user_activity_logs_action_type ON giprozem.user_activity_logs (action_type);
source venv/bin/activate # На Windows: venv\Scripts\activate
Проверка активации: В начале командной строки должно появиться (venv).
config.env:# Настройки базы данных PostgreSQL
DATABASE_HOST=192.168.1.100
DATABASE_PORT=5432
DATABASE_NAME=db
DATABASE_USER=postgres
DATABASE_PASSWORD=your_password
DATABASE_SCHEMA=giprozem
# ArcGIS Server URL
ARCGIS_SERV_URL=https://178.89.0.228:56443/arcgis/rest/services
# Геосервер - локальный доступ
GEOSERVER_LOCAL_URL=http://192.168.1.253:8080/geoserver
# Геосервер - глобальный доступ
GEOSERVER_GLOBAL_URL=http://178.89.245.2:8887/geoserver
# Настройки Flask
SECRET_KEY=your-super-secret-key-change-this-in-production
DEBUG=True
HOST=0.0.0.0
PORT=8080
# Настройки аутентификации
SESSION_TIMEOUT=3600
# Настройки логирования
LOG_LEVEL=INFO
LOG_FILE=app.log
# Настройки прокси
PROXY_TIMEOUT=30
PROXY_VERIFY_SSL=False
# Настройки карты (координаты центра Казахстана)
DEFAULT_MAP_CENTER_LAT=48.0196
DEFAULT_MAP_CENTER_LON=66.9237
DEFAULT_MAP_ZOOM=6
# Лимиты документов
MAX_DOCUMENTS_PER_REQUEST=10
MAX_DOCUMENT_SIZE_MB=10
python compile_translations.py
python3 app.py
Проверка запуска: В консоли должны появиться сообщения о запуске Flask и выборе геосервера.
http://localhost:8080
После запуска приложения проверьте:
Доступность веб-интерфейса:
curl -I http://localhost:8080
Статус геосервера:
curl http://localhost:8080/api/geoserver/status
Проверка ArcGIS Server:
curl -I "http://localhost:8080/Proxy/Map/Kaz/MapServer?f=json"
Подключение к БД:
logs/app.logПроверка зависимостей:
pip list | grep -E "(Flask|psycopg|requests|cryptography)"
LandMonitoring/
├── app.py # Точка входа Flask
├── run_server.py # Альтернативный запуск сервера
├── app/ # Пакет приложения (бэкенд модули)
│ ├── __init__.py # create_app(): конфиг, Babel, блюпринты
│ ├── logging_setup.py # настройка логирования
│ ├── extensions.py # экстеншены (babel)
│ ├── i18n.py # выбор локали
│ ├── blueprints/
│ │ ├── public.py # GET /
│ │ ├── proxy.py # GET /Proxy/Wms, GET /Proxy/Wfs, GET /Proxy/Map/*
│ │ ├── account.py # POST /Account/Login, GET /Account/Logout
│ │ ├── api.py # REST API (настройки, заявки, документы, справочники)
│ │ └── egkn.py # GET /get-zu/<kad_nomer> - поиск по ЕГКН
│ ├── services/
│ │ ├── certificates.py # CertificateWorker - работа с ЭЦП
│ │ ├── notifications.py # NotificationService - генерация PDF уведомлений
│ │ ├── arcgis.py # ArcGISService - работа с ArcGIS REST API
│ │ └── coordinates_parser.py # Парсинг координат
│ └── repositories/
│ └── database_manager.py # DatabaseManager - слой доступа к данным
├── config.py # Конфигурация приложения
├── config.env # Переменные окружения
├── compile_translations.py # Компиляция переводов
├── babel.cfg # Конфигурация Babel
├── requirements.txt # Зависимости Python
├── README.md # Документация проекта
├── DEPLOYMENT.md # Инструкции по деплою
├── docker.md # Документация по Docker
├── IMPORT_FEATURES.md # Документация по импорту функций
├── PyArmor.md # Документация по защите кода
├── windows.md # Инструкция развертывания на Windows
├── LICENSE # Лицензия проекта
├── Dockerfile # Docker образ приложения
├── compose.yaml # Docker Compose конфигурация
├── static/
│ ├── css/
│ │ ├── app.css
│ │ ├── map.css
│ │ └── notifications.css
│ ├── js/
│ │ ├── app.js # Точка входа ES-модуля
│ │ ├── notifications.js # Модуль уведомлений
│ │ ├── map.js # Картографический функционал
│ │ ├── egkn_districts.json # Справочник областей и районов для ЕГКН
│ │ ├── eds/
│ │ │ └── eds.js # ЭЦП функционал
│ │ └── modules/ # Функциональные модули
│ │ ├── auth.js # Авторизация и управление сессиями
│ │ ├── coordinates-import.js # Импорт координат
│ │ ├── coordinates-utils.js # Утилиты для работы с координатами
│ │ ├── documents.js # Загрузка и управление документами
│ │ ├── geojson.js # Работа с GeoJSON данными
│ │ ├── language.js # Смена языка интерфейса
│ │ ├── logging.js # Модуль логирования действий пользователей
│ │ ├── menu.js # Обработчики меню
│ │ ├── modals.js # Жизненный цикл модальных окон
│ │ ├── order-map.js # Карта в модалке создания заявки
│ │ ├── orders.js # Создание заявок на услуги
│ │ ├── personal.js # Личный кабинет и управление пользователями
│ │ ├── request-details.js # Просмотр детальной информации о заявках
│ │ ├── requests.js # Управление заявками и фильтрация
│ │ ├── search.js # Поиск земельных участков по кадастровому номеру
│ │ ├── services.js # Загрузка справочников
│ │ ├── settings.js # Настройки пользователя
│ │ ├── system-logs.js # Работа с системными логами
│ │ └── validators.js # Валидация форм
│ ├── data/
│ │ └── ocsk-services.json # JSON файл с OCSK сервисами
│ ├── images/
│ │ └── logo.png
│ ├── icons/
│ │ └── bootstrap-icons/ # Bootstrap Icons
│ ├── favicon.ico # Иконка сайта
│ └── lib/ # Внешние библиотеки
│ ├── bootstrap/ # Bootstrap 5
│ ├── jquery/ # jQuery
│ ├── leaflet/ # Leaflet.js и плагины
│ ├── esri-leaflet-v2.1.4/ # ESRI Leaflet для ArcGIS
│ ├── proj4.js # Проекции координат
│ ├── proj4leaflet.js # Проекции для Leaflet
│ └── turf.min.js # Геопространственные вычисления
├── templates/
│ ├── layouts/
│ │ └── base.html
│ ├── pages/
│ │ ├── index.html # Главная страница
│ │ ├── test.html # Страница тестирования ArcGIS сервисов
│ │ ├── testview.html # Детальный просмотр сервиса
│ │ ├── license.html # Страница лицензии
│ │ └── readme.html # Страница README
│ ├── partials/
│ │ ├── navbar.html # Навигационная панель
│ │ ├── footer.html # Подвал страницы
│ │ ├── map_controls.html # Элементы управления картой
│ │ ├── opacity_panel.html # Панель прозрачности слоев
│ │ ├── personal_cabinet_button.html
│ │ └── toast.html # Шаблон уведомлений
│ └── modals/
│ ├── agro_settings.html # Настройки агрохимии
│ ├── confirm_delete.html # Подтверждение удаления
│ ├── logging.html # Логирование действий пользователей
│ ├── order_service.html # Создание заявки на услугу
│ ├── personal_cabinet.html # Личный кабинет
│ ├── plots_edit.html # Редактирование участков
│ ├── request_details.html # Детальный просмотр заявки
│ ├── requests.html # Таблица заявок
│ ├── search_result.html # Результаты поиска участков
│ ├── settings.html # Настройки пользователя
│ ├── user_edit.html # Редактирование пользователя
│ └── user_management.html # Управление пользователями
└── translations/
├── messages.pot # Шаблон переводов
├── ru/
│ └── LC_MESSAGES/
│ ├── messages.po # Русские переводы
│ └── messages.mo # Скомпилированные переводы
└── kk/
└── LC_MESSAGES/
├── messages.po # Казахские переводы
└── messages.mo # Скомпилированные переводы
GET / - Главная страница приложенияGET /test - Страница просмотра сервисов ArcGIS с измерением времени загрузкиGET /testview - Детальный просмотр конкретного сервиса ArcGISGET /Proxy/Wms - Прокси для WMS запросов (GeoServer)GET /Proxy/Wfs - Прокси для WFS запросов (GeoServer)GET /Proxy/Map/<path:service_path> - Прокси для ArcGIS REST API запросовGET /api/search - Поиск областей и районовPOST /api/login - Вход в системуGET /api/map/layers - Получение слоев картыGET /api/map/basemaps - Получение базовых картGET /api/geoserver/status - Статус геосервераGET /Proxy/Map/* - Проксирование ArcGIS REST API запросовGET /api/settings/plots — список участков текущего пользователяPOST /api/settings/plots — добавление участкаPUT /api/settings/plots/<plot_id> — обновление участкаDELETE /api/settings/plots/<plot_id> — удаление участкаPOST /api/settings/save - Сохранение настроек пользователяGET /api/settings/get - Получение настроек пользователяGET /api/auth/history - История авторизаций пользователяGET /api/requests - Заявки пользователя (с поддержкой include_documents=true)GET /api/all-requests - Все заявки (с поддержкой include_documents=true)GET /api/services - Список услугGET /api/request-statuses - Статусы заявокPOST /api/requests/create - Создание новой заявкиGET /api/document-limits - Лимиты документовPOST /api/requests/<id>/documents - Загрузка документаGET /api/documents/<id> - Скачивание документаDELETE /api/requests/<id>/documents/<doc_id> - Удаление документаDELETE /api/requests/<id> - Удаление заявкиGET /api/users - Список всех пользователейGET /api/users/<iin> - Информация о пользователеPOST /api/users - Добавление пользователяPUT /api/users/<iin> - Обновление пользователяDELETE /api/users/<iin> - Удаление пользователяGET /api/roles - Список ролейPOST /Account/Login - Авторизация по сертификату ЭЦПGET /Account/Logout - Выход из системыGET /api/auth/status - Статус авторизацииGET /api/logs — получение логов с фильтрами и пагинациейGET /api/logs/users/<iin> — логи по пользователюGET /api/logs/export — экспорт логов в CSVDELETE /api/logs/cleanup?days=<N> — очистка старых логовGET /api/system-logs/files — получение списка системных лог файловGET /api/system-logs/content/<filename> — просмотр содержимого лог файлаGET /api/system-logs/download/<filename> — скачивание отдельного лог файлаGET /api/system-logs/download-all — скачивание архива всех лог файловGET /api/requests/<request_id>/details - Получение детальной информации о заявкеGET /api/download-notification/<request_id> - Скачивание PDF уведомления о приеме заявкиGET /api/verify-notification/<request_number> - Верификация уведомления через QR-код (публичный доступ, использует номер заявки)GET /api/requests/<request_id>/notification-status - Проверка наличия уведомления для заявкиPOST /api/set_language - Смена языка интерфейсаGET /ocsk-services - Получение списка ОЦСК сервисов из JSON файлаGET /export/zu-excel - Экспорт данных земельных участков в формат ExcelХранит настройки пользователей:
iin (VARCHAR(12)) - ИИН пользователя (первичный ключ)phone (VARCHAR(20)) - Номер телефонаemail (VARCHAR(100)) - Email адресcreated_at (TIMESTAMP) - Дата создания записиupdated_at (TIMESTAMP) - Дата последнего обновленияХранит историю авторизаций:
id (SERIAL) - Уникальный идентификаторiin (VARCHAR(12)) - ИИН пользователяfio (VARCHAR(200)) - ФИО пользователяlogin_time (TIMESTAMP) - Время входаlogout_time (TIMESTAMP) - Время выходаip_address (VARCHAR(45)) - IP адресuser_agent (TEXT) - User-Agent браузераsuccess (BOOLEAN) - Успешность авторизацииerror_message (TEXT) - Сообщение об ошибкеРоли пользователей:
iin (VARCHAR(12)) - ИИН пользователяrole_code (VARCHAR(10)) - Код роли (user, admin)Справочник услуг:
id (SERIAL) - Уникальный идентификаторcode (VARCHAR(10)) - Код услугиname_ru (VARCHAR(200)) - Название на русскомname_kk (VARCHAR(200)) - Название на казахскомdescription_ru (TEXT) - Описание на русскомdescription_kk (TEXT) - Описание на казахскомprice (DECIMAL(10,2)) - Стоимость услугиduration_days (INTEGER) - Срок выполнения в дняхis_active (BOOLEAN) - Активность услугиСтатусы заявок:
id (SERIAL) - Уникальный идентификаторcode (VARCHAR(10)) - Код статусаname_ru (VARCHAR(100)) - Название на русскомname_kk (VARCHAR(100)) - Название на казахскомcolor (VARCHAR(20)) - Цвет для отображенияЗаявки пользователей:
id (SERIAL) - Уникальный идентификаторrequest_number (VARCHAR(20)) - Номер заявкиuser_iin (VARCHAR(12)) - ИИН пользователяservice_id (INTEGER) - ID услугиstatus_id (INTEGER) - ID статусаtitle (VARCHAR(200)) - Название заявкиdescription (TEXT) - Описаниеaddress (TEXT) - Адрес объектаcoordinates (JSONB) - Геометрия в формате GeoJSONcreated_at (TIMESTAMP) - Время созданияupdated_at (TIMESTAMP) - Время обновленияcompleted_at (TIMESTAMP) - Время завершенияnotification_pdf (BYTEA) - PDF уведомление о приеме заявкиnotification_created_at (TIMESTAMP) - Время создания уведомленияДокументы заявок:
id (SERIAL) - Уникальный идентификаторrequest_id (INTEGER) - ID заявкиfilename (VARCHAR(255)) - Имя файла в системеoriginal_filename (VARCHAR(255)) - Оригинальное имя файлаfile_size (BIGINT) - Размер файла в байтахmime_type (VARCHAR(100)) - MIME-тип файлаdescription (VARCHAR(500)) - Описание документаuploaded_at (TIMESTAMP) - Время загрузкиuploaded_by (VARCHAR(12)) - ИИН загрузившегоПоследовательность номеров заявок:
service_code (VARCHAR(10)) - Код услугиdate_part (VARCHAR(6)) - Часть даты (YYYYMM)last_sequence (INTEGER) - Последний номер последовательностиupdated_at (TIMESTAMP) - Время обновленияУчастки пользователя (вкладка "Мои участки и отводы"):
id (SERIAL) — первичный ключuser_iin (VARCHAR(12)) — ИИН владельцаname (TEXT) — наименование (обязательно)location (TEXT) — местоположениеcadastral_number (VARCHAR(20)) — кадастровый номер (необязательно)egkn_id (VARCHAR(20)) — идентификатор ЕГКН (необязательно)coordinates (JSONB) — координаты (GeoJSON, необязательно)created_at (TIMESTAMP) — дата созданияupdated_at (TIMESTAMP) — дата измененияРекомендуемые индексы:
CREATE INDEX IF NOT EXISTS idx_user_plots_user_iin ON giprozem.user_plots (user_iin);Журнал действий пользователя (для модалки "Логирование"):
id (SERIAL), user_iin (VARCHAR(12))action_type (VARCHAR(50)) — тип действия (напр. login, add_plot, update_plot, delete_plot, ...)action_description (TEXT), resource_type (VARCHAR(50)), resource_id (VARCHAR(100))ip_address (INET), user_agent (TEXT)created_at (TIMESTAMP), additional_data (JSONB)Индексы:
idx_user_activity_logs_user_iin, idx_user_activity_logs_created_at, idx_user_activity_logs_action_typeВ системе предустановлены следующие пользователи:
| ИИН | ФИО | Роль | Описание |
|---|---|---|---|
| 745896125463 | Пользователь Ф | user | Обычный пользователь |
| 951735469875 | Пользователь Ю | admin | Администратор |
| 870629351133 | Виктор С | admin | Администратор |
Приложение ведет детальное логирование всех операций:
logs/app.log (автоматическая ротация при 1MB)Время - Модуль - Уровень - СообщениеПриложение поддерживает настраиваемую схему базы данных через переменную окружения DATABASE_SCHEMA:
# В файле config.env
DATABASE_SCHEMA=giprozem
public (если переменная не задана)giprozem (настроена в config.env)# В коде приложения
schema = self._get_schema() # Получение схемы из конфига
query = f"SELECT * FROM {schema}.users WHERE id = %s" # Использование в SQL
Приложение автоматически проверяет доступность геосерверов при запуске:
GEOSERVER_LOCAL_URL)GEOSERVER_GLOBAL_URL)Для проверки текущего статуса геосервера используйте API:
curl http://localhost:8080/api/geoserver/status
В версии v1.3.7 реализован переход отображения пространственных данных с GeoServer на ArcGIS Server. Это обеспечивает более стабильную работу с картографическими данными и улучшенную производительность.
Двойная система поддержки:
Добавлена новая переменная окружения ARCGIS_SERV_URL:
# ArcGIS Server URL
ARCGIS_SERV_URL=https://178.89.0.228:56443/arcgis/rest/services
1. REST API интеграция:
2. Улучшенная производительность:
3. Расширенная функциональность:
Backend (Flask):
/Proxy/Map/<path:service_path> для проксирования ArcGIS запросовARCGIS_SERV_URL в config.pyFrontend (JavaScript):
getLayerNames() - получение списка слоевgetLayerFeatures() - получение объектов слояgetLegend() - получение легенды слояСтруктура URL для ArcGIS:
/Proxy/Map/Kaz/MapServer # Основные границы /Proxy/Map/U/MapServer # Земельные участки /Proxy/Map/GR_Pch/MapServer # Почвенные карты /Proxy/Map/GR_Rst/MapServer # Геоботанические карты /Proxy/Map/Pch/MapServer # Почвенные карты районов /Proxy/Map/Rst/MapServer # Геоботанические карты районов
Производительность:
Надежность:
Функциональность:
Система полностью совместима с существующим кодом:
Переход выполнен автоматически:
# ArcGIS Server URL
ARCGIS_SERV_URL=https://178.89.0.228:56443/arcgis/rest/services
session.permanent = TrueПриложение использует Flask-Session для безопасного управления сессиями пользователей:
filesystem - сессии хранятся в файловой системеflask_session/ - папка для файлов сессий10800 секунд (3 часа) - настраиваемое время жизни сессии500 - ограничение на количество файлов сессий384 (0o600) - безопасные права доступа к файлам# Настройки Flask-Session
SESSION_TYPE=filesystem
SESSION_FILE_DIR=flask_session
SESSION_FILE_THRESHOLD=500
SESSION_FILE_MODE=384
PERMANENT_SESSION_LIFETIME=10800
Приложение поддерживает локализацию с использованием Flask-Babel. Реализована поддержка русского (ru) и казахского (kk) языков.
translations/
├── messages.pot # Шаблон переводов
├── ru/
│ └── LC_MESSAGES/
│ ├── messages.po # Русские переводы
│ └── messages.mo # Скомпилированные русские переводы
└── kk/
└── LC_MESSAGES/
├── messages.po # Казахские переводы
└── messages.mo # Скомпилированные казахские переводы
python compile_translations.py
Добавьте строку в HTML шаблон с функцией _():
<span>{{ _('Новая строка') }}</span>
Извлеките новые строки:
pybabel extract -F babel.cfg -k _ -o translations/messages.pot .
Обновите файлы переводов:
pybabel update -i translations/messages.pot -d translations -l ru
pybabel update -i translations/messages.pot -d translations -l kk
Отредактируйте файлы .po в папках translations/ru/LC_MESSAGES/ и translations/kk/LC_MESSAGES/
Скомпилируйте переводы:
python compile_translations.py
Перезапустите приложение, чтобы применить новые .mo файлы.
{{ _('Текст для перевода') }}
from flask_babel import gettext as _
text = _('Текст для перевода')
Пользователи могут сменить язык через интерфейс:
Язык сохраняется в сессии и применяется при следующей загрузке страницы.
Ранее для получения заявок и их документов требовалось делать множество отдельных HTTP запросов. Это приводило к медленной загрузке страниц и высокой нагрузке на сервер.
Решение: Добавлен параметр include_documents в API endpoints для получения заявок.
/api/requestsGET /api/requests?include_documents=true
Параметры:
include_documents (boolean) - включить документы в ответlimit - количество заявок (по умолчанию 50)service - фильтр по коду услугиstatus - фильтр по коду статусаnumber - фильтр по номеру заявкиdate - фильтр по дате создания/api/all-requestsGET /api/all-requests?include_documents=true
Параметры:
include_documents (boolean) - включить документы в ответlimit - количество заявок (по умолчанию 100)service - фильтр по коду услугиstatus - фильтр по коду статусаuser - фильтр по ИИН пользователяnumber - фильтр по номеру заявкиdate - фильтр по дате созданияcurl "http://localhost:8080/api/requests"
curl "http://localhost:8080/api/requests?include_documents=true"
curl "http://localhost:8080/api/all-requests?include_documents=true&limit=10&status=CREATED"
Когда include_documents=true, каждая заявка содержит массив документов:
{
"requests": [
{
"id": 1,
"request_number": "240101SERVICE0000001",
"title": "Заявка на услугу",
"documents_count": 2,
"total_size": 1048576,
"documents": [
{
"id": 1,
"request_id": 1,
"filename": "uuid_filename.pdf",
"original_filename": "document.pdf",
"file_size": 524288,
"file_size_formatted": "512.0 КБ",
"mime_type": "application/pdf",
"description": "Описание документа",
"uploaded_at": "2024-01-01T10:00:00",
"uploaded_by": "745896125463"
}
]
}
]
}
Приложение использует Flask-Compress для автоматического gzip сжатия статических файлов и API ответов.
# Настройки в config.py
COMPRESS_MIMETYPES = [
'text/html', 'text/css', 'text/xml', 'application/json', 'application/javascript',
'application/xml+rss', 'text/javascript', 'application/xml', 'text/plain'
]
COMPRESS_LEVEL = 6
COMPRESS_MIN_SIZE = 500
| Файл | Оригинальный размер | Сжатый размер | Экономия |
|---|---|---|---|
map.js |
71KB | ~20-25KB | 65-70% |
personal.js |
23KB | ~7-10KB | 60-70% |
settings.js |
14KB | ~4-6KB | 60-70% |
| CSS файлы | 9.5KB | ~2-3KB | 70-80% |
| JSON API ответы | Зависит от данных | 60-80% сжатие | 60-80% |
# Проверка статических файлов
curl -H "Accept-Encoding: gzip" -I http://localhost:8080/static/js/map.js
# Проверка API ответов
curl -H "Accept-Encoding: gzip" -I http://localhost:8080/api/requests
При сжатии в заголовках ответа появляется:
Content-Encoding: gzip Content-Length: [сжатый размер]
Для добавления нового слоя карты:
Для ArcGIS Server слоев:
static/js/map.js с новыми переменными _esri_*getLayerNames, getLayerFeatures)Для GeoServer слоев:
/api/map/layersstatic/js/map.jsДля добавления новой базовой карты:
/api/map/basemapsДля добавления нового авторизованного пользователя:
_authorize_by_iin() в app/blueprints/account.pyauthorized_usersstatic/js/modules/your-module.jsstatic/js/app.jswindow внутри модуля<script> в шаблоны — используйте существующую точку входа app.jspython test_api.py
python test_frontend_fix.py
Тестирование авторизации:
Тестирование карты:
Тестирование локализации:
Тестирование заявок:
Тестирование управления пользователями (для администраторов):
config.envПроверьте установку psycopg2-binary:
pip list | grep psycopg
Если psycopg2-binary не установлен:
pip install psycopg2-binary
Проверьте права доступа пользователя БД к схеме giprozem
/api/geoserver/statusПроверьте доступность ArcGIS Server:
curl -I "http://localhost:8080/Proxy/Map/Kaz/MapServer?f=json"
Проверьте настройку ARCGIS_SERV_URL в config.env
Убедитесь, что ArcGIS Server доступен по указанному URL
Проверьте логи приложения на ошибки проксирования ArcGIS запросов
Проверьте права доступа к папке сессий:
ls -la flask_session/
chmod 755 flask_session/
Очистите старые сессии:
rm -rf flask_session/*
Проверьте настройки сессий в config.env:
PERMANENT_SESSION_LIFETIME установлен корректноSESSION_FILE_DIR указывает на существующую папкуПроверьте логи приложения на ошибки, связанные с сессиями
python compile_translations.py.pologs/:chmod 755 logs/
Убедитесь, что виртуальное окружение активировано:
echo $VIRTUAL_ENV
Если не активировано, активируйте:
source venv/bin/activate
Проверьте установленные пакеты:
pip list
Если пакеты отсутствуют, переустановите:
pip install -r requirements.txt
В версии v1.3.7 реализован переход отображения пространственных данных с GeoServer на ArcGIS Server. Основные изменения:
ARCGIS_SERV_URL/Proxy/Map/<path:service_path> для ArcGIS REST APIПри возникновении проблем с ArcGIS Server:
ARCGIS_SERV_URLconfig.envDEBUG=False в config.envSECRET_KEYARCGIS_SERV_URLСоздайте Dockerfile:
FROM python:3.8-slim
# Установка системных зависимостей для psycopg2
RUN apt-get update && apt-get install -y \
python3-dev \
libpq-dev \
gcc \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8080
CMD ["python3", "app.py"]
Docker Compose (опционально):
Создайте docker-compose.yml:
version: '3.8'
services:
app:
build: .
ports:
- "8080:8080"
environment:
- DATABASE_HOST=postgres
- DATABASE_PORT=5432
- DATABASE_NAME=landmonitoring
- DATABASE_USER=postgres
- DATABASE_PASSWORD=password
- ARCGIS_SERV_URL=https://178.89.0.228:56443/arcgis/rest/services
- GEOSERVER_LOCAL_URL=http://192.168.1.253:8080/geoserver
- GEOSERVER_GLOBAL_URL=http://178.89.245.2:8887/geoserver
depends_on:
- postgres
volumes:
- ./logs:/app/logs
postgres:
image: postgres:13
environment:
- POSTGRES_DB=landmonitoring
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
postgres_data:
Создайте /etc/systemd/system/landmonitoring.service:
[Unitl]
Description=Land Monitoring
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=app-host
Group=app-host
WorkingDirectory=/opt/LandMonitoring
Environment=PATH=/opt/LandMonitoring/venv/bin
Environment=ARCGIS_SERV_URL=https://178.89.0.228:56443/arcgis/rest/services
Environment=GEOSERVER_LOCAL_URL=http://192.168.1.253:8080/geoserver
Environment=GEOSERVER_GLOBAL_URL=http://178.89.245.2:8887/geoserver
ExecStart=/opt/LandMonitoring/venv/bin/python /opt/LandMonitoring/app.py
ExecReload=/bin/kill -s HUP $MAINPID
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=app-host
[Install]
WantedBy=multi-user.target
Для развертывания приложения на Windows Server предусмотрена детальная инструкция с использованием современных инструментов:
Полное руководство по развертыванию доступно в файле: windows.md
Реализована система автоматической генерации PDF уведомлений о приеме заявок с QR-кодом для верификации.
NotificationService (app/services/notifications.py)
DatabaseManager (расширен)
notification_pdf)API Endpoints (расширен)
/api/download-notification/<request_id> - скачивание уведомления/api/verify-notification/<request_id> - верификация через QR-код/api/requests/<request_id>/notification-status - статус уведомленияFrontend (расширен)
notification_pdf{NOTIFICATION_DOMAIN}/api/verify-notification/{request_number}config.env (NOTIFICATION_DOMAIN)Уведомление_{номер_заявки}.pdfДобавлены в requirements.txt:
reportlab==4.0.7 qrcode[pil]==7.4.2
В файле config.env добавлена настройка:
# Настройки для QR-кодов уведомлений NOTIFICATION_DOMAIN=http://192.168.1.111:8080
Этот домен используется для генерации полных URL в QR-кодах уведомлений.
PDF уведомления генерируются на двух языках одновременно:
Все элементы документа дублируются на обоих языках:
Для корректного отображения русских и казахских символов в PDF система автоматически ищет и использует системные шрифты с поддержкой кириллицы:
Важно для Docker: В Dockerfile автоматически устанавливаются пакеты fonts-dejavu, fonts-dejavu-core, fonts-dejavu-extra, которые обеспечивают полную поддержку кириллицы в контейнерах Linux.
При отсутствии подходящих системных шрифтов используется Times-Roman как fallback (возможны проблемы с кириллицей).
При создании заявки через API автоматически генерируется уведомление:
# В app/blueprints/api.py
request_id = db_manager.create_request(iin, service_id, title, description, address, coordinates)
if request_id:
# Автоматическая генерация уведомления
request_data = db_manager.get_request_with_service_info(request_id)
user_data = {'iin': iin, 'fio': session.get('user_fio', 'Не указано')}
pdf_data = notification_service.generate_notification_pdf(request_data, user_data)
db_manager.save_notification_pdf(request_id, pdf_data)
// В static/js/modules/requests.js
function downloadNotification(requestId) {
const link = document.createElement('a');
link.href = `/api/download-notification/${requestId}`;
link.download = `Уведомление_${requestId}.pdf`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
Система протестирована:
Все операции с уведомлениями логируются:
Система легко расширяется:
_loaderStack для обработки множественных загрузчиковshowLoader и hideLoader для управления видимостью загрузчиков на основе стекаzuFields3 для дополнительной кадастровой информацииbtn-zu-check на checkZU для лучшей согласованности в обработке чекбоксовgetLayerFeatures для слоев PCH и RSTzuFields2 для дополнительной кадастровой информации, включая "Кадастровый номер" и "Площадь земельного участка"showIdentResult для использования новых полей на основе атрибутов объектов_firstTimePchLoad для отслеживания первого загрузки почвенных карт (PCH)_minZoomToShowAgroLabels с 8 до 9 для оптимизации производительностиagroFields для агрохимических данных (номер поля, площадь поля)enableAgro, disableAgro) для корректной работы при смене районовapp.css для улучшения доступности и визуального оформленияmessages.po (русский и казахский языки)map.js/get-zu/
/ocsk-services для получения списка ОЦСК сервисов из JSON файлаmap_controls.htmlmap.js для работы с ОЦСК даннымиhttps://ags.giprozem.kz/arcgis/rest/services/Ah/MapServeryearob для анализа агрохимических показателейgr{показатель} (grn, grp, grk и т.д.):
agro_settings.html для настройки параметров агрохимии/export/zu-excel для экспорта результатов поиска участковsearch.js для экспорта найденных участковapp.cssmap.jsfonts-dejavu, fonts-dejavu-core, fonts-dejavu-extra)NotificationService для Linux/Docker окруженияDockerfile для автоматической установки необходимых шрифтов при сборке образаsearch.js для обработки логики поиска с полной документациейsearch_result.html для отображения детальных атрибутов найденного участкаapp.css (137 строк новых стилей)/get-zu/<kad_nomer>)map.js
created_at в запросы создания заявок с безопасной обработкой датshowRequestOnMap для визуализации геометрии заявок на картеsimpleReverseCooridnates для реверсирования координат различных геометрических типовproj4leaflet.js для работы с различными системами координатproj4.js и proj4leaflet.js в base.htmlapp/blueprints/egkn.py для работы с Единым государственным кадастром недвижимостиGET /get-zu/<kad_nomer> для поиска земельных участков по кадастровому номеруstatic/js/egkn_districts.json с полным справочником областей и районов КазахстанаEGKN_WFS в config.py для настраиваемого шаблона WFS-запросов к ЕГКНGET /get-zu/<kad_nomer>: поиск участка по кадастровому номеру с валидацией (только цифры, длина 11–12) и определением district_id из static/js/egkn_districts.json.EGKN_WFS в config.py — шаблон WFS-запроса настраивается через config.env; серверный WFS-запрос возвращает GeoJSON или 404, если features пустой.egkn_districts.json и информативные ошибки.AGENTS.md с правилами взаимодействия, код-стайлом и ревьюlandmonitoring-image.tarflask_session/ исключена из трекинга gitsetOpacity и хранится в состоянии картыtemplates/partials/map_controls.html — блок opacity-main с #basemapOpacityRangestatic/js/map.js — обработчик $('input[type=range].range-opacity') вызывает handlePkGkOpacity('basemap', value),_mapLayer?.setOpacity(opacity) и сохраняется _basemapOpacitystatic/css/map.css — оформление панели прозрачности и ползунка.dockerignorelandmonitoring-image.tar) и мелкие исправления репозиторияdata-bs-toggle), удалены устаревшие data-bs-toggle2_translations) и автоперевод заголовка/сообщения в системе уведомлений.po от устаревших записей #~, удалены дубликаты, сняты fuzzy.mowindow.notifications.* теперь автоматически переводятся при наличии словаря _translationsapp)
requests: подтверждена поддержка поля coordinates jsonbresult_file BYTEA, result_created_at TIMESTAMPlock_timeout = 3s, statement_timeout = 10s/api/requests/<id>: принимает title, description, address, status_code, coordinates (json)/api/requests/<id>/result: загрузка файла результата (роль 01/админ)/api/requests/<id>/result-status: наличие результата/api/download-result/<id>: скачивание результата/api/requests/<id>/details: флаг has_resultrequest-details.html: добавлены инпуты для Заголовка/Описание/Адрес, редактор GeoJSONrequest-details.js: корректный режим редактирования, строгий сброс состояния при открытии/закрытии, валидация GeoJSON, обновление таблиц «Заявки»/«Личный кабинет» после сохраненияhas_resulthas_result — использован bool_or(...)result_text удалён из PUT; результат — отдельный endpointDatabaseManager.save_auth_history(...) теперь явно задаёт login_time = CURRENT_TIMESTAMP_ensure_indexes добавлена проверка/установка DEFAULT и безопасный backfill для:
app.user_activity_logs.created_atapp.auth_history.login_timeapp):
NULL значений (миграция данных без простоя)requests добавлены поля result_file BYTEA и result_created_at TIMESTAMPsave_result_file, get_result_file, has_resultPOST /api/requests/<id>/result — загрузка результата (доступ для роли 01 и администратора)GET /api/requests/<id>/result-status — проверка наличия результатаGET|HEAD /api/download-result/<id> — скачивание результата (права, как для уведомлений)GET /api/requests/<id>/details — добавлен флаг has_resultdocuments.js: добавлена функция downloadResult(requestId)requests.js, personal.js: вывод кнопки скачивания результата по has_resultrequest-details.js: загрузка результата (POST) и отображение кнопки скачивания/test для просмотра списка сервисов ArcGIS с возможностью детального просмотра и измерения времени загрузкиArcGISService для работы с ArcGIS REST API/test и /testview для тестирования и мониторинга ArcGIS сервисов/Proxy/Map/<path:service_path> для ArcGIS REST API запросовDATABASE_SCHEMA)public, текущая giprozem_get_schema()/api/requests/<id>/details для получения полных данных заявкиrequest-details.js для управления просмотром заявокnotification_pdf и notification_created_at в таблицу requestssystem-logs.js)user_settings полем notifications_enabledПроект разработан для РГП "ГИПРОЗем" и является проприетарным программным обеспечением.
Республиканское государственное предприятие "ГИПРОЗем"
| Контакт | Информация |
|---|---|
| giprozem@giprozem.kz | |
| 📞 Телефон | +7 700 232 7830 |
| 🌐 Веб-сайт | giprozem.kz |
| 📍 Адрес | Республика Казахстан, город Астана, Проспект Республики 70 |
Виктор С. - Ведущий разработчик
Для получения дополнительной информации, технической поддержки или коммерческих предложений обращайтесь в РГП "ГИПРОЗем".