|
|
@@ -13,8 +13,10 @@ use App\Models\Schedule;
|
|
|
use App\Models\ScheduleProposal;
|
|
|
use App\Models\Speciality;
|
|
|
use App\Rules\ScheduleBusinessRules;
|
|
|
+use App\Services\DistanceService;
|
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
+use Illuminate\Support\Facades\Storage;
|
|
|
|
|
|
class DashboardService
|
|
|
{
|
|
|
@@ -26,7 +28,7 @@ class DashboardService
|
|
|
{
|
|
|
$user = Auth::user();
|
|
|
|
|
|
- $cliente = Client::where('user_id', $user->id)->first();
|
|
|
+ $cliente = Client::with('profileMedia')->where('user_id', $user->id)->first();
|
|
|
|
|
|
$headerBar = [
|
|
|
'rating' => $cliente->average_rating,
|
|
|
@@ -45,6 +47,9 @@ class DashboardService
|
|
|
|
|
|
$summaryInfos = [
|
|
|
'name' => $user->name,
|
|
|
+ 'profile_photo' => $cliente->profileMedia?->path
|
|
|
+ ? Storage::temporaryUrl($cliente->profileMedia->path, now()->addMinutes(60))
|
|
|
+ : null,
|
|
|
'address' => $address,
|
|
|
'pending_services' => Schedule::where('client_id', $cliente->id)
|
|
|
->where('status', 'pending')
|
|
|
@@ -58,6 +63,7 @@ class DashboardService
|
|
|
->leftJoin('providers', 'providers.id', '=', 'schedules.provider_id')
|
|
|
->leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
|
|
|
->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
|
|
|
+ ->leftJoin('media as provider_media', 'provider_media.id', '=', 'providers.profile_media_id')
|
|
|
->where('schedules.date', '>=', now()->toDateString())
|
|
|
->select(
|
|
|
'schedules.id',
|
|
|
@@ -71,11 +77,19 @@ class DashboardService
|
|
|
'schedules.schedule_type',
|
|
|
'schedules.address_id',
|
|
|
'custom_schedules.address_type as custom_address_type',
|
|
|
+ 'provider_media.path as provider_photo_path',
|
|
|
)
|
|
|
->orderBy('schedules.date', 'asc')
|
|
|
->limit(5)
|
|
|
->get();
|
|
|
|
|
|
+ $nextSchedules->each(function ($item) {
|
|
|
+ $item->provider_photo = $item->provider_photo_path
|
|
|
+ ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($item->provider_photo_path);
|
|
|
+ });
|
|
|
+
|
|
|
$lastDoneSchedules = Schedule::where('schedules.client_id', $cliente->id)
|
|
|
->where('schedules.status', 'finished')
|
|
|
->leftJoin('providers', 'providers.id', '=', 'schedules.provider_id')
|
|
|
@@ -85,16 +99,25 @@ class DashboardService
|
|
|
->where('provider_address.source', 'provider')
|
|
|
->orderBy('provider_address.is_primary', 'desc');
|
|
|
})
|
|
|
+ ->leftJoin('media as provider_media', 'provider_media.id', '=', 'providers.profile_media_id')
|
|
|
->select(
|
|
|
'schedules.id',
|
|
|
'schedules.provider_id',
|
|
|
'provider_user.name as provider_name',
|
|
|
'provider_address.district as provider_district',
|
|
|
+ 'provider_media.path as provider_photo_path',
|
|
|
)
|
|
|
->orderBy('schedules.date', 'desc')
|
|
|
->limit(5)
|
|
|
->get();
|
|
|
|
|
|
+ $lastDoneSchedules->each(function ($item) {
|
|
|
+ $item->provider_photo = $item->provider_photo_path
|
|
|
+ ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($item->provider_photo_path);
|
|
|
+ });
|
|
|
+
|
|
|
$favoriteProviders = ClientFavoriteProvider::where('client_favorite_providers.client_id', $cliente->id)
|
|
|
->leftJoin('providers', 'providers.id', '=', 'client_favorite_providers.provider_id')
|
|
|
->leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
|
|
|
@@ -103,17 +126,26 @@ class DashboardService
|
|
|
->where('provider_address.source', 'provider')
|
|
|
->orderBy('provider_address.is_primary', 'desc');
|
|
|
})
|
|
|
+ ->leftJoin('media as provider_media', 'provider_media.id', '=', 'providers.profile_media_id')
|
|
|
->select(
|
|
|
'providers.id as provider_id',
|
|
|
'provider_user.name as provider_name',
|
|
|
'providers.average_rating',
|
|
|
'provider_address.district as provider_district',
|
|
|
+ 'provider_media.path as provider_photo_path',
|
|
|
)
|
|
|
->orderBy('client_favorite_providers.created_at', 'desc')
|
|
|
->limit(5)
|
|
|
->get();
|
|
|
|
|
|
- $blockedProviderIds = ScheduleBusinessRules::getBlockedProviderIdsForClient($cliente->id);
|
|
|
+ $favoriteProviders->each(function ($item) {
|
|
|
+ $item->provider_photo = $item->provider_photo_path
|
|
|
+ ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($item->provider_photo_path);
|
|
|
+ });
|
|
|
+
|
|
|
+ $blockedProviderIds = ScheduleBusinessRules::getBlockedProviderIdsForClient($cliente->id);
|
|
|
$providersWithWorkingDays = ScheduleBusinessRules::getProviderIdsWithWorkingDays();
|
|
|
|
|
|
$clientPrimaryAddress = Address::where('source', 'client')
|
|
|
@@ -137,6 +169,7 @@ class DashboardService
|
|
|
ORDER BY source_id, is_primary DESC
|
|
|
) as provider_address
|
|
|
"), 'provider_address.source_id', '=', 'providers.id')
|
|
|
+ ->leftJoin('media as provider_media', 'provider_media.id', '=', 'providers.profile_media_id')
|
|
|
->whereNotNull('provider_address.id')
|
|
|
->where('provider_address.city_id', $clientPrimaryAddress?->city_id)
|
|
|
->whereNotIn('providers.id', $blockedProviderIds)
|
|
|
@@ -163,15 +196,24 @@ class DashboardService
|
|
|
AND schedules.provider_id = providers.id
|
|
|
) as total_reviews"),
|
|
|
$providersCloseDistanceSelect,
|
|
|
+ 'provider_media.path as provider_photo_path',
|
|
|
)
|
|
|
->get();
|
|
|
|
|
|
+ $providersClose->each(function ($item) {
|
|
|
+ $item->provider_photo = $item->provider_photo_path
|
|
|
+ ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($item->provider_photo_path);
|
|
|
+ });
|
|
|
+
|
|
|
$pendingSchedules = Schedule::with('address:district,address,number,source_id,source,id,address_type')
|
|
|
->where('schedules.client_id', $cliente->id)
|
|
|
->whereIn('schedules.status', ['pending', 'accepted'])
|
|
|
->where('schedules.schedule_type', 'default')
|
|
|
->leftJoin('providers', 'providers.id', '=', 'schedules.provider_id')
|
|
|
->leftJoin('users as provider_user', 'provider_user.id', '=', 'providers.user_id')
|
|
|
+ ->leftJoin('media as provider_media', 'provider_media.id', '=', 'providers.profile_media_id')
|
|
|
->select(
|
|
|
'schedules.id',
|
|
|
'schedules.provider_id',
|
|
|
@@ -186,15 +228,37 @@ class DashboardService
|
|
|
WHEN (now() - schedules.created_at) < INTERVAL '1 hour' THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (now() - schedules.created_at)) / 60), 'min')
|
|
|
WHEN (now() - schedules.created_at) < INTERVAL '1 day' THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (now() - schedules.created_at)) / 3600), 'h')
|
|
|
ELSE CONCAT(ROUND(EXTRACT(EPOCH FROM (now() - schedules.created_at)) / 86400), 'd')
|
|
|
- END as time_since_request")
|
|
|
+ END as time_since_request"),
|
|
|
+ 'provider_media.path as provider_photo_path',
|
|
|
)
|
|
|
->orderBy('schedules.date', 'asc')
|
|
|
->get();
|
|
|
|
|
|
+ $pendingSchedules->each(function ($item) {
|
|
|
+ $item->provider_photo = $item->provider_photo_path
|
|
|
+ ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($item->provider_photo_path);
|
|
|
+ });
|
|
|
+
|
|
|
+ $proposalsDistanceSelect = DistanceService::sqlExpression(
|
|
|
+ $clientPrimaryAddress?->latitude !== null ? (float) $clientPrimaryAddress->latitude : null,
|
|
|
+ $clientPrimaryAddress?->longitude !== null ? (float) $clientPrimaryAddress->longitude : null,
|
|
|
+ );
|
|
|
+
|
|
|
$schedulesProposals = ScheduleProposal::query()
|
|
|
->leftJoin('schedules', 'schedule_proposals.schedule_id', '=', 'schedules.id')
|
|
|
->leftJoin('providers', 'schedule_proposals.provider_id', '=', 'providers.id')
|
|
|
->leftJoin('users', 'providers.user_id', '=', 'users.id')
|
|
|
+ ->leftJoin(DB::raw("(
|
|
|
+ SELECT DISTINCT ON (source_id)
|
|
|
+ *
|
|
|
+ FROM addresses
|
|
|
+ WHERE source = 'provider'
|
|
|
+ AND deleted_at IS NULL
|
|
|
+ ORDER BY source_id, is_primary DESC
|
|
|
+ ) as provider_address"), 'provider_address.source_id', '=', 'providers.id')
|
|
|
+ ->leftJoin('media as provider_media', 'provider_media.id', '=', 'providers.profile_media_id')
|
|
|
->where('schedules.client_id', $cliente->id)
|
|
|
->where('schedules.schedule_type', 'custom')
|
|
|
->where('schedules.status', 'pending')
|
|
|
@@ -217,9 +281,18 @@ class DashboardService
|
|
|
'providers.total_services',
|
|
|
|
|
|
'users.name as provider_name',
|
|
|
+ $proposalsDistanceSelect,
|
|
|
+ 'provider_media.path as provider_photo_path',
|
|
|
])
|
|
|
->get();
|
|
|
|
|
|
+ $schedulesProposals->each(function ($item) {
|
|
|
+ $item->provider_photo = $item->provider_photo_path
|
|
|
+ ? Storage::temporaryUrl($item->provider_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($item->provider_photo_path);
|
|
|
+ });
|
|
|
+
|
|
|
$todaySchedules = Schedule::with('address:district,address,number,source_id,source,id,address_type')
|
|
|
->where('schedules.client_id', $cliente->id)
|
|
|
->whereIn('schedules.status', ['accepted', 'paid', 'started', 'finished'])
|
|
|
@@ -241,7 +314,7 @@ class DashboardService
|
|
|
'schedules.status',
|
|
|
'schedules.code_verified',
|
|
|
'schedules.code',
|
|
|
- 'media.url as provider_photo',
|
|
|
+ 'media.path as provider_photo',
|
|
|
DB::raw("EXISTS(
|
|
|
SELECT 1 FROM reviews
|
|
|
WHERE reviews.schedule_id = schedules.id
|
|
|
@@ -251,7 +324,13 @@ class DashboardService
|
|
|
) as client_reviewed"),
|
|
|
)
|
|
|
->orderBy('schedules.start_time', 'asc')
|
|
|
- ->get();
|
|
|
+ ->get()
|
|
|
+ ->map(function ($item) {
|
|
|
+ $item->provider_photo = $item->provider_photo
|
|
|
+ ? Storage::temporaryUrl($item->provider_photo, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ return $item;
|
|
|
+ });
|
|
|
|
|
|
$hasPaymentMethods = ClientPaymentMethod::where('client_id', $cliente->id)->exists();
|
|
|
|
|
|
@@ -285,7 +364,7 @@ class DashboardService
|
|
|
'schedules.provider_id',
|
|
|
'provider_user.name as provider_name',
|
|
|
'providers.birth_date as provider_birth_date',
|
|
|
- 'media.url as provider_photo',
|
|
|
+ 'media.path as provider_photo',
|
|
|
'custom_schedules.offers_meal',
|
|
|
)
|
|
|
->firstOrFail();
|
|
|
@@ -308,7 +387,9 @@ class DashboardService
|
|
|
return [
|
|
|
'provider_name' => $schedule->provider_name,
|
|
|
'provider_birth_date' => $schedule->provider_birth_date,
|
|
|
- 'provider_photo' => $schedule->provider_photo,
|
|
|
+ 'provider_photo' => $schedule->provider_photo
|
|
|
+ ? Storage::temporaryUrl($schedule->provider_photo, now()->addMinutes(60))
|
|
|
+ : null,
|
|
|
'offers_meal' => $schedule->offers_meal,
|
|
|
'specialities' => $specialities,
|
|
|
];
|
|
|
@@ -318,7 +399,7 @@ class DashboardService
|
|
|
{
|
|
|
$user = Auth::user();
|
|
|
|
|
|
- $provider = Provider::where('user_id', $user->id)->first();
|
|
|
+ $provider = Provider::with('profileMedia')->where('user_id', $user->id)->first();
|
|
|
|
|
|
$headerBar = [
|
|
|
'rating' => $provider->average_rating,
|
|
|
@@ -330,6 +411,9 @@ class DashboardService
|
|
|
|
|
|
$summaryInfos = [
|
|
|
'name' => $user->name,
|
|
|
+ 'profile_photo' => $provider->profileMedia?->path
|
|
|
+ ? Storage::temporaryUrl($provider->profileMedia->path, now()->addMinutes(60))
|
|
|
+ : null,
|
|
|
'address' => $address,
|
|
|
'pending_services' => Schedule::where('provider_id', $provider->id)->where('status', 'pending')->count(),
|
|
|
];
|
|
|
@@ -346,11 +430,12 @@ class DashboardService
|
|
|
'your_price' => $priceActual,
|
|
|
];
|
|
|
|
|
|
- $solicitations = Schedule::with('address:district,source_id,source,id')
|
|
|
+ $solicitations = Schedule::with('address:district,source_id,source,id,latitude,longitude')
|
|
|
->where('schedules.provider_id', $provider->id)
|
|
|
->where('schedules.status', 'pending')
|
|
|
->leftJoin('clients', 'clients.id', '=', 'schedules.client_id')
|
|
|
->leftJoin('users as client_user', 'client_user.id', '=', 'clients.user_id')
|
|
|
+ ->leftJoin('media as client_media', 'client_media.id', '=', 'clients.profile_media_id')
|
|
|
->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
|
|
|
->select(
|
|
|
'schedules.id',
|
|
|
@@ -366,6 +451,7 @@ class DashboardService
|
|
|
'schedules.address_id',
|
|
|
'schedules.status',
|
|
|
'custom_schedules.offers_meal',
|
|
|
+ 'client_media.path as customer_photo_path',
|
|
|
DB::raw("CASE
|
|
|
WHEN (now() - schedules.created_at) < INTERVAL '1 day' THEN CONCAT(ROUND(EXTRACT(EPOCH FROM (now() - schedules.created_at)) / 3600), ' hours ago')
|
|
|
ELSE CONCAT(ROUND(EXTRACT(EPOCH FROM (now() - schedules.created_at)) / 86400), ' days ago')
|
|
|
@@ -374,12 +460,29 @@ class DashboardService
|
|
|
->orderBy('schedules.date', 'asc')
|
|
|
->get();
|
|
|
|
|
|
+ $providerLat = $address?->latitude !== null ? (float) $address->latitude : null;
|
|
|
+ $providerLng = $address?->longitude !== null ? (float) $address->longitude : null;
|
|
|
+
|
|
|
+ $solicitations->each(function ($solicitation) use ($providerLat, $providerLng) {
|
|
|
+ $solicitation->customer_photo = $solicitation->customer_photo_path
|
|
|
+ ? Storage::temporaryUrl($solicitation->customer_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($solicitation->customer_photo_path);
|
|
|
+ $solicitation->distance_km = DistanceService::calculate(
|
|
|
+ $providerLat,
|
|
|
+ $providerLng,
|
|
|
+ $solicitation->address?->latitude !== null ? (float) $solicitation->address->latitude : null,
|
|
|
+ $solicitation->address?->longitude !== null ? (float) $solicitation->address->longitude : null,
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
$todayServices = Schedule::with('address:district,address,number,source_id,source,id')
|
|
|
->where('schedules.provider_id', $provider->id)
|
|
|
->whereIn('schedules.status', ['accepted', 'paid', 'started', 'finished'])
|
|
|
->whereDate('schedules.date', now()->toDateString())
|
|
|
->leftJoin('clients', 'clients.id', '=', 'schedules.client_id')
|
|
|
->leftJoin('users as client_user', 'client_user.id', '=', 'clients.user_id')
|
|
|
+ ->leftJoin('media as client_media', 'client_media.id', '=', 'clients.profile_media_id')
|
|
|
->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
|
|
|
->select(
|
|
|
'schedules.id',
|
|
|
@@ -396,6 +499,7 @@ class DashboardService
|
|
|
'schedules.code_verified',
|
|
|
'schedules.code',
|
|
|
'custom_schedules.offers_meal',
|
|
|
+ 'client_media.path as customer_photo_path',
|
|
|
DB::raw("EXISTS(
|
|
|
SELECT 1 FROM reviews
|
|
|
WHERE reviews.schedule_id = schedules.id
|
|
|
@@ -407,12 +511,20 @@ class DashboardService
|
|
|
->orderBy('schedules.start_time', 'asc')
|
|
|
->get();
|
|
|
|
|
|
- $nextSchedules = Schedule::with('address:district,address,number,source_id,source,id')
|
|
|
+ $todayServices->each(function ($s) {
|
|
|
+ $s->customer_photo = $s->customer_photo_path
|
|
|
+ ? Storage::temporaryUrl($s->customer_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($s->customer_photo_path);
|
|
|
+ });
|
|
|
+
|
|
|
+ $nextSchedules = Schedule::with('address:district,address,number,source_id,source,id,latitude,longitude')
|
|
|
->where('schedules.provider_id', $provider->id)
|
|
|
->whereIn('schedules.status', ['accepted', 'paid'])
|
|
|
->whereDate('schedules.date', '>=', now()->toDateString())
|
|
|
->leftJoin('clients', 'clients.id', '=', 'schedules.client_id')
|
|
|
->leftJoin('users as client_user', 'client_user.id', '=', 'clients.user_id')
|
|
|
+ ->leftJoin('media as client_media', 'client_media.id', '=', 'clients.profile_media_id')
|
|
|
->leftJoin('custom_schedules', 'custom_schedules.schedule_id', '=', 'schedules.id')
|
|
|
->select(
|
|
|
'schedules.id',
|
|
|
@@ -426,10 +538,24 @@ class DashboardService
|
|
|
'schedules.schedule_type',
|
|
|
'schedules.status',
|
|
|
'custom_schedules.offers_meal',
|
|
|
+ 'client_media.path as customer_photo_path',
|
|
|
)
|
|
|
->orderBy('schedules.date', 'asc')
|
|
|
->get();
|
|
|
|
|
|
+ $nextSchedules->each(function ($schedule) use ($providerLat, $providerLng) {
|
|
|
+ $schedule->customer_photo = $schedule->customer_photo_path
|
|
|
+ ? Storage::temporaryUrl($schedule->customer_photo_path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ unset($schedule->customer_photo_path);
|
|
|
+ $schedule->distance_km = DistanceService::calculate(
|
|
|
+ $providerLat,
|
|
|
+ $providerLng,
|
|
|
+ $schedule->address?->latitude !== null ? (float) $schedule->address->latitude : null,
|
|
|
+ $schedule->address?->longitude !== null ? (float) $schedule->address->longitude : null,
|
|
|
+ );
|
|
|
+ });
|
|
|
+
|
|
|
// $opportunities = Schedule::with('address:district,source_id,source,id')
|
|
|
// ->where('schedules.schedule_type', 'custom')
|
|
|
// ->where('schedules.status', 'pending')
|
|
|
@@ -462,6 +588,12 @@ class DashboardService
|
|
|
|
|
|
$opportunities = $this->customScheduleService->getAvailableOpportunities($provider->id);
|
|
|
|
|
|
+ $opportunities->each(function ($o) {
|
|
|
+ $o->customer_photo = $o->client?->profileMedia?->path
|
|
|
+ ? Storage::temporaryUrl($o->client->profileMedia->path, now()->addMinutes(60))
|
|
|
+ : null;
|
|
|
+ });
|
|
|
+
|
|
|
return [
|
|
|
'headerBar' => $headerBar,
|
|
|
'summaryInfos' => $summaryInfos,
|
|
|
@@ -475,27 +607,6 @@ class DashboardService
|
|
|
|
|
|
private function distanceSelect(?float $clientLatitude, ?float $clientLongitude): \Illuminate\Contracts\Database\Query\Expression
|
|
|
{
|
|
|
- if ($clientLatitude === null || $clientLongitude === null) {
|
|
|
- return DB::raw('NULL as distance_km');
|
|
|
- }
|
|
|
-
|
|
|
- return DB::raw("
|
|
|
- CASE
|
|
|
- WHEN provider_address.latitude IS NOT NULL
|
|
|
- AND provider_address.longitude IS NOT NULL
|
|
|
- THEN ROUND((
|
|
|
- 6371 * acos(
|
|
|
- least(1, greatest(-1,
|
|
|
- cos(radians({$clientLatitude}))
|
|
|
- * cos(radians(provider_address.latitude))
|
|
|
- * cos(radians(provider_address.longitude) - radians({$clientLongitude}))
|
|
|
- + sin(radians({$clientLatitude}))
|
|
|
- * sin(radians(provider_address.latitude))
|
|
|
- ))
|
|
|
- )
|
|
|
- )::numeric, 1)
|
|
|
- ELSE NULL
|
|
|
- END as distance_km
|
|
|
- ");
|
|
|
+ return DistanceService::sqlExpression($clientLatitude, $clientLongitude);
|
|
|
}
|
|
|
}
|