import enum from db.db import Base from sqlalchemy import Column, DateTime, ForeignKey, Integer, String, Table, Text, func from sqlalchemy.orm import declarative_mixin, relationship from sqlalchemy.types import Enum @declarative_mixin class TimestampMixin: created_at = Column( DateTime(timezone=True), server_default=func.now(), nullable=False ) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) class InvestmentStage(enum.Enum): SEED = "SEED" SERIES_A = "SERIES_A" SERIES_B = "SERIES_B" SERIES_C = "SERIES_C" GROWTH = "GROWTH" LATE_STAGE = "LATE_STAGE" # Association table for many-to-many relationship between investors and companies investor_company_association = Table( "investor_companies", Base.metadata, Column("investor_id", Integer, ForeignKey("investors.id")), Column("company_id", Integer, ForeignKey("companies.id")), ) # Association table for investor-sector many-to-many investor_sector_association = Table( "investor_sectors", Base.metadata, Column("investor_id", Integer, ForeignKey("investors.id")), Column("sector_id", Integer, ForeignKey("sectors.id")), ) company_sector_association = Table( "company_sector", Base.metadata, Column("company_id", Integer, ForeignKey("companies.id")), Column("sector_id", Integer, ForeignKey("sectors.id")), ) class InvestorTable(Base, TimestampMixin): __tablename__ = "investors" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) description = Column(Text, nullable=True) aum = Column(Integer, nullable=False) # Assets Under Management check_size_lower = Column(Integer, nullable=False) # Lower bound check_size_upper = Column(Integer, nullable=False) # Upper bound geographic_focus = Column(String, nullable=False) stage_focus = Column(Enum(InvestmentStage), nullable=False) number_of_investments = Column(Integer, default=0) # Relationship to portfolio companies portfolio_companies = relationship( "CompanyTable", secondary=investor_company_association, back_populates="investors", ) team_members = relationship("InvestorMember", back_populates="investor") sectors = relationship( "SectorTable", secondary=investor_sector_association, back_populates="investors", ) class InvestorMember(Base, TimestampMixin): __tablename__ = "investor_members" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) role = Column(String, nullable=False) email = Column(String, nullable=False) investor_id = Column(Integer, ForeignKey("investors.id")) investor = relationship("InvestorTable", back_populates="team_members") class CompanyTable(Base, TimestampMixin): __tablename__ = "companies" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) industry = Column(String, nullable=False) location = Column(String, nullable=False) description = Column(String, nullable=True) founded_year = Column(Integer, nullable=True) website = Column(String, nullable=True) members = relationship("CompanyMember", back_populates="company") # Relationship back to investors investors = relationship( "InvestorTable", secondary=investor_company_association, back_populates="portfolio_companies", ) sectors = relationship( "SectorTable", secondary=company_sector_association, back_populates="companies" ) class CompanyMember(Base, TimestampMixin): __tablename__ = "company_members" id = Column(Integer, primary_key=True) name = Column(String) linkedin = Column(String) role = Column(String) company_id = Column(Integer, ForeignKey("companies.id"), nullable=False) company = relationship("CompanyTable", back_populates="members") class SectorTable(Base, TimestampMixin): __tablename__ = "sectors" id = Column(Integer, primary_key=True, index=True) name = Column(String, nullable=False) # Add relationship back to investors investors = relationship( "InvestorTable", secondary=investor_sector_association, back_populates="sectors", ) companies = relationship( "CompanyTable", secondary=company_sector_association, back_populates="sectors" )