ReportService.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. namespace App\Services;
  3. use App\Enums\AppointmentStatusEnum;
  4. use App\Enums\PartnerAgreementTypeEnum;
  5. use App\Enums\UserTypeEnum;
  6. use App\Models\Appointment;
  7. use App\Models\User;
  8. use Carbon\Carbon;
  9. use Illuminate\Database\Eloquent\Builder;
  10. use Illuminate\Pagination\LengthAwarePaginator;
  11. use Illuminate\Database\Eloquent\Collection;
  12. class ReportService
  13. {
  14. private const USOS_CONVENIO_STATUSES = [
  15. AppointmentStatusEnum::CONFIRMADO,
  16. AppointmentStatusEnum::CONCLUIDO,
  17. ];
  18. public function getCounters(): array
  19. {
  20. $now = Carbon::now();
  21. return [
  22. 'novos_associados' => User::where('type', UserTypeEnum::ASSOCIADO)
  23. ->whereYear('created_at', $now->year)
  24. ->whereMonth('created_at', $now->month)
  25. ->count(),
  26. 'contatos' => User::where('type', UserTypeEnum::ASSOCIADO)->count(),
  27. 'exclusoes_mes' => User::where('type', UserTypeEnum::ASSOCIADO)
  28. ->whereNotNull('excluded_at')
  29. ->whereYear('excluded_at', $now->year)
  30. ->whereMonth('excluded_at', $now->month)
  31. ->count(),
  32. 'usos_convenio' => Appointment::whereIn('status', self::USOS_CONVENIO_STATUSES)->count(),
  33. ];
  34. }
  35. public function getNovoAssociadosPaginated(array $filters = [], int $perPage = 10): LengthAwarePaginator
  36. {
  37. $now = Carbon::now();
  38. $query = User::where('type', UserTypeEnum::ASSOCIADO)
  39. ->whereYear('created_at', $now->year)
  40. ->whereMonth('created_at', $now->month)
  41. ->orderBy('created_at', 'desc');
  42. if (!empty($filters['search'])) {
  43. $term = '%' . mb_strtolower($filters['search']) . '%';
  44. $query->where(function ($q) use ($term, $filters) {
  45. $q->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term])
  46. ->orWhereRaw('UNACCENT(LOWER(cpf)) LIKE UNACCENT(?)', [$term])
  47. ->orWhereRaw("TO_CHAR(created_at, 'DD/MM/YYYY') LIKE ?", [$term]);
  48. });
  49. }
  50. return $query->paginate($perPage);
  51. }
  52. public function getContatosAssociadosPaginated(array $filters = [], int $perPage = 10): LengthAwarePaginator
  53. {
  54. $query = User::where('type', UserTypeEnum::ASSOCIADO)
  55. ->orderBy('name', 'asc');
  56. if (!empty($filters['search'])) {
  57. $term = '%' . mb_strtolower($filters['search']) . '%';
  58. $query->where(function ($q) use ($term) {
  59. $q->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term])
  60. ->orWhereRaw('UNACCENT(LOWER(email)) LIKE UNACCENT(?)', [$term])
  61. ->orWhereRaw('UNACCENT(LOWER(COALESCE(phone, \'\'))) LIKE UNACCENT(?)', [$term]);
  62. });
  63. }
  64. return $query->paginate($perPage);
  65. }
  66. public function getExclusoesMesPaginated(array $filters = [], int $perPage = 10): LengthAwarePaginator
  67. {
  68. $now = Carbon::now();
  69. $query = User::where('type', UserTypeEnum::ASSOCIADO)
  70. ->whereNotNull('excluded_at')
  71. ->whereYear('excluded_at', $now->year)
  72. ->whereMonth('excluded_at', $now->month)
  73. ->orderBy('excluded_at', 'desc');
  74. if (!empty($filters['search'])) {
  75. $term = '%' . mb_strtolower($filters['search']) . '%';
  76. $query->where(function ($q) use ($term) {
  77. $q->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term])
  78. ->orWhereRaw('UNACCENT(LOWER(cpf)) LIKE UNACCENT(?)', [$term])
  79. ->orWhereRaw("TO_CHAR(excluded_at, 'DD/MM/YYYY') LIKE ?", [$term]);
  80. });
  81. }
  82. return $query->paginate($perPage);
  83. }
  84. public function getAllNovoAssociados(): Collection
  85. {
  86. $now = Carbon::now();
  87. return User::where('type', UserTypeEnum::ASSOCIADO)
  88. ->whereYear('created_at', $now->year)
  89. ->whereMonth('created_at', $now->month)
  90. ->orderBy('created_at', 'desc')
  91. ->get();
  92. }
  93. public function getAllContatosAssociados(): Collection
  94. {
  95. return User::where('type', UserTypeEnum::ASSOCIADO)
  96. ->orderBy('name', 'asc')
  97. ->get();
  98. }
  99. public function getUsosConvenioPaginated(array $filters = [], int $perPage = 10): LengthAwarePaginator
  100. {
  101. return $this->usosConvenioQuery($filters)->paginate($perPage);
  102. }
  103. public function getAllUsosConvenio(array $filters = []): Collection
  104. {
  105. return $this->usosConvenioQuery($filters)->get();
  106. }
  107. public function formatUsoConvenio(Appointment $appointment): array
  108. {
  109. $criadoEm = $appointment->requested_at ?? $appointment->created_at;
  110. return [
  111. 'id' => $appointment->id,
  112. 'convenio' => $appointment->partnerAgreement?->company_name,
  113. 'type' => $appointment->partnerAgreement?->type?->value,
  114. 'servico' => $appointment->partnerAgreementService?->name,
  115. 'associado' => $appointment->user?->name,
  116. 'criado_em' => $criadoEm?->format('d/m/Y H:i'),
  117. 'agendado_em' => $appointment->date
  118. ? $appointment->date->format('d/m/Y') . ($appointment->time
  119. ? ' ' . Carbon::parse($appointment->time)->format('H:i')
  120. : '')
  121. : null,
  122. ];
  123. }
  124. public function usoConvenioTipoLabel(?string $type): string
  125. {
  126. return match ($type) {
  127. PartnerAgreementTypeEnum::AGREEMENT->value => 'Convênio Médico',
  128. PartnerAgreementTypeEnum::PARTNER->value => 'Parceiro',
  129. default => '',
  130. };
  131. }
  132. private function usosConvenioQuery(array $filters = []): Builder
  133. {
  134. $query = Appointment::query()
  135. ->with([
  136. 'user:id,name',
  137. 'partnerAgreement:id,company_name,type',
  138. 'partnerAgreementService:id,name',
  139. ])
  140. ->whereIn('status', self::USOS_CONVENIO_STATUSES)
  141. ->orderByRaw('COALESCE(appointments.requested_at, appointments.created_at) DESC');
  142. if (!empty($filters['search'])) {
  143. $term = '%' . mb_strtolower($filters['search']) . '%';
  144. $query->where(function ($q) use ($term) {
  145. $q->whereHas('partnerAgreement', fn($p) => $p->whereRaw('UNACCENT(LOWER(company_name)) LIKE UNACCENT(?)', [$term]))
  146. ->orWhereHas('partnerAgreementService', fn($s) => $s->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term]))
  147. ->orWhereHas('user', fn($u) => $u->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term]))
  148. ->orWhereRaw("TO_CHAR(appointments.date, 'DD/MM/YYYY') LIKE ?", [$term])
  149. ->orWhereRaw("TO_CHAR(COALESCE(appointments.requested_at, appointments.created_at), 'DD/MM/YYYY') LIKE ?", [$term]);
  150. });
  151. }
  152. return $query;
  153. }
  154. public function getAllExclusoesMes(): Collection
  155. {
  156. $now = Carbon::now();
  157. return User::where('type', UserTypeEnum::ASSOCIADO)
  158. ->whereNotNull('excluded_at')
  159. ->whereYear('excluded_at', $now->year)
  160. ->whereMonth('excluded_at', $now->month)
  161. ->orderBy('excluded_at', 'desc')
  162. ->get();
  163. }
  164. }