diff --git a/backend/schemas/conferences.py b/backend/schemas/conferences.py index 4ccc938..765637a 100644 --- a/backend/schemas/conferences.py +++ b/backend/schemas/conferences.py @@ -91,7 +91,17 @@ class ConferenceCreateIn(BaseModel): raise ValueError("closed_conference_requires_password") if self.recurrence is not None and not self.is_pinned: raise ValueError("recurrence_requires_pinned") - if self.scheduled_at is not None and self.scheduled_at < datetime.now(UTC) - PAST_TOLERANCE: + # Запрет прошлого — только для обычных (не закреплённых) конференций. + # Закреплённая конференция — не разовое событие с конкретной датой, а + # постоянная комната-ссылка (см. комментарий у `is_pinned` в + # `models/conference.py`); `scheduled_at` для неё — не более чем + # подсказка в календаре, и прошедшая дата (например, «встречаемся тут + # каждый день с такого-то числа», уже наступившего) осмысленна. + if ( + not self.is_pinned + and self.scheduled_at is not None + and self.scheduled_at < datetime.now(UTC) - PAST_TOLERANCE + ): raise ValueError("scheduled_at_in_the_past") return self diff --git a/backend/tests/test_conferences_api.py b/backend/tests/test_conferences_api.py index 8ac17c5..91f36d7 100644 --- a/backend/tests/test_conferences_api.py +++ b/backend/tests/test_conferences_api.py @@ -212,6 +212,23 @@ async def test_create_scheduled_in_the_past_returns_422( assert response.status_code == 422 +async def test_create_pinned_scheduled_in_the_past_is_allowed( + client: httpx.AsyncClient, db_session: AsyncSession +) -> None: + """Закреплённая конференция — не разовое событие, прошлая дата для неё осмысленна.""" + user = await _make_user(db_session) + await db_session.commit() + + past = datetime.now(UTC) - timedelta(hours=1) + response = await client.post( + "/api/v1/conferences", + json={"title": "Pinned past", "scheduled_at": _iso(past), "is_pinned": True}, + headers=_auth_headers(user), + ) + assert response.status_code == 201 + assert response.json()["is_pinned"] is True + + # --- «Мои конференции» ---------------------------------------------------------