Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add more models to match workflows #23

Merged
merged 10 commits into from
Sep 22, 2024
66 changes: 66 additions & 0 deletions backend/alembic/versions/04e02312343d_add_user_question_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""Add user question models
Revision ID: 04e02312343d
Revises: d369cd69a23b
Create Date: 2024-09-22 21:35:48.778303
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "04e02312343d"
down_revision: Union[str, None] = "d369cd69a23b"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"user_question",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("question", sa.String(), nullable=False),
sa.Column("user_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["user_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"answer",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("user_question_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["user_question_id"],
["user_question.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"point",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("title", sa.String(), nullable=False),
sa.Column("body", sa.String(), nullable=False),
sa.Column("answer_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["answer_id"],
["answer.id"],
),
sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("point")
op.drop_table("answer")
op.drop_table("user_question")
# ### end Alembic commands ###
40 changes: 40 additions & 0 deletions backend/alembic/versions/680d9bea2168_add_note_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Add note models
Revision ID: 680d9bea2168
Revises: 04e02312343d
Create Date: 2024-09-22 22:07:11.979617
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "680d9bea2168"
down_revision: Union[str, None] = "04e02312343d"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"note",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("content", sa.String(), nullable=False),
sa.Column("start_index", sa.Integer(), nullable=False),
sa.Column("end_index", sa.Integer(), nullable=False),
sa.Column("parent_id", sa.Integer(), nullable=False),
sa.Column("parent_type", sa.String(), nullable=False),
sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("note")
# ### end Alembic commands ###
58 changes: 58 additions & 0 deletions backend/alembic/versions/8912e0e896bf_add_analysis_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""Add Analysis table
Revision ID: 8912e0e896bf
Revises: ff5af4d7ce04
Create Date: 2024-09-22 18:29:26.096419
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "8912e0e896bf"
down_revision: Union[str, None] = "ff5af4d7ce04"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"analysis",
sa.Column("event_id", sa.Integer(), nullable=False),
sa.Column("category_id", sa.Integer(), nullable=False),
sa.Column("content", sa.String(), nullable=False),
sa.ForeignKeyConstraint(
["category_id"],
["category.id"],
),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.PrimaryKeyConstraint("event_id", "category_id"),
)
op.drop_table("event_category")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"event_category",
sa.Column("event_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("category_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(
["category_id"], ["category.id"], name="event_category_category_id_fkey"
),
sa.ForeignKeyConstraint(
["event_id"], ["event.id"], name="event_category_event_id_fkey"
),
sa.PrimaryKeyConstraint("event_id", "category_id", name="event_category_pkey"),
)
op.drop_table("analysis")
# ### end Alembic commands ###
57 changes: 57 additions & 0 deletions backend/alembic/versions/8c458d0adb18_add_gp_questions_tables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""Add GP Questions tables
Revision ID: 8c458d0adb18
Revises: 8912e0e896bf
Create Date: 2024-09-22 18:49:41.011371
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "8c458d0adb18"
down_revision: Union[str, None] = "8912e0e896bf"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"gp_question",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("question", sa.String(), nullable=False),
sa.Column("is_llm_generated", sa.Boolean(), nullable=False),
sa.Column("event_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table(
"gp_question_categories",
sa.Column("gp_question_id", sa.Integer(), nullable=False),
sa.Column("category_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["category_id"],
["category.id"],
),
sa.ForeignKeyConstraint(
["gp_question_id"],
["gp_question.id"],
),
sa.PrimaryKeyConstraint("gp_question_id", "category_id"),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("gp_question_categories")
op.drop_table("gp_question")
# ### end Alembic commands ###
31 changes: 31 additions & 0 deletions backend/alembic/versions/b8f3f95c78b6_add_image_url_to_article.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Add image url to article
Revision ID: b8f3f95c78b6
Revises: 8c458d0adb18
Create Date: 2024-09-22 18:56:47.024304
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "b8f3f95c78b6"
down_revision: Union[str, None] = "8c458d0adb18"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("article", sa.Column("image_url", sa.String(), nullable=False))
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("article", "image_url")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""Remove analysis field from event
Revision ID: bc5fcbe47713
Revises: f624d58d3f42
Create Date: 2024-09-22 22:33:38.823000
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "bc5fcbe47713"
down_revision: Union[str, None] = "f624d58d3f42"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("event", "analysis")
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"event",
sa.Column("analysis", sa.VARCHAR(), autoincrement=False, nullable=False),
)
# ### end Alembic commands ###
31 changes: 31 additions & 0 deletions backend/alembic/versions/d369cd69a23b_add_rating_to_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Add rating to event
Revision ID: d369cd69a23b
Revises: b8f3f95c78b6
Create Date: 2024-09-22 18:59:11.283743
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "d369cd69a23b"
down_revision: Union[str, None] = "b8f3f95c78b6"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("event", sa.Column("rating", sa.Integer(), nullable=False))
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("event", "rating")
# ### end Alembic commands ###
33 changes: 33 additions & 0 deletions backend/alembic/versions/f624d58d3f42_add_user_id_to_note.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"""Add user id to note
Revision ID: f624d58d3f42
Revises: 680d9bea2168
Create Date: 2024-09-22 22:29:21.220643
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "f624d58d3f42"
down_revision: Union[str, None] = "680d9bea2168"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("note", sa.Column("user_id", sa.Integer(), nullable=False))
op.create_foreign_key(None, "note", "user", ["user_id"], ["id"])
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, "note", type_="foreignkey")
op.drop_column("note", "user_id")
# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Add ArticleEvent join table
Revision ID: ff5af4d7ce04
Revises: a73902039c96
Create Date: 2024-09-22 18:24:05.699420
"""

from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = "ff5af4d7ce04"
down_revision: Union[str, None] = "a73902039c96"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"article_event",
sa.Column("article_id", sa.Integer(), nullable=False),
sa.Column("event_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["article_id"],
["article.id"],
),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.PrimaryKeyConstraint("article_id", "event_id"),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("article_event")
# ### end Alembic commands ###
2 changes: 2 additions & 0 deletions backend/src/auth/models.py
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
from sqlalchemy.orm import Mapped, mapped_column, relationship
from src.common.base import Base
from src.events.models import Category
from src.notes.models import Note


class AccountType(str, Enum):
@@ -27,3 +28,4 @@ class User(Base):
account_type: Mapped[AccountType]

categories: Mapped[list[Category]] = relationship(secondary=user_category_table)
notes: Mapped[list[Note]] = relationship("Note", backref="user")
77 changes: 68 additions & 9 deletions backend/src/events/models.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
from enum import Enum
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship, foreign
from sqlalchemy import Column, ForeignKey, Table, and_
from datetime import datetime
from src.common.base import Base
from src.notes.models import Note


class ArticleSource(str, Enum):
CNA = "CNA"
GUARDIAN = "GUARDIAN"


article_event_table = Table(
"article_event",
Base.metadata,
Column("article_id", ForeignKey("article.id"), primary_key=True),
Column("event_id", ForeignKey("event.id"), primary_key=True),
)


class Article(Base):
__tablename__ = "article"

@@ -20,8 +29,21 @@ class Article(Base):
url: Mapped[str]
source: Mapped[ArticleSource]
date: Mapped[datetime]
image_url: Mapped[str]

original_events: Mapped[list["Event"]] = relationship(
back_populates="original_article"
)

events: Mapped[list["Event"]] = relationship(back_populates="original_article")
events: Mapped[list["Event"]] = relationship(
back_populates="articles", secondary=article_event_table
)

notes = relationship(
"Note",
primaryjoin=and_(id == foreign(Note.parent_id), Note.parent_type == "article"),
backref="article",
)


class Event(Base):
@@ -30,17 +52,27 @@ class Event(Base):
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
description: Mapped[str]
analysis: Mapped[str]
duplicate: Mapped[bool]
date: Mapped[datetime]
is_singapore: Mapped[bool]
original_article_id: Mapped[int] = mapped_column(ForeignKey("article.id"))
rating: Mapped[int]

categories: Mapped[list["Category"]] = relationship(
back_populates="events", secondary="event_category"
back_populates="events", secondary="analysis"
)

original_article: Mapped[Article] = relationship(back_populates="events")
original_article: Mapped[Article] = relationship(back_populates="original_events")
articles: Mapped[list[Article]] = relationship(
back_populates="events", secondary=article_event_table
)
gp_questions: Mapped["GPQuestion"] = relationship(back_populates="event")

notes = relationship(
"Note",
primaryjoin=and_(id == foreign(Note.parent_id), Note.parent_type == "note"),
backref="event",
)


class Category(Base):
@@ -50,14 +82,41 @@ class Category(Base):
name: Mapped[str]

events: Mapped[list[Event]] = relationship(
secondary="event_category", back_populates="categories"
secondary="analysis", back_populates="categories"
)


class EventCategory(Base):
__tablename__ = "event_category"
class Analysis(Base):
__tablename__ = "analysis"

event_id: Mapped[int] = mapped_column(ForeignKey("event.id"), primary_key=True)
category_id: Mapped[int] = mapped_column(
ForeignKey("category.id"), primary_key=True
)
content: Mapped[str]


class GPQuestion(Base):
__tablename__ = "gp_question"

id: Mapped[int] = mapped_column(primary_key=True)
question: Mapped[str]
is_llm_generated: Mapped[bool] = mapped_column(default=True)
event_id = mapped_column(ForeignKey("event.id"))

categories: Mapped[list["Category"]] = relationship(
secondary="gp_question_categories"
)

event: Mapped[Event] = relationship(back_populates="gp_questions")


class GPQuestionCategories(Base):
__tablename__ = "gp_question_categories"

gp_question_id: Mapped[int] = mapped_column(
ForeignKey("gp_question.id"), primary_key=True
)
category_id: Mapped[int] = mapped_column(
ForeignKey("category.id"), primary_key=True
)
26 changes: 26 additions & 0 deletions backend/src/notes/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from sqlalchemy import Enum, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column
from src.common.base import Base


class NoteType(str, Enum):
EVENT = "event"
ARTICLE = "article"
POINT = "point"


class Note(Base):
__tablename__ = "note"

id: Mapped[int] = mapped_column(primary_key=True)
content: Mapped[str]

start_index: Mapped[int]
end_index: Mapped[int]

parent_id: Mapped[int]
parent_type: Mapped[str]

user_id: Mapped[int] = mapped_column(ForeignKey("user.id"))

__mapper_args__ = {"polymorphic_on": "parent_type", "polymorphic_identity": "note"}
1 change: 0 additions & 1 deletion backend/src/scripts/seed.py
Original file line number Diff line number Diff line change
@@ -44,7 +44,6 @@ def test_associations():
event = Event(
title="test event 1",
description="x",
analysis="x",
duplicate=False,
date=datetime.now(),
is_singapore=False,
41 changes: 41 additions & 0 deletions backend/src/user_questions/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from sqlalchemy import ForeignKey, and_
from src.common.base import Base
from sqlalchemy.orm import Mapped, mapped_column, relationship, foreign
from src.notes.models import Note


class UserQuestion(Base):
__tablename__ = "user_question"

id: Mapped[int] = mapped_column(primary_key=True)
question: Mapped[str]

answer: Mapped["Answer"] = relationship(back_populates="user_question")

user_id: Mapped[int] = mapped_column(ForeignKey("user.id"))


class Answer(Base):
__tablename__ = "answer"
id: Mapped[int] = mapped_column(primary_key=True)
user_question_id: Mapped[int] = mapped_column(ForeignKey("user_question.id"))

user_question: Mapped[UserQuestion] = relationship(back_populates="answer")

points: Mapped[list["Point"]] = relationship(back_populates="answer")


class Point(Base):
__tablename__ = "point"
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str]
body: Mapped[str]
answer_id: Mapped[int] = mapped_column(ForeignKey("answer.id"))

answer: Mapped[Answer] = relationship(back_populates="points")

notes = relationship(
"Note",
primaryjoin=and_(id == foreign(Note.parent_id), Note.parent_type == "point"),
backref="point",
)
2 changes: 2 additions & 0 deletions backend/src/utils/models.py
Original file line number Diff line number Diff line change
@@ -2,3 +2,5 @@

from src.auth import models as auth_models # noqa: F401
from src.events import models as event_models # noqa: F401
from src.user_questions import models as user_question_models # noqa: F401
from src.notes import models as note_models # noqa: F401