from sqlalchemy import ( Column, Integer, String, DateTime, Boolean, Enum as SQLEnum, Float, Text, ForeignKey, Date ) from sqlalchemy.orm import relationship from datetime import datetime import enum from ..core.database import Base class UserRole(str, enum.Enum): MEMBER = "member" ADMIN = "admin" SUPER_ADMIN = "super_admin" class MembershipStatus(str, enum.Enum): ACTIVE = "active" EXPIRED = "expired" PENDING = "pending" CANCELLED = "cancelled" class PaymentStatus(str, enum.Enum): PENDING = "pending" COMPLETED = "completed" FAILED = "failed" REFUNDED = "refunded" class PaymentMethod(str, enum.Enum): SQUARE = "square" CASH = "cash" CHECK = "check" DUMMY = "dummy" class EventStatus(str, enum.Enum): DRAFT = "draft" PUBLISHED = "published" CANCELLED = "cancelled" COMPLETED = "completed" class RSVPStatus(str, enum.Enum): PENDING = "pending" ATTENDING = "attending" NOT_ATTENDING = "not_attending" MAYBE = "maybe" class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) email = Column(String(255), unique=True, index=True, nullable=False) hashed_password = Column(String(255), nullable=False) first_name = Column(String(100), nullable=False) last_name = Column(String(100), nullable=False) phone = Column(String(20), nullable=True) address = Column(Text, nullable=True) role = Column(SQLEnum(UserRole), default=UserRole.MEMBER, nullable=False) is_active = Column(Boolean, default=True, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) last_login = Column(DateTime, nullable=True) # Relationships memberships = relationship("Membership", back_populates="user", cascade="all, delete-orphan") payments = relationship("Payment", back_populates="user", cascade="all, delete-orphan") event_rsvps = relationship("EventRSVP", back_populates="user", cascade="all, delete-orphan") volunteer_assignments = relationship("VolunteerAssignment", back_populates="user", cascade="all, delete-orphan") certificates = relationship("Certificate", back_populates="user", cascade="all, delete-orphan") class MembershipTier(Base): __tablename__ = "membership_tiers" id = Column(Integer, primary_key=True, index=True) name = Column(String(100), unique=True, nullable=False) description = Column(Text, nullable=True) annual_fee = Column(Float, nullable=False) benefits = Column(Text, nullable=True) is_active = Column(Boolean, default=True, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships memberships = relationship("Membership", back_populates="tier") class Membership(Base): __tablename__ = "memberships" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) tier_id = Column(Integer, ForeignKey("membership_tiers.id"), nullable=False) status = Column(SQLEnum(MembershipStatus), default=MembershipStatus.PENDING, nullable=False) start_date = Column(Date, nullable=False) end_date = Column(Date, nullable=False) auto_renew = Column(Boolean, default=False, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships user = relationship("User", back_populates="memberships") tier = relationship("MembershipTier", back_populates="memberships") payments = relationship("Payment", back_populates="membership") class Payment(Base): __tablename__ = "payments" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) membership_id = Column(Integer, ForeignKey("memberships.id"), nullable=True) amount = Column(Float, nullable=False) payment_method = Column(SQLEnum(PaymentMethod), nullable=False) status = Column(SQLEnum(PaymentStatus), default=PaymentStatus.PENDING, nullable=False) transaction_id = Column(String(255), nullable=True) payment_date = Column(DateTime, nullable=True) notes = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships user = relationship("User", back_populates="payments") membership = relationship("Membership", back_populates="payments") class Event(Base): __tablename__ = "events" id = Column(Integer, primary_key=True, index=True) title = Column(String(255), nullable=False) description = Column(Text, nullable=True) event_date = Column(DateTime, nullable=False) location = Column(String(255), nullable=True) max_attendees = Column(Integer, nullable=True) status = Column(SQLEnum(EventStatus), default=EventStatus.DRAFT, nullable=False) created_by = Column(Integer, ForeignKey("users.id"), nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships rsvps = relationship("EventRSVP", back_populates="event", cascade="all, delete-orphan") class EventRSVP(Base): __tablename__ = "event_rsvps" id = Column(Integer, primary_key=True, index=True) event_id = Column(Integer, ForeignKey("events.id"), nullable=False) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) status = Column(SQLEnum(RSVPStatus), default=RSVPStatus.PENDING, nullable=False) attended = Column(Boolean, default=False, nullable=False) notes = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships event = relationship("Event", back_populates="rsvps") user = relationship("User", back_populates="event_rsvps") class VolunteerRole(Base): __tablename__ = "volunteer_roles" id = Column(Integer, primary_key=True, index=True) name = Column(String(100), nullable=False) description = Column(Text, nullable=True) is_active = Column(Boolean, default=True, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships assignments = relationship("VolunteerAssignment", back_populates="role", cascade="all, delete-orphan") class VolunteerAssignment(Base): __tablename__ = "volunteer_assignments" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) role_id = Column(Integer, ForeignKey("volunteer_roles.id"), nullable=False) assigned_date = Column(Date, nullable=False) is_active = Column(Boolean, default=True, nullable=False) notes = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships user = relationship("User", back_populates="volunteer_assignments") role = relationship("VolunteerRole", back_populates="assignments") schedules = relationship("VolunteerSchedule", back_populates="assignment", cascade="all, delete-orphan") class VolunteerSchedule(Base): __tablename__ = "volunteer_schedules" id = Column(Integer, primary_key=True, index=True) assignment_id = Column(Integer, ForeignKey("volunteer_assignments.id"), nullable=False) schedule_date = Column(Date, nullable=False) start_time = Column(DateTime, nullable=False) end_time = Column(DateTime, nullable=False) location = Column(String(255), nullable=True) notes = Column(Text, nullable=True) completed = Column(Boolean, default=False, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships assignment = relationship("VolunteerAssignment", back_populates="schedules") class Certificate(Base): __tablename__ = "certificates" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) certificate_name = Column(String(255), nullable=False) issuing_organization = Column(String(255), nullable=True) issue_date = Column(Date, nullable=False) expiry_date = Column(Date, nullable=True) certificate_number = Column(String(100), nullable=True) file_path = Column(String(500), nullable=True) notes = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) # Relationships user = relationship("User", back_populates="certificates") class File(Base): __tablename__ = "files" id = Column(Integer, primary_key=True, index=True) filename = Column(String(255), nullable=False) original_filename = Column(String(255), nullable=False) file_path = Column(String(500), nullable=False) file_size = Column(Integer, nullable=False) mime_type = Column(String(100), nullable=False) min_tier_id = Column(Integer, ForeignKey("membership_tiers.id"), nullable=True) description = Column(Text, nullable=True) uploaded_by = Column(Integer, ForeignKey("users.id"), nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False) class Notification(Base): __tablename__ = "notifications" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) subject = Column(String(255), nullable=False) message = Column(Text, nullable=False) email_sent = Column(Boolean, default=False, nullable=False) sent_at = Column(DateTime, nullable=True) error_message = Column(Text, nullable=True) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) class PasswordResetToken(Base): __tablename__ = "password_reset_tokens" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) token = Column(String(255), unique=True, nullable=False, index=True) expires_at = Column(DateTime, nullable=False) used = Column(Boolean, default=False, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) # Relationships user = relationship("User", backref="password_reset_tokens") class EmailTemplate(Base): __tablename__ = "email_templates" id = Column(Integer, primary_key=True, index=True) template_key = Column(String(100), unique=True, nullable=False, index=True) name = Column(String(255), nullable=False) subject = Column(String(255), nullable=False) html_body = Column(Text, nullable=False) text_body = Column(Text, nullable=True) variables = Column(Text, nullable=True) # JSON string of available variables is_active = Column(Boolean, default=True, nullable=False) created_at = Column(DateTime, default=datetime.utcnow, nullable=False) updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)