467 lines
18 KiB
PHP
467 lines
18 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers;
|
||
|
||
use A7kz\Platform\Models\UniModel;
|
||
use A7kz\Platform\Modules\Platform\Acl\Facades\Acl;
|
||
use A7kz\Platform\Modules\Platform\Segment\Facades\Segment;
|
||
use App\Modules\applications\Enum\ApplicationStatus;
|
||
use App\Modules\auto\Enums\AutoStatusEnums;
|
||
use App\Service\DepositService;
|
||
use Carbon\CarbonPeriod;
|
||
use Exception;
|
||
use Illuminate\Http\JsonResponse;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Carbon;
|
||
use Illuminate\Support\Facades\Auth;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Log;
|
||
use Illuminate\Support\Facades\Notification;
|
||
use Illuminate\Support\Facades\Storage;
|
||
use Mpdf\Tag\Mark;
|
||
use function PHPUnit\Framework\isEmpty;
|
||
|
||
class MobileApiController extends Controller
|
||
{
|
||
public function getMarks(): JsonResponse {
|
||
$data = [];
|
||
$marks = UniModel::model('pipi_brand_models')->get();
|
||
if (!isset($marks)) {
|
||
return response()->json();
|
||
}
|
||
foreach ($marks as $mark) {
|
||
$brand = UniModel::model('pipi_auto_brands')->find($mark->brand_id);
|
||
$tariffs = UniModel::model('pipi_auto_tariffs')->where('model_id', $mark->id)->get();
|
||
$equipment = UniModel::model('pipi_auto_equipment')->where('id', $mark->equipment_id)->first();
|
||
if ($mark->name != 'Ввод остатков') {
|
||
foreach ($tariffs as $tariff) {
|
||
$tariffs_new[] = [
|
||
'name' => $tariff?->name,
|
||
'price' => $tariff?->base_rate,
|
||
'min' => $tariff?->day_range_start,
|
||
'max' => $tariff?->day_range_end,
|
||
];
|
||
}
|
||
$data[$mark->name . '-' . $mark->year] = [
|
||
'id' => $mark->id,
|
||
'brand' => $brand->name,
|
||
'mark' => $mark->name,
|
||
'year' => $mark->year,
|
||
'configuration' => $equipment?->name,
|
||
'tariffs' => $tariffs_new
|
||
];
|
||
}
|
||
}
|
||
|
||
if (empty($data)) {
|
||
$data = (object) [];
|
||
}
|
||
return response()->json($data);
|
||
}
|
||
|
||
/**
|
||
* @throws Exception
|
||
*/
|
||
public function sendApplication(Request $request): JsonResponse {
|
||
$data = $request->all();
|
||
$data['started_at'] = Carbon::createFromFormat('d-m-Y H:i', $data['started_at']);
|
||
$data['ended_at'] = Carbon::createFromFormat('d-m-Y H:i', $data['ended_at']);
|
||
$authToken = null;
|
||
$data['car_id'] = null;
|
||
if ($request->header('Authorization')) {
|
||
$user = auth()->guard('api')->user();
|
||
$data['user_id'] = $user?->id;
|
||
$authToken = $request->header('Authorization');
|
||
} else {
|
||
$user = UniModel::model('core_users')
|
||
->where('email', $data['email'])
|
||
->first();
|
||
|
||
if ($user) {
|
||
$data['user_id'] = $user->id;
|
||
$tokenResult = $user->createToken('auth_token');
|
||
$authToken = $tokenResult->accessToken;
|
||
} else {
|
||
$data['user_id'] = null;
|
||
}
|
||
|
||
}
|
||
|
||
$response = [
|
||
'status' => 'OK',
|
||
'message' => 'Заявка создана',
|
||
];
|
||
|
||
$car = $this->getAvailableCar($data['started_at'], $data['ended_at'], $data['mark_id'], $data['color_code']);
|
||
if (!isset($car)) {
|
||
return response()->json('Нет свободных машин');
|
||
}
|
||
$data['car_id'] = $car->id;
|
||
if ($data['user_id']) {
|
||
$period = CarbonPeriod::create($data['started_at'], $data['ended_at']);
|
||
|
||
$dates = array_map(fn($date) => $date->toDateString(), iterator_to_array($period));
|
||
|
||
foreach ($dates as $date) {
|
||
UniModel::model('pipi_auto_calendar')->create([
|
||
'auto_id' => $data['car_id'],
|
||
'date' => $date,
|
||
'status' => AutoStatusEnums::Rent->name
|
||
]);
|
||
}
|
||
$response['auth_token'] = $authToken;
|
||
$response['message'] = 'Заявка создана, и вы были автоматически авторизованы';
|
||
} elseif (!isset($data['user_id'])) {
|
||
$response['message'] = 'Заявка создана, с вами свяжется наш оператор';
|
||
}
|
||
$address_end = UniModel::model('pipi_address')->where('name', $data['address_end'])->first();
|
||
$address_start = UniModel::model('pipi_address')->where('name', $data['address_start'])->first();
|
||
$service = new DepositService;
|
||
$sums = $service->calculateSummary($data['mark_id'], $data['started_at'], $data['ended_at']);
|
||
$sum = $sums['discounted_sum'];
|
||
if ($data['deposit'] != $sums['deposit_base']) {
|
||
$sum += $data['deposit'];
|
||
}
|
||
UniModel::model('pipi_applications')->create([
|
||
'rent_day' => $data['rent_day'],
|
||
'started_at' => $data['started_at'],
|
||
'ended_at' => $data['ended_at'],
|
||
'user_id' => $data['user_id'],
|
||
'phone' => $data['phone'] ?? '' ,
|
||
'car_id' => $data['car_id'],
|
||
'user_name' => $data['name'] ?? null,
|
||
'user_surname' => $data['surname'] ?? null,
|
||
'user_email' => $data['email'] ?? null,
|
||
'address_end' => $address_end?->id,
|
||
'address_start' => $address_start?->id,
|
||
'deposit' => $data['deposit'] ?? null,
|
||
'status' => ApplicationStatus::pending->value,
|
||
'sum' => $sum
|
||
]);
|
||
|
||
return response()->json($response);
|
||
}
|
||
|
||
public function getApplications(): JsonResponse
|
||
{
|
||
$request = request();
|
||
if ($request->header('Authorization')) {
|
||
$user = auth()->guard('api')->user();
|
||
} else {
|
||
return response()->json([
|
||
'status' => false,
|
||
'message' => __('Вы не авторизованы')
|
||
]);
|
||
}
|
||
|
||
$status = $request->query('status');
|
||
|
||
$data = [];
|
||
$query = UniModel::model('pipi_applications')->where('user_id', $user->id);
|
||
if (isset($status)) {
|
||
$query->where('status', $status);
|
||
}
|
||
|
||
$applications = $query->get();
|
||
foreach ($applications as $app) {
|
||
$car = UniModel::model('pipi_auto')->find($app->car_id);
|
||
$model = UniModel::model('pipi_brand_models')->find($car->model_id);
|
||
$photo = UniModel::model('core_files')->find($model->photo_id);
|
||
$photo = url('api/files/file/' . ltrim($photo?->path, '/'));
|
||
$class_id = UniModel::model('pipi_auto_classes')->where('id', $model->class_id)->first();
|
||
$bodywork_id = UniModel::model('pipi_auto_bodywork')->where('id', $model->bodywork_id)->first();
|
||
$address = UniModel::model('pipi_address')->where('id', $model->address)->first();
|
||
$data[] = [
|
||
'id' => $app->id,
|
||
'rent_day' => $app->rent_day,
|
||
'started_at' => $app->started_at,
|
||
'ended_at' => $app->ended_at,
|
||
'status' => ApplicationStatus::from($app->status)->getName(),
|
||
'sum' => $app->sum ?? 0,
|
||
'address_end' => $address->name ?? '',
|
||
'car' => [
|
||
'name' => $model->name,
|
||
'year' => $model->year,
|
||
'people' => $model?->people ?? '5',
|
||
'actuator' => $model?->actuator ?? 'Передний',
|
||
'fuel_type' => $model?->fuel_type ?? 'АКПП',
|
||
'hp' => $model?->hp ?? '1.6',
|
||
'engine_capacity' => $model?->engine_capacity ?? '1591',
|
||
'fuel_tank' => $model?->fuel_tank ?? '50',
|
||
'class' => $class_id->name ?? 'Эконом',
|
||
'bodywork' => $bodywork_id->name ?? 'Седан',
|
||
'photo' => $photo ?? '',
|
||
]
|
||
];
|
||
}
|
||
if (empty($data)) {
|
||
$data = (object) $data;
|
||
}
|
||
return response()->json($data);
|
||
}
|
||
|
||
public function login(Request $request)
|
||
{
|
||
$credentials = $request->only('email', 'password');
|
||
|
||
if (auth()->attempt($credentials)) {
|
||
$user = auth()->user();
|
||
$tokenResult = $user->createToken('auth_token');
|
||
|
||
$response = [
|
||
'access_token' => $tokenResult->plainTextToken,
|
||
'token_type' => 'Bearer',
|
||
'user' => [
|
||
'id' => $user->id,
|
||
'name' => $user->name,
|
||
'email' => $user->email,
|
||
],
|
||
];
|
||
|
||
return response()->json($response, 200);
|
||
} else {
|
||
return response()->json(['error' => 'Unauthorized'], 401);
|
||
}
|
||
}
|
||
|
||
public function checkAvailableCar($started_at = null, $ended_at = null, $modelId = null): bool {
|
||
if (!$started_at || !$ended_at || !$modelId) {
|
||
$request = request();
|
||
$started_at = $started_at ?? $request->input('started_at');
|
||
$ended_at = $ended_at ?? $request->input('ended_at');
|
||
$modelId = $modelId ?? $request->input('model_id');
|
||
}
|
||
|
||
if (!$started_at || !$ended_at || !$modelId) {
|
||
return false;
|
||
}
|
||
|
||
$started_at = Carbon::parse($started_at)->format('Y-m-d');
|
||
$ended_at = Carbon::parse($ended_at)->format('Y-m-d');
|
||
$cars = UniModel::model('pipi_auto')
|
||
->where('is_inactive', '=', false)
|
||
->where('model_id', $modelId)
|
||
->get();
|
||
$busyCars = UniModel::model('pipi_auto_calendar')
|
||
->whereBetween('date', [$started_at, $ended_at])
|
||
->pluck('auto_id')
|
||
->toArray();
|
||
|
||
$availableCars = $cars->reject(fn($car) => in_array($car->id, $busyCars));
|
||
|
||
return $availableCars->isNotEmpty();
|
||
}
|
||
|
||
public function getAvailableMarksList(Request $request): JsonResponse
|
||
{
|
||
$started_at = $request->query('started_at');
|
||
$ended_at = $request->query('ended_at');
|
||
$class = $request->query('class');
|
||
$bodywork = $request->query('bodywork');
|
||
|
||
$marks = UniModel::model('pipi_brand_models')->get();
|
||
|
||
$availableMarks = [];
|
||
|
||
if ($class) {
|
||
$class_id = UniModel::model('pipi_auto_classes')->where('name', $class)->first()?->id;
|
||
$marks = $marks->where('class_id', $class_id);
|
||
}
|
||
if ($bodywork) {
|
||
$bodywork_id = UniModel::model('pipi_auto_bodywork')->where('name', $bodywork)->first()?->id;
|
||
$marks = $marks->where('bodywork_id', $bodywork_id);
|
||
}
|
||
|
||
foreach ($marks as $mark) {
|
||
if ($mark->name === 'Ввод остатков') {
|
||
continue;
|
||
}
|
||
|
||
if (!$this->checkAvailableCar($started_at, $ended_at, $mark->id)) {
|
||
continue;
|
||
}
|
||
|
||
$cars = UniModel::model('pipi_auto')->where('model_id', $mark->id)->get();
|
||
|
||
|
||
if ($cars->isEmpty()) {
|
||
continue;
|
||
}
|
||
|
||
$brand = UniModel::model('pipi_auto_brands')->find($mark->brand_id);
|
||
$tariffs = UniModel::model('pipi_auto_tariffs')->where('model_id', $mark->id)->get();
|
||
$equipment = UniModel::model('pipi_auto_equipment')->where('id', $mark->equipment_id)->first();
|
||
$class = UniModel::model('pipi_auto_classes')->find($mark->class_id);
|
||
$bodywork = UniModel::model('pipi_auto_bodywork')->find($mark->bodywork_id);
|
||
$photo = UniModel::model('core_files')->find($mark?->photo_id);
|
||
|
||
$path = null;
|
||
if ($photo) {
|
||
$path = url('api/files/file/' . ltrim($photo->path, '/'));
|
||
}
|
||
|
||
$tariffs_new = [];
|
||
foreach ($tariffs as $tariff) {
|
||
$tariffs_new[] = [
|
||
'name' => $tariff?->name,
|
||
'price' => $tariff?->base_rate,
|
||
'min' => $tariff?->day_range_start,
|
||
'max' => $tariff?->day_range_end,
|
||
'deposit' => $tariff?->deposit,
|
||
];
|
||
}
|
||
$carsByColor = $cars->groupBy('color_id');
|
||
|
||
foreach ($carsByColor as $carColor => $carsOfColor) {
|
||
$carColor = UniModel::model('pipi_auto_colors')->find($carColor)->code;
|
||
|
||
$colorPath = $path;
|
||
if ($carsOfColor->first()->photo_id) {
|
||
$photo = UniModel::model('core_files')->find($carsOfColor->first()->photo_id);
|
||
$colorPath = url('api/files/file/' . ltrim($photo->path, '/'));
|
||
}
|
||
|
||
$key = $mark->name . '-' . $mark->year . '-' . $carColor;
|
||
|
||
$availableMarks[$key] = [
|
||
'id' => $mark->id,
|
||
'brand' => $brand?->name,
|
||
'mark' => $mark->name,
|
||
'year' => $mark->year,
|
||
'color' => $carColor,
|
||
'configuration' => $equipment?->name,
|
||
'people' => $mark?->people ?? '5',
|
||
'actuator' => $mark?->actuator ?? 'Передний',
|
||
'fuel_type' => $mark?->fuel_type ?? 'АКПП',
|
||
'hp' => $mark?->hp ?? '1.6',
|
||
'engine_capacity' => $mark?->engine_capacity ?? '1591',
|
||
'fuel_tank' => $mark?->fuel_tank ?? '50',
|
||
'class' => $class->name ?? 'Эконом',
|
||
'bodywork' => $bodywork->name ?? 'Седан',
|
||
'deposit' => $tariffs_new[0]['deposit'] ?? 30000,
|
||
'conditioner' => $mark?->conditioner,
|
||
'photo' => $colorPath,
|
||
'tariffs' => $tariffs_new,
|
||
];
|
||
}
|
||
}
|
||
|
||
if (empty($availableMarks)) {
|
||
$availableMarks = (object) [];
|
||
}
|
||
return response()->json($availableMarks);
|
||
}
|
||
|
||
public function getAvailableCar($started_at, $ended_at, $modelId, $color)
|
||
{
|
||
$started_at = Carbon::parse($started_at)->format('Y-m-d');
|
||
$ended_at = Carbon::parse($ended_at)->format('Y-m-d');
|
||
$color = UniModel::model('pipi_auto_colors')->where('code', $color)->first()->id;
|
||
$cars = UniModel::model('pipi_auto')
|
||
->where('color_id', $color)
|
||
->where('model_id', $modelId)
|
||
->get();
|
||
$busyCars = UniModel::model('pipi_auto_calendar')
|
||
->whereBetween('date', [$started_at, $ended_at])
|
||
->pluck('auto_id')
|
||
->toArray();
|
||
|
||
$availableCars = $cars->reject(fn($car) => in_array($car->id, $busyCars));
|
||
|
||
if ($availableCars->isNotEmpty()) {
|
||
return $availableCars->first();
|
||
} else {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
public function getSum(Request $request)
|
||
{
|
||
$started_at = $request->input('started_at');
|
||
$ended_at = $request->input('ended_at');
|
||
$mark_id = $request->input('mark_id');
|
||
|
||
$start = Carbon::createFromFormat('d-m-Y H:i', $started_at);
|
||
$end = Carbon::createFromFormat('d-m-Y H:i', $ended_at);
|
||
try {
|
||
$service = new DepositService();
|
||
$summary = $service->calculateSummary($mark_id, $start, $end);
|
||
|
||
return response()->json($summary);
|
||
} catch (\Exception $e) {
|
||
return response()->json(['error' => $e->getMessage()], 400);
|
||
}
|
||
}
|
||
|
||
public function closeOrder(Request $request): JsonResponse
|
||
{
|
||
$order_id = $request->input('order_id');
|
||
|
||
$application = UniModel::model('pipi_applications')->find($order_id);
|
||
if (!isset($application)) {
|
||
return response()->json([
|
||
'success' => false,
|
||
'message' => __('Такой заявки не существует')
|
||
]);
|
||
}
|
||
|
||
if (count($request->file('photos')) != 5) {
|
||
return response()->json([
|
||
'success' => false,
|
||
'message' => __('Неверное количество фотографий')
|
||
]);
|
||
}
|
||
|
||
foreach ($request->file('photos') as $photo) {
|
||
$files[] = $this->uploadFile($photo);
|
||
}
|
||
$application->photos = $files;
|
||
$application->save();
|
||
|
||
return response()->json([
|
||
'success' => true,
|
||
'message' => __('Фото получены ожидайте закрытия заявки после проверки оператором'),
|
||
]);
|
||
}
|
||
|
||
private function uploadFile($file)
|
||
{
|
||
$ufile = UniModel::model(config('platform.file_manager.tables.files'));
|
||
$ufile->filename = $file->getClientOriginalName();
|
||
$ufile->path = $this->_gen_storage_file_name($file->getClientOriginalExtension());
|
||
$ufile->ext = $file->getClientOriginalExtension();
|
||
$ufile->size = $file->getSize();
|
||
$ufile->mime = $file->getClientMimeType();
|
||
$ufile->public = 1;
|
||
$ufile->user_file = 1;
|
||
$ufile->company_file = 1;
|
||
|
||
Storage::disk('file')->put($ufile->path, file_get_contents($file->getRealPath()));
|
||
$ufile->save();
|
||
|
||
return ['status' => 1, 'file_id' => $ufile->id, 'name' => 'photos', 'file_name' => $ufile->filename];
|
||
}
|
||
|
||
private function _gen_storage_file_name($ext): string
|
||
{
|
||
$storage_file_name = md5(time());
|
||
$folder1 = substr($storage_file_name, 0, 2);
|
||
$folder2 = substr($storage_file_name, 2, 3);
|
||
return $folder1 . '/' . $folder2 . '/' . $storage_file_name . '.' . $ext;
|
||
}
|
||
|
||
public function getAddress(): JsonResponse
|
||
{
|
||
$addresses = UniModel::model('pipi_address')->get();
|
||
foreach ($addresses as $address) {
|
||
$data[$address->id] = $address->name;
|
||
}
|
||
|
||
if (empty($data)) {
|
||
$data = (object) [];
|
||
}
|
||
|
||
return response()->json($data);
|
||
}
|
||
}
|