From 3c1b9a8754af733b5fdafec09bdc8e3113619249 Mon Sep 17 00:00:00 2001 From: Matthew Horsfall Date: Fri, 21 Aug 2020 20:53:41 -0400 Subject: [PATCH] Rototron: Reconfigure how unavailable and manual overrides react Previously, if you marked yourself unavailable on a day, but someone else marked you manually configured for that day, you'd be assigned that day. That doesn't seem quite right. Now, instead, explicit unavailable wins --- lib/Synergy/Reactor/Rototron.pm | 23 +++++++++++++ lib/Synergy/Rototron.pm | 60 ++++++++++++++++++++++++++------- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/lib/Synergy/Reactor/Rototron.pm b/lib/Synergy/Reactor/Rototron.pm index fc03767b..79a0d8b6 100644 --- a/lib/Synergy/Reactor/Rototron.pm +++ b/lib/Synergy/Reactor/Rototron.pm @@ -161,6 +161,29 @@ sub handle_manual_assignment ($self, $event) { $assign_to = $target->username; } + my (@okay, @errors); + + for my $date (@dates) { + my $debug = []; + if ($self->availability_checker->user_is_available_on($assign_to, $date, $debug)) { + push @okay, $date; + } else { + push @errors, @$debug; + } + } + + @dates = @okay; + + unless (@dates) { + $event->reply("$username was not available for any of those dates:\n" . join("\n", @errors)); + + return; + } + + if (@errors) { + $event->reply("$username was not available for these dates:\n" . join("\n", @errors)); + } + $self->availability_checker->update_manual_assignments({ $rotor_name => { map {; $_->ymd => $assign_to } @dates }, }); diff --git a/lib/Synergy/Rototron.pm b/lib/Synergy/Rototron.pm index 385a6ee2..bc1c8ca8 100644 --- a/lib/Synergy/Rototron.pm +++ b/lib/Synergy/Rototron.pm @@ -457,14 +457,24 @@ package Synergy::Rototron::Rotor { if (my $username = $self->manual_assignment_for($rotor, $day)) { my ($user) = grep {; $_->{username} eq $username } $self->_full_staff->@*; - return $user if $user; - - $Logger->log([ - "no user named %s, but that name is assigned for %s on %s", - $username, - $rotor->name, - $day->ymd, - ]); + + if ($user && $self->user_is_blocked_on($user->{username}, $day)) { + $Logger->log([ + "user %s manually assigned but they are marked unavailable for %s on %s, skipping", + $user->{username}, + $rotor->name, + $day->ymd, + ]); + } elsif ($user) { + return $user; + } else { + $Logger->log([ + "no user named %s, but that name is assigned for %s on %s", + $username, + $rotor->name, + $day->ymd, + ]); + } } my $weekn = _week_of_date($day); @@ -665,16 +675,42 @@ package Synergy::Rototron::AvailabilityChecker { return; } - sub user_is_available_on ($self, $username, $dt) { + sub user_is_available_on ($self, $username, $dt, $debug = []) { my $ymd = $dt->ymd; + unless ($self->user_typically_works_on($username, $dt)) { + push @$debug, "$username does not work on " . $dt->ymd; + return 0; + } + + if ($self->user_has_leave_on($username, $dt)) { + push @$debug, "$username has leave scheduled on " . $dt->ymd; + return 0; + } + + if ($self->user_is_blocked_on($username, $dt)) { + push @$debug, "$username is marked unavailable on " . $dt->ymd; + return 0; + } + + return 1; + } + + sub user_typically_works_on ($self, $username, $dt) { if (my $user = $self->user_directory->user_named($username)) { - return 0 unless $user->hours_for_dow($dt->day_of_week); + return 1 if $user->hours_for_dow($dt->day_of_week); } + return 0; + } + + sub user_has_leave_on ($self, $username, $dt) { my $leave = $self->_leave_days; - return 0 if $leave->{$username}{$dt->ymd}; + return 1 if $leave->{$username}{$dt->ymd}; + } + + sub user_is_blocked_on ($self, $username, $dt) { my ($count) = $self->_dbh->selectrow_array( q{SELECT COUNT(*) FROM blocked_days WHERE username = ? AND date = ?}, undef, @@ -682,7 +718,7 @@ package Synergy::Rototron::AvailabilityChecker { $dt->ymd, ); - return $count == 0; + return $count ? 1 : 0; } sub set_user_unavailable_on ($self, $username, $dt, $reason = undef) {