# Type: Input # Category: Report # Description: Shows daily report - how much time was spent per day # Author: Andriy Lesyuk sub DailyReport_DefaultPeriod($$) { my ($message, $result) = @_; # Base on work day my $now = time; if ((localtime($now))[2] < 6) { $now -= 21600; } # Current month my $time = new Orangutan::Date($now); my $start = $time->MonthStart->Date; my $end = $time->MonthEnd->Date; push(@{$result}, new Orangutan::Date($start + 21600)); push(@{$result}, new Orangutan::Date($end + 21600)); } new Orangutan::Context( response => sub { my ($context, $user, $message) = @_; my @result = ( ); # Remove ending $message =~ s/\?*!*\.*$//; my @regexps = ( 'How (?:much time|many hours) (?:did )?(?:I|([^ ]+)) spen[td] per day', '(?:Show(?: me)? )?(?:days|daily report) (?:of|for) ([^ ]+)', '(?:Show(?: me)? )?(?:(?:my|([^ ]+?)(?:\'s)?) )?(?:days|daily report)' ); # Check base query for (my $i = 0; $i < scalar @regexps; $i++) { if ($message =~ /^$regexps[$i] */i) { if (defined($1)) { my $id = $main::query->UserExists($1); if ($id) { push(@result, 1); push(@result, $id); $message =~ s/^$regexps[$i] *//i; last; } } else { push(@result, 1); push(@result, undef); $message =~ s/^$regexps[$i] *//i; last; } } } if (scalar @result > 0) { ShowTasks_ParsePeriod(\$message, \@result); if (scalar @result == 2) { DailyReport_DefaultPeriod(\$message, \@result); } ShowTasks_ParseFilter(\$message, \@result); if ($message !~ /^ *$/) { @result = ( ); } } return @result; }, handler => sub { my ($context, $manager, $item, $userid, $start, $end, $project, $issue, $activity) = @_; my $user; if (!defined($userid) || ($userid == $manager->GetUserID)) { $userid = $manager->GetUserID; $user = $manager; } elsif (!$manager->IsCreator && !$manager->IsManager) { $manager->SendMessage([ 'Well... I need several hours to prepare and print the document...', "I won't do this! Unless you hack me...", 'Daily report? What daily report?..', 'Why do you care?..' ]); return; } else { $user = $main::users->GetUserID($userid); } if (!defined($start) || !defined($end)) { $manager->SendMessage([ 'Please check the request - I did not understand it.', 'I guess my english is too bad... I do not get it.', 'I do not get it...' ]); return; } if ($start->IsFuture) { $manager->SendMessage([ "I'm not prophet to do things like this...", "I can't give report for future!", 'Hey! This is in future!' ]); return; } elsif ($end->IsFuture) { $end->Set(time); } if (defined($issue) && defined($activity)) { $manager->SendMessage([ "It's too complicated for now to consider issue and activity...", 'It would take much longer to consider issue ID and activity...', "I'm not going to take into account issue ID and activity..." ]); } elsif (defined($issue)) { $manager->SendMessage([ "Well... It's too complicated for me right now to consider issue ID...", "I don't support issue for this request..." ]); } elsif (defined($activity)) { $manager->SendMessage([ 'Well... Let me do this without taking the activity into account...', "Can't use activity to filter records..." ]); } my @workdays = (); if (defined($user)) { @workdays = $user->GetWorkDays($start, $end); } else { @workdays = Orangutan::Date::GetWorkDays($start, $end); } $start->Set($start->Date - 21600); $end->Set($end->Date - 21600); my $projectid = defined($project) ? $project->{'id'} : undef; my %days = Orangutan::User::GetWorkHoursPerDay(defined($user) ? $user : $userid, $start, $end, $projectid); my %wdays = ( ); foreach my $workday (@workdays) { my $date = $workday->DayStart->Date; if (!defined($days{$date})) { $days{$date} = 0; } $wdays{$date} = 1; } if (scalar keys %days > 0) { my $message = Orangutan::Context::Random( 'Spent time per a day', 'The daily report', 'Catch it' ).":\n"; my $total = 0; my $required = 0; my $hours = defined($user) ? $user->GetWorkTimeHours : 8; foreach my $date (sort keys %days) { my ($day, $mon, $year, $wday) = (localtime($date))[3..6]; $message .= sprintf(' o %s, %s %d', $Orangutan::Date::weekdays_short[$wday], $Orangutan::Date::months_short[$mon], $day); if ((time - $date) > 31536000) { $message .= sprintf(" %04d", $year + 1900); } $message .= ' - '; $message .= sprintf('%d:%02d', int($days{$date} / 3600), int(($days{$date} % 3600) / 60)); if (defined($wdays{$date}) && ($days{$date} > 0)) { $message .= sprintf(' (%.4g%%)', ($days{$date} * 100) / ($hours * 3600)); } $message .= ' spent'; if (defined($wdays{$date})) { if ($days{$date} < ($hours * 3600)) { $message .= sprintf(' (+%d:%02d needed)', int((($hours * 3600) - $days{$date}) / 3600), int(((($hours * 3600) - $days{$date}) % 3600) / 60)); } elsif ($days{$date} > ($hours * 3600)) { $message .= sprintf(' (%d:%02d overtime)', int(($days{$date} - ($hours * 3600)) / 3600), int((($days{$date} - ($hours * 3600)) % 3600) / 60)); } $required += ($hours * 3600); } else { $message .= sprintf(' (%d:%02d overtime)', int($days{$date} / 3600), int(($days{$date} % 3600) / 60)); } $message .= "\n"; $total += $days{$date}; } if (scalar keys %days > 1) { $message .= 'Total time - '; $message .= sprintf('%d:%02d', int($total / 3600), int(($total % 3600) / 60)); $message .= sprintf(' (%.4g%%)', ($total * 100) / $required); $message .= ' spent'; if ($total < $required) { $message .= sprintf(' (+%d:%02d needed)', int(($required - $total) / 3600), int((($required - $total) % 3600) / 60)); } elsif ($total > $required) { $message .= sprintf(' (%d:%02d overtime)', int(($total - $required) / 3600), int((($total - $required) % 3600) / 60)); } } $manager->SendMessage($message); if (!defined($user)) { $manager->SendMessage([ 'I could not determine leave days so the report can be a little bit incorrect...', 'Warning: This user does not use me so data may be incomplete...' ]); } } else { $manager->SendMessage([ 'There is no data to generate the report...', 'Nothing to be shown...', 'No data to show...' ]); } }, help => { title => 'How can I check how much time did I spend per day?', question => [ '^(?:(?:How )?(?:(?:can|do) I |to )(?:check|see) )?how (?:much|many) (?:time|hours) '. '(?:did )?I spen[td] per day(?: (?:during|for|at) some period)?\?*!*\.*$', '^(?:How )?(?:(?:can|do) I |to )(?:check|see) (?:my )?(?:work(?:ing)? )?(?:time|hours)(?: spent)? '. 'per day(?: (?:during|for|at) some period)?\?*!*\.*$', '^(?:How )?(?:(?:can|do) I |to )(?:check|get|see) (?:(?:my|the) )?daily report(?: for some period)?\?*!*\.*$' ], answer => "If you are required to work some number of hours per day you may need ". "to get a short report telling you how much time did you spent per day. ". "Orangutan can show you such report for today, yesterday, current week, last month or any other period.\n". "Check queries:\n". " o How much time did I spent per day this month?\n". " o How many hours did I spent per day last week?\n". " o DailyReport from August 1 to August 31\n". " o Show me daily report for last month\n". " o Daily report\n". " o Days\n". "You can optionally specify project name:\n". "o Show daily report for Orangutan\n". "o Show days on Kayako\n". "If no period is specified Orangutan shows daily report for the current month.", weight => 720 } ); # kate: syntax perl