Adding more shit
This commit is contained in:
@@ -4,11 +4,12 @@ from typing import List
|
||||
from datetime import date, timedelta
|
||||
|
||||
from ...core.database import get_db
|
||||
from ...models.models import Membership, MembershipStatus, User, MembershipTier
|
||||
from ...models.models import Membership, MembershipStatus, User, MembershipTier, Payment, PaymentStatus
|
||||
from ...schemas import (
|
||||
MembershipCreate, MembershipUpdate, MembershipResponse, MessageResponse
|
||||
)
|
||||
from ...api.dependencies import get_current_active_user, get_admin_user
|
||||
from ...services.email_service import email_service
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -112,6 +113,11 @@ async def update_membership(
|
||||
)
|
||||
|
||||
update_data = membership_update.model_dump(exclude_unset=True)
|
||||
was_activated = False
|
||||
|
||||
# Check if status is being changed to ACTIVE
|
||||
if update_data.get("status") == MembershipStatus.ACTIVE and membership.status != MembershipStatus.ACTIVE:
|
||||
was_activated = True
|
||||
|
||||
for field, value in update_data.items():
|
||||
setattr(membership, field, value)
|
||||
@@ -119,6 +125,32 @@ async def update_membership(
|
||||
db.commit()
|
||||
db.refresh(membership)
|
||||
|
||||
# Send activation email if membership was just activated
|
||||
if was_activated:
|
||||
try:
|
||||
# Get the most recent payment for this membership
|
||||
recent_payment = db.query(Payment).filter(
|
||||
Payment.membership_id == membership.id,
|
||||
Payment.status == PaymentStatus.COMPLETED
|
||||
).order_by(Payment.payment_date.desc()).first()
|
||||
|
||||
payment_amount = recent_payment.amount if recent_payment else membership.tier.annual_fee
|
||||
payment_method = recent_payment.payment_method.value if recent_payment else "N/A"
|
||||
|
||||
# Send activation email (non-blocking)
|
||||
await email_service.send_membership_activation_email(
|
||||
to_email=membership.user.email,
|
||||
first_name=membership.user.first_name,
|
||||
membership_tier=membership.tier.name,
|
||||
annual_fee=membership.tier.annual_fee,
|
||||
payment_amount=payment_amount,
|
||||
payment_method=payment_method,
|
||||
renewal_date=membership.end_date.strftime("%d %B %Y")
|
||||
)
|
||||
except Exception as e:
|
||||
# Log error but don't fail the membership update
|
||||
print(f"Failed to send membership activation email: {e}")
|
||||
|
||||
return membership
|
||||
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@ from typing import List
|
||||
from datetime import datetime
|
||||
|
||||
from ...core.database import get_db
|
||||
from ...models.models import Payment, PaymentStatus, User, Membership
|
||||
from ...models.models import Payment, PaymentStatus, User, Membership, MembershipStatus
|
||||
from ...schemas import (
|
||||
PaymentCreate, PaymentUpdate, PaymentResponse, MessageResponse
|
||||
)
|
||||
from ...api.dependencies import get_current_active_user, get_admin_user
|
||||
from ...services.email_service import email_service
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -114,6 +115,31 @@ async def update_payment(
|
||||
db.commit()
|
||||
db.refresh(payment)
|
||||
|
||||
# If payment was just marked as completed and has an associated membership,
|
||||
# activate the membership and send activation email
|
||||
if (update_data.get("status") == PaymentStatus.COMPLETED and
|
||||
payment.membership_id and
|
||||
payment.membership.status == MembershipStatus.PENDING):
|
||||
|
||||
# Activate the membership
|
||||
payment.membership.status = MembershipStatus.ACTIVE
|
||||
db.commit()
|
||||
|
||||
# Send activation email (non-blocking)
|
||||
try:
|
||||
await email_service.send_membership_activation_email(
|
||||
to_email=payment.membership.user.email,
|
||||
first_name=payment.membership.user.first_name,
|
||||
membership_tier=payment.membership.tier.name,
|
||||
annual_fee=payment.membership.tier.annual_fee,
|
||||
payment_amount=payment.amount,
|
||||
payment_method=payment.payment_method.value,
|
||||
renewal_date=payment.membership.end_date.strftime("%d %B %Y")
|
||||
)
|
||||
except Exception as e:
|
||||
# Log error but don't fail the payment update
|
||||
print(f"Failed to send membership activation email: {e}")
|
||||
|
||||
return payment
|
||||
|
||||
|
||||
@@ -152,6 +178,7 @@ async def record_manual_payment(
|
||||
)
|
||||
|
||||
# Verify membership if provided
|
||||
membership = None
|
||||
if payment_data.membership_id:
|
||||
membership = db.query(Membership).filter(
|
||||
Membership.id == payment_data.membership_id,
|
||||
@@ -178,4 +205,24 @@ async def record_manual_payment(
|
||||
db.commit()
|
||||
db.refresh(payment)
|
||||
|
||||
# If payment has an associated membership that's pending, activate it and send email
|
||||
if membership and membership.status == MembershipStatus.PENDING:
|
||||
membership.status = MembershipStatus.ACTIVE
|
||||
db.commit()
|
||||
|
||||
# Send activation email (non-blocking)
|
||||
try:
|
||||
await email_service.send_membership_activation_email(
|
||||
to_email=membership.user.email,
|
||||
first_name=membership.user.first_name,
|
||||
membership_tier=membership.tier.name,
|
||||
annual_fee=membership.tier.annual_fee,
|
||||
payment_amount=payment.amount,
|
||||
payment_method=payment.payment_method.value,
|
||||
renewal_date=membership.end_date.strftime("%d %B %Y")
|
||||
)
|
||||
except Exception as e:
|
||||
# Log error but don't fail the payment creation
|
||||
print(f"Failed to send membership activation email: {e}")
|
||||
|
||||
return payment
|
||||
|
||||
@@ -7,7 +7,7 @@ from ...models.models import MembershipTier
|
||||
from ...schemas import (
|
||||
MembershipTierCreate, MembershipTierUpdate, MembershipTierResponse, MessageResponse
|
||||
)
|
||||
from ...api.dependencies import get_current_active_user, get_admin_user
|
||||
from ...api.dependencies import get_current_active_user, get_admin_user, get_super_admin_user
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -47,10 +47,10 @@ async def get_membership_tier(
|
||||
@router.post("/", response_model=MembershipTierResponse, status_code=status.HTTP_201_CREATED)
|
||||
async def create_membership_tier(
|
||||
tier_data: MembershipTierCreate,
|
||||
current_user = Depends(get_admin_user),
|
||||
current_user = Depends(get_super_admin_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Create a new membership tier (admin only)"""
|
||||
"""Create a new membership tier (super admin only)"""
|
||||
# Check if tier with same name exists
|
||||
existing_tier = db.query(MembershipTier).filter(
|
||||
MembershipTier.name == tier_data.name
|
||||
@@ -74,10 +74,10 @@ async def create_membership_tier(
|
||||
async def update_membership_tier(
|
||||
tier_id: int,
|
||||
tier_update: MembershipTierUpdate,
|
||||
current_user = Depends(get_admin_user),
|
||||
current_user = Depends(get_super_admin_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Update membership tier (admin only)"""
|
||||
"""Update membership tier (super admin only)"""
|
||||
tier = db.query(MembershipTier).filter(MembershipTier.id == tier_id).first()
|
||||
if not tier:
|
||||
raise HTTPException(
|
||||
@@ -99,10 +99,10 @@ async def update_membership_tier(
|
||||
@router.delete("/{tier_id}", response_model=MessageResponse)
|
||||
async def delete_membership_tier(
|
||||
tier_id: int,
|
||||
current_user = Depends(get_admin_user),
|
||||
current_user = Depends(get_super_admin_user),
|
||||
db: Session = Depends(get_db)
|
||||
):
|
||||
"""Delete membership tier (admin only)"""
|
||||
"""Delete membership tier (super admin only)"""
|
||||
tier = db.query(MembershipTier).filter(MembershipTier.id == tier_id).first()
|
||||
if not tier:
|
||||
raise HTTPException(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import httpx
|
||||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
from ..core.config import settings
|
||||
|
||||
|
||||
@@ -141,6 +142,83 @@ class EmailService:
|
||||
|
||||
return await self.send_email(to_email, subject, html_body, text_body)
|
||||
|
||||
async def send_membership_activation_email(
|
||||
self,
|
||||
to_email: str,
|
||||
first_name: str,
|
||||
membership_tier: str,
|
||||
annual_fee: float,
|
||||
payment_amount: float,
|
||||
payment_method: str,
|
||||
renewal_date: str
|
||||
) -> dict:
|
||||
"""Send membership activation email with payment details and renewal date"""
|
||||
subject = f"Your {settings.APP_NAME} Membership is Now Active!"
|
||||
|
||||
html_body = f"""
|
||||
<html>
|
||||
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
|
||||
<h2 style="color: #28a745;">Welcome to {settings.APP_NAME}!</h2>
|
||||
<p>Hello {first_name},</p>
|
||||
<p>Great news! Your membership has been successfully activated. You now have full access to all the benefits of your membership tier.</p>
|
||||
|
||||
<div style="background-color: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0; border-left: 4px solid #28a745;">
|
||||
<h3 style="margin-top: 0; color: #28a745;">Membership Details</h3>
|
||||
<p style="margin: 8px 0;"><strong>Membership Tier:</strong> {membership_tier}</p>
|
||||
<p style="margin: 8px 0;"><strong>Annual Fee:</strong> £{annual_fee:.2f}</p>
|
||||
<p style="margin: 8px 0;"><strong>Next Renewal Date:</strong> {renewal_date}</p>
|
||||
</div>
|
||||
|
||||
<div style="background-color: #e9ecef; padding: 20px; border-radius: 8px; margin: 20px 0;">
|
||||
<h3 style="margin-top: 0; color: #495057;">Payment Information</h3>
|
||||
<p style="margin: 8px 0;"><strong>Amount Paid:</strong> £{payment_amount:.2f}</p>
|
||||
<p style="margin: 8px 0;"><strong>Payment Method:</strong> {payment_method}</p>
|
||||
<p style="margin: 8px 0;"><strong>Payment Date:</strong> {datetime.now().strftime('%d %B %Y')}</p>
|
||||
</div>
|
||||
|
||||
<p>Your membership will automatically renew on <strong>{renewal_date}</strong> unless you choose to cancel it. You can manage your membership settings in your account dashboard.</p>
|
||||
|
||||
<p>If you have any questions about your membership or need assistance, please don't hesitate to contact us.</p>
|
||||
|
||||
<p>Welcome to the {settings.APP_NAME} community!</p>
|
||||
|
||||
<p>Best regards,<br>
|
||||
<strong>{settings.APP_NAME} Team</strong></p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
text_body = f"""
|
||||
Welcome to {settings.APP_NAME}!
|
||||
|
||||
Hello {first_name},
|
||||
|
||||
Great news! Your membership has been successfully activated. You now have full access to all the benefits of your membership tier.
|
||||
|
||||
MEMBERSHIP DETAILS
|
||||
------------------
|
||||
Membership Tier: {membership_tier}
|
||||
Annual Fee: £{annual_fee:.2f}
|
||||
Next Renewal Date: {renewal_date}
|
||||
|
||||
PAYMENT INFORMATION
|
||||
-------------------
|
||||
Amount Paid: £{payment_amount:.2f}
|
||||
Payment Method: {payment_method}
|
||||
Payment Date: {datetime.now().strftime('%d %B %Y')}
|
||||
|
||||
Your membership will automatically renew on {renewal_date} unless you choose to cancel it. You can manage your membership settings in your account dashboard.
|
||||
|
||||
If you have any questions about your membership or need assistance, please don't hesitate to contact us.
|
||||
|
||||
Welcome to the {settings.APP_NAME} community!
|
||||
|
||||
Best regards,
|
||||
{settings.APP_NAME} Team
|
||||
"""
|
||||
|
||||
return await self.send_email(to_email, subject, html_body, text_body)
|
||||
|
||||
async def send_membership_renewal_reminder(
|
||||
self,
|
||||
to_email: str,
|
||||
|
||||
Reference in New Issue
Block a user