148 lines
5.4 KiB
Python
148 lines
5.4 KiB
Python
from rest_framework import serializers
|
|
from django.contrib.auth import authenticate
|
|
from django.contrib.auth.password_validation import validate_password
|
|
from .models import User, UserProfile, AnalysisSession
|
|
|
|
|
|
class UserRegistrationSerializer(serializers.ModelSerializer):
|
|
"""사용자 회원가입 시리얼라이저"""
|
|
password = serializers.CharField(write_only=True, validators=[validate_password])
|
|
password_confirm = serializers.CharField(write_only=True)
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = ('email', 'username', 'password', 'password_confirm', 'first_name', 'last_name')
|
|
|
|
def validate(self, attrs):
|
|
if attrs['password'] != attrs['password_confirm']:
|
|
raise serializers.ValidationError("비밀번호가 일치하지 않습니다.")
|
|
return attrs
|
|
|
|
def create(self, validated_data):
|
|
validated_data.pop('password_confirm')
|
|
user = User.objects.create_user(**validated_data)
|
|
|
|
# 사용자 프로필 자동 생성
|
|
UserProfile.objects.create(user=user)
|
|
|
|
return user
|
|
|
|
|
|
class UserLoginSerializer(serializers.Serializer):
|
|
"""사용자 로그인 시리얼라이저"""
|
|
email = serializers.EmailField()
|
|
password = serializers.CharField(write_only=True)
|
|
|
|
def validate(self, attrs):
|
|
email = attrs.get('email')
|
|
password = attrs.get('password')
|
|
|
|
if email and password:
|
|
user = authenticate(username=email, password=password)
|
|
if not user:
|
|
raise serializers.ValidationError('올바르지 않은 이메일 또는 비밀번호입니다.')
|
|
if not user.is_active:
|
|
raise serializers.ValidationError('비활성화된 계정입니다.')
|
|
attrs['user'] = user
|
|
else:
|
|
raise serializers.ValidationError('이메일과 비밀번호를 모두 입력해주세요.')
|
|
|
|
return attrs
|
|
|
|
|
|
class UserProfileSerializer(serializers.ModelSerializer):
|
|
"""사용자 프로필 시리얼라이저"""
|
|
has_openai_api_key = serializers.SerializerMethodField()
|
|
openai_api_key = serializers.CharField(write_only=True, required=False, allow_blank=True)
|
|
|
|
class Meta:
|
|
model = UserProfile
|
|
fields = (
|
|
'default_ticker',
|
|
'preferred_research_depth',
|
|
'preferred_shallow_thinker',
|
|
'preferred_deep_thinker',
|
|
'has_openai_api_key',
|
|
'openai_api_key',
|
|
'created_at',
|
|
'updated_at'
|
|
)
|
|
read_only_fields = ('created_at', 'updated_at')
|
|
|
|
def get_has_openai_api_key(self, obj):
|
|
return obj.has_openai_api_key()
|
|
|
|
def update(self, instance, validated_data):
|
|
openai_api_key = validated_data.pop('openai_api_key', None)
|
|
|
|
# OpenAI API 키 업데이트
|
|
if openai_api_key is not None:
|
|
instance.set_openai_api_key(openai_api_key)
|
|
|
|
# 다른 필드 업데이트
|
|
for attr, value in validated_data.items():
|
|
setattr(instance, attr, value)
|
|
|
|
instance.save()
|
|
return instance
|
|
|
|
|
|
class UserSerializer(serializers.ModelSerializer):
|
|
"""사용자 정보 시리얼라이저"""
|
|
profile = UserProfileSerializer(read_only=True)
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = ('id', 'email', 'username', 'first_name', 'last_name', 'profile', 'date_joined')
|
|
read_only_fields = ('id', 'email', 'date_joined')
|
|
|
|
|
|
class AnalysisSessionSerializer(serializers.ModelSerializer):
|
|
"""분석 세션 시리얼라이저"""
|
|
user_email = serializers.CharField(source='user.email', read_only=True)
|
|
duration = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = AnalysisSession
|
|
fields = (
|
|
'id', 'user_email', 'ticker', 'analysis_date',
|
|
'analysts_selected', 'research_depth', 'shallow_thinker', 'deep_thinker',
|
|
'status', 'final_report', 'error_message',
|
|
'created_at', 'started_at', 'completed_at', 'duration'
|
|
)
|
|
read_only_fields = ('id', 'user_email', 'created_at', 'duration')
|
|
|
|
def get_duration(self, obj):
|
|
if obj.started_at and obj.completed_at:
|
|
duration = obj.completed_at - obj.started_at
|
|
return int(duration.total_seconds())
|
|
return None
|
|
|
|
|
|
class CreateAnalysisSessionSerializer(serializers.ModelSerializer):
|
|
"""분석 세션 생성 시리얼라이저"""
|
|
class Meta:
|
|
model = AnalysisSession
|
|
fields = (
|
|
'ticker', 'analysis_date',
|
|
'analysts_selected', 'research_depth',
|
|
'shallow_thinker', 'deep_thinker'
|
|
)
|
|
|
|
def validate_analysts_selected(self, value):
|
|
"""선택된 분석가들 검증"""
|
|
if not isinstance(value, list) or len(value) == 0:
|
|
raise serializers.ValidationError("최소 하나의 분석가를 선택해야 합니다.")
|
|
|
|
valid_analysts = ['market', 'social', 'news', 'fundamentals']
|
|
for analyst in value:
|
|
if analyst not in valid_analysts:
|
|
raise serializers.ValidationError(f"올바르지 않은 분석가: {analyst}")
|
|
|
|
return value
|
|
|
|
def validate_research_depth(self, value):
|
|
"""연구 깊이 검증"""
|
|
if value not in [1, 3, 5]:
|
|
raise serializers.ValidationError("연구 깊이는 1, 3, 5 중 하나여야 합니다.")
|
|
return value |