Telezab/app/services/regions_service.py
UdoChudo 52e31864b3 feat: Develop web interface
- Implemented the initial version of the web interface.
refactor: Begin Telegram bot refactoring
- Started restructuring the bot’s code for better maintainability.
chore: Migrate to Flask project structure
- Reorganized the application to follow Flask's project structure.
cleanup: Extensive code cleanup
- Removed redundant code and improved readability.

Signed-off-by: UdoChudo <stream@udochudo.ru>
2025-06-10 14:39:11 +05:00

300 lines
12 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from flask import current_app
from sqlalchemy import desc, asc
import logging
from app import Regions, db, Users, Subscriptions
from app.extensions.audit_logger import AuditLogger
auditlog = AuditLogger(db.session)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
class RegionService:
def __init__(self):
self.db = db
self.auditlog = auditlog
self.logger = logger
def get_regions(self, page=1, per_page=10, sort_field='region_id', sort_order='asc'):
self.logger.info(f"Получение регионов: page={page}, per_page={per_page}, sort_field={sort_field}, sort_order={sort_order}")
# Определение порядка сортировки
sort_func = asc if sort_order == 'asc' else desc
# Получение атрибута модели для сортировки
if sort_field:
sort_attr = getattr(Regions, sort_field, Regions.region_id) # По умолчанию сортируем по region_id
else:
sort_attr = Regions.region_id
# Запрос к базе данных с учетом сортировки и пагинации
if sort_field == 'region_id':
regions_query = Regions.query.order_by(sort_func(Regions.region_id.cast(db.Integer))).paginate(page=page, per_page=per_page, error_out=False)
elif sort_field == 'name':
regions_query = Regions.query.order_by(sort_func(Regions.region_name)).paginate(page=page, per_page=per_page, error_out=False)
else:
regions_query = Regions.query.order_by(sort_func(sort_attr)).paginate(page=page, per_page=per_page, error_out=False)
regions_list = [{
'region_id': r.region_id,
'name': r.region_name,
'active': r.active
} for r in regions_query.items]
# bf.app.logger.info(f"Получены регионы: {len(regions_list)} элементов")
return {
'regions': regions_list,
'total_regions': regions_query.total,
'total_pages': regions_query.pages,
'current_page': regions_query.page,
'per_page': regions_query.per_page
}
def get_region_by_id(self, region_id):
# bf.app.logger.info(f"Поиск региона по ID: {region_id}")
# Получение региона по его ID
region = Regions.query.filter_by(region_id=region_id).first()
if region:
# bf.app.logger.info(f"Найден регион: {region.region_name}")
return region.region_name
else:
# bf.app.logger.warning(f"Регион с ID {region_id} не найден.")
return None
def get_region_subscribers(self, region_id):
# bf.app.logger.info(f"Получение подписчиков региона: region_id={region_id}")
try:
region = Regions.query.get(region_id)
if not region:
# bf.app.logger.warning(f"Регион с ID {region_id} не найден")
return {'status': 'error', 'message': 'Регион не найден'}, 404
subscribers = self.db.session.query(
Users).join(Subscriptions).filter(Subscriptions.region_id == region_id).all()
subscribers_list = [{
'chat_id': user.chat_id,
'telegram_id': user.telegram_id,
'email': user.user_email
} for user in subscribers]
# bf.app.logger.info(f"Получены подписчики региона {region_id}: {len(subscribers_list)} элементов")
return {'status': 'success', 'subscribers': subscribers_list}, 200
except Exception as e:
# bf.app.logger.error(f"Ошибка при получении подписчиков региона: {e}")
return {'status': 'error', 'message': str(e)}, 500
def add_region(self, data, user):
region_id = data.get('region_id')
name = data.get('name')
active = data.get('active', True)
self.logger.info(f"Добавление региона: region_id={region_id}, name={name}, active={active}")
try:
if not region_id.isdigit():
self.logger.warning(f"ID региона {region_id} содержит нечисловые символы")
error_msg = 'ID региона должен содержать только числа.'
self.auditlog.regions(
action_type="add",
actor_display_name=user.display_name,
ldap_user_id=user.id,
name=name,
region_id=region_id,
error=error_msg
)
return {'status': 'error', 'message': error_msg}, 400
existing_region = Regions.query.get(region_id)
if existing_region:
self.logger.warning(f"Регион с ID {region_id} уже существует")
error_msg = 'Регион с таким ID уже существует'
self.auditlog.regions(
action_type="add",
actor_display_name=user.display_name,
ldap_user_id=user.id,
name=name,
region_id=region_id,
error=error_msg
)
return {'status': 'error', 'message': error_msg}, 409
region = Regions(region_id=region_id, region_name=name, active=active)
self.db.session.add(region)
self.db.session.commit()
self.logger.info(f"Регион {region_id} успешно добавлен")
self.auditlog.regions(
action_type="add",
actor_display_name=user.display_name,
ldap_user_id=user.id,
name=name,
region_id=region_id
)
return {'status': 'success', 'message': 'Регион добавлен'}, 201
except Exception as e:
self.db.session.rollback()
error_msg = str(e)
self.logger.error(f"Ошибка при добавлении региона: {error_msg}")
self.auditlog.regions(
action_type="add",
actor_display_name=user.display_name,
ldap_user_id=user.id,
name=name,
region_id=region_id,
error=error_msg
)
return {'status': 'error', 'message': error_msg}, 500
def update_region_status(self, data, user):
region_id = data.get('region_id')
new_status = data.get('active')
self.logger.info(f"Изменение статуса региона: region_id={region_id}, new_status={new_status}")
try:
region = Regions.query.get(region_id)
if region:
old_status = region.active
region.active = new_status
self.db.session.commit()
self.logger.info(f"Статус региона {region_id} изменён: {old_status}{new_status}")
self.auditlog.regions(
action_type="toggle",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
old_active=old_status,
active=new_status
)
return {'status': 'success', 'message': 'Статус региона обновлён'}, 200
else:
error_msg = f"Регион с ID {region_id} не найден"
self.logger.warning(error_msg)
self.auditlog.regions(
action_type="toggle",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
active=new_status,
error=error_msg
)
return {'status': 'error', 'message': 'Регион не найден'}, 404
except Exception as e:
self.db.session.rollback()
error_msg = str(e)
self.logger.error(f"Ошибка при изменении статуса региона: {error_msg}")
self.auditlog.regions(
action_type="toggle",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
active=new_status,
error=error_msg
)
return {'status': 'error', 'message': error_msg}, 500
def update_region_name(self, data, user):
region_id = data.get('region_id')
name = data.get('name')
self.logger.info(f"Изменение названия региона: region_id={region_id}, name={name}")
try:
region = Regions.query.get(region_id)
if region:
old_name = region.region_name
region.region_name = name
self.db.session.commit()
self.logger.info(f"Название региона {region_id} изменено с {old_name} на {name}")
self.auditlog.regions(
action_type="rename",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
new_name=name,
old_name=old_name
)
return {'status': 'success', 'message': 'Название региона изменено'}, 200
else:
error_msg = f"Регион с ID {region_id} не найден"
self.logger.warning(error_msg)
self.auditlog.regions(
action_type="rename",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
new_name=name,
error=error_msg
)
return {'status': 'error', 'message': 'Регион не найден'}, 404
except Exception as e:
self.db.session.rollback()
error_msg = str(e)
self.logger.error(f"Ошибка при изменении названия региона: {error_msg}")
self.auditlog.regions(
action_type="rename",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
new_name=name,
error=error_msg
)
return {'status': 'error', 'message': error_msg}, 500
def delete_region(self, region_id, user):
self.logger.info(f"Удаление региона: region_id={region_id}")
try:
region = Regions.query.get(region_id)
if region:
name = region.region_name
self.db.session.delete(region)
self.db.session.commit()
self.logger.info(f"Регион {region_id} успешно удалён")
self.auditlog.regions(
action_type="delete",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
new_name=name
)
return {'status': 'success', 'message': 'Регион удалён'}, 200
else:
error_msg = f"Регион с ID {region_id} не найден"
self.logger.warning(error_msg)
self.auditlog.regions(
action_type="delete",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
error=error_msg
)
return {'status': 'error', 'message': 'Регион не найден'}, 404
except Exception as e:
self.db.session.rollback()
error_msg = str(e)
self.logger.error(f"Ошибка при удалении региона: {error_msg}")
self.auditlog.regions(
action_type="delete",
actor_display_name=user.display_name,
ldap_user_id=user.id,
region_id=region_id,
error=error_msg
)
return {'status': 'error', 'message': error_msg}, 500