feat: automated seminar invitations#4968
Open
CLC0609 wants to merge 6 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Implements the initial “automated seminar invitations” workflow (TECH-329 groundwork) by introducing training seminars, invitations, attendee tracking, CTS group session syncing, and a scheduled expiry process, surfaced through a new Filament Training “Seminars” resource and member-facing invitation response pages.
Changes:
- Added Seminar/Invitation/Attendee domain models, migrations, factories, and services to send/track invitations and create attendees.
- Added member routes + controller + Blade views for accepting/declining seminar invitations, plus an expiry command scheduled daily.
- Added CTS sync support (group session + students) via a service and observers, with corresponding tests and CTS test DB schema additions.
Reviewed changes
Copilot reviewed 43 out of 43 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/Training/Seminar/SeminarInvitationServiceTest.php | Unit coverage for invitation sending/accept/decline/expiry behaviors. |
| tests/Unit/Training/Seminar/SeminarCtsSyncServiceTest.php | Unit coverage for syncing seminars/attendees into CTS tables. |
| tests/Feature/Training/Seminar/SeminarInvitationControllerTest.php | Feature coverage for member invitation response endpoints and authorization. |
| tests/Feature/Training/Seminar/CheckForExpiredSeminarInvitationsCommandTest.php | Feature coverage for the scheduled expiry command behavior. |
| tests/Database/MockCtsDatabase.php | Extends mocked CTS schema to include group session tables used by the sync service. |
| routes/web-main.php | Adds member routes for seminar invitation accept/decline actions by token. |
| resources/views/training/seminar-invitation/result.blade.php | Member-facing result page for accept/decline flows. |
| resources/views/training/seminar-invitation/expired.blade.php | Member-facing page for expired/invalid/non-respondable invitations. |
| resources/views/emails/training/seminar_invitation.blade.php | Email template for seminar invitations with response links. |
| database/seeders/RolesAndPermissionsSeeder.php | Adds permissions for viewing/managing seminars in Filament. |
| database/migrations/2026_07_02_100020_create_training_seminar_attendees_table.php | Creates attendee table (incl. CTS student ID back-reference). |
| database/migrations/2026_07_02_100010_create_training_seminar_invitations_table.php | Creates invitations table with token + status + expiry fields. |
| database/migrations/2026_07_02_100000_create_training_seminars_table.php | Creates seminars table with capacity, expiry window, and CTS session ID. |
| database/factories/Training/Seminar/SeminarInvitationFactory.php | Factory + states for invitations used in tests. |
| database/factories/Training/Seminar/SeminarFactory.php | Factory + states for seminars (closed/automatic/past/CTS session). |
| database/factories/Training/Seminar/SeminarAttendeeFactory.php | Factory for seminar attendees used in tests. |
| app/Services/Training/SeminarInvitationService.php | Core invitation logic (top-up, create, accept/decline, expiry cleanup). |
| app/Services/Training/SeminarCtsSyncService.php | Syncs core seminars/attendees into legacy CTS group session tables. |
| app/Observers/Training/SeminarObserver.php | Triggers CTS sync when seminars are created/updated. |
| app/Observers/Training/SeminarAttendeeObserver.php | Triggers CTS sync when attendees are created. |
| app/Notifications/Training/SeminarInvitationNotification.php | Notification that renders the seminar invitation email. |
| app/Models/Training/WaitingList/RemovalReason.php | Adds waiting list removal reasons for seminar invitation outcomes. |
| app/Models/Training/Seminar/SeminarInvitation.php | Invitation model with enum cast and response eligibility logic. |
| app/Models/Training/Seminar/SeminarAttendee.php | Attendee model + observer binding. |
| app/Models/Training/Seminar/Seminar.php | Seminar model with capacity/cutoff calculations and relations. |
| app/Models/Mship/Concerns/HasSeminarInvitations.php | Adds invitation relationship + cannot-attend counting on Account. |
| app/Models/Mship/Account.php | Wires in the seminar invitations trait. |
| app/Models/Cts/GroupSessionStudent.php | CTS model for group session student join table. |
| app/Models/Cts/GroupSession.php | CTS model for group sessions. |
| app/Http/Controllers/Mship/Training/SeminarInvitationController.php | Member controller for responding to invitations by token. |
| app/Filament/Training/Resources/TrainingPlaces/TrainingPlaceResource.php | Adjusts navigation sort to accommodate new Seminars navigation ordering. |
| app/Filament/Training/Resources/Seminars/Widgets/SeminarStatsOverview.php | Adds per-seminar stats widget (sent/pending/declined/attendees). |
| app/Filament/Training/Resources/Seminars/SeminarResource.php | New Filament resource for creating/viewing seminars and managing relations. |
| app/Filament/Training/Resources/Seminars/RelationManagers/WaitingListRelationManager.php | Shows waiting list accounts + supports manual invitations. |
| app/Filament/Training/Resources/Seminars/RelationManagers/InvitationsRelationManager.php | Lists invitations and their statuses in Filament. |
| app/Filament/Training/Resources/Seminars/RelationManagers/AttendeesRelationManager.php | Lists attendees and supports creating Training Places from attendees. |
| app/Filament/Training/Resources/Seminars/Pages/ViewSeminar.php | Seminar view page actions (enable/disable auto invites, close seminar). |
| app/Filament/Training/Resources/Seminars/Pages/ListSeminars.php | List page for seminars. |
| app/Filament/Training/Resources/Seminars/Pages/EditSeminar.php | Edit page for seminars. |
| app/Filament/Training/Resources/Seminars/Pages/CreateSeminar.php | Create page for seminars (sets created_by to current user). |
| app/Enums/SeminarInvitationStatus.php | Enum for invitation statuses incl. label/color/responded helpers. |
| app/Console/Kernel.php | Schedules the daily seminar invitation expiry check at 11:30. |
| app/Console/Commands/Training/CheckForExpiredSeminarInvitations.php | Command wrapper to run the expiry cleanup service method. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…//github.com/CLC0609/core into tech-329-automate-obs-s1-seminar-arrangement
Contributor
Author
|
Fixes TECH-681 |
kristiankunc
reviewed
Jul 3, 2026
kristiankunc
reviewed
Jul 3, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Parts of TECH-329
Summary of changes
A fairly simple version of what was requested in TECH-329. Currently the implemented workflow looks like:
capacity - (number of pending invites + number of confirmed attendees) = 0. This means there will only ever be capacity number of potential people invited at any timeWhat it doesn't do:
The spec requested was fairly large, and with this PR already 3000+ lines, I think it's best to leave these for another one, but most of the groundwork is here to make those fairly simple.
Syncs with CTS
group_session_*tables to allow the later part of the workflow to be done on the CTS for now.Screenshots (if necessary)
Awaiting copy text