feat: clinic approval flow
This commit is contained in:
parent
205e423b56
commit
a00c3884c4
|
|
@ -11,7 +11,7 @@ from .endpoints import clinics, doctors, calender, appointments, patients, admin
|
||||||
|
|
||||||
api_router = APIRouter()
|
api_router = APIRouter()
|
||||||
# api_router.include_router(twilio.router, prefix="/twilio")
|
# api_router.include_router(twilio.router, prefix="/twilio")
|
||||||
api_router.include_router(clinics.router, prefix="/clinics", tags=["clinics"])
|
api_router.include_router(clinics.router, prefix="/clinics", tags=["clinics"], dependencies=[Depends(auth_required)])
|
||||||
|
|
||||||
api_router.include_router(doctors.router, prefix="/doctors", tags=["doctors"])
|
api_router.include_router(doctors.router, prefix="/doctors", tags=["doctors"])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,13 @@
|
||||||
from fastapi import APIRouter, status
|
from fastapi import APIRouter, Request, status
|
||||||
|
|
||||||
|
from services.clinicServices import ClinicServices
|
||||||
|
from schemas.UpdateSchemas import ClinicStatusUpdate
|
||||||
|
from schemas.ApiResponse import ApiResponse
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/", status_code=status.HTTP_200_OK)
|
@router.put("/clinic/status")
|
||||||
def get_admin():
|
def update_clinic_status(req:Request, data: ClinicStatusUpdate):
|
||||||
return {"message": "Admin"}
|
response = ClinicServices().update_clinic_status(req.state.user, data.clinic_id, data.status)
|
||||||
|
return ApiResponse(data=response, message="Clinic status updated successfully")
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,33 @@
|
||||||
from typing import List
|
from typing import List, Literal, Union
|
||||||
from fastapi import APIRouter, HTTPException, status
|
from fastapi import APIRouter, status, Request
|
||||||
|
|
||||||
# database
|
|
||||||
from database import get_db
|
|
||||||
|
|
||||||
# schemas
|
# schemas
|
||||||
from schemas.ResponseSchemas import Clinic
|
from schemas.ResponseSchemas import Clinic
|
||||||
from schemas.UpdateSchemas import ClinicUpdate
|
from schemas.UpdateSchemas import ClinicUpdate
|
||||||
from models.Clinics import Clinics
|
|
||||||
|
|
||||||
# services
|
# services
|
||||||
from services.clinicServices import ClinicServices
|
from services.clinicServices import ClinicServices
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
from schemas.ApiResponse import ApiResponse
|
from schemas.ApiResponse import ApiResponse
|
||||||
from utils.constants import DEFAULT_SKIP, DEFAULT_LIMIT
|
from interface.common_response import CommonResponse
|
||||||
|
from utils.constants import DEFAULT_PAGE, DEFAULT_SKIP, DEFAULT_LIMIT
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
||||||
@router.get("/", response_model=List[Clinic])
|
@router.get("/")
|
||||||
async def get_clinics(
|
async def get_clinics(
|
||||||
skip: int = DEFAULT_SKIP, limit: int = DEFAULT_LIMIT
|
req:Request,
|
||||||
|
page: int = DEFAULT_PAGE,
|
||||||
|
limit: int = DEFAULT_LIMIT,
|
||||||
|
filter_type: Union[Literal["UNREGISTERED"], Literal["REGISTERED"]] = "UNREGISTERED",
|
||||||
|
search:str = ""
|
||||||
):
|
):
|
||||||
clinics = ClinicServices().get_clinics(skip, limit)
|
if page < 1:
|
||||||
|
page = 1
|
||||||
|
offset = (page - 1) * limit
|
||||||
|
clinics = ClinicServices().get_clinics(req.state.user, limit, offset, filter_type, search)
|
||||||
return ApiResponse(data=clinics, message="Clinics retrieved successfully" )
|
return ApiResponse(data=clinics, message="Clinics retrieved successfully" )
|
||||||
|
|
||||||
@router.get("/latest-id")
|
@router.get("/latest-id")
|
||||||
|
|
@ -31,26 +35,26 @@ async def get_latest_clinic_id():
|
||||||
clinic_id = ClinicServices().get_latest_clinic_id()
|
clinic_id = ClinicServices().get_latest_clinic_id()
|
||||||
return ApiResponse(data=clinic_id, message="Latest clinic ID retrieved successfully")
|
return ApiResponse(data=clinic_id, message="Latest clinic ID retrieved successfully")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/verified-files/{clinic_id}")
|
||||||
|
async def get_verified_files(clinic_id: int):
|
||||||
|
clinic = ClinicServices().get_clinic_by_id(clinic_id)
|
||||||
|
return ApiResponse(data=clinic, message="Clinic retrieved successfully")
|
||||||
|
|
||||||
@router.get("/{clinic_id}")
|
@router.get("/{clinic_id}")
|
||||||
async def get_clinic(clinic_id: int):
|
async def get_clinic(clinic_id: int):
|
||||||
clinic = ClinicServices().get_clinic_by_id(clinic_id)
|
clinic = ClinicServices().get_clinic_by_id(clinic_id)
|
||||||
return ApiResponse(data=clinic, message="Clinic retrieved successfully")
|
return ApiResponse(data=clinic, message="Clinic retrieved successfully")
|
||||||
|
|
||||||
|
@router.put("/{clinic_id}")
|
||||||
@router.put("/{clinic_id}", response_model=Clinic)
|
|
||||||
async def update_clinic(
|
async def update_clinic(
|
||||||
|
req:Request,
|
||||||
clinic_id: int, clinic: ClinicUpdate
|
clinic_id: int, clinic: ClinicUpdate
|
||||||
):
|
):
|
||||||
clinic = ClinicServices().update_clinic(clinic_id, clinic)
|
clinic = ClinicServices().update_clinic(req.state.user, clinic_id, clinic)
|
||||||
return ApiResponse(data=clinic, message="Clinic updated successfully")
|
return ApiResponse(data=clinic, message="Clinic updated successfully")
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{clinic_id}", status_code=status.HTTP_204_NO_CONTENT)
|
@router.delete("/{clinic_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||||
async def delete_clinic(clinic_id: int):
|
async def delete_clinic(clinic_id: int):
|
||||||
db_clinic = db.query(Clinics).where(Clinics.id == clinic_id).first()
|
ClinicServices().delete_clinic(clinic_id)
|
||||||
if db_clinic is None:
|
return ApiResponse(message="Clinic deleted successfully")
|
||||||
raise HTTPException(status_code=404, detail="Clinic not found")
|
|
||||||
|
|
||||||
db.delete(db_clinic)
|
|
||||||
db.commit()
|
|
||||||
return None
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from fastapi import APIRouter, Request
|
||||||
from services.dashboardService import DashboardService
|
from services.dashboardService import DashboardService
|
||||||
from schemas.ApiResponse import ApiResponse
|
from schemas.ApiResponse import ApiResponse
|
||||||
from enums.enums import UserType
|
from enums.enums import UserType
|
||||||
|
from schemas.CreateSchemas import SignupPricingMasterCreate
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
|
@ -9,3 +10,15 @@ router = APIRouter()
|
||||||
async def get_clinic_doctor_status_count(req:Request):
|
async def get_clinic_doctor_status_count(req:Request):
|
||||||
counts = DashboardService().get_dashboard_counts(isSuperAdmin=req.state.user["userType"] == UserType.SUPER_ADMIN)
|
counts = DashboardService().get_dashboard_counts(isSuperAdmin=req.state.user["userType"] == UserType.SUPER_ADMIN)
|
||||||
return ApiResponse(data=counts, message="Counts fetched successfully")
|
return ApiResponse(data=counts, message="Counts fetched successfully")
|
||||||
|
|
||||||
|
@router.post("/signup-pricing-master")
|
||||||
|
async def update_signup_pricing_master(req:Request, signup_pricing_master:SignupPricingMasterCreate):
|
||||||
|
user = req.state.user
|
||||||
|
response = DashboardService().update_signup_pricing_master(user, signup_pricing_master)
|
||||||
|
return ApiResponse(data=response, message="Signup pricing master updated successfully")
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/signup-pricing-master")
|
||||||
|
async def get_signup_pricing_master():
|
||||||
|
pricing = DashboardService().get_signup_pricing_master()
|
||||||
|
return ApiResponse(data=pricing, message="Signup pricing master fetched successfully")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
"""file-verification-table
|
||||||
|
|
||||||
|
Revision ID: 497238c0338d
|
||||||
|
Revises: ad47f4af583e
|
||||||
|
Create Date: 2025-05-19 16:34:54.211429
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = '497238c0338d'
|
||||||
|
down_revision: Union[str, None] = 'ad47f4af583e'
|
||||||
|
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! ###
|
||||||
|
op.add_column('clinic_file_verifications', sa.Column('rejection_reason', sa.String(length=255), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
"""Downgrade schema."""
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('clinic_file_verifications', 'rejection_reason')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
"""file-verification-table
|
||||||
|
|
||||||
|
Revision ID: ec157808ef2a
|
||||||
|
Revises: 497238c0338d
|
||||||
|
Create Date: 2025-05-19 17:16:52.137111
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = 'ec157808ef2a'
|
||||||
|
down_revision: Union[str, None] = '497238c0338d'
|
||||||
|
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! ###
|
||||||
|
op.add_column('clinic_file_verifications', sa.Column('logo_is_verified', sa.Boolean(), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
"""Downgrade schema."""
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('clinic_file_verifications', 'logo_is_verified')
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
from database import Base
|
||||||
|
from sqlalchemy import Column, Integer, Boolean, ForeignKey, String
|
||||||
|
from .CustomBase import CustomBase
|
||||||
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
|
class ClinicFileVerifications(Base, CustomBase):
|
||||||
|
__tablename__ = "clinic_file_verifications"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
clinic_id = Column(Integer, ForeignKey("clinics.id"), nullable=False)
|
||||||
|
logo_is_verified = Column(Boolean, default=False)
|
||||||
|
abn_doc_is_verified = Column(Boolean, default=False)
|
||||||
|
contract_doc_is_verified = Column(Boolean, default=False)
|
||||||
|
last_changed_by = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||||
|
rejection_reason = Column(String(255), nullable=True)
|
||||||
|
|
||||||
|
clinic = relationship("Clinics", back_populates="clinic_file_verifications")
|
||||||
|
last_changed_by_user = relationship("Users", back_populates="clinic_file_verifications")
|
||||||
|
|
@ -45,3 +45,4 @@ class Clinics(Base, CustomBase):
|
||||||
doctors = relationship("Doctors", back_populates="clinic")
|
doctors = relationship("Doctors", back_populates="clinic")
|
||||||
clinicDoctors = relationship("ClinicDoctors", back_populates="clinic")
|
clinicDoctors = relationship("ClinicDoctors", back_populates="clinic")
|
||||||
creator = relationship("Users", back_populates="created_clinics")
|
creator = relationship("Users", back_populates="created_clinics")
|
||||||
|
clinic_file_verifications = relationship("ClinicFileVerifications", back_populates="clinic")
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
from sqlalchemy import Column, Integer, Numeric
|
||||||
|
from database import Base
|
||||||
|
from .CustomBase import CustomBase
|
||||||
|
|
||||||
|
class SignupPricingMaster(Base, CustomBase):
|
||||||
|
__tablename__ = "signup_pricing_master"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
setup_fees = Column(Numeric(precision=10, scale=2))
|
||||||
|
subscription_fees = Column(Numeric(precision=10, scale=2))
|
||||||
|
per_call_charges = Column(Numeric(precision=10, scale=2))
|
||||||
|
|
@ -25,3 +25,4 @@ class Users(Base, CustomBase):
|
||||||
|
|
||||||
# Clinics created by this user
|
# Clinics created by this user
|
||||||
created_clinics = relationship("Clinics", back_populates="creator")
|
created_clinics = relationship("Clinics", back_populates="creator")
|
||||||
|
clinic_file_verifications = relationship("ClinicFileVerifications", back_populates="last_changed_by_user")
|
||||||
|
|
@ -11,6 +11,8 @@ from .Notifications import Notifications
|
||||||
from .CallTranscripts import CallTranscripts
|
from .CallTranscripts import CallTranscripts
|
||||||
from .Fcm import Fcm
|
from .Fcm import Fcm
|
||||||
from .BlockedEmail import BlockedEmail
|
from .BlockedEmail import BlockedEmail
|
||||||
|
from .SignupPricingMaster import SignupPricingMaster
|
||||||
|
from .ClinicFileVerifications import ClinicFileVerifications
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Users",
|
"Users",
|
||||||
|
|
@ -26,4 +28,6 @@ __all__ = [
|
||||||
"CallTranscripts",
|
"CallTranscripts",
|
||||||
"Fcm",
|
"Fcm",
|
||||||
"BlockedEmail",
|
"BlockedEmail",
|
||||||
|
"SignupPricingMaster",
|
||||||
|
"ClinicFileVerifications"
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,17 @@ class SNSBase(BaseModel):
|
||||||
Message: str
|
Message: str
|
||||||
|
|
||||||
|
|
||||||
|
class ClinicFileVerificationBase(BaseModel):
|
||||||
|
abn_doc_is_verified: Optional[bool] = None
|
||||||
|
contract_doc_is_verified: Optional[bool] = None
|
||||||
|
logo_is_verified: Optional[bool] = None
|
||||||
|
last_changed_by: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
|
class SignupPricingMasterBase(BaseModel):
|
||||||
|
setup_fees: Optional[float] = None
|
||||||
|
subscription_fees: Optional[float] = None
|
||||||
|
per_call_charges: Optional[float] = None
|
||||||
|
|
||||||
class AuthBase(BaseModel):
|
class AuthBase(BaseModel):
|
||||||
email: EmailStr
|
email: EmailStr
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ class CalendarCreate(CalendarBase):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SignupPricingMasterCreate(SignupPricingMasterBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class AppointmentCreateWithNames(BaseModel):
|
class AppointmentCreateWithNames(BaseModel):
|
||||||
doctor_name: str
|
doctor_name: str
|
||||||
patient_name: str
|
patient_name: str
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
|
from enums.enums import ClinicStatus
|
||||||
from .BaseSchemas import *
|
from .BaseSchemas import *
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
|
|
@ -8,6 +10,7 @@ class Clinic(ClinicBase):
|
||||||
id: int
|
id: int
|
||||||
create_time: datetime
|
create_time: datetime
|
||||||
update_time: datetime
|
update_time: datetime
|
||||||
|
status: ClinicStatus
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
orm_mode = True
|
orm_mode = True
|
||||||
|
|
@ -22,6 +25,15 @@ class ClinicDoctorResponse(ClinicDoctorBase):
|
||||||
orm_mode = True
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
class SignupPricingMasterResponse(SignupPricingMasterBase):
|
||||||
|
id: int
|
||||||
|
create_time: datetime
|
||||||
|
update_time: datetime
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
orm_mode = True
|
||||||
|
|
||||||
|
|
||||||
class UserResponse(UserBase):
|
class UserResponse(UserBase):
|
||||||
id: int
|
id: int
|
||||||
create_time: datetime
|
create_time: datetime
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ class ClinicUpdate(BaseModel):
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
address: Optional[str] = None
|
address: Optional[str] = None
|
||||||
phone: Optional[str] = None
|
phone: Optional[str] = None
|
||||||
status: Optional[ClinicStatus] = None
|
|
||||||
integration: Optional[Integration] = None
|
integration: Optional[Integration] = None
|
||||||
pms_id: Optional[str] = None
|
pms_id: Optional[str] = None
|
||||||
practice_name: Optional[str] = None
|
practice_name: Optional[str] = None
|
||||||
|
|
@ -29,6 +28,14 @@ class ClinicUpdate(BaseModel):
|
||||||
general_info: Optional[str] = None
|
general_info: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class ClinicStatusUpdate(BaseModel):
|
||||||
|
clinic_id: int
|
||||||
|
status: ClinicStatus
|
||||||
|
rejection_reason: Optional[str] = None
|
||||||
|
|
||||||
|
class SignupPricingMasterUpdate(SignupPricingMasterBase):
|
||||||
|
pass
|
||||||
|
|
||||||
class DoctorUpdate(BaseModel):
|
class DoctorUpdate(BaseModel):
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
age: Optional[int] = None
|
age: Optional[int] = None
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,145 @@
|
||||||
from database import get_db
|
from database import get_db
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session, joinedload
|
||||||
from models import Clinics
|
from models import Clinics
|
||||||
from schemas.UpdateSchemas import ClinicUpdate
|
from schemas.UpdateSchemas import ClinicStatusUpdate, ClinicUpdate
|
||||||
from schemas.ResponseSchemas import Clinic
|
from schemas.ResponseSchemas import Clinic
|
||||||
from typing import List
|
from typing import List, Literal, Union
|
||||||
from exceptions import ResourceNotFoundException
|
from exceptions import ResourceNotFoundException
|
||||||
from enums.enums import ClinicStatus
|
from enums.enums import ClinicStatus, UserType
|
||||||
|
from exceptions.unauthorized_exception import UnauthorizedException
|
||||||
|
from interface.common_response import CommonResponse
|
||||||
|
from sqlalchemy import or_,func, case
|
||||||
|
|
||||||
|
from services.s3Service import get_signed_url
|
||||||
|
from models import ClinicFileVerifications
|
||||||
|
from schemas.BaseSchemas import ClinicFileVerificationBase
|
||||||
|
|
||||||
class ClinicServices:
|
class ClinicServices:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.db: Session = next(get_db())
|
self.db: Session = next(get_db())
|
||||||
|
|
||||||
def get_clinics(self, limit:int, offset:int) -> List[Clinic]:
|
def get_clinics(self, user, limit:int, offset:int, filter_type: Union[Literal["UNREGISTERED"], Literal["REGISTERED"]] = "UNREGISTERED", search:str = ""):
|
||||||
clinics = self.db.query(Clinics).limit(limit).offset(offset).all()
|
|
||||||
|
if user["userType"] != UserType.SUPER_ADMIN:
|
||||||
|
raise UnauthorizedException("You are not authorized to get clinics")
|
||||||
|
|
||||||
|
clinics_query = self.db.query(Clinics)
|
||||||
|
|
||||||
|
if filter_type == "UNREGISTERED":
|
||||||
|
clinics_query = clinics_query.filter(Clinics.status != ClinicStatus.ACTIVE)
|
||||||
|
elif filter_type == "REGISTERED":
|
||||||
|
clinics_query = clinics_query.filter(Clinics.status == ClinicStatus.ACTIVE)
|
||||||
|
|
||||||
|
if search:
|
||||||
|
clinics_query = clinics_query.filter(
|
||||||
|
or_(
|
||||||
|
Clinics.name.contains(search),
|
||||||
|
Clinics.email.contains(search),
|
||||||
|
Clinics.phone.contains(search),
|
||||||
|
Clinics.address.contains(search)
|
||||||
|
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
clinics = clinics_query.limit(limit).offset(offset).all()
|
||||||
|
|
||||||
|
# Get all counts in a single optimized query
|
||||||
|
from sqlalchemy import text
|
||||||
|
|
||||||
|
count_query = text("""
|
||||||
|
SELECT
|
||||||
|
COUNT(*) as total,
|
||||||
|
COUNT(CASE WHEN status = 'ACTIVE' THEN 1 END) as active,
|
||||||
|
COUNT(CASE WHEN status = 'REJECTED' THEN 1 END) as rejected
|
||||||
|
FROM clinics
|
||||||
|
""")
|
||||||
|
|
||||||
|
result = self.db.execute(count_query).first()
|
||||||
|
|
||||||
|
totalClinics = result.total or 0
|
||||||
|
totalRegisteredClinics = result.active or 0
|
||||||
|
totalRejectedClinics = result.rejected or 0
|
||||||
|
|
||||||
clinic_response = [Clinic(**clinic.__dict__.copy()) for clinic in clinics]
|
clinic_response = [Clinic(**clinic.__dict__.copy()) for clinic in clinics]
|
||||||
|
|
||||||
return clinic_response
|
for clinic in clinic_response:
|
||||||
|
clinic.logo = get_signed_url(clinic.logo) if clinic.logo else None
|
||||||
|
|
||||||
|
clinic_response_with_total = {
|
||||||
|
"clinics": clinic_response,
|
||||||
|
"totalRegisteredClinics": totalRegisteredClinics,
|
||||||
|
"totalRejectedClinics": totalRejectedClinics,
|
||||||
|
}
|
||||||
|
|
||||||
|
response = CommonResponse(data=clinic_response_with_total, total=totalClinics)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
def get_latest_clinic_id(self) -> int:
|
def get_latest_clinic_id(self) -> int:
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
def get_clinic_by_id(self, clinic_id: int) -> Clinic:
|
def get_clinic_by_id(self, clinic_id: int):
|
||||||
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
try:
|
||||||
|
clinic = self.db.query(Clinics).options(joinedload(Clinics.creator)).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_response = Clinic(**clinic.__dict__.copy())
|
clinic_response = Clinic(**clinic.__dict__.copy())
|
||||||
return clinic_response
|
|
||||||
|
|
||||||
def update_clinic(self, clinic_id: int, clinic_data: ClinicUpdate):
|
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_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)
|
||||||
|
}
|
||||||
|
|
||||||
|
return clinic_resp
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(e)
|
||||||
|
|
||||||
|
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:
|
||||||
|
raise ResourceNotFoundException("Clinic not found")
|
||||||
|
|
||||||
|
response = ClinicFileVerificationBase(**clinic_files.__dict__.copy())
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
def update_clinic(self, user, clinic_id: int, clinic_data: ClinicUpdate):
|
||||||
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")
|
||||||
|
|
||||||
|
if clinic.creator_id != user["id"]:
|
||||||
|
raise UnauthorizedException("You are not authorized to update this clinic")
|
||||||
|
|
||||||
update_data = clinic_data.model_dump(exclude_unset=True)
|
update_data = clinic_data.model_dump(exclude_unset=True)
|
||||||
|
|
||||||
for key, value in update_data.items():
|
for key, value in update_data.items():
|
||||||
setattr(clinic, key, value)
|
setattr(clinic, key, value)
|
||||||
|
|
||||||
self.db.add(clinic)
|
self.db.add(clinic)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
self.db.refresh(clinic)
|
self.db.refresh(clinic)
|
||||||
return Clinic(**clinic.__dict__.copy())
|
|
||||||
|
clinic_response = Clinic(**clinic.__dict__.copy())
|
||||||
|
clinic_response.logo = get_signed_url(clinic_response.logo) if clinic_response.logo else None
|
||||||
|
|
||||||
|
return clinic_response
|
||||||
|
|
||||||
def delete_clinic(self, clinic_id: int):
|
def delete_clinic(self, clinic_id: int):
|
||||||
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
||||||
|
|
@ -95,3 +189,28 @@ class ClinicServices:
|
||||||
counts[key] = count
|
counts[key] = count
|
||||||
|
|
||||||
return counts
|
return counts
|
||||||
|
|
||||||
|
|
||||||
|
def update_clinic_status(self, user, clinic_id: int, status: ClinicStatus):
|
||||||
|
|
||||||
|
if user["userType"] != UserType.SUPER_ADMIN:
|
||||||
|
raise UnauthorizedException("You are not authorized to update clinic status")
|
||||||
|
|
||||||
|
clinic = self.db.query(Clinics).filter(Clinics.id == clinic_id).first()
|
||||||
|
|
||||||
|
if clinic is None:
|
||||||
|
raise ResourceNotFoundException("Clinic not found")
|
||||||
|
|
||||||
|
clinic.status = status
|
||||||
|
self.db.add(clinic)
|
||||||
|
self.db.commit()
|
||||||
|
self.db.refresh(clinic)
|
||||||
|
|
||||||
|
clinic_response = Clinic(**clinic.__dict__.copy())
|
||||||
|
|
||||||
|
# if rejected then email to clinic creator
|
||||||
|
if clinic.status == ClinicStatus.REJECTED:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return clinic_response
|
||||||
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
from database import get_db
|
from database import get_db
|
||||||
from services.clinicDoctorsServices import ClinicDoctorsServices
|
from services.clinicDoctorsServices import ClinicDoctorsServices
|
||||||
from services.clinicServices import ClinicServices
|
from services.clinicServices import ClinicServices
|
||||||
|
from schemas.BaseSchemas import SignupPricingMasterBase
|
||||||
|
from schemas.ResponseSchemas import SignupPricingMasterResponse
|
||||||
|
from models.SignupPricingMaster import SignupPricingMaster
|
||||||
|
from exceptions import UnauthorizedException
|
||||||
|
from enums.enums import UserType
|
||||||
|
from exceptions import ResourceNotFoundException
|
||||||
|
|
||||||
class DashboardService:
|
class DashboardService:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
@ -15,3 +21,54 @@ class DashboardService:
|
||||||
else:
|
else:
|
||||||
clinicDoctorsCount = self.clinicDoctorsServices.get_doctor_status_count()
|
clinicDoctorsCount = self.clinicDoctorsServices.get_doctor_status_count()
|
||||||
return clinicDoctorsCount
|
return clinicDoctorsCount
|
||||||
|
|
||||||
|
def update_signup_pricing_master(
|
||||||
|
self, user, pricing_data: SignupPricingMasterBase
|
||||||
|
):
|
||||||
|
if user["userType"] != UserType.SUPER_ADMIN:
|
||||||
|
raise UnauthorizedException(
|
||||||
|
"You are not authorized to update signup pricing master"
|
||||||
|
)
|
||||||
|
|
||||||
|
existing_pricing = self.db.query(SignupPricingMaster).first()
|
||||||
|
|
||||||
|
if existing_pricing is None:
|
||||||
|
# Create new record
|
||||||
|
new_pricing = SignupPricingMaster(
|
||||||
|
**pricing_data.model_dump()
|
||||||
|
)
|
||||||
|
self.db.add(new_pricing)
|
||||||
|
self.db.commit()
|
||||||
|
self.db.refresh(new_pricing)
|
||||||
|
|
||||||
|
response = SignupPricingMasterResponse(
|
||||||
|
**new_pricing.__dict__.copy()
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
# Update existing record with values from the request
|
||||||
|
existing_pricing.setup_fees = pricing_data.setup_fees
|
||||||
|
existing_pricing.subscription_fees = pricing_data.subscription_fees
|
||||||
|
existing_pricing.per_call_charges = pricing_data.per_call_charges
|
||||||
|
|
||||||
|
self.db.commit()
|
||||||
|
self.db.refresh(existing_pricing)
|
||||||
|
|
||||||
|
response = SignupPricingMasterResponse(
|
||||||
|
**existing_pricing.__dict__.copy()
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
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")
|
||||||
|
|
||||||
|
response = SignupPricingMasterResponse(
|
||||||
|
**signup_pricing_master.__dict__.copy()
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,12 @@ from schemas.UpdateSchemas import UserUpdate
|
||||||
from exceptions.unauthorized_exception import UnauthorizedException
|
from exceptions.unauthorized_exception import UnauthorizedException
|
||||||
from interface.common_response import CommonResponse
|
from interface.common_response import CommonResponse
|
||||||
from exceptions.business_exception import BusinessValidationException
|
from exceptions.business_exception import BusinessValidationException
|
||||||
|
from models import ClinicFileVerifications
|
||||||
from utils.password_utils import hash_password
|
from utils.password_utils import hash_password
|
||||||
from schemas.CreateSchemas import UserCreate
|
from schemas.CreateSchemas import UserCreate
|
||||||
from exceptions.resource_not_found_exception import ResourceNotFoundException
|
from exceptions.resource_not_found_exception import ResourceNotFoundException
|
||||||
from exceptions.db_exceptions import DBExceptionHandler
|
from exceptions.db_exceptions import DBExceptionHandler
|
||||||
|
from sqlalchemy.orm import joinedload
|
||||||
|
|
||||||
|
|
||||||
class UserServices:
|
class UserServices:
|
||||||
|
|
@ -98,6 +100,18 @@ class UserServices:
|
||||||
|
|
||||||
# Add clinic to database
|
# Add clinic to database
|
||||||
self.db.add(new_clinic)
|
self.db.add(new_clinic)
|
||||||
|
self.db.flush()
|
||||||
|
|
||||||
|
# Create clinic files
|
||||||
|
clinic_files = ClinicFileVerifications(
|
||||||
|
clinic_id=new_clinic.id,
|
||||||
|
abn_doc_is_verified=False,
|
||||||
|
contract_doc_is_verified=False,
|
||||||
|
last_changed_by=new_user.id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add clinic files to database
|
||||||
|
self.db.add(clinic_files)
|
||||||
|
|
||||||
# Now commit both user and clinic in a single transaction
|
# Now commit both user and clinic in a single transaction
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
@ -114,7 +128,6 @@ class UserServices:
|
||||||
def get_user(self, user_id) -> UserResponse:
|
def get_user(self, user_id) -> UserResponse:
|
||||||
try:
|
try:
|
||||||
# Query the user by ID and explicitly load the created clinics relationship
|
# Query the user by ID and explicitly load the created clinics relationship
|
||||||
from sqlalchemy.orm import joinedload
|
|
||||||
user = self.db.query(Users).options(joinedload(Users.created_clinics)).filter(Users.id == user_id).first()
|
user = self.db.query(Users).options(joinedload(Users.created_clinics)).filter(Users.id == user_id).first()
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue