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