Add SNS Marketing Campaign feature

- Add cash_cc_balance to User model (withdrawable CC)
- Create SnsShareSubmission model for SNS share verification
- Add marketing campaign settings to SystemSettings
- Add reward_type to ReferralReward model
- Create /api/sns-share endpoints for submission and verification
- Add referral signup reward logic (10CC on signup)
- Create /sns-share user page for SNS sharing
- Create /admin/sns-shares management page
- Add marketing settings UI to admin settings page
- Add SNS Shares menu to admin sidebar

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
AutonetSellCar Deploy
2026-01-03 18:21:17 +09:00
parent 718c5b0474
commit 7c943d8553
17 changed files with 1414 additions and 6 deletions

View File

@@ -47,6 +47,10 @@ from .notification import (
NotificationCreate, NotificationResponse,
NotificationListResponse, NotificationMarkRead,
)
from .sns_share import (
SnsShareSubmit, SnsShareResponse, SnsShareListResponse,
SnsShareVerify, SnsShareStats,
)
__all__ = [
"CarMakerCreate", "CarMakerResponse",
@@ -78,4 +82,6 @@ __all__ = [
"ReferralSettingsResponse", "ReferralSettingsUpdate",
"NotificationCreate", "NotificationResponse",
"NotificationListResponse", "NotificationMarkRead",
"SnsShareSubmit", "SnsShareResponse", "SnsShareListResponse",
"SnsShareVerify", "SnsShareStats",
]

View File

@@ -22,6 +22,16 @@ class SystemSettingsUpdate(BaseModel):
referral_reward_percent: Optional[float] = None
referral_reward_type: Optional[str] = None
# 마케팅 캠페인 설정
marketing_enabled: Optional[bool] = None
marketing_start_date: Optional[datetime] = None
marketing_end_date: Optional[datetime] = None
sns_share_reward_cc: Optional[float] = None
referral_signup_reward_cc: Optional[float] = None
event_cc_validity_months: Optional[int] = None
withdrawal_enabled: Optional[bool] = None
min_withdrawal_usd: Optional[float] = None
class SystemSettingsResponse(BaseModel):
"""시스템 설정 응답 스키마"""
@@ -42,6 +52,17 @@ class SystemSettingsResponse(BaseModel):
referral_reward_enabled: bool = True
referral_reward_percent: float = 10.0
referral_reward_type: str = "one_time"
# 마케팅 캠페인 설정
marketing_enabled: bool = False
marketing_start_date: Optional[datetime] = None
marketing_end_date: Optional[datetime] = None
sns_share_reward_cc: float = 3.0
referral_signup_reward_cc: float = 10.0
event_cc_validity_months: int = 6
withdrawal_enabled: bool = True
min_withdrawal_usd: float = 10.0
created_at: Optional[datetime] = None
updated_at: Optional[datetime] = None

View File

@@ -0,0 +1,57 @@
from pydantic import BaseModel, HttpUrl
from typing import Optional, List
from datetime import datetime
class SnsShareSubmit(BaseModel):
"""SNS 공유 제출 요청"""
car_id: int
platform: str # twitter, instagram, facebook
sns_url: str # 공유 게시물 URL
class SnsShareResponse(BaseModel):
"""SNS 공유 제출 응답"""
id: int
user_id: int
car_id: int
platform: str
sns_url: str
status: str
rejected_reason: Optional[str] = None
reward_cc: float
rewarded_at: Optional[datetime] = None
submitted_at: datetime
verified_at: Optional[datetime] = None
verified_by: Optional[int] = None
# Car info for display
car_name: Optional[str] = None
car_image: Optional[str] = None
class Config:
from_attributes = True
class SnsShareListResponse(BaseModel):
"""SNS 공유 목록 응답"""
submissions: List[SnsShareResponse]
total: int
pending_count: int
approved_count: int
rejected_count: int
class SnsShareVerify(BaseModel):
"""관리자 검증 요청"""
approved: bool
rejected_reason: Optional[str] = None
class SnsShareStats(BaseModel):
"""SNS 공유 통계"""
total_submissions: int
pending_submissions: int
approved_submissions: int
rejected_submissions: int
total_rewarded_cc: float