Files
ACORE/ext-visit manager/files(1)/attendance_views.py
T
lokses 131cb27d16 Initial commit — ACORE pharmacy network management system
Django project: employees, locations, visit_manager, it_manager,
mattermost_connector and stub connectors (ad, mail, portal).
2026-05-31 14:21:47 +03:00

117 lines
4.0 KiB
Python

# apps/attendance/api/views.py
"""
REST API для регистрации посещений с PPOS/терминалов.
"""
import base64
from django.core.files.base import ContentFile
from rest_framework import serializers, status
from rest_framework.response import Response
from rest_framework.views import APIView
from ..services import register_attendance
from ..models import AttendanceLog
# ---------------------------------------------------------------------------
# Serializers
# ---------------------------------------------------------------------------
class AttendanceCreateSerializer(serializers.Serializer):
employee_id = serializers.IntegerField()
location_id = serializers.IntegerField()
direction = serializers.ChoiceField(choices=['in', 'out'])
# Фото передаётся как base64-строка (multipart тоже поддерживается — см. ниже)
photo_b64 = serializers.CharField(write_only=True)
device_id = serializers.CharField(required=False, default='')
def validate_photo_b64(self, value: str) -> bytes:
try:
# Убираем data URI prefix если есть
if ',' in value:
value = value.split(',', 1)[1]
return base64.b64decode(value)
except Exception:
raise serializers.ValidationError('Невалидный base64')
class AttendanceLogSerializer(serializers.ModelSerializer):
photo_thumb = serializers.SerializerMethodField()
class Meta:
model = AttendanceLog
fields = [
'id', 'employee_id', 'location_id', 'direction',
'timestamp', 'photo', 'photo_thumb', 'device_id',
]
def get_photo_thumb(self, obj):
return obj.photo_thumb_b64
# ---------------------------------------------------------------------------
# Views
# ---------------------------------------------------------------------------
class AttendanceRegisterView(APIView):
"""
POST /api/attendance/register/
Принимает фото в base64, создаёт запись посещения.
"""
def post(self, request):
serializer = AttendanceCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
log = register_attendance(
employee_id=data['employee_id'],
location_id=data['location_id'],
direction=data['direction'],
photo_bytes=data['photo_b64'],
device_id=data.get('device_id', ''),
ip_address=request.META.get('REMOTE_ADDR'),
)
return Response(
AttendanceLogSerializer(log).data,
status=status.HTTP_201_CREATED,
)
class AttendanceListView(APIView):
"""
GET /api/attendance/?employee_id=&date=YYYY-MM-DD&location_id=
Список записей с превью (без оригиналов фото — только thumb в base64).
"""
def get(self, request):
qs = AttendanceLog.objects.select_related('employee', 'location')
if emp := request.query_params.get('employee_id'):
qs = qs.filter(employee_id=emp)
if loc := request.query_params.get('location_id'):
qs = qs.filter(location_id=loc)
if date := request.query_params.get('date'):
qs = qs.filter(timestamp__date=date)
qs = qs.order_by('-timestamp')[:200]
return Response(AttendanceLogSerializer(qs, many=True).data)
class AttendancePhotoView(APIView):
"""
GET /api/attendance/<uuid>/photo/
Возвращает оригинал фото (redirect к MEDIA_URL или streaming).
"""
from django.http import HttpResponseRedirect
def get(self, request, pk):
from django.http import HttpResponseRedirect, Http404
try:
log = AttendanceLog.objects.get(pk=pk)
except AttendanceLog.DoesNotExist:
raise Http404
if not log.photo:
raise Http404
return HttpResponseRedirect(log.photo.url)