Skip to content

Commit

Permalink
feat: correct get meta, update class, new class
Browse files Browse the repository at this point in the history
  • Loading branch information
tiptenbrink committed Jan 3, 2024
1 parent 3cdee22 commit 217f5be
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 28 deletions.
41 changes: 26 additions & 15 deletions backend/src/apiserver/app/routers/ranking.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@
from apiserver.data.context.ranking import (
add_new_event,
add_new_training,
context_modify_class,
context_most_recent_class_points,
context_new_classes,
most_recent_classes,
sync_publish_ranking,
)
from apiserver.lib.logic.ranking import is_rank_type
from apiserver.lib.model.entities import (
ClassEvent,
ClassMetaList,
ClassUpdate,
ClassView,
NewEvent,
NewTrainingEvent,
RankingInfo,
Expand Down Expand Up @@ -98,22 +104,13 @@ async def get_classification_with_meta(
return RawJSONResponse(RankingInfo.model_dump_json(ranking_info).encode())


@ranking_members_router.get("/get_meta/{rank_type}/", response_model=RankingInfo)
async def member_classification_meta(
rank_type: str, dsrc: SourceDep, app_context: AppContext
@ranking_admin_router.get("/get_meta/{recent_number}/", response_model=list[ClassView])
async def get_classifications(
recent_number: int, dsrc: SourceDep, app_context: AppContext
) -> RawJSONResponse:
return await get_classification_with_meta(
dsrc, app_context.rank_ctx, rank_type, False
)


@ranking_admin_router.get("/get_meta/{rank_type}/", response_model=RankingInfo)
async def member_classification_admin_meta(
rank_type: str, dsrc: SourceDep, app_context: AppContext
) -> RawJSONResponse:
return await get_classification_with_meta(
dsrc, app_context.rank_ctx, rank_type, True
)
recent_classes = await most_recent_classes(app_context.rank_ctx, dsrc, recent_number)

return RawJSONResponse(ClassMetaList.dump_json(recent_classes))


@ranking_members_router.get("/get/{rank_type}/", response_model=list[UserPointsNames])
Expand Down Expand Up @@ -205,3 +202,17 @@ async def get_event_users(
)

return RawJSONResponse(UserPointsNamesList.dump_json(event_users))


@ranking_admin_router.post("/new/")
async def new_classes(
dsrc: SourceDep, app_context: AppContext,
) -> None:
await context_new_classes(app_context.rank_ctx, dsrc)


@ranking_admin_router.post("/modify/")
async def modify_class(
updated_class: ClassUpdate, dsrc: SourceDep, app_context: AppContext,
) -> None:
await context_modify_class(app_context.rank_ctx, dsrc, updated_class)
22 changes: 17 additions & 5 deletions backend/src/apiserver/data/api/classifications.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from datetime import date, timedelta
from typing import Literal
from schema.model.model import CLASS_END_DATE

from sqlalchemy import RowMapping
from sqlalchemy.ext.asyncio import AsyncConnection

from apiserver.lib.model.entities import (
ClassEvent,
ClassMeta,
ClassMetaList,
ClassUpdate,
Classification,
ClassView,
EventDate,
Expand Down Expand Up @@ -46,7 +50,9 @@
lit_model,
select_some_join_where,
select_some_where,
update_by_unique,
update_column_by_unique,
upsert_by_unique,
)
from store.error import DataError, NoDataError, DbError, DbErrors

Expand Down Expand Up @@ -75,8 +81,8 @@ async def insert_classification(


async def most_recent_class_of_type(
conn: AsyncConnection, class_type: Literal["training", "points"]
) -> ClassView:
conn: AsyncConnection, class_type: Literal["training", "points"], amount: int = 1
) -> list[ClassMeta]:
if class_type == "training":
query_class_type = "training"
elif class_type == "points":
Expand All @@ -90,19 +96,19 @@ async def most_recent_class_of_type(
largest_class_list = await get_largest_where(
conn,
CLASSIFICATION_TABLE,
{CLASS_ID, CLASS_LAST_UPDATED, CLASS_START_DATE, CLASS_HIDDEN_DATE},
{CLASS_ID, CLASS_LAST_UPDATED, CLASS_START_DATE, CLASS_HIDDEN_DATE, CLASS_END_DATE},
CLASS_TYPE,
query_class_type,
CLASS_START_DATE,
1,
amount,
)
if len(largest_class_list) == 0:
raise NoDataError(
"No most recent training classification found!",
"no_most_recent_training_class",
)

return ClassView.model_validate(largest_class_list[0])
return ClassMetaList.validate_python(largest_class_list)


async def all_points_in_class(
Expand Down Expand Up @@ -260,3 +266,9 @@ async def class_update_last_updated(
return await update_column_by_unique(
conn, CLASSIFICATION_TABLE, CLASS_LAST_UPDATED, date, CLASS_ID, class_id
)

async def update_classification(
conn: AsyncConnection, class_view: ClassUpdate
) -> None:

await update_by_unique(conn, CLASSIFICATION_TABLE, lit_model(class_view), "classification_id", class_view.classification_id)
21 changes: 21 additions & 0 deletions backend/src/apiserver/data/context/app_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
from apiserver.data import Source
from apiserver.lib.model.entities import (
ClassEvent,
ClassMeta,
ClassUpdate,
ClassView,
NewEvent,
RankingInfo,
UserData,
Expand Down Expand Up @@ -101,6 +104,24 @@ async def context_get_event_users(
cls, dsrc: Source, event_id: str
) -> list[UserPointsNames]:
raise ContextNotImpl()

@classmethod
async def most_recent_classes(
cls, dsrc: Source, amount: int = 10
) -> list[ClassMeta]:
raise ContextNotImpl()

@classmethod
async def context_new_classes(
cls, dsrc: Source
) -> None:
raise ContextNotImpl()

@classmethod
async def context_modify_class(
cls, dsrc: Source, class_update: ClassUpdate
) -> None:
raise ContextNotImpl()


class AuthorizeAppContext(Context):
Expand Down
51 changes: 45 additions & 6 deletions backend/src/apiserver/data/context/ranking.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

from apiserver.lib.model.entities import (
ClassEvent,
ClassMeta,
ClassUpdate,
ClassView,
NewEvent,
NewTrainingEvent,
Expand All @@ -25,7 +27,9 @@
class_update_last_updated,
events_in_class,
get_event_user_points,
insert_classification,
most_recent_class_of_type,
update_classification,
)
from apiserver.data.context import RankingContext
from apiserver.data.source import get_conn
Expand All @@ -49,7 +53,7 @@ async def add_new_event(dsrc: Source, new_event: NewEvent) -> None:
date. Use the 'publish' function to force them to be equal."""
async with get_conn(dsrc) as conn:
try:
classification = await most_recent_class_of_type(conn, new_event.class_type)
classification = (await most_recent_class_of_type(conn, new_event.class_type))[0]
except DataError as e:
if e.key != "incorrect_class_type":
raise e
Expand Down Expand Up @@ -135,17 +139,17 @@ async def context_most_recent_class_id_of_type(
dsrc: Source, rank_type: Literal["points", "training"]
) -> int:
async with get_conn(dsrc) as conn:
class_id = (await most_recent_class_of_type(conn, rank_type)).classification_id
class_id = (await most_recent_class_of_type(conn, rank_type))[0].classification_id

return class_id


@ctx_reg.register(RankingContext)
async def context_most_recent_class_points(
dsrc: Source, rank_type: Literal["points", "training"], is_admin: bool
dsrc: Source, rank_type: Literal["points", "training"], is_admin: bool,
) -> RankingInfo:
async with get_conn(dsrc) as conn:
class_view = await most_recent_class_of_type(conn, rank_type)
class_view = (await most_recent_class_of_type(conn, rank_type))[0]
user_points = await all_points_in_class(
conn, class_view.classification_id, is_admin
)
Expand All @@ -161,8 +165,8 @@ async def context_most_recent_class_points(
@ctx_reg.register(RankingContext)
async def sync_publish_ranking(dsrc: Source, publish: bool) -> None:
async with get_conn(dsrc) as conn:
training_class = await most_recent_class_of_type(conn, "training")
points_class = await most_recent_class_of_type(conn, "points")
training_class = (await most_recent_class_of_type(conn, "training"))[0]
points_class = (await most_recent_class_of_type(conn, "points"))[0]
await update_class_points(conn, training_class.classification_id, publish)
await update_class_points(conn, points_class.classification_id, publish)

Expand Down Expand Up @@ -192,3 +196,38 @@ async def context_get_event_users(dsrc: Source, event_id: str) -> list[UserPoint
events_points = await get_event_user_points(conn, event_id)

return events_points


@ctx_reg.register(RankingContext)
async def most_recent_classes(
dsrc: Source, amount: int = 10
) -> list[ClassMeta]:
if amount < 2 or amount % 2 != 0:
raise AppError(
ErrorKeys.DATA,
"Request at least 2 classes and make sure it is an even number!",
"most_recent_too_few",
)

async with get_conn(dsrc) as conn:
training_classes = (await most_recent_class_of_type(conn, "training", amount // 2))
points_classes = (await most_recent_class_of_type(conn, "points", amount // 2))

return training_classes + points_classes


@ctx_reg.register(RankingContext)
async def context_new_classes(
dsrc: Source
) -> None:
async with get_conn(dsrc) as conn:
await insert_classification(conn, "training")
await insert_classification(conn, "points")


@ctx_reg.register(RankingContext)
async def context_modify_class(
dsrc: Source, class_update: ClassUpdate
) -> None:
async with get_conn(dsrc) as conn:
await update_classification(conn, class_update)
13 changes: 13 additions & 0 deletions backend/src/apiserver/lib/model/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,16 @@ class NewTrainingEvent(BaseModel):

class EventDate(BaseModel):
date: date


class ClassMeta(ClassView):
end_date: date


class ClassUpdate(BaseModel):
classification_id: int
start_date: date
hidden_date: date
end_date: date

ClassMetaList = TypeAdapter(List[ClassMeta])
21 changes: 21 additions & 0 deletions backend/src/store/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,27 @@ async def upsert_by_unique(
return row_cnt(res)


async def update_by_unique(
conn: AsyncConnection,
table: LiteralString,
set_dict: LiteralDict,
unique_column: LiteralString,
value: Any,
) -> int:
"""Note that while the values are safe from injection, the column names are not."""

_, _, row_keys_set = _row_keys_vars_set(set_dict)

query = text(
f"UPDATE {table} SET {row_keys_set} WHERE {unique_column} = :val;"
)
val_dict: LiteralDict = {"val": value}
params = set_dict | val_dict

res = await execute_catch(conn, query, parameters=params)
return row_cnt(res)


async def update_column_by_unique(
conn: AsyncConnection,
table: LiteralString,
Expand Down
4 changes: 2 additions & 2 deletions dev.nu
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def pull [envnmt: string, env_file: string, profile: string] {
}

def up [envnmt: string, env_file: string, profile: string] {
pull $envnmt $env_file $profile
# pull $envnmt $env_file $profile
docker compose -f $"($deploy_dir)/use/($envnmt)/docker-compose.yml" --env-file $"($deploy_dir)/use/($envnmt)/($env_file).env" --profile $profile up -d
}

Expand Down Expand Up @@ -49,4 +49,4 @@ def "main backend" [] {
# important for the command to be exposed to the outside

# Useful development commands for starting and stopping databases
def main [] {}
def main [] {}

0 comments on commit 217f5be

Please sign in to comment.