147 lines
5.2 KiB
Python

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"),
)