Rapport-Laravel/app/Http/Controllers/AdherencepobdrivereportCont...

180 lines
5.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Exports\AdherencePobDriveExport;
use App\Http\Requests\LambdaRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdherencepobdrivereportController extends Controller
{
private const REPORT_START = '2026-04-01';
public function __construct()
{
$this->_service = 'reports';
$this->_module = 'team2_reports';
$this->_viewname = 'adherencepobdrivereport';
$this->_title = 'Adherence Pack POB Drive';
$this->_base_url = '/adherencepobdrivereport';
}
public static function canDownload($user): bool
{
if (!$user || ($user->domain ?? '') !== 'team2') {
return false;
}
$permissions = json_decode($user->permissions ?? '[]');
if (is_array($permissions) && in_array('all_data_access', $permissions, true)) {
return true;
}
$designation = strtoupper(trim(self::tokenDesignation($user->access_token ?? '')));
return $designation === 'HO' || $designation === 'ADMIN';
}
public function list(Request $request)
{
return redirect($this->_base_url . '/report');
}
public function report(Request $request)
{
$this->assertCanDownload();
$months = $this->monthChoices();
$selected = trim((string) $request->query('month', ''));
if (!in_array($selected, $months, true)) {
$selected = $this->currentMonth();
}
$reportError = session('reportError');
$sections = [];
try {
$data = $this->fetchReport($selected);
$export = new AdherencePobDriveExport($data, $selected);
if (!method_exists($export, 'sections')) {
throw new \RuntimeException('The report view is out of date. Deploy app/Exports/AdherencePobDriveExport.php and reload PHP.');
}
$sections = $export->sections();
} catch (\Throwable $e) {
$reportError = $e->getMessage();
}
return $this->view('report')->with([
'title' => $this->_title,
'base_url' => $this->_base_url,
'months' => $months,
'selectedMonth' => $selected,
'reportError' => $reportError,
'sections' => $sections,
]);
}
public function export(Request $request)
{
$this->assertCanDownload();
$months = $this->monthChoices();
$month = trim((string) $request->query('month', ''));
if (!in_array($month, $months, true)) {
$month = $this->currentMonth();
}
try {
$data = $this->fetchReport($month);
} catch (\RuntimeException $e) {
return $this->backToReport($month, $e->getMessage());
}
return (new AdherencePobDriveExport($data, $month))->download();
}
/**
* @return object
*/
private function fetchReport(string $month)
{
$token = Auth::user()->access_token ?? '';
try {
$response = LambdaRequest::getrequest(
$this->_service,
$this->_module . '/adherence_report',
['month' => $month],
$token,
120
);
} catch (\Throwable $e) {
throw new \RuntimeException('Failed to load the adherence report.');
}
if (!is_object($response) || strtolower((string) ($response->status ?? '')) !== 'success' || !is_object($response->data ?? null)) {
$message = is_object($response) ? trim((string) ($response->message ?? '')) : '';
throw new \RuntimeException($message !== '' ? $message : 'Failed to load the adherence report.');
}
return $response->data;
}
/**
* @return array<int, string>
*/
private function monthChoices(): array
{
$cursor = new \DateTimeImmutable(self::REPORT_START);
$end = new \DateTimeImmutable('first day of this month');
$months = [];
while ($cursor <= $end) {
$months[] = $cursor->format('F Y');
$cursor = $cursor->modify('+1 month');
}
if ($months === []) {
$months[] = $this->currentMonth();
}
return $months;
}
private function currentMonth(): string
{
return date('F Y');
}
private function assertCanDownload(): void
{
if (!self::canDownload(Auth::user())) {
abort(403, 'You do not have access to this report.');
}
}
private function backToReport(string $month, string $message)
{
return redirect($this->_base_url . '/report?month=' . urlencode($month))->with('reportError', $message);
}
private static function tokenDesignation(string $token): string
{
$token = trim($token);
if (stripos($token, 'Bearer ') === 0) {
$token = trim(substr($token, 7));
}
$parts = explode('.', $token);
if (count($parts) < 2) {
return '';
}
$segment = strtr($parts[1], '-_', '+/');
$pad = strlen($segment) % 4;
if ($pad > 0) {
$segment .= str_repeat('=', 4 - $pad);
}
$payload = json_decode(base64_decode($segment));
$user = is_object($payload) ? ($payload->user ?? null) : null;
if (!is_object($user)) {
return '';
}
return (string) ($user->designation ?? '');
}
}