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

Election and some other stuff #104

Merged
merged 16 commits into from
Jan 19, 2025
Merged
18 changes: 15 additions & 3 deletions api_schemas/candidate_schema.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
from pydantic_extra_types.phone_numbers import PhoneNumber
from api_schemas.base_schema import BaseSchema
from api_schemas.user_schemas import UserRead
from helpers.types import datetime_utc


class CandidateUserRead(BaseSchema):
first_name: str
last_name: str
email: str
telephone_number: PhoneNumber
start_year: int
account_created: datetime_utc
want_notifications: bool


class PostRead(BaseSchema):
Expand All @@ -10,14 +21,15 @@ class PostRead(BaseSchema):
class CandidateRead(BaseSchema):
candidate_id: int
election_id: int
user: UserRead
user_id: int
user: CandidateUserRead
election_posts: list[PostRead]


class CandidateElectionRead(BaseSchema):
candidate_id: int
user_id: int
user: UserRead
user: CandidateUserRead
election_posts: list[PostRead]


Expand Down
6 changes: 3 additions & 3 deletions db_models/candidate_model.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from db_models.candidate_post_model import CandidatePost_DB
from db_models.candidate_post_model import Candidation_DB
from db_models.election_post_model import ElectionPost_DB
from .base_model import BaseModel_DB
from sqlalchemy.orm import mapped_column, Mapped, relationship
Expand All @@ -25,12 +25,12 @@ class Candidate_DB(BaseModel_DB):

user: Mapped["User_DB"] = relationship("User_DB", back_populates="candidates", init=False)

candidate_posts: Mapped[list["CandidatePost_DB"]] = relationship(
candidations: Mapped[list["Candidation_DB"]] = relationship(
back_populates="candidate", cascade="all, delete-orphan", init=False
)

election_posts: AssociationProxy[list["ElectionPost_DB"]] = association_proxy(
target_collection="candidate_posts", attr="election_post", init=False
target_collection="candidations", attr="election_post", init=False
)

pass
Equasa marked this conversation as resolved.
Show resolved Hide resolved
8 changes: 4 additions & 4 deletions db_models/candidate_post_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
from db_models.candidate_model import Candidate_DB


class CandidatePost_DB(BaseModel_DB):
__tablename__ = "candidate_post_table"
class Candidation_DB(BaseModel_DB):
__tablename__ = "candidations_table"

candidate_id: Mapped[int] = mapped_column(ForeignKey("candidate_table.candidate_id"), primary_key=True)
election_post_id: Mapped[int] = mapped_column(ForeignKey("election_post_table.election_post_id"), primary_key=True)

candidate: Mapped["Candidate_DB"] = relationship(back_populates="candidate_posts", init=False)
election_post: Mapped["ElectionPost_DB"] = relationship(back_populates="candidate_posts", init=False)
candidate: Mapped["Candidate_DB"] = relationship(back_populates="candidations", init=False)
election_post: Mapped["ElectionPost_DB"] = relationship(back_populates="candidations", init=False)
25 changes: 1 addition & 24 deletions db_models/election_model.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from datetime import datetime
from db_models.candidate_model import Candidate_DB
from db_models.candidate_post_model import CandidatePost_DB
from db_models.election_post_model import ElectionPost_DB
from db_models.post_model import Post_DB
from helpers.constants import MAX_ELECTION_DESC
from .base_model import BaseModel_DB
from sqlalchemy.orm import mapped_column, Mapped, relationship
from typing import Optional, TYPE_CHECKING
from typing import Optional
from sqlalchemy import String
from sqlalchemy.ext.associationproxy import association_proxy, AssociationProxy

Expand Down Expand Up @@ -35,25 +34,3 @@ class Election_DB(BaseModel_DB):
posts: AssociationProxy[list["Post_DB"]] = association_proxy(
target_collection="election_posts", attr="post", init=False
)


# class Election_DB(BaseModel_DB):
# __tablename__ = "election_table"

# election_id: Mapped[int] = mapped_column(primary_key=True, init=False)
# title: Mapped[str] = mapped_column()
# start_time: Mapped[datetime] = mapped_column()
# end_time: Mapped[datetime] = mapped_column()
# description: Mapped[Optional[str]] = mapped_column(String(MAX_ELECTION_DESC), default=None)

# election_posts: Mapped[list["ElectionPost_DB"]] = relationship(
# back_populates="election", cascade="all, delete-orphan", init=False
# )

# candidates: Mapped[list["Candidate_DB"]] = relationship(
# "Candidate_DB", back_populates="election", cascade="all, delete-orphan", init=False
# )

# posts: AssociationProxy[list["Post_DB"]] = association_proxy(
# target_collection="election_posts", attr="post", init=False
# )
9 changes: 4 additions & 5 deletions db_models/election_post_model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import TYPE_CHECKING, Optional
from sqlalchemy import ForeignKey, String
from db_models.candidate_post_model import CandidatePost_DB
from helpers.constants import MAX_ELECTION_DESC
from typing import TYPE_CHECKING
from sqlalchemy import ForeignKey
from db_models.candidate_post_model import Candidation_DB
from .base_model import BaseModel_DB
from sqlalchemy.orm import relationship, Mapped, mapped_column

Expand All @@ -22,4 +21,4 @@ class ElectionPost_DB(BaseModel_DB):
post: Mapped["Post_DB"] = relationship(back_populates="election_posts", init=False)
election: Mapped["Election_DB"] = relationship(back_populates="election_posts", init=False)

candidate_posts: Mapped[list["CandidatePost_DB"]] = relationship(back_populates="election_post", init=False)
candidations: Mapped[list["Candidation_DB"]] = relationship(back_populates="election_post", init=False)
1 change: 0 additions & 1 deletion db_models/post_model.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import TYPE_CHECKING, Callable
from sqlalchemy import ForeignKey, String

from db_models.candidate_post_model import CandidatePost_DB
from db_models.election_post_model import ElectionPost_DB
from .base_model import BaseModel_DB
from sqlalchemy.ext.associationproxy import association_proxy, AssociationProxy
Expand Down
4 changes: 4 additions & 0 deletions db_models/user_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ class User_DB(BaseModel_DB, SQLAlchemyBaseUserTable[int]):
back_populates="user", cascade="all, delete-orphan", init=False
)

cafe_shifts: Mapped[list["CafeShift_DB"]] = relationship(
back_populates="user", cascade="all, delete-orphan", init=False
)

is_member: Mapped[bool] = mapped_column(default=False)

want_notifications: Mapped[bool] = mapped_column(default=True)
Expand Down
4 changes: 3 additions & 1 deletion helpers/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ def force_utc(date: datetime):
# Adding to them is always safe though.

PERMISSION_TYPE = Literal["view", "manage"]
PERMISSION_TARGET = Literal["Event", "User", "Post", "Permission", "News", "Song", "Ads", "Gallery", "Car", "Election"]
PERMISSION_TARGET = Literal[
"Event", "User", "Post", "Permission", "News", "Song", "Ads", "Gallery", "Car", "Cafe", "Election"
]

# This is a little ridiculous now, but if we have many actions, this is a neat system.
# This one is to make one action eg. "be_a_god" mean several actions eg. "view", "manage", "know_everything",
Expand Down
8 changes: 1 addition & 7 deletions routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
from fastapi import APIRouter

from routes import candidate_router

from .election_router import election_router
from .user_router import user_router
from .post_router import post_router
from .permission_router import permission_router
Expand Down Expand Up @@ -50,6 +46,4 @@

main_router.include_router(car_router, prefix="/car", tags=["cars"])

main_router.include_router(election_router, prefix="/election", tags=["elections"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Detta verkar ha försvunnit i mergen :(


main_router.include_router(candidate_router, prefix="/candidate", tags=["candidates"])
main_router.include_router(song_category_router, prefix="/songs-category", tags=["songs category"])
2 changes: 1 addition & 1 deletion routes/ad_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from database import DB_dependency
from db_models.ad_model import BookAd_DB
from api_schemas.ad_schema import AdRead, AdCreate, AdUpdate
from db_models.council_model import Council_DB
from db_models.user_model import User_DB
from user.permission import Permission

Expand Down Expand Up @@ -77,6 +76,7 @@ def remove_ad(id: int, current_user: Annotated[User_DB, Permission.base()], db:
raise HTTPException(status.HTTP_403_FORBIDDEN)
db.delete(ad)
db.commit()

return ad


Expand Down
69 changes: 62 additions & 7 deletions routes/candidate_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from api_schemas.candidate_schema import CandidateElectionCreate, CandidateRead
from database import DB_dependency
from db_models.candidate_model import Candidate_DB
from db_models.candidate_post_model import CandidatePost_DB
from db_models.candidate_post_model import Candidation_DB
from db_models.election_model import Election_DB
from db_models.election_post_model import ElectionPost_DB
from db_models.user_model import User_DB
Expand All @@ -22,8 +22,8 @@ def get_all_candidations(election_id: int, db: DB_dependency):
return candidations


@candidate_router.post("/{election_id}", response_model=CandidateRead, dependencies=[Permission.member()])
def create_candidation(
@candidate_router.post("/many/{election_id}", response_model=CandidateRead, dependencies=[Permission.member()])
def create_candidations(
election_id: int, data: CandidateElectionCreate, me: Annotated[User_DB, Permission.member()], db: DB_dependency
):
candidate = (
Expand Down Expand Up @@ -54,9 +54,9 @@ def create_candidation(
valid_election_post_ids = [post_id_to_election_post_id[post] for post in data.post_ids]

existing_candidations = (
db.query(CandidatePost_DB.election_post_id)
.filter(CandidatePost_DB.candidate_id == candidate.candidate_id)
.filter(CandidatePost_DB.election_post_id.in_(valid_election_post_ids))
db.query(Candidation_DB.election_post_id)
.filter(Candidation_DB.candidate_id == candidate.candidate_id)
.filter(Candidation_DB.election_post_id.in_(valid_election_post_ids))
.all()
)
existing_election_post_ids = {cp.election_post_id for cp in existing_candidations}
Expand All @@ -70,10 +70,65 @@ def create_candidation(
)

candidations = [
CandidatePost_DB(candidate_id=candidate.candidate_id, election_post_id=ep_id) for ep_id in new_election_post_ids
Candidation_DB(candidate_id=candidate.candidate_id, election_post_id=ep_id) for ep_id in new_election_post_ids
]

db.add_all(candidations)
db.commit()

return candidate


@candidate_router.post("/{election_id}", response_model=CandidateRead, dependencies=[Permission.member()])
def create_candidation(election_id: int, post_id: int, me: Annotated[User_DB, Permission.member()], db: DB_dependency):

election = db.query(Election_DB).filter(Election_DB.election_id == election_id).one_or_none()
if election is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Election does not exist",
)

candidate = (
db.query(Candidate_DB)
.filter(Candidate_DB.election_id == election_id, Candidate_DB.user_id == me.id)
.one_or_none()
)
if candidate is None:
candidate = Candidate_DB(election_id=election_id, user_id=me.id)
db.add(candidate)
db.commit()
db.refresh(candidate)

election_post = (
db.query(ElectionPost_DB)
.filter(ElectionPost_DB.election_id == election_id, ElectionPost_DB.post_id == post_id)
.one_or_none()
)
if election_post is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invalid post_id ({post_id}) for this election.",
)

existing_candidation = (
db.query(Candidation_DB)
.filter(
Candidation_DB.candidate_id == candidate.candidate_id,
Candidation_DB.election_post_id == election_post.election_post_id,
)
.one_or_none()
)
if existing_candidation:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="This candidate is already associated with the specified post.",
)

new_candidation = Candidation_DB(
candidate_id=candidate.candidate_id, election_post_id=election_post.election_post_id
)
db.add(new_candidation)
db.commit()

return candidate
3 changes: 1 addition & 2 deletions routes/election_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

@election_router.get("/", response_model=list[ElectionRead], dependencies=[Permission.require("manage", "Election")])
def get_all_elections(db: DB_dependency):
# return fix_election_reads(db.query(Election_DB).all())
return db.query(Election_DB).all()


Expand All @@ -28,7 +27,7 @@ def get_election(election_id: int, db: DB_dependency):
@election_router.post("/", response_model=ElectionRead, dependencies=[Permission.require("manage", "Election")])
def create_election(data: ElectionCreate, db: DB_dependency):
if data.end_time < data.start_time:
raise HTTPException(status.HTTP_400_BAD_REQUEST)
raise HTTPException(status.HTTP_400_BAD_REQUEST, "Starttime is after endtime")
election = Election_DB(
title=data.title, start_time=data.start_time, end_time=data.end_time, description=data.description
)
Expand Down
2 changes: 2 additions & 0 deletions seed.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ def seed_permissions(db: Session, posts: list[Post_DB]):
perm8 = Permission_DB(action="manage", target="Ads")
perm9 = Permission_DB(action="manage", target="Car")
perm10 = Permission_DB(action="manage", target="Election")
perm11 = Permission_DB(action="manage", target="Cafe")
posts[0].permissions.append(perm1)
posts[0].permissions.append(perm2)
posts[1].permissions.append(perm3)
Expand All @@ -158,6 +159,7 @@ def seed_permissions(db: Session, posts: list[Post_DB]):
posts[0].permissions.append(perm8)
posts[0].permissions.append(perm9)
posts[0].permissions.append(perm10)
posts[1].permissions.append(perm11)
db.commit()


Expand Down