From 0caa0f21b1a7cb981774507d444c80cf096a2f38 Mon Sep 17 00:00:00 2001 From: Artem Bratyashin Date: Sat, 2 May 2026 09:19:39 +0300 Subject: [PATCH 1/3] first version is ready --- modal_backend/models/db.py | 26 +++++++++++++++++++++++++- modal_backend/routes/notes.py | 26 +++++++++++++++++++++++--- modal_backend/utils/services.py | 22 +++++++++++++++++++--- 3 files changed, 67 insertions(+), 7 deletions(-) diff --git a/modal_backend/models/db.py b/modal_backend/models/db.py index d5b36a6..cb86916 100644 --- a/modal_backend/models/db.py +++ b/modal_backend/models/db.py @@ -10,8 +10,12 @@ ForeignKey, Integer, String, + cast, + desc, + or_, true, ) +from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.ext.hybrid import hybrid_method from sqlalchemy.orm import Mapped, mapped_column @@ -79,10 +83,30 @@ class Note(BaseDbModel): @hybrid_method def search_by_type_id(self, query: int) -> bool: - if not self.query: + if query is None: return true() return Note.type_id == query + @hybrid_method + def search_by_group_ids(self, query: list[int]) -> bool: + if not query: + return true() + group_ids_jsonb = cast(Note.group_ids, JSONB) + return or_(*(group_ids_jsonb.contains([qid]) for qid in query)) + + @hybrid_method + def search_by_service_ids(self, query: list[int]) -> bool: + if not query: + return true() + service_ids_jsonb = cast(Note.service_ids, JSONB) + return or_(*(service_ids_jsonb.contains([qid]) for qid in query)) + + @hybrid_method + def order_by_start_ts( + self, query: str, asc_order: bool + ) -> UnaryExpression[datetime.datetime] | InstrumentedAttribute: + return getattr(Note, query) if asc_order else desc(getattr(Note, query)) + class NoteResponse(BaseDbModel): __tablename__ = "note_response" diff --git a/modal_backend/routes/notes.py b/modal_backend/routes/notes.py index 1fc2b82..3a6eea6 100644 --- a/modal_backend/routes/notes.py +++ b/modal_backend/routes/notes.py @@ -40,15 +40,35 @@ async def get_notes( default=None, ), asc_order: bool = False, - user=Depends(UnionAuth()), + #user=Depends(UnionAuth()), ) -> list[NoteGet]: """ - Получить список модалок по type_id. + Получить список модалок по фильтрам + + `limit` - максимальное количество возвращаемых комментариев + + `offset` - смещение, определяющее, с какого по порядку комментария начинать выборку. + Если без смещения возвращается комментарий с условным номером N, + то при значении offset = X будет возвращаться комментарий с номером N + X + + `status` - возможные значения `"active", "archived"`. + Если передано `'active'` - возвращается список активных комментариев + Если передано `'archived'` - возвращается список архивированных комментариев + + `type_id` - вернет все модалки конкретного типа по type_id типа + + `groups_id` - вернет все модалки с конкретным groups_id + + `services_id` - вернет все модалки сервиса по id + + `asc_order` -Если передано true, сортировать в порядке возрастания. Иначе - в порядке убывания В случае несуществующего type_id ошибка ObjectNotFound """ - notes = await NoteService.get_note_by_type_id(db, type_id, limit, offset, groups_id, services_id, status, asc_order) + notes = await NoteService.get_notes_by_filters( + db, type_id, limit, offset, groups_id, services_id, status, asc_order + ) return [NoteGet.model_validate(note) for note in notes] diff --git a/modal_backend/utils/services.py b/modal_backend/utils/services.py index 9c21069..40ccf96 100644 --- a/modal_backend/utils/services.py +++ b/modal_backend/utils/services.py @@ -11,7 +11,7 @@ class NoteService: """ @classmethod - async def get_note_by_type_id( + async def get_notes_by_filters( cls, db: Session, type_id: int, @@ -22,8 +22,24 @@ async def get_note_by_type_id( status: str, asc_order: bool, ): - # add filter logic - notes = Note.query(session=db.session).filter(Note.search_by_type_id(type_id)).limit(limit).offset(offset).all() + notes_query = ( + Note.query(session=db.session) + .filter(Note.search_by_type_id(type_id)) + .filter(Note.search_by_group_ids(groups_id)) + .filter(Note.search_by_service_ids(services_id)) + ) + + if status == 'active': + notes_query = notes_query.filter(Note.is_deleted == 0) + if status == 'archived': + notes_query = notes_query.filter(Note.is_deleted == 1) + + notes_query = notes_query.order_by(Note.order_by_start_ts("start_ts", asc_order)) + notes = notes_query.limit(limit).offset(offset).all() + + if not notes: + raise ObjectNotFound(Note, 'all') + return notes @staticmethod From 38e7f542ac8e7c4c62df815c56a95a66d369514a Mon Sep 17 00:00:00 2001 From: Artem Bratyashin Date: Sat, 2 May 2026 09:53:29 +0300 Subject: [PATCH 2/3] need to be tested --- modal_backend/routes/notes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modal_backend/routes/notes.py b/modal_backend/routes/notes.py index 3a6eea6..547a9b3 100644 --- a/modal_backend/routes/notes.py +++ b/modal_backend/routes/notes.py @@ -40,7 +40,7 @@ async def get_notes( default=None, ), asc_order: bool = False, - #user=Depends(UnionAuth()), + user=Depends(UnionAuth()), ) -> list[NoteGet]: """ Получить список модалок по фильтрам From ad4fba2116fcf54b1e46ff342e15fbb6042e7f57 Mon Sep 17 00:00:00 2001 From: Artem Bratyashin Date: Mon, 25 May 2026 21:11:00 +0300 Subject: [PATCH 3/3] It's ready --- modal_backend/utils/services.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modal_backend/utils/services.py b/modal_backend/utils/services.py index 40ccf96..57362cc 100644 --- a/modal_backend/utils/services.py +++ b/modal_backend/utils/services.py @@ -30,9 +30,9 @@ async def get_notes_by_filters( ) if status == 'active': - notes_query = notes_query.filter(Note.is_deleted == 0) + notes_query = notes_query.filter(Note.status == "active") if status == 'archived': - notes_query = notes_query.filter(Note.is_deleted == 1) + notes_query = notes_query.filter(Note.status == "archived") notes_query = notes_query.order_by(Note.order_by_start_ts("start_ts", asc_order)) notes = notes_query.limit(limit).offset(offset).all()