- docker-compose.yml: профили docs (Nextcloud), office (ONLYOFFICE Document Server), ai (Ollama + скачивание модели) - автонастройка: адреса Nextcloud, ONLYOFFICE, портала и модели подставляются из .env или по именам сервисов во внутренней сети Docker; значения из интерфейса важнее - локальная модель в своей сети (имя сервиса, частный IP) подключается без ключа API - .env.example, docs/DEPLOY.md (раздел 7а), README
Портал технической службы (чек-листы, наряды, инструмент)
FastAPI + SQLAlchemy, веб-интерфейс на чистом JS, JWT-API для будущего Android-приложения.
Документация API (Swagger): /docs.
Модель
- Должность (
technician/engineer) имеет график (по дням недели или цикл N/M, дневная/ночная смена). Пользователь привязывается к должности администратором. - Чек-лист — список задач; тип ответа: статус (в работе/выполнено), список, число (с границами), текст.
- Шаблон наряда — единожды настроенный наряд + периодичность (каждый день / дни недели / раз в месяц / каждые N дней). Планировщик внутри приложения создаёт из него наряды.
- Наряд — копия чек-листа с оборудованием, местом, исполнителем и проверяющим.
Исполнитель: конкретный человек или должность (тогда наряд видят те, кто сейчас на смене; кто первый начал — тот исполнитель).
Статусы:
new → in_progress → review → completed(проверяющий может вернуть на доработку),cancelled. - Права: техник — только свои наряды; инженер — всё про наряды/чек-листы/оборудование + проверка; админ — ещё пользователи, должности, графики.
Документация
- Руководство пользователя (PDF) — для техников, инженеров, модераторов и администраторов: скриншоты с пометками, работа без связи, проверка, графики, отчёты, FAQ. Пересборка: tools/guide.
- docs/DEPLOY.md — установка на свой сервер (Docker Compose); docs/API.md — описание API для разработчика клиентов; android/README.md — сборка приложения.
Роли
- Администратор — всё, включая «Настройки сервера» (каталог фото, лимит размера, контакт push).
- Модератор — панель «Администрирование»: пользователи, должности, графики, чек-листы, оборудование, наряды; не меняет администраторов, не выдаёт права, не видит настройки сервера, сам наряды не выполняет.
- Инженер / техник — по типу должности (см. выше).
Android-приложение
Нативное приложение (Kotlin + Compose) в каталоге android/: список и выполнение нарядов, фото с камеры,
комментарии, проверка для инженеров, полноценная работа без связи (накопленное уходит на сервер само), уведомления.
Распространяется APK-файлом: готовая версия лежит в release/ и раздаётся по https://<домен>/app.apk (ссылка на экране входа);
новый файл можно положить в DATA_DIR/apk/ — он важнее.
Мобильная версия в браузере (PWA)
Запасной вариант, если приложение недоступно (например, iPhone): https://<домен>/m. Устанавливается на экран «Домой»
(Android: «Установить приложение»; iPhone: «Поделиться → На экран Домой»), работает полностью без связи: наряды и чек-листы
хранятся в браузере (IndexedDB), ответы, фото, комментарии и сдача копятся в очереди и уходят сами (фото с Idempotency-Key,
ответы пачкой через /orders/{id}/sync). Все экраны: список с фильтрами и поиском, чек-лист с крупными кнопками, фото с камеры,
комментарии, проверка для инженеров, уведомления (Web Push), выход.
- С телефона на основном адресе предлагается перейти на
/m(выбор «Остаться» запоминается); на ПК остаётся полная версия. - Файлы:
app/static/m/(m.js, m.css, manifest, иконки); service worker —app/static/sw.js(кэш оболочки + push). - Ограничения iOS: нет фоновой синхронизации (отправка идёт, пока приложение открыто), push работает только у установленной PWA (iOS 16.4+) и только по HTTPS. Данные браузера iOS может очистить, если не открывать сайт долго.
Демонстрационный режим (личный)
«Администрирование → Демонстрационный режим». Демо включается только для того, кто его включил: его запросы идут в отдельную
SQLite-базу с тестовыми данными (сотрудники, оборудование и краны, чек-листы, наряды и задачи за 14 дней, карты, склады, инциденты),
остальные пользователи продолжают работать с рабочей базой. Администратор может включить или выключить демо любому сотруднику.
Тестовые учётные записи (пароль demo1234) работают параллельно с рабочими. Приложение для Android и мобильная версия при смене
режима очищают локальные данные. Подробнее — docs/API.md, раздел «Демонстрационный режим».
Графики и отчёты
- Графики: по дням недели, простой цикл N через M или конструктор цикла из шагов (смена/выходной, любая длительность, дневные, ночные и суточные смены, метки «отсыпной» и т. п.) с календарём-предпросмотром на 6 недель.
- Отчёты → «Выполненные наряды»: машина, чек-лист, кто выполнил, должность, когда. Период (дата+время) обязателен;
фильтры по машине, должности, исполнителю; экспорт в PDF и CSV. Шрифт DejaVu лежит в
app/fonts(кириллица в PDF).
Регламентное обслуживание и «Текущее состояние»
- Узлы машины. Карточка машины («Оборудование» → «Узлы и наработка») хранит наработку (моточасы) и список обслуживаемых узлов: масло, фильтры, ремни и т. п. Для каждого узла выбирается, как он обслуживается: по наработке (каждые N м/ч), по календарю (раз в N дней / недель / месяцев) или что наступит раньше; задаётся порог предупреждения «Скоро» (% от интервала). При добавлении указывается, когда и при какой наработке узел обслуживался в последний раз.
- Чек-лист «Регламентное обслуживание». Тип чек-листа в редакторе. В наряд подставляются: показание наработки машины, ваши обычные задачи и по пункту «обслужено?» на каждый узел выбранной машины (можно только «Требуется/Скоро»). Оборудование обязательно. Когда наряд завершён (после проверки, если она есть), отмеченные узлы сбрасываются, а наработка машины обновляется. Работает и в автозапуске (шаблоны нарядов). Android-приложение показывает пункты узлов с остатком и содержит экран «Состояние узлов» (наработка, сброс); мобильная версия — как обычные задачи.
- Сброс узла вручную — если замена или обслуживание выполнены отдельно либо при внештатной ситуации (дата, наработка, комментарий; всё в истории узла). Показание счётчика не может уменьшаться, кроме «коррекции» (замена/обнуление счётчика).
- Отчёт «Текущее состояние» (Отчёты): узлы всех машин с состоянием Требуется / Скоро / В норме, остатком по наработке и календарю, сроком и прогнозом даты (по средней наработке в сутки за 30 дней). Фильтры по машине, месту и состоянию; экспорт PDF и CSV.
- API:
/equipment/{id}/service-units,/service-units/{id}[/reset|/events],/equipment/{id}/meter,/reports/equipment-state(см. docs/API.md).
Портал: задания, инциденты, карта, инструмент, сотрудники
- Боковое меню вместо шапок: на компьютере всегда видно, на телефоне (сайт, /m, Android 1.1.0) — по кнопке ☰.
- Суточные задания (
/tasks): назначен / в работе / приостановлен / выполнен / отменён; для трёх последних комментарий обязателен; фото, привязка к машине или узлу. Другим ставят инженер, модератор, админ; техник — себе. - Инциденты (
/incidents): авария на машине — описание, затронутые узлы, была ли замена (замена сбрасывает ресурс узла). Открытый инцидент — состояние машины «Авария». Сводка состояний:/equipment-health. - Иконки оборудования: встроенный набор
app/static/icons(генерируетсяtools/make_icons.py) или своё фото. - Карта завода (
/map): картинку и расстановку иконок ведёт админ; «!» — авария, жёлтое свечение — скоро/пора ТО. Карта складов — зоны складов на том же плане (ведёт администратор склада), клик — содержимое склада. - Инструмент и склады (
/inventory/*,/warehouses): каталог, остатки, выдача лично сотруднику, возврат, перемещение, списание, журнал. Роль «Администратор склада» (is_storekeeper). Сотрудник видит только выданное ему (/me/inventory). - Заявки на инструмент (
/tool-requests): что купить, зачем, ссылка на товар; статусы и ответ ответственного. - Карточка сотрудника (
/users/{id}/card): ФИО, фото, должность, ближайшие смены, «что умею», текущие задания и наряды, инструмент. - Передача задания (
POST /tasks/{id}/transfer): исполнитель, поставивший задание или инженер; причина обязательна, видна в истории. - Инциденты извне. Публичная форма
/reportбез входа: место → только машины этого места (и вложенных) → описание и контакты (обязательно); лимит отправок по адресу, ловушка для ботов, выключается в «Настройках сервера». API для внешних систем:POST /external/incidentsс заголовкомX-API-Key(машина по id или инвентарному номеру,external_idзащищает от дублей), справочникGET /external/equipment; ключи выпускает и отзывает админ в «Настройках сервера» (в БД — только хэш). - История машины (
GET /equipment/{id}/history, вкладка в карточке машины): инциденты, обслуживание и замены узлов, наработка, наряды, задания; фильтры по типу, периоду и тексту. - Отделы (
/departments): вложенность, руководитель; отдел в карточке пользователя, фильтр в «Сотрудниках». - Мастер первичной настройки (Администрирование → 🧭): графики, должности, отделы, места, оборудование, сотрудники (пакетный ввод строками, логины и временные пароли — таблицей для печати), карта, склады и остатки, чек-листы, внешние обращения, копии.
- Резервные копии (Администрирование → «Резервные копии»,
/backups): база в переносимом формате + конфигурация (+ фото по желанию), автокопии по расписанию, скачивание, загрузка, восстановление. - AI-помощник (включается в «Настройках сервера»: провайдер, адрес, модель, ключ): кнопка в правом нижнем углу на всех экранах; отвечает только о работе в портале, учитывает права пользователя и читает данные только от его имени.
- Отчёт «Выполнение работ» (
/reports/execution): % выполнения суточных осмотров, чек-листов, ТО и заданий по машинам, отклонения; PDF/CSV.
Комментарии, фото, уведомления
- Комментарии к наряду видят все, кто видит наряд; участникам (исполнитель, проверяющий, назначенный) уходит уведомление.
- Фото: у пункта чек-листа режим «без фото / по желанию / обязательно». Браузер уменьшает снимок до 1600 px. Файлы лежат в каталоге из настроек (по умолчанию
data/photos, в Docker —./photosна хосте), в БД — только путь. API:POST /api/orders/{id}/items/{item_id}/photos(тело — сам файл,Content-Type: image/jpeg|png|webp),GET /api/photos/{id}(с токеном). - Уведомления — Web Push: кнопка «🔔» в шапке. Нужен HTTPS (через Nginx Proxy Manager подойдёт). Приходят при назначении наряда (человеку или тем, кто в этот момент на смене в должности), на проверку, при возврате и при комментариях.
API
Версионированный REST: /api/v1, Swagger на /docs. Короткий access-токен + refresh с ротацией, пакетная офлайн-синхронизация
(POST /orders/{id}/sync), курсор updated_since, идемпотентная загрузка фото, FCM для Android.
Полное описание для разработчика приложения: docs/API.md.
Переменные: ACCESS_TTL_MIN (60), REFRESH_TTL_DAYS (90), LOGIN_MAX_FAILS (5), LOGIN_WINDOW_SEC (300).
Локальный запуск
python -m venv .venv && .venv\Scripts\pip install -r requirements.txt
.venv\Scripts\python -m uvicorn app.main:app --reload
Вход: admin / admin (создаётся при первом старте, смените). Тесты: pytest tests.
Требования к серверу
Оценка по устройству портала (одно приложение на Python + PostgreSQL в Docker), нагрузочных замеров не было.
| Минимум (до 20–30 сотрудников) | Рекомендуется (до 100–150 сотрудников, с запасом) | |
|---|---|---|
| Процессор | 1 ядро (x86-64 или ARM64) | 2 ядра |
| Память | 2 ГБ (с 1 ГБ работает, но первая сборка образа может не пройти без файла подкачки) | 4 ГБ |
| Диск | 10 ГБ: система, Docker, образ ~1 ГБ, база, резервные копии | 40 ГБ |
| ОС | Linux (Debian 12/13, Ubuntu 22.04/24.04), Docker 24+ с Compose v2 | — |
- Фото — главный расход места. Приложение их сжимает, ориентир 0,3–0,5 МБ на снимок: при 50 фото в день — 6–9 ГБ в год, и ещё столько же, если резервные копии делаются с фото.
- Нужны домен и HTTPS (обратный прокси): без них не работают уведомления, мобильная версия на iPhone и релизное приложение для Android.
- Интернет серверу нужен только для уведомлений Android (Firebase) и AI-помощника, если он включён; остальное работает в локальной сети.
- Тяжелее всего для процессора PDF-отчёты и анализ надёжности — секунды на запрос, не постоянная нагрузка.
Пошаговая установка — docs/DEPLOY.md.
Дополнительные сервисы
Рядом с порталом docker-compose.yml может поднять Nextcloud (документация оборудования), ONLYOFFICE (просмотр
Word/Excel/PowerPoint в портале) и Ollama (локальная модель для AI-помощника) — профилями docs, office, ai
(COMPOSE_PROFILES=docs,office,ai в .env). Портал сам находит их во внутренней сети Docker и заполняет адреса в настройках.
Подробно — docs/DEPLOY.md, раздел 7а.
Установка без Coolify (Docker Compose)
Пошаговая инструкция для любого Linux-сервера с Docker: docs/DEPLOY.md (шаблон настроек — .env.example).
Коротко: cp .env.example .env → заполнить → docker compose up -d --build → обратный прокси с HTTPS на APP_PORT.
Деплой (Coolify + Nginx Proxy Manager)
Приложение разворачивается из docker-compose.yml (сервис приложения + PostgreSQL, тома pgdata, photos, appdata).
- В Coolify: Project → New → Application из Git-репозитория, Build Pack = Docker Compose, файл
docker-compose.yml. - Переменные окружения (Coolify → Environment Variables):
DB_PASSWORD,SECRET_KEY(случайная строка),ADMIN_PASSWORD(пароль администратораadmin, применяется при первом старте),FORWARDED_ALLOW_IPS(IP вашего NPM, например192.168.1.10), при желанииAPP_TZ(по умолчанию Europe/Moscow) иAPP_PORT(порт хоста, по умолчанию 8080). В боевом режиме (APP_ENV=production, уже прописан в compose) приложение не запустится, еслиSECRET_KEYкороче 32 символов или пуст, аADMIN_PASSWORDслабее 10 символов (проверяется при первом создании администратора). Пароли пользователей — от 10 символов. - Домен в Coolify не задаётся: прокси — NPM. Proxy Host → Forward
http://<IP сервера Coolify>:8080, SSL (Let's Encrypt), Force SSL. В Advanced добавьтеclient_max_body_size 20m;(иначе фото больше 1 МБ вернут 413). Порт приложения обязательно закройте файрволом для всех, кроме адреса NPM, а вFORWARDED_ALLOW_IPSукажите этот адрес: только от него принимаются заголовкиX-Forwarded-For. Проверка: «Администрирование → Настройки сервера» показывает адрес клиента, каким его видит сервер. - Запуск строго в одном процессе (так и настроено): планировщик нарядов и демо-режим живут внутри процесса.
- APK: готовый подписанный файл лежит в репозитории (
release/) и входит в образ, поэтому ссылка «Скачать приложение для Android» на экране входа и адрес/app.apkработают сразу после деплоя. Новую версию можно выложить без передеплоя: положить файл в томappdataпо путиapk/(он важнее файла из образа):docker cp checklists.apk <контейнер приложения>:/srv/data/apk/. - Резервные копии:
pg_dumpбазы по расписанию + томаphotosиappdata.