From 25ff221f864aa65f8286ccbf790b99cd4bd59390 Mon Sep 17 00:00:00 2001 From: Niraj Adhikari Date: Mon, 8 Jul 2024 10:57:46 +0545 Subject: [PATCH] update: task events for finish mapping --- src/backend/app/tasks/task_crud.py | 99 ++++++++++++++++++++++----- src/backend/app/tasks/task_routes.py | 71 +++++++++---------- src/backend/app/tasks/task_schemas.py | 1 + 3 files changed, 115 insertions(+), 56 deletions(-) diff --git a/src/backend/app/tasks/task_crud.py b/src/backend/app/tasks/task_crud.py index dccd364a..a6d1d828 100644 --- a/src/backend/app/tasks/task_crud.py +++ b/src/backend/app/tasks/task_crud.py @@ -1,5 +1,4 @@ import uuid -from app.models.enums import State from databases import Database @@ -8,22 +7,87 @@ async def all_tasks_states(db: Database, project_id: uuid.UUID): SELECT DISTINCT ON (task_id) project_id, task_id, state FROM task_events WHERE project_id=:project_id + ORDER BY task_id, created_at DESC """ r = await db.fetch_all(query, {"project_id": str(project_id)}) return [dict(r) for r in r] -async def update_task_event( - db: Database, - project_id: uuid.UUID, - user_id: str, - task_id: uuid.UUID, - state: State, -) -> None: - event_id = str(uuid.uuid4()) - comment = "comment" +async def map_task( + db: Database, project_id: uuid.UUID, task_id: uuid.UUID, user_id: str, comment: str +): + query = """ + WITH latest_events AS ( + SELECT DISTINCT ON (task_id) + project_id, + task_id, + user_id, + comment, + state + FROM task_events + WHERE project_id = :project_id + ORDER BY task_id, created_at DESC + ), + valid_tasks AS ( + SELECT * + FROM latest_events + WHERE state = :unlocked_to_map_state + ), + missing_task AS ( + SELECT + CAST(:project_id AS UUID) AS project_id, + CAST(:task_id AS UUID) AS task_id, + :user_id AS user_id, + :comment AS comment, + CAST(:locked_for_mapping_state AS State) AS state + WHERE NOT EXISTS ( + SELECT 1 + FROM task_events + WHERE project_id = :project_id + AND task_id = :task_id + ) + ) + INSERT INTO task_events (event_id, project_id, task_id, user_id, comment, state, created_at) + SELECT + gen_random_uuid(), + project_id, + task_id, + user_id, + comment, + state, + now() + FROM valid_tasks + UNION ALL + SELECT + gen_random_uuid(), + project_id, + task_id, + user_id, + comment, + state, + now() + FROM missing_task + RETURNING project_id, task_id, user_id; + """ + values = { + "project_id": str(project_id), + "task_id": str(task_id), + "user_id": str(user_id), + "comment": comment, + "unlocked_to_map_state": "UNLOCKED_TO_MAP", + "locked_for_mapping_state": "LOCKED_FOR_MAPPING", + } + + await db.fetch_one(query, values) + + return {"project_id": project_id, "task_id": task_id} + + +async def finish( + db: Database, project_id: uuid.UUID, task_id: uuid.UUID, user_id: str, comment: str +): query = """ WITH last AS ( SELECT * @@ -35,22 +99,22 @@ async def update_task_event( locked AS ( SELECT * FROM last - WHERE user_id = :user_id AND state = :state + WHERE user_id = :user_id AND state = :locked_for_mapping_state ) - INSERT INTO public.task_events(event_id, project_id, task_id, user_id, state, comment, created_at) - SELECT :event_id, project_id, task_id, user_id, :state, :comment, now() + INSERT INTO task_events(event_id, project_id, task_id, user_id, state, comment, created_at) + SELECT gen_random_uuid(), project_id, task_id, user_id, :unlocked_to_validate_state, :comment, now() FROM last WHERE user_id = :user_id RETURNING project_id, task_id, user_id; - """ + """ values = { "project_id": str(project_id), "task_id": str(task_id), "user_id": str(user_id), - "state": str(state.name), - "event_id": event_id, "comment": comment, + "unlocked_to_validate_state": "UNLOCKED_TO_VALIDATE", + "locked_for_mapping_state": "LOCKED_FOR_MAPPING", } r = await db.fetch_one(query, values) @@ -59,5 +123,4 @@ async def update_task_event( assert r["project_id"] == project_id assert r["task_id"] == task_id assert r["user_id"] == user_id - - return None + return r diff --git a/src/backend/app/tasks/task_routes.py b/src/backend/app/tasks/task_routes.py index 064f590e..ebe78d2a 100644 --- a/src/backend/app/tasks/task_routes.py +++ b/src/backend/app/tasks/task_routes.py @@ -5,7 +5,6 @@ from app.tasks import task_schemas, task_crud from app.users.user_deps import login_required from app.users.user_schemas import AuthUser -from app.models.enums import State from databases import Database from app.db import database @@ -17,49 +16,45 @@ ) -@router.post("/project/{project_id}/event") +@router.get("/states/{project_id}") +async def task_states( + project_id: uuid.UUID, db: Database = Depends(database.encode_db) +): + """Get all tasks states for a project.""" + + return await task_crud.all_tasks_states(db, project_id) + + +@router.post("/update-event/") async def new_event( - project_id: uuid.UUID, detail: task_schemas.NewEvent, user_data: AuthUser = Depends(login_required), db: Database = Depends(database.encode_db), ): user_id = user_data.id - # Event state mappings - event_state_mapping = { - "map": State.LOCKED_FOR_MAPPING, - "finish": State.UNLOCKED_TO_VALIDATE, - "validate": State.LOCKED_FOR_VALIDATION, - "good": State.UNLOCKED_DONE, - "bad": State.UNLOCKED_TO_MAP, - "split": State.UNLOCKED_DONE, - "assign": State.LOCKED_FOR_MAPPING, - "comment": None, # Comment should keep the same state - } - - # Get the current state based on the event - if detail.event in event_state_mapping: - state = event_state_mapping[detail.event] - else: - raise ValueError("Invalid event type") - - # If the event is a comment, we need to get the current state from the last event - if detail.event == EventType.COMMENT: - last_event_query = """ - SELECT state - FROM task_events - WHERE project_id = :project_id AND task_id = :task_id - ORDER BY event_id DESC - LIMIT 1; - """ - last_event = await db.fetch_one( - last_event_query, {"project_id": project_id, "task_id": detail.task_id} - ) - if last_event is None: - raise ValueError("No previous event found for this project and task.") - state = last_event["state"] - - await task_crud.update_task_event(db, project_id, user_id, detail.task_id, state) + match detail.event: + case EventType.MAP: + await task_crud.map_task( + db, + detail.project_id, + detail.task_id, + user_id, + "Done: locked for mapping", + ) + case EventType.FINISH: + await task_crud.finish( + db, + detail.project_id, + detail.task_id, + user_id, + "Done: unlocked to validate", + ) + case EventType.VALIDATE: + pass + case EventType.GOOD: + pass + case EventType.BAD: + pass return True diff --git a/src/backend/app/tasks/task_schemas.py b/src/backend/app/tasks/task_schemas.py index 147705d2..967d9b52 100644 --- a/src/backend/app/tasks/task_schemas.py +++ b/src/backend/app/tasks/task_schemas.py @@ -5,4 +5,5 @@ class NewEvent(BaseModel): event: EventType + project_id: uuid.UUID task_id: uuid.UUID