-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/volunteer_management_lifecycle #62
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
Merged
Changes from 6 commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
e0fc09b
feat(vol): fix docker compose
RaymondC-tech c56060d
fix(vol): item array bug
RaymondC-tech 01113bc
fix(vol): api call volunteer application + volunteer approval
RaymondC-tech 8febba7
feat(vol): backend volunteer expiry logic + tests
RaymondC-tech 24bc4ad
feat(vol): frontend modal + updated function call + change text to be…
RaymondC-tech 0d67fbf
edit(vol): update frontend tests
RaymondC-tech 9e8704b
fix(vol): added additional check for volunteer
RaymondC-tech 893d33a
fix(vol): updated patch call with added admin permissions
RaymondC-tech e684808
fix(vol): volunteer application number to total volunteers
RaymondC-tech 7c70063
fix(vol): standardize date formats frontend and backend
RaymondC-tech 17278ba
fix(vol): error handling for invalid datetime format
RaymondC-tech 2b94170
fix(vol): fix N + 1 query issue
RaymondC-tech 78cc270
fix(vol): formattig issues
RaymondC-tech File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| .vscode | ||
| .vscode | ||
| .env |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -297,3 +297,145 @@ def test_expired_user_blocked_by_middleware(client): | |
|
|
||
| res_expired = client.get("/api/users/", HTTP_AUTHORIZATION=f"Bearer {token}") | ||
| assert res_expired.status_code == status.HTTP_403_FORBIDDEN | ||
|
|
||
|
|
||
| # --- New tests for volunteer lifecycle --- | ||
|
|
||
|
|
||
| @pytest.mark.django_db | ||
| def test_approve_application_sets_expiry(): | ||
| """Approving an application with access_expires_at creates the user with that expiry.""" | ||
| client = Client() | ||
|
|
||
| application = VolunteerApplication.objects.create( | ||
| name="Expiry Volunteer", | ||
| email="[email protected]", | ||
| motivation_text="I want to help", | ||
| status="PENDING", | ||
| ) | ||
|
|
||
| expires = (timezone.now() + timedelta(days=30)).replace(microsecond=0) | ||
| url = f"/api/users/volunteer-applications/{application.id}/" | ||
| response = client.patch( | ||
| url, | ||
| {"status": "APPROVED", "access_expires_at": expires.isoformat()}, | ||
| content_type="application/json", | ||
| ) | ||
| assert response.status_code in (200, 202) | ||
|
|
||
| user = User.objects.get(email="[email protected]") | ||
| assert user.role == "VOLUNTEER" | ||
| assert user.access_expires_at is not None | ||
| assert abs((user.access_expires_at - expires).total_seconds()) < 2 | ||
|
|
||
|
|
||
| @pytest.mark.django_db | ||
| def test_approve_application_no_expiry(): | ||
| """Approving an application without access_expires_at creates user with no expiry.""" | ||
| client = Client() | ||
|
|
||
| application = VolunteerApplication.objects.create( | ||
| name="No Expiry Vol", | ||
| email="[email protected]", | ||
| motivation_text="Happy to help", | ||
| status="PENDING", | ||
| ) | ||
|
|
||
| url = f"/api/users/volunteer-applications/{application.id}/" | ||
| response = client.patch(url, {"status": "APPROVED"}, content_type="application/json") | ||
| assert response.status_code in (200, 202) | ||
|
|
||
| user = User.objects.get(email="[email protected]") | ||
| assert user.role == "VOLUNTEER" | ||
| assert user.access_expires_at is None | ||
|
|
||
|
|
||
| @pytest.mark.django_db | ||
| def test_reapprove_application_updates_expiry(): | ||
| """Re-approving an application for an existing user updates their access_expires_at.""" | ||
| client = Client() | ||
|
|
||
| existing_user = User.objects.create_user( | ||
| email="[email protected]", | ||
| name="Existing Vol", | ||
| password="pass", | ||
| role="VOLUNTEER", | ||
| access_expires_at=timezone.now() + timedelta(days=5), | ||
| ) | ||
|
|
||
| application = VolunteerApplication.objects.create( | ||
| name="Existing Vol", | ||
| email="[email protected]", | ||
| motivation_text="Previously approved", | ||
| status="PENDING", | ||
| ) | ||
|
|
||
| new_expires = (timezone.now() + timedelta(days=60)).replace(microsecond=0) | ||
| url = f"/api/users/volunteer-applications/{application.id}/" | ||
| response = client.patch( | ||
| url, | ||
| {"status": "APPROVED", "access_expires_at": new_expires.isoformat()}, | ||
| content_type="application/json", | ||
| ) | ||
| assert response.status_code in (200, 202) | ||
|
|
||
| existing_user.refresh_from_db() | ||
| assert abs((existing_user.access_expires_at - new_expires).total_seconds()) < 2 | ||
|
|
||
|
|
||
| @pytest.mark.django_db | ||
| def test_volunteer_applications_list_enriched_with_user_data(client): | ||
| """Approved applications in the list endpoint include user_id, expires_at, days_remaining.""" | ||
| admin = User.objects.create_user(email="[email protected]", name="Admin", password="adminpass", role="ADMIN") | ||
|
|
||
| expires = timezone.now() + timedelta(days=10) | ||
| volunteer_user = User.objects.create_user( | ||
| email="[email protected]", | ||
| name="List Vol", | ||
| password="pass", | ||
| role="VOLUNTEER", | ||
| access_expires_at=expires, | ||
| ) | ||
| VolunteerApplication.objects.create( | ||
| name="List Vol", | ||
| email="[email protected]", | ||
| motivation_text="Help", | ||
| status="APPROVED", | ||
| ) | ||
|
|
||
| res_login = client.post( | ||
| "/api/auth/login/", | ||
| {"email": "[email protected]", "password": "adminpass"}, | ||
| content_type="application/json", | ||
| ) | ||
| token = res_login.data["access"] | ||
|
|
||
| res = client.get("/api/users/volunteer-applications/", HTTP_AUTHORIZATION=f"Bearer {token}") | ||
| assert res.status_code == 200 | ||
|
|
||
| data = res.json() | ||
| items = data.get("results", data) if isinstance(data, dict) else data | ||
| approved = [i for i in items if i.get("status") == "APPROVED" and i.get("email") == "[email protected]"] | ||
| assert len(approved) == 1 | ||
| row = approved[0] | ||
| assert row["user_id"] == volunteer_user.id | ||
| assert row["expires_at"] is not None | ||
| assert row["days_remaining"] is not None | ||
| assert 9 <= row["days_remaining"] <= 10 | ||
|
|
||
|
|
||
| @pytest.mark.django_db | ||
| def test_volunteer_stats_includes_warning_days(client): | ||
| """The volunteer-stats endpoint returns warning_days: 7.""" | ||
| admin = User.objects.create_user(email="[email protected]", name="Admin", password="adminpass", role="ADMIN") | ||
|
|
||
| res_login = client.post( | ||
| "/api/auth/login/", | ||
| {"email": "[email protected]", "password": "adminpass"}, | ||
| content_type="application/json", | ||
| ) | ||
| token = res_login.data["access"] | ||
|
|
||
| res = client.get("/api/users/volunteer-stats/", HTTP_AUTHORIZATION=f"Bearer {token}") | ||
| assert res.status_code == 200 | ||
| assert res.json()["warning_days"] == 7 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,3 @@ | ||
| version: '3.8' | ||
|
|
||
| services: | ||
| backend: | ||
| build: ./backend | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.