Приложение бригады

Приложение бригады: наряды, обходы по формам, дефекты на месте, фото и трек. Работает без связи и отправляет накопленное, когда связь появится.

Где найти
адрес …/itwin-map/field — на телефоне бригады.
Функция показана в сквозном сценарии:Авария: от нарушения до наряда
Читаю как

Возможности

  • Список открытых нарядов: всех или одной бригады («Бригада» — «Все бригады» или конкретная). Сначала более срочные, при равной срочности — по плановому сроку; просроченный помечен «· просрочен».
  • Карточка наряда: что сделать, место, описание, карта места работ с сетью в радиусе 300 м, «Маршрут» в навигатор телефона, «На карте сети» — то же место в основном приложении.
  • «Начать работу» и «Выполнено» с текстом «Что сделано»; фото с подписью («Снять»); комментарий для диспетчера; история наряда.
  • Обход по контуру осмотра: узлы по порядку, отметка «осмотрен» или «с дефектом», ссылка до следующего узла, «Итог обхода» — готовый текст для «Что сделано».
  • Форма обхода, если она назначена наряду: раз на наряд или на каждом узле.
  • «Дефект на обходе» — дефект в журнал нарушений с точкой телефона и фото; по нему сервер сам создаёт заявку.
  • «Передавать местоположение» — трек бригады для диспетчера; у места наряда наряд сам отмечает «на месте с …».
  • Всё перечисленное работает без связи и уходит на сервер, когда связь вернётся.

Как это работает

Без связи. Каждое действие бригады («Начать работу», «Выполнено», комментарий, фото, отметка узла, форма, дефект) сначала записывается в очередь на телефоне (IndexedDB браузера, своя база на каждый город), затем отправляется. Пока очередь не пуста, вверху раздел «Ждут отправки: N. Уйдут сами, когда появится связь.», а у кнопки обновления — счётчик. Карточка сразу показывает результат: после «Начать работу» без связи наряд уже «В работе» и видна кнопка «Выполнено».

Отправка запускается сразу после действия, при появлении сети, при возврате на вкладку и каждые 30 секунд, пока есть неотправленное. Действия уходят строго по времени создания: «Выполнено» не обгонит «Начать работу». У каждого действия свой ключ: если связь оборвалась после записи на сервере, повтор не создаст дубль.

Что делает отправка с ответом сервера:

Ответ Что происходит
нет сети, 408, 425, 429, 5xx отправка останавливается, действие ждёт следующей попытки
401 (нужен вход) отправка останавливается, открывается вход; очередь не трогается
409 (наряд изменил диспетчер) действие помечается конфликтом; у перехода — кнопка «Ещё раз»
другие ошибки (422, 413, 415 …) действие помечается «не принято» с текстом сервера; повтор не поможет

Если переход наряда упёрся в конфликт, остальные переходы этого наряда тоже не уходят («Предыдущий переход этого наряда не прошёл»), а комментарии и фото уходят. «Ещё раз» загружает свежий наряд: если переход ещё возможен — шлёт его заново, если нет — пишет «Наряд уже «…» — этот переход больше не нужен, уберите его.». Действия с ошибкой удаляются из очереди кнопкой «Убрать из очереди».

Что хранится на телефоне. Последний загруженный список нарядов (без связи — «Без связи — список от …»), справочники нарядов и журнала дефектов, действующие формы обходов, сеть вокруг каждого открытого наряда и маршрут обхода. Сеть (участки и узлы в радиусе 300 м, только фрагмент наряда, до 2000 объектов) скачивается при загрузке списка и обновляется, если ей больше 12 часов. Подложка карты без связи не грузится — на карте подпись «без связи — без подложки». Последнее известное право отмечать работу тоже запоминается: без связи кнопки остаются, а сервер проверит право при отправке.

Страница без связи. Service worker (field-sw.js) обслуживает только страницу /field и её файлы: сначала сеть, без сети — сохранённая копия. Поэтому после выкатки бригада сразу получает новую версию. Чтобы страница открылась без связи, её нужно хотя бы раз открыть при связи (лучше дважды: при первом заходе service worker только ставится). Основное приложение, API и тайлы идут мимо него.

Переходы наряда. Бригаде доступна цепочка вперёд: «Начать работу» — только из «Назначен», «Выполнено» — из «В работе» и только с заполненным «Что сделано». Наряд в статусе «Заявка» бригада не начинает: сначала диспетчер назначает бригаду. Если наряд создан по дефекту, «Начать работу» ставит дефекту состояние «Ремонт» и дату начала ремонта, «Выполнено» — «После ремонта» и дату завершения. Закрывает наряд диспетчер («Выполнено. Закроет диспетчер.»). После обновления выполненный наряд из списка уходит: список показывает только открытые.

Фото. Снимок уменьшается на телефоне: длинная сторона — до 1600 пикселей, JPEG с качеством 0,82, 0,7 или 0,55 — первое, что укладывается в 2 МБ. Поворот берётся из EXIF. Сервер принимает JPEG, PNG и WebP до 2 МБ (тип проверяет по содержимому файла) и не больше 30 фото на наряд. Фото и координаты хранятся в базе (tgid_work_order_photo).

Координаты действия. К каждому действию добавляется точка GPS: замер ждёт до 8 секунд, годится замер не старше минуты. Нет разрешения или спутников — действие уходит без координат.

Дефект на обходе. Окно ждёт координаты телефона: без них кнопка «Записать дефект» недоступна. Описание обязательно; есть готовые фразы («Парение», «Течь», «Открыт люк» …). Источник по умолчанию — «Осмотр», если он есть в справочнике. Сервер пишет запись в журнал нарушений десктопа в состоянии «Нарушение» и привязывает её к ближайшему участку не дальше 30 м от точки (дефект с узла обхода — к участку контура у этого узла). Тут же создаётся заявка «Дефект: …» в статусе «Заявка» с выбранной срочностью; узел обхода отмечается «с дефектом».

Трек. Пока включено «Передавать местоположение», телефон пишет точку не чаще раза в 5 секунд — после сдвига на 25 м или через минуту стоянки. Точки с точностью хуже 100 м не пишутся. Накопленное уходит пачками до 500 точек раз в минуту. Браузер даёт координаты, только пока страница открыта и экран включён — в фоне трек прерывается. Если на телефоне выбрана конкретная бригада и её точка оказалась в 100 м от места открытого наряда этой бригады («Назначен» или «В работе»; у обхода — от любого участка контура), в наряде появляется «на месте с ЧЧ:ММ». Сервер хранит трек 90 дней.

Выход. «Выйти» предупреждает о неотправленном: оно ушло бы от имени того, кто войдёт следующим. Точки трека при выходе отправляются, если есть связь, остальные удаляются с телефона; сохранённый список нарядов тоже удаляется.

Что нужно для работы

  • Права: смотреть наряды — любой вошедший. Отмечать работу, фото, комментарии, формы, дефект на обходе и трек — право «Журналы» (есть у ролей «Редактор» и «Администратор») при включённой записи на сервере. Без права в карточке — «Отмечать работу может пользователь с правом «Журналы».»; с правом, но при выключенной записи — «Запись выключена на сервере (MUTATIONS_ENABLED).». В обоих случаях кнопок действий и переключателя «Передавать местоположение» нет.
  • Данные: справочник бригад и наряды с назначенной бригадой (окно «Наряды и заявки»); для обхода — контур осмотра; для формы — форма, назначенная наряду.
  • Телефон и браузер: современный браузер с IndexedDB и service worker, адрес по HTTPS (service worker, камера и геолокация в браузере работают только на защищённом адресе). Разрешения на камеру и геолокацию. Для работы без связи — открыть страницу хотя бы раз при связи. В приватном режиме очередь может жить только до закрытия вкладки — тогда предупреждение «Браузер не даёт хранилище…».
  • Страницу можно добавить на главный экран телефона: у неё свой manifest, ярлык открывает сразу наряды бригады.

Шаги

  1. Главный экран: открытые наряды бригады (выбор бригады — сверху), кнопка «Дефект на обходе» — записать дефект с места с фото и координатами, переключатель «Передавать местоположение» — диспетчер увидит бригаду на карте.

    Приложение бригады: шаг 1

  2. Наряд открыт: что сделать, участок и фрагмент, описание, карта с местом работ и сетью рядом; «Маршрут» строит путь до места, «На карте сети» открывает его на основной карте. Ниже — фото с подписью, комментарий для диспетчера и история наряда. Без связи действия копятся на телефоне и уходят, когда связь появится.

    Приложение бригады: шаг 2

Примеры

Копия Алматы на стенде инструкции. Справочник бригад пуст, поэтому в «Бригада» — только «Все бригады». Открытых нарядов нет (в базе 5 нарядов, все «Отменён»), страница пишет «Открытых нарядов нет.». Чтобы попробовать приложение, диспетчер создаёт наряд в «Наряды и заявки» и назначает бригаду. Источник «Осмотр» в справочнике журнала есть (запись № 6) — «Дефект на обходе» подставит его сам.

Фото с камеры 4000 × 3000. Телефон уменьшит его до 1600 × 1200 и сохранит JPEG с качеством 0,82; если файл всё ещё больше 2 МБ — 0,7, затем 0,55. Если и так не уложится — «Фото слишком большое даже после уменьшения».

Смена без связи. Бригада в подвале нажала «Начать работу», сделала два фото и «Выполнено». На экране наряд сразу «Выполнен», вверху — «Ждут отправки: 4». Связь появилась — действия уходят по порядку. «Выполнено» записано с той же версией наряда, что и «Начать работу», и получает новую версию из ответа на «Начать». Если диспетчер за это время изменил наряд, «Начать работу» получит конфликт, а «Выполнено» — «Предыдущий переход этого наряда не прошёл»; оба фото уйдут.

Если не получается

  • «Список не загрузился: …» — сервер не ответил, а сохранённого списка на телефоне нет.
  • «Список не сохранился на телефоне: …» — браузер не дал записать в хранилище; без связи список не откроется.
  • «Не сохранилось на телефоне: … Повторите.» — браузер не дал положить действие в очередь. Оно не записано и не уйдёт; текст комментария или «Что сделано» остаётся в поле — нажмите кнопку ещё раз.
  • «Работа без связи недоступна: …» — service worker не зарегистрировался (адрес не HTTPS или браузер запрещает).
  • «Сеть вокруг не сохранена — откройте наряд при связи» — карта наряда не скачалась до потери связи.
  • «Нет координат: разрешите геолокацию и выйдите на открытое место.» — в окне дефекта нет точки; без неё дефект не записать. Кнопка «Уточнить» повторяет замер.
  • «Дефект записан на телефоне — уйдёт, когда появится связь.» — это не ошибка: сервер недоступен, дефект в очереди.
  • «Не удалось открыть фото — снимите ещё раз или выберите JPEG» — браузер не прочитал файл (например, HEIC), а сам файл не JPEG, PNG или WebP до 2 МБ.
  • «Нет разрешения на геолокацию — включите его в настройках браузера» — трек выключился сам.
  • «Нет сигнала GPS — трек продолжится, когда он появится».
  • «Трек не принят: …» — сервер отказал в пачке точек; эта пачка удаляется с телефона.
  • Действие с ошибкой «Наряд уже изменили — обновите карточку» — диспетчер изменил наряд; нажмите «Ещё раз».
  • «У наряда уже 30 фото» — больше фото к наряду не добавить.
  • Нет кнопки «Начать работу» — наряд в статусе «Заявка»: диспетчер ещё не назначил бригаду.
  • Нет отметки «на месте» — на телефоне выбрано «Все бригады» или наряд не назначен этой бригаде.

Для администратора

  • Запись нарядов, фото, форм, дефекта с обхода и трека — при MUTATIONS_ENABLED=true; без этого бригада только смотрит, а POST /api/v1/field/track отвечает 503, как и запись журналов.
  • Таблицы: tgid_work_order, tgid_work_order_event (история и ключи действий client_id), tgid_work_order_photo (фото в базе, bytea), tgid_work_order_check (отметки обхода), tgid_field_track (трек, хранится 90 дней), журнал нарушений defect. Запись дефекта с обхода попадает в audit_log.
  • Service worker field-sw.js и field.webmanifest лежат в public/ веба и отдаются по пути приложения (NUXT_APP_BASE_URL). Кеш называется tgid-field-v1; при смене имени старый кеш удаляется сам.
  • Адрес для бригады — <адрес веба>/field. Нужен HTTPS.

Для разработчика

  • Страница: pages/field.vue (без общего макета). Компоненты: FieldOrderMap.vue, FieldDefectDialog.vue, FieldFormDialog.vue; трек — composables/useFieldTrack.ts.
  • Правила: utils/fieldQueue.ts (очередь, classifySendError, flushQueue), utils/fieldStore.ts (IndexedDB), utils/fieldPhoto.ts (уменьшение фото, GPS, ссылка «Маршрут»), utils/fieldNetwork.ts (сеть 300 м, 12 ч), utils/fieldRoute.ts (обход), utils/fieldDefect.ts, utils/fieldTrack.ts. Service worker — public/field-sw.js.
  • API: GET /api/v1/work-orders?open_only=true&brigade_id=, GET /api/v1/work-orders/lookups, GET /api/v1/work-orders/{id}, POST /api/v1/work-orders/{id}/transition, POST …/{id}/comments, POST …/{id}/photos (multipart), GET /api/v1/work-orders/photos/{photo_id}, GET …/{id}/route, POST …/{id}/checks, POST /api/v1/work-orders/field-defect, POST /api/v1/field/track, POST /api/v1/forms/submissions, GET /api/v1/work-orders/{id}/forms, POST /api/v1/network-select, GET /api/defects/lookups. Код — routers/work_orders.py, database/work_orders.py, database/work_order_route.py, routers/field_track.py, database/field_track.py.
  • Тесты: vitest — tests/utils/fieldQueue.spec.ts, fieldNetwork.spec.ts, fieldRoute.spec.ts, fieldDefect.spec.ts, fieldTrack.spec.ts, workOrders.spec.ts; API — tests/test_work_orders.py, tests/test_work_order_route.py, tests/test_field_track.py, tests/test_forms.py. Отдельного e2e у страницы нет.
Хотите увидеть эту функцию на своих данных?Покажем ТГИД на демонстрации и ответим на вопросы инженеров.
Запросить демо