File: /home/xedaptot/rms.naniguide.com/app/Http/Controllers/ReportController.php
<?php
namespace App\Http\Controllers;
use App\Models\Hotel;
use App\Models\Report;
use App\Services\RevenueManagementService;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class ReportController extends Controller
{
public function __construct(private RevenueManagementService $rms)
{
}
public function index(Request $request)
{
$hotel = $this->hotel($request);
$reports = Report::where('hotel_id', $hotel->id)->latest()->get();
return view('rms.reports', compact('hotel', 'reports'));
}
public function generate(Request $request)
{
$data = $request->validate([
'type' => ['required'],
'period_start' => ['required', 'date'],
'period_end' => ['required', 'date'],
]);
$hotel = $this->hotel($request);
$payload = $this->rms->reportPayload($hotel, $data['type'], $data['period_start'], $data['period_end']);
Report::create($data + ['hotel_id' => $hotel->id, 'payload' => $payload]);
return back()->with('status', 'Đã tạo báo cáo.');
}
public function export(Request $request, Report $report, string $format)
{
abort_unless($report->hotel_id === $this->hotel($request)->id, 403);
$content = $format === 'excel'
? view('rms.report-export', ['report' => $report])->render()
: $this->simplePdf($report);
$extension = $format === 'excel' ? 'xls' : 'pdf';
$contentType = $format === 'excel' ? 'application/vnd.ms-excel' : 'application/pdf';
return new Response($content, 200, [
'Content-Type' => $contentType,
'Content-Disposition' => "attachment; filename=report-{$report->id}.{$extension}",
]);
}
private function hotel(Request $request): Hotel
{
return $request->user()->hotel_id ? Hotel::findOrFail($request->user()->hotel_id) : Hotel::firstOrFail();
}
private function simplePdf(Report $report): string
{
$lines = [
'Hotel RMS Report',
$report->type,
$report->period_start.' - '.$report->period_end,
'Occupancy: '.$report->payload['kpis']['occupancy'].'%',
'ADR: '.$report->payload['kpis']['adr'],
'RevPAR: '.$report->payload['kpis']['revpar'],
'Total Revenue: '.$report->payload['kpis']['total_revenue'],
'Recommendation: '.$report->payload['ai']['suggested_action'],
];
$commands = collect($lines)
->map(fn ($line) => '('.str_replace(['\\', '(', ')'], ['\\\\', '\(', '\)'], $line).') Tj T*')
->implode(' ');
$stream = "BT /F1 12 Tf 14 TL 72 760 Td {$commands} ET";
$objects = [
'1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj',
'2 0 obj << /Type /Pages /Kids [3 0 R] /Count 1 >> endobj',
'3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >> endobj',
'4 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> endobj',
'5 0 obj << /Length '.strlen($stream).' >> stream '.$stream.' endstream endobj',
];
$pdf = "%PDF-1.4\n";
$offsets = [0];
foreach ($objects as $object) {
$offsets[] = strlen($pdf);
$pdf .= $object."\n";
}
$xref = strlen($pdf);
$pdf .= "xref\n0 ".(count($objects) + 1)."\n0000000000 65535 f \n";
foreach (array_slice($offsets, 1) as $offset) {
$pdf .= str_pad((string) $offset, 10, '0', STR_PAD_LEFT)." 00000 n \n";
}
$pdf .= "trailer << /Size ".(count($objects) + 1)." /Root 1 0 R >>\nstartxref\n{$xref}\n%%EOF";
return $pdf;
}
}