OWAP (Oneway Additional App)

#vue.js #node.js #express.js #sqlite #freelance #2021

Это продолжение решения задачи с парсером http://alex.dzen-code.ru/projects/oneway-parser.

Хотелось обойтись без велосипедов, связанных с Google Sheets Api. Плюс к тому были необходимы дополнительные возможности, такие как: загрузка, просмотр файлов, сложные расчет времени и другое.

Стэк

На фронтенд был взят Vue.js. Я с ним давно работаю и хорошо знаю, да и для небольшого приложение это оптимальное решение. Для реализации компонентов был взят дополнительно фреймворк Vutify. Так же с ним работал.

На бэкенд я решил взять и попробовать node.js, а точнее его фреймворк Express.js. Так же с ним работал, но не реализовывал крупные проекты. Можно было бы взять Laravel или его мини версию lumen, но мне захотелось использовать js как на фронтенде так и на бэкенде. Да и node.js мне очень нравится.

Сервер был организован через Nginx путем проксирования на порт 3000, где располагается node.js приложение. Само приложение поддерживается с помощью утилиты PM2. Она следит, чтобы приложение не падало, в случае чего перезагружало.

База данных SQLite. Небольшая начальная база.

Интерфейс

Был реализован простой логин, для теста, чтобы система на начальном этапе не имела общего доступа.

Сам интерфейс представляет собой таблицу. В ней выводится информация, которая попадает в базу из парсера, такие как: номер машины, ее статус, местоположение, направление, время ориентировочного прибытия.

Помимо данных с пасера в интефейсе представлены компоненты для заполнения диспетчером. Это дата время погрузки, выгрузки, прилагаемые файлы с документами и заказами, комментарий.
Для документов был сделан отдельный компонент. Была задача - сделать простой менеджер для управлением этими документами. То есть их загрузка, удаление, вывод и просмотр.

Так же был ряд интересных задач касающихся просчета дат.
Одной из них было расчет разницы времени от ориентировочного прибытия машины и времени указывающимся диспетчером из заказа.
Сложение дат - это довольно специфичное действие, тк надо было считать не только минуты, часы, но и дни.
Другая задача касалась определения времени, которое машина проводит на стоянке. Это было реализовано с помощью таймера. По кодам положения машины и точки прибытия определялось, что машина стоит на месте. Дальше активировался таймер, состояние которого хранится в базе. И соответсвенно при начале движения, таймер пропадал и показывалась разница времени.

Так же стоит сказать, что вся система находится в постоянной синхронизацией с базой данных, которая в. свою очередь по средству парсера связывается с данными платформы Webfleet. Интерфейс обновляет данные каждую минуту без перезагрузки страницы.

Таким образом в итоге получилась система мониторинга за состоянием машин и заказов.

Парсер

Парсер остался практически аналогичным с предыдущей версии проекта http://alex.dzen-code.ru/projects/oneway-parser.
Суть его осталась та же. Логин на платформе Webfleet, переход на нужные страницы и собирание с них необходимой информации.

Но были некоторые доработки.
Был изменен формата отправляемых данных. Потребовалось преобразовать в связи с поменявшейся несколько логики приложения и для удобства записи в базу данных.

Другая доработка касалась изменения логина. Изначально тратилось значительное время на логин в систему при каждой итерации парсинга. Но мы подумали и решили сделать, чтобы вход был только один раз, а дальше парсер оставался в системе без выхода из нее. За счет этого время парсинга было уменьшено почти в 3 раза. Но скрипт все равно проверял, остался ли он в системе или нет.

Так же были добавлена система логирования, чтобы смотреть за ошибками парсера.

Exception

Error

We're sorry, but an unhandled error occurred. Please see the details below.

file_put_contents(/home/admin/web/alex.dzen-code.ru/public_html/storage/framework/cache/11/de/11de31e1eabb2682cf62ee9c9ccb0630f1019006): failed to open stream: Permission denied

/home/admin/web/alex.dzen-code.ru/public_html/vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php line 122

     * @param  string  $contents
     * @param  bool  $lock
     * @return int
     */
    public function put($path, $contents, $lock = false)
    {
        return file_put_contents($path, $contents, $lock ? LOCK_EX : 0);
    }
 
    /**
     * Prepend to a file.
     *
     * @param  string  $path

Stack trace

# Called Code Document Line
30 file_put_contents(…) ~/vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php 122
29 Illuminate\Filesystem\Filesystem->put(…) ~/vendor/october/rain/src/Filesystem/Filesystem.php 217
28 October\Rain\Filesystem\Filesystem->put(…) ~/vendor/laravel/framework/src/Illuminate/Cache/FileStore.php 65
27 Illuminate\Cache\FileStore->put(…) ~/vendor/laravel/framework/src/Illuminate/Cache/Repository.php 191
26 Illuminate\Cache\Repository->put(…) ~/vendor/october/rain/src/Halcyon/MemoryRepository.php 61
25 October\Rain\Halcyon\MemoryRepository->put(…) ~/vendor/laravel/framework/src/Illuminate/Cache/Repository.php 323
24 Illuminate\Cache\Repository->remember(…) ~/vendor/laravel/framework/src/Illuminate/Cache/CacheManager.php 304
23 Illuminate\Cache\CacheManager->__call(…) ~/vendor/october/rain/src/Database/QueryBuilder.php 158
22 October\Rain\Database\QueryBuilder->getCached(…) ~/vendor/october/rain/src/Database/QueryBuilder.php 121
21 October\Rain\Database\QueryBuilder->getDuplicateCached(…) ~/vendor/october/rain/src/Database/QueryBuilder.php 92
20 October\Rain\Database\QueryBuilder->get(…) ~/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php 481
19 Illuminate\Database\Eloquent\Builder->getModels(…) ~/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php 465
18 Illuminate\Database\Eloquent\Builder->get(…) ~/vendor/laravel/framework/src/Illuminate/Database/Concerns/BuildsQueries.php 77
17 Illuminate\Database\Eloquent\Builder->first() ~/modules/system/behaviors/SettingsModel.php 114
16 System\Behaviors\SettingsModel->getSettingsRecord() ~/modules/system/behaviors/SettingsModel.php 76
15 System\Behaviors\SettingsModel->instance() ~/modules/system/behaviors/SettingsModel.php 135
14 System\Behaviors\SettingsModel->get(…)
13 call_user_func_array(…) ~/vendor/october/rain/src/Extension/ExtendableTrait.php 414
12 October\Rain\Database\Model->extendableCall(…) ~/vendor/october/rain/src/Database/Model.php 647
11 October\Rain\Database\Model->__call(…) ~/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php 1489
10 Illuminate\Database\Eloquent\Model::__callStatic(…) ~/modules/system/models/EventLog.php 37
9 System\Models\EventLog::useLogging() ~/modules/system/ServiceProvider.php 286
8 System\ServiceProvider->System\{closure}(…)
7 call_user_func_array(…) ~/vendor/october/rain/src/Events/Dispatcher.php 233
6 October\Rain\Events\Dispatcher->dispatch(…) ~/vendor/laravel/framework/src/Illuminate/Log/Writer.php 295
5 Illuminate\Log\Writer->fireLogEvent(…) ~/vendor/laravel/framework/src/Illuminate/Log/Writer.php 201
4 Illuminate\Log\Writer->writeLog(…) ~/vendor/laravel/framework/src/Illuminate/Log/Writer.php 114
3 Illuminate\Log\Writer->error(…) ~/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php 221
2 Illuminate\Support\Facades\Facade::__callStatic(…) ~/vendor/october/rain/src/Foundation/Exception/Handler.php 66
1 October\Rain\Foundation\Exception\Handler->report(…) ~/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php 81
0 Illuminate\Foundation\Bootstrap\HandleExceptions->handleException(…)