feat: clinic bank details api

fix: relation betn stripe and user table
This commit is contained in:
deepvasoya 2025-06-05 19:25:33 +05:30
parent 7f2f730426
commit 165385358f
13 changed files with 381 additions and 149 deletions

View File

@ -10,6 +10,7 @@ router = APIRouter()
@router.get("/")
async def get_clinic_doctors(
req:Request,
limit:int= DEFAULT_LIMIT,
page:int = DEFAULT_PAGE,
search:str = "",
@ -19,7 +20,7 @@ async def get_clinic_doctors(
if page < 1:
page = 1
offset = (page - 1) * limit
clinic_doctors = await ClinicDoctorsServices().get_clinic_doctors(limit, offset, search, sort_by, sort_order)
clinic_doctors = await ClinicDoctorsServices().get_clinic_doctors(req.state.user, limit, offset, search, sort_by, sort_order)
return ApiResponse(data=clinic_doctors, message="Clinic doctors retrieved successfully")
@router.post("/")

View File

@ -8,7 +8,7 @@ router = APIRouter()
@router.get("/")
async def get_clinic_doctor_status_count(req:Request):
counts = await DashboardService().get_dashboard_counts(isSuperAdmin=req.state.user["userType"] == UserType.SUPER_ADMIN)
counts = await DashboardService().get_dashboard_counts(req.state.user)
return ApiResponse(data=counts, message="Counts fetched successfully")
@router.post("/signup-pricing-master")

View File

@ -25,6 +25,10 @@ stripe_service = StripeServices()
# customer_id="cus_SNn49FDltUcSLP"
# )
@router.get("/create-stripe-account-link", dependencies=[Depends(auth_required)])
async def create_stripe_account_link(req:Request):
link = await stripe_service.create_stripe_account_link(req.state.user)
return ApiResponse(data=link, message="Stripe account link created successfully")
@router.get("/get-invoice", dependencies=[Depends(auth_required)])
async def get_invoice(req:Request):

View File

@ -0,0 +1,38 @@
"""updated_stripeuser
Revision ID: e50edac1c8f0
Revises: 8d19e726b997
Create Date: 2025-06-05 18:22:38.502127
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = 'e50edac1c8f0'
down_revision: Union[str, None] = '8d19e726b997'
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('stripe_users', sa.Column('clinic_id', sa.Integer(), nullable=True))
op.drop_constraint('stripe_users_user_id_key', 'stripe_users', type_='unique')
op.drop_constraint('stripe_users_user_id_fkey', 'stripe_users', type_='foreignkey')
op.create_foreign_key(None, 'stripe_users', 'clinics', ['clinic_id'], ['id'])
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'stripe_users', type_='foreignkey')
op.create_foreign_key('stripe_users_user_id_fkey', 'stripe_users', 'users', ['user_id'], ['id'])
op.create_unique_constraint('stripe_users_user_id_key', 'stripe_users', ['user_id'])
op.drop_column('stripe_users', 'clinic_id')
# ### end Alembic commands ###

View File

@ -46,3 +46,6 @@ class Clinics(Base, CustomBase):
clinicDoctors = relationship("ClinicDoctors", back_populates="clinic")
creator = relationship("Users", back_populates="created_clinics")
clinic_file_verifications = relationship("ClinicFileVerifications", back_populates="clinic")
# Stripe relationships
stripe_user = relationship("StripeUsers", back_populates="clinic")

View File

@ -6,8 +6,10 @@ from sqlalchemy.orm import relationship
class StripeUsers(Base, CustomBase):
__tablename__ = "stripe_users"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey('users.id'), nullable=False, unique=True)
user_id = Column(Integer, nullable=True)
clinic_id = Column(Integer, ForeignKey('clinics.id'), nullable=True)
customer_id = Column(String)
account_id = Column(String)
user = relationship("Users", back_populates="stripe_user")
clinic = relationship("Clinics", back_populates="stripe_user")

View File

@ -27,5 +27,4 @@ class Users(Base, CustomBase):
created_clinics = relationship("Clinics", back_populates="creator")
clinic_file_verifications = relationship("ClinicFileVerifications", back_populates="last_changed_by_user")
# Stripe relationships
stripe_user = relationship("StripeUsers", back_populates="user")
# No longer have Stripe relationships

View File

@ -139,3 +139,8 @@ class ClinicOffersBase(BaseModel):
setup_fees_waived: bool
special_offer_for_month: str
class StripeUserBase(BaseModel):
account_id: str
customer_id: str
user_id: int

View File

@ -23,7 +23,7 @@ class ClinicDoctorResponse(ClinicDoctorBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class SignupPricingMasterResponse(SignupPricingMasterBase):
@ -32,7 +32,7 @@ class SignupPricingMasterResponse(SignupPricingMasterBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class UserResponse(UserBase):
@ -53,7 +53,7 @@ class Doctor(DoctorBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class Patient(PatientBase):
@ -62,7 +62,7 @@ class Patient(PatientBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class AppointmentSchema(AppointmentBase):
@ -71,7 +71,7 @@ class AppointmentSchema(AppointmentBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class Calendar(CalendarBase):
@ -80,7 +80,7 @@ class Calendar(CalendarBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
# custom schema for response
@ -88,7 +88,7 @@ class CalendarTimeSchema(BaseModel):
time: str
class Config:
orm_mode = True
from_attributes = True
class ClinicSchema(BaseModel):
@ -99,7 +99,7 @@ class ClinicSchema(BaseModel):
email: str
class Config:
orm_mode = True
from_attributes = True
# Detailed response schemas with nested relationships
@ -133,7 +133,7 @@ class AppointmentDetailed(AppointmentSchema):
address: str
class Config:
orm_mode = True
from_attributes = True
class Patient(BaseModel):
id: int
@ -145,7 +145,7 @@ class AppointmentDetailed(AppointmentSchema):
dob: str
class Config:
orm_mode = True
from_attributes = True
doctor: Doctor
patient: Patient
@ -157,7 +157,7 @@ class CallTranscriptsResponse(CallTranscriptsBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class NotificationResponse(NotificationBase):
@ -166,7 +166,7 @@ class NotificationResponse(NotificationBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class MasterAppointmentTypeResponse(MasterAppointmentTypeBase):
@ -175,7 +175,7 @@ class MasterAppointmentTypeResponse(MasterAppointmentTypeBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class ClinicDoctorResponse(ClinicDoctorBase):
@ -185,7 +185,6 @@ class ClinicDoctorResponse(ClinicDoctorBase):
appointmentTypes: Optional[List[MasterAppointmentTypeResponse]] = []
class Config:
orm_mode = True
from_attributes = True
allow_population_by_field_name = True
@ -196,4 +195,14 @@ class ClinicOfferResponse(ClinicOffersBase):
update_time: datetime
class Config:
orm_mode = True
from_attributes = True
class StripeUserReponse(StripeUserBase):
id: int
create_time: datetime
update_time: datetime
class Config:
from_attributes = True

View File

@ -3,14 +3,13 @@ from schemas.CreateSchemas import ClinicDoctorCreate
from schemas.UpdateSchemas import ClinicDoctorUpdate
from schemas.ResponseSchemas import ClinicDoctorResponse, MasterAppointmentTypeResponse
from database import get_db
from models import ClinicDoctors
from sqlalchemy.orm import Session, joinedload, selectinload
from services.clinicServices import ClinicServices
from exceptions import ResourceNotFoundException
from interface.common_response import CommonResponse
from sqlalchemy import func, or_, cast, String
from enums.enums import ClinicDoctorStatus, UserType
from models import MasterAppointmentTypes, AppointmentRelations
from models import MasterAppointmentTypes, AppointmentRelations, Users, ClinicDoctors
from utils.constants import DEFAULT_ORDER, DEFAULT_ORDER_BY
@ -174,13 +173,14 @@ class ClinicDoctorsServices:
finally:
self.db.close()
async def get_doctor_status_count(self):
async def get_doctor_status_count(self, clinic_id:int):
try:
# Query to count doctors by status
status_counts = (
self.db.query(
ClinicDoctors.status, func.count(ClinicDoctors.id).label("count")
)
.filter(ClinicDoctors.clinic_id == clinic_id)
.group_by(ClinicDoctors.status)
.all()
)
@ -198,10 +198,11 @@ class ClinicDoctorsServices:
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,user, limit: int, offset: int, search: str = "", sort_by: str = DEFAULT_ORDER, sort_order: str = DEFAULT_ORDER_BY):
try:
clinic_doctors_query = (
self.db.query(ClinicDoctors)
.filter(ClinicDoctors.clinic_id == user["created_clinics"][0]["id"])
.options(
selectinload(ClinicDoctors.appointmentRelations)
.selectinload(AppointmentRelations.masterAppointmentTypes)

View File

@ -8,6 +8,8 @@ from exceptions import UnauthorizedException
from enums.enums import UserType
from exceptions import ResourceNotFoundException
from loguru import logger
from models import Users
class DashboardService:
def __init__(self):
self.db = next(get_db())
@ -15,13 +17,17 @@ class DashboardService:
self.clinicServices = ClinicServices()
self.logger = logger
async def get_dashboard_counts(self, isSuperAdmin: bool):
if isSuperAdmin:
async def get_dashboard_counts(self, user):
try:
if user["userType"] == UserType.SUPER_ADMIN:
clinicCounts = await self.clinicServices.get_clinic_count()
return clinicCounts
else:
clinicDoctorsCount = await self.clinicDoctorsServices.get_doctor_status_count()
clinicDoctorsCount = await self.clinicDoctorsServices.get_doctor_status_count(user["created_clinics"][0]["id"])
return clinicDoctorsCount
except Exception as e:
self.logger.error("Error getting dashboard counts: ", e)
raise e
async def update_signup_pricing_master(
self, user, pricing_data: SignupPricingMasterBase

View File

@ -3,7 +3,6 @@ import os
import dotenv
dotenv.load_dotenv()
from models import ClinicOffers, StripeUsers
@ -11,12 +10,13 @@ from services.dashboardService import DashboardService
from exceptions.validation_exception import ValidationException
from exceptions.resource_not_found_exception import ResourceNotFoundException
from exceptions.unauthorized_exception import UnauthorizedException
from models import Clinics,PaymentSessions, Subscriptions
from models import Clinics, PaymentSessions, Subscriptions
import uuid
from fastapi import Request
from datetime import datetime
from models import PaymentLogs
from enums.enums import ClinicStatus, UserType
from schemas.ResponseSchemas import StripeUserReponse
from database import get_db
from sqlalchemy.orm import Session
@ -75,28 +75,110 @@ class StripeServices:
self.logger.error(f"Error deleting account: {e}")
raise
async def get_stripe_data(self, clinic_id: int):
try:
user = (
self.db.query(StripeUsers)
.filter(StripeUsers.clinic_id == clinic_id)
.first()
)
if not user:
self.logger.error(f"User not found!")
raise ResourceNotFoundException("User not found!")
return StripeUserReponse.model_validate(user).model_dump()
except Exception as e:
self.logger.error(f"Error retrieving account data: {e}")
raise
finally:
self.db.close()
async def create_stripe_account_link(self, user):
try:
stripe_account = await self.get_stripe_data(user["created_clinics"][0]["id"])
if not stripe_account:
self.logger.error("Stripe account not found!")
raise ResourceNotFoundException("Stripe account not found!")
# Pass the account_id as a string, not as a dictionary
data = await stripe.AccountLink.create_async(
account=stripe_account["account_id"],
refresh_url=self.redirect_url,
return_url=self.redirect_url,
type="account_onboarding",
)
return data.url
except Exception as e:
self.logger.error(f"Error creating stripe account link: {e}")
raise
async def check_account_capabilities(self, user):
try:
stripe_account = await self.get_stripe_data(user["created_clinics"][0]["id"])
if not stripe_account:
self.logger.error("Stripe account not found!")
raise ResourceNotFoundException("Stripe account not found!")
data = await stripe.Account.retrieve_async(stripe_account["account_id"])
return {
"capabilities": data.capabilities,
"charges_enabled": data.charges_enabled,
"requirements": data.requirements.currently_due,
"error": data.requirements.errors,
}
except Exception as e:
self.logger.error(f"Error checking stripe account capabilities: {e}")
raise
finally:
self.db.close()
async def get_invoice(self, user):
try:
if user["userType"] != UserType.CLINIC_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action")
raise UnauthorizedException(
"User is not authorized to perform this action"
)
clinic = self.db.query(Clinics).filter(Clinics.creator_id == user["id"]).first()
clinic = (
self.db.query(Clinics).filter(Clinics.creator_id == user["id"]).first()
)
if not clinic:
raise ResourceNotFoundException("Clinic not found!")
customer = self.db.query(StripeUsers).filter(StripeUsers.user_id == user["id"]).first()
customer = (
self.db.query(StripeUsers)
.filter(StripeUsers.user_id == user["id"])
.first()
)
if not customer:
raise ResourceNotFoundException("Customer not found!")
subscription = self.db.query(Subscriptions).filter(Subscriptions.clinic_id == clinic.id, Subscriptions.customer_id == customer.customer_id, Subscriptions.status == "active").first()
subscription = (
self.db.query(Subscriptions)
.filter(
Subscriptions.clinic_id == clinic.id,
Subscriptions.customer_id == customer.customer_id,
Subscriptions.status == "active",
)
.first()
)
if not subscription:
raise ResourceNotFoundException("Subscription not found!")
stripe_subscription = await stripe.Subscription.retrieve_async(subscription.subscription_id)
stripe_subscription = await stripe.Subscription.retrieve_async(
subscription.subscription_id
)
invoice = await stripe.Invoice.retrieve_async(
stripe_subscription["latest_invoice"]
@ -114,35 +196,53 @@ class StripeServices:
async def create_payment_session(self, user):
try:
if user["userType"] != UserType.CLINIC_ADMIN:
raise UnauthorizedException("User is not authorized to perform this action")
raise UnauthorizedException(
"User is not authorized to perform this action"
)
clinic = user["created_clinics"][0]
if clinic["status"] != ClinicStatus.PAYMENT_DUE:
raise ValidationException("Clinic is not due for payment")
customer = self.db.query(StripeUsers).filter(StripeUsers.user_id == user['id']).first()
customer = (
self.db.query(StripeUsers)
.filter(StripeUsers.user_id == user["id"])
.first()
)
if not customer:
raise ResourceNotFoundException("Customer not found")
clinic_offers = self.db.query(ClinicOffers).filter(ClinicOffers.clinic_email == clinic["email"]).first()
clinic_offers = (
self.db.query(ClinicOffers)
.filter(ClinicOffers.clinic_email == clinic["email"])
.first()
)
signup_pricing= await self.dashboard_service.get_signup_pricing_master()
signup_pricing = await self.dashboard_service.get_signup_pricing_master()
fees_to_be = {
"setup_fees": signup_pricing.setup_fees,
"subscription_fees": signup_pricing.subscription_fees,
"per_call_charges": signup_pricing.per_call_charges,
"total": signup_pricing.setup_fees + signup_pricing.subscription_fees + signup_pricing.per_call_charges
"total": signup_pricing.setup_fees
+ signup_pricing.subscription_fees
+ signup_pricing.per_call_charges,
}
if clinic_offers:
fees_to_be["setup_fees"] = clinic_offers.setup_fees
fees_to_be["per_call_charges"] = clinic_offers.per_call_charges
fees_to_be["total"] = clinic_offers.setup_fees + fees_to_be["subscription_fees"] + clinic_offers.per_call_charges
fees_to_be["total"] = (
clinic_offers.setup_fees
+ fees_to_be["subscription_fees"]
+ clinic_offers.per_call_charges
)
payment_link = await self.create_subscription_checkout(fees_to_be, clinic["id"], customer.account_id, customer.customer_id)
payment_link = await self.create_subscription_checkout(
fees_to_be, clinic["id"], customer.account_id, customer.customer_id
)
return payment_link.url
@ -193,67 +293,79 @@ class StripeServices:
self.logger.error(f"Error creating setup intent: {e}")
raise
async def create_subscription_checkout(self, fees_to_be: dict, clinic_id: int, account_id: str, customer_id: str):
async def create_subscription_checkout(
self, fees_to_be: dict, clinic_id: int, account_id: str, customer_id: str
):
try:
unique_id = str(uuid.uuid4())
unique_clinic_id = f"clinic_{clinic_id}_{unique_id}"
line_items = [{
'price_data': {
'currency': 'aud',
'product_data': {
'name': 'Monthly Subscription',
line_items = [
{
"price_data": {
"currency": "aud",
"product_data": {
"name": "Monthly Subscription",
},
'unit_amount': int(fees_to_be["subscription_fees"] * 100), # Convert to cents
'recurring': {
'interval': 'year',
"unit_amount": int(
fees_to_be["subscription_fees"] * 100
), # Convert to cents
"recurring": {
"interval": "year",
},
},
'quantity': 1,
}]
"quantity": 1,
}
]
line_items.append({
'price_data': {
'currency': 'aud',
'product_data': {
'name': 'Per Call',
line_items.append(
{
"price_data": {
"currency": "aud",
"product_data": {
"name": "Per Call",
},
'unit_amount': int(fees_to_be["per_call_charges"] * 100), # Convert to cents
"unit_amount": int(
fees_to_be["per_call_charges"] * 100
), # Convert to cents
},
'quantity': 1,
})
"quantity": 1,
}
)
line_items.append({
'price_data': {
'currency': 'aud',
'product_data': {
'name': 'Setup Fee',
line_items.append(
{
"price_data": {
"currency": "aud",
"product_data": {
"name": "Setup Fee",
},
'unit_amount': int(fees_to_be["setup_fees"] * 100), # Convert to cents
"unit_amount": int(
fees_to_be["setup_fees"] * 100
), # Convert to cents
},
'quantity': 1,
})
"quantity": 1,
}
)
metadata = {
"clinic_id": clinic_id,
"unique_clinic_id": unique_clinic_id,
"account_id": account_id,
"customer_id": customer_id,
"fees_to_be": json.dumps(fees_to_be)
"fees_to_be": json.dumps(fees_to_be),
}
session_data = {
'customer': customer_id,
"payment_method_types": ["card","au_becs_debit"],
'mode': 'subscription',
'line_items': line_items,
'success_url': f"{self.redirect_url}auth/waiting",
'cancel_url': f"{self.redirect_url}auth/waiting",
'metadata': metadata,
'subscription_data': {
'metadata': metadata
}
"customer": customer_id,
"payment_method_types": ["card", "au_becs_debit"],
"mode": "subscription",
"line_items": line_items,
"success_url": f"{self.redirect_url}auth/waiting",
"cancel_url": f"{self.redirect_url}auth/waiting",
"metadata": metadata,
"subscription_data": {"metadata": metadata},
}
session = await stripe.checkout.Session.create_async(**session_data)
@ -261,18 +373,20 @@ class StripeServices:
payment_log = PaymentLogs(
customer_id=customer_id,
account_id=account_id,
amount=Decimal(str(fees_to_be["total"])), # Keep as Decimal for database storage
amount=Decimal(
str(fees_to_be["total"])
), # Keep as Decimal for database storage
clinic_id=clinic_id,
unique_clinic_id=unique_clinic_id,
payment_status="pending",
metadata_logs=json.dumps(metadata)
metadata_logs=json.dumps(metadata),
)
new_payment_session = PaymentSessions(
session_id=session.id,
customer_id=customer_id,
clinic_id=clinic_id,
status="pending"
status="pending",
)
self.db.add(payment_log)
@ -296,12 +410,16 @@ class StripeServices:
if event["type"] == "customer.subscription.deleted":
self.logger.info("customer subscription ended")
subscription_id = event["data"]["object"]["items"]["data"][0]["subscription"]
subscription_id = event["data"]["object"]["items"]["data"][0][
"subscription"
]
await self._subscription_expired(subscription_id)
if event["type"] == "checkout.session.completed":
unique_clinic_id = event["data"]["object"]["metadata"]["unique_clinic_id"]
unique_clinic_id = event["data"]["object"]["metadata"][
"unique_clinic_id"
]
clinic_id = event["data"]["object"]["metadata"]["clinic_id"]
customer_id = event["data"]["object"]["metadata"]["customer_id"]
account_id = event["data"]["object"]["metadata"]["account_id"]
@ -310,15 +428,24 @@ class StripeServices:
session_id = event["data"]["object"]["id"]
subscription_id = event["data"]["object"]["subscription"]
await self._update_payment_log(unique_clinic_id, clinic_id, customer_id, account_id, total, metadata)
await self._update_payment_log(
unique_clinic_id,
clinic_id,
customer_id,
account_id,
total,
metadata,
)
await self._create_subscription_entry({
await self._create_subscription_entry(
{
"clinic_id": clinic_id,
"customer_id": customer_id,
"account_id": account_id,
"session_id": session_id,
"subscription_id": subscription_id,
})
}
)
# TODO: handle subscription period end
return "OK"
@ -329,9 +456,19 @@ class StripeServices:
finally:
self.db.close()
async def _update_payment_log(self, unique_clinic_id:str, clinic_id:int, customer_id:str, account_id:str, total:float, metadata:any):
async def _update_payment_log(
self,
unique_clinic_id: str,
clinic_id: int,
customer_id: str,
account_id: str,
total: float,
metadata: any,
):
try:
self.db.query(PaymentSessions).filter(PaymentSessions.clinic_id == clinic_id).delete()
self.db.query(PaymentSessions).filter(
PaymentSessions.clinic_id == clinic_id
).delete()
payment_log = PaymentLogs(
customer_id=customer_id,
@ -340,7 +477,7 @@ class StripeServices:
clinic_id=clinic_id,
unique_clinic_id=unique_clinic_id,
payment_status="paid",
metadata_logs=json.dumps(metadata.to_dict())
metadata_logs=json.dumps(metadata.to_dict()),
)
self.db.add(payment_log)
@ -356,12 +493,12 @@ class StripeServices:
self.db.commit()
self.db.close()
async def _create_subscription_entry(self,data:dict):
async def _create_subscription_entry(self, data: dict):
try:
subscription = stripe.Subscription.retrieve(data["subscription_id"])
metadata_dict = json.loads(subscription.metadata)
metadata_dict = subscription.metadata
fees_to_be = json.loads(metadata_dict["fees_to_be"])
new_subscription = Subscriptions(
@ -374,9 +511,13 @@ class StripeServices:
per_call_charge=fees_to_be["per_call_charges"],
subscription_id=data["subscription_id"],
status=subscription.status,
current_period_start=subscription["items"]["data"][0]["current_period_start"],
current_period_end=subscription["items"]["data"][0]["current_period_end"],
metadata_logs=json.dumps(subscription.metadata)
current_period_start=subscription["items"]["data"][0][
"current_period_start"
],
current_period_end=subscription["items"]["data"][0][
"current_period_end"
],
metadata_logs=json.dumps(subscription.metadata),
)
self.db.add(new_subscription)
@ -384,7 +525,7 @@ class StripeServices:
session_id=data["session_id"],
customer_id=data["customer_id"],
clinic_id=data["clinic_id"],
status="paid"
status="paid",
)
self.db.add(payment_session)
return
@ -394,11 +535,15 @@ class StripeServices:
self.db.commit()
self.db.close()
async def _subscription_expired(self,subscription_id):
async def _subscription_expired(self, subscription_id):
try:
subscription = stripe.Subscription.retrieve(subscription_id)
db_subscription = self.db.query(Subscriptions).filter(Subscriptions.subscription_id == subscription_id).first()
db_subscription = (
self.db.query(Subscriptions)
.filter(Subscriptions.subscription_id == subscription_id)
.first()
)
if not db_subscription:
self.logger.error("Subscription not found!")

View File

@ -1,5 +1,6 @@
import asyncio
from loguru import logger
from sqlalchemy import or_
from sqlalchemy.orm import Session
from database import get_db
@ -62,23 +63,6 @@ class UserServices:
self.db.add(new_user)
self.db.flush() # Flush to get the user ID without committing
stripe_customer, stripe_account = await asyncio.gather(
self.stripe_service.create_customer(
new_user.id, user.email, user.username
),
self.stripe_service.create_account(
new_user.id, user.email, user.username, user.mobile
),
)
# Create stripe user
stripe_user = StripeUsers(
user_id=new_user.id,
customer_id=stripe_customer.id,
account_id=stripe_account.id,
)
self.db.add(stripe_user)
# Get clinic data
clinic = user_data.clinic
@ -90,18 +74,35 @@ class UserServices:
if char.isalnum() or char == "-" or char == "_"
)
existing_clinic = (
self.db.query(Clinics).filter(Clinics.domain == domain).first()
self.db.query(Clinics).filter(
or_(Clinics.domain == domain,
Clinics.email == clinic.email,
Clinics.phone == clinic.phone,
Clinics.emergency_phone == clinic.emergency_phone,
Clinics.abn_number == clinic.abn_number,
)
).first()
)
if existing_clinic:
# This will trigger rollback in the exception handler
raise ValidationException("Clinic with same domain already exists")
if existing_clinic.domain == domain:
raise ValidationException("Clinic with same name already exists")
if existing_clinic.email == clinic.email:
raise ValidationException("Clinic with same email already exists")
if existing_clinic.phone == clinic.phone:
raise ValidationException("Clinic with same phone already exists")
if existing_clinic.emergency_phone == clinic.emergency_phone:
raise ValidationException("Clinic with same emergency phone already exists")
if existing_clinic.abn_number == clinic.abn_number:
raise ValidationException("Clinic with same ABN already exists")
# Create clinic instance
new_clinic = Clinics(
name=clinic.name,
address=clinic.address,
phone=clinic.phone,
emergency_phone=clinic.emergency_phone,
email=clinic.email,
integration=clinic.integration,
pms_id=clinic.pms_id,
@ -151,6 +152,24 @@ class UserServices:
clinic.email
)
stripe_customer, stripe_account = await asyncio.gather(
self.stripe_service.create_customer(
new_user.id, user.email, user.username
),
self.stripe_service.create_account(
new_user.id, user.email, user.username, user.mobile
),
)
# Create stripe user
stripe_user = StripeUsers(
user_id=new_user.id,
customer_id=stripe_customer.id,
account_id=stripe_account.id,
)
self.db.add(stripe_user)
signup_pricing = await self.dashboard_service.get_signup_pricing_master()
fees_to_be = {