mr_mvp_dev / backend /models.py
srivatsavdamaraju's picture
Upload 173 files
b2315b1 verified
from datetime import datetime, timezone
import enum
import uuid
from uuid import UUID
from sqlalchemy import (
Column, String, Boolean, ForeignKey, Float,
DateTime, Text, Enum as SQLEnum, Integer
)
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import JSONB, UUID as PG_UUID
import os
import sys
from pathlib import Path
# ensure project root (agent/) is on sys.path so sibling packages like "s3" can be imported
project_root = Path(__file__).resolve().parents[2] # -> ...\openai_agents\agent
if str(project_root) not in sys.path:
sys.path.insert(0, str(project_root))
from .database import Base
# ---------- ENUMS ----------
class UserRole(str, enum.Enum):
superadmin = "superadmin"
org_admin = "org_admin"
employee = "employee"
provider = "provider"
user = "user" # Fixed: Was "User" → lowercase "user" for consistency
class DatasetStatus(str, enum.Enum):
pending = "pending"
approved = "approved"
rejected = "rejected"
published = "published"
in_review = "in_review"
deprecated = "deprecated"
paused = "paused"
class LeadStatus(str, enum.Enum):
new = "new"
contacted = "contacted"
closed = "closed"
interested = "interested"
meeting_scheduled = "meeting_scheduled"
follow_up = "follow_up"
won = "won"
lost = "lost"
# ---------- MODELS ----------
class Plan(Base):
__tablename__ = "plans"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
plan_type = Column(String(100), nullable=False)
price = Column(Float, nullable=False)
features = Column(Text)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
deleted_at = Column(DateTime(timezone=True), nullable=True)
created_by = Column(
PG_UUID(as_uuid=True),
ForeignKey("users.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"),
nullable=True,
index=True
)
organizations = relationship("Organization", back_populates="plan")
def __repr__(self):
return f"<Plan(id={self.id}, plan_type={self.plan_type}, price={self.price})>"
class Organization(Base):
__tablename__ = "organizations"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name = Column(String(255), nullable=False)
domain = Column(String(255), nullable=True, index=True) # Fixed: Removed duplicate definition
plan_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("plans.id", ondelete="RESTRICT", deferrable=True, initially="DEFERRED"),
nullable=False,
index=True
)
location = Column(Text)
city = Column(String(100))
state = Column(String(100))
country = Column(String(100))
is_active = Column(Boolean, default=True, nullable=False)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc), nullable=False)
deleted_at = Column(DateTime(timezone=True), nullable=True)
created_by = Column(
PG_UUID(as_uuid=True),
ForeignKey("users.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"),
nullable=True,
index=True
)
admin_name = Column(String(255), nullable=True)
admin_email = Column(String(255), unique=True, nullable=True, index=True)
timezone = Column(String(50))
seats = Column(Integer, default=5)
storage_quota_gb = Column(Integer, default=100)
data_residency = Column(String(50), nullable=True)
status = Column(String(50), default="active", nullable=False)
contact_number = Column(String(50), nullable=True)
notes = Column(Text, nullable=True)
plan = relationship("Plan", back_populates="organizations")
users = relationship("User", back_populates="organization", foreign_keys="User.organization_id")
leads = relationship("Lead", back_populates="organization")
datasets = relationship("Dataset", back_populates="organization")
# audit_logs = relationship("ActivityLog", back_populates="organization")
def __repr__(self):
return f"<Organization(id={self.id}, name={self.name}, domain={self.domain})>"
class ThirdPartyProvider(Base):
__tablename__ = "third_party_providers"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
provider_name = Column(String(255), nullable=False)
is_active = Column(Boolean, default=True, nullable=False)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
deleted_at = Column(DateTime(timezone=True), nullable=True)
created_by = Column(
PG_UUID(as_uuid=True),
ForeignKey("users.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"),
nullable=True,
index=True
)
domain = Column(String(255), nullable=True, index=True)
full_name = Column(String(255), nullable=True, index=True)
provider_email = Column(String(255), unique=True, nullable=False, index=True)
providerphone_number = Column(String(50), nullable=True)
country = Column(String(100))
data_residency = Column(String(50), nullable=True)
storage_quota = Column(Integer, default=100)
timezone = Column(String(50))
provider_status = Column(String(50), default="active", nullable=False)
provider_notes = Column(Text, nullable=True)
users = relationship("User", back_populates="provider", foreign_keys="User.provider_id")
datasets = relationship("Dataset", back_populates="provider")
leads = relationship("Lead", back_populates="provider")
def __repr__(self):
return f"<ThirdPartyProvider(id={self.id}, provider_name={self.provider_name})>"
class User(Base):
__tablename__ = "users"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
fullname = Column(String(255), nullable=False)
username = Column(String(100), unique=True, nullable=False, index=True)
password = Column(String(500), nullable=False) # Increased for bcrypt compatibility
email = Column(String(255), unique=True, nullable=False, index=True)
role = Column(SQLEnum(UserRole), nullable=False, index=True)
is_active = Column(Boolean, default=True, nullable=False, index=True)
last_login = Column(DateTime(timezone=True))
organization_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("organizations.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"),
nullable=True,
index=True
)
provider_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("third_party_providers.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"),
nullable=True,
index=True
)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc), nullable=False)
deleted_at = Column(DateTime(timezone=True), nullable=True)
organization = relationship("Organization", back_populates="users", foreign_keys=[organization_id])
provider = relationship("ThirdPartyProvider", back_populates="users", foreign_keys=[provider_id])
conversation_data = relationship("ConversationData", back_populates="user", cascade="all, delete-orphan")
def __repr__(self):
return f"<User(id={self.id}, username={self.username}, email={self.email}, role={self.role})>"
class Dataset(Base):
__tablename__ = "datasets"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
dataset_name = Column(String(255), nullable=False)
dataset_type = Column(String(100))
tags = Column(String(500))
price = Column(Float)
submitted_time = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
description = Column(Text)
file_url = Column(Text)
status = Column(SQLEnum(DatasetStatus), default=DatasetStatus.pending, nullable=False, index=True)
created_by = Column(
PG_UUID(as_uuid=True),
ForeignKey("users.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"),
nullable=True,
index=True
)
organization_id = Column( # Added: Assumed missing FK based on relationship; adjust if not needed
PG_UUID(as_uuid=True),
ForeignKey("organizations.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"),
nullable=True,
index=True
)
provider_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("third_party_providers.id", ondelete="RESTRICT", deferrable=True, initially="DEFERRED"),
nullable=False,
index=True
)
reviewed_by = Column(
PG_UUID(as_uuid=True),
ForeignKey("users.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"),
nullable=True,
index=True
)
approved_at = Column(DateTime(timezone=True))
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
deleted_at = Column(DateTime(timezone=True), nullable=True)
organization = relationship("Organization", back_populates="datasets") # Added: To match new FK
provider = relationship("ThirdPartyProvider", back_populates="datasets")
reviewer = relationship("User", foreign_keys=[reviewed_by])
creator = relationship("User", foreign_keys=[created_by])
def __repr__(self):
return f"<Dataset(id={self.id}, dataset_name={self.dataset_name}, status={self.status})>"
class Lead(Base):
__tablename__ = "leads"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
organization_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("organizations.id", ondelete="CASCADE", deferrable=True, initially="DEFERRED"),
nullable=False,
index=True
)
provider_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("third_party_providers.id", ondelete="RESTRICT", deferrable=True, initially="DEFERRED"),
nullable=False,
index=True
)
dataset_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("datasets.id", ondelete="RESTRICT", deferrable=True, initially="DEFERRED"),
nullable=False,
index=True
)
contact = Column(String(255), nullable=False)
status = Column(SQLEnum(LeadStatus), default=LeadStatus.new, nullable=False, index=True)
note = Column(Text)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc), nullable=False)
deleted_at = Column(DateTime(timezone=True), nullable=True)
organization = relationship("Organization", back_populates="leads")
provider = relationship("ThirdPartyProvider", back_populates="leads")
dataset = relationship("Dataset", foreign_keys=[dataset_id])
def __repr__(self):
return f"<Lead(id={self.id}, contact={self.contact}, status={self.status})>"
class ConversationData(Base):
__tablename__ = "conversation_data"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
convo_id = Column(String(255), nullable=False, index=True)
user_query = Column(JSONB, nullable=False)
response = Column(JSONB, nullable=False)
file_metadata = Column(JSONB, nullable=True)
is_saved = Column(Boolean, default=False, nullable=False)
user_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("users.id", ondelete="CASCADE", deferrable=True, initially="DEFERRED"),
nullable=False,
index=True
)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc), nullable=False)
deleted_at = Column(DateTime(timezone=True), nullable=True)
user = relationship("User", back_populates="conversation_data")
def __repr__(self):
return f"<ConversationData(id={self.id}, convo_id={self.convo_id})>"
class UserDatasetsMetadata(Base):
__tablename__ = "user_datasets_metadata"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column(
PG_UUID(as_uuid=True),
ForeignKey("users.id", ondelete="CASCADE", deferrable=True, initially="DEFERRED"),
nullable=False,
index=True
)
user_metadata = Column(JSONB, nullable=False)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at = Column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
nullable=False
)
path = Column(String(512), nullable=True)
url = Column(String(1024), nullable=True)
filename = Column(String(255), nullable=True)
file_type = Column(String(50), nullable=True)
file_size_bytes = Column(Integer, nullable=True)
file_hash = Column(String(1024), nullable=True)
# Relationship
user = relationship("User", backref="user_datasets_metadata")
def __repr__(self):
return f"<UserDatasetsMetadata(id={self.id}, user_id={self.user_id})>"
class PasswordReset(Base):
__tablename__ = "password_reset"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column(PG_UUID(as_uuid=True), ForeignKey("users.id", deferrable=True, initially="DEFERRED"), nullable=True)
otp = Column(String(6), nullable=True)
is_verified = Column(Boolean, default=True)
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
expires_at = Column(DateTime(timezone=True), nullable=True)
user = relationship("User", backref="password_resets")
class GeneratedReport(Base):
__tablename__ = "generated_reports"
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
report_name = Column(String(400), nullable=True)
user_id = Column(PG_UUID(as_uuid=True), ForeignKey("users.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"))
org_id = Column(PG_UUID(as_uuid=True), ForeignKey("organizations.id", ondelete="SET NULL", deferrable=True, initially="DEFERRED"))
format = Column(String(20)) # pdf, pptx
# content_items = Column(JSONB) # list of query ids / dataset ids
theme = Column(String(100))
file_url = Column(Text)
status = Column(String(50), default="ready") # generating, ready, failed
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=True)
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc), nullable=True)
file_path = Column(String(512), nullable=True)
filename = Column(String(255), nullable=True)
size_bytes = Column(Integer, nullable=True)
user = relationship("User", back_populates="generated_reports") # Added: back_populates for bidirectionality
organization = relationship("Organization", back_populates="generated_reports") # Added: back_populates for bidirectionality
# Add to User model (after its definition) for GeneratedReport relationships
# Note: Since User is defined earlier, add these lines after the User class in the file
User.generated_reports = relationship("GeneratedReport", back_populates="user", foreign_keys="GeneratedReport.user_id")
# Add to Organization model (after its definition) for GeneratedReport relationships
Organization.generated_reports = relationship("GeneratedReport", back_populates="organization", foreign_keys="GeneratedReport.org_id")