diff --git a/Modules/Taxi/App/Console/SendOrdersToTaxiCommand.php b/Modules/Taxi/App/Console/SendOrdersToTaxiCommand.php new file mode 100644 index 0000000..072024a --- /dev/null +++ b/Modules/Taxi/App/Console/SendOrdersToTaxiCommand.php @@ -0,0 +1,90 @@ +executeCommand(function () { + $todayOrders = TaxiMain::where('cancel_rqst', 0) + ->where('taxi_date', (new DateTime())->format('Y-m-d')) + ->get() + ->toArray(); + + if (!$todayOrders) { + Mail::send(new Mailer( + new BaseMailerObj( + + ) + )); + echo '
'; var_dump('da'); echo'';
+ } else {
+ echo ''; var_dump('net'); echo'';
+ }
+
+ throw new Error('Ошипка!');
+ }, 'еще инва');
+
+ // try {
+ // throw new Error('Ошипка!');
+ // } catch (\Throwable $th) {
+ // \Log::channel('schedule_err')->error($th->getFile() . ": " . $th->getMessage() . " Line: " . $th->getLine());
+ // }
+
+ //$this->info('Daily report generated at ' . now());
+
+ return 0;
+ }
+
+ /**
+ * Get the console command arguments.
+ */
+ protected function getArguments(): array
+ {
+ return [
+ ['example', InputArgument::REQUIRED, 'An example argument.'],
+ ];
+ }
+
+ /**
+ * Get the console command options.
+ */
+ protected function getOptions(): array
+ {
+ return [
+ ['example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null],
+ ];
+ }
+}
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/Jobs/TaxiMailJob.php b/Modules/Taxi/App/Jobs/TaxiMailJob.php new file mode 100644 index 0000000..a91a9ca --- /dev/null +++ b/Modules/Taxi/App/Jobs/TaxiMailJob.php @@ -0,0 +1,40 @@ +jobData + )); + } +} diff --git a/Modules/Taxi/App/Mail/BaseTaxiMail.php b/Modules/Taxi/App/Mail/BaseTaxiMail.php new file mode 100644 index 0000000..d3a2c43 --- /dev/null +++ b/Modules/Taxi/App/Mail/BaseTaxiMail.php @@ -0,0 +1,32 @@ +orderData->emp_login], + "Создана заявка на такси", + "Для вас создана заявка на такси № {$this->orderId}: +
| {el[1]} | + ) + } +Управление | +|
|---|---|---|
| { props.empSupervisors.find(empData => empData.emp_login == rqstData.emp_login)?.emp_supervisor } | + :{ rqstData[el[0]] } | + ) + }) + } ++ {/* Можно взаимодействовать только с заявками на такси на сегодняшнюю, либо завтрашнюю дату */} + {differenceInDays(new Date(rqstData.taxi_date), new Date()) >= 0 && !rqstData.cancel_rqst ? + <> + | +
Module: {!! config('taxi.name') !!}
+@endsection diff --git a/Modules/Taxi/resources/views/layouts/master.blade.php b/Modules/Taxi/resources/views/layouts/master.blade.php new file mode 100644 index 0000000..3e32149 --- /dev/null +++ b/Modules/Taxi/resources/views/layouts/master.blade.php @@ -0,0 +1,31 @@ + + + + + + + + + + + +