health-apps-backend/apis/endpoints/doctors.py

144 lines
4.4 KiB
Python

from asyncio.log import logger
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List, Dict
from datetime import datetime, timedelta
from sqlalchemy import and_
# database
from database import get_db
# schemas
from models.Doctors import Doctors
from models.Appointments import Appointments
from models.Calendar import Calenders
from schemas.ResponseSchemas import (
Doctor,
DoctorWithAppointments,
DoctorWithCalendar,
CalendarTimeSchema,
)
from schemas.CreateSchemas import DoctorCreate
from schemas.UpdateSchemas import DoctorUpdate
from enums.enums import AppointmentStatus
router = APIRouter()
@router.post("/", response_model=Doctor, status_code=status.HTTP_201_CREATED)
def create_doctor(doctor: DoctorCreate, db: Session = Depends(get_db)):
try:
db_doctor = Doctors(**doctor.model_dump())
db.add(db_doctor)
db.commit()
db.refresh(db_doctor)
return db_doctor
except Exception as e:
db.rollback()
raise HTTPException(
status_code=500,
detail=str(e.__cause__),
) from e
@router.get("/", response_model=List[DoctorWithCalendar])
def read_doctors(
doctor_name: str | None = None,
skip: int = 0,
limit: int = 100,
db: Session = Depends(get_db),
):
query = db.query(Doctors)
if doctor_name:
query = query.filter(Doctors.name.ilike(f"%{doctor_name}%"))
doctors = query.offset(skip).limit(limit).all()
return doctors
@router.get("/available-slots/{doctor_name}", response_model=Dict[str, List[str]])
def get_available_slots(
doctor_name: str | None = None,
date: str | None = datetime.now().strftime("%Y-%m-%d"),
db: Session = Depends(get_db),
):
"""
Get available slots for a doctor on a specific date.
date format: YYYY-MM-DD
"""
# Get the doctor
print(f"-----------------doctor_name: {doctor_name}")
doctor = db.query(Doctors).filter(Doctors.name.ilike(f"%{doctor_name}%")).first()
if not doctor:
raise HTTPException(status_code=404, detail="Doctor not found")
# Get all calendar slots for the doctor
calendar_slots = db.query(Calenders).filter(Calenders.doc_id == doctor.id).all()
if not calendar_slots:
return {"available_slots": []}
available_slots = [slot.time for slot in calendar_slots]
try:
target_date = datetime.strptime(date, "%Y-%m-%d").date()
except ValueError:
raise HTTPException(
status_code=400, detail="Invalid date format. Use YYYY-MM-DD"
)
# Get all appointments for the doctor on the specified date
appointments = (
db.query(Appointments)
.filter(
and_(
Appointments.doctor_id == doctor.id,
Appointments.appointment_time >= target_date,
Appointments.appointment_time < target_date + timedelta(days=1),
)
)
.all()
)
# Remove slots that have appointments
for appointment in appointments:
appointment_time = appointment.appointment_time.strftime("%H:%M")
if appointment_time in available_slots and (
not appointment.status == AppointmentStatus.COMPLETED
):
available_slots.remove(appointment_time)
return {"available_slots": available_slots}
# @router.get("/{doctor_name}", response_model=DoctorWithAppointments)
# def read_doctor(doctor_name: str, db: Session = Depends(get_db)):
# db_doctor = db.query(Doctors).filter(Doctors.name.ilike(f"%{doctor_name}%")).all()
# return db_doctor
@router.put("/{doctor_id}", response_model=Doctor)
def update_doctor(doctor_id: int, doctor: DoctorUpdate, db: Session = Depends(get_db)):
db_doctor = db.query(Doctors).filter(Doctors.id == doctor_id).first()
if db_doctor is None:
raise HTTPException(status_code=404, detail="Doctor not found")
update_data = doctor.model_dump(exclude_unset=True)
for key, value in update_data.items():
setattr(db_doctor, key, value)
db.commit()
db.refresh(db_doctor)
return db_doctor
@router.delete("/{doctor_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_doctor(doctor_id: int, db: Session = Depends(get_db)):
db_doctor = db.query(Doctors).filter(Doctors.id == doctor_id).first()
if db_doctor is None:
raise HTTPException(status_code=404, detail="Doctor not found")
db.delete(db_doctor)
db.commit()
return None