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: Waiting list automated removals #2798
feat: Waiting list automated removals #2798
Conversation
…k to process the waiting lists and identify members who do not meet activity requirements, triggering the removal process
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General Comments:
Given the scale of the number of members on lists, I'd suggest that some of the jobs, like marking for approval, detect if those marked for approval are now back into eligibility, and sending the notifications are done via an event-driven architecture. In Laravel terms, this is where an event is emitted and a queued listener responds to the relevant action. Blocking the command until the completion of this process could lead to performance issues.
This would make it easier for other things in the future to start the process of marking them for removal e.g. if it was that we wanted to start looking for activity on specific positions, or whether a theory exam had been completed within X time of joining the list, for example. You'd be able to trigger from multiple sources, rather than coupling to the implementation of the command.
You may wish to have a separate command that runs more frequently to check the removals so you are avoiding the edge conditions you have with the daily checks. Separating the command out would be my advice in general here.
I'll do a second review if you have any questions. Feel free to reach out on DIscord with any other questions.
database/migrations/2022_11_06_111641_add_training_list_enforce_hour_eligibility_column.php
Outdated
Show resolved
Hide resolved
app/Console/Commands/WaitingLists/CheckMembersMeetActivityRules.php
Outdated
Show resolved
Hide resolved
app/Console/Commands/WaitingLists/CheckMembersMeetActivityRules.php
Outdated
Show resolved
Hide resolved
app/Console/Commands/WaitingLists/CheckMembersMeetActivityRules.php
Outdated
Show resolved
Hide resolved
app/Console/Commands/WaitingLists/CheckMembersMeetActivityRules.php
Outdated
Show resolved
Hide resolved
app/Console/Commands/WaitingLists/CheckMembersMeetActivityRules.php
Outdated
Show resolved
Hide resolved
…at are pending removal
Hi @AxonC I have refactored this PR, including splitting the system into two isolated commands that be be ran on separate schedules. The first command is responsible for checking waiting list accounts meet the activity requirement, both those not marked for removal and those which are. The second command is responsible for actioning pending removals. I've also created unit tests to cover both of the new commands. |
public function handle() | ||
{ | ||
WaitingList::all()->filter(function ($waitingList) { | ||
return $waitingList->isAtcList(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest since you're using this filter for ATC lists in more than one place, you create a local scope: https://laravel.com/docs/9.x/eloquent#local-scopes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.../migrations/2022_11_06_201538_create_training_waiting_list_account_pending_removal_table.php
Show resolved
Hide resolved
.../migrations/2022_11_06_201538_create_training_waiting_list_account_pending_removal_table.php
Show resolved
Hide resolved
->filter(function ($account) { | ||
return $account->pivot->current_status->name == 'Active'; | ||
})->filter(function ($account) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another example of where this logic should be abstracted to a model method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @AxonC
I am struggling with this one a little - can you provide an example of the logic?
I don't work with Laravel in my day-to-day so lack an in-depth knowledge of it at this level.
The main issue I am facing is that as far as I can see, to add a model method such as activeAccountsPendingRemoval()
to replace the following two filters:
->filter(function ($account) {
return $account->pivot->current_status->name == 'Active';
})->filter(function ($account) {
return $account->pivot->pending_removal?->status == 'Pending';
})
I would need to add it to the Account
model, not the WaitingListAccount
model. Adding it to the WaitingListAccount
seems like the correct place, but is then not accessible in the query builder as far as I can see due to it being on a pivot and not the parent model.
I believe I could do something like:
->filter(function ($account) {
return $account->pivot->activeAccountsPendingRemoval();
})
But using a filter appears to defeat the point of the change.
})->each(function ($account) use ($waitingList) { | ||
// Send 5 day reminders | ||
if ( | ||
Carbon::parse($account->pivot->pending_removal->removal_date)->subDays(6) <= Carbon::now() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The magic number 6 has no relationship to the comment - please explain why in a comment subDays(6) is used since it isn't self-explanatory.
app/Listeners/Training/WaitingList/SendAccountMarkedForRemovalNotification.php
Show resolved
Hide resolved
tests/Unit/Training/WaitingList/WaitingListCheckAccountMeetActivityRequirementTest.php
Show resolved
Hide resolved
if ($activeMinutes < $this->minutesRequired) { | ||
if (is_null($account->pivot->pending_removal?->removal_date) || $account->pivot->pending_removal->status != 'Pending') { | ||
$removalDate = Carbon::now(); | ||
$removalDate->addDays(31); // When calculating date diff, this will be a difference of 30 days |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest rather than relying on this, a consistent processing time should be used, or there needs to be more edge case testing of this.
Given the requirements, I am happy to do this on should the amount of feedback be overwhelming. |
This PR adds functionality to have waiting list members automatically removed as directed in the ATC training handbook, when their network activity falls below the requirements.
The work adds a scheduled task which runs and performs the following functions:
Finally, the UI has been updated for viewing waiting lists to provide members with information relating to this process.
This is my first contribution to core, and I am happy to receive feedback and make any required amendments.
This PR relates to an upcoming training policy change, and should not be merged without prior co-ordination with the ATC training director.