import re
from datetime import datetime
from aiogram import F
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database.models import Tariff
from filters.admin import IsAdminFilter
from .. import router
from .common import (
TariffConfigState,
build_cancel_config_kb,
build_config_menu_kb,
build_config_summary_text,
)
@router.callback_query(F.data.startswith("cfg_edit_devices|"), TariffConfigState.choosing_section, IsAdminFilter())
async def ask_devices_config(callback: CallbackQuery, state: FSMContext):
tariff_id = int(callback.data.split("|")[1])
await state.set_state(TariffConfigState.entering_devices)
await state.update_data(tariff_id=tariff_id)
text = (
"π± ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ² ΡΡΡΡΠΎΠΉΡΡΠ².\n\n"
"ΠΠ²Π΅Π΄ΠΈΡΠ΅ ΡΠΏΠΈΡΠΎΠΊ Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ² ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΡΡΡΡΠΎΠΉΡΡΠ² ΡΠ΅ΡΠ΅Π· ΠΏΡΠΎΠ±Π΅Π» ΠΈΠ»ΠΈ Π·Π°ΠΏΡΡΡΡ.\n"
"ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ: 1 3 5\n\n"
"Π§ΠΈΡΠ»ΠΎ 0 ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠ°ΠΊ Π²Π°ΡΠΈΠ°Π½Ρ Π±Π΅Π·Π»ΠΈΠΌΠΈΡΠ°.\n"
"Π§ΡΠΎΠ±Ρ ΡΠΎΠ²ΡΠ΅ΠΌ ΠΎΡΠΊΠ»ΡΡΠΈΡΡ Π²ΡΠ±ΠΎΡ ΡΡΡΡΠΎΠΉΡΡΠ² ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π±Π°Π·ΠΎΠ²ΡΠΉ Π»ΠΈΠΌΠΈΡ ΡΠ°ΡΠΈΡΠ°, ΠΎΡΠΏΡΠ°Π²ΡΡΠ΅ Π΅Π΄ΠΈΠ½ΠΈΡΠ½ΡΠΉ 0."
)
await callback.message.edit_text(text=text, reply_markup=build_cancel_config_kb(tariff_id))
@router.message(TariffConfigState.entering_devices, IsAdminFilter())
async def save_devices_config(message: Message, state: FSMContext, session: AsyncSession):
data = await state.get_data()
tariff_id = data["tariff_id"]
raw_text = message.text.strip()
result = await session.execute(select(Tariff).where(Tariff.id == tariff_id))
tariff = result.scalar_one_or_none()
if not tariff:
await message.answer("β Π’Π°ΡΠΈΡ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½.")
await state.clear()
return
if raw_text == "0":
tariff.device_options = None
else:
try:
parts = [p for p in re.split(r"[,\s]+", raw_text) if p.strip()]
if not parts:
raise ValueError
values: list[int] = []
for part in parts:
v = int(part)
if v < 0:
raise ValueError
values.append(v)
values = sorted(set(values))
tariff.device_options = values
except Exception:
await message.answer(
"β ΠΠ΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ. ΠΠ²Π΅Π΄ΠΈΡΠ΅ ΠΏΠΎΠ»ΠΎΠΆΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠΈΡΠ»Π° ΠΈΠ»ΠΈ 0 ΡΠ΅ΡΠ΅Π· ΠΏΡΠΎΠ±Π΅Π» ΠΈΠ»ΠΈ Π·Π°ΠΏΡΡΡΡ,\n"
"Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ: 1 3 5, 0 1 3 5 (0 ΠΊΠ°ΠΊ Π±Π΅Π·Π»ΠΈΠΌΠΈΡ)\n"
"ΠΈΠ»ΠΈ 0 Π΄Π»Ρ ΠΎΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π²ΡΠ±ΠΎΡΠ° ΡΡΡΡΠΎΠΉΡΡΠ².",
reply_markup=build_cancel_config_kb(tariff_id),
)
return
tariff.updated_at = datetime.utcnow()
await state.set_state(TariffConfigState.choosing_section)
text = build_config_summary_text(tariff)
await message.answer(text=text, reply_markup=build_config_menu_kb(tariff_id))
@router.callback_query(F.data.startswith("cfg_edit_traffic|"), TariffConfigState.choosing_section, IsAdminFilter())
async def ask_traffic_config(callback: CallbackQuery, state: FSMContext):
tariff_id = int(callback.data.split("|")[1])
await state.set_state(TariffConfigState.entering_traffic)
await state.update_data(tariff_id=tariff_id)
text = (
"π¦ ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π²Π°ΡΠΈΠ°Π½ΡΠΎΠ² ΡΡΠ°ΡΠΈΠΊΠ°.\n\n"
"ΠΠ²Π΅Π΄ΠΈΡΠ΅ ΡΠΏΠΈΡΠΎΠΊ Π»ΠΈΠΌΠΈΡΠΎΠ² ΡΡΠ°ΡΠΈΠΊΠ° Π² ΠΠ ΡΠ΅ΡΠ΅Π· ΠΏΡΠΎΠ±Π΅Π» ΠΈΠ»ΠΈ Π·Π°ΠΏΡΡΡΡ.\n"
"ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ: 100 200 500\n\n"
"Π§ΠΈΡΠ»ΠΎ 0 ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠ°ΠΊ Π²Π°ΡΠΈΠ°Π½Ρ Π±Π΅Π·Π»ΠΈΠΌΠΈΡΠ°.\n"
"Π§ΡΠΎΠ±Ρ ΡΠΎΠ²ΡΠ΅ΠΌ ΠΎΡΠΊΠ»ΡΡΠΈΡΡ Π²ΡΠ±ΠΎΡ ΡΡΠ°ΡΠΈΠΊΠ° ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π±Π°Π·ΠΎΠ²ΡΠΉ Π»ΠΈΠΌΠΈΡ ΡΠ°ΡΠΈΡΠ°, ΠΎΡΠΏΡΠ°Π²ΡΡΠ΅ Π΅Π΄ΠΈΠ½ΠΈΡΠ½ΡΠΉ 0."
)
await callback.message.edit_text(text=text, reply_markup=build_cancel_config_kb(tariff_id))
@router.message(TariffConfigState.entering_traffic, IsAdminFilter())
async def save_traffic_config(message: Message, state: FSMContext, session: AsyncSession):
data = await state.get_data()
tariff_id = data["tariff_id"]
raw_text = message.text.strip()
result = await session.execute(select(Tariff).where(Tariff.id == tariff_id))
tariff = result.scalar_one_or_none()
if not tariff:
await message.answer("β Π’Π°ΡΠΈΡ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½.")
await state.clear()
return
if raw_text == "0":
tariff.traffic_options_gb = None
else:
try:
parts = [p for p in re.split(r"[,\s]+", raw_text) if p.strip()]
if not parts:
raise ValueError
values: list[int] = []
for part in parts:
v = int(part)
if v < 0:
raise ValueError
values.append(v)
values = sorted(set(values))
tariff.traffic_options_gb = values
except Exception:
await message.answer(
"β ΠΠ΅ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ. ΠΠ²Π΅Π΄ΠΈΡΠ΅ ΡΠΈΡΠ»Π° 0 ΠΈ Π±ΠΎΠ»ΡΡΠ΅ ΡΠ΅ΡΠ΅Π· ΠΏΡΠΎΠ±Π΅Π» ΠΈΠ»ΠΈ Π·Π°ΠΏΡΡΡΡ,\n"
"Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ: 100 200 500.\n"
"0 ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΊΠ°ΠΊ Π²Π°ΡΠΈΠ°Π½Ρ Π±Π΅Π·Π»ΠΈΠΌΠΈΡΠ° ΠΈΠ»ΠΈ ΠΎΡΠΏΡΠ°Π²ΠΈΡΡ Π΅Π΄ΠΈΠ½ΡΡΠ²Π΅Π½Π½ΡΠΉ 0 Π΄Π»Ρ ΠΎΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π²ΡΠ±ΠΎΡΠ°.",
reply_markup=build_cancel_config_kb(tariff_id),
)
return
tariff.updated_at = datetime.utcnow()
await state.set_state(TariffConfigState.choosing_section)
text = build_config_summary_text(tariff)
await message.answer(text=text, reply_markup=build_config_menu_kb(tariff_id))