PartnerAgreementService.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <?php
  2. namespace App\Services;
  3. use App\Enums\PartnerAgreementStatusEnum;
  4. use App\Enums\UserStatusEnum;
  5. use App\Enums\UserTypeEnum;
  6. use App\Models\PartnerAgreement;
  7. use App\Models\User;
  8. use Illuminate\Database\Eloquent\Builder;
  9. use Illuminate\Database\Eloquent\Collection;
  10. use Illuminate\Pagination\LengthAwarePaginator;
  11. use Illuminate\Support\Facades\DB;
  12. use Illuminate\Support\Facades\Hash;
  13. class PartnerAgreementService
  14. {
  15. public function getAll(array $filters = []): Collection
  16. {
  17. $query = PartnerAgreement::with(['category', 'city', 'logo'])
  18. ->orderBy('company_name');
  19. if (!empty($filters['type'])) {
  20. $query->where('type', $filters['type']);
  21. }
  22. return $query->get();
  23. }
  24. public function getForSelectPaginated(array $filters, int $perPage): LengthAwarePaginator
  25. {
  26. $query = PartnerAgreement::with(['category', 'city', 'logo'])
  27. ->where('status', PartnerAgreementStatusEnum::ACTIVE)
  28. ->orderBy('company_name');
  29. if (!empty($filters['type'])) {
  30. $query->where('type', $filters['type']);
  31. }
  32. if (!empty($filters['search'])) {
  33. $term = '%' . mb_strtolower($filters['search']) . '%';
  34. $query->whereRaw('UNACCENT(LOWER(company_name)) LIKE UNACCENT(?)', [$term]);
  35. }
  36. return $query->paginate($perPage);
  37. }
  38. public function getAllPaginated(array $filters = [], int $perPage = 10): LengthAwarePaginator
  39. {
  40. $query = $this->baseQuery($filters)
  41. ->with(['category', 'city', 'logo']);
  42. if (!empty($filters['expires_in_days'])) {
  43. $query->orderBy('contract_end');
  44. } else {
  45. $query->orderBy('company_name');
  46. }
  47. if (!empty($filters['status'])) {
  48. $query->where('status', $filters['status']);
  49. }
  50. return $query->paginate($perPage);
  51. }
  52. /**
  53. * Status existentes no conjunto filtrado, desconsiderando o próprio filtro de status.
  54. *
  55. * @return array<int, string>
  56. */
  57. public function getStatusOptions(array $filters = []): array
  58. {
  59. return $this->baseQuery($filters)
  60. ->toBase()
  61. ->distinct()
  62. ->pluck('status')
  63. ->filter()
  64. ->values()
  65. ->all();
  66. }
  67. private function baseQuery(array $filters): Builder
  68. {
  69. $query = PartnerAgreement::query();
  70. if (!empty($filters['type'])) {
  71. $query->where('type', $filters['type']);
  72. }
  73. if (!empty($filters['category_id'])) {
  74. $query->where('category_id', (int) $filters['category_id']);
  75. }
  76. if (!empty($filters['search'])) {
  77. $term = '%' . mb_strtolower($filters['search']) . '%';
  78. $query->where(function ($q) use ($term) {
  79. $q->whereRaw('UNACCENT(LOWER(company_name)) LIKE UNACCENT(?)', [$term])
  80. ->orWhereRaw('UNACCENT(LOWER(COALESCE(responsible, \'\'))) LIKE UNACCENT(?)', [$term])
  81. ->orWhereRaw('UNACCENT(LOWER(COALESCE(cnpj, \'\'))) LIKE UNACCENT(?)', [$term])
  82. ->orWhereRaw('UNACCENT(LOWER(COALESCE(email, \'\'))) LIKE UNACCENT(?)', [$term])
  83. ->orWhereRaw('UNACCENT(LOWER(COALESCE(address, \'\'))) LIKE UNACCENT(?)', [$term])
  84. ->orWhereHas('category', fn($cq) => $cq->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term]))
  85. ->orWhereHas('city', fn($cq) => $cq->whereRaw('UNACCENT(LOWER(name)) LIKE UNACCENT(?)', [$term]));
  86. });
  87. }
  88. if (!empty($filters['expires_in_days'])) {
  89. $days = (int) $filters['expires_in_days'];
  90. $query->whereBetween('contract_end', [now()->startOfDay(), now()->addDays($days)->endOfDay()]);
  91. }
  92. if (!empty($filters['created_month']) && $filters['created_month'] === 'current') {
  93. $query->whereMonth('created_at', now()->month)
  94. ->whereYear('created_at', now()->year);
  95. }
  96. return $query;
  97. }
  98. public function getExpiringPaginated(int $days = 30, int $perPage = 10): LengthAwarePaginator
  99. {
  100. return PartnerAgreement::with(['category', 'city', 'logo'])
  101. ->whereNotNull('contract_end')
  102. ->whereBetween('contract_end', [now()->startOfDay(), now()->addDays($days)->endOfDay()])
  103. ->orderBy('contract_end')
  104. ->paginate($perPage);
  105. }
  106. public function findById(int $id): ?PartnerAgreement
  107. {
  108. return PartnerAgreement::with(['category', 'city', 'state', 'services', 'logo', 'media', 'user'])->find($id);
  109. }
  110. public function findByUserId(int $userId): ?PartnerAgreement
  111. {
  112. $partner = PartnerAgreement::with(['category', 'city', 'state', 'services', 'logo', 'media'])
  113. ->where('user_id', $userId)
  114. ->first();
  115. if (!$partner) {
  116. if (PartnerAgreement::onlyTrashed()->where('user_id', $userId)->exists()) {
  117. return null;
  118. }
  119. $partner = new PartnerAgreement();
  120. $partner->company_name = 'Novo Parceiro';
  121. $partner->user_id = $userId;
  122. $partner->save();
  123. $partner->fresh(['category', 'city', 'state', 'services', 'logo', 'media']);
  124. }
  125. return $partner;
  126. }
  127. public function findDados(int $id): ?PartnerAgreement
  128. {
  129. return PartnerAgreement::with(['category', 'logo'])->find($id);
  130. }
  131. public function findContato(int $id): ?PartnerAgreement
  132. {
  133. return PartnerAgreement::find($id);
  134. }
  135. public function findEndereco(int $id): ?PartnerAgreement
  136. {
  137. return PartnerAgreement::with(['city', 'state'])->find($id);
  138. }
  139. public function findContrato(int $id): ?PartnerAgreement
  140. {
  141. return PartnerAgreement::with(['media'])->find($id);
  142. }
  143. public function create(array $data): PartnerAgreement
  144. {
  145. $user = User::create([
  146. 'name' => $data['user_name'],
  147. 'email' => $data['user_email'],
  148. 'password' => Hash::make($data['user_password']),
  149. 'type' => UserTypeEnum::PARCEIRO,
  150. ]);
  151. $partnerData = collect($data)
  152. ->except(['user_name', 'user_email', 'user_password'])
  153. ->put('user_id', $user->id)
  154. ->all();
  155. $model = PartnerAgreement::create($partnerData);
  156. return $model->fresh(['category', 'logo', 'user']);
  157. }
  158. public function update(int $id, array $data): ?PartnerAgreement
  159. {
  160. $model = PartnerAgreement::find($id);
  161. if (!$model) {
  162. return null;
  163. }
  164. $model->update($data);
  165. return $model->fresh(['category', 'city', 'state', 'logo', 'media']);
  166. }
  167. public function getTrashed(array $filters = []): Collection
  168. {
  169. $query = PartnerAgreement::onlyTrashed()->orderByDesc('deleted_at');
  170. if (!empty($filters['type'])) {
  171. $query->where('type', $filters['type']);
  172. }
  173. return $query->get(['id', 'company_name', 'type', 'deleted_at']);
  174. }
  175. public function restore(int $id): ?PartnerAgreement
  176. {
  177. $model = PartnerAgreement::onlyTrashed()->find($id);
  178. if (!$model) {
  179. return null;
  180. }
  181. return DB::transaction(function () use ($model): PartnerAgreement {
  182. $model->restore();
  183. $model->update(['status' => PartnerAgreementStatusEnum::ACTIVE]);
  184. $model->user?->update(['status' => UserStatusEnum::ACTIVE]);
  185. return $model->fresh();
  186. });
  187. }
  188. public function delete(int $id): bool
  189. {
  190. $model = PartnerAgreement::find($id);
  191. if (!$model) {
  192. return false;
  193. }
  194. return DB::transaction(function () use ($model): bool {
  195. $model->services()->delete();
  196. $model->user?->update(['status' => UserStatusEnum::INACTIVE]);
  197. $model->update(['status' => PartnerAgreementStatusEnum::INACTIVE]);
  198. return (bool) $model->delete();
  199. });
  200. }
  201. }