change payment link creation, add price field to doctor table

This commit is contained in:
Oleg Oleg 2025-12-20 23:54:06 +04:00
parent a1933c7b14
commit d12a1105a1
4 changed files with 68 additions and 9 deletions

View File

@ -4,7 +4,9 @@ import base64
import re
import pytz
from datetime import datetime
from decimal import Decimal
from urllib.parse import urlparse
from urllib.parse import urlencode
def UUID_code_generator(code_length: int) -> str:
@ -65,8 +67,20 @@ def is_valid_url(text: str) -> bool:
return False
def make_a_payment_link(base_link: str, code: str, phone: str) -> str:
if base_link and code and phone:
return f"{base_link}/?order_id={code}&customer_phone={phone}&do=pay"
else:
return null
def make_a_payment_link(base_link: str, code: str, phone: str, amount: Decimal, *, service_name: str) -> str | None:
if not all([base_link, code, phone]) or amount is None:
return None
currency = "RUB"
quantity = "1"
params = [
("order_id", code),
("customer_phone", phone),
("products[0][name]", service_name),
("products[0][price]", f"{amount:.2f}"),
("products[0][quantity]", quantity),
("products[0][currency]", currency),
("do", "pay"),
]
return f"{base_link}/?{urlencode(params, doseq=True)}"

View File

@ -4,6 +4,9 @@ from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from sqlalchemy.sql import func
from sqlalchemy import String, ForeignKey, BigInteger, UniqueConstraint, Text, DateTime
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy import Numeric
from decimal import Decimal
import enum
from typing import List, Optional
@ -101,6 +104,7 @@ class Doctors(Base):
back_populates="doctor", cascade="all, delete-orphan")
verification_requests: Mapped[List["VerificationRequests"]] = relationship(
back_populates="doctor", cascade="all, delete-orphan")
consultation_price: Mapped[Optional[Decimal]] = mapped_column(Numeric(12, 2), nullable=True)
def __repr__(self) -> str:
return f"<Doctors(telegram_id={self.telegram_id!r}, name={self.name!r}, is_active={self.is_active})>"

View File

@ -17,10 +17,10 @@ from docbot.services.patients_service import (
is_user_has_phone
)
from docbot.services.doctors_service import (
get_doctors_payment_link, get_doctor_by_code
get_doctors_payment_link, get_doctor_by_code, get_doctor_consultation_price
)
from docbot.services.session_service import create_session
from core.logging import logger, ActorLogger
from core.logging import ActorLogger
from core.exceptions import DatabaseError
from core.enums.dialog_helpers import ConfirmationMessage
from core.utils import is_phone_correct, make_a_payment_link
@ -73,6 +73,7 @@ async def accept_personal_data_agreement(update: Update, context: ContextTypes.D
]
]
context.user_data.clear()
user_data = context.user_data
user_data['telegram_id'] = user_id = update.effective_user.id
@ -118,6 +119,7 @@ async def receive_patient_aceptance(update: Update, context: ContextTypes.DEFAUL
await update.callback_query.edit_message_text(
text="❌ Произошла ошибка при создании вашей записи. Пожалуйста, попробуйте позже."
)
context.user_data.clear()
return ConversationHandler.END
await update.callback_query.edit_message_text(
@ -132,6 +134,7 @@ async def receive_patient_aceptance(update: Update, context: ContextTypes.DEFAUL
text="❌ Вы отказались от обработки персональных данных. Запись на консультацию невозможна. Запустите команду /consultation, чтобы начать заново",
parse_mode="Markdown"
)
context.user_data.clear()
return ConversationHandler.END
@ -241,6 +244,23 @@ async def receive_doctor_number(update: Update, context: ContextTypes.DEFAULT_TY
if not context.user_data.get('doctor_number'):
doctor_number = update.message.text.strip()
context.user_data['doctor_number'] = doctor_number
try:
doctor = await get_doctor_by_code(doctor_number)
actor_logger.info(user_id, f"Doctor found: {doctor}")
except DatabaseError as e:
actor_logger.error(user_id, f"Failed to fetch doctor by code {doctor_number}: {e}")
await update.message.reply_text(
"Не удалось проверить код врача. Попробуйте повторить запрос позже. /"
)
context.user_data.clear()
return ConversationHandler.END
if not doctor:
await update.message.reply_text(
"Врач с таким кодом не найден. Проверьте номер или запросите новый код."
)
context.user_data.pop('doctor_number', None)
return ENTER_DOCTOR_NUMBER
if not await is_user_has_phone(user_id):
patient_phone = context.user_data['phone']
@ -304,6 +324,7 @@ async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -
await update.callback_query.message.reply_text(
"❌ Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже."
)
context.user_data.clear()
return ConversationHandler.END
session_code = ""
@ -321,6 +342,7 @@ async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -
await update.callback_query.message.reply_text(
"❌ Произошла ошибка при создании записи на консультацию. Пожалуйста, попробуйте позже."
)
context.user_data.clear()
return ConversationHandler.END
base_link = await get_doctors_payment_link(context.user_data['doctor_number'])
@ -332,9 +354,20 @@ async def pay_consultation(update: Update, context: ContextTypes.DEFAULT_TYPE) -
"Пожалуйста, проверьте правильность введённого номера и попробуйте снова.",
parse_mode="Markdown"
)
context.user_data.clear()
return ConversationHandler.END
price = await get_doctor_consultation_price(context.user_data['doctor_number'])
if price is None:
await update.callback_query.message.reply_text("Цена консультации ещё не настроена, попробуйте позже. /start")
context.user_data.clear()
return ConversationHandler.END
service_name = "Консультация врача"
payment_link = make_a_payment_link(base_link=base_link, code=session_code, phone=patient.phone)
payment_link = make_a_payment_link(
base_link=base_link, code=session_code, phone=patient.phone, amount=price, service_name=service_name
)
await update.callback_query.answer()
await update.callback_query.message.reply_text(

View File

@ -1,7 +1,7 @@
from __future__ import annotations
from datetime import datetime, timezone
from decimal import Decimal
from sqlalchemy import select
from db.session import AsyncSessionLocal
@ -126,3 +126,11 @@ async def create_doctor(referral_obj: ReferralCode, telegram_id: int, name: str,
session.add(new_doc)
await session.commit()
return new_doc
async def get_doctor_consultation_price(doctor_code: str) -> Decimal | None:
async with AsyncSessionLocal() as session:
result = await session.execute(
select(Doctors.consultation_price)
.where(Doctors.code == doctor_code)
)
return result.scalar_one_or_none()