Аудитории: фильтры по типу, вместимости и оснащению + режим «свободные на паре»

Бэкенд:
- parse_rooms_info разбирает описание аудитории (формат «тип; оснащение; N мест»)
  в атрибуты: type (фразой как в таблице), capacity (места, а для компьютерных
  классов — рабочие места; null, если данных нет), equipment (ПК, Проектор,
  Интерактивная панель, Телевизор, Маркер, Меловая доска) и available_days
  («402 четверг пятница»); «без проектора» трактуется как отсутствие;
- /rooms-day и /rooms-free отдают атрибуты (room_payload); аудитории с
  ограничением по дням не предлагаются в /rooms-free в остальные дни.

Фронтенд (вкладка «Аудитории»):
- панель фильтров: тип (значения из данных таблицы), «мест не меньше», оснащение
  чекбоксами с выбором условия «все (И)» / «любое (ИЛИ)»;
- счётчик «Показано N из M» и пояснения: сколько аудиторий скрыто из-за
  отсутствия данных о вместимости, сколько доступны только по отдельным дням;
- переключатель «Занятость за день» / «Свободные на паре» (с выбором пары) —
  вместе с фильтрами это «свободная аудитория на 30 человек с проектором в
  3-ю пару»; выбранные фильтры запоминаются в браузере;
- в карточке аудитории видны разобранные атрибуты и пометки из таблицы.

Тесты: разбор всех форматов описаний (включая отрицания и меловую доску),
API атрибутов и учёта доступных дней. Всего 159.
This commit is contained in:
2026-10-10 12:25:16 +03:00
parent 3d5bfe3023
commit 6f16736359
7 changed files with 626 additions and 68 deletions

View File

@@ -263,3 +263,31 @@ def test_cache_without_link():
assert c.get("/groups").status_code == 502
body = c.get("/status").json()
assert "Ссылка" in body["error"]
def test_rooms_day_and_free_include_attributes(monkeypatch):
"""Аудитории отдаются с типом/вместимостью/оснащением и учётом доступных дней."""
from fixtures import fixture_sheets
from xlsx_builder import build_workbook
sheets = fixture_sheets()
rooms = sheets["аудитории"]
rooms.rows[0].append("402")
rooms.rows[1].append("402 четверг пятница")
cache, _, _ = make_cache(monkeypatch, build_workbook(sheets))
with TestClient(main.create_app(cache)) as client:
day = client.get("/rooms-day", params={"day": "понедельник"}).json()
by_label = {r["room"]: r for r in day["rooms"]}
room215 = by_label["ауд. 215"]
assert room215["type"] == "комп.класс"
assert room215["capacity"] == 12
assert room215["equipment"] == ["ПК"]
assert by_label["ауд. 402"]["available_days"] == ["четверг", "пятница"]
free_monday = client.get("/rooms-free", params={"day": "понедельник", "period": 1}).json()
assert not any(r["room"] == "ауд. 402" for r in free_monday)
assert all("capacity" in r and "equipment" in r for r in free_monday)
free_thursday = client.get("/rooms-free", params={"day": "четверг", "period": 1}).json()
assert any(r["room"] == "ауд. 402" for r in free_thursday)