mirror of
https://github.com/olegvodyanov/docbot.git
synced 2025-12-19 23:57:05 +03:00
change datetime fields, add upcomming sessions check
This commit is contained in:
parent
d310e73708
commit
e20f789497
@ -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)
|
||||||
@ -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()
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 ещё не заполнен.
|
||||||
|
|||||||
@ -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()
|
||||||
|
|
||||||
|
|||||||
13
src/docbot/tasks/sessions.py
Normal file
13
src/docbot/tasks/sessions.py
Normal 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}")
|
||||||
Loading…
x
Reference in New Issue
Block a user