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 project status field based on task counts #271

Merged
merged 8 commits into from
Oct 8, 2024
28 changes: 24 additions & 4 deletions src/backend/app/projects/project_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,10 @@ async def one(db: Connection, project_id: uuid.UUID):
te.user_id,
CASE
WHEN te.state = 'REQUEST_FOR_MAPPING' THEN 'request logs'
WHEN te.state = 'LOCKED_FOR_MAPPING' THEN 'ongoing'
WHEN te.state = 'LOCKED_FOR_MAPPING' OR te.state = 'IMAGE_UPLOADED' THEN 'ongoing'
WHEN te.state = 'IMAGE_PROCESSED' THEN 'completed'
WHEN te.state = 'UNFLYABLE_TASK' THEN 'unflyable task'
ELSE 'UNLOCKED_TO_MAP'
ELSE ''
END AS calculated_state
FROM
task_events te
Expand All @@ -273,7 +273,7 @@ async def one(db: Connection, project_id: uuid.UUID):
ST_YMin(ST_Envelope(t.outline)) AS ymin,
ST_XMax(ST_Envelope(t.outline)) AS xmax,
ST_YMax(ST_Envelope(t.outline)) AS ymax,
COALESCE(tsc.calculated_state, 'UNLOCKED_TO_MAP') AS state,
COALESCE(tsc.calculated_state) AS state,
tsc.user_id,
u.name,
ST_Area(ST_Transform(t.outline, 3857)) / 1000000 AS task_area
Expand Down Expand Up @@ -341,7 +341,10 @@ async def all(
COUNT(t.id) AS total_task_count,

-- Count based on the latest state of tasks
COUNT(CASE WHEN te.state = 'LOCKED_FOR_MAPPING' THEN 1 END) AS ongoing_task_count
COUNT(CASE WHEN te.state = 'LOCKED_FOR_MAPPING' THEN 1 END) AS ongoing_task_count,

-- Count based on the latest state of tasks
COUNT(CASE WHEN te.state = 'IMAGE_PROCESSED' THEN 1 END) AS completed_task_count

FROM projects p
LEFT JOIN tasks t ON t.project_id = p.id
Expand Down Expand Up @@ -526,6 +529,8 @@ class ProjectInfo(BaseModel):
tasks: Optional[list[TaskOut]] = []
image_url: Optional[str] = None
ongoing_task_count: Optional[int] = 0
completed_task_count: Optional[int] = 0
status: Optional[str] = "not-started"

@model_validator(mode="after")
def set_image_url(cls, values):
Expand All @@ -537,6 +542,21 @@ def set_image_url(cls, values):
values.image_url = get_presigned_url(settings.S3_BUCKET_NAME, image_dir, 5)
return values

@model_validator(mode="after")
def calculate_status(cls, values):
"""Set the project status based on task counts."""
ongoing_task_count = values.ongoing_task_count
completed_task_count = values.completed_task_count

if ongoing_task_count == 0:
values.status = "not-started"
elif ongoing_task_count > 0 and ongoing_task_count != completed_task_count:
values.status = "ongoing"
elif ongoing_task_count == completed_task_count:
values.status = "completed"

return values


class ProjectOut(BaseModel):
"""Base project model."""
Expand Down
4 changes: 2 additions & 2 deletions src/backend/app/tasks/task_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ async def get_tasks_by_user(
task_events.updated_at,
CASE
WHEN task_events.state = 'REQUEST_FOR_MAPPING' THEN 'request logs'
WHEN task_events.state = 'LOCKED_FOR_MAPPING' THEN 'ongoing'
WHEN task_events.state = 'LOCKED_FOR_MAPPING' OR task_events.state = 'IMAGE_UPLOADED' THEN 'ongoing'
WHEN task_events.state = 'IMAGE_PROCESSED' THEN 'completed'
WHEN task_events.state = 'UNFLYABLE_TASK' THEN 'unflyable task'
ELSE 'UNLOCKED_TO_MAP'
ELSE ''
END AS state
FROM
task_events
Expand Down