mirror of
https://github.com/olegvodyanov/docbot.git
synced 2025-12-19 23:57:05 +03:00
update logic, add time zones, add new db fields, send payment link
This commit is contained in:
parent
547cac174d
commit
dfb3de958b
@ -2,6 +2,7 @@ import uuid
|
||||
import hashlib
|
||||
import base64
|
||||
import re
|
||||
import pytz
|
||||
from datetime import datetime
|
||||
from urllib.parse import urlparse
|
||||
|
||||
@ -11,7 +12,7 @@ def UUID_code_generator(code_length: int) -> str:
|
||||
Генерирует уникальный код в формате UUID.
|
||||
Возвращает строку с кодом.
|
||||
"""
|
||||
return str(uuid.uuid4().hex[:{code_length}].upper())
|
||||
return str(uuid.uuid4().hex[:code_length].upper())
|
||||
|
||||
|
||||
def generate_session_code(telegram_id: int, phone: str, consultation_date_time: str) -> str:
|
||||
@ -40,6 +41,22 @@ def is_phone_correct(phone: str) -> bool:
|
||||
return re.match(regex, normalized)
|
||||
|
||||
|
||||
def get_timezones():
|
||||
return_value = {}
|
||||
for tz in pytz.common_timezones:
|
||||
c = tz.split("/")
|
||||
if len(c) > 1:
|
||||
if c[0] not in return_value.keys():
|
||||
return_value[c[0]] = []
|
||||
return_value[c[0]].append(c[1])
|
||||
|
||||
for i in ["GMT"]:
|
||||
if i in return_value.keys():
|
||||
return_value.pop(i)
|
||||
|
||||
return return_value
|
||||
|
||||
|
||||
def is_valid_url(text: str) -> bool:
|
||||
try:
|
||||
result = urlparse(text)
|
||||
|
||||
@ -83,6 +83,8 @@ class Doctors(Base):
|
||||
__tablename__ = "doctors"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
code: Mapped[str] = mapped_column(unique=True, nullable=True)
|
||||
time_zone: Mapped[Optional[str]] = mapped_column(nullable=True)
|
||||
telegram_id: Mapped[int] = mapped_column(unique=True, nullable=False)
|
||||
name: Mapped[str] = mapped_column(nullable=False)
|
||||
available_formats: Mapped[Optional[List[str]]
|
||||
|
||||
@ -5,6 +5,7 @@ from telegram.ext import (
|
||||
CommandHandler,
|
||||
)
|
||||
|
||||
from core.logging import logger
|
||||
from docbot.services.doctors_service import get_doctors_names
|
||||
from docbot.services.admins_service import get_admin_info
|
||||
|
||||
@ -22,9 +23,14 @@ async def get_doctors(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int
|
||||
return ConversationHandler.END
|
||||
|
||||
doctors = await get_doctors_names()
|
||||
doctors_table = ""
|
||||
for row in doctors:
|
||||
logger.info(f"{row.Doctors.name} {row.VerificationRequests.code}")
|
||||
doctors_table += f"\n- {row.Doctors.name} (код врача: {row.Doctors.code}) (код верификации: {row.VerificationRequests.code})"
|
||||
|
||||
if doctors:
|
||||
await update.message.reply_text(
|
||||
f"📝 Список активных врачей. \n {doctors}",
|
||||
f"📝 Список активных врачей. \n {doctors_table}",
|
||||
parse_mode="Markdown"
|
||||
)
|
||||
return ConversationHandler.END
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from telegram import Update, ReplyKeyboardMarkup, ReplyKeyboardRemove
|
||||
from telegram import Update, ReplyKeyboardMarkup, ReplyKeyboardRemove, InlineKeyboardButton
|
||||
from telegram.ext import (
|
||||
ContextTypes,
|
||||
ConversationHandler,
|
||||
@ -11,7 +11,8 @@ from docbot.handlers.utils.cancel_handler import get_cancel_handler
|
||||
from docbot.services.referral_service import validate_referral_code
|
||||
from docbot.services.doctors_service import create_doctor
|
||||
from core.enums.dialog_helpers import ConfirmationMessage, Acknowledgement
|
||||
from core.utils import UUID_code_generator
|
||||
from core.utils import UUID_code_generator, get_timezones
|
||||
from core.logging import logger
|
||||
|
||||
ASK_REFERRAL_CODE = 1
|
||||
SEND_ACKNOWLEDGEMENT_INFO = 2
|
||||
@ -19,6 +20,8 @@ ASK_NAME = 3
|
||||
ASK_SPECIALITY = 4
|
||||
SEND_DIPLOMA_ACK_INFO = 5
|
||||
SEND_CONSULTATION_TYPE_ACK_INFO = 6
|
||||
ASK_TIMEZONE = 7
|
||||
ASK_CONTINENT = 8
|
||||
|
||||
SEND_ME_REFERRAL_CODE_TEXT = (
|
||||
"✌️ Пожалуйста, пришлите реферальный код, чтобы начать процесс регистрации."
|
||||
@ -34,6 +37,9 @@ SEND_ME_YOUR_SPECIALITY_TEXT = (
|
||||
"📝 Пожалуйста, введите вашу специальность/специальности, в соответствии с которой планируете проводить консультации.\n"
|
||||
"Например: терапевт, кардиолог, невролог и т.д."
|
||||
)
|
||||
SELECT_YOUR_TIMEZONE_TEXT = (
|
||||
"📝 Пожалуйста, выбирете временную зону, в соответствии с которой планируете проводить консультации.\n"
|
||||
)
|
||||
WAIT_FOR_ACTIVATION_TEXT = (
|
||||
"📝 Заявка принята, направьте диплом и аккредитацию с указанием кода верификации {0} в теме письма на адрес электронной почты: docbot@docbot.ru\n"
|
||||
"В этом шаге нужно встроить подсказку: в каком формате направлять диплом, как скачать с госуслуг\n"
|
||||
@ -101,6 +107,43 @@ async def receive_doctor_name(update: Update, context: ContextTypes.DEFAULT_TYPE
|
||||
doctor_name = update.message.text.strip()
|
||||
context.user_data["doctor_name"] = doctor_name
|
||||
|
||||
keyboard = []
|
||||
|
||||
for continent in sorted(get_timezones().keys()):
|
||||
keyboard.append([InlineKeyboardButton(continent)])
|
||||
|
||||
reply_markup = ReplyKeyboardMarkup(keyboard, one_time_keyboard=True)
|
||||
|
||||
await update.message.reply_text(
|
||||
SELECT_YOUR_TIMEZONE_TEXT,
|
||||
parse_mode="Markdown",
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
return ASK_CONTINENT
|
||||
|
||||
|
||||
async def receive_continent(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
keyboard = []
|
||||
|
||||
context.user_data["selected_continent"] = selected_continent = update.message.text
|
||||
|
||||
for continent in sorted(get_timezones()[selected_continent]):
|
||||
keyboard.append([InlineKeyboardButton(continent)])
|
||||
reply_markup = ReplyKeyboardMarkup(keyboard, one_time_keyboard=True)
|
||||
|
||||
await update.message.reply_text(
|
||||
SELECT_YOUR_TIMEZONE_TEXT,
|
||||
parse_mode="Markdown",
|
||||
reply_markup=reply_markup,
|
||||
)
|
||||
return ASK_TIMEZONE
|
||||
|
||||
|
||||
async def receive_time_zone(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
|
||||
context.user_data["time_zone"] = context.user_data["selected_continent"] + "/" + update.message.text
|
||||
|
||||
logger.info(f"User {context.user_data['doctor_telegram_id']} selected timezone {context.user_data['time_zone']}")
|
||||
|
||||
await update.message.reply_text(
|
||||
SEND_ME_YOUR_SPECIALITY_TEXT,
|
||||
parse_mode="Markdown"
|
||||
@ -168,11 +211,15 @@ async def receive_doctor_consultation_packages_acknowledgement_status(update: Up
|
||||
reply_markup=ReplyKeyboardRemove()
|
||||
)
|
||||
|
||||
doc_code = UUID_code_generator(code_length=5)
|
||||
|
||||
await create_doctor(
|
||||
context.user_data["ref_obj"],
|
||||
context.user_data["doctor_telegram_id"],
|
||||
context.user_data["doctor_name"],
|
||||
context.user_data["verification_request_code"]
|
||||
context.user_data["verification_request_code"],
|
||||
code=doc_code,
|
||||
time_zone=context.user_data["time_zone"]
|
||||
)
|
||||
return ConversationHandler.END
|
||||
|
||||
@ -198,6 +245,14 @@ def get_register_doctor_first_stage_handler() -> ConversationHandler:
|
||||
MessageHandler(filters.TEXT & ~filters.COMMAND,
|
||||
receive_doctor_name)
|
||||
],
|
||||
ASK_TIMEZONE: [
|
||||
MessageHandler(filters.TEXT & ~filters.COMMAND,
|
||||
receive_time_zone)
|
||||
],
|
||||
ASK_CONTINENT: [
|
||||
MessageHandler(filters.TEXT & ~filters.COMMAND,
|
||||
receive_continent)
|
||||
],
|
||||
ASK_SPECIALITY: [
|
||||
MessageHandler(filters.TEXT & ~filters.COMMAND,
|
||||
receive_doctor_speciality)
|
||||
|
||||
@ -17,6 +17,7 @@ from docbot.services.patients_service import (
|
||||
create_patient, update_patient_phone, get_patient_by_telegram_id,
|
||||
is_user_has_phone
|
||||
)
|
||||
from docbot.services.doctors_service import get_doctors_payment_link
|
||||
from docbot.services.session_service import create_session
|
||||
from core.logging import logger
|
||||
|
||||
@ -283,7 +284,8 @@ async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -
|
||||
patient=patient
|
||||
)
|
||||
|
||||
link = f"https://example.com/consultation/{user_id}"
|
||||
link = await get_doctors_payment_link(context.user_data['doctor_number'])
|
||||
|
||||
await update.callback_query.answer()
|
||||
await update.callback_query.message.reply_text(
|
||||
f"Чтобы оплатить консультацию перейдите по ссылке {link}.",
|
||||
|
||||
@ -24,6 +24,7 @@ async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> No
|
||||
"/start ‒ Запустить бота\n"
|
||||
"/genref ‒ Сгенерировать новый реферальный код для врача\n"
|
||||
"/doctors ‒ Посмотреть список зарегистрированных врачей\n"
|
||||
"/verify ‒ Верифицировать врача по реферальному коду\n"
|
||||
"/help ‒ Показать это меню\n"
|
||||
)
|
||||
# (При необходимости в будущем можно добавить другие admin-команды)
|
||||
|
||||
@ -24,10 +24,28 @@ async def get_doctor(telegram_id: int) -> Doctors | None:
|
||||
async def get_doctors_names() -> Doctors | None:
|
||||
async with AsyncSessionLocal() as session:
|
||||
result = await session.execute(
|
||||
select(Doctors.name)
|
||||
select(Doctors, VerificationRequests)
|
||||
.join(VerificationRequests, Doctors.id == VerificationRequests.doctor_id)
|
||||
.where(Doctors.is_active)
|
||||
)
|
||||
return result.all()
|
||||
return result.fetchall()
|
||||
|
||||
|
||||
async def get_doctors_payment_link(doctor_code: str) -> str | None:
|
||||
async with AsyncSessionLocal() as session:
|
||||
result = await session.execute(
|
||||
select(PaymentMethod.method)
|
||||
.join(Doctors, PaymentMethod.doctor_id == Doctors.id)
|
||||
.where(
|
||||
Doctors.code == doctor_code,
|
||||
PaymentMethod.is_active.is_(True),
|
||||
PaymentMethod.is_primary.is_(True)
|
||||
)
|
||||
)
|
||||
payment_link = result.scalar_one_or_none()
|
||||
if payment_link:
|
||||
return payment_link
|
||||
return None
|
||||
|
||||
|
||||
async def is_there_primary_payment_method() -> PaymentMethod | None:
|
||||
@ -67,7 +85,7 @@ async def add_doctor(telegram_id: int, name: str, available_formats: Consultatio
|
||||
))
|
||||
|
||||
|
||||
async def create_doctor(referral_obj: ReferralCode, telegram_id: int, name: str, verification_code: str) -> Doctors:
|
||||
async def create_doctor(referral_obj: ReferralCode, telegram_id: int, name: str, verification_code: str, code: str, time_zone: str) -> Doctors:
|
||||
"""
|
||||
Помечает referral_obj как использованный, создаёт запись в таблице Doctors
|
||||
с привязкой к telegram_id и возвращает объект Doctor.
|
||||
@ -84,7 +102,9 @@ async def create_doctor(referral_obj: ReferralCode, telegram_id: int, name: str,
|
||||
name=name,
|
||||
is_active=False,
|
||||
created_at=datetime.utcnow(),
|
||||
referral=referral_obj
|
||||
referral=referral_obj,
|
||||
code=code,
|
||||
time_zone=time_zone
|
||||
)
|
||||
|
||||
verification_request = VerificationRequests()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user