Created
November 2, 2022 03:53
-
-
Save ahsanmster/c5e844d1aaa093baa7396aa338312764 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers\Api\DrivingRoute; | |
use App\Http\Controllers\Controller; | |
use App\Http\Requests\DrivingRoute\DrivingRouteKpiRequest; | |
use App\Http\Requests\DrivingRoute\FilterDrivingRoutesRequest; | |
use App\Models\PropertyLeadStatus; | |
use App\Services\DrivingRoute\DrivingRouteService; | |
use App\Models\DrivingRoute\DrivingRoute; | |
use Carbon\Carbon; | |
class KpiRouteReportsController extends Controller | |
{ | |
/** | |
* @OA\Post( | |
* path="/api/driving-route/kpi-report/dashboard", | |
* operationId="DrivingRouteReport", | |
* tags={"DrivingRouteReport"}, | |
* summary="Driving Route Dashboard KPI", | |
* description="Driving Route Dashboard KPI", | |
* @OA\RequestBody( | |
* required = true, | |
* description = "", | |
* @OA\JsonContent( | |
* @OA\Property( | |
* property="from_date", | |
* type="date", | |
* example="2022-06-01", | |
* ), | |
* @OA\Property( | |
* property="to_date", | |
* type="date", | |
* example="2022-06-15", | |
* ), | |
* @OA\Property( | |
* property="team_member", | |
* type="boolean", | |
* example="1", | |
* ), | |
* @OA\Property( | |
* property="lead_status", | |
* type="integer", | |
* example="1", | |
* ), | |
* @OA\Property( | |
* property="route_type", | |
* type="integer", | |
* example="1", | |
* ), | |
* @OA\Property( | |
* property="driving_type", | |
* type="integer", | |
* example="1", | |
* ), | |
* ), | |
* ), | |
* @OA\Response( | |
* response="200", | |
* description="data found", | |
* @OA\JsonContent( | |
* type="json", | |
* format="application/json", | |
* example="" | |
* ) | |
* ), | |
* security={{ "apiAuth": {} }} | |
* ) | |
* @param FilterDrivingRoutesRequest $request | |
* @return | |
*/ | |
public function kpiReports(DrivingRouteKpiRequest $request) | |
{ | |
$userCompanyId = appCompanyId(); | |
if(!empty($request->lead_status)) { | |
$leadStatus = self::getPropertyLeadStatus($request->lead_status); | |
if(empty($leadStatus) || ($leadStatus->is_system != 1 && $leadStatus->user_id != $userCompanyId)) { | |
return response()->errorResponse('Invalid Lead Status', []); | |
} | |
} | |
if(!empty($request->team_member)) { | |
$user = appUserById($request->team_member); | |
if(empty($user) || ($userCompanyId != $user->company_id)){ | |
return response()->errorResponse('Invalid Team member', []); | |
} | |
} | |
$request->request->add([ | |
'timezone' => appCompanyUser()->default_timezone | |
]); | |
/** @var DrivingRouteService $drivingRouteService */ | |
$drivingRouteService = resolve(DrivingRouteService::class); | |
$response = $drivingRouteService->gateway($request)->getData(); | |
if (!empty($response->data->data)) { | |
$record = collect(($response->data)->data)->values(); | |
$dates = ($response->data)->dates; | |
$startDate = Carbon::parse($dates->start_date)->startOfDay(); | |
$endDate = Carbon::parse($dates->end_date)->endOfDay(); | |
$prevStartDate = Carbon::parse($dates->prev_start_date)->toDateString(); | |
$prevEndDate = $dates->prev_end_date; | |
// Applying lead status | |
if (!empty($request->lead_status) && $request->lead_status != 0) { | |
$recordWithLeadStatus = $drivingRouteService->getRecordsLeadStatus($record, $prevStartDate, $endDate, $request->lead_status); | |
$drivingRouteIds = $recordWithLeadStatus->pluck('driving_route_id'); | |
$record = $record->whereIn('driving_route_id', $drivingRouteIds); | |
$newRecord = collect(); | |
// the record(total properties count) coming from pgsql is against all lead status | |
// so i am calculating the record from mysql and updating in pgsql count | |
foreach ($record as $key => $rls){ | |
$newRecordObject = $rls; | |
$newRecordObject->property_count = $recordWithLeadStatus->where('driving_route_id', '=', $rls->driving_route_id)->sum('total_count'); | |
$newRecord->push($newRecordObject); | |
} | |
$record = $newRecord; | |
} | |
$record = ($record->groupBy('name')->values()); // all record previous & current | |
$formattedArray = self::createArray($record); | |
$propertiesAddedStats = self::calculateStats($formattedArray['property_added_live'], $formattedArray['property_added_virtual'], $dates); | |
$milesDrivenStats = self::calculateStats($formattedArray['miles_driven_live'], $formattedArray['miles_driven_virtual'], $dates); | |
$timesDrivenStats = self::calculateStats($formattedArray['times_driven_live'], $formattedArray['times_driven_virtual'], $dates, 'secondsToMinutes'); | |
$propertiesAddedGraph = self::formatObject($formattedArray['property_added_virtual'], $formattedArray['property_added_live'], $startDate, $endDate); | |
$milesDrivenGraph = self::formatObject($formattedArray['miles_driven_virtual'], $formattedArray['miles_driven_live'], $startDate, $endDate); | |
$timesDrivenGraph = self::formatObject($formattedArray['times_driven_virtual'], $formattedArray['times_driven_live'], $startDate, $endDate); | |
$response = collect([ | |
'stats' => [ | |
'start_date' => Carbon::parse($startDate)->toDateString(), | |
'end_date' => Carbon::parse($endDate)->toDateString(), | |
'prev_start_date' => Carbon::parse($prevStartDate)->toDateString(), | |
'prev_end_date' => Carbon::parse($prevEndDate)->toDateString(), | |
'total_properties_added' => $propertiesAddedStats['current_total'], | |
'total_miles_drive' => toFixDecimal($milesDrivenStats['current_total']), | |
'total_time_drive' => floor($timesDrivenStats['current_total']), | |
'virtual_properties_added' => $propertiesAddedStats['virtual_total'], | |
'live_properties_added' => $propertiesAddedStats['live_total'], | |
'virtual_miles_added' => toFixDecimal($milesDrivenStats['virtual_total']), | |
'live_miles_added' => toFixDecimal($milesDrivenStats['live_total']), | |
'virtual_time_added' => floor($timesDrivenStats['virtual_total']), | |
'live_time_added' => floor($timesDrivenStats['live_total']), | |
], | |
'properties_added' => [ | |
'stats' => $propertiesAddedStats, | |
'graph' => $propertiesAddedGraph | |
], | |
'miles_driven' => [ | |
'stats' => $milesDrivenStats, | |
'graph' => $milesDrivenGraph | |
], | |
'time_driven' => [ | |
'stats' => $timesDrivenStats, | |
'graph' => $timesDrivenGraph | |
] | |
]); | |
return response()->successResponse('Data Found', $response); | |
} else { | |
return response()->successResponse('Data Not Found', []); | |
} | |
} | |
// all record arrays previous & current | |
/** | |
* @param $record | |
* @return \Illuminate\Support\Collection | |
*/ | |
private function createArray($record) | |
{ | |
$propertiesAddedLive = collect(); | |
$propertiesAddedVirtual = collect(); | |
$milesDrivenRecordLive = collect(); | |
$milesDrivenRecordVirtual = collect(); | |
$timesDrivenRecordLive = collect(); | |
$timesDrivenRecordVirtual = collect(); | |
foreach ($record as $pgsql) { | |
$live = $pgsql->where('route_type', '=', DrivingRouteService::ROUTE_TYPE_LIVE); | |
$virtual = $pgsql->where('route_type', '=', DrivingRouteService::ROUTE_TYPE_VIRTUAL); | |
if ($live->count() > 0) { | |
$propertiesAddedLive->push([ | |
'route_type' => $live->first()->route_type, | |
'name' => $pgsql->first()->name, | |
'value' => $live->sum('property_count') | |
]); | |
$milesDrivenRecordLive->push([ | |
'route_type' => $live->first()->route_type, | |
'name' => $pgsql->first()->name, | |
'value' => $live->sum('total_distance') | |
]); | |
$timesDrivenRecordLive->push([ | |
'route_type' => $live->first()->route_type, | |
'name' => $pgsql->first()->name, | |
'value' => $live->sum('total_seconds') | |
]); | |
} | |
if ($virtual->count() > 0) { | |
$propertiesAddedVirtual->push([ | |
'route_type' => $virtual->first()->route_type, | |
'name' => $pgsql->first()->name, | |
'value' => $virtual->sum('property_count') | |
]); | |
$milesDrivenRecordVirtual->push([ | |
'route_type' => $virtual->first()->route_type, | |
'name' => $pgsql->first()->name, | |
'value' => $virtual->sum('total_distance') | |
]); | |
$timesDrivenRecordVirtual->push([ | |
'route_type' => $virtual->first()->route_type, | |
'name' => $pgsql->first()->name, | |
'value' => $virtual->sum('total_seconds') | |
]); | |
} | |
} | |
return collect([ | |
'property_added_live' => $propertiesAddedLive, | |
'property_added_virtual' => $propertiesAddedVirtual, | |
'miles_driven_live' => $milesDrivenRecordLive, | |
'miles_driven_virtual' => $milesDrivenRecordVirtual, | |
'times_driven_live' => $timesDrivenRecordLive, | |
'times_driven_virtual' => $timesDrivenRecordVirtual | |
]); | |
} | |
/** | |
* @param $virtual | |
* @param $live | |
* @param $startDate | |
* @param $endDate | |
* @return \Illuminate\Support\Collection | |
*/ | |
private function formatObject($virtual, $live, $startDate, $endDate) | |
{ | |
$graph = collect(); | |
//setting up virtual data | |
$data = $virtual->whereBetween('name', [$startDate, $endDate])->values(); | |
$data = self::setupDataForDates($data, $startDate, $endDate, 2); | |
$graph->push([ | |
'name' => DrivingRouteService::ROUTE_TYPE_VIRTUAL_KEY, | |
'series' => $data | |
]); | |
//setting up live data | |
$data = $live->whereBetween('name', [$startDate, $endDate])->values(); | |
$data = self::setupDataForDates($data, $startDate, $endDate, 1); | |
$graph->push([ | |
'name' => DrivingRouteService::ROUTE_TYPE_LIVE_KEY, | |
'series' => $data | |
]); | |
return $graph; | |
} | |
/** | |
* The purpose of the function is to loop from start to end date | |
* and if there is no data against any date it will send 0 as value | |
* to populate graph on the client side. | |
* | |
* @param $data | |
* @param $startDate | |
* @param $endDate | |
* @param $routeType | |
* @return array | |
*/ | |
public function setupDataForDates($data, $startDate, $endDate, $routeType) | |
{ | |
$days = $startDate->diffInDays($endDate)+1; | |
$newArr = array(); | |
for ($i=0; $i < $days; $i++){ | |
$d1 = (Carbon::parse($startDate)->startOfDay()->addDays($i)->toDateString()); | |
$d2 = (Carbon::parse($startDate)->endOfDay()->addDays($i)->toDateString()); | |
$dt = $data->whereBetween('name', [$d1, $d2]); | |
if(count($dt) > 0) { | |
array_push($newArr, array( | |
'route_type' => $dt->first()['route_type'], | |
'name' => $dt->first()['name'], | |
'value' => $dt->first()['value'], | |
)); | |
} else { | |
array_push($newArr, array( | |
'route_type' => $routeType, | |
'name' => $d1, | |
'value' => 0 | |
)); | |
} | |
} | |
return $newArr; | |
} | |
/** | |
* @param $live | |
* @param $virtual | |
* @param $dates | |
* @param null $convert // can pass helper function name here and it will apply that filter on final calculations | |
* @return mixed | |
*/ | |
private function calculateStats($live, $virtual, $dates, $convert = null) | |
{ | |
$startDate = Carbon::parse($dates->start_date)->startOfDay()->toDateString(); | |
$endDate = Carbon::parse($dates->end_date)->endOfDay()->toDateString(); | |
$prevStartDate = Carbon::parse($dates->prev_start_date)->startOfDay()->toDateString(); | |
$prevEndDate = Carbon::parse($dates->prev_end_date)->endOfDay()->toDateString(); | |
$allRecord = $live->merge($virtual); | |
$virtual_total = $virtual->whereBetween('name', [$startDate, $endDate])->sum('value'); | |
$live_total = $live->whereBetween('name', [$startDate, $endDate])->sum('value'); | |
$current_total = $allRecord->whereBetween('name', [$startDate, $endDate])->sum('value'); | |
$previous_total = $allRecord->whereBetween('name', [$prevStartDate, $prevEndDate])->sum('value'); | |
if (!empty($convert)) { | |
$virtual_total = call_user_func($convert, $virtual_total); | |
$live_total = call_user_func($convert, $live_total); | |
$current_total = call_user_func($convert, $current_total); | |
$previous_total = call_user_func($convert, $previous_total); | |
} | |
$percent_change = pct_change($previous_total, $current_total); | |
return [ | |
'virtual_total' => toFixDecimal($virtual_total), | |
'live_total' => toFixDecimal($live_total), | |
'current_total' => toFixDecimal($current_total), | |
'previous_total' => toFixDecimal($previous_total), | |
'percent_change' => toFixDecimal($percent_change), | |
]; | |
} | |
public function getPropertyLeadStatus($id) | |
{ | |
return PropertyLeadStatus::query()->find($id); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment