ReviewService.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. namespace App\Services;
  3. use App\Models\Client;
  4. use App\Models\ClientFavoriteProvider;
  5. use App\Models\ClientProviderBlock;
  6. use App\Models\Provider;
  7. use App\Models\ProviderClientBlock;
  8. use App\Models\Review;
  9. use App\Models\ReviewMedia;
  10. use App\Models\Schedule;
  11. use Exception;
  12. use Illuminate\Support\Facades\DB;
  13. use Illuminate\Support\Facades\Log;
  14. use Illuminate\Support\Facades\Storage;
  15. class ReviewService
  16. {
  17. public function __construct(private readonly MediaService $mediaService) {}
  18. public function getAll()
  19. {
  20. return Review::with(['schedule.client.user', 'schedule.provider.user', 'reviewsImprovements.improvementType'])
  21. ->orderBy('created_at', 'desc')
  22. ->get();
  23. }
  24. public function getByScheduleId(int $scheduleId)
  25. {
  26. return Review::with(['schedule.client.user', 'schedule.provider.user'])
  27. ->where('schedule_id', $scheduleId)
  28. ->orderBy('created_at', 'desc')
  29. ->get();
  30. }
  31. public function getByOrigin(string $origin, int $originId)
  32. {
  33. return Review::with(['schedule.client.user', 'schedule.provider.user'])
  34. ->where('origin', $origin)
  35. ->where('origin_id', $originId)
  36. ->orderBy('created_at', 'desc')
  37. ->get();
  38. }
  39. public function create(array $data): Review
  40. {
  41. try {
  42. DB::beginTransaction();
  43. $review = new Review;
  44. $review->fill($data);
  45. $review->save();
  46. $review->refresh();
  47. if (isset($data['origin']) && isset($data['origin_id'])) {
  48. switch ($data['origin']) {
  49. case 'client':
  50. $schedule = Schedule::find($data['schedule_id']);
  51. $provider = Provider::find($schedule->provider_id);
  52. $provider->updateAverageRating((float) $data['stars']);
  53. break;
  54. case 'provider':
  55. $schedule = Schedule::find($data['schedule_id']);
  56. $client = Client::find($schedule->client_id);
  57. $client->updateAverageRating((float) $data['stars']);
  58. break;
  59. }
  60. }
  61. if (isset($data['improvements_ids'])) {
  62. $review->improvements()->sync($data['improvements_ids']);
  63. }
  64. if (! empty($data['block_provider'])) {
  65. $schedule = Schedule::find($data['schedule_id']);
  66. $alreadyBlocked = ClientProviderBlock::where('client_id', $schedule->client_id)
  67. ->where('provider_id', $schedule->provider_id)
  68. ->whereNull('deleted_at')
  69. ->exists();
  70. if (! $alreadyBlocked) {
  71. ClientProviderBlock::create([
  72. 'client_id' => $schedule->client_id,
  73. 'provider_id' => $schedule->provider_id,
  74. ]);
  75. }
  76. }
  77. if (! empty($data['block_client'])) {
  78. $schedule = Schedule::find($data['schedule_id']);
  79. $alreadyBlocked = ProviderClientBlock::where('provider_id', $schedule->provider_id)
  80. ->where('client_id', $schedule->client_id)
  81. ->whereNull('deleted_at')
  82. ->exists();
  83. if (! $alreadyBlocked) {
  84. ProviderClientBlock::create([
  85. 'provider_id' => $schedule->provider_id,
  86. 'client_id' => $schedule->client_id,
  87. ]);
  88. }
  89. }
  90. if (! empty($data['favorite_provider'])) {
  91. $schedule = Schedule::find($data['schedule_id']);
  92. $alreadyFavorited = ClientFavoriteProvider::where('client_id', $schedule->client_id)
  93. ->where('provider_id', $schedule->provider_id)
  94. ->whereNull('deleted_at')
  95. ->exists();
  96. if (! $alreadyFavorited) {
  97. ClientFavoriteProvider::create([
  98. 'client_id' => $schedule->client_id,
  99. 'provider_id' => $schedule->provider_id,
  100. ]);
  101. }
  102. }
  103. if (! empty($data['photos'])) {
  104. $schedule = Schedule::find($data['schedule_id']);
  105. $origin = $data['origin'];
  106. foreach ($data['photos'] as $photo) {
  107. $media = $this->mediaService->createFromFile(
  108. file: $photo,
  109. folder: "review/{$schedule->id}/{$origin}",
  110. source: 'review',
  111. sourceId: $review->id,
  112. );
  113. ReviewMedia::create([
  114. 'review_id' => $review->id,
  115. 'media_id' => $media->id,
  116. 'origin' => $origin,
  117. ]);
  118. }
  119. }
  120. DB::commit();
  121. return $review->load('reviewMedia.media');
  122. } catch (Exception $e) {
  123. DB::rollBack();
  124. Log::error('Error creating review: '.$e->getMessage());
  125. throw $e;
  126. }
  127. }
  128. private function detailEagerLoads(): array
  129. {
  130. return [
  131. 'schedule.client.user',
  132. 'schedule.client.profileMedia',
  133. 'schedule.provider.user',
  134. 'schedule.address.city',
  135. 'schedule.address.state',
  136. 'schedule.customSchedule.serviceType',
  137. 'schedule.customSchedule.specialities',
  138. 'improvements',
  139. ];
  140. }
  141. public function getByClientSent(int $clientId)
  142. {
  143. return Review::with($this->detailEagerLoads())
  144. ->whereIn('origin', ['client', 'clients'])
  145. ->where('origin_id', $clientId)
  146. ->orderBy('created_at', 'desc')
  147. ->get();
  148. }
  149. public function getByClientReceived(int $clientId)
  150. {
  151. return Review::with($this->detailEagerLoads())
  152. ->whereIn('origin', ['provider', 'providers'])
  153. ->whereHas('schedule', fn ($q) => $q->where('client_id', $clientId))
  154. ->orderBy('created_at', 'desc')
  155. ->get();
  156. }
  157. public function getByProviderSent(int $providerId)
  158. {
  159. return Review::with($this->detailEagerLoads())
  160. ->whereIn('origin', ['provider', 'providers'])
  161. ->where('origin_id', $providerId)
  162. ->orderBy('created_at', 'desc')
  163. ->get();
  164. }
  165. public function getByProviderReceived(int $providerId)
  166. {
  167. $reviews = Review::with($this->detailEagerLoads())
  168. ->whereIn('origin', ['client', 'clients'])
  169. ->whereHas('schedule', fn ($q) => $q->where('provider_id', $providerId))
  170. ->orderBy('created_at', 'desc')
  171. ->get();
  172. foreach ($reviews as $review) {
  173. if ($review->schedule?->client?->profileMedia?->path) {
  174. $review->schedule->client->profile_photo = Storage::temporaryUrl($review->schedule->client->profileMedia->path, now()->addMinutes(60));
  175. } else {
  176. $review->schedule->client->profile_photo = null;
  177. }
  178. }
  179. return $reviews;
  180. }
  181. public function update(int $id, array $data): Review
  182. {
  183. $review = Review::findOrFail($id);
  184. $review->update($data);
  185. return $review->fresh();
  186. }
  187. public function delete(int $id): bool
  188. {
  189. $review = Review::findOrFail($id);
  190. return $review->delete();
  191. }
  192. }