feat: документация из Nextcloud, график у сотрудника, автоочистка фото, мониторинг, итог мастера, фильтр по местам; доп. сервисы в docker-compose

- docker-compose.yml: профили docs (Nextcloud), office (ONLYOFFICE Document Server), ai (Ollama + скачивание модели)
- автонастройка: адреса Nextcloud, ONLYOFFICE, портала и модели подставляются из .env или по именам сервисов
  во внутренней сети Docker; значения из интерфейса важнее
- локальная модель в своей сети (имя сервиса, частный IP) подключается без ключа API
- .env.example, docs/DEPLOY.md (раздел 7а), README
This commit is contained in:
darkorion
2026-10-13 13:27:20 +03:00
parent 6b8fca4f5a
commit e67c175f80
44 changed files with 2131 additions and 94 deletions
+21 -3
View File
@@ -67,8 +67,26 @@ def shift_active(s: ShiftSchedule | None, dt: datetime) -> bool:
def user_on_shift(u: User, dt: datetime | None = None) -> bool:
"""На смене ли сотрудник: занимает должность и сейчас по СВОЕМУ графику работает (без графика — всегда)."""
dt = dt or config.now()
return bool(u.position) and shift_active(u.position.schedule, dt)
return bool(u.position) and shift_active(u.schedule, dt)
def schedules_to_users(db) -> int:
"""Однократный перенос: раньше график задавался должности — теперь он у каждого сотрудника.
Сотрудникам без своего графика ставится график их должности; повторно не выполняется (отметка в настройках)."""
from . import settings_store as ss
from .models import Position
if ss.get(db, "schedule_per_user") == "1":
return 0
n = 0
for u, sid in db.execute(select(User, Position.schedule_id).join(Position, Position.id == User.position_id)
.where(User.schedule_id.is_(None), Position.schedule_id.is_not(None))):
u.schedule_id = sid
n += 1
ss.set_(db, "schedule_per_user", "1")
db.commit()
return n
# ---------- расписание запуска нарядов ----------
@@ -120,7 +138,7 @@ def create_order(db: Session, *, title, checklist_id, equipment_id=None, locatio
for it in cl.items:
o.items.append(OrderItem(position=it.position, text=it.text, answer_type=it.answer_type,
options=it.options, unit=it.unit, min_value=it.min_value,
max_value=it.max_value, required=it.required, photo=it.photo))
max_value=it.max_value, required=it.required, photo=it.photo, photo_keep=it.photo_keep))
db.add(o)
return o
@@ -141,7 +159,7 @@ def _regular_items(db: Session, o: Order, cl: Checklist) -> None:
pos += 1
o.items.append(OrderItem(position=pos, text=it.text, answer_type=it.answer_type, options=it.options,
unit=it.unit, min_value=it.min_value, max_value=it.max_value,
required=it.required, photo=it.photo))
required=it.required, photo=it.photo, photo_keep=it.photo_keep))
for u, ev in units:
pos += 1
o.items.append(OrderItem(position=pos, text=service.describe(u, ev) + " — обслужено?", answer_type="status",