|
|
@@ -26,6 +26,8 @@ use Illuminate\Support\Facades\Storage;
|
|
|
|
|
|
class DashboardService
|
|
|
{
|
|
|
+ private const NEARBY_RADIUS_KM = 20.0;
|
|
|
+
|
|
|
public function __construct(
|
|
|
private readonly CustomScheduleService $customScheduleService,
|
|
|
private readonly ZipCodeCoordinatesService $zipCodeCoordinatesService,
|
|
|
@@ -55,6 +57,8 @@ class DashboardService
|
|
|
->where('source_id', $cliente->id)
|
|
|
->with(['city', 'state'])
|
|
|
->select('id', 'source', 'source_id', 'address', 'number', 'district', 'nickname', 'address_type', 'city_id', 'state_id', 'is_primary')
|
|
|
+ ->orderByDesc('is_primary')
|
|
|
+ ->orderByDesc('id')
|
|
|
->first();
|
|
|
|
|
|
$summaryInfos = [
|
|
|
@@ -194,17 +198,15 @@ class DashboardService
|
|
|
->orderByDesc('id')
|
|
|
->first();
|
|
|
|
|
|
- $clientDistanceAddress = $this->addressForDistance($cliente->id, $clientPrimaryAddress);
|
|
|
+ $providersCloseCityId = $clientPrimaryAddress?->city_id;
|
|
|
+ $providersCloseLatitude = $clientPrimaryAddress?->latitude !== null ? (float) $clientPrimaryAddress->latitude : null;
|
|
|
+ $providersCloseLongitude = $clientPrimaryAddress?->longitude !== null ? (float) $clientPrimaryAddress->longitude : null;
|
|
|
|
|
|
- $clientCoordinates = $this->zipCodeCoordinatesService->resolve(
|
|
|
- $clientDistanceAddress?->latitude !== null ? (float) $clientDistanceAddress->latitude : null,
|
|
|
- $clientDistanceAddress?->longitude !== null ? (float) $clientDistanceAddress->longitude : null,
|
|
|
- $clientDistanceAddress?->zip_code,
|
|
|
- );
|
|
|
+ $hasLocation = $providersCloseLatitude !== null && $providersCloseLongitude !== null;
|
|
|
|
|
|
$providersCloseDistanceSelect = $this->distanceSelect(
|
|
|
- data_get($clientCoordinates, 'latitude'),
|
|
|
- data_get($clientCoordinates, 'longitude'),
|
|
|
+ $providersCloseLatitude,
|
|
|
+ $providersCloseLongitude,
|
|
|
);
|
|
|
|
|
|
$providerAddressLatestSubquery = DB::raw("
|
|
|
@@ -223,107 +225,121 @@ class DashboardService
|
|
|
) AS provider_address
|
|
|
");
|
|
|
|
|
|
- $providersClose = Provider::leftJoin(
|
|
|
- 'users as provider_user',
|
|
|
- 'provider_user.id',
|
|
|
- '=',
|
|
|
- 'providers.user_id'
|
|
|
- )
|
|
|
- ->visibleToCustomers()
|
|
|
- ->leftJoin(
|
|
|
- $providerAddressLatestSubquery,
|
|
|
- 'provider_address.source_id',
|
|
|
+ $providersClose = $hasLocation
|
|
|
+ ? Provider::leftJoin(
|
|
|
+ 'users as provider_user',
|
|
|
+ 'provider_user.id',
|
|
|
'=',
|
|
|
- 'providers.id'
|
|
|
+ 'providers.user_id'
|
|
|
)
|
|
|
- ->whereNotNull('provider_address.id')
|
|
|
- ->when(
|
|
|
- $clientPrimaryAddress?->city_id,
|
|
|
- fn($query, int $cityId) => $query->where('provider_address.city_id', $cityId)
|
|
|
- )
|
|
|
- ->whereNotIn('providers.id', $blockedProviderIds)
|
|
|
- ->whereIn('providers.id', $providersWithWorkingDays)
|
|
|
- ->whereNull('providers.deleted_at')
|
|
|
- ->select(
|
|
|
- 'providers.id as provider_id',
|
|
|
- 'provider_user.name as provider_name',
|
|
|
- 'providers.gender',
|
|
|
- 'provider_address.id as address_id',
|
|
|
- 'provider_address.zip_code as provider_zip_code',
|
|
|
- 'provider_address.district',
|
|
|
- 'provider_address.latitude as provider_latitude',
|
|
|
- 'provider_address.longitude as provider_longitude',
|
|
|
- 'providers.average_rating',
|
|
|
- 'providers.total_services',
|
|
|
- 'providers.daily_price_8h',
|
|
|
- 'providers.daily_price_6h',
|
|
|
- 'providers.daily_price_4h',
|
|
|
- 'providers.daily_price_2h',
|
|
|
-
|
|
|
- DB::raw("
|
|
|
- (
|
|
|
- SELECT COUNT(*)
|
|
|
- FROM reviews
|
|
|
- LEFT JOIN schedules
|
|
|
- ON schedules.id = reviews.schedule_id
|
|
|
- WHERE reviews.origin = 'provider'
|
|
|
- AND schedules.provider_id = providers.id
|
|
|
- ) AS total_reviews
|
|
|
- "),
|
|
|
+ ->visibleToCustomers()
|
|
|
+ ->leftJoin(
|
|
|
+ $providerAddressLatestSubquery,
|
|
|
+ 'provider_address.source_id',
|
|
|
+ '=',
|
|
|
+ 'providers.id'
|
|
|
+ )
|
|
|
+ ->whereNotNull('provider_address.id')
|
|
|
+ ->where(function ($query) use ($providersCloseCityId, $providersCloseLatitude, $providersCloseLongitude) {
|
|
|
+ if ($providersCloseCityId !== null) {
|
|
|
+ $query->orWhere('provider_address.city_id', $providersCloseCityId);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($providersCloseLatitude !== null && $providersCloseLongitude !== null) {
|
|
|
+ $query->orWhereRaw(
|
|
|
+ DistanceService::withinRadiusSqlCondition(
|
|
|
+ (float) $providersCloseLatitude,
|
|
|
+ (float) $providersCloseLongitude,
|
|
|
+ self::NEARBY_RADIUS_KM,
|
|
|
+ )
|
|
|
+ );
|
|
|
+ }
|
|
|
+ })
|
|
|
+ ->whereNotIn('providers.id', $blockedProviderIds)
|
|
|
+ ->whereIn('providers.id', $providersWithWorkingDays)
|
|
|
+ ->whereNull('providers.deleted_at')
|
|
|
+ ->select(
|
|
|
+ 'providers.id as provider_id',
|
|
|
+ 'provider_user.name as provider_name',
|
|
|
+ 'providers.gender',
|
|
|
+ 'provider_address.id as address_id',
|
|
|
+ 'provider_address.zip_code as provider_zip_code',
|
|
|
+ 'provider_address.district',
|
|
|
+ 'provider_address.latitude as provider_latitude',
|
|
|
+ 'provider_address.longitude as provider_longitude',
|
|
|
+ 'providers.average_rating',
|
|
|
+ 'providers.total_services',
|
|
|
+ 'providers.daily_price_8h',
|
|
|
+ 'providers.daily_price_6h',
|
|
|
+ 'providers.daily_price_4h',
|
|
|
+ 'providers.daily_price_2h',
|
|
|
+
|
|
|
+ DB::raw("
|
|
|
+ (
|
|
|
+ SELECT COUNT(*)
|
|
|
+ FROM reviews
|
|
|
+ LEFT JOIN schedules
|
|
|
+ ON schedules.id = reviews.schedule_id
|
|
|
+ WHERE reviews.origin = 'provider'
|
|
|
+ AND schedules.provider_id = providers.id
|
|
|
+ ) AS total_reviews
|
|
|
+ "),
|
|
|
|
|
|
- $providersCloseDistanceSelect,
|
|
|
- )
|
|
|
- ->orderByRaw('distance_km ASC NULLS LAST')
|
|
|
- ->get();
|
|
|
+ $providersCloseDistanceSelect,
|
|
|
+ )
|
|
|
+ ->orderByRaw('distance_km ASC NULLS LAST')
|
|
|
+ ->get()
|
|
|
+ : collect();
|
|
|
|
|
|
- $this->zipCodeCoordinatesService->preload(
|
|
|
- $providersClose->whereNull('distance_km')->pluck('provider_zip_code')
|
|
|
- );
|
|
|
+ if ($hasLocation) {
|
|
|
+ $this->zipCodeCoordinatesService->preload(
|
|
|
+ $providersClose->whereNull('distance_km')->pluck('provider_zip_code')
|
|
|
+ );
|
|
|
|
|
|
- $providersClose->each(function ($item) use ($clientDistanceAddress) {
|
|
|
- $item->gender_label = GenderEnum::labelFor($item->gender);
|
|
|
+ $providersClose->each(function ($item) use ($clientPrimaryAddress) {
|
|
|
+ $item->gender_label = GenderEnum::labelFor($item->gender);
|
|
|
|
|
|
- if ($item->distance_km === null) {
|
|
|
- $item->distance_km = $this->zipCodeCoordinatesService->calculateDistance(
|
|
|
- $clientDistanceAddress?->latitude !== null ? (float) $clientDistanceAddress->latitude : null,
|
|
|
- $clientDistanceAddress?->longitude !== null ? (float) $clientDistanceAddress->longitude : null,
|
|
|
- $clientDistanceAddress?->zip_code,
|
|
|
- $item->provider_latitude !== null ? (float) $item->provider_latitude : null,
|
|
|
- $item->provider_longitude !== null ? (float) $item->provider_longitude : null,
|
|
|
- $item->provider_zip_code,
|
|
|
- );
|
|
|
- }
|
|
|
- $item->specialities = ProviderSpeciality::query()
|
|
|
- ->join('specialities', 'specialities.id', '=', 'provider_specialities.speciality_id')
|
|
|
- ->where('provider_specialities.provider_id', $item->provider_id)
|
|
|
- ->where('specialities.active', true)
|
|
|
- ->orderBy('specialities.description')
|
|
|
- ->get([
|
|
|
- 'specialities.id',
|
|
|
- 'specialities.description',
|
|
|
- ]);
|
|
|
-
|
|
|
- $item->age = Provider::query()
|
|
|
- ->where('id', $item->provider_id)
|
|
|
- ->value(DB::raw("DATE_PART('year', AGE(birth_date))"));
|
|
|
-
|
|
|
- unset($item->provider_zip_code);
|
|
|
-
|
|
|
- $item->daily_price_8h_base = $item->daily_price_8h;
|
|
|
- $item->daily_price_6h_base = $item->daily_price_6h;
|
|
|
- $item->daily_price_4h_base = $item->daily_price_4h;
|
|
|
- $item->daily_price_2h_base = $item->daily_price_2h;
|
|
|
-
|
|
|
- $item->daily_price_8h = $this->applyCreditCardFee($item->daily_price_8h);
|
|
|
- $item->daily_price_6h = $this->applyCreditCardFee($item->daily_price_6h);
|
|
|
- $item->daily_price_4h = $this->applyCreditCardFee($item->daily_price_4h);
|
|
|
- $item->daily_price_2h = $this->applyCreditCardFee($item->daily_price_2h);
|
|
|
- });
|
|
|
+ if ($item->distance_km === null) {
|
|
|
+ $item->distance_km = $this->zipCodeCoordinatesService->calculateDistance(
|
|
|
+ $clientPrimaryAddress?->latitude !== null ? (float) $clientPrimaryAddress->latitude : null,
|
|
|
+ $clientPrimaryAddress?->longitude !== null ? (float) $clientPrimaryAddress->longitude : null,
|
|
|
+ $clientPrimaryAddress?->zip_code,
|
|
|
+ $item->provider_latitude !== null ? (float) $item->provider_latitude : null,
|
|
|
+ $item->provider_longitude !== null ? (float) $item->provider_longitude : null,
|
|
|
+ $item->provider_zip_code,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ $item->specialities = ProviderSpeciality::query()
|
|
|
+ ->join('specialities', 'specialities.id', '=', 'provider_specialities.speciality_id')
|
|
|
+ ->where('provider_specialities.provider_id', $item->provider_id)
|
|
|
+ ->where('specialities.active', true)
|
|
|
+ ->orderBy('specialities.description')
|
|
|
+ ->get([
|
|
|
+ 'specialities.id',
|
|
|
+ 'specialities.description',
|
|
|
+ ]);
|
|
|
+
|
|
|
+ $item->age = Provider::query()
|
|
|
+ ->where('id', $item->provider_id)
|
|
|
+ ->value(DB::raw("DATE_PART('year', AGE(birth_date))"));
|
|
|
+
|
|
|
+ unset($item->provider_zip_code);
|
|
|
+
|
|
|
+ $item->daily_price_8h_base = $item->daily_price_8h;
|
|
|
+ $item->daily_price_6h_base = $item->daily_price_6h;
|
|
|
+ $item->daily_price_4h_base = $item->daily_price_4h;
|
|
|
+ $item->daily_price_2h_base = $item->daily_price_2h;
|
|
|
+
|
|
|
+ $item->daily_price_8h = $this->applyCreditCardFee($item->daily_price_8h);
|
|
|
+ $item->daily_price_6h = $this->applyCreditCardFee($item->daily_price_6h);
|
|
|
+ $item->daily_price_4h = $this->applyCreditCardFee($item->daily_price_4h);
|
|
|
+ $item->daily_price_2h = $this->applyCreditCardFee($item->daily_price_2h);
|
|
|
+ });
|
|
|
|
|
|
- $providersClose = $providersClose
|
|
|
- ->sortBy(fn($provider) => $provider->distance_km ?? PHP_FLOAT_MAX)
|
|
|
- ->sortBy(fn($provider) => $provider->distance_km ?? PHP_FLOAT_MAX)
|
|
|
- ->values();
|
|
|
+ $providersClose = $providersClose
|
|
|
+ ->sortBy(fn($provider) => $provider->distance_km ?? PHP_FLOAT_MAX)
|
|
|
+ ->values();
|
|
|
+ }
|
|
|
|
|
|
$pendingSchedules = Schedule::with([
|
|
|
'address:district,address,number,source_id,source,id,address_type',
|
|
|
@@ -399,8 +415,8 @@ class DashboardService
|
|
|
});
|
|
|
|
|
|
$proposalsDistanceSelect = DistanceService::sqlExpression(
|
|
|
- data_get($clientCoordinates, 'latitude'),
|
|
|
- data_get($clientCoordinates, 'longitude'),
|
|
|
+ $providersCloseLatitude,
|
|
|
+ $providersCloseLongitude,
|
|
|
);
|
|
|
|
|
|
$schedulesProposals = ScheduleProposal::query()
|
|
|
@@ -433,6 +449,12 @@ class DashboardService
|
|
|
'=',
|
|
|
'providers.id'
|
|
|
)
|
|
|
+ ->leftJoin(
|
|
|
+ 'addresses as schedule_address',
|
|
|
+ 'schedule_address.id',
|
|
|
+ '=',
|
|
|
+ 'schedules.address_id'
|
|
|
+ )
|
|
|
->where('schedules.client_id', $cliente->id)
|
|
|
->where('schedules.schedule_type', 'custom')
|
|
|
->where('schedules.status', 'pending')
|
|
|
@@ -464,6 +486,11 @@ class DashboardService
|
|
|
'provider_address.longitude as provider_longitude',
|
|
|
'provider_address.zip_code as provider_zip_code',
|
|
|
|
|
|
+ 'schedule_address.address as address',
|
|
|
+ 'schedule_address.number as address_number',
|
|
|
+ 'schedule_address.district as address_district',
|
|
|
+ 'schedule_address.address_type as address_type',
|
|
|
+
|
|
|
$proposalsDistanceSelect,
|
|
|
])
|
|
|
->get();
|
|
|
@@ -479,14 +506,23 @@ class DashboardService
|
|
|
->doesntHave('proposals')
|
|
|
->get();
|
|
|
|
|
|
- $schedulesProposals->each(function ($item) use ($clientDistanceAddress) {
|
|
|
+ $schedulesProposals->each(function ($item) use ($clientPrimaryAddress) {
|
|
|
$item->gender_label = GenderEnum::labelFor($item->gender);
|
|
|
|
|
|
+ $item->address = [
|
|
|
+ 'address' => $item->address,
|
|
|
+ 'number' => $item->address_number,
|
|
|
+ 'district' => $item->address_district,
|
|
|
+ 'address_type' => $item->address_type,
|
|
|
+ ];
|
|
|
+
|
|
|
+ unset($item->address_number, $item->address_district);
|
|
|
+
|
|
|
if ($item->distance_km === null) {
|
|
|
$item->distance_km = $this->zipCodeCoordinatesService->calculateDistance(
|
|
|
- $clientDistanceAddress?->latitude !== null ? (float) $clientDistanceAddress->latitude : null,
|
|
|
- $clientDistanceAddress?->longitude !== null ? (float) $clientDistanceAddress->longitude : null,
|
|
|
- $clientDistanceAddress?->zip_code,
|
|
|
+ $clientPrimaryAddress?->latitude !== null ? (float) $clientPrimaryAddress->latitude : null,
|
|
|
+ $clientPrimaryAddress?->longitude !== null ? (float) $clientPrimaryAddress->longitude : null,
|
|
|
+ $clientPrimaryAddress?->zip_code,
|
|
|
$item->provider_latitude !== null ? (float) $item->provider_latitude : null,
|
|
|
$item->provider_longitude !== null ? (float) $item->provider_longitude : null,
|
|
|
$item->provider_zip_code,
|
|
|
@@ -632,6 +668,7 @@ class DashboardService
|
|
|
'customSchedulesNoProposals' => $custom_schedules_with_no_proposals,
|
|
|
'notifications' => $notifications,
|
|
|
'has_payment_methods' => $hasPaymentMethods,
|
|
|
+ 'has_location' => $hasLocation,
|
|
|
'pendingServicePackages' => $pendingServicePackages,
|
|
|
];
|
|
|
}
|
|
|
@@ -1075,21 +1112,6 @@ class DashboardService
|
|
|
|
|
|
//
|
|
|
|
|
|
- private function addressForDistance(int $clientId, ?Address $primaryAddress): ?Address
|
|
|
- {
|
|
|
- if ($primaryAddress?->latitude !== null && $primaryAddress?->longitude !== null) {
|
|
|
- return $primaryAddress;
|
|
|
- }
|
|
|
-
|
|
|
- return Address::where('source', 'client')
|
|
|
- ->where('source_id', $clientId)
|
|
|
- ->whereNotNull('latitude')
|
|
|
- ->whereNotNull('longitude')
|
|
|
- ->orderByDesc('is_primary')
|
|
|
- ->orderByDesc('id')
|
|
|
- ->first() ?? $primaryAddress;
|
|
|
- }
|
|
|
-
|
|
|
private function distanceSelect(?float $clientLatitude, ?float $clientLongitude): \Illuminate\Contracts\Database\Query\Expression
|
|
|
{
|
|
|
return DistanceService::sqlExpression($clientLatitude, $clientLongitude);
|