Browse Source

feat: :sparkles: feat (relatorio) novo relatorio de usos do convenio

foi criado o novo relatorio de usos do convenio, exportavel em excel

fase:dev | origin:escopo
Gustavo Zanatta 8 hours ago
parent
commit
64605572ac

+ 66 - 0
app/Exports/UsosConvenioExport.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Exports;
+
+use App\Services\ReportService;
+use Maatwebsite\Excel\Concerns\FromCollection;
+use Maatwebsite\Excel\Concerns\WithHeadings;
+use Maatwebsite\Excel\Concerns\WithStyles;
+use Maatwebsite\Excel\Concerns\WithColumnWidths;
+use Maatwebsite\Excel\Concerns\WithTitle;
+use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
+use PhpOffice\PhpSpreadsheet\Style\Fill;
+use PhpOffice\PhpSpreadsheet\Style\Alignment;
+use Illuminate\Support\Collection;
+
+class UsosConvenioExport implements FromCollection, WithHeadings, WithStyles, WithColumnWidths, WithTitle
+{
+    public function __construct(
+        private readonly ReportService $service,
+        private readonly ?string $search = null,
+    ) {}
+
+    public function collection(): Collection
+    {
+        $filters = $this->search ? ['search' => $this->search] : [];
+
+        return $this->service->getAllUsosConvenio($filters)->map(function ($appointment) {
+            $row = $this->service->formatUsoConvenio($appointment);
+
+            return [
+                $row['convenio'] ?? '',
+                $this->service->usoConvenioTipoLabel($row['type']),
+                $row['servico'] ?? '',
+                $row['associado'] ?? '',
+                $row['criado_em'] ?? '',
+                $row['agendado_em'] ?? '',
+            ];
+        });
+    }
+
+    public function headings(): array
+    {
+        return ['Convênio', 'Tipo', 'Serviço', 'Associado', 'Criação do Agendamento', 'Data do Agendamento'];
+    }
+
+    public function title(): string
+    {
+        return 'Usos do Convênio';
+    }
+
+    public function columnWidths(): array
+    {
+        return ['A' => 35, 'B' => 20, 'C' => 35, 'D' => 35, 'E' => 24, 'F' => 24];
+    }
+
+    public function styles(Worksheet $sheet): array
+    {
+        return [
+            1 => [
+                'font'      => ['bold' => true, 'color' => ['argb' => 'FFFFFFFF']],
+                'fill'      => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['argb' => 'FF661D75']],
+                'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER],
+            ],
+        ];
+    }
+}

+ 24 - 0
app/Http/Controllers/ReportController.php

@@ -5,6 +5,7 @@ namespace App\Http\Controllers;
 use App\Exports\ContatosAssociadosExport;
 use App\Exports\ExclusoesMesExport;
 use App\Exports\NovoAssociadosExport;
+use App\Exports\UsosConvenioExport;
 use App\Services\ReportService;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
@@ -86,6 +87,23 @@ class ReportController extends Controller
         ]);
     }
 
+    public function getUsosConvenioPaginated(Request $request): JsonResponse
+    {
+        $filters   = $request->only(['search']);
+        $perPage   = min((int) $request->get('per_page', 10), 100);
+        $paginator = $this->service->getUsosConvenioPaginated($filters, $perPage);
+
+        return $this->successResponse(payload: [
+            'data'  => array_map(
+                fn($a) => $this->service->formatUsoConvenio($a),
+                $paginator->items()
+            ),
+            'total' => $paginator->total(),
+            'from'  => $paginator->firstItem() ?? 0,
+            'to'    => $paginator->lastItem() ?? 0,
+        ]);
+    }
+
     public function exportNovoAssociados(Request $request): BinaryFileResponse
     {
         $filename = 'novos_associados_' . now()->format('d-m-Y') . '.xlsx';
@@ -103,4 +121,10 @@ class ReportController extends Controller
         $filename = 'exclusoes_mes_' . now()->format('d-m-Y') . '.xlsx';
         return Excel::download(new ExclusoesMesExport($request->get('search')), $filename);
     }
+
+    public function exportUsosConvenio(Request $request): BinaryFileResponse
+    {
+        $filename = 'usos_convenio_' . now()->format('d-m-Y') . '.xlsx';
+        return Excel::download(new UsosConvenioExport($this->service, $request->get('search')), $filename);
+    }
 }

+ 73 - 0
app/Services/ReportService.php

@@ -2,14 +2,23 @@
 
 namespace App\Services;
 
+use App\Enums\AppointmentStatusEnum;
+use App\Enums\PartnerAgreementTypeEnum;
 use App\Enums\UserTypeEnum;
+use App\Models\Appointment;
 use App\Models\User;
 use Carbon\Carbon;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Pagination\LengthAwarePaginator;
 use Illuminate\Database\Eloquent\Collection;
 
 class ReportService
 {
+    private const USOS_CONVENIO_STATUSES = [
+        AppointmentStatusEnum::CONFIRMADO,
+        AppointmentStatusEnum::CONCLUIDO,
+    ];
+
     public function getCounters(): array
     {
         $now = Carbon::now();
@@ -25,6 +34,7 @@ class ReportService
                 ->whereYear('excluded_at', $now->year)
                 ->whereMonth('excluded_at', $now->month)
                 ->count(),
+            'usos_convenio' => Appointment::whereIn('status', self::USOS_CONVENIO_STATUSES)->count(),
         ];
     }
 
@@ -106,6 +116,69 @@ class ReportService
             ->get();
     }
 
+    public function getUsosConvenioPaginated(array $filters = [], int $perPage = 10): LengthAwarePaginator
+    {
+        return $this->usosConvenioQuery($filters)->paginate($perPage);
+    }
+
+    public function getAllUsosConvenio(array $filters = []): Collection
+    {
+        return $this->usosConvenioQuery($filters)->get();
+    }
+
+    public function formatUsoConvenio(Appointment $appointment): array
+    {
+        $criadoEm = $appointment->requested_at ?? $appointment->created_at;
+
+        return [
+            'id'          => $appointment->id,
+            'convenio'    => $appointment->partnerAgreement?->company_name,
+            'type'        => $appointment->partnerAgreement?->type?->value,
+            'servico'     => $appointment->partnerAgreementService?->name,
+            'associado'   => $appointment->user?->name,
+            'criado_em'   => $criadoEm?->format('d/m/Y H:i'),
+            'agendado_em' => $appointment->date
+                ? $appointment->date->format('d/m/Y') . ($appointment->time
+                    ? ' ' . Carbon::parse($appointment->time)->format('H:i')
+                    : '')
+                : null,
+        ];
+    }
+
+    public function usoConvenioTipoLabel(?string $type): string
+    {
+        return match ($type) {
+            PartnerAgreementTypeEnum::AGREEMENT->value => 'Convênio Médico',
+            PartnerAgreementTypeEnum::PARTNER->value   => 'Parceiro',
+            default                                    => '',
+        };
+    }
+
+    private function usosConvenioQuery(array $filters = []): Builder
+    {
+        $query = Appointment::query()
+            ->with([
+                'user:id,name',
+                'partnerAgreement:id,company_name,type',
+                'partnerAgreementService:id,name',
+            ])
+            ->whereIn('status', self::USOS_CONVENIO_STATUSES)
+            ->orderByRaw('COALESCE(appointments.requested_at, appointments.created_at) DESC');
+
+        if (!empty($filters['search'])) {
+            $term = '%' . mb_strtolower($filters['search']) . '%';
+            $query->where(function ($q) use ($term) {
+                $q->whereHas('partnerAgreement', fn($p) => $p->whereRaw('UNACCENT(LOWER(company_name)) LIKE UNACCENT(?)', [$term]))
+                  ->orWhereHas('partnerAgreementService', fn($s) => $s->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term]))
+                  ->orWhereHas('user', fn($u) => $u->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term]))
+                  ->orWhereRaw("TO_CHAR(appointments.date, 'DD/MM/YYYY') LIKE ?", [$term])
+                  ->orWhereRaw("TO_CHAR(COALESCE(appointments.requested_at, appointments.created_at), 'DD/MM/YYYY') LIKE ?", [$term]);
+            });
+        }
+
+        return $query;
+    }
+
     public function getAllExclusoesMes(): Collection
     {
         $now = Carbon::now();

+ 2 - 0
routes/authRoutes/relatorio.php

@@ -9,8 +9,10 @@ Route::controller(ReportController::class)->prefix('relatorio')->middleware('per
     Route::get('/novos-associados', 'getNovoAssociadosPaginated');
     Route::get('/contatos-associados', 'getContatosAssociadosPaginated');
     Route::get('/exclusoes-mes', 'getExclusoesMesPaginated');
+    Route::get('/usos-convenio', 'getUsosConvenioPaginated');
 
     Route::get('/novos-associados/export', 'exportNovoAssociados');
     Route::get('/contatos-associados/export', 'exportContatosAssociados');
     Route::get('/exclusoes-mes/export', 'exportExclusoesMes');
+    Route::get('/usos-convenio/export', 'exportUsosConvenio');
 });