from __future__ import annotations
from datetime import datetime
from uuid import uuid4
from sqlalchemy import Column, DateTime, ForeignKey, String, Table, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.core.database import Base
ENTRY_ID_LENGTH = 36
TAG_NAME_LENGTH = 128
TAG_DESCRIPTION_LENGTH = 255
entry_tag_table = Table(
"entry_tags",
Base.metadata,
Column(
"entry_id",
String(ENTRY_ID_LENGTH),
ForeignKey("work_entries.id", ondelete="CASCADE"),
primary_key=True,
),
Column(
"tag_name",
String(TAG_NAME_LENGTH),
ForeignKey("tags.name", ondelete="CASCADE"),
primary_key=True,
),
)
class WorkEntry(Base):
__tablename__ = "work_entries"
id: Mapped[str] = mapped_column(
String(ENTRY_ID_LENGTH),
primary_key=True,
default=lambda: str(uuid4()),
)
description: Mapped[str] = mapped_column(Text, nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.now)
tags: Mapped[list["Tag"]] = relationship(
"Tag",
secondary=entry_tag_table,
back_populates="entries",
lazy="joined",
)
class Tag(Base):
__tablename__ = "tags"
name: Mapped[str] = mapped_column(String(TAG_NAME_LENGTH), primary_key=True)
description: Mapped[str | None] = mapped_column(String(TAG_DESCRIPTION_LENGTH), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, default=datetime.now)
entries: Mapped[list[WorkEntry]] = relationship(
"WorkEntry",
secondary=entry_tag_table,
back_populates="tags",
lazy="selectin",
)