from sqlalchemy import Column, Integer, String, DateTime, Boolean, ForeignKey, Enum as SQLEnum from sqlalchemy.orm import relationship,Mapped from datetime import datetime from database import Base class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) internal_id = Column(String, unique=True, index=True) email = Column(String, index=True) musics = relationship("Music", back_populates="user", cascade="delete, delete-orphan") music_analysis = relationship("Music_Analysis", back_populates="user", cascade="all, delete-orphan") ai_detection_musics = relationship("AI_Detection_Music", back_populates="user") posts = relationship("Post", back_populates="user", cascade="delete, delete-orphan") asks = relationship("Ask", back_populates="user", cascade="delete, delete-orphan") albums = relationship("Album", back_populates="user") user_info = relationship("UserInfo", back_populates="user", uselist=False, cascade="delete, delete-orphan") access_logs = relationship( "UserAccessLog", back_populates="user", cascade="delete, delete-orphan") comments = relationship('Comment', back_populates='user') likes = relationship("Like", back_populates="user") notifications = relationship( "Notification", back_populates="user", cascade="all, delete-orphan") survey_responses = relationship("SurveyResponse", back_populates="user", cascade="all, delete-orphan") auth_provider = Column( SQLEnum("Google", "Naver", "Kakao", "None", name="oauth_provier_enum")) auth_provider_id = Column(String, nullable=True) # OAuth 공급자의 고유 식별자 created_at = Column(DateTime, default=datetime.utcnow) subscriptions = relationship( "Subscription", back_populates="user", cascade="all, delete-orphan") payments = relationship( "Payment", back_populates="user", cascade="all, delete-orphan") billing_info: Mapped["UserBillingInfo"] = relationship( "UserBillingInfo", back_populates="user", uselist=False, cascade="all, delete-orphan") additional_info_submitted = Column(Boolean, default=False) deleted = Column(Boolean, default=False, nullable=False) reports = relationship("Report", back_populates="user") last_monitoring_email_sent = Column(DateTime, nullable=True) last_notice_seen = Column(DateTime, nullable=True) refresh_token = Column(String, index=True) # 리프레시 토큰 저장 token_expires = Column(DateTime, default=datetime.utcnow) def __repr__(self): return f"" @property def user_name(self): return self.user_info.name if self.user_info else None @property def nickname(self): return self.user_info.nickname if self.user_info else None class UserBillingInfo(Base): __tablename__ = "user_billing_info" id = Column(Integer, ForeignKey("users.id"), primary_key=True) user = relationship("User", back_populates="billing_info") subscription = Column(String, default='free') # Deprecated. 엥..간해서는 사용 안해야함 """ # "basic-usd-monthly" "standard-usd-monthly" "premium-usd-monthly" "basic-usd-yearly" "standard-usd-yearly" "premium-usd-yearly" "basic-krw-monthly" "standard-krw-monthly" "premium-krw-monthly" "basic-krw-yearly" "standard-krw-yearly" "premium-krw-yearly" """ remain_credit = Column(Integer, default=600) # 해당 요소는 사용하지 않아도 될 꺼 같음. # monitoring from subscription monitoring_number = Column(Integer, default=0) additional_monitoring_number = Column( Integer, default=1) # monitoring from addtional buy first_month_used = Column(Boolean, default=False) # deprecated maybe. deleted_credit = Column(Integer, default=0) # 복구용? def to_dict(self): return { 'remain_credit': self.remain_credit, 'monitoring_number': self.monitoring_number, 'additional_monitoring_number': self.additional_monitoring_number, 'first_month_used': self.first_month_used } class UserInfo(Base): __tablename__ = "user_info" id: Column[int] = Column(Integer, ForeignKey("users.id"), primary_key=True) user = relationship("User", back_populates="user_info") name:Column[str] = Column(String) nickname: Column[str] = Column(String, unique=True) phone = Column(String) birthdate = Column(String) termsofservice = Column(Boolean, default=False) marketingconsent = Column(Boolean, default=False) organization = Column(String, nullable=True) deleted = Column(Boolean, default=False) profile_image_link = Column( String, default="https://storage.cloud.google.com/mippia-userfile-bucket/userfiles/blank-profile-picture.svg") song_available = Column(Integer, default=10) def __repr__(self): return f"" class UserAccessLog(Base): __tablename__ = "user_access_logs" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey('users.id')) access_time = Column(DateTime, default=datetime.utcnow) ip_address = Column(String) user_agent = Column(String) user = relationship("User", back_populates="access_logs") def __repr__(self): return f"" @property def user_name(self): return self.user.user_info.name if self.user and self.user.user_info else None class SurveyResponse(Base): __tablename__ = "survey_responses" id = Column(Integer, primary_key=True, index=True) question_id = Column(String, ForeignKey("survey_questions.question_id"), index=True) answer = Column(String, nullable=False) user_id = Column(Integer, ForeignKey("users.id")) created_at = Column(DateTime, default=datetime.utcnow) user = relationship("User", back_populates="survey_responses") question = relationship( "SurveyQuestion", primaryjoin="foreign(SurveyResponse.question_id) == SurveyQuestion.question_id", viewonly=True, sync_backref=False ) @property def question_text(self): return self.question.question_kr if self.question else None class SurveyQuestion(Base): __tablename__ = "survey_questions" id = Column(Integer, primary_key=True, index=True) question_id = Column(String, unique=True, index=True) question_kr = Column(String, nullable=False) question_en = Column(String, nullable=False)