diff --git a/backend/resources/hacknight.py b/backend/resources/hacknight.py index c68f245d..91cd82fe 100644 --- a/backend/resources/hacknight.py +++ b/backend/resources/hacknight.py @@ -8,17 +8,31 @@ from marshmallow import fields, Schema, ValidationError from backend.extensions import db -from backend.models import Hacknight, Participant -from backend.serializers.hacknight_serializer import HacknightSchema +from backend.models import Hacknight, Participant, participant_hacknight +from backend.serializers.hacknight_serializer import DateFilterSchema, HacknightSchema class HacknightList(Resource): @jwt_required def get(self): - hacknight_schema = HacknightSchema(many=True) + hacknight_schema = HacknightSchema( + many=True, only=("id", "date", "participants.id") + ) + date_filter_schema = DateFilterSchema(partial=True) + date_filter = date_filter_schema.load(request.args) + query = db.session.query(Hacknight) + + # Apply date filter if provided + if start_date := date_filter.get("start_date"): + query = query.filter(Hacknight.date >= start_date) + if end_date := date_filter.get("end_date"): + query = query.filter(Hacknight.date <= end_date) + return ( hacknight_schema.dump( - Hacknight.query.order_by(Hacknight.date.desc()).all() + query.join(participant_hacknight, isouter=True) + .order_by(Hacknight.date.desc()) + .all() ), HTTPStatus.OK, ) diff --git a/backend/serializers/hacknight_serializer.py b/backend/serializers/hacknight_serializer.py index f10621e4..9ff37bac 100644 --- a/backend/serializers/hacknight_serializer.py +++ b/backend/serializers/hacknight_serializer.py @@ -1,4 +1,4 @@ -from marshmallow import Schema, fields +from marshmallow import Schema, fields, pre_load class HacknightSchema(Schema): @@ -12,3 +12,13 @@ class Meta: "ParticipantSchema", exclude=("hacknights",), many=True ) date = fields.Date() + + +class DateFilterSchema(Schema): + start_date = fields.Date(data_key="startDate") + end_date = fields.Date(data_key="endDate") + + @pre_load + def remove_empty_value(self, data, many, **kwargs): + """Remove field whenever value is empty string.""" + return {key: value for key, value in data.items() if value} diff --git a/backend/tests/test_hacknight.py b/backend/tests/test_hacknight.py index 4aa23438..7a299af1 100644 --- a/backend/tests/test_hacknight.py +++ b/backend/tests/test_hacknight.py @@ -1,15 +1,50 @@ from http import HTTPStatus import json +import pytest +from datetime import date, timedelta + +from backend.factories import HacknightFactory from backend.models import Hacknight, Participant -def test_get_hacknights_when_logged_in(auth_client, add_hacknights): +def test_get_all_hacknights_when_logged_in( + auth_client, add_hacknights, add_participants_to_hacknight +): """Test get list of hacknights for logged in user.""" rv = auth_client.get("/api/hacknights/") response = rv.get_json() assert rv.status_code == HTTPStatus.OK assert len(response) == len(Hacknight.query.all()) + for hacknigt in response: + assert len(hacknigt["participants"]) == len( + Hacknight.query.get(hacknigt["id"]).participants + ) + + +@pytest.mark.parametrize( + "start_date,end_date", + [("2022-01-12", "2022-10-12"), ("2022-01-12", ""), ("", "2022-10-12")], +) +def test_get_hacknights_date_filter(auth_client, start_date, end_date): + """Test get list of hacknights with date filter applied.""" + expected_count = 0 + if start_date: + start_date_formatted = date.fromisoformat(start_date) + out_of_range = start_date_formatted - timedelta(days=1) + HacknightFactory.create(date=start_date_formatted) + HacknightFactory.create(date=out_of_range) + expected_count += 1 + if end_date: + end_date_formatted = date.fromisoformat(end_date) + out_of_range = end_date_formatted + timedelta(days=1) + HacknightFactory.create(date=end_date_formatted) + HacknightFactory.create(date=out_of_range) + expected_count += 1 + rv = auth_client.get(f"/api/hacknights/?startDate={start_date}&endDate={end_date}") + response = rv.get_json() + assert rv.status_code == HTTPStatus.OK + assert len(response) == expected_count def test_get_hacknights_with_empty_db(auth_client):