import logging from urllib.parse import quote from django.http import HttpResponse from django.shortcuts import get_object_or_404 from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiResponse, extend_schema from rest_framework import status from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from common.logstorm_client import LogStormClient, LogStormClientError from ..serializers import ( AttendanceDayEventSerializer, ) from ..support import _day_event_records_visible_to, _employee_attendance_aliases logger = logging.getLogger(__name__) class AttendanceRecordDayEventsAPIView(APIView): serializer_class = AttendanceDayEventSerializer permission_classes = [IsAuthenticated] def get_record(self, request, record_id): return get_object_or_404( _day_event_records_visible_to(request.user).select_related("employee"), pk=record_id, ) def get(self, request, record_id): record = self.get_record(request, record_id) try: events = LogStormClient().get_attendance_day_events( employee_id=str(record.employee_id), record_date=record.date, aliases=_employee_attendance_aliases(record), ) except LogStormClientError as exc: logger.warning( "LogStorm attendance day event retrieval failed", extra={ "event": "attendance.logstorm.day_events_failed", "attendance_record_id": record.id, "employee_id": record.employee_id, "record_date": record.date, "upstream_status_code": exc.status_code, "error_type": type(exc).__name__, }, ) return Response( {"detail": str(exc), "error": "logstorm_unavailable"}, status=status.HTTP_502_BAD_GATEWAY, ) return Response( [ self._with_proxy_photo_url(request, record, event) for event in events if isinstance(event, dict) ] ) @staticmethod def _with_proxy_photo_url(request, record, event): result = dict(event) event_key = str(result.get("event_key") or "") if result.get("has_photo") and event_key: result["photo_url"] = ( f"/api/v1/attendance/records/{record.id}/day-events/" f"{quote(event_key)}/photo/" ) else: result["photo_url"] = None return result class AttendanceRecordDayEventPhotoAPIView(APIView): serializer_class = AttendanceDayEventSerializer permission_classes = [IsAuthenticated] def get_record(self, request, record_id): return get_object_or_404( _day_event_records_visible_to(request.user).select_related("employee"), pk=record_id, ) @extend_schema( responses={ 200: OpenApiResponse( response=OpenApiTypes.BINARY, description="Фотография события прохода", ) } ) def get(self, request, record_id, event_key): record = self.get_record(request, record_id) client = LogStormClient() try: events = client.get_attendance_day_events( employee_id=str(record.employee_id), record_date=record.date, aliases=_employee_attendance_aliases(record), ) event = next( ( item for item in events if isinstance(item, dict) and str(item.get("event_key")) == str(event_key) ), None, ) if not event or not event.get("has_photo"): return Response( {"detail": "Event photo not found"}, status=status.HTTP_404_NOT_FOUND, ) photo_response = client.get_attendance_event_photo(event_key) except LogStormClientError as exc: if exc.status_code == status.HTTP_404_NOT_FOUND: return Response( {"detail": "Event photo not found"}, status=status.HTTP_404_NOT_FOUND, ) logger.warning( "LogStorm attendance event photo retrieval failed", extra={ "event": "attendance.logstorm.event_photo_failed", "attendance_record_id": record.id, "employee_id": record.employee_id, "upstream_status_code": exc.status_code, "error_type": type(exc).__name__, }, ) return Response( {"detail": str(exc), "error": "logstorm_unavailable"}, status=status.HTTP_502_BAD_GATEWAY, ) return HttpResponse( photo_response.content, content_type=photo_response.headers.get("Content-Type", "image/jpeg"), )