From f19862ec6b470c5c2d5b4824dfac8929c9b75069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Fri, 26 Dec 2025 15:59:16 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20requests=20detail=20view=20-=20stage=20?= =?UTF-8?q?2:=20backend=20=D1=80=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Этап 2 разработки включает: ✅ Создан RequestDetailView класс в views_front.py: - Наследуется от LoginRequiredMixin, TemplateView - Загружает данные о заявлении через API (/api/v1/requests/{pk}/) - Загружает комментарии к заявлению - Проверяет права доступа (обрабатывает 404, 403) - Форматирует даты для отображения ✅ Обновлены URLs (urls_front.py): - Добавлен маршрут: path('/', RequestDetailView.as_view(), name='request_detail') - Импортирован RequestDetailView ✅ Обновлен шаблон request_detail.html: - Раскомментированы комментарии (были закрыты) - Добавлена обработка ошибок (404, 403) - Оформлено отображение заявления и комментариев - Включен функционал добавления комментариев � URLs в notification_signals.py уже правильные (проверено) Готово для следующего этапа 3: Frontend разработка --- backend/requests_app/urls_front.py | 2 + backend/requests_app/views_front.py | 75 +++++++++++++++++++ .../requests_app/request_detail.html | 24 +++++- 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/backend/requests_app/urls_front.py b/backend/requests_app/urls_front.py index c5a84e01..48ab43d0 100644 --- a/backend/requests_app/urls_front.py +++ b/backend/requests_app/urls_front.py @@ -2,6 +2,7 @@ from django.urls import path from .views_front import ( RequestsView, + RequestDetailView, request_comments, request_comment_add, ) @@ -10,6 +11,7 @@ app_name = "requests" urlpatterns = [ path("", RequestsView.as_view(), name="request_list"), + path("/", RequestDetailView.as_view(), name="request_detail"), path("comments//", request_comments, name="request_comments"), path( "comments//add/", diff --git a/backend/requests_app/views_front.py b/backend/requests_app/views_front.py index d5b8f847..e5b41494 100644 --- a/backend/requests_app/views_front.py +++ b/backend/requests_app/views_front.py @@ -274,6 +274,81 @@ class RequestsView(LoginRequiredMixin, TemplateView): return ctx +class RequestDetailView(LoginRequiredMixin, TemplateView): + """ + Детальный просмотр заявления. + + Загружает одно заявление и его комментарии через API. + Может быть использовано как для отдельной страницы, так и для модального окна. + + GET /requests/{pk}/: + - Загружает заявление через GET /api/v1/requests/{pk}/ + - Загружает комментарии через GET /api/v1/requests/{pk}/comments/ + - Проверяет права доступа (делает ошибку если нет прав) + + Контекст: + - request_obj: dict с данными заявления + - comments: list[dict] с комментариями + - can_process: bool - может ли пользователь обрабатывать заявку + - error: str - описание ошибки (если она была) + - error_code: int - HTTP код ошибки + """ + + template_name = "requests_app/request_detail.html" + + def get_context_data(self, pk: int, **kwargs: Any) -> Dict[str, Any]: + """ + Загружает данные заявления и комментарии. + + Args: + pk: ID заявления + + Returns: + Dict с контекстом для шаблона + """ + ctx = super().get_context_data(**kwargs) + request = self.request + api = get_api_client(request) + + # Загружаем основные данные заявления + ok, data, status = _api_unpack(api.get(f"v1/requests/{pk}/")) + + if not ok: + # Обработка ошибок (404, 403 и т.д.) + error_msg = data.get("detail", f"HTTP {status}") + if isinstance(error_msg, list): + error_msg = "; ".join(str(e) for e in error_msg) + + ctx.update({ + "request_obj": None, + "comments": [], + "can_process": _user_can_process_requests(request.user), + "error": error_msg, + "error_code": status, + }) + return ctx + + request_data = data + + # Загружаем комментарии + comments = [] + ok_c, data_c, st_c = _api_unpack(api.get(f"v1/requests/{pk}/comments/")) + if ok_c: + results_c, _, _, _ = _parse_page_payload(data_c) + comments = _format_datetime_fields( + results_c, + fields=("created_at", "updated_at") + ) + + ctx.update({ + "request_obj": _format_datetime_fields([request_data], fields=("created_at", "updated_at", "decided_at"))[0], + "comments": comments, + "can_process": _user_can_process_requests(request.user), + }) + + return ctx + + def request_comments(request: HttpRequest, pk: int) -> JsonResponse: """Прокси: список комментариев (JSON) для заявки. Требует авторизации (используем ту же обёртку клиента, что и основная вью). diff --git a/backend/templates/requests_app/request_detail.html b/backend/templates/requests_app/request_detail.html index 2e7850ba..189b0186 100644 --- a/backend/templates/requests_app/request_detail.html +++ b/backend/templates/requests_app/request_detail.html @@ -8,7 +8,22 @@
- {# — Шапка — #} + {% if error %} + {# — Ошибка при загрузке — #} + + + К списку заявлений + + {% elif request_obj %}

Детали заявления

@@ -150,7 +165,12 @@
- --> + + {% else %} + + {% endif %}