parent
dabc7dd308
commit
13023e5913
|
|
@ -7,17 +7,17 @@ from services.clinicDoctorsServices import ClinicDoctorsServices
|
|||
router = APIRouter()
|
||||
|
||||
|
||||
@router.post("/clinic-doctor")
|
||||
@router.post("/")
|
||||
def create_clinic_doctor(clinic_doctor: ClinicDoctorCreate):
|
||||
clinic_doctor = ClinicDoctorsServices().create_clinic_doctor(clinic_doctor)
|
||||
return ApiResponse(data=clinic_doctor, message="Clinic doctor created successfully")
|
||||
|
||||
@router.put("/clinic-doctor/{clinic_doctor_id}")
|
||||
@router.put("/{clinic_doctor_id}")
|
||||
def update_clinic_doctor(clinic_doctor_id: int, clinic_doctor: ClinicDoctorUpdate):
|
||||
clinic_doctor = ClinicDoctorsServices().update_clinic_doctor(clinic_doctor)
|
||||
clinic_doctor = ClinicDoctorsServices().update_clinic_doctor(clinic_doctor_id, clinic_doctor)
|
||||
return ApiResponse(data=clinic_doctor, message="Clinic doctor updated successfully")
|
||||
|
||||
@router.delete("/clinic-doctor/{clinic_doctor_id}")
|
||||
@router.delete("/{clinic_doctor_id}")
|
||||
def delete_clinic_doctor(clinic_doctor_id: int):
|
||||
ClinicDoctorsServices().delete_clinic_doctor(clinic_doctor_id)
|
||||
return ApiResponse(data="OK", message="Clinic doctor deleted successfully")
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ from schemas.CreateSchemas import ClinicCreate
|
|||
from schemas.UpdateSchemas import ClinicUpdate
|
||||
from models.Clinics import Clinics
|
||||
|
||||
# services
|
||||
from services.clinicServices import ClinicServices
|
||||
|
||||
# Constants
|
||||
from schemas.ApiResponse import ApiResponse
|
||||
from utils.constants import DEFAULT_SKIP, DEFAULT_LIMIT
|
||||
|
||||
router = APIRouter()
|
||||
|
|
@ -20,56 +24,28 @@ router = APIRouter()
|
|||
|
||||
@router.get("/", response_model=List[Clinic])
|
||||
async def get_clinics(
|
||||
skip: int = DEFAULT_SKIP, limit: int = DEFAULT_LIMIT, db: Session = Depends(get_db)
|
||||
skip: int = DEFAULT_SKIP, limit: int = DEFAULT_LIMIT
|
||||
):
|
||||
clinics = db.query(Clinics).offset(skip).limit(limit).all()
|
||||
return clinics
|
||||
clinics = ClinicServices().get_clinics(skip, limit)
|
||||
return ApiResponse(data=clinics, message="Clinics retrieved successfully", status_code=status.HTTP_200_OK)
|
||||
|
||||
|
||||
@router.get("/{clinic_id}", response_model=ClinicWithDoctors)
|
||||
async def get_clinic(clinic_id: int, db: Session = Depends(get_db)):
|
||||
db_clinic = db.query(Clinics).where(Clinics.id == clinic_id).first()
|
||||
if db_clinic is None:
|
||||
raise HTTPException(status_code=404, detail="Clinic not found")
|
||||
return db_clinic
|
||||
|
||||
|
||||
@router.post("/", response_model=Clinic, status_code=status.HTTP_201_CREATED)
|
||||
async def create_clinic(clinic: ClinicCreate, db: Session = Depends(get_db)):
|
||||
try:
|
||||
db_clinic = Clinics(**clinic.model_dump())
|
||||
db.add(db_clinic)
|
||||
db.commit()
|
||||
db.refresh(db_clinic)
|
||||
return db_clinic
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail=str(e.__cause__),
|
||||
) from e
|
||||
@router.get("/{clinic_id}")
|
||||
async def get_clinic(clinic_id: int):
|
||||
clinic = ClinicServices().get_clinic_by_id(clinic_id)
|
||||
return ApiResponse(data=clinic, message="Clinic retrieved successfully", status_code=status.HTTP_200_OK)
|
||||
|
||||
|
||||
@router.put("/{clinic_id}", response_model=Clinic)
|
||||
async def update_clinic(
|
||||
clinic_id: int, clinic: ClinicUpdate, db: Session = Depends(get_db)
|
||||
clinic_id: int, clinic: ClinicUpdate
|
||||
):
|
||||
db_clinic = db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
||||
if db_clinic is None:
|
||||
raise HTTPException(status_code=404, detail="Clinic not found")
|
||||
|
||||
update_data = clinic.model_dump(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(db_clinic, key, value)
|
||||
|
||||
db.commit()
|
||||
db.refresh(db_clinic)
|
||||
return db_clinic
|
||||
clinic = ClinicServices().update_clinic(clinic_id, clinic)
|
||||
return ApiResponse(data=clinic, message="Clinic updated successfully", status_code=status.HTTP_200_OK)
|
||||
|
||||
|
||||
@router.delete("/{clinic_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def delete_clinic(clinic_id: int, db: Session = Depends(get_db)):
|
||||
async def delete_clinic(clinic_id: int):
|
||||
db_clinic = db.query(Clinics).where(Clinics.id == clinic_id).first()
|
||||
if db_clinic is None:
|
||||
raise HTTPException(status_code=404, detail="Clinic not found")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
"""fix enum clinic doctor
|
||||
|
||||
Revision ID: 0ce7107c1910
|
||||
Revises: a3a9b7d17bdd
|
||||
Create Date: 2025-05-13 12:20:49.384154
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from sqlalchemy import text
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '0ce7107c1910'
|
||||
down_revision: Union[str, None] = 'a3a9b7d17bdd'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
|
||||
# Check if the enum type exists before creating it
|
||||
conn = op.get_bind()
|
||||
result = conn.execute(text("SELECT EXISTS(SELECT 1 FROM pg_type WHERE typname = 'clinicdoctortype')"))
|
||||
enum_exists = result.scalar()
|
||||
|
||||
if not enum_exists:
|
||||
# Create the new enum type if it doesn't exist
|
||||
op.execute(text("CREATE TYPE clinicdoctortype AS ENUM ('DOCTOR', 'NURSE')"))
|
||||
|
||||
# Check if the new_role column already exists
|
||||
inspector = sa.inspect(conn)
|
||||
columns = inspector.get_columns('clinic_doctors')
|
||||
column_names = [column['name'] for column in columns]
|
||||
|
||||
if 'new_role' not in column_names:
|
||||
# Add a temporary column with the new type
|
||||
op.add_column('clinic_doctors', sa.Column('new_role', postgresql.ENUM('DOCTOR', 'NURSE', name='clinicdoctortype'), nullable=True))
|
||||
|
||||
# Update the temporary column with values based on the old column
|
||||
op.execute(text("UPDATE clinic_doctors SET new_role = 'DOCTOR' WHERE role = 'DIRECTOR'"))
|
||||
op.execute(text("UPDATE clinic_doctors SET new_role = 'NURSE' WHERE role = 'PRACTICE_MANAGER'"))
|
||||
|
||||
# Drop the old column and rename the new one
|
||||
op.drop_column('clinic_doctors', 'role')
|
||||
op.alter_column('clinic_doctors', 'new_role', new_column_name='role')
|
||||
|
||||
# We need to handle the users table that depends on the clinicuserroles enum
|
||||
# First check if the users table has a clinicRole column that uses the enum
|
||||
has_clinic_role = False
|
||||
try:
|
||||
user_columns = inspector.get_columns('users')
|
||||
for column in user_columns:
|
||||
if column['name'] == 'clinicRole':
|
||||
has_clinic_role = True
|
||||
break
|
||||
except:
|
||||
# Table might not exist
|
||||
pass
|
||||
|
||||
if has_clinic_role:
|
||||
# We need to update the users table to not use the enum before dropping it
|
||||
# First, create a temporary column with a string type
|
||||
op.add_column('users', sa.Column('temp_clinic_role', sa.String(), nullable=True))
|
||||
|
||||
# Copy the values - use double quotes to preserve case sensitivity in PostgreSQL
|
||||
op.execute(text('UPDATE users SET temp_clinic_role = "clinicRole"::text'))
|
||||
|
||||
# Drop the old column and rename the new one
|
||||
op.drop_column('users', 'clinicRole')
|
||||
op.alter_column('users', 'temp_clinic_role', new_column_name='clinicRole')
|
||||
|
||||
# Now we can safely drop the old enum type
|
||||
op.execute(text("DROP TYPE IF EXISTS clinicuserroles"))
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
|
||||
# Create the old enum type
|
||||
op.execute(text("CREATE TYPE clinicuserroles AS ENUM ('DIRECTOR', 'PRACTICE_MANAGER')"))
|
||||
|
||||
# Add a temporary column with the old type
|
||||
op.add_column('clinic_doctors', sa.Column('old_role', postgresql.ENUM('DIRECTOR', 'PRACTICE_MANAGER', name='clinicuserroles'), nullable=True))
|
||||
|
||||
# Update the temporary column with values based on the new column
|
||||
op.execute(text("UPDATE clinic_doctors SET old_role = 'DIRECTOR' WHERE role = 'DOCTOR'"))
|
||||
op.execute(text("UPDATE clinic_doctors SET old_role = 'PRACTICE_MANAGER' WHERE role = 'NURSE'"))
|
||||
|
||||
# Drop the new column and rename the old one
|
||||
op.drop_column('clinic_doctors', 'role')
|
||||
op.alter_column('clinic_doctors', 'old_role', new_column_name='role')
|
||||
|
||||
# If we modified the users table in the upgrade, we need to restore it
|
||||
conn = op.get_bind()
|
||||
inspector = sa.inspect(conn)
|
||||
has_clinic_role = False
|
||||
try:
|
||||
user_columns = inspector.get_columns('users')
|
||||
for column in user_columns:
|
||||
if column['name'] == 'clinicRole':
|
||||
has_clinic_role = True
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
if has_clinic_role:
|
||||
# Create a temporary column with the enum type
|
||||
op.add_column('users', sa.Column('temp_clinic_role', postgresql.ENUM('DIRECTOR', 'PRACTICE_MANAGER', name='clinicuserroles'), nullable=True))
|
||||
|
||||
# Copy the values (with appropriate conversion) - use double quotes to preserve case sensitivity
|
||||
op.execute(text('UPDATE users SET temp_clinic_role = "clinicRole"::clinicuserroles'))
|
||||
|
||||
# Drop the old column and rename the new one
|
||||
op.drop_column('users', 'clinicRole')
|
||||
op.alter_column('users', 'temp_clinic_role', new_column_name='clinicRole')
|
||||
|
||||
# Drop the new enum type
|
||||
op.execute(text("DROP TYPE IF EXISTS clinicdoctortype"))
|
||||
# ### end Alembic commands ###
|
||||
# ### end Alembic commands ###
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
from sqlalchemy import Column, Enum, Integer, String, ForeignKey,Table
|
||||
from database import Base
|
||||
from enums.enums import ClinicUserRoles, ClinicDoctorStatus
|
||||
from enums.enums import ClinicDoctorType, ClinicDoctorStatus
|
||||
from .CustomBase import CustomBase
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
|
|
@ -9,9 +9,10 @@ class ClinicDoctors(Base, CustomBase):
|
|||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
name = Column(String)
|
||||
role = Column(Enum(ClinicUserRoles))
|
||||
role = Column(Enum(ClinicDoctorType))
|
||||
status = Column(Enum(ClinicDoctorStatus))
|
||||
|
||||
appointmentRelations = relationship("AppointmentRelations", back_populates="clinicDoctors")
|
||||
clinic_id = Column(Integer, ForeignKey("clinics.id"))
|
||||
clinic = relationship("Clinics", back_populates="clinicDoctors")
|
||||
|
||||
|
|
@ -10,4 +10,3 @@ class MasterAppointmentTypes(Base, CustomBase):
|
|||
type = Column(String)
|
||||
|
||||
appointmentRelations = relationship("AppointmentRelations", back_populates="masterAppointmentTypes")
|
||||
clinicDoctors = relationship("ClinicDoctors", back_populates="masterAppointmentTypes")
|
||||
|
|
@ -76,3 +76,4 @@ class ClinicDoctorBase(BaseModel):
|
|||
name: str
|
||||
role: ClinicDoctorType
|
||||
status: ClinicDoctorStatus
|
||||
clinic_id: int
|
||||
|
|
@ -136,7 +136,7 @@ class AppointmentDetailed(AppointmentSchema):
|
|||
patient: Patient
|
||||
|
||||
|
||||
class ClinicDoctor(ClinicDoctorBase):
|
||||
class ClinicDoctorResponse(ClinicDoctorBase):
|
||||
id: int
|
||||
create_time: datetime
|
||||
update_time: datetime
|
||||
|
|
|
|||
|
|
@ -1,12 +1,32 @@
|
|||
from .BaseSchemas import *
|
||||
|
||||
from enums.enums import ClinicStatus, Integration
|
||||
|
||||
# Update schemas (all fields optional for partial updates)
|
||||
class ClinicUpdate(BaseModel):
|
||||
name: Optional[str] = None
|
||||
address: Optional[str] = None
|
||||
phone: Optional[str] = None
|
||||
email: Optional[EmailStr] = None
|
||||
status: Optional[ClinicStatus] = None
|
||||
integration: Optional[Integration] = None
|
||||
pms_id: Optional[str] = None
|
||||
practice_name: Optional[str] = None
|
||||
logo: Optional[str] = None
|
||||
country: Optional[str] = None
|
||||
postal_code: Optional[str] = None
|
||||
city: Optional[str] = None
|
||||
state: Optional[str] = None
|
||||
abn_doc: Optional[str] = None
|
||||
abn_number: Optional[str] = None
|
||||
contract_doc: Optional[str] = None
|
||||
clinic_phone: Optional[str] = None
|
||||
is_clinic_phone_enabled: Optional[bool] = True
|
||||
other_info: Optional[str] = None
|
||||
greeting_msg: Optional[str] = None
|
||||
voice_model: Optional[str] = None
|
||||
voice_model_provider: Optional[str] = None
|
||||
voice_model_gender: Optional[str] = None
|
||||
scenarios: Optional[str] = None
|
||||
general_info: Optional[str] = None
|
||||
|
||||
|
||||
class DoctorUpdate(BaseModel):
|
||||
|
|
|
|||
|
|
@ -1,21 +1,49 @@
|
|||
from schemas.CreateSchemas import ClinicDoctorCreate
|
||||
from schemas.UpdateSchemas import ClinicDoctorUpdate
|
||||
from schemas.ResponseSchemas import ClinicDoctorResponse
|
||||
from database import get_db
|
||||
from models import ClinicDoctors
|
||||
from sqlalchemy.orm import Session
|
||||
from services.clinicServices import ClinicServices
|
||||
from exceptions import ResourceNotFoundException
|
||||
|
||||
class ClinicDoctorsServices:
|
||||
def __init__(self):
|
||||
self.db = next(get_db())
|
||||
self.db: Session = next(get_db())
|
||||
self.clinic_services = ClinicServices()
|
||||
|
||||
def create_clinic_doctor(self, clinic_doctor: ClinicDoctorCreate):
|
||||
clinic_doctor = ClinicDoctors(**clinic_doctor.dict())
|
||||
def create_clinic_doctor(self, clinic_doctor: ClinicDoctorCreate) -> ClinicDoctorResponse:
|
||||
|
||||
# check if clinic exists
|
||||
self.clinic_services.get_clinic_by_id(clinic_doctor.clinic_id)
|
||||
|
||||
clinic_doctor = ClinicDoctors(**clinic_doctor.model_dump())
|
||||
self.db.add(clinic_doctor)
|
||||
self.db.commit()
|
||||
self.db.refresh(clinic_doctor)
|
||||
return clinic_doctor
|
||||
return ClinicDoctorResponse(**clinic_doctor.__dict__.copy())
|
||||
|
||||
def update_clinic_doctor(self, clinic_doctor_id: int, clinic_doctor: ClinicDoctorUpdate):
|
||||
pass
|
||||
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")
|
||||
|
||||
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)
|
||||
|
||||
# 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())
|
||||
|
||||
def delete_clinic_doctor(self, clinic_doctor_id: int):
|
||||
pass
|
||||
clinic_doctor = self.db.query(ClinicDoctors).filter(ClinicDoctors.id == clinic_doctor_id).first()
|
||||
self.db.delete(clinic_doctor)
|
||||
self.db.commit()
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
from database import get_db
|
||||
from sqlalchemy.orm import Session
|
||||
from models import Clinics
|
||||
from schemas.UpdateSchemas import ClinicUpdate
|
||||
from schemas.ResponseSchemas import Clinic
|
||||
from typing import List
|
||||
from exceptions import ResourceNotFoundException
|
||||
|
||||
class ClinicServices:
|
||||
def __init__(self):
|
||||
self.db: Session = next(get_db())
|
||||
|
||||
def get_clinics(self, limit:int, offset:int) -> List[Clinic]:
|
||||
clinics = self.db.query(Clinics).limit(limit).offset(offset).all()
|
||||
|
||||
clinic_response = [Clinic(**clinic.__dict__.copy()) for clinic in clinics]
|
||||
|
||||
return clinic_response
|
||||
|
||||
|
||||
def get_clinic_by_id(self, clinic_id: int) -> Clinic:
|
||||
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
||||
|
||||
if clinic is None:
|
||||
raise ResourceNotFoundException("Clinic not found")
|
||||
|
||||
clinic_response = Clinic(**clinic.__dict__.copy())
|
||||
return clinic_response
|
||||
|
||||
def update_clinic(self, clinic_id: int, clinic_data: ClinicUpdate):
|
||||
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
||||
|
||||
if clinic is None:
|
||||
raise ResourceNotFoundException("Clinic not found")
|
||||
|
||||
update_data = clinic_data.model_dump(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(clinic, key, value)
|
||||
|
||||
self.db.add(clinic)
|
||||
self.db.commit()
|
||||
self.db.refresh(clinic)
|
||||
return Clinic(**clinic.__dict__.copy())
|
||||
|
||||
def delete_clinic(self, clinic_id: int):
|
||||
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
||||
|
||||
if clinic is None:
|
||||
raise ResourceNotFoundException("Clinic not found")
|
||||
|
||||
self.db.delete(clinic)
|
||||
self.db.commit()
|
||||
|
|
@ -6,7 +6,7 @@ from models.Users import Users
|
|||
from exceptions.validation_exception import ValidationException
|
||||
from schemas.ResponseSchemas import UserResponse
|
||||
from models import Clinics
|
||||
from enums.enums import ClinicStatus
|
||||
from enums.enums import ClinicStatus, UserType
|
||||
from schemas.UpdateSchemas import UserUpdate
|
||||
from exceptions.unauthorized_exception import UnauthorizedException
|
||||
from utils.password_utils import hash_password
|
||||
|
|
@ -150,34 +150,36 @@ class UserServices:
|
|||
|
||||
return user_response
|
||||
|
||||
def update_user(self, admin_id:int|None, user_id: int, user_data: UserUpdate):
|
||||
|
||||
def update_user(self, admin_id:int|None, user_id: int, user_data: UserUpdate) -> UserResponse:
|
||||
# Check admin authorization if admin_id is provided
|
||||
if admin_id:
|
||||
admin = self.db.query(Users).filter(Users.id == admin_id).first()
|
||||
|
||||
if not admin:
|
||||
logger.error("Admin not found")
|
||||
raise ResourceNotFoundException("Admin not found")
|
||||
|
||||
if admin.userType != UserType.ADMIN:
|
||||
logger.error("User is not authorized to perform this action")
|
||||
raise UnauthorizedException("User is not authorized to perform this action")
|
||||
# Only check admin type if admin_id was provided
|
||||
if admin.userType != UserType.SUPER_ADMIN:
|
||||
logger.error("User is not authorized to perform this action")
|
||||
raise UnauthorizedException("User is not authorized to perform this action")
|
||||
|
||||
# Find the user to update
|
||||
user = self.db.query(Users).filter(Users.id == user_id).first()
|
||||
|
||||
if not user:
|
||||
logger.error("User not found")
|
||||
raise ResourceNotFoundException("User not found")
|
||||
|
||||
user.username = user_data.username
|
||||
user.clinicRole = user_data.clinicRole
|
||||
user.userType = user_data.userType
|
||||
user.profile_pic = user_data.profile_pic
|
||||
# Update only the fields that were provided
|
||||
update_data = user_data.model_dump(exclude_unset=True)
|
||||
for key, value in update_data.items():
|
||||
setattr(user, key, value)
|
||||
|
||||
self.db.add(user)
|
||||
self.db.commit()
|
||||
self.db.refresh(user)
|
||||
|
||||
return user
|
||||
# Return properly serialized response
|
||||
return UserResponse.model_validate(user)
|
||||
|
||||
def delete_user(self, user_id: int):
|
||||
user = self.db.query(Users).filter(Users.id == user_id).first()
|
||||
|
|
|
|||
Loading…
Reference in New Issue