This is the helper class used in the code above:
<?php
namespace app\helper;
use app\jobs\SearchDriverJob;
use app\models\Business;
use app\models\Error;
use app\models\Errors;
use app\models\Fare;
use app\models\forms\ApiBatchRequestForm;
use app\models\Ride;
use app\models\RideInsurance;
use app\models\RidePrice;
use app\models\RideStatus;
use app\models\RideVolume;
use app\models\Zone;
use yii\db\Exception;
use yii\console\Response as ConsoleResponse;
use Yii;
use function GuzzleHttp\json_encode;
class RequestRideHelper
{
protected function setResponseStatusCode($statusCode)
{
if (!Yii::$app->response instanceof ConsoleResponse) {
Yii::$app->response->statusCode = $statusCode;
}
}
public function requestRide($data, $user)
{
$batchRequestRideForm = new ApiBatchRequestForm();
$batchRequestRideForm->setAttributes($data);
$transaction = Yii::$app->db->beginTransaction();
try {
if ($batchRequestRideForm->validate()) {
$ride_type = 0;
$ride_date = date('Y-m-d H:i:s');
$num_waypoints = count($batchRequestRideForm->rides);
$waypoint = 1;
$parent_id = null;
$previousRide = null;
$index = 0;
$values = null;
// CHECK IF THE USER SELECTED OPTIMIZE OPTION AND HAS MULTIPLE RIDES
if ($batchRequestRideForm->optimize && count($batchRequestRideForm->rides) > 1) {
$newRides = RideHelper::optimizeRide($batchRequestRideForm->rides);
if ($newRides['statusCode']) {
$transaction->rollBack();
$this->setResponseStatusCode(422);
return new Error("ERROR_OPTIMIZING_RIDES");
}
// SET THE NEW ORDER OF RIDES
$batchRequestRideForm->rides = $newRides;
}
$outputRides = array();
foreach ($batchRequestRideForm->rides as $requestRideForm) {
$index++;
$requestRideForm = (object) $requestRideForm;
$requester = $user->getId();
if ($user->business_id != null && $requestRideForm->requester) {
$requesterId = SecurityHash::fromHashids($requestRideForm->requester);
if ($requester != $requesterId) {
if ($user->business_id != $requesterId) {
$transaction->rollBack();
$this->setResponseStatusCode(422);
return new Error("REQUESTER_NOT_FOUND");
} else {
$requester = $requesterId;
}
}
}
if (!$batchRequestRideForm->optimize || count($batchRequestRideForm->rides) <= 1) {
// // CHECK IF THERE`S A PREVIOUS RIDE ALREADY ASSIGNED
if (!is_null($previousRide)) {
// IF PREVIOUS RIDE ALREADY EXISTS, THIS RIDE ORIGN IS PREVIOUS RIDE DESTINATION
$requestRideForm->originAddress = $previousRide->destinationAddress;
$requestRideForm->origin_latitude = $previousRide->destination_latitude;
$requestRideForm->origin_longitude = $previousRide->destination_longitude;
}
$values = ApiServiceHelper::getDistance($requestRideForm->origin_latitude, $requestRideForm->origin_longitude, $requestRideForm->destination_latitude, $requestRideForm->destination_longitude, $requestRideForm->originAddress, $requestRideForm->destinationAddress);
if (isset($values['statusCode']) && $values['statusCode'] == 422) {
$transaction->rollBack();
$this->setResponseStatusCode(422);
return new Error("ROUTE_NOT_FOUND");
}
if (is_null($previousRide)) {
$requestRideForm->origin_latitude = $values['origin_latitude'];
$requestRideForm->origin_longitude = $values['origin_longitude'];
}
$requestRideForm->destination_latitude = $values['destination_latitude'];
$requestRideForm->destination_longitude = $values['destination_longitude'];
$zone = Zone::findBySql(
"select * from zone where available = 1 and size > getDistance(zone.origin_latitude, zone.origin_longitude, :origin_latitude, :origin_longitude) and size > getDistance(zone.origin_latitude, zone.origin_longitude, :dest_latitude, :dest_longitude)",
[
":origin_latitude" => $requestRideForm->origin_latitude,
":origin_longitude" => $requestRideForm->origin_longitude,
":dest_latitude" => $values['destination_latitude'],
":dest_longitude" => $values['destination_longitude']
]
)
->one();
} else {
$zone = Zone::findBySql(
"select * from zone where available = 1 and size > getDistance(zone.origin_latitude, zone.origin_longitude, :origin_latitude, :origin_longitude) and size > getDistance(zone.origin_latitude, zone.origin_longitude, :dest_latitude, :dest_longitude)",
[
":origin_latitude" => $requestRideForm->origin_latitude,
":origin_longitude" => $requestRideForm->origin_longitude,
":dest_latitude" => $requestRideForm->destination_latitude,
":dest_longitude" => $requestRideForm->destination_longitude
]
)->one();
}
if (!$zone) {
$transaction->rollBack();
$this->setResponseStatusCode(422);
return new Error("UNAVAILABLE_ADDRESS");
}
$fare = Fare::findBySql(
"select * from fare where status = 1 and type_of_content = :type_of_content and vehicle_type = :vehicle_type and user_id = :requester",
[
":type_of_content" => $requestRideForm->type_of_content,
":vehicle_type" => $requestRideForm->vehicle_type,
":requester" => $requester
]
)->one();
if (!$fare) {
$fare = Fare::findBySql(
"select * from fare where status = 1 and type_of_content = :type_of_content and vehicle_type = :vehicle_type and zone_id = :zone_id",
[
":type_of_content" => $requestRideForm->type_of_content,
":vehicle_type" => $requestRideForm->vehicle_type,
":zone_id" => $zone->id
]
)->one();
if (!$fare) {
$transaction->rollBack();
$this->setResponseStatusCode(422);
return new Error("FARE_NOT_FOUND");
}
}
$isBusiness = Business::find()->where(['user_id' => $requester, 'active' => 1])->exists(); //TODO retornar erro amigável
if (!$isBusiness) {
$transaction->rollBack();
$this->setResponseStatusCode(422);
return new Error("USER_IS_NOT_BUSINESS");
}
$ride = new Ride();
$ride->setAttribute('requester_id', $requester);
if (!$batchRequestRideForm->optimize || count($batchRequestRideForm->rides) <= 1) {
$ride->setAttribute('distance', $values['distance']);
$ride->setAttribute('estimated_duration', $values['estimated_duration']);
$ride->setAttribute('destination_latitude', $values['destination_latitude']);
$ride->setAttribute('destination_longitude', $values['destination_longitude']);
$ride->setAttribute('path', $values['path']);
} else {
$ride->setAttribute('distance', $requestRideForm->distance);
$ride->setAttribute('estimated_duration', $requestRideForm->estimated_duration);
$ride->setAttribute('destination_latitude', $requestRideForm->destination_latitude);
$ride->setAttribute('destination_longitude', $requestRideForm->destination_longitude);
$ride->setAttribute('path', $requestRideForm->path);
}
$ride->setAttribute('destinationAddress', $requestRideForm->destinationAddress);
$ride->setAttribute('originAddress', $requestRideForm->originAddress);
$ride->setAttribute('origin_latitude', $requestRideForm->origin_latitude);
$ride->setAttribute('origin_longitude', $requestRideForm->origin_longitude);
$ride->setAttribute('origin_note', $requestRideForm->origin_note);
$ride->setAttribute('destination_note', $requestRideForm->destination_note);
$ride->setAttribute('external_id', $requestRideForm->external_id);
$ride->setAttribute('is_food', $requestRideForm->is_food != null ? intval($requestRideForm->is_food) : null);
$ride->setAttribute('is_integration', 1);
if (is_null($parent_id)) {
if ($requestRideForm->date) {
$ride->setAttribute('date', $requestRideForm->date);
$ride->setAttribute('type', 1);
$ride_type = 1;
$ride_date = $requestRideForm->date;
} else {
$ride->setAttribute('date', date("Y-m-d H:i:s"));
$ride->setAttribute('type', 0);
$ride_type = 0;
$ride_date = date("Y-m-d H:i:s");
}
} else {
if ($ride_type == 1) {
$ride->setAttribute('date', $ride_date);
$ride->setAttribute('type', 1);
} else {
$ride->setAttribute('date', date("Y-m-d H:i:s"));
$ride->setAttribute('type', 0);
}
}
$ride->setAttribute('payment_method', 3);
$ride->setAttribute('fare', $fare->id);
$ride->setAttribute('measures_id', $requestRideForm->measures_id);
$ride->setAttribute('note', $requestRideForm->note);
$ride->setAttribute('receiver_phone', $requestRideForm->receiver_phone);
$ride->setAttribute('receiver_name', $requestRideForm->receiver_name);
$ride->setAttribute('receiver_intermediate', $requestRideForm->receiver_intermediate);
$ride->setAttribute('vehicle_type', $requestRideForm->vehicle_type);
$ride->setAttribute('created_by', $user->getId());
$ride->setAttribute('num_waypoints', $num_waypoints);
$ride->setAttribute('waypoint', $waypoint++);
$ride->setAttribute('parent_id', $parent_id);
if ($requestRideForm->num_volumes) {
$ride->setAttribute('num_volumes', $requestRideForm->num_volumes);
}
if (!$ride->save()) {
$transaction->rollBack();
$this->setResponseStatusCode(400);
return new Errors($ride->getErrorSummary(true));
}
if (is_null($parent_id)) {
$parent_id = $ride->id;
}
if ($requestRideForm->volume) {
$rideVolume = new RideVolume();
$rideVolume->setAttribute('ride_id', $ride->id);
$rideVolume->setAttribute('length', $requestRideForm->volume['length']);
$rideVolume->setAttribute('width', $requestRideForm->volume['width']);
$rideVolume->setAttribute('height', $requestRideForm->volume['height']);
$rideVolume->setAttribute('weight', $requestRideForm->volume['weight']);
$calcWeight = doubleval($requestRideForm->volume['length']) * doubleval($requestRideForm->volume['width']) * doubleval($requestRideForm->volume['height']) * 300.0;
$calcWeight = HelperFunctions::toMoney($calcWeight);
$rideVolume->setAttribute('calc_weight', $calcWeight);
$rideVolume->save();
}
if ($ride_type == 0) {
$rideStatus = new RideStatus();
$rideStatus->setAttribute('status_id', 1);
$rideStatus->setAttribute('ride_id', $ride->id);
$rideStatus->setAttribute('created_by', $user->getId());
if (!$rideStatus->save(true)) {
$transaction->rollBack();
$this->setResponseStatusCode(400);
return new Errors($rideStatus->getErrorSummary(true));
}
} else {
$rideStatus = new RideStatus();
$rideStatus->setAttribute('status_id', 0);
$rideStatus->setAttribute('ride_id', $ride->id);
$rideStatus->setAttribute('created_by', $user->getId());
if (!$rideStatus->save(true)) {
$transaction->rollBack();
$this->setResponseStatusCode(400);
return new Errors($rideStatus->getErrorSummary(true));
}
}
if (!$batchRequestRideForm->optimize || count($batchRequestRideForm->rides) <= 1) {
$distancePrice = HelperFunctions::toMoney(doubleval($values['distance'] / 1000) * doubleval($ride->fare0->distance_value));
} else {
$distancePrice = HelperFunctions::toMoney(doubleval($requestRideForm->distance / 1000) * doubleval($ride->fare0->distance_value));
}
if ($distancePrice < $fare->minimum)
$distancePrice = $fare->minimum;
$volumePrice = 0;
if ($fare->type_of_content >= 1) {
if ($requestRideForm->is_food) {
$volumePrice = $fare->food != null ? $fare->food : 0;
} else {
if ($requestRideForm->volume) {
$weight = doubleval($requestRideForm->volume['weight']);
$calcWeight = doubleval($requestRideForm->volume['length']) * doubleval($requestRideForm->volume['width']) * doubleval($requestRideForm->volume['height']) * 300.0;
$maxWeight = max($weight, $calcWeight);
$discount = floor($maxWeight / 10.0) * 0.02;
$discount = min($discount, 0.20);
$volumeValue = doubleval($fare->volume_value) - $discount;
$volumePrice = HelperFunctions::toMoney($maxWeight * $volumeValue);
}
}
if ($volumePrice < $fare->minimum_volume)
$volumePrice = $fare->minimum_volume;
} else {
$volumePrice = doubleval($fare->volume_value);
}
//Mínimo de seguro
// $insuranceRate = Constants::INSURANCE_PRICE;
$insuranceRate = doubleval($fare->insurance_rate / 100);
$assuredPrice = Constants::MINIMUM_ASSURED_PRICE;
$insurancePrice = doubleval($assuredPrice) * doubleval($insuranceRate);
if ($requestRideForm->product_price != null && $requestRideForm->product_price > $assuredPrice) {
$assuredPrice = $requestRideForm->product_price;
$insurancePrice = doubleval($requestRideForm->product_price) * doubleval($insuranceRate);
$insurancePrice = HelperFunctions::toMoney($insurancePrice);
}
$rideInsurance = new RideInsurance();
$rideInsurance->setAttributes([
'ride' => $ride->id,
'product_price' => $assuredPrice,
'price' => $insurancePrice,
'tax_number' => $requestRideForm->tax_number
]);
$rideInsurance->save();
$totalPrice = $distancePrice + $volumePrice + $insurancePrice;
$totalPrice = HelperFunctions::toMoney($totalPrice);
$driverPrice = HelperFunctions::toMoney(($distancePrice + $volumePrice) * 0.75);
$ridePrice = new RidePrice();
$ridePrice->setAttributes([
'ride_id' => $ride->id,
'distance_price' => $distancePrice,
'volume_price' => $volumePrice,
'insurance_price' => $insurancePrice,
'discount_price' => 0,
'total_price' => $totalPrice,
'driver_price' => $driverPrice
]);
$url = "https://maps.googleapis.com/maps/api/staticmap?size=500x300&key=" . env("MAPS_API_KEY") . "&markers=color:red|label:O|" . $ride->origin_latitude . "," . $ride->origin_longitude . "&markers=color:blue|label:D|" . $ride->destination_latitude . "," . $ride->destination_longitude . "&path=color:red|weight:2|enc:" . $ride->path;
$fileName = SecurityHash::toHashids($ride->id) . '.png';
$image = file_get_contents(addcslashes($url, "\v"));
$fp = fopen("temp/" . $fileName, 'a');
fputs($fp, $image);
fclose($fp);
$result = S3Helper::uploadMapImageToS3($fp, $fileName);
if ($result['statusCode'] != null && $result['statusCode'] == 200) {
$ride->map = $result["effectiveUri"];
$ride->save();
}
// ASSIGN THE CURRENT RIDE AS PREVIOUS RIDE FOR THE NEXT RIDE
if (!$batchRequestRideForm->optimize || count($batchRequestRideForm->rides) <= 1) {
$previousRide = $requestRideForm;
}
if (!$ridePrice->save()) {
$transaction->rollBack();
$this->setResponseStatusCode(400);
return new Errors($ridePrice->getErrorSummary(true));
}
$outputRides[] = $ride;
}
echo "Depois da solicitação";
$transaction->commit();
if ($ride_type == 0) {
Yii::$app->queue->push(
new SearchDriverJob([
'currentTry' => 0,
'rideId' => $parent_id
])
);
}
return [
"rides" => $outputRides
];
} else {
$transaction->rollBack();
$this->setResponseStatusCode(400);
\Yii::warning([
'msg' => "Erro ao solicitar corrida",
'extra' => json_encode($batchRequestRideForm->getErrorSummary(true)),
], 'testes');
return new Errors($batchRequestRideForm->getErrorSummary(true));
}
} catch (Exception $e) {
\Yii::warning([
'msg' => "Erro ao solicitar corrida",
'extra' => $e->getMessage(),
], 'testes');
$transaction->rollBack();
$this->setResponseStatusCode(400);
return new Error("INTERNAL ERROR");
}
}
}