pipicar/app/Http/Controllers/MobileApiController.php

543 lines
22 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?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\Http\Notifications\TelegramNotification;
use App\Models\User;
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 {
try {
$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 = User::where('email', $data['email'])->first();
if ($user) {
$data['user_id'] = $user->id;
$tokenResult = $user->createToken('auth_token');
$authToken = $tokenResult->plainTextToken;
} else {
$data['user_id'] = null;
}
}
$response = [
'status' => 'OK',
'message' => 'Заявка создана',
];
$car = $this->getAvailableCar($data['started_at'], $data['ended_at'], $data['mark_id'], $data['color_code']);
$status = ApplicationStatus::pending->value;
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
]);
}
$status = ApplicationStatus::approved->value;
$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' => $user?->phone ?? $data['phone'] ?? '' ,
'car_id' => $data['car_id'],
'user_name' => $user?->name ?? $data['name'] ?? null,
'user_surname' => $user?->name ?? $data['surname'] ?? null,
'user_email' => $user?->email ?? $data['email'] ?? null,
'address_end' => $address_end?->id,
'address_start' => $address_start?->id,
'deposit' => $data['deposit'] ?? null,
'status' => $status,
'sum' => $sum
]);
$notification = [];
$notification['Адрес получения'] = $data['address_start'];
$notification['Адрес возврата'] = $data['address_end'];
$notification['Дата и время начала'] = $data['started_at'];
$notification['Дата и время возврата'] = $data['ended_at'];
$notification['Телефон'] = $data['phone'] ?? $user?->phone ?? null;
$notification['Имя'] = $data['name'] ?? $user?->name ?? null;
$notification['Почта'] = $data['email'] ?? $user?->email ?? null;
$notification['Сообщение'] = __('Новая заявка');
$this->sendNotification($notification);
return response()->json($response);
} catch (Exception $e) {
return response()->json($e->getMessage());
}
}
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);
} else {
$query->whereIn('status', [ApplicationStatus::approved->value, ApplicationStatus::review->value]);
}
$applications = $query->orderBy('id', 'desc')->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', $app->address_end)->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, $color = null): bool|JsonResponse
{
if (!$started_at || !$ended_at || !$modelId || !$color) {
$request = request();
$started_at = $started_at ?? $request->input('started_at');
$ended_at = $ended_at ?? $request->input('ended_at');
$modelId = $modelId ?? $request->input('model_id');
$color = Unimodel::model('pipi_auto_colors')->where('code', $request->input('color'))->first()->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)
->where('color_id', $color)
->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 response()->json($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;
}
$tariffs = UniModel::model('pipi_auto_tariffs')->where('model_id', $mark->id)->get();
if ($tariffs->isEmpty()) {
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);
$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, '/'));
}
if (!$this->checkAvailableCar($started_at, $ended_at, $mark->id, $carColor->code)) {
continue;
}
$key = $mark->name . '-' . $mark->year . '-' . $carColor->code;
$availableMarks[$key] = [
'id' => $mark->id,
'brand' => $brand?->name,
'mark' => $mark->name,
'year' => $mark->year,
'color' => $carColor->code,
'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)
->whereNull('regular_user')
->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->status = ApplicationStatus::review->value;
$application->save();
$notification = [];
$notification['ID заявки'] = $application->id;
$notification['Сообщение'] = __('Получена заявка на закрытие');
$this->sendNotification($notification);
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);
}
public function getFAQCategory(): JsonResponse
{
$faqs = UniModel::model('pipi_faq')->distinct('category')->get();
$data = [];
foreach ($faqs as $faq) {
$data[] = $faq->category;
}
return response()->json($data);
}
public function getFAQSubCategory(Request $request): JsonResponse
{
$category = $request->query('category');
$query = UniModel::model('pipi_faq');
if (isset($category)) {
$query->where('category', $category);
}
$faqs = $query->distinct('subcategory')->get();
$data = [];
foreach ($faqs as $faq) {
$data[] = $faq->subcategory;
}
return response()->json($data);
}
public function getFAQText(Request $request): JsonResponse
{
$subcategory = $request->query('subcategory');
$query = UniModel::model('pipi_faq')->where('subcategory', $subcategory)->first();
$text = $query?->text;
return response()->json($text ?? '');
}
private function sendNotification(array $data): void
{
foreach ($data as $key => $value) {
$text[$key] = $key . ': ' . $value;
}
Notification::send([$text], new TelegramNotification($text));
}
}