Skip to content

Пользовательская ручка view #38 - #40

Open
Aiz0r wants to merge 3 commits into
mainfrom
modal_display_checking
Open

Пользовательская ручка view #38#40
Aiz0r wants to merge 3 commits into
mainfrom
modal_display_checking

Conversation

@Aiz0r

@Aiz0r Aiz0r commented Aug 21, 2026

Copy link
Copy Markdown

Изменения

Добавлена ручка POST /user/{id}/view, она фиксирует реальный показ модалки пользователю. Показ засчитывается в таблице note_view: при первом показе создаётся запись, при повторных увеличивается счётчик показов. Если модалки не существует - ошибка 404, если модалка не активна - ошибка 403

Детали реализации

NoteViewService.mark_view (utils/services.py) - основная логика
Тесты в tests/test_routes/test_user.py: первый показ, повторный показ (инкремент), несуществующая модалка (404), неактивная модалка (403)

Check-List

  • Вы проверили свой код перед отправкой запроса?
  • Вы написали тесты к реализованным функциям?
  • Вы не забыли применить форматирование black и isort для Back-End или Prettier для Front-End?

@Aiz0r
Aiz0r requested a review from petrCher August 21, 2026 18:39
@Aiz0r Aiz0r self-assigned this Aug 21, 2026
@github-actions

Copy link
Copy Markdown

💩 Code linting failed, use black and isort to fix it.

@github-actions

github-actions Bot commented Aug 21, 2026

Copy link
Copy Markdown

Code Coverage

Coverage Report
FileStmtsMissCoverMissing
modal_backend
   __main__.py440%1–6
   exceptions.py20195%37
modal_backend/models
   base.py62789%22, 25–28, 57, 87
modal_backend/routes
   exc_handlers.py17194%38
modal_backend/schemas
   base.py12467%6–9
modal_backend/utils
   user_logic.py22291%22, 26
TOTAL5551997% 

Summary

Tests Skipped Failures Errors Time
79 0 💤 0 ❌ 0 🔥 9.277s ⏱️

@Aiz0r
Aiz0r requested a review from Georgon August 21, 2026 18:42
@Aiz0r

Aiz0r commented Aug 23, 2026

Copy link
Copy Markdown
Author

пофиксил формат, вроде теперь норм

@petrCher petrCher linked an issue Aug 25, 2026 that may be closed by this pull request

@petrCher petrCher left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

тесты еще не смотрел, сперва надо поправить мои комменты

плюс еще дополнение небольшое, возможно непонятно:
visit_count в другой таблице (ты с ней здесь не работаешь) просто считает вообще все заходы в сервис пользователя
shown_count считает сколько раз показали именно эту модалку
last_visit_number это копия visit_count на момент последнего показа


if not notes:
raise ObjectNotFound(Note, 'all')
raise ObjectNotFound(Note, "all")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а в чем смысл замены?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

похоже что случайно форматнулось пока я пытался подгонать нужное форматирование для пуша. Поправлю обратно

Comment thread modal_backend/routes/user.py Outdated
"""
Отмечает, что модалка реально была отрисована пользователю.

Увеличивает shown_count в note_view и запоминает номер захода

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

уточни, что note_view это таблица

Comment thread modal_backend/routes/user.py Outdated
user=Depends(UnionAuth()),
) -> StatusResponseModel:
"""
Отмечает, что модалка реально была отрисована пользователю.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

была "показана", "отрисована" не слишком литературно

Отмечает, что модалка реально была отрисована пользователю.

Увеличивает shown_count в note_view и запоминает номер захода
(last_visit_number), от которого потом считается frequency.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

эта строка должна быть по идее на прошлой, если линтинг сам не переносит строку то надо на одной написать (но там не должен переносить он ничего, 120 вроде символов ограничение)

Comment thread modal_backend/routes/user.py Outdated

Повторный вызов не ошибка

Исключение ObjectNotFound(404), если модалки с `id` не существует

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

про 404 и 403 можно не писать, это и так известно из названий исключений

Comment thread modal_backend/utils/services.py Outdated
user_id=user_id,
shown_count=1,
last_visit_number=visit_count,
rejected_count=0,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

это можно не писать, там же в структуре бд по дефолту 0

Comment thread modal_backend/utils/services.py Outdated
note_id=note_id,
user_id=user_id,
shown_count=1,
last_visit_number=visit_count,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а откуда visit_count у юзера, у которого только создается запись? просто при беглом взгляде можно упустить момент с тем что выше ты задал равным 0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

здесь лучше будет прописать last_visit_number=1 так как при создании нового уже пользователь точно видел одно оповещение

Comment thread modal_backend/utils/services.py Outdated

if user_visit is not None:
visit_count = user_visit.visit_count
else:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/profcomff/modal-service-api/pull/40/changes#r3861487114 по этому комменту смотри
лучше просто без else

Comment thread modal_backend/utils/services.py Outdated
note = Note.get(session=db.session, id=note_id)
if note.status != ModalStatus.ACTIVE:
raise ForbiddenAction(Note)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

сюда еще добавить проверку на существование сервиса (для этого есть даже отдельная таблица в бд)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

и еще проверка не истекла ли модалка
те end_ts не превышен ли

Comment thread modal_backend/utils/services.py Outdated
"""

@classmethod
async def mark_view(cls, db: Session, note_id: int, user_id: int, service_id: int) -> NoteView:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

честно говоря не вижу смысла в аннотации NoteView
просто все равно возвращается именно он
если бы работали со схемами pydantic то это ок, но с схемой в бд плохо

да и return в конце не нужен, так как классметод в ручку ничего не возвращает по текущей логике

@petrCher

Copy link
Copy Markdown
Member

@Aiz0r если будут вопросы, то лучше прямо сюда пиши тегнув меня

@Georgon тоже рекомендую посмотреть и если есть, что написать делай ревью прямо в коде со своими комментами

@Aiz0r

Aiz0r commented Sep 1, 2026

Copy link
Copy Markdown
Author

Вроде все пофиксил, жду ревью

@Aiz0r
Aiz0r requested a review from petrCher September 1, 2026 18:45
@petrCher

petrCher commented Sep 4, 2026

Copy link
Copy Markdown
Member

@Aiz0r когда исправляешь мой коммент, надо его резолвить, чтобы я видел что он действительно исправлен
также есть комменты по поводу линтинга, которые не изменились, там где кавычки и переносы на другую строку

@petrCher petrCher left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

когда доделаешь попроси @Georgon отревьюить, потом я ревью сделаю финальный и замерджим
Гоша как раз сейчас вроде освободился от срочных дел)

assert view is not None
assert view.shown_count == 1

dbsession.delete(view)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

всю работу с бд выносим в фикстуры, там можно yield использовать для передачи, потом удаляем

dbsession.commit()


def test_second_view_increments_shown_count(client, dbsession, notes, authlib_user_data):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

плохо когда один и тот же тест разделен на 2, где разница - числовое значение

def test_second_view_increments_shown_count(client, dbsession, notes, authlib_user_data):
note = notes[0]

client.post(f"{url}/{note.id}/view", params={"service_id": 1})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

почему есть привязка к сервису с айди 1?

dbsession.commit()


def test_nonexistent_note_returns_404(client):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

вообще надо один бы тест сделать, так как одна ручка, надо через mark.parametrize прописать тест-кейсы и на разные статусы ответов разная логика

assert response.status_code == status.HTTP_404_NOT_FOUND


def test_archived_note_returns_403(client, notes):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

это все тоже в один тест общий можно сделать

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Пользовательская ручка view

2 participants