update logic

This commit is contained in:
o.vodianov 2025-08-04 23:51:02 +04:00
parent bcd5aa45e3
commit c783275c6f
7 changed files with 56 additions and 26 deletions

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ conversations.pkl
*.jpg *.jpg
*.png *.png
*.jpeg *.jpeg
.vscode/

View File

@ -1,6 +1,7 @@
import uuid import uuid
import hashlib import hashlib
import base64 import base64
import re
from datetime import datetime from datetime import datetime
@ -29,3 +30,10 @@ def date_time_formatter(date_time: str) -> datetime:
""" """
dt = datetime.strptime(date_time, '%d.%m.%y %H:%M') dt = datetime.strptime(date_time, '%d.%m.%y %H:%M')
return dt return dt
def is_phone_correct(phone: str) -> bool:
normalized = re.sub(r"[()\s-]", "", phone)
regex = r"^(?:\+7|8|7)\d{10}$"
return re.match(regex, normalized)

View File

@ -108,7 +108,7 @@ async def doctor_action(update: Update, context: ContextTypes.DEFAULT_TYPE):
if action == "approve": if action == "approve":
# Здесь твоя логика верификации врача (например, запись в базу) # Здесь твоя логика верификации врача (например, запись в базу)
approve_doctor(doctor_telegram_id) await approve_doctor(doctor_telegram_id)
logger.info("Врач с ID %s верифицирован.", doctor_telegram_id) logger.info("Врач с ID %s верифицирован.", doctor_telegram_id)
# Отправляем сообщение об успешной верификации # Отправляем сообщение об успешной верификации
await query.edit_message_text( await query.edit_message_text(

View File

@ -1,6 +1,5 @@
from telegram import ( from telegram import (
Update, ReplyKeyboardRemove, Update, InlineKeyboardButton, InlineKeyboardMarkup
InlineKeyboardButton, InlineKeyboardMarkup
) )
from telegram.ext import ( from telegram.ext import (
ContextTypes, ContextTypes,
@ -13,6 +12,7 @@ from telegram.ext import (
from docbot.handlers.utils.cancel_handler import get_cancel_handler from docbot.handlers.utils.cancel_handler import get_cancel_handler
from docbot.handlers.start_handler import get_start_handler from docbot.handlers.start_handler import get_start_handler
from core.enums.dialog_helpers import ConfirmationMessage from core.enums.dialog_helpers import ConfirmationMessage
from core.utils import is_phone_correct
from docbot.services.patients_service import ( from docbot.services.patients_service import (
create_patient, update_patient_phone, get_patient_by_telegram_id, create_patient, update_patient_phone, get_patient_by_telegram_id,
is_user_has_phone is_user_has_phone
@ -28,6 +28,7 @@ ENTER_PATIENT_PHONE = 4
ENTER_DOCTOR_NUMBER = 5 ENTER_DOCTOR_NUMBER = 5
ENTER_CONSULTATION_DATE = 6 ENTER_CONSULTATION_DATE = 6
PAY_CONSULTATION = 7 PAY_CONSULTATION = 7
ERROR_PHONE_NUMBER = 8
STOPPING = 99 STOPPING = 99
@ -109,10 +110,10 @@ async def receive_patient_aceptance(update: Update, context: ContextTypes.DEFAUL
else: else:
user_data['accepted'] = False user_data['accepted'] = False
await update.callback_query.edit_message_text( await update.callback_query.edit_message_text(
text="❌ Вы отказались от обработки персональных данных. Запись на консультацию невозможна.", text="❌ Вы отказались от обработки персональных данных. Запись на консультацию невозможна. Запустите команду /consultation, чтобы начать заново",
parse_mode="Markdown" parse_mode="Markdown"
) )
return STOPPING return ConversationHandler.END
async def choose_consultation_type(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: async def choose_consultation_type(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
@ -155,8 +156,9 @@ async def enter_patient_phone(update: Update, context: ContextTypes.DEFAULT_TYPE
if not has_phone: if not has_phone:
logger.info(f"Ask user {user_id} enter a phone number.") logger.info(f"Ask user {user_id} enter a phone number.")
await update.callback_query.edit_message_text( await update.callback_query.message.reply_text(
text="Пожалуйста, введите ваш номер телефона для записи на консультацию:" text="Пожалуйста, введите ваш номер мобильного телефона для записи на консультацию:\n"
"Без знака +, вида 79991112233"
) )
return ENTER_PATIENT_PHONE return ENTER_PATIENT_PHONE
else: else:
@ -176,13 +178,30 @@ async def receive_patient_phone(update: Update, context: ContextTypes.DEFAULT_TY
# Например, вызов сервиса для обновления информации о пациенте # Например, вызов сервиса для обновления информации о пациенте
# await update_patient_phone(telegram_id=user_id, phone=phone) # await update_patient_phone(telegram_id=user_id, phone=phone)
logger.info((f"Checking user's phone {is_phone_correct(phone=phone)}"))
if not is_phone_correct(phone=phone):
keyboard = [
[
InlineKeyboardButton(
"Изменить",
callback_data="back"
),
]
]
await update.message.reply_text(
text=f"Вы ввели неверный номер телефона: {phone}\n",
parse_mode="Markdown",
reply_markup=InlineKeyboardMarkup(keyboard)
)
return ERROR_PHONE_NUMBER
logger.info((f"receive_patient_phone User {user_id} provided phone: {phone}")) logger.info((f"receive_patient_phone User {user_id} provided phone: {phone}"))
context.user_data['phone'] = phone context.user_data['phone'] = phone
keyboard = [ keyboard = [
[ [
InlineKeyboardButton( InlineKeyboardButton(
"Назад", "Изменить",
callback_data="back" callback_data="back"
), ),
] ]
@ -190,7 +209,7 @@ async def receive_patient_phone(update: Update, context: ContextTypes.DEFAULT_TY
await update.message.reply_text( await update.message.reply_text(
text=f"Ваш номер телефона: {phone}\n" text=f"Ваш номер телефона: {phone}\n"
"Если хотите изменить номер телефона, то нажмите кнопку Назад\n" "Если хотите изменить номер телефона, то нажмите кнопку Изменить\n"
"Если всё ок, то введите номер врача.", "Если всё ок, то введите номер врача.",
parse_mode="Markdown", parse_mode="Markdown",
reply_markup=InlineKeyboardMarkup(keyboard) reply_markup=InlineKeyboardMarkup(keyboard)
@ -201,10 +220,11 @@ async def receive_patient_phone(update: Update, context: ContextTypes.DEFAULT_TY
async def receive_doctor_number(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: async def receive_doctor_number(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = context.user_data['telegram_id'] user_id = context.user_data['telegram_id']
if not context.user_data.get('doctor_number'): if not context.user_data.get('doctor_number'):
patient_phone = context.user_data['phone']
doctor_number = update.message.text.strip() doctor_number = update.message.text.strip()
context.user_data['doctor_number'] = doctor_number context.user_data['doctor_number'] = doctor_number
if not await is_user_has_phone(user_id):
patient_phone = context.user_data['phone']
await update_patient_phone(telegram_id=user_id, phone=patient_phone) await update_patient_phone(telegram_id=user_id, phone=patient_phone)
logger.info((f"Saved patient's phone number {patient_phone}")) logger.info((f"Saved patient's phone number {patient_phone}"))
@ -215,8 +235,7 @@ async def receive_doctor_number(update: Update, context: ContextTypes.DEFAULT_TY
) )
else: else:
logger.info(f"User {user_id} requested correction of their consultation date") logger.info(f"User {user_id} requested correction of their consultation date")
await update.callback_query.answer() await update.effective_message.reply_text(
await update.callback_query.edit_message_text(
text="Введите дату и время консультации в формате ДД.ММ.ГГ ЧЧ:ММ, например, 01.01.23 12:00.", text="Введите дату и время консультации в формате ДД.ММ.ГГ ЧЧ:ММ, например, 01.01.23 12:00.",
parse_mode="Markdown" parse_mode="Markdown"
) )
@ -234,7 +253,7 @@ async def receive_consultation_date(update: Update, context: ContextTypes.DEFAUL
keyboard = [ keyboard = [
[ [
InlineKeyboardButton( InlineKeyboardButton(
"Назад", "Изменить",
callback_data="back" callback_data="back"
), ),
InlineKeyboardButton( InlineKeyboardButton(
@ -246,7 +265,7 @@ async def receive_consultation_date(update: Update, context: ContextTypes.DEFAUL
await update.message.reply_text( await update.message.reply_text(
text=f"Вы ввели следующую дату консультации: {consultation_date_time}\n" text=f"Вы ввели следующую дату консультации: {consultation_date_time}\n"
"Если хотите изменить дату консультации, то нажмите кнопку Назад\n" "Если хотите изменить дату консультации, то нажмите кнопку Изменить\n"
"Если всё ок, то нажмите Продолжить.", "Если всё ок, то нажмите Продолжить.",
parse_mode="Markdown", parse_mode="Markdown",
reply_markup=InlineKeyboardMarkup(keyboard) reply_markup=InlineKeyboardMarkup(keyboard)
@ -257,13 +276,12 @@ async def receive_consultation_date(update: Update, context: ContextTypes.DEFAUL
async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int:
user_id = context.user_data['telegram_id'] user_id = context.user_data['telegram_id']
phone = context.user_data['phone']
consultation_date_time = context.user_data['consultation_date_time'] consultation_date_time = context.user_data['consultation_date_time']
patient = await get_patient_by_telegram_id(user_id) patient = await get_patient_by_telegram_id(user_id)
await create_session( await create_session(
telegram_id=user_id, telegram_id=user_id,
phone=phone, phone=patient.phone,
consultation_date_time=consultation_date_time, consultation_date_time=consultation_date_time,
patient=patient patient=patient
) )
@ -275,6 +293,8 @@ async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -
parse_mode="Markdown" parse_mode="Markdown"
) )
context.user_data.clear()
return ConversationHandler.END return ConversationHandler.END
@ -290,16 +310,17 @@ def get_consultation_handler() -> ConversationHandler:
SEND_ACKNOWLEDGEMENT_INFO: [CallbackQueryHandler(receive_patient_aceptance)], SEND_ACKNOWLEDGEMENT_INFO: [CallbackQueryHandler(receive_patient_aceptance)],
PROCEED_WITH_CONSULTATION: [CallbackQueryHandler(choose_consultation_type)], PROCEED_WITH_CONSULTATION: [CallbackQueryHandler(choose_consultation_type)],
SELECT_CONSULTATION_TYPE: [CallbackQueryHandler(enter_patient_phone)], SELECT_CONSULTATION_TYPE: [CallbackQueryHandler(enter_patient_phone)],
ENTER_PATIENT_PHONE: [MessageHandler(filters=None, callback=receive_patient_phone)], ENTER_PATIENT_PHONE: [MessageHandler(filters=filters.TEXT & ~filters.COMMAND, callback=receive_patient_phone)],
ENTER_DOCTOR_NUMBER: [ ENTER_DOCTOR_NUMBER: [
MessageHandler(filters.TEXT & ~filters.COMMAND, receive_doctor_number), MessageHandler(filters.TEXT & ~filters.COMMAND, receive_doctor_number),
CallbackQueryHandler(enter_patient_phone, pattern="^" + "back" + "$") CallbackQueryHandler(enter_patient_phone, pattern="^" + "back" + "$")
], ],
ENTER_CONSULTATION_DATE: [MessageHandler(filters=None, callback=receive_consultation_date)], ENTER_CONSULTATION_DATE: [MessageHandler(filters=filters.TEXT & ~filters.COMMAND, callback=receive_consultation_date)],
PAY_CONSULTATION: [ PAY_CONSULTATION: [
CallbackQueryHandler(pay_consultation, pattern="^" + "proceed" + "$"), CallbackQueryHandler(pay_consultation, pattern="^" + "proceed" + "$"),
CallbackQueryHandler(receive_doctor_number, pattern="^" + "back" + "$") CallbackQueryHandler(receive_doctor_number, pattern="^" + "back" + "$")
], ],
ERROR_PHONE_NUMBER: [CallbackQueryHandler(enter_patient_phone, pattern="^" + "back" + "$")],
STOPPING: [get_start_handler()], STOPPING: [get_start_handler()],
}, },
fallbacks=[get_cancel_handler()], fallbacks=[get_cancel_handler()],

View File

@ -3,6 +3,7 @@ from datetime import datetime
from sqlalchemy import select from sqlalchemy import select
from db.session import AsyncSessionLocal from db.session import AsyncSessionLocal
from db.models import Patients from db.models import Patients
from core.logging import logger
async def update_patient_phone(telegram_id: int, phone: str) -> bool: async def update_patient_phone(telegram_id: int, phone: str) -> bool:

View File

@ -1,15 +1,13 @@
from __future__ import annotations from __future__ import annotations
import uuid
from datetime import datetime from datetime import datetime
from sqlalchemy import select from sqlalchemy import select
from db.session import AsyncSessionLocal from db.session import AsyncSessionLocal
from db.models import Sessions, Patients, SessionStatusHistory, SessionDateTimeHistory from db.models import Sessions, Patients, SessionStatusHistory, SessionDateTimeHistory
from core.utils import ( from core.utils import (generate_session_code, date_time_formatter)
UUID_code_generator, generate_session_code, date_time_formatter from core.logging import logger
)
async def create_session(telegram_id: int, phone: str, consultation_date_time: str, patient: Patients) -> str: async def create_session(telegram_id: int, phone: str, consultation_date_time: str, patient: Patients) -> str:
@ -18,6 +16,7 @@ async def create_session(telegram_id: int, phone: str, consultation_date_time: s
Возвращает этот код. Возвращает этот код.
""" """
code = generate_session_code(telegram_id=telegram_id, phone=phone, consultation_date_time=consultation_date_time) code = generate_session_code(telegram_id=telegram_id, phone=phone, consultation_date_time=consultation_date_time)
logger.info(f"Uniq session code generated: {code}")
async with AsyncSessionLocal() as session: async with AsyncSessionLocal() as session:
async with session.begin(): async with session.begin():
sessions = Sessions( sessions = Sessions(