Celts User Profile, Wrong label for event participation type
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 68/100
Research direction
Start with the affected-record SQL query using the event name and isAllVolunteerTraining flag, then review each result to confirm it is truly an all-volunteer training. Update both flags for confirmed records and reload Julius Fritz's Participation History; the event should no longer appear there.
Written by the indexing model from the issue text.
Description
Bug: Manually-created "All Volunteer Training" events are typed as Volunteer and display service hours on Participation History
Summary
Some events named "All Volunteer Training" were created through the generic Create Event form instead of the All Volunteer Training shortcut. Those events were saved without the training flag set, and with the service flag set instead.
Because of that, the Participation History table treats them as ordinary volunteer service events, gives them a participation type of Volunteer, and displays service hours next to them. Students who attended a training therefore appear to have earned service hours they should not have.
This is a data problem with a display symptom. The query and template logic are behaving as designed. They are being fed events whose flags describe them incorrectly.
Expected behavior
An "All Volunteer Training" event should be stored with:
| Column | Expected value |
|---|---|
| isAllVolunteerTraining | 1 |
| isService | 0 |
Those events pass through the filter, get labeled Volunteer, and render service hours.
Steps to reproduce
1. Sign in to CELTS as an admin. You should land on the admin home page.
<2. Go to the Student Search page. Search for Fritzj2 and click on Julius Fritz.
3. Click Participation History.
<4. Find the row named All Volunteer Training. Its Participation Type reads Volunteer and its Service Hours column is populated, rather than the event being excluded from this table.
Root cause
How the event got into this state
Events are added through Create Event.
<There is an All Volunteer Training shortcut at the top of that form. Selecting it applies the correct flags automatically.
<In several past cases the shortcut was not used. The event was instead created manually, typed in by name, and attached under an unrelated program. Nothing in the form requires the training flag to be set, so the record was saved as a regular service event that merely happens to be named "All Volunteer Training".
<Why the wrong flags produce this specific output
For anyone new to this part of the codebase, two pieces of logic matter.
First, the filter. The Participation History query excludes training events with this condition in its where clause:
Event.isAllVolunteerTraining == False
An event with isAllVolunteerTraining = 0 is not excluded by that condition, so it stays in the result set.
Second, the label. Participation Type is not a stored column. It is computed in SQL by a Case expression in the select, which checks the event's flags in order and returns the first match:
Case(None, (
((Event.isLaborOnly | Event.name.contains("Labor")) & Event.isService, "Labor & Volunteer"),
((Event.isLaborOnly | Event.name.contains("Labor")), "Labor"),
(Event.isService, "Volunteer")), "Attendee").alias("participatedType")
An event with isService = 1 falls into the third branch and is labeled Volunteer.
The template then shows hours only for rows whose type contains Volunteer:
{% if 'Volunteer' in event.participatedType %}
<td>{{ ... hoursEarned ... }}</td>
{% else %}
<td>N/A</td>
{% endif %}
So a single wrong flag at creation time cascades into a wrong label and a wrong hours display. Correctly-created training events have isService = 0, fall through to the "Attendee" default, and would show N/A even if the filter somehow missed them. That is the double protection the affected records are missing.
Evidence from the database
SELECT id, name, isAllVolunteerTraining, isService
FROM event
WHERE name LIKE '%All Volunteer%';
Most rows are correct:
| id | name | isAllVolunteerTraining | isService |
| 2 | All Volunteer Training | 1 | 0 |
| 13 | All Volunteer Training | 1 | 0 |
| 98 | All Volunteer Training | 1 | 0 |
| ... | | | |
A subset is not:
| 703 | All Volunteer Training | 0 | 0 |
| 704 | All Volunteer Training | 0 | 0 |
| 706 | All Volunteer Training | 0 | 0 |
And at least one has the service flag set, which is the record surfacing in the screenshots above (event dated 09/04/2025). The full affected set can be listed with:
SELECT id, name, startDate, isAllVolunteerTraining, isService
FROM event
WHERE name LIKE '%All Volunteer%'
AND isAllVolunteerTraining = 0;
Suggested fix
1. Identify the affected records. Run the query above and review each row by hand before changing anything. The name match is a substring search, so confirm each result really is an all-volunteer training and not a differently-scoped event that happens to share wording.
2. Correct the flags. For the confirmed rows:
UPDATE event
SET isAllVolunteerTraining = 1,
isService = 0
WHERE id IN ( ... );
Both columns need updating. Setting only isAllVolunteerTraining removes the row from Participation History but leaves isService = 1, which means the event still counts toward service hour totals anywhere else in the application that aggregates on that flag.
3. Verify. Reload Julius Fritz's Participation History. The All Volunteer Training row should no longer appear.
Follow-up worth opening separately
This will recur. Nothing in the Create Event form prevents an admin from typing "All Volunteer Training" into a regular event, so the same cleanup will be needed again next time it happens.
Two possible directions, either of which deserves its own issue rather than being bundled here:
- Validation or a warning on the Create Event form when the name matches an all-volunteer training but the shortcut was not used.
- Reconsidering whether
isAllVolunteerTrainingandisServiceneed to be maintained as two independent flags, given that they encode overlapping information and have already drifted apart on several records.
Related
- #805
- Dominant language
- Python
- Stars
- 1
- Forks
- 15
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 5
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from BCStudentSoftwareDevTeam/celts
-
Drop down placementPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
BCStudentSoftwareDevTeam/celts#1817 ·
Maintainers usually reply within 1 day
-
Rename second All buttonPossibly taken @Avinash-006 claimed this 3 days ago. Open
Difficulty 1/5 Under an hour Newbie friendliness 85/100
BCStudentSoftwareDevTeam/celts#1816 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
BCStudentSoftwareDevTeam/celts#1806 ·
Maintainers usually reply within 1 day
-
Add Required Field AsterisksPossibly taken @Avinash-006 claimed this 3 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
BCStudentSoftwareDevTeam/celts#1785 ·
Maintainers usually reply within 1 day
-
Incorrectly Displayed Buttons on the Course Management PagePossibly taken @Avinash-006 claimed this 3 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
BCStudentSoftwareDevTeam/celts#1733 ·
Maintainers usually reply within 1 day
All issues in BCStudentSoftwareDevTeam/celts
Similar issues
-
json_params_matcher fails on falsy top-level JSON primitives (0, False, "")Possibly taken @mayureshsonawane17 claimed this today. OpenWaiting for: Product Owner
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Maintainers usually reply within 5 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
bojieli/ai-agent-book#1169 ·
Maintainers usually reply within 1 day
-
priority:low ready-for-dev
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
OpenHands/extensions#738 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
micronaut-projects/micronaut-core#13677 ·
Maintainers usually reply within 1 day