change datetime fields, add upcomming sessions check

This commit is contained in:
Oleg Oleg 2025-11-09 02:15:52 +08:00
parent d310e73708
commit e20f789497
10 changed files with 108 additions and 60 deletions

View File

@ -1,10 +1,10 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime from datetime import datetime
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
from sqlalchemy import String, ForeignKey, BigInteger, UniqueConstraint, Text, Enum from sqlalchemy.sql import func
from sqlalchemy.dialects.postgresql import UUID, ARRAY from sqlalchemy import String, ForeignKey, BigInteger, UniqueConstraint, Text, DateTime
from sqlalchemy.dialects.postgresql import ARRAY
import enum import enum
import uuid
from typing import List, Optional from typing import List, Optional
@ -15,44 +15,39 @@ class Base(DeclarativeBase):
class Sessions(Base): class Sessions(Base):
__tablename__ = "sessions" __tablename__ = "sessions"
id: Mapped[uuid.UUID] = mapped_column( id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
code: Mapped[str] = mapped_column(String(8), unique=True, nullable=False) code: Mapped[str] = mapped_column(String(8), unique=True, nullable=False)
patient_id: Mapped[int] = mapped_column( patient_id: Mapped[int] = mapped_column(
ForeignKey("patients.id", ondelete="CASCADE"), nullable=False) ForeignKey("patients.id", ondelete="CASCADE"), nullable=False)
patient: Mapped["Patients"] = relationship(back_populates="sessions") patient: Mapped["Patients"] = relationship(back_populates="sessions")
sent_at: Mapped[datetime] = mapped_column(nullable=False) sent_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
consulted_at: Mapped[Optional[datetime]] = mapped_column(nullable=True) consulted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
doctor_id: Mapped[int] = mapped_column(ForeignKey("doctors.id")) doctor_id: Mapped[int] = mapped_column(ForeignKey("doctors.id"))
session_status_history: Mapped[List["SessionStatusHistory"]] = relationship( session_status_history: Mapped[List["SessionStatusHistory"]] = relationship(
back_populates="sessions", cascade="all, delete-orphan") back_populates="sessions", cascade="all, delete-orphan")
session_date_time_history: Mapped[List["SessionDateTimeHistory"]] = relationship( session_date_time_history: Mapped[List["SessionDateTimeHistory"]] = relationship(
back_populates="sessions", cascade="all, delete-orphan") back_populates="sessions", cascade="all, delete-orphan")
paid_at: Mapped[Optional[datetime]] = mapped_column(nullable=True) paid_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
class SessionDateTimeHistory(Base): class SessionDateTimeHistory(Base):
__tablename__ = "session_date_time_history" __tablename__ = "session_date_time_history"
id: Mapped[uuid.UUID] = mapped_column( id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) sessions_id: Mapped[int] = mapped_column(ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False)
sessions_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False)
sessions: Mapped["Sessions"] = relationship(back_populates="session_date_time_history") sessions: Mapped["Sessions"] = relationship(back_populates="session_date_time_history")
updated_at: Mapped[datetime] = mapped_column(nullable=False, default=datetime.utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
consultation_date_time: Mapped[Optional[datetime]] = mapped_column(nullable=True) consultation_date_time: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
who_updated: Mapped[Optional[str]] = mapped_column(String(50), nullable=True) who_updated: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
class SessionStatusHistory(Base): class SessionStatusHistory(Base):
__tablename__ = "session_status_history" __tablename__ = "session_status_history"
id: Mapped[uuid.UUID] = mapped_column( id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) sessions_id: Mapped[int] = mapped_column(ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False)
sessions_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False)
sessions: Mapped["Sessions"] = relationship(back_populates="session_status_history") sessions: Mapped["Sessions"] = relationship(back_populates="session_status_history")
updated_at: Mapped[datetime] = mapped_column(nullable=False, default=datetime.utcnow) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
status: Mapped[str] = mapped_column(String(50), nullable=False, default="pending") status: Mapped[str] = mapped_column(String(50), nullable=False, default="pending")
who_updated: Mapped[Optional[str]] = mapped_column(String(50), nullable=True) who_updated: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
@ -62,7 +57,7 @@ class Admins(Base):
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
telegram_id: Mapped[int] = mapped_column(BigInteger, unique=True, nullable=False) telegram_id: Mapped[int] = mapped_column(BigInteger, unique=True, nullable=False)
created_at: Mapped[Optional[datetime]] = mapped_column(nullable=True) created_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
available_payment_methods: Mapped[Optional[List[str]]] = mapped_column( available_payment_methods: Mapped[Optional[List[str]]] = mapped_column(
ARRAY(String), nullable=True) ARRAY(String), nullable=True)
@ -73,8 +68,8 @@ class Patients(Base):
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
telegram_id: Mapped[int] = mapped_column(BigInteger, unique=True, nullable=False) telegram_id: Mapped[int] = mapped_column(BigInteger, unique=True, nullable=False)
phone: Mapped[Optional[str]] = mapped_column(nullable=True) phone: Mapped[Optional[str]] = mapped_column(nullable=True)
created_at: Mapped[datetime] = mapped_column(nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
updated_at: Mapped[Optional[datetime]] = mapped_column(nullable=True) updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
accepted_terms: Mapped[bool] = mapped_column(default=False, nullable=True) accepted_terms: Mapped[bool] = mapped_column(default=False, nullable=True)
sessions: Mapped[List["Sessions"]] = relationship( sessions: Mapped[List["Sessions"]] = relationship(
back_populates="patient", cascade="all, delete-orphan") back_populates="patient", cascade="all, delete-orphan")
@ -92,12 +87,11 @@ class Doctors(Base):
] = mapped_column(ARRAY(String), nullable=True) ] = mapped_column(ARRAY(String), nullable=True)
is_active: Mapped[bool] = mapped_column(default=False, nullable=False) is_active: Mapped[bool] = mapped_column(default=False, nullable=False)
is_verified: Mapped[bool] = mapped_column(default=False, nullable=False) is_verified: Mapped[bool] = mapped_column(default=False, nullable=False)
created_at: Mapped[datetime] = mapped_column(nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
referral_code_id: Mapped[int] = mapped_column( referral_code_id: Mapped[int] = mapped_column(
ForeignKey("referral_codes.id"), nullable=False) ForeignKey("referral_codes.id"), nullable=False)
specialties: Mapped[List[str]] = mapped_column( specialties: Mapped[List[str]] = mapped_column(
ARRAY(String), nullable=False, default=list) ARRAY(String), nullable=False, default=list)
referral: Mapped["ReferralCode"] = relationship( referral: Mapped["ReferralCode"] = relationship(
back_populates="doctor", uselist=False) back_populates="doctor", uselist=False)
sessions: Mapped[List["Sessions"]] = relationship() sessions: Mapped[List["Sessions"]] = relationship()
@ -118,8 +112,8 @@ class ReferralCode(Base):
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
code: Mapped[str] = mapped_column(unique=True, nullable=False) code: Mapped[str] = mapped_column(unique=True, nullable=False)
is_used: Mapped[bool] = mapped_column(default=False, nullable=False) is_used: Mapped[bool] = mapped_column(default=False, nullable=False)
created_at: Mapped[datetime] = mapped_column(nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
used_at: Mapped[Optional[datetime]] = mapped_column(nullable=True) used_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
doctor: Mapped[Optional["Doctors"]] = relationship( doctor: Mapped[Optional["Doctors"]] = relationship(
back_populates="referral", uselist=False) back_populates="referral", uselist=False)
@ -134,8 +128,8 @@ class VerificationRequests(Base):
doctor_id: Mapped[int] = mapped_column( doctor_id: Mapped[int] = mapped_column(
ForeignKey("doctors.id", ondelete="CASCADE"), unique=True, nullable=False) ForeignKey("doctors.id", ondelete="CASCADE"), unique=True, nullable=False)
code: Mapped[str] = mapped_column(unique=True, nullable=False) code: Mapped[str] = mapped_column(unique=True, nullable=False)
sent_at: Mapped[datetime] = mapped_column(nullable=False) sent_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
reviewed_at: Mapped[Optional[datetime]] = mapped_column(nullable=True) reviewed_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
status: Mapped[str] = mapped_column(default=False, nullable=False) status: Mapped[str] = mapped_column(default=False, nullable=False)
# Связь поправлена — связь с doctor через doctor_id # Связь поправлена — связь с doctor через doctor_id
doctor: Mapped["Doctors"] = relationship( doctor: Mapped["Doctors"] = relationship(
@ -154,7 +148,7 @@ class FormLink(Base):
url: Mapped[str] = mapped_column(nullable=False) url: Mapped[str] = mapped_column(nullable=False)
label: Mapped[Optional[str]] = mapped_column(nullable=True) label: Mapped[Optional[str]] = mapped_column(nullable=True)
is_active: Mapped[bool] = mapped_column(default=True, nullable=False) is_active: Mapped[bool] = mapped_column(default=True, nullable=False)
created_at: Mapped[datetime] = mapped_column(nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
doctor: Mapped["Doctors"] = relationship(back_populates="form_links") doctor: Mapped["Doctors"] = relationship(back_populates="form_links")
@ -170,7 +164,7 @@ class PaymentMethod(Base):
payment_api_key: Mapped[str] = mapped_column(nullable=False) payment_api_key: Mapped[str] = mapped_column(nullable=False)
is_active: Mapped[bool] = mapped_column(default=True, nullable=False) is_active: Mapped[bool] = mapped_column(default=True, nullable=False)
is_primary: 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) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
doctor: Mapped["Doctors"] = relationship(back_populates="payment_methods") doctor: Mapped["Doctors"] = relationship(back_populates="payment_methods")
@ -192,9 +186,9 @@ class SessionNotification(Base):
) )
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
session_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False) session_id: Mapped[int] = mapped_column(ForeignKey("sessions.id", ondelete="CASCADE"), nullable=False)
patient_id: Mapped[int] = mapped_column(ForeignKey("patients.id", ondelete="CASCADE"), nullable=False) patient_id: Mapped[int] = mapped_column(ForeignKey("patients.id", ondelete="CASCADE"), nullable=False)
type: Mapped[NotificationType] = mapped_column(nullable=False) type: Mapped[NotificationType] = mapped_column(nullable=False)
created_at: Mapped[datetime] = mapped_column(nullable=False, default=datetime.utcnow) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, server_default=func.now())
sent_at: Mapped[Optional[datetime]] = mapped_column(nullable=True) sent_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
last_error: Mapped[Optional[str]] = mapped_column(Text, nullable=True) last_error: Mapped[Optional[str]] = mapped_column(Text, nullable=True)

View File

@ -14,6 +14,7 @@ from docbot.handlers.utils.help import get_help_handler
from docbot.handlers.utils.unknown import get_unknown_handler from docbot.handlers.utils.unknown import get_unknown_handler
from docbot.handlers.utils.cancel_handler import get_cancel_handler from docbot.handlers.utils.cancel_handler import get_cancel_handler
from docbot.tasks.payments import map_payments from docbot.tasks.payments import map_payments
from docbot.tasks.sessions import get_sessions_with_consultation_datetime
def main(): def main():
@ -46,7 +47,13 @@ def main():
logger.info("Запускаем таски") logger.info("Запускаем таски")
job_queue = app.job_queue job_queue = app.job_queue
payments_mapping_task = job_queue.run_repeating(map_payments, interval=60, first=10) payments_mapping_task = job_queue.run_repeating(
map_payments, interval=60, job_kwargs={'misfire_grace_time': 10}
) # Таска сопоставления оплат сессиям
upcoming_sessions = job_queue.run_repeating(
get_sessions_with_consultation_datetime, interval=10, job_kwargs={'misfire_grace_time': 10}
)
logger.info("Таски запущены") logger.info("Таски запущены")
app.run_polling() app.run_polling()

View File

@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime from datetime import datetime, timezone
from sqlalchemy import select from sqlalchemy import select
@ -78,7 +78,7 @@ async def add_payment_link(telegram_id: int, payment_link: str, payment_api_key:
details="", details="",
is_active=True, is_active=True,
is_primary=False if await is_there_primary_payment_method() else True, is_primary=False if await is_there_primary_payment_method() else True,
created_at=datetime.utcnow() created_at=datetime.now(timezone.utc)
)) ))
@ -90,7 +90,7 @@ async def add_doctor(telegram_id: int, name: str, available_formats: Consultatio
name=name, name=name,
available_formats=available_formats, available_formats=available_formats,
is_active=is_active, is_active=is_active,
created_at=datetime.utcnow() created_at=datetime.now(timezone.utc)
)) ))
@ -103,14 +103,14 @@ async def create_doctor(referral_obj: ReferralCode, telegram_id: int, name: str,
async with session.begin(): async with session.begin():
# помечаем код # помечаем код
referral_obj.is_used = True referral_obj.is_used = True
referral_obj.used_at = datetime.utcnow() referral_obj.used_at = datetime.now(timezone.utc)
# создаём врача # создаём врача
new_doc = Doctors( new_doc = Doctors(
telegram_id=telegram_id, telegram_id=telegram_id,
name=name, name=name,
is_active=False, is_active=False,
created_at=datetime.utcnow(), created_at=datetime.now(timezone.utc),
referral=referral_obj, referral=referral_obj,
code=code, code=code,
time_zone=time_zone time_zone=time_zone
@ -118,10 +118,10 @@ async def create_doctor(referral_obj: ReferralCode, telegram_id: int, name: str,
verification_request = VerificationRequests() verification_request = VerificationRequests()
verification_request.code = verification_code verification_request.code = verification_code
verification_request.requested_at = datetime.utcnow() verification_request.requested_at = datetime.now(timezone.utc)
verification_request.status = ObjectStatuses.SENT.value verification_request.status = ObjectStatuses.SENT.value
verification_request.doctor = new_doc verification_request.doctor = new_doc
verification_request.sent_at = datetime.utcnow() verification_request.sent_at = datetime.now(timezone.utc)
session.add(verification_request) session.add(verification_request)
session.add(new_doc) session.add(new_doc)
await session.commit() await session.commit()

View File

@ -1,5 +1,5 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime from datetime import datetime, timezone
from sqlalchemy import select from sqlalchemy import select
from sqlalchemy.dialects.postgresql import insert as pg_insert from sqlalchemy.dialects.postgresql import insert as pg_insert
@ -32,7 +32,7 @@ async def create_payment_received_once(session_code: str) -> tuple[bool, int | N
session_id=patient_session.id, session_id=patient_session.id,
patient_id=patient.id, patient_id=patient.id,
type=NotificationType.PAYMENT_RECEIVED, type=NotificationType.PAYMENT_RECEIVED,
created_at=datetime.utcnow(), created_at=datetime.now(timezone.utc),
).on_conflict_do_nothing( ).on_conflict_do_nothing(
index_elements=[SessionNotification.session_id, SessionNotification.type] index_elements=[SessionNotification.session_id, SessionNotification.type]
).returning(SessionNotification) ).returning(SessionNotification)
@ -50,7 +50,7 @@ async def mark_notification_sent(notif_id):
async with session.begin(): async with session.begin():
n = await session.get(SessionNotification, notif_id) n = await session.get(SessionNotification, notif_id)
if n: if n:
n.sent_at = datetime.utcnow() n.sent_at = datetime.now(timezone.utc)
async def mark_notification_error(notif_id, err: str): async def mark_notification_error(notif_id, err: str):
async with AsyncSessionLocal() as session: async with AsyncSessionLocal() as session:

View File

@ -1,9 +1,8 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime from datetime import datetime, timezone
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:
@ -22,7 +21,7 @@ async def update_patient_phone(telegram_id: int, phone: str) -> bool:
patient = result.scalar_one_or_none() patient = result.scalar_one_or_none()
if patient: if patient:
patient.phone = phone patient.phone = phone
patient.updated_at = datetime.utcnow() patient.updated_at = datetime.now(timezone.utc)
return True return True
return False return False
@ -38,7 +37,7 @@ async def create_patient(telegram_id: int, terms_acceptance: bool) -> Patients:
async with session.begin(): async with session.begin():
new_patient = Patients( new_patient = Patients(
telegram_id=telegram_id, telegram_id=telegram_id,
created_at=datetime.utcnow(), created_at=datetime.now(timezone.utc),
accepted_terms=terms_acceptance accepted_terms=terms_acceptance
) )
session.add(new_patient) session.add(new_patient)

View File

@ -1,6 +1,6 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime from datetime import datetime, timezone
from sqlalchemy import select from sqlalchemy import select
@ -57,7 +57,7 @@ async def update_payment_and_session(code: str) -> bool:
session_rec = session_result.scalar_one_or_none() session_rec = session_result.scalar_one_or_none()
if not session_rec or session_rec.paid_at is not None: if not session_rec or session_rec.paid_at is not None:
return False return False
session_rec.paid_at = datetime.utcnow() session_rec.paid_at = datetime.now(timezone.utc)
return True return True
except Exception as e: except Exception as e:

View File

@ -1,6 +1,6 @@
import secrets import secrets
import string import string
from datetime import datetime from datetime import datetime, timezone
from sqlalchemy import select from sqlalchemy import select
@ -25,7 +25,7 @@ async def generate_referral_code(length: int = 12) -> str:
exists = result.scalar_one_or_none() exists = result.scalar_one_or_none()
if not exists: if not exists:
new_ref = ReferralCode( new_ref = ReferralCode(
code=referral_code, created_at=datetime.utcnow()) code=referral_code, created_at=datetime.now(timezone.utc))
session.add(new_ref) session.add(new_ref)
await session.commit() await session.commit()
return referral_code return referral_code

View File

@ -1,13 +1,14 @@
from __future__ import annotations from __future__ import annotations
from datetime import datetime from datetime import datetime, timezone
from typing import Sequence
from sqlalchemy import select, join from sqlalchemy import Sequence, Row, select
from db.session import AsyncSessionLocal from db.session import AsyncSessionLocal
from db.models import ( from db.models import (
Sessions, Patients, SessionStatusHistory, SessionDateTimeHistory, Sessions, Patients, SessionStatusHistory, SessionDateTimeHistory,
PaymentsRegistered Doctors
) )
from core.utils import (generate_session_code, date_time_formatter) from core.utils import (generate_session_code, date_time_formatter)
from core.logging import logger from core.logging import logger
@ -25,20 +26,20 @@ async def create_session(telegram_id: int, phone: str, consultation_date_time: s
sessions = Sessions( sessions = Sessions(
code=code, code=code,
patient=patient, patient=patient,
sent_at=datetime.utcnow(), sent_at=datetime.now(timezone.utc),
doctor_id=doctor_id doctor_id=doctor_id
) )
sessions_code_history = SessionStatusHistory( sessions_code_history = SessionStatusHistory(
sessions=sessions, sessions=sessions,
updated_at=datetime.utcnow(), updated_at=datetime.now(timezone.utc),
status="created", status="created",
who_updated="bot" who_updated="bot"
) )
sessions_date_time_history = SessionDateTimeHistory( sessions_date_time_history = SessionDateTimeHistory(
sessions=sessions, sessions=sessions,
updated_at=datetime.utcnow(), updated_at=datetime.now(timezone.utc),
consultation_date_time=date_time_formatter(consultation_date_time), consultation_date_time=date_time_formatter(consultation_date_time),
who_updated="bot" who_updated="bot"
) )
@ -61,10 +62,43 @@ async def mark_consulted(code: str) -> bool:
sc: Sessions | None = result.scalar_one_or_none() sc: Sessions | None = result.scalar_one_or_none()
if not sc: if not sc:
return False return False
sc.consulted_at = datetime.utcnow() sc.consulted_at = datetime.now(timezone.utc)
return True return True
async def get_all_upcomming_sessions() -> Sequence[Row[Sessions]] | bool:
"""
Возвращает все сессии, у которых consulted_at ещё не заполнен.
"""
async with AsyncSessionLocal() as session:
async with session.begin():
q = (
select(
SessionDateTimeHistory.consultation_date_time.label("date"),
Sessions.code.label("code"),
Patients.telegram_id.label("telegram_id"),
Doctors.time_zone.label("time_zone")
)
.join(Sessions, Sessions.id == SessionDateTimeHistory.sessions_id)
.join(Patients, Patients.id == Sessions.patient_id)
.join(Doctors, Doctors.id == Sessions.doctor_id)
.where(Sessions.paid_at.is_not(None), Sessions.consulted_at.is_(None))
.subquery()
)
stmt = (
select(q.c.telegram_id, q.c.code, q.c.date, q.c.time_zone)
.distinct(q.c.code)
.order_by(q.c.code, q.c.date.desc())
)
result = await session.execute(stmt)
sc = result.scalars()
if not sc:
return False
return result.all()
async def get_pending_session(telegram_id: int) -> Sessions | None: async def get_pending_session(telegram_id: int) -> Sessions | None:
""" """
Ищет самую «свежую» сессию по telegram_id, где consulted_at ещё не заполнен. Ищет самую «свежую» сессию по telegram_id, где consulted_at ещё не заполнен.

View File

@ -3,7 +3,7 @@ from telegram.ext import (
) )
from typing import Sequence, List from typing import Sequence, List
from docbot.services.payments_service import get_not_mapped_payments, update_payment_and_session from docbot.services.payments_service import get_not_mapped_payments, update_payment_and_session
from docbot.services.session_service import get_sessions_awaiting_payments, get_patient_telegram_by_session_code from docbot.services.session_service import get_sessions_awaiting_payments
from docbot.services.notifications_service import ( from docbot.services.notifications_service import (
create_payment_received_once, create_payment_received_once,
mark_notification_sent, mark_notification_sent,
@ -23,6 +23,7 @@ PAYMENT_OK_TEXT = (
# Сопоставляем оплаты, которые пришли от продамуса с сессиями, по которым ещё не было оплаты # Сопоставляем оплаты, которые пришли от продамуса с сессиями, по которым ещё не было оплаты
async def map_payments(context: ContextTypes.DEFAULT_TYPE) -> None: async def map_payments(context: ContextTypes.DEFAULT_TYPE) -> None:
logger.info(f"Запуск таски сопоставления оплат сессиям")
not_mapped_payments: Sequence[Row[PaymentsRegistered]] = await get_not_mapped_payments() not_mapped_payments: Sequence[Row[PaymentsRegistered]] = await get_not_mapped_payments()
sessions_awaiting_payments: Sequence[Row[Sessions]] = await get_sessions_awaiting_payments() sessions_awaiting_payments: Sequence[Row[Sessions]] = await get_sessions_awaiting_payments()

View File

@ -0,0 +1,13 @@
from telegram.ext import (
ContextTypes
)
from docbot.services.session_service import get_all_upcomming_sessions
from core.logging import logger
async def get_sessions_with_consultation_datetime(context: ContextTypes.DEFAULT_TYPE) -> None:
logger.info("Fetching sessions with consultation datetime")
sessions = await get_all_upcomming_sessions()
if sessions:
logger.info(f"Found {len(sessions)} upcoming sessions:")
for session in sessions:
logger.info(f"Telegram: {session.telegram_id} Session code: {session.code}, datetime: {session.date}, time_zone: {session.time_zone}")