InnerVoice / backend /models /database.py
E5K7's picture
feat: Connect Trusted Circle invites to real Brevo transactional email sender
9a86182
import uuid
from datetime import datetime
from typing import Optional, List
from sqlalchemy import (
create_engine, Column, String, Float, Integer,
Boolean, Text, ForeignKey, DateTime, JSON
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
import os
from dotenv import load_dotenv
load_dotenv()
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite:///./innervoice.db")
engine = create_engine(
DATABASE_URL,
connect_args={"check_same_thread": False} if "sqlite" in DATABASE_URL else {}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
class User(Base):
__tablename__ = "users"
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
email = Column(String, unique=True, nullable=False, index=True)
name = Column(String, nullable=False)
password_hash = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
baseline_pitch = Column(Float, nullable=True)
baseline_energy = Column(Float, nullable=True)
baseline_speech_rate = Column(Float, nullable=True)
voice_entries = relationship("VoiceEntry", back_populates="user", cascade="all, delete-orphan")
mood_alerts = relationship("MoodAlert", back_populates="user", cascade="all, delete-orphan")
chat_messages = relationship("ChatMessage", back_populates="user", cascade="all, delete-orphan")
chat_channels = relationship("ChatChannel", back_populates="user", cascade="all, delete-orphan")
trusted_members = relationship("TrustedMember", back_populates="user", cascade="all, delete-orphan")
class VoiceEntry(Base):
__tablename__ = "voice_entries"
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
user_id = Column(String, ForeignKey("users.id"), nullable=False, index=True)
created_at = Column(DateTime, default=datetime.utcnow)
audio_url = Column(String, nullable=True)
duration_seconds = Column(Float, nullable=True)
transcription = Column(Text, nullable=True)
primary_emotion = Column(String, nullable=True)
emotion_confidence = Column(Float, nullable=True)
energy_score = Column(Integer, nullable=True)
calmness_score = Column(Integer, nullable=True)
mood_score = Column(Integer, nullable=True)
clarity_score = Column(Integer, nullable=True)
pitch_mean = Column(Float, nullable=True)
pitch_std = Column(Float, nullable=True)
energy_raw = Column(Float, nullable=True)
speech_rate = Column(Float, nullable=True)
pause_count = Column(Integer, nullable=True)
avg_pause_duration = Column(Float, nullable=True)
filler_rate = Column(Float, nullable=True)
mfcc_features = Column(JSON, nullable=True)
sleep_hours = Column(Float, nullable=True) # hours slept before this check-in
user = relationship("User", back_populates="voice_entries")
chat_messages = relationship("ChatMessage", back_populates="voice_entry")
class MoodAlert(Base):
__tablename__ = "mood_alerts"
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
user_id = Column(String, ForeignKey("users.id"), nullable=False, index=True)
created_at = Column(DateTime, default=datetime.utcnow)
alert_type = Column(String, nullable=False)
severity = Column(String, nullable=False)
message = Column(Text, nullable=False)
is_read = Column(Boolean, default=False)
suggested_action = Column(Text, nullable=True)
user = relationship("User", back_populates="mood_alerts")
class ChatChannel(Base):
__tablename__ = "chat_channels"
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
user_id = Column(String, ForeignKey("users.id"), nullable=False, index=True)
title = Column(String, nullable=False, default="New Chat")
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
user = relationship("User", back_populates="chat_channels")
messages = relationship("ChatMessage", back_populates="channel", cascade="all, delete-orphan")
class ChatMessage(Base):
__tablename__ = "chat_messages"
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
user_id = Column(String, ForeignKey("users.id"), nullable=False, index=True)
channel_id = Column(String, ForeignKey("chat_channels.id"), nullable=True, index=True)
created_at = Column(DateTime, default=datetime.utcnow)
role = Column(String, nullable=False) # user / assistant
content = Column(Text, nullable=False)
voice_entry_id = Column(String, ForeignKey("voice_entries.id"), nullable=True)
user = relationship("User", back_populates="chat_messages")
channel = relationship("ChatChannel", back_populates="messages")
voice_entry = relationship("VoiceEntry", back_populates="chat_messages")
class TrustedMember(Base):
__tablename__ = "trusted_members"
id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4()))
user_id = Column(String, ForeignKey("users.id"), nullable=False, index=True)
email = Column(String, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
is_active = Column(Boolean, default=True)
user = relationship("User", back_populates="trusted_members")
def init_db():
Base.metadata.create_all(bind=engine)