/** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { $period = $input->getArgument('period'); $start = $input->getOption('start'); $project = $input->getOption('project'); $start = $start ? new \DateTime($start) : NULL; if (!in_array($period, [static::MONTH, static::DAY, static::WEEK, static::FORTNIGHT], TRUE)) { $output->writeln('<error>Period must be one of day|week|month|fortnight</error>'); $output->writeln('E.g. <comment>tl billable week</comment>'); return; } switch ($period) { case static::WEEK: $date = DateHelper::startOfWeek($start); $end = clone $date; $end->modify('+7 days'); break; case static::MONTH: $date = DateHelper::startOfMonth($start); $end = clone $date; $end->modify('+1 month'); $end = DateHelper::startOfMonth($end); $end->modify('-1 second'); break; case static::FORTNIGHT: $date = DateHelper::startOfWeek($start); $date->modify('-7 days'); $end = clone $date; $end->modify('+14 days'); break; default: $date = DateHelper::startOfDay($start); $end = clone $date; $end->modify('+1 day'); } $billable = 0; $non_billable = 0; $unknown = 0; $unknowns = []; $projects = []; $billable_projects = []; $non_billable_projects = []; foreach ($this->repository->totalByTicket($date->getTimestamp(), $end->getTimestamp()) as $tid => $duration) { $details = $this->connector->ticketDetails($tid); if ($details) { if (!isset($projects[$details->getProjectId()])) { $projects[$details->getProjectId()] = 0; } if ($details->isBillable()) { $billable += $duration; $projects[$details->getProjectId()] += $duration; $billable_projects[$details->getProjectId()] = $details->getProjectId(); } else { $non_billable += $duration; $projects[$details->getProjectId()] += $duration; $non_billable_projects[$details->getProjectId()] = $details->getProjectId(); } } else { $unknown += $duration; $unknowns[] = $tid; } } $table = new Table($output); if (!$project) { $table->setHeaders(['Type', 'Hours', 'Percent']); } else { $table->setHeaders(['Type', 'Project', 'Hours', 'Percent']); } $total = $billable + $non_billable + $unknown; $tag = 'info'; // @todo make this configurable. if ($billable / $total < 0.8) { $tag = 'error'; } if ($project) { $project_names = $this->connector->projectNames(); $rows[] = ['Billable', '', '', '']; foreach ($billable_projects as $project_id) { $project_name = isset($project_names[$project_id]) ? $project_names[$project_id] : "Project ID {$project_id}"; $rows[] = ['', $project_name, Formatter::formatDuration($projects[$project_id]), '']; } $rows[] = new TableSeparator(); $rows[] = ['Billable', '', Formatter::formatDuration($billable), "<{$tag}>" . round(100 * $billable / $total, 2) . "%</{$tag}>"]; $rows[] = new TableSeparator(); $rows[] = ['Non-Billable', '', '', '']; foreach ($non_billable_projects as $project_id) { $project_name = isset($project_names[$project_id]) ? $project_names[$project_id] : "Project ID {$project_id}"; $rows[] = ['', $project_name, Formatter::formatDuration($projects[$project_id]), '']; } $rows[] = new TableSeparator(); $rows[] = ['Non-billable', '', Formatter::formatDuration($non_billable), round(100 * $non_billable / $total, 2) . '%']; if ($unknown) { $rows[] = new TableSeparator(); $rows[] = ['Unknown', '', '', '']; $rows[] = ['', 'Unknown<comment>*</comment>', Formatter::formatDuration($unknown), round(100 * $unknown / $total, 2) . '%']; $rows[] = ['', '<comment>* Deleted or access denied tickets:</comment> ' . implode(',', $unknowns), '', '']; } $rows[] = new TableSeparator(); $rows[] = ['', 'Total', Formatter::formatDuration($total), '100%']; } else { $rows[] = ['Billable', Formatter::formatDuration($billable), "<{$tag}>" . round(100 * $billable / $total, 2) . "%</{$tag}>"]; $rows[] = ['Non-billable', Formatter::formatDuration($non_billable), round(100 * $non_billable / $total, 2) . '%']; if ($unknown) { $rows[] = ['Unknown<comment>*</comment>', Formatter::formatDuration($unknown), round(100 * $unknown / $total, 2) . '%']; $rows[] = ['<comment>* Deleted or access denied tickets:</comment> ' . implode(',', $unknowns), '', '']; } $rows[] = new TableSeparator(); $rows[] = ['Total', Formatter::formatDuration($total), '100%']; } $table->setRows($rows); $table->render(); }