From 2dc250669e6e34d695db58c012e80b6469926090 Mon Sep 17 00:00:00 2001 From: vasya Date: Sun, 5 Apr 2026 19:47:49 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D1=8F?= =?UTF-8?q?=D1=8E=20=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=D1=8B,=20=D0=BE?= =?UTF-8?q?=D1=82=D0=B2=D0=B5=D1=87=D0=B0=D1=8E=D1=89=D0=B8=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=20=D1=81=D0=B0=D0=BC=D1=83=20=D0=BB=D0=BE=D0=B3=D0=B8?= =?UTF-8?q?=D0=BA=D1=83\=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE=D0=BD?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modules/Taxi/App/DTO/TaxiOrderDTO.php | 65 ++++ .../App/Http/Controllers/TaxiController.php | 351 ++++++++++++++++++ .../Middleware/CheckTimeRqstAvailability.php | 54 +++ .../App/Http/Requests/TaxiOrderRequest.php | 110 ++++++ .../Taxi/App/Providers/TaxiOrderProvider.php | 27 ++ .../Taxi/App/Services/TaxiOrderService.php | 42 +++ 6 files changed, 649 insertions(+) create mode 100644 Modules/Taxi/App/DTO/TaxiOrderDTO.php create mode 100644 Modules/Taxi/App/Http/Controllers/TaxiController.php create mode 100644 Modules/Taxi/App/Http/Middleware/CheckTimeRqstAvailability.php create mode 100644 Modules/Taxi/App/Http/Requests/TaxiOrderRequest.php create mode 100644 Modules/Taxi/App/Providers/TaxiOrderProvider.php create mode 100644 Modules/Taxi/App/Services/TaxiOrderService.php diff --git a/Modules/Taxi/App/DTO/TaxiOrderDTO.php b/Modules/Taxi/App/DTO/TaxiOrderDTO.php new file mode 100644 index 0000000..995f132 --- /dev/null +++ b/Modules/Taxi/App/DTO/TaxiOrderDTO.php @@ -0,0 +1,65 @@ +validated(); + + switch ($rqstMethod) { + case 'PATCH': + return new self( + id: $validated['id'], + //При обновлении запроса логин пользователя должен оставаться неизменным + emp_login: $rqst->emp_login, + emp_phone: $validated['emp_phone'], + taxi_date: $validated['taxi_date'], + taxi_time: $validated['taxi_time'], + taxi_address_from: $validated['taxi_address_from'], + taxi_address_to: $validated['taxi_address_to'], + cancel_rqst: $validated['cancel_rqst'] ?? null, + ); + break; + default: + return new self( + id: $validated['id'] ?? null, + emp_login: $validated['emp_login'], + emp_phone: $validated['emp_phone'], + taxi_date: $validated['taxi_date'], + taxi_time: $validated['taxi_time'], + taxi_address_from: $validated['taxi_address_from'], + taxi_address_to: $validated['taxi_address_to'], + cancel_rqst: $validated['cancel_rqst'] ?? null, + ); + break; + } + } +} diff --git a/Modules/Taxi/App/Http/Controllers/TaxiController.php b/Modules/Taxi/App/Http/Controllers/TaxiController.php new file mode 100644 index 0000000..b160c13 --- /dev/null +++ b/Modules/Taxi/App/Http/Controllers/TaxiController.php @@ -0,0 +1,351 @@ +first(); + + return $taxiOrder; + } + + + /** + * Получение адресов офисов для подстановки в запросы такси + * + * @return array + */ + public function getOfficeAddress() + { + $taxiAddress = TaxiModels\OfficeAddress::all(); + + return $taxiAddress; + } + + + /** + * Получение всех активных заказов + * + * @return array + */ + public function getActiveOrders() + { + $todaydate = new DateTime(); + $todaydate->setTime(00, 00, 00); + $todaydate = $todaydate->format('Y-m-d'); + $orders = TaxiModels\TaxiMain::where('taxi_date', '>=', $todayFdate) + ->get(); + + return $orders; + } + + + /** + * Метод получения заказов по условиям фильтра + * + * @param Request $rqst запрос с параметрами поиска + * @return string + */ + public function getFilterOrders(Request $rqst) + { + $rqstCond = []; + foreach ($rqst->all() as $fieldName => $fieldVal) { + if (!$fieldVal) continue; + $rqstCond[] = [$fieldName, '=', $fieldVal]; + } + $filterRqst = TaxiModels\TaxiMain::where($rqstCond)->get(); + + return json_encode($filterRqst->toArray()); + } + + + //ГАВРИЛОВ используй транзакцию, а то создается запрос, не отправляется письмо и сообщение об ошибке + /** + * Show the form for creating a new resource. + */ + public function createTaxiOrder(TaxiOrderRequest $rqst) + { + $validateData = TaxiOrderDTO::setTaxiOrderDTO($rqst, $rqst->method()); + //Пытаемся найти уже существующий запрос на этот же логин и эту же дату. Если запрос найден, возвращаем ошибку. + $searchExistsOrder = TaxiModels\TaxiMain::where([ + ['emp_login', '=', $validateData->emp_login], + ['taxi_date', '=', $validateData->taxi_date] + ])->take(1)->get(); + if (count($searchExistsOrder)) { + return response()->json(['message' => "Ошибка! Заявка для сотрудника $validateData->emp_login на дату $validateData->taxi_date уже существует"], 400); + } + // $createRqstMsg; + try { + $newOrderId = (new TaxiModels\TaxiMain())->createOrder($validateData); + //$newOrderId = $this->orderService->createOrder($validateData); + $createRqstMsg = "Заявка успешно создана. Номер $newOrderId"; + #Гаврилов + //ПРОВЕРЬ, ЧТОБЫ ПИСЬМО НЕ ОТПРАВЛЯЛОСЬ, ЕСЛИ ВОЗНИКАЕТ ОШИБКА НА ЭТАПЕ СОЗДАНИЯ ЗАЯВКИ + //Один метод отправки письма для всех методов работы с заказом: создание, редактирование, отмена + $this->sendMailService->sendMail(new NewOrderMail($validateData, $newOrderId)); + // SendMailNewOrder::dispatch(json_decode(json_encode($validateData), true), $newOrderId)->onQueue('emails')->delay(10); + // Mail::send(new Mailer( + // [$validateData->emp_login], + // 'Создание заказа на такси', + // "Для вас создана заявка на заказ такси на дату {$validateData->taxi_date} и время {$validateData->taxi_time}. Номер заказа {$newOrderId}", + // #Гаврилов + // //ЗДЕСЬ НЕПОНЯТНО ОТКУДА ВЗЯТЬ ЗНАЧЕНИЕ. ОБРАТИТЬСЯ К ЛОКАЛЬНО МОДУЛЬНОМУ ENV? + // config('taxi.name_ru'), + // )); + return response()->json(['message' => "Заявка успешно создана. Номер заявки $newOrderId"]); + } catch (\Throwable $t) { + #Гаврилов + //ОТПРАВКА СООБЩЕНИЯ С ОШИБКОЙ. ЗАТЕСТИ и отправляй response + //ОШИБКИ $T->GETmESSAGE НУЖНО ЛОГИРОВАТЬ, НО ПОЛЬЗОВАТЕЛЯМ ВЫВОДИТЬ ПРОСТО СООБЩЕНИЕ "оШИБКА", ИНАЧЕ ОНИ ВИДЯТ ТЕХНиЧЕСКИЙ ТЕКСТ + //СНАЧАЛА ПЕРЕХВАТЫЙ EXCEPTION, ПОТОМ УЖЕ THOWBLE. ТЕКСТ ИЗ EXCEPTION ВЫВОДИ ПОЛЬЗОВАТЕЛЮ - ТАМ КАСТОМНЫЕ ТЕКСТ ОШИБКИ, А ТЕКСТ ИЗ THORWBLE ЛОГИРУЙ ОТДЕЛЬНО, ТАК КАК ТАМ ТЕХНИЧЕСКОЕ ОПИСАНИЕ ОШИБКИ + echo '
';
+            var_dump($t->getMessage());
+            echo '
'; + echo '
';
+            var_dump($t->getTrace());
+            echo '
'; + $createRqstMsg = "Ошибка!" . $t->getMessage() . ". Заявка не создана"; + return response()->json(['message' => $createRqstMsg], 400); + } + + //ГАВРИЛОВ + //ДОБАВЬ ФОРМИРОВАНИЕ ОТВЕТА ЧЕРЕЗ ApiResponder, а не через response() + } + + + #Гаврилов + //ИСПОЛЬЗУЙ TaxiOrderRequest ПРИ ОБРАБОТКЕ ЗАЯВОК НА ТАКСИ + + /** + * Метод отмены запроса + * + * @param integer $rqstId идентификатор запроса + * @return string + */ + public function cancelRqst(int $rqstId): string + { + #Гаврилов + //ПОПРОБУЙ ОТПРАВИТЬ ЗАПРОС К API ЕНДПОИНТУ (ОТМЕНА ЗАПРОСА НА ТАКСИ) ЧЕРЕЗ POSTMAN С ПЕРЕДАЧЕЙ ЗАГОЛОВКА АУТЕНТИФИКАЦИИ С SANCTUM ТОКЕНОМ. ДОЛЖЕН ПРОПУСТИТЬ, А БЕЗ ЗАГОЛОВКА НЕ ДОЛЖЕН + $rqstData = $this->getOrderById($rqstId); + try { + #Гаврилов + //ПЕРЕНЕСИ ЭТУ ПРОВЕРКУ В РОУТИНГ? FINDORFAIL С РЕДИРЕКТОМ И ОШИБКОЙ + if (!$rqstData) { + throw new \Exception("Запрос $rqstId не существует"); + } + if (!$this->checkRqstDate($rqstData->taxi_date)) { + throw new \Exception("Дата запроса $rqstId уже прошла"); + } + } catch (\Throwable $t) { + return response()->json([ + 'errorMsg' => "Ошибка: $t->getMessage(). Заявка не отменена", + ], 400); + } + + $rqstData['cancel_rqst'] = 1; + $rqstData->save(); + + $this->sendMailService->sendCancelOrderMail($validateData, $newOrderId); + + // Mail::send(new Mailer( + // [$rqstData->emp_login], + // 'Отмена заказа на такси', + // "Заказ номер $rqstId на дату $rqstData->taxi_date и время $rqstData->taxi_time отменен", + // $this->appName)); + + return redirect('/taxi/home')->with([ + 'notification' => "Запрос $rqstId отменен", + 'notification_err' => false + ]); + } + + + /** + * Проверяем находится ли дата запроса на такси в диапазоне сегодняшнего или завтрашнего дня. + * + * @param string $rqstDate дата запроса на такси + * @return boolean + */ + private function checkRqstDate($rqstDate): bool + { + $todaydate = new DateTime(); + $todaydate->setTime(00, 00, 00); + + return new DateTime($rqstDate) >= $todaydate; + } + + + /** + * Получаем временные промежутки + * + * @return array + */ + public function getTimePeriods() + { + $empAllData = TaxiModels\TaxiTimePeriod::select('time_period', 'is_morning_time') + ->where('archive', 0) + ->get(); + + return $empAllData; + } + + + /** + * Метод получает информацию по всем активным пользователям + * + * @return array + */ + public function getActiveUsersInfo() + { + $empAllData = OldMagicModels\CcEmp::whereIn('emp_area', ['Курск', 'Пенза']) + ->whereNotIn('emp_state', ['Уволен', 'Декрет', 'Перевод на позицию', 'Перевод в ГРАН']) + ->get(); + foreach ($empAllData as &$empData) { + $empData['full_name'] = $empData['emp_surname'] . " " . $empData['emp_name'] . " " . $empData['emp_surname']; + $empData['extension_number'] = $empData['emp_phone']; + $empData['emp_phone'] = $empData['emp_mob_phone']; + } + + return $empAllData; + } + + + /** + * Метод получает информацию по конкретному пользователю + * + * @return array + */ + public function getUserInfoByLogin(string $userLogin) + { + $empLoginData = OldMagicModels\CcEmp::where('emp_login', $userLogin) + ->get(); + + // dd($empLoginData); + $empLoginData[0]['full_name'] = $empLoginData[0]['emp_surname'] . " " . $empLoginData[0]['emp_name'] . " " . $empLoginData[0]['emp_surname']; + $empLoginData[0]['extension_number'] = $empLoginData[0]['emp_phone']; + $empLoginData[0]['emp_phone'] = $empLoginData[0]['emp_mob_phone']; + + return $empLoginData; + } + + + #Гаврилов + //НЕ ЗАБУДЬ УДАЛИТЬ + public function testRedisMethod() + { + RedisNotifications::module('taxi') + ->notifications(['текст1', 'tеуые2']) + ->types(['error', 'success']) + ->put(); + } + + + /** + * Обновление заявки на такси + * + * @param TaxiOrderRequest $rqst информация по измененному запросу + * @return response + */ + public function updateTaxiOrder(TaxiOrderRequest $rqst) + { + try { + DB::beginTransaction(); + $orderData = TaxiModels\TaxiMain::lockForUpdate()->find($rqst->id); + $oldOrderData = TaxiModels\TaxiMain::find($rqst->id); + + if (!$orderData) { + throw new Exception("Заказ номер " . $rqst->id . " не найден"); + //return response()->json(['message' => 'Заказ номер ' . $rqst->id . ' не найден'], 400); + } + $editOrderData = TaxiOrderDTO::setTaxiOrderDTO($rqst, $rqst->method()); + #Гаврилов + //НА ДОМАШНЕЙ СТРАНИЦЕ ПОКАЗЫВАТЬ ТОЛЬКО ТЕ ЗАПРОСЫ, ДАТА КОТОРЫХ СЕГОДНЯ ИЛИ ЗАВТРА + $dateInterval = (new DateTime())->diff(new DateTime($orderData->taxi_date)); + if ($dateInterval->format('%R') == '-' && $dateInterval->format('%a') >= 1) { + throw new Exception("Нельзя менять заявки, дата которых уже прошла"); + // return response()->json(['message' => 'Нельзя менять заявки, дата которых уже прошла'], 400); + } + foreach ($editOrderData as $fieldName => $fieldVal) { + if (isset($orderData->$fieldName)) { + $orderData[$fieldName] = $fieldVal; + } + } + $orderDataDiff = $orderData->getDirty(); + if (empty($orderDataDiff)) { + throw new Exception("Вы не внесли никаких изменений"); + //return response()->json(['message' => 'Вы не внесли никаких изменений'], 400); + } + $orderData->save(); + $this->sendMailService->sendEditOrderMail($oldOrderData->toArray(), $orderDataDiff, $orderData['id']); + + DB::commit(); + + return response()->json(['message' => 'Заявка успешно изменена'], 200); + } catch (\Exception $e) { + DB::rollBack(); + + return response()->json(['message' => "Ошибка." . $e->getMessage() . ". Не удалось обновить заявку"], 400); + } + + + + //ГАВРИЛОВ. ДОБАВЬ БЛОКИРОВКУ В МОМЕНТ ПОЛУЧЕНИЯ ДАННЫХ ПО РЕДАКТИРУЕМОМУ ЗАПРОСУ И ДО МОМЕНТА ЕГО ОБНОВЛЕНИЯ. ЛИБО ЧЕРЕЗ УСТАНОВКУ УРОВНЯ ИЗОЛЯЦИИ + + //ГАВРИЛОВ. ДОБАВЬ В DTO НЕ ОБНУЛЕНИЕ НЕНУЖНЫХД ДАННЫХ, А ПРИНУДИТЕЬНАЯ ИХ УСТАНОВКА. НАПРИМЕР ПРИ ОБНОВЛЕНИИ ЗАПРОСА НА ТАКСИ, УСТАНАВЛИВАТЬ EMP_LOGIN = ПЕРЕДАННОМУ ЗНАЧЕНИЮ, ВЗЯТОМУ ИЗ СУЩЕСТВУЮЩЕГО ЗАПРОСА. + + //Обновляем текущую модель, добавляя туда измененные значения, затем проверяем есть ли измененные значения через getDirty() + + + + + + //ГАВРИЛОВ. убрать поле Запрос актуален? и при отмене заявки убирать ее из таблицы Активные заявки? + + //гаврилов. СДЕЛАТЬ ВОЗМОЖНОСТЬ ВЫГРУЗИТЬ В ОТЧЕТНОСТЬ ВСЕ ИМЕЮЩИЕСЯ ЗАЯВКИ В CSV ФАЙЛ. + } +} diff --git a/Modules/Taxi/App/Http/Middleware/CheckTimeRqstAvailability.php b/Modules/Taxi/App/Http/Middleware/CheckTimeRqstAvailability.php new file mode 100644 index 0000000..d8400c4 --- /dev/null +++ b/Modules/Taxi/App/Http/Middleware/CheckTimeRqstAvailability.php @@ -0,0 +1,54 @@ +setTimezone($timezone); + $timeMax = (new \DateTime())->setTimezone($timezone); + $timeMin = (new \DateTime())->setTimezone($timezone); + $timeMax->setTime($maxRqstTime, 00, 00); + $timeMin->setTime($minRqstTime, 00, 00); + + #Гаврилов + //ПОМЕНЯЙ (ПОКА ТАК ДЛЯ ТЕСТИРОВАНИЯ) + if (!($timeNow > $timeMin && $timeNow < $timeMax)) { + //if (!($timeNow > $timeMin && $timeNow > $timeMax)) { + $errMsg = "Работа с заявками на такси заблокирована с $maxRqstTime:00 по 0$minRqstTime:00"; + #Гаврилов + //ПОДУМАТЬ КАКОЙ КОД ЛУЧШЕ ВЕРНУТЬ + //Метод expectsJson позволяет определить вызывается ли api роут через ajax/fetch, либо web route. + if ($request->expectsJson()) { + #Гаврилов + //ЗАМЕНИТЬ НА ОТВЕТ ЧЕРЕЗ APIRESPONDER. ТАМ ЛУЧШЕ РЕАЛИЗОВАТЬ ВСЮ КАСТОМНУЮ ЛОГИКУ ГЕНЕРАЦИИ ОТВЕТОВ НА API ЗАПРОСЫ С ФРОНТА + return response()->json([ + 'errorMsg' => $errMsg + ], 400); + } else { + #Гаврилов + //ПРОВЕРЬ КОГДА РЕАЛИЗУЕШЬ ОПОВЕЩЕНИЯ + return redirect('/taxi/home')->with([ + 'notification' => $errMsg, + 'notification_err' => true + ]); + } + } else { + return $next($request); + } + } +} diff --git a/Modules/Taxi/App/Http/Requests/TaxiOrderRequest.php b/Modules/Taxi/App/Http/Requests/TaxiOrderRequest.php new file mode 100644 index 0000000..cc843ba --- /dev/null +++ b/Modules/Taxi/App/Http/Requests/TaxiOrderRequest.php @@ -0,0 +1,110 @@ +'; var_dump($this->all()); echo''; + } + + + /** + * Get the validation rules that apply to the request. + */ + public function rules(): array + { + //Получаем список активных пользователей + $empActiveLogins = OldMagicModels\CcEmp::select('emp_login') + ->whereNotIn('emp_state', ['Уволен', 'Декрет']) + ->get() + ->toArray(); + //Правила валидации + $validationRules = [ + 'id' => [ + 'int' + ], + 'taxi_date' => [ + 'date_format:Y-m-d', + //Заказ можно создать только на сегодняшний или завтрашний день + Rule::in([ + (new DateTime())->format('Y-m-d'), + (new DateTime())->modify('+1 day')->format('Y-m-d') + ]), + ], + 'taxi_time' => [ + 'required', + 'string', + 'regex:/^[0-9]{2}:[0-9]{2}$/', //время в формате 00:00 + ], + 'cancel_rqst' => 'boolean', + 'emp_phone' => [ + 'required', + 'int', + 'regex:/^(7|8)?[0-9]{10}$/' + ], + 'emp_login' => [ + $validationRules['emp_login'] = [ + 'required', + 'string', + 'regex:/^[a-z\-]+[0-9]*$/', + //Логины ищем среди активных логинов на текущий момент + Rule::in( + array_map(fn($el) => $el['emp_login'], $empActiveLogins) + ) + ], + ], + 'taxi_address_from' => [ + 'required', + 'string', + 'max: 500' + ], + 'taxi_address_to' => [ + 'required', + 'string', + 'max: 500' + ] + ]; + + //Во время создания запроса поле ID не валидируется + if ($this->isMethod('POST')){ + $validationRules['id'] = [ + 'prohibited' + ]; + } + + return $validationRules; + } + + /** + * Determine if the user is authorized to make this request. + */ + public function authorize(): bool + { + return true; + } + + /** + * Переопределение сообщений об ошибках валидации + * + * @return array + */ + public function messages(): array + { + return [ + 'taxi_date.in' => 'Заявку на такси можно завести только на сегодняшний или завтрашний день' + ]; + } +} diff --git a/Modules/Taxi/App/Providers/TaxiOrderProvider.php b/Modules/Taxi/App/Providers/TaxiOrderProvider.php new file mode 100644 index 0000000..11279e6 --- /dev/null +++ b/Modules/Taxi/App/Providers/TaxiOrderProvider.php @@ -0,0 +1,27 @@ +app->bind(TaxiOrderService::class, function($app) { + return new TaxiOrderService(); + }); + } + + /** + * Get the services provided by the provider. + */ + public function provides(): array + { + return []; + } +} diff --git a/Modules/Taxi/App/Services/TaxiOrderService.php b/Modules/Taxi/App/Services/TaxiOrderService.php new file mode 100644 index 0000000..4291c0a --- /dev/null +++ b/Modules/Taxi/App/Services/TaxiOrderService.php @@ -0,0 +1,42 @@ + $orderData->emp_login, + 'taxi_date' => $orderData->taxi_date, + 'emp_phone' => $orderData->emp_phone, + 'taxi_time' => $orderData->taxi_time, + 'taxi_address_from' => $orderData->taxi_address_from, + 'taxi_address_to' => $orderData->taxi_address_to + ] + ); + return $newOrder->id; + // } catch (\Exception $e) { + // return $e->getMessage(); + // } + } +}