feat: clinic doc api
This commit is contained in:
@@ -1,79 +1,257 @@
|
||||
from loguru import logger
|
||||
from schemas.CreateSchemas import ClinicDoctorCreate
|
||||
from schemas.UpdateSchemas import ClinicDoctorUpdate
|
||||
from schemas.ResponseSchemas import ClinicDoctorResponse
|
||||
from schemas.ResponseSchemas import ClinicDoctorResponse, MasterAppointmentTypeResponse
|
||||
from database import get_db
|
||||
from models import ClinicDoctors
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.orm import Session, joinedload, selectinload
|
||||
from services.clinicServices import ClinicServices
|
||||
from exceptions import ResourceNotFoundException
|
||||
from interface.common_response import CommonResponse
|
||||
from sqlalchemy import func
|
||||
from enums.enums import ClinicDoctorStatus
|
||||
from sqlalchemy import func, or_, cast, String
|
||||
from enums.enums import ClinicDoctorStatus, UserType
|
||||
from models import MasterAppointmentTypes, AppointmentRelations
|
||||
from utils.constants import DEFAULT_ORDER, DEFAULT_ORDER_BY
|
||||
|
||||
|
||||
class ClinicDoctorsServices:
|
||||
def __init__(self):
|
||||
self.db: Session = next(get_db())
|
||||
self.clinic_services = ClinicServices()
|
||||
self.logger = logger
|
||||
|
||||
async def create_clinic_doctor(self, clinic_doctor: ClinicDoctorCreate) -> ClinicDoctorResponse:
|
||||
async def create_clinic_doctor(
|
||||
self, user, clinic_doctor: ClinicDoctorCreate
|
||||
) -> ClinicDoctorResponse:
|
||||
try:
|
||||
|
||||
# check if clinic exists
|
||||
self.clinic_services.get_clinic_by_id(clinic_doctor.clinic_id)
|
||||
if user["userType"] != UserType.CLINIC_ADMIN:
|
||||
self.logger.error("user is not clinic admin")
|
||||
raise ResourceNotFoundException(
|
||||
"You are not authorized to perform this action"
|
||||
)
|
||||
|
||||
clinic_doctor = ClinicDoctors(**clinic_doctor.model_dump())
|
||||
self.db.add(clinic_doctor)
|
||||
self.db.commit()
|
||||
self.db.refresh(clinic_doctor)
|
||||
return ClinicDoctorResponse(**clinic_doctor.__dict__.copy())
|
||||
if not user["created_clinics"][0]["id"]:
|
||||
self.logger.error("user has no clinics")
|
||||
raise ResourceNotFoundException(
|
||||
"You are not authorized to perform this action"
|
||||
)
|
||||
|
||||
async def update_clinic_doctor(self, clinic_doctor_id: int, clinic_doctor_data: ClinicDoctorUpdate) -> ClinicDoctorResponse:
|
||||
# check if clinic doctor exists
|
||||
clinic_doctor = self.db.query(ClinicDoctors).filter(ClinicDoctors.id == clinic_doctor_id).first()
|
||||
if clinic_doctor is None:
|
||||
raise ResourceNotFoundException("Clinic doctor not found")
|
||||
# verify all appointment types exist in a single query
|
||||
if clinic_doctor.appointmentTypes:
|
||||
existing_types = {
|
||||
t.id
|
||||
for t in self.db.query(MasterAppointmentTypes.id)
|
||||
.filter(
|
||||
MasterAppointmentTypes.id.in_(clinic_doctor.appointmentTypes)
|
||||
)
|
||||
.all()
|
||||
}
|
||||
missing_types = set(clinic_doctor.appointmentTypes) - existing_types
|
||||
if missing_types:
|
||||
raise ResourceNotFoundException(
|
||||
f"Appointment types not found: {', '.join(map(str, missing_types))}"
|
||||
)
|
||||
|
||||
if clinic_doctor_data.clinic_id != clinic_doctor.clinic_id:
|
||||
# check if clinic exists
|
||||
self.clinic_services.get_clinic_by_id(clinic_doctor_data.clinic_id)
|
||||
await self.clinic_services.get_clinic_by_id(user["created_clinics"][0]["id"])
|
||||
|
||||
# Update the existing object with new values
|
||||
update_data = clinic_doctor_data.model_dump(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(clinic_doctor, key, value)
|
||||
|
||||
self.db.add(clinic_doctor)
|
||||
self.db.commit()
|
||||
self.db.refresh(clinic_doctor)
|
||||
return ClinicDoctorResponse(**clinic_doctor.__dict__.copy())
|
||||
# exclude appointmentTypes from clinic_doctor
|
||||
clinic_doctor_db = ClinicDoctors(
|
||||
name=clinic_doctor.name,
|
||||
clinic_id=user["created_clinics"][0]["id"],
|
||||
role=clinic_doctor.role,
|
||||
status=ClinicDoctorStatus.ACTIVE,
|
||||
)
|
||||
self.db.add(clinic_doctor_db)
|
||||
self.db.flush()
|
||||
# create clinic doctor appointment types
|
||||
for appointment_type_id in clinic_doctor.appointmentTypes:
|
||||
clinic_doctor_appointment_type = AppointmentRelations(
|
||||
clinic_doctor_id=clinic_doctor_db.id,
|
||||
appointment_type_id=appointment_type_id,
|
||||
)
|
||||
self.db.add(clinic_doctor_appointment_type)
|
||||
|
||||
self.db.commit()
|
||||
|
||||
return
|
||||
except Exception as e:
|
||||
self.logger.error(e)
|
||||
self.db.rollback()
|
||||
raise e
|
||||
|
||||
async def update_clinic_doctor(
|
||||
self, user, clinic_doctor_id: int, clinic_doctor_data: ClinicDoctorUpdate
|
||||
) -> ClinicDoctorResponse:
|
||||
|
||||
try:
|
||||
|
||||
if user["userType"] != UserType.CLINIC_ADMIN:
|
||||
self.logger.error("user is not clinic admin")
|
||||
raise ResourceNotFoundException(
|
||||
"You are not authorized to perform this action"
|
||||
)
|
||||
|
||||
if not user["created_clinics"][0]["id"]:
|
||||
self.logger.error("user has no clinics")
|
||||
raise ResourceNotFoundException(
|
||||
"You are not authorized to perform this action"
|
||||
)
|
||||
|
||||
# verify all appointment types exist in a single query
|
||||
if clinic_doctor_data.appointmentTypes:
|
||||
existing_types = {
|
||||
t.id
|
||||
for t in self.db.query(MasterAppointmentTypes.id)
|
||||
.filter(
|
||||
MasterAppointmentTypes.id.in_(
|
||||
clinic_doctor_data.appointmentTypes
|
||||
)
|
||||
)
|
||||
.all()
|
||||
}
|
||||
|
||||
missing_types = set(clinic_doctor_data.appointmentTypes) - existing_types
|
||||
if missing_types:
|
||||
raise ResourceNotFoundException(
|
||||
f"Appointment types not found: {', '.join(map(str, missing_types))}"
|
||||
)
|
||||
|
||||
# check if clinic doctor exists
|
||||
clinic_doctor = (
|
||||
self.db.query(ClinicDoctors)
|
||||
.filter(ClinicDoctors.id == clinic_doctor_id)
|
||||
.first()
|
||||
)
|
||||
|
||||
if clinic_doctor is None:
|
||||
raise ResourceNotFoundException("Clinic doctor not found")
|
||||
|
||||
|
||||
# Update the existing object with new values
|
||||
update_data = clinic_doctor_data.model_dump(exclude_unset=True)
|
||||
|
||||
for key, value in update_data.items():
|
||||
setattr(clinic_doctor, key, value)
|
||||
|
||||
self.db.add(clinic_doctor)
|
||||
|
||||
# delete existing clinic doctor appointment types
|
||||
self.db.query(AppointmentRelations).filter(
|
||||
AppointmentRelations.clinic_doctor_id == clinic_doctor_id
|
||||
).delete()
|
||||
|
||||
# create clinic doctor appointment types
|
||||
for appointment_type_id in clinic_doctor_data.appointmentTypes:
|
||||
clinic_doctor_appointment_type = AppointmentRelations(
|
||||
clinic_doctor_id=clinic_doctor_id,
|
||||
appointment_type_id=appointment_type_id,
|
||||
)
|
||||
self.db.add(clinic_doctor_appointment_type)
|
||||
|
||||
self.db.commit()
|
||||
return
|
||||
except Exception as e:
|
||||
self.db.rollback()
|
||||
raise e
|
||||
|
||||
async def delete_clinic_doctor(self, clinic_doctor_id: int):
|
||||
clinic_doctor = self.db.query(ClinicDoctors).filter(ClinicDoctors.id == clinic_doctor_id).first()
|
||||
clinic_doctor = (
|
||||
self.db.query(ClinicDoctors)
|
||||
.filter(ClinicDoctors.id == clinic_doctor_id)
|
||||
.first()
|
||||
)
|
||||
self.db.delete(clinic_doctor)
|
||||
self.db.commit()
|
||||
|
||||
async def get_doctor_status_count(self):
|
||||
|
||||
|
||||
# Query to count doctors by status
|
||||
status_counts = self.db.query(
|
||||
ClinicDoctors.status,
|
||||
func.count(ClinicDoctors.id).label('count')
|
||||
).group_by(ClinicDoctors.status).all()
|
||||
|
||||
status_counts = (
|
||||
self.db.query(
|
||||
ClinicDoctors.status, func.count(ClinicDoctors.id).label("count")
|
||||
)
|
||||
.group_by(ClinicDoctors.status)
|
||||
.all()
|
||||
)
|
||||
|
||||
# Initialize result dictionary with all possible statuses set to 0
|
||||
result = {status.value: 0 for status in ClinicDoctorStatus}
|
||||
|
||||
|
||||
# Update with actual counts from the query
|
||||
for status, count in status_counts:
|
||||
result[status.value] = count
|
||||
|
||||
|
||||
return result
|
||||
|
||||
async def get_clinic_doctors(self):
|
||||
clinic_doctors = self.db.query(ClinicDoctors).all()
|
||||
|
||||
total = self.db.query(ClinicDoctors).count()
|
||||
async def get_clinic_doctors(self, limit: int, offset: int, search: str = "", sort_by: str = DEFAULT_ORDER, sort_order: str = DEFAULT_ORDER_BY):
|
||||
try:
|
||||
clinic_doctors_query = (
|
||||
self.db.query(ClinicDoctors)
|
||||
.options(
|
||||
selectinload(ClinicDoctors.appointmentRelations)
|
||||
.selectinload(AppointmentRelations.masterAppointmentTypes)
|
||||
)
|
||||
.order_by(
|
||||
getattr(ClinicDoctors, sort_by).desc()
|
||||
if sort_order == "desc"
|
||||
else getattr(ClinicDoctors, sort_by).asc()
|
||||
)
|
||||
)
|
||||
|
||||
response = CommonResponse(data=[ClinicDoctorResponse(**clinic_doctor.__dict__.copy()) for clinic_doctor in clinic_doctors], total=total)
|
||||
total = self.db.query(ClinicDoctors).count()
|
||||
|
||||
return response
|
||||
|
||||
if search:
|
||||
clinic_doctors_query = clinic_doctors_query.filter(
|
||||
or_(
|
||||
ClinicDoctors.name.ilike(f"%{search}%"),
|
||||
cast(ClinicDoctors.role, String).ilike(f"%{search}%"),
|
||||
ClinicDoctors.appointmentRelations.any(
|
||||
AppointmentRelations.masterAppointmentTypes.has(
|
||||
MasterAppointmentTypes.type.ilike(f"%{search}%")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
total = clinic_doctors_query.count()
|
||||
|
||||
clinic_doctors = clinic_doctors_query.limit(limit).offset(offset).all()
|
||||
|
||||
# Build response data manually to include appointment types
|
||||
response_data = []
|
||||
for clinic_doctor in clinic_doctors:
|
||||
# Extract appointment types from the relationships
|
||||
appointment_types = []
|
||||
for relation in clinic_doctor.appointmentRelations:
|
||||
if relation.masterAppointmentTypes:
|
||||
appointment_types.append(
|
||||
MasterAppointmentTypeResponse(
|
||||
id=relation.masterAppointmentTypes.id,
|
||||
type=relation.masterAppointmentTypes.type,
|
||||
create_time=relation.masterAppointmentTypes.create_time,
|
||||
update_time=relation.masterAppointmentTypes.update_time
|
||||
)
|
||||
)
|
||||
|
||||
# Create the clinic doctor response
|
||||
clinic_doctor_data = ClinicDoctorResponse(
|
||||
id=clinic_doctor.id,
|
||||
name=clinic_doctor.name,
|
||||
role=clinic_doctor.role,
|
||||
status=clinic_doctor.status,
|
||||
create_time=clinic_doctor.create_time,
|
||||
update_time=clinic_doctor.update_time,
|
||||
appointmentTypes=appointment_types
|
||||
)
|
||||
response_data.append(clinic_doctor_data)
|
||||
|
||||
response = CommonResponse(
|
||||
data=response_data,
|
||||
total=total,
|
||||
)
|
||||
|
||||
return response
|
||||
except Exception as e:
|
||||
self.logger.error(e)
|
||||
raise e
|
||||
|
||||
Reference in New Issue
Block a user