feat: subscription ended webhook
refactor: subscription table
This commit is contained in:
parent
f545a5b75b
commit
7f2f730426
|
|
@ -0,0 +1,42 @@
|
|||
"""updated_subscription_table
|
||||
|
||||
Revision ID: 8d19e726b997
|
||||
Revises: 5ed8ac3d258c
|
||||
Create Date: 2025-06-03 19:07:17.107577
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '8d19e726b997'
|
||||
down_revision: Union[str, None] = '5ed8ac3d258c'
|
||||
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('subscriptions', sa.Column('total', sa.String(), nullable=True))
|
||||
op.add_column('subscriptions', sa.Column('setup_fee', sa.String(), nullable=True))
|
||||
op.add_column('subscriptions', sa.Column('subscription_fee', sa.String(), nullable=True))
|
||||
op.add_column('subscriptions', sa.Column('per_call_charge', sa.String(), nullable=True))
|
||||
op.drop_index('ix_subscriptions_session_id', table_name='subscriptions')
|
||||
op.drop_column('subscriptions', 'session_id')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column('subscriptions', sa.Column('session_id', sa.VARCHAR(length=255), autoincrement=False, nullable=True))
|
||||
op.create_index('ix_subscriptions_session_id', 'subscriptions', ['session_id'], unique=False)
|
||||
op.drop_column('subscriptions', 'per_call_charge')
|
||||
op.drop_column('subscriptions', 'subscription_fee')
|
||||
op.drop_column('subscriptions', 'setup_fee')
|
||||
op.drop_column('subscriptions', 'total')
|
||||
# ### end Alembic commands ###
|
||||
|
|
@ -5,9 +5,13 @@ from .CustomBase import CustomBase
|
|||
class Subscriptions(Base, CustomBase):
|
||||
__tablename__ = "subscriptions"
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String(255), index=True)
|
||||
# session_id = Column(String(255), index=True)
|
||||
customer_id = Column(String,index=True)
|
||||
account_id = Column(String,index=True)
|
||||
account_id = Column(String,index=True)
|
||||
total = Column(String)
|
||||
setup_fee = Column(String)
|
||||
subscription_fee = Column(String)
|
||||
per_call_charge = Column(String)
|
||||
subscription_id = Column(String,index=True)
|
||||
clinic_id = Column(Integer, index=True)
|
||||
status = Column(String)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class StripeServices:
|
|||
|
||||
async def create_customer(self, user_id: int, email: str, name: str):
|
||||
try:
|
||||
customer = stripe.Customer.create(
|
||||
customer = await stripe.Customer.create_async(
|
||||
email=email, name=name, metadata={"user_id": user_id}
|
||||
)
|
||||
return customer
|
||||
|
|
@ -45,14 +45,14 @@ class StripeServices:
|
|||
|
||||
async def delete_customer(self, customer_id: str):
|
||||
try:
|
||||
stripe.Customer.delete(customer_id)
|
||||
await stripe.Customer.delete_async(customer_id)
|
||||
except stripe.error.StripeError as e:
|
||||
self.logger.error(f"Error deleting customer: {e}")
|
||||
raise
|
||||
|
||||
async def create_account(self, user_id: int, email: str, name: str, phone: str):
|
||||
try:
|
||||
account = stripe.Account.create(
|
||||
account = await stripe.Account.create_async(
|
||||
type="express",
|
||||
country="AU",
|
||||
capabilities={
|
||||
|
|
@ -70,7 +70,7 @@ class StripeServices:
|
|||
|
||||
async def delete_account(self, account_id: str):
|
||||
try:
|
||||
stripe.Account.delete(account_id)
|
||||
await stripe.Account.delete_async(account_id)
|
||||
except stripe.error.StripeError as e:
|
||||
self.logger.error(f"Error deleting account: {e}")
|
||||
raise
|
||||
|
|
@ -96,9 +96,9 @@ class StripeServices:
|
|||
if not subscription:
|
||||
raise ResourceNotFoundException("Subscription not found!")
|
||||
|
||||
stripe_subscription = stripe.Subscription.retrieve(subscription.subscription_id)
|
||||
stripe_subscription = await stripe.Subscription.retrieve_async(subscription.subscription_id)
|
||||
|
||||
invoice = stripe.Invoice.retrieve(
|
||||
invoice = await stripe.Invoice.retrieve_async(
|
||||
stripe_subscription["latest_invoice"]
|
||||
)
|
||||
return invoice.hosted_invoice_url
|
||||
|
|
@ -154,7 +154,7 @@ class StripeServices:
|
|||
|
||||
async def create_checkout_session(self, user_id: int):
|
||||
try:
|
||||
checkout_session = stripe.checkout.Session.create(
|
||||
checkout_session = await stripe.checkout.Session.create_async(
|
||||
payment_method_types=["card"],
|
||||
line_items=[
|
||||
{
|
||||
|
|
@ -182,7 +182,7 @@ class StripeServices:
|
|||
|
||||
async def create_setup_fees(self, customer_id: str, amount: int):
|
||||
try:
|
||||
setup_intent = stripe.InvoiceItem.create(
|
||||
setup_intent = await stripe.InvoiceItem.create_async(
|
||||
customer=customer_id,
|
||||
amount=amount,
|
||||
currency="aud",
|
||||
|
|
@ -256,7 +256,7 @@ class StripeServices:
|
|||
}
|
||||
}
|
||||
|
||||
session = stripe.checkout.Session.create(**session_data)
|
||||
session = await stripe.checkout.Session.create_async(**session_data)
|
||||
|
||||
payment_log = PaymentLogs(
|
||||
customer_id=customer_id,
|
||||
|
|
@ -294,8 +294,11 @@ class StripeServices:
|
|||
)
|
||||
self.logger.info(f"Stripe webhook event type: {event['type']}")
|
||||
|
||||
if event["type"] == "checkout.session.expired":
|
||||
pass
|
||||
if event["type"] == "customer.subscription.deleted":
|
||||
self.logger.info("customer subscription ended")
|
||||
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"]
|
||||
|
|
@ -307,9 +310,9 @@ class StripeServices:
|
|||
session_id = event["data"]["object"]["id"]
|
||||
subscription_id = event["data"]["object"]["subscription"]
|
||||
|
||||
self._update_payment_log(unique_clinic_id, clinic_id, customer_id, account_id, total, metadata, session_id)
|
||||
await self._update_payment_log(unique_clinic_id, clinic_id, customer_id, account_id, total, metadata)
|
||||
|
||||
self._create_subscription_entry({
|
||||
await self._create_subscription_entry({
|
||||
"clinic_id": clinic_id,
|
||||
"customer_id": customer_id,
|
||||
"account_id": account_id,
|
||||
|
|
@ -326,7 +329,7 @@ class StripeServices:
|
|||
finally:
|
||||
self.db.close()
|
||||
|
||||
def _update_payment_log(self, unique_clinic_id:str, clinic_id:int, customer_id:str, account_id:str, total:float, metadata:any, session_id:str):
|
||||
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()
|
||||
|
||||
|
|
@ -353,16 +356,22 @@ class StripeServices:
|
|||
self.db.commit()
|
||||
self.db.close()
|
||||
|
||||
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)
|
||||
fees_to_be = json.loads(metadata_dict["fees_to_be"])
|
||||
|
||||
new_subscription = Subscriptions(
|
||||
clinic_id=data["clinic_id"],
|
||||
customer_id=data["customer_id"],
|
||||
account_id=data["account_id"],
|
||||
session_id=data["session_id"],
|
||||
total=fees_to_be["total"],
|
||||
setup_fee=fees_to_be["setup_fees"],
|
||||
subscription_fee=fees_to_be["subscription_fees"],
|
||||
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"],
|
||||
|
|
@ -384,4 +393,26 @@ class StripeServices:
|
|||
finally:
|
||||
self.db.commit()
|
||||
self.db.close()
|
||||
|
||||
|
||||
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()
|
||||
|
||||
if not db_subscription:
|
||||
self.logger.error("Subscription not found!")
|
||||
raise Exception("Subscription not found!")
|
||||
|
||||
db_subscription.status = subscription.status
|
||||
self.db.add(db_subscription)
|
||||
|
||||
# TODO: update clinic status
|
||||
# TODO: send email to user
|
||||
|
||||
return
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error ending subscription: {e}")
|
||||
finally:
|
||||
self.db.commit()
|
||||
self.db.close()
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import asyncio
|
||||
from loguru import logger
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
|
|
@ -61,14 +62,13 @@ class UserServices:
|
|||
self.db.add(new_user)
|
||||
self.db.flush() # Flush to get the user ID without committing
|
||||
|
||||
# Create stripe customer
|
||||
stripe_customer = await self.stripe_service.create_customer(
|
||||
new_user.id, user.email, user.username
|
||||
)
|
||||
|
||||
# Create stripe account
|
||||
stripe_account = await self.stripe_service.create_account(
|
||||
new_user.id, user.email, user.username, user.mobile
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue