feat: implement billing system with Pally integration
- Added billing models and repository for handling bills. - Introduced BillingService to manage payment initiation and bill creation. - Updated user service to remove ticket-related functionality. - Refactored settings to include new billing-related fields. - Removed ticket-related handlers and schemas. - Added new billing handlers for processing payments. - Updated database schema with new bills table and status enum. - Enhanced utility functions to calculate prices considering discounts. - Introduced prehandling for non-private messages. - Updated main application to initialize new billing services and repositories.
This commit is contained in:
@@ -1,69 +1,5 @@
|
||||
from aiogram import F, Router
|
||||
from aiogram.filters import Command
|
||||
from aiogram.fsm.context import FSMContext
|
||||
from aiogram.types import CallbackQuery, Message
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from config import settings
|
||||
from keyboards.admins import promotion_confirmation
|
||||
from keyboards.client import close_kb
|
||||
from schemas.di import DependenciesDTO
|
||||
from schemas.promotions import NewPromotionContext
|
||||
from states.admins import AdminStorage
|
||||
from texts import (
|
||||
ADMIN_PROMOTION_CONFIRMATION,
|
||||
ADMIN_PROMOTION_INIT,
|
||||
ADMIN_STANDARD_FALLBACK,
|
||||
SUCCESSFULLY_SENT_PROMOTION,
|
||||
)
|
||||
from aiogram import Router
|
||||
|
||||
router = Router()
|
||||
|
||||
|
||||
@router.message(
|
||||
F.chat.id == settings.admin_group_id, F.message_thread_id.is_(None), Command("push")
|
||||
)
|
||||
async def push_cmd(msg: Message, state: FSMContext):
|
||||
await state.clear()
|
||||
|
||||
ctx = NewPromotionContext(creator_id=msg.from_user.id)
|
||||
await msg.delete()
|
||||
await msg.answer(ADMIN_PROMOTION_INIT, reply_markup=close_kb)
|
||||
|
||||
await state.set_state(AdminStorage.promotion_msg)
|
||||
await state.set_data({"ctx": ctx})
|
||||
|
||||
|
||||
@router.message(F.chat.id == settings.admin_group_id, AdminStorage.promotion_msg)
|
||||
async def send_promotion(msg: Message, state: FSMContext):
|
||||
data = await state.get_data()
|
||||
|
||||
ctx: NewPromotionContext | None = data.get("ctx")
|
||||
if not ctx:
|
||||
await msg.answer(ADMIN_STANDARD_FALLBACK)
|
||||
return
|
||||
|
||||
ctx.message = msg
|
||||
await msg.reply(ADMIN_PROMOTION_CONFIRMATION, reply_markup=promotion_confirmation)
|
||||
|
||||
await state.set_state(AdminStorage.promotion_msg)
|
||||
await state.set_data({"ctx": ctx})
|
||||
|
||||
|
||||
@router.callback_query(AdminStorage.promotion_msg, F.data.in_(["approve", "decline"]))
|
||||
async def promotion_action(
|
||||
cb: CallbackQuery, state: FSMContext, session: AsyncSession, deps: DependenciesDTO
|
||||
):
|
||||
data = await state.get_data()
|
||||
await state.clear()
|
||||
|
||||
await cb.message.delete()
|
||||
if cb.data == "decline":
|
||||
return
|
||||
ctx: NewPromotionContext | None = data.get("ctx")
|
||||
if not (ctx and ctx.creator_id and ctx.message):
|
||||
await cb.message.answer(ADMIN_STANDARD_FALLBACK)
|
||||
return
|
||||
|
||||
sent = await deps.user_service.send_promotion_to_users(session, ctx.message)
|
||||
await cb.message.answer(SUCCESSFULLY_SENT_PROMOTION.format(user_count=len(sent)))
|
||||
# FIXME: Refine newsletter system
|
||||
|
||||
Reference in New Issue
Block a user