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>
This commit is contained in:
192
backend/app/api/referral.py
Normal file
192
backend/app/api/referral.py
Normal file
@@ -0,0 +1,192 @@
|
||||
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
|
||||
Reference in New Issue
Block a user