mirror of
https://github.com/olegvodyanov/docbot.git
synced 2025-12-19 23:57:05 +03:00
add logic
This commit is contained in:
parent
c783275c6f
commit
3c87cc575c
@ -3,6 +3,7 @@ import hashlib
|
||||
import base64
|
||||
import re
|
||||
from datetime import datetime
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
def UUID_code_generator() -> str:
|
||||
@ -37,3 +38,11 @@ def is_phone_correct(phone: str) -> bool:
|
||||
regex = r"^(?:\+7|8|7)\d{10}$"
|
||||
|
||||
return re.match(regex, normalized)
|
||||
|
||||
|
||||
def is_valid_url(text: str) -> bool:
|
||||
try:
|
||||
result = urlparse(text)
|
||||
return all([result.scheme in ["http", "https"], result.netloc])
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@ -168,7 +168,9 @@ class PaymentMethod(Base):
|
||||
"doctors.id", ondelete="CASCADE"), nullable=False)
|
||||
method: Mapped[str] = mapped_column(nullable=False)
|
||||
details: Mapped[Optional[str]] = mapped_column(nullable=True)
|
||||
payment_api_key: Mapped[str] = mapped_column(nullable=False)
|
||||
is_active: Mapped[bool] = mapped_column(default=True, nullable=False)
|
||||
is_primary: Mapped[bool] = mapped_column(default=True, nullable=False)
|
||||
created_at: Mapped[datetime] = mapped_column(nullable=False)
|
||||
|
||||
doctor: Mapped["Doctors"] = relationship(back_populates="payment_methods")
|
||||
|
||||
124
src/docbot/handlers/doctors/add_payments_method.py
Normal file
124
src/docbot/handlers/doctors/add_payments_method.py
Normal file
@ -0,0 +1,124 @@
|
||||
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
|
||||
from telegram.ext import (
|
||||
ContextTypes,
|
||||
ConversationHandler,
|
||||
CommandHandler,
|
||||
MessageHandler,
|
||||
filters,
|
||||
)
|
||||
|
||||
from docbot.handlers.utils.cancel_handler import get_cancel_handler
|
||||
from docbot.services.doctors_service import add_payment_link
|
||||
from docbot.handlers.utils.utils import cleanup_session
|
||||
from core.enums.dialog_helpers import ConfirmationMessage
|
||||
from core.logging import logger
|
||||
from core.utils import is_valid_url
|
||||
|
||||
|
||||
ASK_PAYMENT_LINK = 1
|
||||
ASK_PAYMENT_SYSTEM_API = 2
|
||||
SAVE_PAYMENT_METHOD = 3
|
||||
|
||||
|
||||
async def send_info(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
user_id = update.effective_user.id
|
||||
context.user_data['user_id'] = user_id
|
||||
|
||||
keyboard_accept = [
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
ConfirmationMessage.PROCEED.value,
|
||||
callback_data="accepted"
|
||||
),
|
||||
InlineKeyboardButton(
|
||||
ConfirmationMessage.DECLINE.value,
|
||||
callback_data="declined"
|
||||
),
|
||||
]
|
||||
]
|
||||
|
||||
await update.message.reply_text(
|
||||
text="Вам предстоит последовательно ввести вашу платёжную ссылку и API ключ.\n"
|
||||
"Эти данные нам необходимы для того, чтобы отслеживать состояние платежей по вашей платёжной ссылке.",
|
||||
parse_mode="Markdown",
|
||||
reply_markup=InlineKeyboardMarkup(keyboard_accept),
|
||||
)
|
||||
logger.info(f"Show user {user_id} payment configuration information.")
|
||||
|
||||
return ASK_PAYMENT_LINK
|
||||
|
||||
|
||||
async def ask_payment_link(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
user_id = context.user_data['user_id']
|
||||
|
||||
await update.message.reply_text(
|
||||
text="Введите адрес вашей платёжной ссылки, пожалуйста."
|
||||
)
|
||||
logger.info(f"Ask user {user_id} to enter their payment link.")
|
||||
|
||||
return ASK_PAYMENT_SYSTEM_API
|
||||
|
||||
|
||||
async def ask_payment_system_api(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
payment_link = update.message.text.strip()
|
||||
user_id = context.user_data['user_id']
|
||||
context.user_data['payment_link'] = payment_link
|
||||
|
||||
if is_valid_url(payment_link):
|
||||
logger.info(f"Payment link {payment_link} provided by user {user_id} is valid.")
|
||||
await update.message.reply_text(
|
||||
text="Введите API ключ, который указан у вас личном кабинете плтёжной системы, пожалуйста."
|
||||
)
|
||||
return ASK_PAYMENT_SYSTEM_API
|
||||
else:
|
||||
logger.info(f"Payment link {payment_link} provided by user {user_id} is invalid.")
|
||||
await update.message.reply_text(
|
||||
text="Ссылка на вашу платёжную система не прошла проверку формата."
|
||||
)
|
||||
return ASK_PAYMENT_LINK
|
||||
|
||||
|
||||
async def save_payment_method(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
payment_system_api = update.message.text.strip()
|
||||
user_id = context.user_data['user_id']
|
||||
|
||||
await add_payment_link(
|
||||
telegram_id=user_id,
|
||||
payment_link=context.user_data['payment_link'],
|
||||
payment_api_key=payment_system_api
|
||||
)
|
||||
|
||||
await update.message.reply_text(
|
||||
text="Ваши платёжные данные успешно сохранены!"
|
||||
)
|
||||
context.user_data.clear()
|
||||
|
||||
return ConversationHandler.END
|
||||
|
||||
|
||||
def add_payment_method() -> CommandHandler:
|
||||
"""Фабрика для регистрации в Application."""
|
||||
return CommandHandler("payment_methods", send_info)
|
||||
|
||||
|
||||
def get_add_payment_method_handler() -> ConversationHandler:
|
||||
return ConversationHandler(
|
||||
entry_points=[add_payment_method()],
|
||||
states={
|
||||
ASK_PAYMENT_LINK: [
|
||||
MessageHandler(filters.TEXT & ~filters.COMMAND,
|
||||
ask_payment_link)
|
||||
],
|
||||
ASK_PAYMENT_SYSTEM_API: [
|
||||
MessageHandler(filters.TEXT & ~filters.COMMAND,
|
||||
ask_payment_system_api)
|
||||
],
|
||||
SAVE_PAYMENT_METHOD: [
|
||||
MessageHandler(filters.TEXT & ~filters.COMMAND,
|
||||
save_payment_method)
|
||||
],
|
||||
},
|
||||
fallbacks=[get_cancel_handler()],
|
||||
name="add_payment_method",
|
||||
persistent=True,
|
||||
)
|
||||
@ -163,7 +163,8 @@ async def receive_doctor_consultation_packages_acknowledgement_status(update: Up
|
||||
|
||||
await update.message.reply_text(
|
||||
ALL_INFORMATION_RECEIVED_TEXT,
|
||||
parse_mode="Markdown"
|
||||
parse_mode="Markdown",
|
||||
reply_markup=ReplyKeyboardRemove
|
||||
)
|
||||
|
||||
await create_doctor(
|
||||
|
||||
@ -54,7 +54,6 @@ keyboard = [
|
||||
|
||||
|
||||
async def accept_personal_data_agreement(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
|
||||
keyboard_accept = [
|
||||
[
|
||||
InlineKeyboardButton(
|
||||
@ -92,8 +91,6 @@ async def accept_personal_data_agreement(update: Update, context: ContextTypes.D
|
||||
|
||||
|
||||
async def receive_patient_aceptance(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
# Здесь можно добавить логику обработки согласия пациента
|
||||
|
||||
user_data = context.user_data
|
||||
await update.callback_query.answer()
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
from telegram import Update, ReplyKeyboardMarkup
|
||||
from telegram import Update, ReplyKeyboardMarkup, ReplyKeyboardRemove
|
||||
from telegram.ext import ContextTypes, CommandHandler
|
||||
|
||||
from docbot.services.admins_service import get_admin_info
|
||||
from docbot.services.doctors_service import get_doctor_info
|
||||
from docbot.services.doctors_service import get_doctor
|
||||
|
||||
|
||||
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||
@ -28,21 +28,15 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
return
|
||||
|
||||
# 2) Проверим, зарегистрирован ли врач
|
||||
if await get_doctor_info(user_id):
|
||||
if await get_doctor(user_id):
|
||||
text = (
|
||||
"👨⚕️ *Меню доктора*:\n\n"
|
||||
"/start ‒ Запустить бота\n"
|
||||
"/sessions ‒ Посмотреть список пациентов (или текущих сессий)\n"
|
||||
"/markconsulted <CODE> ‒ Отметить, что пациент с кодом <CODE> получил консультацию\n"
|
||||
"/help ‒ Показать это меню\n"
|
||||
)
|
||||
# Можно предлагать докторам также специальные кнопки:
|
||||
keyboard = ReplyKeyboardMarkup(
|
||||
[["/sessions"], ["/markconsulted <CODE>"], ["/help"]],
|
||||
one_time_keyboard=True,
|
||||
resize_keyboard=True
|
||||
)
|
||||
await update.message.reply_text(text, parse_mode="Markdown", reply_markup=keyboard)
|
||||
|
||||
await update.message.reply_text(text, parse_mode="Markdown")
|
||||
return
|
||||
|
||||
# 3) Иначе — это пациент (незарегистрированный/обычный пользователь)
|
||||
@ -53,12 +47,8 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
"/send_form ‒ Отправить ссылку на заполненную анкету\n"
|
||||
"/help ‒ Показать это меню\n"
|
||||
)
|
||||
keyboard = ReplyKeyboardMarkup(
|
||||
[["/form", "/consult"], ["/help"]],
|
||||
one_time_keyboard=True,
|
||||
resize_keyboard=True
|
||||
)
|
||||
await update.message.reply_text(text, parse_mode="Markdown", reply_markup=keyboard)
|
||||
|
||||
await update.message.reply_text(text, parse_mode="Markdown")
|
||||
|
||||
|
||||
def get_help_handler() -> CommandHandler:
|
||||
|
||||
10
src/docbot/handlers/utils/utils.py
Normal file
10
src/docbot/handlers/utils/utils.py
Normal file
@ -0,0 +1,10 @@
|
||||
from telegram import Update, ReplyKeyboardRemove
|
||||
from telegram.ext import ContextTypes
|
||||
|
||||
|
||||
async def cleanup_session(update: Update, context: ContextTypes.DEFAULT_TYPE, message: str):
|
||||
context.user_data.clear()
|
||||
await update.message.reply_text(
|
||||
message,
|
||||
reply_markup=ReplyKeyboardRemove()
|
||||
)
|
||||
@ -6,11 +6,13 @@ from docbot.handlers.start_handler import get_start_handler
|
||||
from docbot.handlers.patients.send_form_handler import get_send_form_handler
|
||||
from docbot.handlers.patients.consultation_handler import get_consultation_handler
|
||||
from docbot.handlers.admins.doctors_handler import get_doctors_handler
|
||||
from docbot.handlers.doctors.register_handler import get_register_doctor_first_stage_handler
|
||||
from docbot.handlers.admins.generate_ref import get_referral_handlers
|
||||
from docbot.handlers.admins.verify_handler import get_verify_handler
|
||||
from docbot.handlers.doctors.register_handler import get_register_doctor_first_stage_handler
|
||||
from docbot.handlers.doctors.add_payments_method import get_add_payment_method_handler
|
||||
from docbot.handlers.utils.help import get_help_handler
|
||||
from docbot.handlers.utils.unknown import get_unknown_handler
|
||||
from docbot.handlers.admins.verify_handler import get_verify_handler
|
||||
from docbot.handlers.utils.cancel_handler import get_cancel_handler
|
||||
|
||||
|
||||
def main():
|
||||
@ -24,16 +26,19 @@ def main():
|
||||
.concurrent_updates(concurrent_updates=False)
|
||||
.build()
|
||||
)
|
||||
app.add_handler(get_consultation_handler())
|
||||
app.add_handler(get_start_handler())
|
||||
app.add_handler(get_send_form_handler())
|
||||
app.add_handler(get_doctors_handler())
|
||||
app.add_handler(get_register_doctor_first_stage_handler())
|
||||
app.add_handler(get_referral_handlers())
|
||||
app.add_handler(get_verify_handler())
|
||||
app.add_handler(get_help_handler())
|
||||
app.add_handler(get_unknown_handler())
|
||||
app.add_handler(get_start_handler(), group=0)
|
||||
app.add_handler(get_cancel_handler(), group=0)
|
||||
app.add_handler(get_help_handler(), group=0)
|
||||
app.add_handler(get_consultation_handler(), group=1)
|
||||
app.add_handler(get_send_form_handler(), group=2)
|
||||
app.add_handler(get_doctors_handler(), group=3)
|
||||
app.add_handler(get_register_doctor_first_stage_handler(), group=1)
|
||||
app.add_handler(get_referral_handlers(), group=3)
|
||||
app.add_handler(get_verify_handler(), group=3)
|
||||
app.add_handler(get_unknown_handler(), group=0)
|
||||
app.add_handler(get_add_payment_method_handler(), group=1)
|
||||
app.add_error_handler(get_start_handler())
|
||||
app.add_handlers
|
||||
|
||||
logger.debug("Все хэндлеры зарегистрированы, запускаем polling")
|
||||
app.run_polling()
|
||||
|
||||
@ -5,12 +5,14 @@ from datetime import datetime
|
||||
from sqlalchemy import select
|
||||
|
||||
from db.session import AsyncSessionLocal
|
||||
from db.models import Doctors, VerificationRequests, ReferralCode
|
||||
from db.models import (
|
||||
Doctors, VerificationRequests, ReferralCode, PaymentMethod
|
||||
)
|
||||
from core.enums.consultation_types import Consultation
|
||||
from core.enums.statuses_helpers import ObjectStatuses
|
||||
|
||||
|
||||
async def get_doctor_info(telegram_id: int) -> Doctors | None:
|
||||
async def get_doctor(telegram_id: int) -> Doctors | None:
|
||||
async with AsyncSessionLocal() as session:
|
||||
result = await session.execute(
|
||||
select(Doctors)
|
||||
@ -28,6 +30,31 @@ async def get_doctors_names() -> Doctors | None:
|
||||
return result.all()
|
||||
|
||||
|
||||
async def is_there_primary_payment_method() -> PaymentMethod | None:
|
||||
async with AsyncSessionLocal() as session:
|
||||
result = await session.execute(
|
||||
select(PaymentMethod.method)
|
||||
.where(PaymentMethod.is_primary and PaymentMethod.is_active)
|
||||
)
|
||||
return result.all()
|
||||
|
||||
|
||||
async def add_payment_link(telegram_id: int, payment_link: str, payment_api_key: str):
|
||||
async with AsyncSessionLocal() as session:
|
||||
async with session.begin():
|
||||
doctor = get_doctor(telegram_id=telegram_id)
|
||||
|
||||
session.add(PaymentMethod(
|
||||
doctor_id=doctor.id,
|
||||
method=payment_link,
|
||||
payment_api_key=payment_api_key,
|
||||
details="",
|
||||
is_active=True,
|
||||
is_primary=False if await is_there_primary_payment_method() else True,
|
||||
created_at=datetime.utcnow()
|
||||
))
|
||||
|
||||
|
||||
async def add_doctor(telegram_id: int, name: str, available_formats: Consultation, is_active: bool):
|
||||
async with AsyncSessionLocal() as session:
|
||||
async with session.begin():
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user