fix: async apis

This commit is contained in:
2025-05-23 13:32:24 +05:30
parent 8159d34c65
commit b2fb39ff87
17 changed files with 173 additions and 175 deletions
+12 -12
View File
@@ -36,10 +36,10 @@ class AuthService:
self.email_service = EmailService()
self.url = os.getenv("FRONTEND_URL")
def login(self, data: AuthBase) -> str:
async def login(self, data: AuthBase) -> str:
# get user
user = self.user_service.get_user_by_email(data.email)
user = await self.user_service.get_user_by_email(data.email)
# verify password
if not verify_password(data.password, user.password):
@@ -53,8 +53,8 @@ class AuthService:
token = create_jwt_token(user_dict)
return token
def register(self, user_data: UserCreate, background_tasks=None):
response = self.user_service.create_user(user_data, background_tasks)
async def register(self, user_data: UserCreate, background_tasks=None):
response = await self.user_service.create_user(user_data, background_tasks)
user = {
"id": response.id,
"username": response.username,
@@ -93,7 +93,7 @@ class AuthService:
return "OK"
def send_otp(self, email:str):
async def send_otp(self, email:str):
otp = generateOTP()
self.email_service.send_otp_email(email, otp)
@@ -105,7 +105,7 @@ class AuthService:
return
def verify_otp(self, data: AuthOTP):
async def verify_otp(self, data: AuthOTP):
db_otp = self.db.query(OTP).filter(OTP.email == data.email, OTP.otp == data.otp).first()
if not db_otp:
raise ValidationException("Invalid OTP")
@@ -121,7 +121,7 @@ class AuthService:
return
def get_admins(self, user, limit:int, offset:int, search:str):
async def get_admins(self, user, limit:int, offset:int, search:str):
try:
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action")
@@ -150,7 +150,7 @@ class AuthService:
except Exception as e:
raise e
def create_super_admin(self, user, data: CreateSuperAdmin):
async def create_super_admin(self, user, data: CreateSuperAdmin):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action")
@@ -191,7 +191,7 @@ class AuthService:
return
def update_super_admin(self, user, user_id: int, data: UpdateSuperAdmin):
async def update_super_admin(self, user, user_id: int, data: UpdateSuperAdmin):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action")
@@ -207,7 +207,7 @@ class AuthService:
return
def delete_super_admin(self, user, user_id: int):
async def delete_super_admin(self, user, user_id: int):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action")
@@ -221,7 +221,7 @@ class AuthService:
return
def forget_password(self, email: str):
async def forget_password(self, email: str):
user = self.db.query(Users).filter(Users.email == email.lower()).first()
if not user:
@@ -240,7 +240,7 @@ class AuthService:
return
def reset_password(self, token: str, password: str):
async def reset_password(self, token: str, password: str):
reset_password = self.db.query(ResetPasswordTokens).filter(ResetPasswordTokens.token == token).first()
if not reset_password:
+2 -2
View File
@@ -18,7 +18,7 @@ class CallTranscriptServices:
def __init__(self):
self.db:Session = next(get_db())
def get_call_transcripts(self, limit:int, offset:int):
async def get_call_transcripts(self, limit:int, offset:int):
call_transcripts = self.db.query(CallTranscripts).limit(limit).offset(offset).all()
total = self.db.query(CallTranscripts).count()
@@ -84,7 +84,7 @@ class CallTranscriptServices:
except Exception as e:
print(f"Error during cleanup: {e}")
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):
transcript_ids = self.db.query(CallTranscripts).filter(CallTranscripts.id.in_(key_ids)).all()
+7 -8
View File
@@ -7,13 +7,15 @@ from sqlalchemy.orm import Session
from services.clinicServices import ClinicServices
from exceptions import ResourceNotFoundException
from interface.common_response import CommonResponse
from sqlalchemy import func
from enums.enums import ClinicDoctorStatus
class ClinicDoctorsServices:
def __init__(self):
self.db: Session = next(get_db())
self.clinic_services = ClinicServices()
def create_clinic_doctor(self, clinic_doctor: ClinicDoctorCreate) -> ClinicDoctorResponse:
async def create_clinic_doctor(self, clinic_doctor: ClinicDoctorCreate) -> ClinicDoctorResponse:
# check if clinic exists
self.clinic_services.get_clinic_by_id(clinic_doctor.clinic_id)
@@ -24,7 +26,7 @@ class ClinicDoctorsServices:
self.db.refresh(clinic_doctor)
return ClinicDoctorResponse(**clinic_doctor.__dict__.copy())
def update_clinic_doctor(self, clinic_doctor_id: int, clinic_doctor_data: ClinicDoctorUpdate) -> ClinicDoctorResponse:
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:
@@ -44,15 +46,12 @@ class ClinicDoctorsServices:
self.db.refresh(clinic_doctor)
return ClinicDoctorResponse(**clinic_doctor.__dict__.copy())
def delete_clinic_doctor(self, clinic_doctor_id: int):
async def delete_clinic_doctor(self, clinic_doctor_id: int):
clinic_doctor = self.db.query(ClinicDoctors).filter(ClinicDoctors.id == clinic_doctor_id).first()
self.db.delete(clinic_doctor)
self.db.commit()
def get_doctor_status_count(self):
# Use SQLAlchemy's func.count to get the count for each status
from sqlalchemy import func
from enums.enums import ClinicDoctorStatus
async def get_doctor_status_count(self):
# Query to count doctors by status
status_counts = self.db.query(
@@ -69,7 +68,7 @@ class ClinicDoctorsServices:
return result
def get_clinic_doctors(self):
async def get_clinic_doctors(self):
clinic_doctors = self.db.query(ClinicDoctors).all()
total = self.db.query(ClinicDoctors).count()
+46 -42
View File
@@ -11,7 +11,7 @@ from sqlalchemy import or_,not_
from sqlalchemy import text
from services.s3Service import get_file_key, get_signed_url
from models import ClinicFileVerifications, ClinicOffers, Clinics
from models import ClinicFileVerifications, ClinicOffers, Clinics, Users
from schemas.BaseSchemas import ClinicFileVerificationBase, ClinicOffersBase
from services.emailService import EmailService
@@ -20,12 +20,12 @@ class ClinicServices:
self.db: Session = next(get_db())
self.email_service = EmailService()
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 = ""):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to get clinics")
clinics_query = self.db.query(Clinics)
clinics_query = self.db.query(Clinics).order_by(Clinics.update_time.desc())
if filter_type == "UNREGISTERED":
clinics_query = clinics_query.filter(not_(Clinics.status == ClinicStatus.ACTIVE),not_(Clinics.status == ClinicStatus.INACTIVE))
@@ -43,7 +43,7 @@ class ClinicServices:
)
)
clinics = clinics_query.limit(limit).offset(offset).all()
clinics = clinics_query.offset(offset).limit(limit).all()
count_query = text("""
SELECT
@@ -62,7 +62,7 @@ class ClinicServices:
clinic_response = [Clinic(**clinic.__dict__.copy()) for clinic in clinics]
for clinic in clinic_response:
clinic.logo = get_signed_url(clinic.logo) if clinic.logo else None
clinic.logo = await get_signed_url(clinic.logo) if clinic.logo else None
clinic_response_with_total = {
"clinics": clinic_response,
@@ -74,45 +74,42 @@ class ClinicServices:
return response
def get_latest_clinic_id(self) -> int:
async def get_latest_clinic_id(self) -> int:
clinic = self.db.query(Clinics).order_by(Clinics.id.desc()).first()
return clinic.id if clinic else 0
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()
async def get_clinic_by_id(self, clinic_id: int):
clinic = self.db.query(Clinics).options(joinedload(Clinics.creator)).filter(Clinics.id == clinic_id).first()
if clinic is None:
raise ResourceNotFoundException("Clinic not found")
if clinic is None:
raise ResourceNotFoundException("Clinic not found")
clinic_response = Clinic(**clinic.__dict__.copy())
clinic_response.logo = get_signed_url(clinic_response.logo) if clinic_response.logo else None
clinic_response.abn_doc = get_signed_url(clinic_response.abn_doc) if clinic_response.abn_doc else None
clinic_response.contract_doc = get_signed_url(clinic_response.contract_doc) if clinic_response.contract_doc else None
clinic_response = Clinic(**clinic.__dict__.copy())
clinic_response.logo = await get_signed_url(clinic_response.logo) if clinic_response.logo else None
clinic_response.abn_doc = await get_signed_url(clinic_response.abn_doc) if clinic_response.abn_doc else None
clinic_response.contract_doc = await get_signed_url(clinic_response.contract_doc) if clinic_response.contract_doc else None
clinicFiles = None
if(clinic.status != ClinicStatus.ACTIVE):
clinicFiles = self.db.query(ClinicFileVerifications).filter(ClinicFileVerifications.clinic_id == clinic_id).first()
clinicFiles = None
if(clinic.status != ClinicStatus.ACTIVE):
clinicFiles = self.db.query(ClinicFileVerifications).filter(ClinicFileVerifications.clinic_id == clinic_id).first()
clinic_resp = {
"clinic": clinic_response,
"creator": {
"name": clinic.creator.username,
"email": clinic.creator.email,
"phone": clinic.creator.mobile,
"designation": clinic.creator.clinicRole
},
"clinic_files": self.get_clinic_files(clinic_id),
"fileStatus": {"reason":clinicFiles.rejection_reason if clinicFiles else None},
}
clinic_resp = {
"clinic": clinic_response,
"creator": {
"name": clinic.creator.username,
"email": clinic.creator.email,
"phone": clinic.creator.mobile,
"designation": clinic.creator.clinicRole
},
"clinic_files": await self.get_clinic_files(clinic_id),
"fileStatus": {"reason":clinicFiles.rejection_reason if clinicFiles else None},
}
return clinic_resp
except Exception as e:
raise Exception(e)
return clinic_resp
def get_clinic_files(self, clinic_id: int):
async def get_clinic_files(self, clinic_id: int):
clinic_files = self.db.query(ClinicFileVerifications).filter(ClinicFileVerifications.clinic_id == clinic_id).first()
if clinic_files is None:
@@ -122,7 +119,7 @@ class ClinicServices:
return response
def update_clinic(self, user, clinic_id: int, clinic_data: ClinicUpdate):
async def update_clinic(self, user, clinic_id: int, clinic_data: ClinicUpdate):
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
if clinic is None:
@@ -149,7 +146,7 @@ class ClinicServices:
return clinic_response
def delete_clinic(self, clinic_id: int):
async def delete_clinic(self, clinic_id: int):
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
if clinic is None:
@@ -157,7 +154,7 @@ class ClinicServices:
clinic.soft_delete(self.db)
def get_clinic_count(self):
async def get_clinic_count(self):
from sqlalchemy import func
# Get total count
@@ -199,7 +196,7 @@ class ClinicServices:
return counts
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):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to update clinic status")
@@ -258,11 +255,18 @@ class ClinicServices:
# handle inactive status
if clinic.status == ClinicStatus.INACTIVE:
# get clinic creator
# clinic_creator = self.db.query(Users).options(joinedload(Users.created_clinics)).filter(Clinics.id == clinic.id).first()
# # block clinic creator
# clinic_creator.isBlocked = True
# self.db.add(clinic_creator)
# self.db.commit()
pass
return
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 = ""):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to get clinic offers")
@@ -283,7 +287,7 @@ class ClinicServices:
return response
def create_clinic_offer(self, user, clinic_offer_data: ClinicOffersBase):
async def create_clinic_offer(self, user, clinic_offer_data: ClinicOffersBase):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to create clinic offer")
@@ -299,7 +303,7 @@ class ClinicServices:
return
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):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to update clinic offer")
@@ -316,7 +320,7 @@ class ClinicServices:
return
def delete_clinic_offer(self, user, clinic_offer_id: int):
async def delete_clinic_offer(self, user, clinic_offer_id: int):
if user["userType"] != UserType.SUPER_ADMIN:
raise UnauthorizedException("You are not authorized to delete clinic offer")
+5 -5
View File
@@ -14,15 +14,15 @@ class DashboardService:
self.clinicDoctorsServices = ClinicDoctorsServices()
self.clinicServices = ClinicServices()
def get_dashboard_counts(self, isSuperAdmin: bool):
async def get_dashboard_counts(self, isSuperAdmin: bool):
if isSuperAdmin:
clinicCounts = self.clinicServices.get_clinic_count()
clinicCounts = await self.clinicServices.get_clinic_count()
return clinicCounts
else:
clinicDoctorsCount = self.clinicDoctorsServices.get_doctor_status_count()
clinicDoctorsCount = await self.clinicDoctorsServices.get_doctor_status_count()
return clinicDoctorsCount
def update_signup_pricing_master(
async def update_signup_pricing_master(
self, user, pricing_data: SignupPricingMasterBase
):
if user["userType"] != UserType.SUPER_ADMIN:
@@ -62,7 +62,7 @@ class DashboardService:
return response
def get_signup_pricing_master(self):
async def get_signup_pricing_master(self):
signup_pricing_master = self.db.query(SignupPricingMaster).first()
if signup_pricing_master is None:
raise ResourceNotFoundException("Signup pricing master not found")
+4 -4
View File
@@ -12,7 +12,7 @@ class MasterAppointmentServices:
self.db: Session = next(get_db())
def get_master_appointment_types(self):
async def get_master_appointment_types(self):
appointment_types = self.db.query(MasterAppointmentTypes).all()
total= self.db.query(MasterAppointmentTypes).count()
response = CommonResponse(data=[MasterAppointmentTypeResponse(**appointment_type.__dict__.copy()) for appointment_type in appointment_types], total=total)
@@ -22,7 +22,7 @@ class MasterAppointmentServices:
existing_appointment_type = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.type == appointment_type.type.lower()).first()
return existing_appointment_type
def create_master_appointment_type(self, appointment_type: MasterAppointmentTypeBase):
async def create_master_appointment_type(self, appointment_type: MasterAppointmentTypeBase):
# get existing appointment type
existing_appointment_type = self.is_appointment_type_exists(appointment_type)
@@ -37,7 +37,7 @@ class MasterAppointmentServices:
self.db.commit()
return
def delete_master_appointment_type(self, appointment_type_id: int):
async def delete_master_appointment_type(self, appointment_type_id: int):
appointment_type = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.id == appointment_type_id).first()
if appointment_type is None:
@@ -47,7 +47,7 @@ class MasterAppointmentServices:
self.db.commit()
return
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):
appointment_type_db = self.db.query(MasterAppointmentTypes).filter(MasterAppointmentTypes.id == appointment_type_id).first()
if appointment_type_db is None:
+2 -2
View File
@@ -40,7 +40,7 @@ class S3Service:
def get_s3_service():
return S3Service()
def upload_file(
async def upload_file(
folder: S3FolderNameEnum,
file_name: str,
) -> Dict[str, str]:
@@ -93,7 +93,7 @@ def upload_file(
print(f"Error generating pre-signed URL: {e}")
raise BusinessValidationException(str(e))
def get_signed_url(key: str) -> str:
async def get_signed_url(key: str) -> str:
"""
Generate a pre-signed URL for retrieving a file from S3.
+18 -22
View File
@@ -24,7 +24,7 @@ class UserServices:
self.db: Session = next(get_db())
self.email_service = EmailService()
def create_user(self, user_data: UserCreate, background_tasks=None):
async def create_user(self, user_data: UserCreate, background_tasks=None):
# Start a transaction
try:
user = user_data.user
@@ -114,9 +114,6 @@ class UserServices:
# Add clinic files to database
self.db.add(clinic_files)
# Now commit both user and clinic in a single transaction
self.db.commit()
# Send mail to admin in a non-blocking way using background tasks
if background_tasks:
background_tasks.add_task(self._send_emails_to_admins, clinic.email)
@@ -130,8 +127,10 @@ class UserServices:
# Use the centralized exception handler
DBExceptionHandler.handle_exception(e, context="creating user")
finally:
self.db.commit()
def get_user(self, user_id) -> UserResponse:
async def get_user(self, user_id) -> UserResponse:
try:
# Query the user by ID and explicitly load the created clinics relationship
user = self.db.query(Users).options(joinedload(Users.created_clinics)).filter(Users.id == user_id).first()
@@ -165,7 +164,7 @@ class UserServices:
from twillio.exceptions.db_exceptions import DBExceptionHandler
DBExceptionHandler.handle_exception(e, context="getting user")
def get_users(self, limit:int, offset:int, search:str):
async def get_users(self, limit:int, offset:int, search:str):
query = self.db.query(Users)
if search:
query = query.filter(
@@ -185,23 +184,20 @@ class UserServices:
return response
def get_user_by_email(self, email: str) -> UserResponse:
try:
user = self.db.query(Users).filter(Users.email == email.lower()).first()
async def get_user_by_email(self, email: str) -> UserResponse:
user = self.db.query(Users).filter(Users.email == email.lower()).first()
if not user:
logger.error("User not found")
raise ResourceNotFoundException("User not found")
if not user:
logger.error("User not found")
raise ResourceNotFoundException("User not found")
user_dict = user.__dict__.copy()
user_dict = user.__dict__.copy()
user_response = UserResponse(**user_dict)
user_response = UserResponse(**user_dict)
return user_response
except Exception as e:
raise e
return user_response
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:
# Check admin authorization if admin_id is provided
if admin_id:
admin = self.db.query(Users).filter(Users.id == admin_id).first()
@@ -232,7 +228,7 @@ class UserServices:
# Return properly serialized response
return UserResponse.model_validate(user)
def delete_user(self, user_id: int):
async def delete_user(self, user_id: int):
user = self.db.query(Users).filter(Users.id == user_id).first()
if not user:
@@ -244,13 +240,13 @@ class UserServices:
return True
def get_super_admins(self):
async def get_super_admins(self):
return self.db.query(Users).filter(Users.userType == UserType.SUPER_ADMIN).all()
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"""
try:
admins = self.get_super_admins()
admins = await self.get_super_admins()
for admin in admins:
self.email_service.send_new_clinic_email(
to_address=admin.email,