chaors: db optimization

This commit is contained in:
deepvasoya 2025-05-28 11:16:55 +05:30
parent 62b6020897
commit 6c4fcca9bd
9 changed files with 753 additions and 536 deletions

View File

@ -12,15 +12,10 @@ from sqlalchemy.exc import SQLAlchemyError
engine = create_engine( engine = create_engine(
os.getenv("DB_URL"), os.getenv("DB_URL"),
pool_pre_ping=True, pool_pre_ping=True,
pool_size=2, # Reduced from 5 echo=True if os.getenv("IS_DEV") == "True" else False, # Disable in production - this uses memory
max_overflow=3, # Reduced from 10
pool_recycle=1800, # Reduced to 30 minutes
pool_timeout=30, # Add connection timeout
echo=False, # Disable in production - this uses memory
connect_args={ connect_args={
"sslmode": "require" if os.getenv("IS_DEV") == "False" else "disable", "sslmode": "require" if os.getenv("IS_DEV") == "False" else "disable",
"connect_timeout": 10, # Connection timeout "connect_timeout": 10, # Connection timeout
"command_timeout": 60, # Query timeout
}, },
) )

View File

@ -26,7 +26,7 @@ from schemas.BaseSchemas import AuthBase, AuthOTP
from exceptions.unauthorized_exception import UnauthorizedException from exceptions.unauthorized_exception import UnauthorizedException
from database import get_db from database import get_db
from loguru import logger
class AuthService: class AuthService:
@ -35,6 +35,7 @@ class AuthService:
self.db = next(get_db()) self.db = next(get_db())
self.email_service = EmailService() self.email_service = EmailService()
self.url = os.getenv("FRONTEND_URL") self.url = os.getenv("FRONTEND_URL")
self.logger = logger
async def login(self, data: AuthBase) -> str: async def login(self, data: AuthBase) -> str:
@ -58,6 +59,7 @@ class AuthService:
return response return response
def blockEmailSNS(self, body: str): def blockEmailSNS(self, body: str):
try:
# confirm subscription # confirm subscription
if body["Type"] == "SubscriptionConfirmation": if body["Type"] == "SubscriptionConfirmation":
urllib.request.urlopen(body["SubscribeURL"]) urllib.request.urlopen(body["SubscribeURL"])
@ -82,8 +84,14 @@ class AuthService:
self.db.commit() self.db.commit()
return "OK" return "OK"
except Exception as e:
self.logger.error(f"Error blocking email: {e}")
raise
finally:
self.db.close()
async def send_otp(self, email:str): async def send_otp(self, email:str):
try:
otp = generateOTP() otp = generateOTP()
self.email_service.send_otp_email(email, otp) self.email_service.send_otp_email(email, otp)
@ -94,8 +102,14 @@ class AuthService:
self.db.commit() self.db.commit()
return return
except Exception as e:
self.logger.error(f"Error sending OTP: {e}")
raise
finally:
self.db.close()
async def verify_otp(self, data: AuthOTP): async def verify_otp(self, data: AuthOTP):
try:
db_otp = self.db.query(OTP).filter(OTP.email == data.email, OTP.otp == data.otp).first() db_otp = self.db.query(OTP).filter(OTP.email == data.email, OTP.otp == data.otp).first()
if not db_otp: if not db_otp:
raise ValidationException("Invalid OTP") raise ValidationException("Invalid OTP")
@ -105,11 +119,15 @@ class AuthService:
raise ValidationException("OTP expired") raise ValidationException("OTP expired")
# OTP is valid, delete it to prevent reuse # OTP is valid, delete it to prevent reuse
# self.db.delete(db_otp) self.db.delete(db_otp)
# self.db.commit() self.db.commit()
return return
except Exception as e:
self.logger.error(f"Error verifying OTP: {e}")
raise
finally:
self.db.close()
async def get_admins(self, user, limit:int, offset:int, search:str): async def get_admins(self, user, limit:int, offset:int, search:str):
try: try:
@ -138,10 +156,13 @@ class AuthService:
return common_response return common_response
except Exception as e: except Exception as e:
self.logger.error(f"Error getting admins: {e}")
raise e raise e
finally:
self.db.close()
async def create_super_admin(self, user, data: CreateSuperAdmin): async def create_super_admin(self, user, data: CreateSuperAdmin):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action") raise UnauthorizedException("User is not authorized to perform this action")
@ -179,9 +200,15 @@ class AuthService:
self.email_service.send_new_admin_email(data.username, data.email, password, LOGIN_URL) self.email_service.send_new_admin_email(data.username, data.email, password, LOGIN_URL)
return return
except Exception as e:
self.logger.error(f"Error creating super admin: {e}")
raise e
finally:
self.db.close()
async def update_super_admin(self, user, user_id: int, data: UpdateSuperAdmin): async def update_super_admin(self, user, user_id: int, data: UpdateSuperAdmin):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action") raise UnauthorizedException("User is not authorized to perform this action")
@ -196,8 +223,14 @@ class AuthService:
self.db.commit() self.db.commit()
return return
except Exception as e:
self.logger.error(f"Error updating super admin: {e}")
raise e
finally:
self.db.close()
async def delete_super_admin(self, user, user_id: int): async def delete_super_admin(self, user, user_id: int):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action") raise UnauthorizedException("User is not authorized to perform this action")
@ -209,9 +242,14 @@ class AuthService:
user.soft_delete(self.db) user.soft_delete(self.db)
return return
except Exception as e:
self.logger.error(f"Error deleting super admin: {e}")
raise e
finally:
self.db.close()
async def forget_password(self, email: str): async def forget_password(self, email: str):
try:
user = self.db.query(Users).filter(Users.email == email.lower()).first() user = self.db.query(Users).filter(Users.email == email.lower()).first()
if not user: if not user:
@ -229,8 +267,14 @@ class AuthService:
self.email_service.send_reset_password_email(email, reset_password_url) self.email_service.send_reset_password_email(email, reset_password_url)
return return
except Exception as e:
self.logger.error(f"Error forgetting password: {e}")
raise e
finally:
self.db.close()
async def reset_password(self, token: str, password: str): async def reset_password(self, token: str, password: str):
try:
reset_password = self.db.query(ResetPasswordTokens).filter(ResetPasswordTokens.token == token).first() reset_password = self.db.query(ResetPasswordTokens).filter(ResetPasswordTokens.token == token).first()
if not reset_password: if not reset_password:
@ -246,4 +290,10 @@ class AuthService:
self.db.commit() self.db.commit()
return return
except Exception as e:
self.logger.error(f"Error resetting password: {e}")
raise e
finally:
self.db.close()

View File

@ -13,12 +13,17 @@ from models.CallTranscripts import CallTranscripts
from exceptions.business_exception import BusinessValidationException from exceptions.business_exception import BusinessValidationException
from services.s3Service import get_signed_url from services.s3Service import get_signed_url
from interface.common_response import CommonResponse from interface.common_response import CommonResponse
from loguru import logger
from exceptions.db_exceptions import DBExceptionHandler
class CallTranscriptServices: class CallTranscriptServices:
def __init__(self): def __init__(self):
self.db:Session = next(get_db()) self.db:Session = next(get_db())
self.logger = logger
async def get_call_transcripts(self, limit:int, offset:int): async def get_call_transcripts(self, limit:int, offset:int):
try:
call_transcripts = self.db.query(CallTranscripts).limit(limit).offset(offset).all() call_transcripts = self.db.query(CallTranscripts).limit(limit).offset(offset).all()
total = self.db.query(CallTranscripts).count() total = self.db.query(CallTranscripts).count()
@ -31,14 +36,23 @@ class CallTranscriptServices:
return_response = CommonResponse(data=response, total=total) return_response = CommonResponse(data=response, total=total)
return return_response return return_response
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting call transcripts")
finally:
self.db.close()
def download_call_transcript(self, key_id: str): def download_call_transcript(self, key_id: str):
try:
call_transcript = self.db.query(CallTranscripts).filter(CallTranscripts.transcript_key_id == key_id).first() call_transcript = self.db.query(CallTranscripts).filter(CallTranscripts.transcript_key_id == key_id).first()
if not call_transcript: if not call_transcript:
raise BusinessValidationException("Call transcript not found!") raise BusinessValidationException("Call transcript not found!")
return get_signed_url(call_transcript.transcript_key_id) return get_signed_url(call_transcript.transcript_key_id)
except Exception as e:
DBExceptionHandler.handle_exception(e, context="downloading call transcript")
finally:
self.db.close()
def download_file(self, url: str, file_path: str) -> None: def download_file(self, url: str, file_path: str) -> None:
@ -85,7 +99,7 @@ class CallTranscriptServices:
print(f"Error during cleanup: {e}") print(f"Error during cleanup: {e}")
async def bulk_download_call_transcripts(self, key_ids: list[int], background_tasks: BackgroundTasks): async def bulk_download_call_transcripts(self, key_ids: list[int], background_tasks: BackgroundTasks):
try:
transcript_ids = self.db.query(CallTranscripts).filter(CallTranscripts.id.in_(key_ids)).all() transcript_ids = self.db.query(CallTranscripts).filter(CallTranscripts.id.in_(key_ids)).all()
keys = [transcript.transcript_key_id for transcript in transcript_ids] keys = [transcript.transcript_key_id for transcript in transcript_ids]
@ -143,3 +157,7 @@ class CallTranscriptServices:
filename="call_transcripts.zip", filename="call_transcripts.zip",
background=background_tasks background=background_tasks
) )
except Exception as e:
DBExceptionHandler.handle_exception(e, context="bulk downloading call transcripts")
finally:
self.db.close()

View File

@ -80,6 +80,8 @@ class ClinicDoctorsServices:
self.logger.error(e) self.logger.error(e)
self.db.rollback() self.db.rollback()
raise e raise e
finally:
self.db.close()
async def update_clinic_doctor( async def update_clinic_doctor(
self, user, clinic_doctor_id: int, clinic_doctor_data: ClinicDoctorUpdate self, user, clinic_doctor_id: int, clinic_doctor_data: ClinicDoctorUpdate
@ -155,6 +157,8 @@ class ClinicDoctorsServices:
except Exception as e: except Exception as e:
self.db.rollback() self.db.rollback()
raise e raise e
finally:
self.db.close()
async def delete_clinic_doctor(self, clinic_doctor_id: int): async def delete_clinic_doctor(self, clinic_doctor_id: int):
try: try:
@ -167,9 +171,11 @@ class ClinicDoctorsServices:
self.db.commit() self.db.commit()
except Exception as e: except Exception as e:
raise e raise e
finally:
self.db.close()
async def get_doctor_status_count(self): async def get_doctor_status_count(self):
try:
# Query to count doctors by status # Query to count doctors by status
status_counts = ( status_counts = (
self.db.query( self.db.query(
@ -187,6 +193,10 @@ class ClinicDoctorsServices:
result[status.value] = count result[status.value] = count
return result return result
except Exception as e:
raise e
finally:
self.db.close()
async def get_clinic_doctors(self, limit: int, offset: int, search: str = "", sort_by: str = DEFAULT_ORDER, sort_order: str = DEFAULT_ORDER_BY): async def get_clinic_doctors(self, limit: int, offset: int, search: str = "", sort_by: str = DEFAULT_ORDER, sort_order: str = DEFAULT_ORDER_BY):
try: try:
@ -258,3 +268,5 @@ class ClinicDoctorsServices:
except Exception as e: except Exception as e:
self.logger.error(e) self.logger.error(e)
raise e raise e
finally:
self.db.close()

View File

@ -14,14 +14,18 @@ from services.s3Service import get_file_key, get_signed_url
from models import ClinicFileVerifications, ClinicOffers, Clinics, Users from models import ClinicFileVerifications, ClinicOffers, Clinics, Users
from schemas.BaseSchemas import ClinicFileVerificationBase, ClinicOffersBase from schemas.BaseSchemas import ClinicFileVerificationBase, ClinicOffersBase
from services.emailService import EmailService from services.emailService import EmailService
from loguru import logger
from sqlalchemy import func
from exceptions.db_exceptions import DBExceptionHandler
class ClinicServices: class ClinicServices:
def __init__(self): def __init__(self):
self.db: Session = next(get_db()) self.db: Session = next(get_db())
self.email_service = EmailService() self.email_service = EmailService()
self.logger = logger
async def get_clinics(self, user, limit:int, offset:int, filter_type: Union[Literal["UNREGISTERED"], Literal["REGISTERED"]] = "UNREGISTERED", search:str = ""): async def get_clinics(self, user, limit:int, offset:int, filter_type: Union[Literal["UNREGISTERED"], Literal["REGISTERED"]] = "UNREGISTERED", search:str = ""):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to get clinics") raise UnauthorizedException("You are not authorized to get clinics")
@ -73,13 +77,23 @@ class ClinicServices:
response = CommonResponse(data=clinic_response_with_total, total=totalClinics) response = CommonResponse(data=clinic_response_with_total, total=totalClinics)
return response return response
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting clinics")
finally:
self.db.close()
async def get_latest_clinic_id(self) -> int: async def get_latest_clinic_id(self) -> int:
try:
clinic = self.db.query(Clinics).order_by(Clinics.id.desc()).first() clinic = self.db.query(Clinics).order_by(Clinics.id.desc()).first()
return clinic.id if clinic else 0 return clinic.id if clinic else 0
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting latest clinic id")
finally:
self.db.close()
async def get_clinic_by_id(self, clinic_id: int): async def get_clinic_by_id(self, clinic_id: int):
try:
clinic = self.db.query(Clinics).options(joinedload(Clinics.creator)).filter(Clinics.id == clinic_id).first() clinic = self.db.query(Clinics).options(joinedload(Clinics.creator)).filter(Clinics.id == clinic_id).first()
if clinic is None: if clinic is None:
@ -108,8 +122,13 @@ class ClinicServices:
} }
return clinic_resp return clinic_resp
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting clinic by id")
finally:
self.db.close()
async def get_clinic_files(self, clinic_id: int): async def get_clinic_files(self, clinic_id: int):
try:
clinic_files = self.db.query(ClinicFileVerifications).filter(ClinicFileVerifications.clinic_id == clinic_id).first() clinic_files = self.db.query(ClinicFileVerifications).filter(ClinicFileVerifications.clinic_id == clinic_id).first()
if clinic_files is None: if clinic_files is None:
@ -118,8 +137,13 @@ class ClinicServices:
response = ClinicFileVerificationBase(**clinic_files.__dict__.copy()) response = ClinicFileVerificationBase(**clinic_files.__dict__.copy())
return response return response
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting clinic files")
finally:
self.db.close()
async def update_clinic(self, user, clinic_id: int, clinic_data: ClinicUpdate): async def update_clinic(self, user, clinic_id: int, clinic_data: ClinicUpdate):
try:
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first() clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
if clinic is None: if clinic is None:
@ -145,18 +169,26 @@ class ClinicServices:
clinic_response.logo = get_signed_url(clinic_response.logo) if clinic_response.logo else None clinic_response.logo = get_signed_url(clinic_response.logo) if clinic_response.logo else None
return clinic_response return clinic_response
except Exception as e:
DBExceptionHandler.handle_exception(e, context="updating clinic")
finally:
self.db.close()
async def delete_clinic(self, clinic_id: int): async def delete_clinic(self, clinic_id: int):
try:
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first() clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
if clinic is None: if clinic is None:
raise ResourceNotFoundException("Clinic not found") raise ResourceNotFoundException("Clinic not found")
clinic.soft_delete(self.db) clinic.soft_delete(self.db)
except Exception as e:
DBExceptionHandler.handle_exception(e, context="deleting clinic")
finally:
self.db.close()
async def get_clinic_count(self): async def get_clinic_count(self):
from sqlalchemy import func try:
# Get total count # Get total count
totalClinics = self.db.query(Clinics).count() totalClinics = self.db.query(Clinics).count()
@ -194,9 +226,14 @@ class ClinicServices:
counts[key] = count counts[key] = count
return counts return counts
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting clinic count")
finally:
self.db.close()
async def update_clinic_status(self, user, clinic_id: int, status: ClinicStatus, documentStatus: Optional[dict] = None, rejection_reason: Optional[str] = None): async def update_clinic_status(self, user, clinic_id: int, status: ClinicStatus, documentStatus: Optional[dict] = None, rejection_reason: Optional[str] = None):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to update clinic status") raise UnauthorizedException("You are not authorized to update clinic status")
@ -265,13 +302,22 @@ class ClinicServices:
pass pass
return return
except Exception as e:
DBExceptionHandler.handle_exception(e, context="updating clinic status")
finally:
self.db.close()
async def get_clinic_offer_by_clinic_email(self, clinic_email: str): async def get_clinic_offer_by_clinic_email(self, clinic_email: str):
try:
clinic_offer = self.db.query(ClinicOffers).filter(ClinicOffers.clinic_email == clinic_email).first() clinic_offer = self.db.query(ClinicOffers).filter(ClinicOffers.clinic_email == clinic_email).first()
return clinic_offer return clinic_offer
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting clinic offer by clinic email")
finally:
self.db.close()
async def get_clinic_offers(self, user, limit:int, offset:int, search:str = ""): async def get_clinic_offers(self, user, limit:int, offset:int, search:str = ""):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to get clinic offers") raise UnauthorizedException("You are not authorized to get clinic offers")
@ -290,8 +336,13 @@ class ClinicServices:
response = CommonResponse(data=clinic_offers_response, total=total) response = CommonResponse(data=clinic_offers_response, total=total)
return response return response
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting clinic offers")
finally:
self.db.close()
async def create_clinic_offer(self, user, clinic_offer_data: ClinicOffersBase): async def create_clinic_offer(self, user, clinic_offer_data: ClinicOffersBase):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to create clinic offer") raise UnauthorizedException("You are not authorized to create clinic offer")
@ -306,8 +357,13 @@ class ClinicServices:
self.db.commit() self.db.commit()
return return
except Exception as e:
DBExceptionHandler.handle_exception(e, context="creating clinic offer")
finally:
self.db.close()
async def update_clinic_offer(self, user, clinic_offer_id: int, clinic_offer_data: ClinicOffersBase): async def update_clinic_offer(self, user, clinic_offer_id: int, clinic_offer_data: ClinicOffersBase):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to update clinic offer") raise UnauthorizedException("You are not authorized to update clinic offer")
@ -323,8 +379,13 @@ class ClinicServices:
self.db.commit() self.db.commit()
return return
except Exception as e:
DBExceptionHandler.handle_exception(e, context="updating clinic offer")
finally:
self.db.close()
async def delete_clinic_offer(self, user, clinic_offer_id: int): async def delete_clinic_offer(self, user, clinic_offer_id: int):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to delete clinic offer") raise UnauthorizedException("You are not authorized to delete clinic offer")
@ -336,3 +397,7 @@ class ClinicServices:
clinic_offer.soft_delete(self.db) clinic_offer.soft_delete(self.db)
return return
except Exception as e:
DBExceptionHandler.handle_exception(e, context="deleting clinic offer")
finally:
self.db.close()

View File

@ -7,12 +7,13 @@ from models.SignupPricingMaster import SignupPricingMaster
from exceptions import UnauthorizedException from exceptions import UnauthorizedException
from enums.enums import UserType from enums.enums import UserType
from exceptions import ResourceNotFoundException from exceptions import ResourceNotFoundException
from loguru import logger
class DashboardService: class DashboardService:
def __init__(self): def __init__(self):
self.db = next(get_db()) self.db = next(get_db())
self.clinicDoctorsServices = ClinicDoctorsServices() self.clinicDoctorsServices = ClinicDoctorsServices()
self.clinicServices = ClinicServices() self.clinicServices = ClinicServices()
self.logger = logger
async def get_dashboard_counts(self, isSuperAdmin: bool): async def get_dashboard_counts(self, isSuperAdmin: bool):
if isSuperAdmin: if isSuperAdmin:
@ -25,6 +26,7 @@ class DashboardService:
async def update_signup_pricing_master( async def update_signup_pricing_master(
self, user, pricing_data: SignupPricingMasterBase self, user, pricing_data: SignupPricingMasterBase
): ):
try:
if user["userType"] != UserType.SUPER_ADMIN: if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException( raise UnauthorizedException(
"You are not authorized to update signup pricing master" "You are not authorized to update signup pricing master"
@ -60,9 +62,15 @@ class DashboardService:
) )
return response return response
except Exception as e:
self.logger.error(f"Error updating signup pricing master: {e}")
raise e
finally:
self.db.close()
async def get_signup_pricing_master(self): async def get_signup_pricing_master(self):
try:
signup_pricing_master = self.db.query(SignupPricingMaster).first() signup_pricing_master = self.db.query(SignupPricingMaster).first()
if signup_pricing_master is None: if signup_pricing_master is None:
raise ResourceNotFoundException("Signup pricing master not found") raise ResourceNotFoundException("Signup pricing master not found")
@ -72,3 +80,8 @@ class DashboardService:
) )
return response return response
except Exception as e:
self.logger.error(f"Error getting signup pricing master: {e}")
raise e
finally:
self.db.close()

View File

@ -6,24 +6,32 @@ from schemas.BaseSchemas import MasterAppointmentTypeBase
from exceptions import ResourceNotFoundException from exceptions import ResourceNotFoundException
from interface.common_response import CommonResponse from interface.common_response import CommonResponse
from schemas.ResponseSchemas import MasterAppointmentTypeResponse from schemas.ResponseSchemas import MasterAppointmentTypeResponse
from loguru import logger
class MasterAppointmentServices: class MasterAppointmentServices:
def __init__(self): def __init__(self):
self.db: Session = next(get_db()) self.db: Session = next(get_db())
self.logger = logger
async def get_master_appointment_types(self): async def get_master_appointment_types(self):
try:
appointment_types = self.db.query(MasterAppointmentTypes).all() appointment_types = self.db.query(MasterAppointmentTypes).all()
total= self.db.query(MasterAppointmentTypes).count() total= self.db.query(MasterAppointmentTypes).count()
response = CommonResponse(data=[MasterAppointmentTypeResponse(**appointment_type.__dict__.copy()) for appointment_type in appointment_types], total=total) response = CommonResponse(data=[MasterAppointmentTypeResponse(**appointment_type.__dict__.copy()) for appointment_type in appointment_types], total=total)
return response return response
except Exception as e:
self.logger.error(f"Error getting master appointment types: {e}")
raise e
finally:
self.db.close()
def is_appointment_type_exists(self, appointment_type: MasterAppointmentTypeBase): def is_appointment_type_exists(self, appointment_type: MasterAppointmentTypeBase):
existing_appointment_type = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.type == appointment_type.type.lower()).first() existing_appointment_type = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.type == appointment_type.type.lower()).first()
return existing_appointment_type return existing_appointment_type
async def create_master_appointment_type(self, appointment_type: MasterAppointmentTypeBase): async def create_master_appointment_type(self, appointment_type: MasterAppointmentTypeBase):
try:
# get existing appointment type # get existing appointment type
existing_appointment_type = self.is_appointment_type_exists(appointment_type) existing_appointment_type = self.is_appointment_type_exists(appointment_type)
@ -36,8 +44,14 @@ class MasterAppointmentServices:
self.db.add(appointment_type) self.db.add(appointment_type)
self.db.commit() self.db.commit()
return return
except Exception as e:
self.logger.error(f"Error creating master appointment type: {e}")
raise e
finally:
self.db.close()
async def delete_master_appointment_type(self, appointment_type_id: int): async def delete_master_appointment_type(self, appointment_type_id: int):
try:
appointment_type = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.id == appointment_type_id).first() appointment_type = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.id == appointment_type_id).first()
if appointment_type is None: if appointment_type is None:
@ -46,8 +60,14 @@ class MasterAppointmentServices:
appointment_type.soft_delete(self.db) appointment_type.soft_delete(self.db)
self.db.commit() self.db.commit()
return return
except Exception as e:
self.logger.error(f"Error deleting master appointment type: {e}")
raise e
finally:
self.db.close()
async def update_master_appointment_type(self, appointment_type_id: int, appointment_type: MasterAppointmentTypeBase): async def update_master_appointment_type(self, appointment_type_id: int, appointment_type: MasterAppointmentTypeBase):
try:
appointment_type_db = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.id == appointment_type_id).first() appointment_type_db = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.id == appointment_type_id).first()
if appointment_type_db is None: if appointment_type_db is None:
@ -64,3 +84,8 @@ class MasterAppointmentServices:
self.db.add(appointment_type_db) self.db.add(appointment_type_db)
self.db.commit() self.db.commit()
return return
except Exception as e:
self.logger.error(f"Error updating master appointment type: {e}")
raise e
finally:
self.db.close()

View File

@ -186,6 +186,8 @@ class StripeServices:
except stripe.error.StripeError as e: except stripe.error.StripeError as e:
self.logger.error(f"Error creating checkout session: {e}") self.logger.error(f"Error creating checkout session: {e}")
raise raise
finally:
self.db.close()
async def handle_webhook(self, request: Request): async def handle_webhook(self, request: Request):
@ -212,6 +214,8 @@ class StripeServices:
except stripe.error.SignatureVerificationError as e: except stripe.error.SignatureVerificationError as e:
self.logger.error(f"Invalid signature: {e}") self.logger.error(f"Invalid signature: {e}")
raise raise
finally:
self.db.close()
async def update_payment_log(self, unique_clinic_id:str, clinic_id:int): async def update_payment_log(self, unique_clinic_id:str, clinic_id:int):
try: try:
@ -228,3 +232,5 @@ class StripeServices:
except Exception as e: except Exception as e:
self.logger.error(f"Error updating payment log: {e}") self.logger.error(f"Error updating payment log: {e}")
raise raise
finally:
self.db.close()

View File

@ -173,6 +173,7 @@ class UserServices:
DBExceptionHandler.handle_exception(e, context="creating user") DBExceptionHandler.handle_exception(e, context="creating user")
finally: finally:
self.db.commit() self.db.commit()
self.db.close()
async def get_user(self, user_id) -> UserResponse: async def get_user(self, user_id) -> UserResponse:
@ -205,11 +206,12 @@ class UserServices:
# Return the response as a dictionary # Return the response as a dictionary
return user_response.model_dump() return user_response.model_dump()
except Exception as e: except Exception as e:
# Use the centralized exception handler
from twillio.exceptions.db_exceptions import DBExceptionHandler
DBExceptionHandler.handle_exception(e, context="getting user") DBExceptionHandler.handle_exception(e, context="getting user")
finally:
self.db.close()
async def get_users(self, limit:int, offset:int, search:str): async def get_users(self, limit:int, offset:int, search:str):
try:
query = self.db.query(Users) query = self.db.query(Users)
if search: if search:
query = query.filter( query = query.filter(
@ -228,8 +230,13 @@ class UserServices:
response = CommonResponse(data=[UserResponse(**user.__dict__.copy()) for user in users], total=total) response = CommonResponse(data=[UserResponse(**user.__dict__.copy()) for user in users], total=total)
return response return response
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting users")
finally:
self.db.close()
async def get_user_by_email(self, email: str) -> UserResponse: async def get_user_by_email(self, email: str) -> UserResponse:
try:
user = self.db.query(Users).filter(Users.email == email.lower()).first() user = self.db.query(Users).filter(Users.email == email.lower()).first()
if not user: if not user:
@ -241,8 +248,13 @@ class UserServices:
user_response = UserResponse(**user_dict) user_response = UserResponse(**user_dict)
return user_response return user_response
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting user by email")
finally:
self.db.close()
async def update_user(self, admin_id:int|None, user_id: int, user_data: UserUpdate) -> UserResponse: async def update_user(self, admin_id:int|None, user_id: int, user_data: UserUpdate) -> UserResponse:
try:
# Check admin authorization if admin_id is provided # Check admin authorization if admin_id is provided
if admin_id: if admin_id:
admin = self.db.query(Users).filter(Users.id == admin_id).first() admin = self.db.query(Users).filter(Users.id == admin_id).first()
@ -272,8 +284,13 @@ class UserServices:
# Return properly serialized response # Return properly serialized response
return UserResponse.model_validate(user) return UserResponse.model_validate(user)
except Exception as e:
DBExceptionHandler.handle_exception(e, context="updating user")
finally:
self.db.close()
async def delete_user(self, user_id: int): async def delete_user(self, user_id: int):
try:
user = self.db.query(Users).filter(Users.id == user_id).first() user = self.db.query(Users).filter(Users.id == user_id).first()
if not user: if not user:
@ -284,9 +301,18 @@ class UserServices:
user.soft_delete(self.db) user.soft_delete(self.db)
return True return True
except Exception as e:
DBExceptionHandler.handle_exception(e, context="deleting user")
finally:
self.db.close()
async def get_super_admins(self): async def get_super_admins(self):
try:
return self.db.query(Users).filter(Users.userType == UserType.SUPER_ADMIN).all() return self.db.query(Users).filter(Users.userType == UserType.SUPER_ADMIN).all()
except Exception as e:
DBExceptionHandler.handle_exception(e, context="getting super admins")
finally:
self.db.close()
async def _send_emails_to_admins(self, clinic_name): async def _send_emails_to_admins(self, clinic_name):
"""Helper method to send emails to all super admins""" """Helper method to send emails to all super admins"""
@ -300,8 +326,11 @@ class UserServices:
except Exception as e: except Exception as e:
# Log the error but don't interrupt the main flow # Log the error but don't interrupt the main flow
logger.error(f"Error sending admin emails: {str(e)}") logger.error(f"Error sending admin emails: {str(e)}")
finally:
self.db.close()
async def create_payment_link(self, user_id: int): async def create_payment_link(self, user_id: int):
try:
user = self.db.query(Users).filter(Users.id == user_id).first() user = self.db.query(Users).filter(Users.id == user_id).first()
if not user: if not user:
@ -309,3 +338,7 @@ class UserServices:
raise ResourceNotFoundException("User not found") raise ResourceNotFoundException("User not found")
return self.stripe_service.create_payment_link(user_id) return self.stripe_service.create_payment_link(user_id)
except Exception as e:
DBExceptionHandler.handle_exception(e, context="creating payment link")
finally:
self.db.close()