Files
AutonetSellCar/backend/app/api/referral.py
AutonetSellCar Deploy 1f0dcb1ddb Initial commit: AutonetSellCar platform with deployment system
- Frontend: Next.js 14 with TypeScript
- Backend: FastAPI with SQLAlchemy
- Agent: Carmodoo sync agent
- Deployment: Docker Compose based staging/production setup
- Scripts: Automated deployment with rollback support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-30 13:24:39 +09:00

193 lines
6.6 KiB
Python

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import func as sql_func
from datetime import datetime
from typing import List
from ..database import get_db
from ..models import User, ReferralReward, SystemSettings
from ..schemas import (
ReferralRewardResponse, ReferralStats,
ReferralSettingsResponse, ReferralSettingsUpdate,
)
from .auth import get_current_user
from .notification import notify_referral_reward
router = APIRouter(prefix="/referral", tags=["referral"])
def get_referral_settings(db: Session) -> SystemSettings:
"""Get or create system settings"""
settings = db.query(SystemSettings).first()
if not settings:
settings = SystemSettings()
db.add(settings)
db.commit()
db.refresh(settings)
return settings
def create_referral_reward(
referrer_id: int,
referred_user_id: int,
payment_amount: float,
db: Session
):
"""Create a referral reward when a referred user makes a payment"""
settings = get_referral_settings(db)
# Check if referral rewards are enabled
if not settings.referral_reward_enabled:
return None
# Check if this is a one_time reward and already exists
if settings.referral_reward_type == "one_time":
existing = db.query(ReferralReward).filter(
ReferralReward.referrer_id == referrer_id,
ReferralReward.referred_user_id == referred_user_id
).first()
if existing:
return None # Already gave reward for this referral
# Calculate reward amount
reward_amount = payment_amount * (settings.referral_reward_percent / 100)
# Create reward record
reward = ReferralReward(
referrer_id=referrer_id,
referred_user_id=referred_user_id,
payment_amount=payment_amount,
reward_amount=reward_amount,
status="credited", # Auto-credit for simplicity
credited_at=datetime.utcnow()
)
db.add(reward)
db.commit()
db.refresh(reward)
# Send notification to referrer
referred_user = db.query(User).filter(User.id == referred_user_id).first()
referred_name = referred_user.name or referred_user.email if referred_user else "회원"
notify_referral_reward(db, referrer_id, reward_amount, referred_name)
return reward
@router.get("/my-link")
def get_my_referral_link(current_user: User = Depends(get_current_user)):
"""Get current user's referral link/code"""
return {
"referral_code": current_user.referral_code,
"referral_link": f"/register?ref={current_user.referral_code}"
}
@router.get("/my-rewards", response_model=List[ReferralRewardResponse])
def get_my_rewards(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get current user's referral rewards"""
rewards = db.query(ReferralReward).filter(
ReferralReward.referrer_id == current_user.id
).order_by(ReferralReward.created_at.desc()).all()
return rewards
@router.get("/stats", response_model=ReferralStats)
def get_referral_stats(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get referral statistics for current user"""
# Get all rewards where user is the referrer
rewards = db.query(ReferralReward).filter(
ReferralReward.referrer_id == current_user.id
).all()
# Count unique referred users
referred_users = db.query(sql_func.count(sql_func.distinct(ReferralReward.referred_user_id))).filter(
ReferralReward.referrer_id == current_user.id
).scalar() or 0
total_rewards_earned = sum(r.reward_amount for r in rewards)
total_rewards_credited = sum(r.reward_amount for r in rewards if r.status == "credited")
total_rewards_pending = sum(r.reward_amount for r in rewards if r.status == "pending")
total_withdrawn = sum(r.reward_amount for r in rewards if r.status == "withdrawn")
return ReferralStats(
total_referrals=referred_users,
total_rewards_earned=total_rewards_earned,
total_rewards_credited=total_rewards_credited,
total_rewards_pending=total_rewards_pending,
available_for_withdrawal=total_rewards_credited - total_withdrawn
)
@router.get("/settings", response_model=ReferralSettingsResponse)
def get_settings(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get referral settings (public endpoint)"""
settings = get_referral_settings(db)
return ReferralSettingsResponse(
referral_reward_enabled=settings.referral_reward_enabled,
referral_reward_percent=settings.referral_reward_percent,
referral_reward_type=settings.referral_reward_type
)
# Admin endpoints
@router.put("/admin/settings", response_model=ReferralSettingsResponse)
def update_settings(
update_data: ReferralSettingsUpdate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""[Admin] Update referral settings"""
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
settings = get_referral_settings(db)
if update_data.referral_reward_enabled is not None:
settings.referral_reward_enabled = update_data.referral_reward_enabled
if update_data.referral_reward_percent is not None:
if update_data.referral_reward_percent < 0 or update_data.referral_reward_percent > 100:
raise HTTPException(status_code=400, detail="Reward percent must be between 0 and 100")
settings.referral_reward_percent = update_data.referral_reward_percent
if update_data.referral_reward_type is not None:
if update_data.referral_reward_type not in ["one_time", "recurring"]:
raise HTTPException(status_code=400, detail="Reward type must be 'one_time' or 'recurring'")
settings.referral_reward_type = update_data.referral_reward_type
db.commit()
db.refresh(settings)
return ReferralSettingsResponse(
referral_reward_enabled=settings.referral_reward_enabled,
referral_reward_percent=settings.referral_reward_percent,
referral_reward_type=settings.referral_reward_type
)
@router.get("/admin/all-rewards", response_model=List[ReferralRewardResponse])
def admin_get_all_rewards(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""[Admin] Get all referral rewards"""
if not current_user.is_admin:
raise HTTPException(status_code=403, detail="Admin access required")
rewards = db.query(ReferralReward).order_by(
ReferralReward.created_at.desc()
).limit(100).all()
return rewards